spyder-3.2.6/0000775000175000017500000000000013225025007013616 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_breakpoints/0000775000175000017500000000000013225025007017525 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_breakpoints/locale/0000775000175000017500000000000013225025007020764 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_breakpoints/locale/ru/0000775000175000017500000000000013225025007021412 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_breakpoints/locale/ru/LC_MESSAGES/0000775000175000017500000000000013225025007023177 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_breakpoints/locale/ru/LC_MESSAGES/breakpoints.po0000664000175000017500000000301013224121062026047 0ustar carloscarlos00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR ORGANIZATION # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: 2017-12-14 15:40+-05\n" "PO-Revision-Date: 2016-04-18 19:58+0300\n" "Last-Translator: Roman Kulagin \n" "Language-Team: \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "X-Generator: Poedit 1.5.4\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" #: spyder_breakpoints/breakpoints.py:45 msgid "Breakpoints" msgstr "Точки останова" #: spyder_breakpoints/breakpoints.py:80 msgid "List breakpoints" msgstr "Список точек останова" #: spyder_breakpoints/widgets/breakpointsgui.py:97 msgid "Condition" msgstr "Условие" #: spyder_breakpoints/widgets/breakpointsgui.py:97 msgid "File" msgstr "Файл" #: spyder_breakpoints/widgets/breakpointsgui.py:97 msgid "Line" msgstr "Строка" #: spyder_breakpoints/widgets/breakpointsgui.py:180 msgid "Clear breakpoints in all files" msgstr "Очистить все точки останова" #: spyder_breakpoints/widgets/breakpointsgui.py:201 msgid "Clear this breakpoint" msgstr "Убрать эту точку останова" #: spyder_breakpoints/widgets/breakpointsgui.py:206 msgid "Edit this breakpoint" msgstr "Редактировать эту точку останова" spyder-3.2.6/spyder_breakpoints/locale/ru/LC_MESSAGES/breakpoints.mo0000664000175000017500000000205313224121062026052 0ustar carloscarlos00000000000000 d   ",AFK\3;/o= ( BreakpointsClear breakpoints in all filesClear this breakpointConditionEdit this breakpointFileLineList breakpointsProject-Id-Version: POT-Creation-Date: 2017-07-11 13:28+COT PO-Revision-Date: 2016-04-18 19:58+0300 Last-Translator: Roman Kulagin Language-Team: Language: ru MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generated-By: pygettext.py 1.5 X-Generator: Poedit 1.5.4 Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2); Точки остановаОчистить все точки остановаУбрать эту точку остановаУсловиеРедактировать эту точку остановаФайлСтрокаСписок точек остановаspyder-3.2.6/spyder_breakpoints/locale/pt_BR/0000775000175000017500000000000013225025007021772 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_breakpoints/locale/pt_BR/LC_MESSAGES/0000775000175000017500000000000013225025007023557 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_breakpoints/locale/pt_BR/LC_MESSAGES/breakpoints.po0000664000175000017500000000252613224121062026442 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # Spyder's brazilian portuguese translation file # Valter Nazianzeno , 2014. # msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: 2017-12-14 15:40+-05\n" "PO-Revision-Date: 2015-02-25 22:08-0400\n" "Last-Translator: Valter Nazianzeno \n" "Language-Team: \n" "Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "X-Generator: Poedit 1.7.4\n" #: spyder_breakpoints/breakpoints.py:45 msgid "Breakpoints" msgstr "Pontos de interrupção" #: spyder_breakpoints/breakpoints.py:80 msgid "List breakpoints" msgstr "Listar pontos de interrupção" #: spyder_breakpoints/widgets/breakpointsgui.py:97 msgid "Condition" msgstr "Condição" #: spyder_breakpoints/widgets/breakpointsgui.py:97 msgid "File" msgstr "Arquivo" #: spyder_breakpoints/widgets/breakpointsgui.py:97 msgid "Line" msgstr "Linha" #: spyder_breakpoints/widgets/breakpointsgui.py:180 msgid "Clear breakpoints in all files" msgstr "Limpar pontos de interrupção em todos os arquivos" #: spyder_breakpoints/widgets/breakpointsgui.py:201 msgid "Clear this breakpoint" msgstr "Limpar este ponto" #: spyder_breakpoints/widgets/breakpointsgui.py:206 msgid "Edit this breakpoint" msgstr "Editar este ponto" spyder-3.2.6/spyder_breakpoints/locale/pt_BR/LC_MESSAGES/breakpoints.mo0000664000175000017500000000153713224121062026440 0ustar carloscarlos00000000000000 d   ",AFKZ\3  2:@ BreakpointsClear breakpoints in all filesClear this breakpointConditionEdit this breakpointFileLineList breakpointsProject-Id-Version: POT-Creation-Date: 2017-07-11 13:28+COT PO-Revision-Date: 2015-02-25 22:08-0400 Last-Translator: Valter Nazianzeno Language-Team: Language: pt_BR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generated-By: pygettext.py 1.5 X-Generator: Poedit 1.7.4 Pontos de interrupçãoLimpar pontos de interrupção em todos os arquivosLimpar este pontoCondiçãoEditar este pontoArquivoLinhaListar pontos de interrupçãospyder-3.2.6/spyder_breakpoints/locale/ja/0000775000175000017500000000000013225025007021356 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_breakpoints/locale/ja/LC_MESSAGES/0000775000175000017500000000000013225025007023143 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_breakpoints/locale/ja/LC_MESSAGES/breakpoints.po0000664000175000017500000000310113224121062026014 0ustar carloscarlos00000000000000# Japanese translations for Spyder package # Spyder-ide パッケージに対する英訳. # Copyright (C) 2016 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the Spyder package. # Ohnishi Seiki , 2016. # msgid "" msgstr "" "Project-Id-Version: Spyder\n" "POT-Creation-Date: 2017-12-14 15:40+-05\n" "PO-Revision-Date: 2017-04-23 17:22+0900\n" "Last-Translator: sohnishi \n" "Language-Team: Japanese\n" "Language: ja\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Poedit 1.8.11\n" #: spyder_breakpoints/breakpoints.py:45 msgid "Breakpoints" msgstr "ブレークポイント" #: spyder_breakpoints/breakpoints.py:80 msgid "List breakpoints" msgstr "ブレークポイントをリストアップ" #: spyder_breakpoints/widgets/breakpointsgui.py:97 msgid "Condition" msgstr "条件" #: spyder_breakpoints/widgets/breakpointsgui.py:97 msgid "File" msgstr "ファイル" #: spyder_breakpoints/widgets/breakpointsgui.py:97 msgid "Line" msgstr "行" #: spyder_breakpoints/widgets/breakpointsgui.py:180 msgid "Clear breakpoints in all files" msgstr "全ファイルのブレークポイントをクリア" #: spyder_breakpoints/widgets/breakpointsgui.py:201 msgid "Clear this breakpoint" msgstr "ブレークポイントをクリア" #: spyder_breakpoints/widgets/breakpointsgui.py:206 msgid "Edit this breakpoint" msgstr "ブレークポイントを編集" spyder-3.2.6/spyder_breakpoints/locale/ja/LC_MESSAGES/breakpoints.mo0000664000175000017500000000167313224121062026025 0ustar carloscarlos00000000000000 d   ",AFK\6$.S!Z |- BreakpointsClear breakpoints in all filesClear this breakpointConditionEdit this breakpointFileLineList breakpointsProject-Id-Version: Spyder POT-Creation-Date: 2017-07-11 13:28+COT PO-Revision-Date: 2017-04-23 17:22+0900 Last-Translator: sohnishi Language-Team: Japanese Language: ja MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generated-By: pygettext.py 1.5 Plural-Forms: nplurals=1; plural=0; X-Generator: Poedit 1.8.11 ブレークポイント全ファイルのブレークポイントをクリアブレークポイントをクリア条件ブレークポイントを編集ファイル行ブレークポイントをリストアップspyder-3.2.6/spyder_breakpoints/locale/es/0000775000175000017500000000000013225025007021373 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_breakpoints/locale/es/LC_MESSAGES/0000775000175000017500000000000013225025007023160 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_breakpoints/locale/es/LC_MESSAGES/breakpoints.po0000664000175000017500000000247013224121062026041 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR ORGANIZATION # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: 2.2\n" "POT-Creation-Date: 2017-12-14 15:40+-05\n" "PO-Revision-Date: 2013-05-07 17:37-0500\n" "Last-Translator: Carlos Cordoba \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" #: spyder_breakpoints/breakpoints.py:45 msgid "Breakpoints" msgstr "Puntos de interrupción" #: spyder_breakpoints/breakpoints.py:80 msgid "List breakpoints" msgstr "Listar puntos de interrupción" #: spyder_breakpoints/widgets/breakpointsgui.py:97 msgid "Condition" msgstr "Condición" #: spyder_breakpoints/widgets/breakpointsgui.py:97 msgid "File" msgstr "Archivo" #: spyder_breakpoints/widgets/breakpointsgui.py:97 msgid "Line" msgstr "Línea" #: spyder_breakpoints/widgets/breakpointsgui.py:180 msgid "Clear breakpoints in all files" msgstr "Borrar los puntos de todos los archivos" #: spyder_breakpoints/widgets/breakpointsgui.py:201 msgid "Clear this breakpoint" msgstr "Eliminar este punto" #: spyder_breakpoints/widgets/breakpointsgui.py:206 #, fuzzy msgid "Edit this breakpoint" msgstr "Eliminar este punto" spyder-3.2.6/spyder_breakpoints/locale/es/LC_MESSAGES/breakpoints.mo0000664000175000017500000000140413224121062026032 0ustar carloscarlos00000000000000\  G/w' BreakpointsClear breakpoints in all filesClear this breakpointConditionFileLineList breakpointsProject-Id-Version: 2.2 POT-Creation-Date: 2017-07-11 13:28+COT PO-Revision-Date: 2013-05-07 17:37-0500 Last-Translator: Carlos Cordoba Language-Team: LANGUAGE Language: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generated-By: pygettext.py 1.5 Puntos de interrupciónBorrar los puntos de todos los archivosEliminar este puntoCondiciónArchivoLíneaListar puntos de interrupciónspyder-3.2.6/spyder_breakpoints/locale/fr/0000775000175000017500000000000013225025007021373 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_breakpoints/locale/fr/LC_MESSAGES/0000775000175000017500000000000013225025007023160 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_breakpoints/locale/fr/LC_MESSAGES/breakpoints.po0000664000175000017500000000245513224121062026044 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR ORGANIZATION # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2017-12-14 15:40+-05\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: utf-8\n" "Generated-By: pygettext.py 1.5\n" #: spyder_breakpoints/breakpoints.py:45 msgid "Breakpoints" msgstr "Points d'arrêt" #: spyder_breakpoints/breakpoints.py:80 msgid "List breakpoints" msgstr "Liste des points d'arrêt" #: spyder_breakpoints/widgets/breakpointsgui.py:97 msgid "Condition" msgstr "Condition" #: spyder_breakpoints/widgets/breakpointsgui.py:97 msgid "File" msgstr "Fichier" #: spyder_breakpoints/widgets/breakpointsgui.py:97 msgid "Line" msgstr "Ligne" #: spyder_breakpoints/widgets/breakpointsgui.py:180 msgid "Clear breakpoints in all files" msgstr "Supprimer tous les points d'arrêts" #: spyder_breakpoints/widgets/breakpointsgui.py:201 msgid "Clear this breakpoint" msgstr "Supprimer ce point d'arrêt" #: spyder_breakpoints/widgets/breakpointsgui.py:206 msgid "Edit this breakpoint" msgstr "Supprimer ce point d'arrêt" spyder-3.2.6/spyder_breakpoints/locale/fr/LC_MESSAGES/breakpoints.mo0000664000175000017500000000150313224121062026032 0ustar carloscarlos00000000000000 d   ",AFKH\# #) BreakpointsClear breakpoints in all filesClear this breakpointConditionEdit this breakpointFileLineList breakpointsProject-Id-Version: PACKAGE VERSION POT-Creation-Date: 2017-07-11 13:28+COT PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language-Team: LANGUAGE Language: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: utf-8 Generated-By: pygettext.py 1.5 Points d'arrêtSupprimer tous les points d'arrêtsSupprimer ce point d'arrêtConditionSupprimer ce point d'arrêtFichierLigneListe des points d'arrêtspyder-3.2.6/spyder_breakpoints/locale/breakpoints.pot0000664000175000017500000000216713224121062024034 0ustar carloscarlos00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR ORGANIZATION # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2017-12-14 15:40+-05\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: ENCODING\n" "Generated-By: pygettext.py 1.5\n" #: spyder_breakpoints/breakpoints.py:45 msgid "Breakpoints" msgstr "" #: spyder_breakpoints/breakpoints.py:80 msgid "List breakpoints" msgstr "" #: spyder_breakpoints/widgets/breakpointsgui.py:97 msgid "Condition" msgstr "" #: spyder_breakpoints/widgets/breakpointsgui.py:97 msgid "File" msgstr "" #: spyder_breakpoints/widgets/breakpointsgui.py:97 msgid "Line" msgstr "" #: spyder_breakpoints/widgets/breakpointsgui.py:180 msgid "Clear breakpoints in all files" msgstr "" #: spyder_breakpoints/widgets/breakpointsgui.py:201 msgid "Clear this breakpoint" msgstr "" #: spyder_breakpoints/widgets/breakpointsgui.py:206 msgid "Edit this breakpoint" msgstr "" spyder-3.2.6/spyder_breakpoints/breakpoints.py0000664000175000017500000000717613224740762022446 0ustar carloscarlos00000000000000# -*- coding:utf-8 -*- # # Copyright © Spyder Project Contributors # Based loosely on p_pylint.py by Pierre Raybaut # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Breakpoint Plugin""" # pylint: disable=C0103 # pylint: disable=R0903 # pylint: disable=R0911 # pylint: disable=R0201 # Standard library imports import os.path as osp # Local imports from spyder.config.base import get_translation from spyder.utils import icon_manager as ima from spyder.utils.qthelpers import create_action from spyder.plugins import SpyderPluginMixin from spyder.py3compat import to_text_string, is_text_string from .widgets.breakpointsgui import BreakpointWidget _ = get_translation("breakpoints", "spyder_breakpoints") class Breakpoints(BreakpointWidget, SpyderPluginMixin): """Breakpoint list""" CONF_SECTION = 'breakpoints' # CONFIGWIDGET_CLASS = BreakpointConfigPage def __init__(self, parent=None): BreakpointWidget.__init__(self, parent=parent) SpyderPluginMixin.__init__(self, parent) # Initialize plugin self.initialize_plugin() self.set_data() #------ SpyderPluginWidget API -------------------------------------------- def get_plugin_title(self): """Return widget title""" return _("Breakpoints") def get_plugin_icon(self): """Return widget icon""" path = osp.join(self.PLUGIN_PATH, self.IMG_PATH) return ima.icon('profiler', icon_path=path) def get_focus_widget(self): """ Return the widget to give focus to when this plugin's dockwidget is raised on top-level """ return self.dictwidget def get_plugin_actions(self): """Return a list of actions related to plugin""" return [] def on_first_registration(self): """Action to be performed on first plugin registration""" self.main.tabify_plugins(self.main.help, self) def register_plugin(self): """Register plugin in Spyder's main window""" self.edit_goto.connect(self.main.editor.load) #self.redirect_stdio.connect(self.main.redirect_internalshell_stdio) self.clear_all_breakpoints.connect( self.main.editor.clear_all_breakpoints) self.clear_breakpoint.connect(self.main.editor.clear_breakpoint) self.main.editor.breakpoints_saved.connect(self.set_data) self.set_or_edit_conditional_breakpoint.connect( self.main.editor.set_or_edit_conditional_breakpoint) self.main.add_dockwidget(self) list_action = create_action(self, _("List breakpoints"), triggered=self.show) list_action.setEnabled(True) pos = self.main.debug_menu_actions.index('list_breakpoints') self.main.debug_menu_actions.insert(pos, list_action) self.main.editor.pythonfile_dependent_actions += [list_action] def refresh_plugin(self): """Refresh widget""" pass def closing_plugin(self, cancelable=False): """Perform actions before parent main window is closed""" return True def apply_plugin_settings(self, options): """Apply configuration file's plugin settings""" pass def show(self): """Show the breakpoints dockwidget""" if self.dockwidget and not self.ismaximized: self.dockwidget.setVisible(True) self.dockwidget.setFocus() self.dockwidget.raise_() spyder-3.2.6/spyder_breakpoints/widgets/0000775000175000017500000000000013225025007021173 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_breakpoints/widgets/breakpointsgui.py0000664000175000017500000002303513224740762024611 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # based loosley on pylintgui.py by Pierre Raybaut # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Breakpoint widget""" # pylint: disable=C0103 # pylint: disable=R0903 # pylint: disable=R0911 # pylint: disable=R0201 # Standard library imports import os.path as osp import sys # Third party imports from qtpy import API from qtpy.compat import to_qvariant from qtpy.QtCore import (QAbstractTableModel, QModelIndex, QTextCodec, Qt, Signal) from qtpy.QtWidgets import (QItemDelegate, QMenu, QTableView, QVBoxLayout, QWidget) # Local imports from spyder.config.base import get_translation from spyder.config.main import CONF from spyder.utils.qthelpers import add_actions, create_action # This is needed for testing this module as a stand alone script try: _ = get_translation("breakpoints", "spyder_breakpoints") except KeyError as error: import gettext _ = gettext.gettext locale_codec = QTextCodec.codecForLocale() class BreakpointTableModel(QAbstractTableModel): """ Table model for breakpoints dictionary """ def __init__(self, parent, data): QAbstractTableModel.__init__(self, parent) if data is None: data = {} self._data = None self.breakpoints = None self.set_data(data) def set_data(self, data): """Set model data""" self._data = data keys = list(data.keys()) self.breakpoints = [] for key in keys: bp_list = data[key] if bp_list: for item in data[key]: self.breakpoints.append((key, item[0], item[1], "")) self.reset() def rowCount(self, qindex=QModelIndex()): """Array row number""" return len(self.breakpoints) def columnCount(self, qindex=QModelIndex()): """Array column count""" return 4 def sort(self, column, order=Qt.DescendingOrder): """Overriding sort method""" if column == 0: self.breakpoints.sort( key=lambda breakpoint: breakpoint[1]) self.breakpoints.sort( key=lambda breakpoint: osp.basename(breakpoint[0])) elif column == 1: pass elif column == 2: pass elif column == 3: pass self.reset() def headerData(self, section, orientation, role=Qt.DisplayRole): """Overriding method headerData""" if role != Qt.DisplayRole: return to_qvariant() i_column = int(section) if orientation == Qt.Horizontal: headers = (_("File"), _("Line"), _("Condition"), "") return to_qvariant( headers[i_column] ) else: return to_qvariant() def get_value(self, index): """Return current value""" return self.breakpoints[index.row()][index.column()] def data(self, index, role=Qt.DisplayRole): """Return data at table index""" if not index.isValid(): return to_qvariant() if role == Qt.DisplayRole: if index.column() == 0: value = osp.basename(self.get_value(index)) return to_qvariant(value) else: value = self.get_value(index) return to_qvariant(value) elif role == Qt.TextAlignmentRole: return to_qvariant(int(Qt.AlignLeft|Qt.AlignVCenter)) elif role == Qt.ToolTipRole: if index.column() == 0: value = self.get_value(index) return to_qvariant(value) else: return to_qvariant() def reset(self): self.beginResetModel() self.endResetModel() class BreakpointDelegate(QItemDelegate): def __init__(self, parent=None): QItemDelegate.__init__(self, parent) class BreakpointTableView(QTableView): edit_goto = Signal(str, int, str) clear_breakpoint = Signal(str, int) clear_all_breakpoints = Signal() set_or_edit_conditional_breakpoint = Signal() def __init__(self, parent, data): QTableView.__init__(self, parent) self.model = BreakpointTableModel(self, data) self.setModel(self.model) self.delegate = BreakpointDelegate(self) self.setItemDelegate(self.delegate) self.setup_table() def setup_table(self): """Setup table""" self.horizontalHeader().setStretchLastSection(True) self.adjust_columns() self.columnAt(0) # Sorting columns self.setSortingEnabled(False) self.sortByColumn(0, Qt.DescendingOrder) def adjust_columns(self): """Resize three first columns to contents""" for col in range(3): self.resizeColumnToContents(col) def mouseDoubleClickEvent(self, event): """Reimplement Qt method""" index_clicked = self.indexAt(event.pos()) if self.model.breakpoints: filename = self.model.breakpoints[index_clicked.row()][0] line_number_str = self.model.breakpoints[index_clicked.row()][1] self.edit_goto.emit(filename, int(line_number_str), '') if index_clicked.column()==2: self.set_or_edit_conditional_breakpoint.emit() def contextMenuEvent(self, event): index_clicked = self.indexAt(event.pos()) actions = [] self.popup_menu = QMenu(self) clear_all_breakpoints_action = create_action(self, _("Clear breakpoints in all files"), triggered=lambda: self.clear_all_breakpoints.emit()) actions.append(clear_all_breakpoints_action) if self.model.breakpoints: filename = self.model.breakpoints[index_clicked.row()][0] lineno = int(self.model.breakpoints[index_clicked.row()][1]) # QAction.triggered works differently for PySide and PyQt if not API == 'pyside': clear_slot = lambda _checked, filename=filename, lineno=lineno: \ self.clear_breakpoint.emit(filename, lineno) edit_slot = lambda _checked, filename=filename, lineno=lineno: \ (self.edit_goto.emit(filename, lineno, ''), self.set_or_edit_conditional_breakpoint.emit()) else: clear_slot = lambda filename=filename, lineno=lineno: \ self.clear_breakpoint.emit(filename, lineno) edit_slot = lambda filename=filename, lineno=lineno: \ (self.edit_goto.emit(filename, lineno, ''), self.set_or_edit_conditional_breakpoint.emit()) clear_breakpoint_action = create_action(self, _("Clear this breakpoint"), triggered=clear_slot) actions.insert(0,clear_breakpoint_action) edit_breakpoint_action = create_action(self, _("Edit this breakpoint"), triggered=edit_slot) actions.append(edit_breakpoint_action) add_actions(self.popup_menu, actions) self.popup_menu.popup(event.globalPos()) event.accept() class BreakpointWidget(QWidget): """ Breakpoint widget """ VERSION = '1.0.0' clear_all_breakpoints = Signal() set_or_edit_conditional_breakpoint = Signal() clear_breakpoint = Signal(str, int) edit_goto = Signal(str, int, str) def __init__(self, parent): QWidget.__init__(self, parent) self.setWindowTitle("Breakpoints") self.dictwidget = BreakpointTableView(self, self._load_all_breakpoints()) layout = QVBoxLayout() layout.addWidget(self.dictwidget) self.setLayout(layout) self.dictwidget.clear_all_breakpoints.connect( lambda: self.clear_all_breakpoints.emit()) self.dictwidget.clear_breakpoint.connect( lambda s1, lino: self.clear_breakpoint.emit(s1, lino)) self.dictwidget.edit_goto.connect( lambda s1, lino, s2: self.edit_goto.emit(s1, lino, s2)) self.dictwidget.set_or_edit_conditional_breakpoint.connect( lambda: self.set_or_edit_conditional_breakpoint.emit()) def _load_all_breakpoints(self): bp_dict = CONF.get('run', 'breakpoints', {}) for filename in list(bp_dict.keys()): if not osp.isfile(filename): bp_dict.pop(filename) return bp_dict def get_data(self): pass def set_data(self): bp_dict = self._load_all_breakpoints() self.dictwidget.model.set_data(bp_dict) self.dictwidget.adjust_columns() self.dictwidget.sortByColumn(0, Qt.DescendingOrder) #============================================================================== # Tests #============================================================================== def test(): """Run breakpoint widget test""" from spyder.utils.qthelpers import qapplication app = qapplication() widget = BreakpointWidget(None) widget.show() sys.exit(app.exec_()) if __name__ == '__main__': test() spyder-3.2.6/spyder_breakpoints/widgets/__init__.py0000664000175000017500000000000013003520703023267 0ustar carloscarlos00000000000000spyder-3.2.6/spyder_breakpoints/__init__.py0000664000175000017500000000046713003520703021642 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- #============================================================================== # The following statement is required to register this 3rd party plugin: #============================================================================== from .breakpoints import Breakpoints as PLUGIN_CLASS spyder-3.2.6/spyder_io_hdf5/0000775000175000017500000000000013225025007016521 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_io_hdf5/hdf5.py0000664000175000017500000000520713026261006017725 0ustar carloscarlos00000000000000# -*- coding:utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """I/O plugin for loading/saving HDF5 files Note that this is a fairly dumb implementation which reads the whole HDF5 file into Spyder's variable explorer. Since HDF5 files are designed for storing very large data-sets, it may be much better to work directly with the HDF5 objects, thus keeping the data on disk. Nonetheless, this plugin gives quick and dirty but convenient access to HDF5 files. There is no support for creating files with compression, chunking etc, although these can be read without problem. All datatypes to be saved must be convertible to a numpy array, otherwise an exception will be raised. Data attributes are currently ignored. When reading an HDF5 file with sub-groups, groups in the HDF5 file will correspond to dictionaries with the same layout. However, when saving data, dictionaries are not turned into HDF5 groups. TODO: Look for the pytables library if h5py is not found?? TODO: Check issues with valid python names vs valid h5f5 names """ from __future__ import print_function try: # Do not import h5py here because it will try to import IPython, # and this is freezing the Spyder GUI import imp imp.find_module('h5py') import numpy as np def load_hdf5(filename): import h5py def get_group(group): contents = {} for name, obj in list(group.items()): if isinstance(obj, h5py.Dataset): contents[name] = np.array(obj) elif isinstance(obj, h5py.Group): # it is a group, so call self recursively contents[name] = get_group(obj) # other objects such as links are ignored return contents try: f = h5py.File(filename, 'r') contents = get_group(f) f.close() return contents, None except Exception as error: return None, str(error) def save_hdf5(data, filename): import h5py try: f = h5py.File(filename, 'w') for key, value in list(data.items()): f[key] = np.array(value) f.close() except Exception as error: return str(error) except ImportError: load_hdf5 = None save_hdf5 = None if __name__ == "__main__": data = {'a' : [1, 2, 3, 4], 'b' : 4.5} print(save_hdf5(data, "test.h5")) print(load_hdf5("test.h5")) spyder-3.2.6/spyder_io_hdf5/__init__.py0000664000175000017500000000054613003520703020634 0ustar carloscarlos00000000000000# ============================================================================= # The following statements are required to register this I/O plugin: # ============================================================================= from .hdf5 import load_hdf5, save_hdf5 FORMAT_NAME = "HDF5" FORMAT_EXT = ".h5" FORMAT_LOAD = load_hdf5 FORMAT_SAVE = save_hdf5 spyder-3.2.6/img_src/0000775000175000017500000000000013225025007015241 5ustar carloscarlos00000000000000spyder-3.2.6/img_src/spyder.png0000664000175000017500000001275213003520702017260 0ustar carloscarlos00000000000000PNG  IHDR>a cHRMz&u0`:pQ< pHYs ) )@:NbKGD^IDATx]UV@, %,AF IQHG)*H^ % *HR*}oSL|]{g<;;_OBEtH$>h\+vС@t>P7//OXWr?0 ` LgcbZ@t륲0Qd 0? 0V2/8ZKj{ _ɼjd˦s2ƾM:l?P! xO, $1_ K"@.JɢL#x?Sk/Ym`0x M`&LS)$`"0fm2k`0 A@ЗO2 xt[mEY\ZH&*t8u\Kw@}D`g#gj7/'^5L(.v,}D׮]En @Ϟ= @߾}   (^|E1h 1x`1d1tP1l01|p1b1rH1j(1zh1f1vXK/_~Y7N+W_?~[@T>KJ_FM7 vm⫯L׾}mF q 5k&;1k׮u?IoibA%KHNAb۶mN$QQv-&Ol|rwY:/BzZn-8D2A!R]v瞳}}ΝV:vXGK2.C=$}Oc-Z3f!AMo޼y(w=cT6m*56nDH(}}[nyj~RS}@ @zz"rR잞ŋ۾ĉRc :t`D Jߟ>qV,[,֊ )4%&K;lze͛7F.ԩuO5iC SOi/һk=˧RԩS #3yBGnhʔ)@T)~<[nEZʉ5t^ F}g}2OEÆ ۝HbI >;iFzuP)~\ &P? #3s|O?Iٰosq4 ^tZ4F]v=sLu]Ab͚5b޽ByEawrQ@G[`A B<M~dv` JTG8 NI tO?ԓg dKAfAc~3ȑ#"@J_nfѸqcѪU+##=`Ҏ 154"0&?C%O0NJ{<`<}12Fҳ~zNͣcҥF"{_Xs;]o#jڄ8z,Ex&X̫ǰ.^ IW/fjشi@wA}H@K\)$'P\zRIXuW>Yz 7Q FAάpY䠢8V(@otnb$\ ɧEF$][W(iC2"KEH"81u۲s(vfѧZ53ŞeEEyǂ#`0՞_K3>[G>t<>B.H,WNk{Nm7v8&‡_<B BVl)_^%<-w |$_k7qbK0PNPt0$P , <'nBZeB쳼2n tk qMȘ[G/]~!g\C##u:߿XwވIV55ǰ4xtm?n۫2oQL/ $sh}qRvtZ#}KڑvsX3Xs2  J󷖳 B9 'd\39hseaLpLĹ}4H"B~\ $¬j*z٢vV= z+H@UT-իC,_~ʚol,|a\A6WD 1<^O8 W9 ~z`gPCjUg[÷ݐ-0"9 PI$$@C*(`vi ~?Bxm?JSL|un^$p+|Vm1H偋*"'(\'*u'hhvH[YE9T$p+|zјIsf k{!BH xUCRAvȟ`N pX* 0k`%uOsAQw[cVw%dE(,fS4jQ* D"[EF-b)x԰HX(|涅46n)IzTN%Ī-L%s6& n#tHZ'8&|t[2yqд,smb;P&.W6.HZT 9umU[8?ڵzܦ;?\Pqu˓ _oxk]~b̡Bch+:ӧ69% nz>n^q[Q_z\GA ZUC- Cn H2ŝ(>uc©}I PNU[ig]'D`yY/krѩBQƩZ:VU=JLWd#m+FjEPSUNNNmTw} ŚՊNm**~Porz#8\׬I&0 1`NVc˘}n M BU #f*yOPd7˗d6V,pQ(5Zy5.؃fI$Ъ<*ŧSH6-Z4w\r}03lɀ`p04+lgL5!`4=s+/ǁ٩ұ5O ,JB=Wawàsj90fH{W X`0m(ۘ$`dXJA_evܹN<Toqܶ|6^ǩ3ham\m$ = W*צRyC<>A%^Znv:l`7W4$5~;xR*й jrQsw8pA`GL1~ faSƐq:1yn|XCY ݻ = \ 1ߚDL5rۮ"j6)fL5(t~كڱc K65?r% x%;]t,,12߻S(:CǍ: |$`ZS' ,NO^Yl̪5(4K?9Ub S-K BA݁ yf{.0S ?N{R~IENDB`spyder-3.2.6/img_src/spyder3.png0000664000175000017500000001275213003520702017343 0ustar carloscarlos00000000000000PNG  IHDR>a cHRMz&u0`:pQ< pHYs ) )@:NbKGD^IDATx]UV@, %,AF IQHG)*H^ % *HR*}oSL|]{g<;;_OBEtH$>h\+vС@t>P7//OXWr?0 ` LgcbZ@t륲0Qd 0? 0V2/8ZKj{ _ɼjd˦s2ƾM:l?P! xO, $1_ K"@.JɢL#x?Sk/Ym`0x M`&LS)$`"0fm2k`0 A@ЗO2 xt[mEY\ZH&*t8u\Kw@}D`g#gj7/'^5L(.v,}D׮]En @Ϟ= @߾}   (^|E1h 1x`1d1tP1l01|p1b1rH1j(1zh1f1vXK/_~Y7N+W_?~[@T>KJ_FM7 vm⫯L׾}mF q 5k&;1k׮u?IoibA%KHNAb۶mN$QQv-&Ol|rwY:/BzZn-8D2A!R]v瞳}}ΝV:vXGK2.C=$}Oc-Z3f!AMo޼y(w=cT6m*56nDH(}}[nyj~RS}@ @zz"rR잞ŋ۾ĉRc :t`D Jߟ>qV,[,֊ )4%&K;lze͛7F.ԩuO5iC SOi/һk=˧RԩS #3yBGnhʔ)@T)~<[nEZʉ5t^ F}g}2OEÆ ۝HbI >;iFzuP)~\ &P? #3s|O?Iٰosq4 ^tZ4F]v=sLu]Ab͚5b޽ByEawrQ@G[`A B<M~dv` JTG8 NI tO?ԓg dKAfAc~3ȑ#"@J_nfѸqcѪU+##=`Ҏ 154"0&?C%O0NJ{<`<}12Fҳ~zNͣcҥF"{_Xs;]o#jڄ8z,Ex&X̫ǰ.^ IW/fjشi@wA}H@K\)$'P\zRIXuW>Yz 7Q FAάpY䠢8V(@otnb$\ ɧEF$][W(iC2"KEH"81u۲s(vfѧZ53ŞeEEyǂ#`0՞_K3>[G>t<>B.H,WNk{Nm7v8&‡_<B BVl)_^%<-w |$_k7qbK0PNPt0$P , <'nBZeB쳼2n tk qMȘ[G/]~!g\C##u:߿XwވIV55ǰ4xtm?n۫2oQL/ $sh}qRvtZ#}KڑvsX3Xs2  J󷖳 B9 'd\39hseaLpLĹ}4H"B~\ $¬j*z٢vV= z+H@UT-իC,_~ʚol,|a\A6WD 1<^O8 W9 ~z`gPCjUg[÷ݐ-0"9 PI$$@C*(`vi ~?Bxm?JSL|un^$p+|Vm1H偋*"'(\'*u'hhvH[YE9T$p+|zјIsf k{!BH xUCRAvȟ`N pX* 0k`%uOsAQw[cVw%dE(,fS4jQ* D"[EF-b)x԰HX(|涅46n)IzTN%Ī-L%s6& n#tHZ'8&|t[2yqд,smb;P&.W6.HZT 9umU[8?ڵzܦ;?\Pqu˓ _oxk]~b̡Bch+:ӧ69% nz>n^q[Q_z\GA ZUC- Cn H2ŝ(>uc©}I PNU[ig]'D`yY/krѩBQƩZ:VU=JLWd#m+FjEPSUNNNmTw} ŚՊNm**~Porz#8\׬I&0 1`NVc˘}n M BU #f*yOPd7˗d6V,pQ(5Zy5.؃fI$Ъ<*ŧSH6-Z4w\r}03lɀ`p04+lgL5!`4=s+/ǁ٩ұ5O ,JB=Wawàsj90fH{W X`0m(ۘ$`dXJA_evܹN<Toqܶ|6^ǩ3ham\m$ = W*צRyC<>A%^Znv:l`7W4$5~;xR*й jrQsw8pA`GL1~ faSƐq:1yn|XCY ݻ = \ 1ߚDL5rۮ"j6)fL5(t~كڱc K65?r% x%;]t,,12߻S(:CǍ: |$`ZS' ,NO^Yl̪5(4K?9Ub S-K BA݁ yf{.0S ?N{R~IENDB`spyder-3.2.6/img_src/spyder_reset.ico0000664000175000017500000030224713003520702020451 0ustar carloscarlos00000000000000 7f (?800 %g@  f v h?PNG  IHDR\rf7IDATx VSש:]_GRHDD0eÌ4ˈ! ]B.ɵ$D._w5=k|gkw^YϥDedw9wݟQQ"p~! 9"]+.dZd"rԪ_]/dyiO9plt}+v䷩#r[r(F}uI&>rs#GVʱu6tfokw8[~Lj@r٬O7[:l EN:o/ajńF6=z5 unlV }/AlgɱA{w:5"v^lvmh'yr4#I 9͖A\ Oa{SN4<")f7yDN&[\ OacyFu"G?9=j,ms} q 9]d AiC~*ʠ3B&>1 Ey6!';eq5ąL|"rz_Y/y&{g g1'?VWh9Rxo^o͠9fy$ T=|NXVlr72@I9vݏ m~-Zם#h p~Z#h 0LNwGo ;W2@R9]V]w"dH4u_2|ADֺH2i?rݗ -_hN2q%;w2RG\w"dP 2IJᅩ'\w$dPFh/AD`đL R9gq?$dFTr@f˩D&b 7ߨx|NuwjS% j6nI"ɨpB5~|$6QFSk׎ˋU.]|..dP ]U/tի=cvqG_o|X!#e7bfחKsOuQVK)-0uǁL߸qW_}RcGݺuiׯo]S`^Pgv}{jw,H{~ӧOWӦMs}ɱEO4UX|f`[1bE+Q 1w\SO?餓 >~zwu ~lt}O\Poҥt}P]vn!uԨQ.z%Eu"W'.(Vi&uwzbA/>_l!:0iRtя)=o xs-YR过-?taݔ۷jݺun,ԱRe//t4i3gVZkc#x.ՕW:[o{L-^>٢h ,w}=֭S{[o|M׷͛7n;c kU1&0 W1Y'S( aϧ_>f͚n۟Y@~?Liݾ?0zn]ES`US۳A.F4;)6? A@/9)Q"t:"+~h۶:ôBӄhO>D=VjXD[|$R\ A6֖:w-[z?ۘ VKA?IF02dVJA2{ pFLT%'x=q_!}6sL+DrlccٲejNã-  @<%q1B7mj„ Q*k0p0Alk[q)"#q2B7EZ*۟|gjtAu1$"O0~"!U@ S#j^d6x!)+_! Ё%Kү_?#Id91@!H2T/A?'j[u'ELkH%jIRz/"kc@b-q6@:U`pe(7JO:b+F?j7 9Q q{4[ԩ:ۅ#ju~c@$WpSa$IRPIeKJFd"2aW2q AK _5Pbc0_}8 ,몀\Ej;Hѯ" qOo}c |}D ;,>\_Oeb%I3U$MxC`'x;b?ͥu1 Dnw}=$W  o^al%:U@7bS"T_!t] @n@翅=3 B΀EXd$Wȸx w7S0A7I 9SN:A?jUv^%ֹ$Wb0i$5g_ks4B5)[7ʳrq*I7!Pj\U7ٜ%[~0xTEƸgORZ~ BN' ooFw=}Z@륂 9:|Z\|i59+_!8{F,裏ɓ]w#tԣ0L@>R߹W_!HA 0$y;{9CH/|V)9LW{n @ڌ~hժ?3q$>zG])3p<2ζ5~*G~::O*7*i4fp%<)!En j_}nDna*`KhctA/M]RYO<]j˚~9uh f|-ZQH/>_-~Un_ʳgr"q41h;]m[=#3ڳfٳU>PrԞ;fbpF3 H]4IvJ*tmM( &rMDyo|xfK6^v7OUKzKmjJ~#GLA703ipUX͚3P+nIoG [$5)$gMnʒ/SW6:O?f%2ߨi<$H~'RIpüM J-ZNTj뛔xy"ԡI׮NRYۯ a" @jEPa.9e?(+dUVyXItQ9]V?BlflTIh#Sݥ?6hb'!Yں$9! (*q2#'s"8T塬|q`M7^u蜳#nGa $;SIxPŋ޼yo\8j͑Ì.!մiqǹ]'z@;pɒ% zBy㇐!ǽ26fWνء (X2Edu+ooBt}/0< /I_f}ǎjA?A}y۳w43(r dg+--jժ'w 'Yfm11%[sъ65-vh,5=ۍ;V}׮_% t{:՟B~2tۑ ;aJ8tP6[N롱AKL : ֟)>S}2Zت($m۞YqIe oJHTibvvBmO1b8_0?0 8X岚hC%>{,k£d@LIsmڨ%fVE1c` |zbƏDB-Ps)2md:t:vLD#z欳a (h;>,M ɼFDe9i'O~Gk/_:}j1c6l mte;mL3ǜeRp{EOEHvn;d(R|?^m}y+Jϵ"0"h y{ | 7"C~*|͈#bUO!CheM׺vdl4D36K^ancmV{f3Fʁ[\D[۱lXujկݎ !@+rm:YaCϨr[n&?#am̕SvI"0uhԧ*2#Z"&!\xA6$r{.pqhz Yxސ_(`ʥ1" ~m1զ~Zz9`oL |sl3Щ[Be}4`]w ƎUwwݍ--4@0F<DQ*"0ON{]zף^hmVvcz՜-f< >nxBu(ooCFin  ʒk-o&:S{Z9k L(˓goMyuQ@˿KC5z4tn86Ec]wJm֨PLٷgjDkKiI$8]gOb2-ww蠖 3fB#L2DWMŖm:w<@_kմ];vƆm=O@4aՁiT_/>?leL ϗv$8ˋPVSF6쳏Z6aܴi?'@="z )$˗4p@/6/x@5bݶwWdaҤI^kHRBH"MHN0D`iiopժoھQfN;y7EÏ1pԨQ*C G6iS(c2A'[}+X`3!lNlt6z* Ҝp ZmJu׭tf;`@>WzLƿ5մ"$vnC({Ȁ֡ٮ..зtQ)Xu<,̝;W=SN7 \z[}-7I;e˼pqDwWoTS͜xI->3u3<[k,L.ޚCm`XsOl<*]*ƽzvln@-3Fm0K478w 6')ckb uA'tjѢ￧8XCA ´cjڴiZm΄(_"+U+QNm!luXv뭪V R]2}i^&+[mؒ MxvR}C;UD91i!ug$(l#U…N[H/oذgԉC v6(Z$P;W0iwXA(!XT/nkU+ VJ<,@jL:uzwC7؆6Q`[(80u2Y3!`^)mVe7yA,X׃=yêG$9pfWې .)hRI혾=VI4 ٰA;Vt =~sp 7{{ꩧ <= C-ܐCD$0p)V=8w}w[ ʔP=X%_ kC+ydp?^gFPɝ֔u{#Fx~It^zw_uق ZTZK8DNFspS =XmڴDGC!YǼU~ꫯdwTfm>O^NK ArݔM>V*3-[Fr [ ː-U*G{~0GYX 3+v^*A&,HoN58!r"~TecƀԑwoT3gӿ``aU؅ g0!Hap8VM"^hǎ!wYu… c2}up IjzB0}z2A wrT |+pIsVĵ`6}ĤmAa ~vǏNL!!j\U׫**߷4`Rss/la R$J umf3g0,\ iS?7iC 9qƅovLUnP- D1]fza^* 㧠C;EηS@;rA ~70LCIE K]Y11#^,AG6L+>$0h#ݥx1' gO-u%1f1.|U˛ AkAWv *Fv >2811f3.x#'Hq"H095`Z(O8D `bg?)SԬYݧ4iDtA^k!`FgAN&PmknK7@XcᰈHՌX5Jl1amBXAc!`4^!lwhD]&Pƍ;{{>l0dbba\!RRH!_ Q^;1.*l&%:8E vl5YxP8T ^۷֮];aPU6gחˡjg=6o r[\GIۚq-LR|y3V 7lf_Iw[Tc1ݙyQyf͢: ~A$$a7܁y%$'%L*02di]E~~@,D$iS<  5 kx:2q*=MH>W,`1=wÈP5xnBA(=A ~#w\ZOu+kuN&A9fhJSeI. *;1%c7{{=ꫯ-g![c:׽~zKMa2ۺ['vx& C֔+-0D_X^NFB^z6"񞊛y.l vߓ{u^pO,@v{ML=d{ !X#G!K=4Qr3>,0V$nN֨K"pXv1t˅"w}9Y={z\_u m_p|&0 7D9` P'J1 4TD5.ZQ.Q~A=+J%-#BL*qpGj& c_RYsrbS!NkL8G0NֱT)fx?_/5M)hI=EeHDȺ1#i%aT-v@;"S{IJo"kL\ 4 1jI$hё=H,X̰ ~ȣ@e#9mʐ2|A1h,ÖDk'"4JX]㠠vqʸC*opJjiF{T8৺fM<ēZuC7% 1GN!@BʉW)O,J}rHRmѭdd5jTlWt  YtwY"cY/~9Po?cMR:RD[əjb;k'BPAb߉ ~@L;s_(h KeyY耍Ҕ'p[C 0/DXpbUdg\W\O?XO;4_^ L"!2E>"N@?%Z* WWԷCjy@E>!@^"mOS5y4zνBIѣu#bGTd5l^T̛7 ]h뮄>l68S}箻n TEb#HU$K+Q"m}ad #VIu,4B@ӴiSuꩧj*֞ {d@RrR-B+\P#b\!rqc*[A ÿDyS"r |,'u `ͅM PP>o}Uڈ/˿TVv@H13$Sʚ:q[Ď+ԅ`+O!dqThVP}幏t &$ZSwfFB >a4|C< IcʄwߓGqY D9:=||Z{d\qㆆ٧N@.;?\k:T.FT~#֭ E">UWA:t:vgoxu .e˖?YXEywE \`~!hb^QiZVϞ*'naܹsmouq\w{XӳaoZ3M[эTK~ @y%;4 ͫSҷT. r^A?`1gF܃={T{챇GHuIʁqρn>KO$LUNn |jCqv!=oW@g9]r;V˿p5K2 _]YU(M#X"}|3y1 ΰGqq3*'L5m_ F_n!u0\ Uf|=yMfTy`Or *W/myY^wm|ߍe .W@$OQ!HX >uTZcp<+$*EHPb[~xiL<˟52':ϡ.h:2 3pXM?K)\{4).cN6~*&bSԆ osћM81򆟨ru_,߱rzX~ acn#cPP=U#x?L.*>J*j!`=4hV1cD .[yH8rFZy:˳AEX4Cj !Mm\u~- az3x6lև tC͡.;K#NO]u"t?^]om}([>'| *z-r--C!F1ׇ ޽{k;Cv{;te ~U!X9~/Z=,`jU \P vrO&aqIC)/[Ξ,NE;~?BvZ]tk#_bz?j *8Ԓ1~`9lPܒ uu6lhvw##"Bʙ*xdݬ`(1cʽ}*q@Un>Cw]pn @@âOWPm?:B'Uɻ]pN;cbD&!Q ޶'7x`:s ;dbD\uC&)FrQmuJg$LR rDLf##0JJe@/ΰG&)F`7& ňFkD~ ňT_OE wfD&{=2H)"}٬aLR!5u3 @J M(܉}ϰG&)Ei4ZKΰK&)EorP aLR*WMk@ΰK&EssE~庯v-g p4IENDB`( R{PnsY?% #=Vi%n. r8 wC|NYdo zmO"#%%,<^)6 GW -A130L Bq5W9bX9=m"G ] m sOV<x9r)essUpp mm Rii ee8cc q__?[[ zXX&&,,Tss33,99gAAII7 QQp**TLLllee SssA|$$6DD.odd##i $,4<--,U::~<vGGGGc[XX..?rrHHUUKO5 bb77{{>Yup0,HU %N,T2a,TAt+ S(R+S5e+RDxL% ?h~}{zxwuts:z}T10 +6x_:'W i#L+C[???????????`?????????????(0` |>bJgVlb pn  uz cLzjt(ng D%}`)@@b<<N77ss H ;AAvNN $U99IYY[[PqqII25&IhhV^7-g5 aF{7+dlq eO2 I -v-Nw???????( @ 'Vp0$4- 88v;D&L`!k/zb{:aa-s[[h ggW U22uuj ]]44 `A>Mu 6)bTnlkjhgedcatd_'"߀c?(0 G`NCRN91VZ syZf? =;;7vs||}%%ff<<5+`XI1  AAAAAAAAAAAAAAAAAAAAA?AAA(  2 ~ ?Yi E>憬Yݲ_䢺ӤnMG A?AAAAAAAAAAAAAAAspyder-3.2.6/img_src/spyder.ico0000664000175000017500000030463313003520702017250 0ustar carloscarlos00000000000000 <f (3=00 %[E  k { h3PNG  IHDR\rf>N0wvBpNw܂/>;[J>kyk"|?`9yW)p5ݶDMVޭX?o^:  %]ѱ:!'yVPwo/fZZ  m>MBPDm[[6Wv~Jnaô@w_(4ϿEН=msP/1* I=0mOD~»^=|>`~v:CNw O%xu}`},䇩v'|0B[[% o,߳ӺC5xQ_a*݉ߣ{¡X߯AVr'5 Ѫ?E)d =]U'|R¡y+sЅ/&,/<1~>v9X<^G_>`~.!o?2|O7}Ic<ߟ'un|0 ?l!Sk^ 5p^J9t Iaw"onMx|o>}n'>AA"7W[8|ߓu[$5ݧm{ xCPhsp $xXm~ؾv/,ޜ8&|0 ?x)47bT޾Pi0uKIgo}:Mb57)QCx  ++{-'pGn?*[jۺO5?`*P-3gR~ˬ< !@/ݻwS.~644h@=&n;v=tq*W2 }Mtpə3gYft9ݗ@;W]u1ʒ%ÇKGy5j$YOL}mT zoc:uDK;RJۼya3o-k #j>Tb?G% %Ueg~z7n|%z$2JOj:FNBo v7|J :my#*FR~RK<>ˆSτ K.1}iӌ-Qۯ(3f̠?8ݿ-ZzI3[rsy{ Q&pN^[FuF{1V… >oAڸ{q3OOV=2?yH5БCSժUM+濉H9hK֭3ٖ-[=.uYP~ uI&]o 6G}w`$QqL27ha eER@ѯO>Z8˗7֡Exh׮]/Rzcʅ5Ųyʕ0 ^qmx"(. l߉G͛+V<@ի7ɓO?Xmx,O9~4IH5ӯ4E{B-^êa ßRziӦ2N-H箒><'NfYfz\z4dKCq,]v "[QC5oPt킐ь~ g?ՃDo_Eͥwo95=fj^k}/F<%縷##Fh3|5xn9Rҹsgߥ#,&g:<#oPxcFhv^z%O.ѫJ7|qs1<,eSbECX$03aUFhΝF 6kJ *T0;E9ru܉?8կ__W=" n~:|e˖g͚E'z3Vs"C}e%ALJ.mVE`cUD j_4"7x#F_m۶f.vK20rV ;L\ ,?`X>|nnYA+>"-뎘YI;o܆m2rNVt!uN>r);r5Ji[kժEO?zEMH\ N_4ʔ)c _EON_*e`^ݽ{w 0!ןjڴiCwuݯ`mEO@*R~o.t=z1X9ꫯF*>s-q H&br&@ wc{1f6s5}GO=qy!RgTQ0{v ;v2+_wH/HVYC2]u"EAӀ!nƍOncJ&!hVG7ѢE ]:tHuALG9(za z!jܸj"0F%. [~@*+H%V} >8΃stFl)@t3vYFhRQ[:cԩ'>4Zj"҉2ҀFH`D;v1X9X`cmr@#Z8Aּ 2l3VE E9eFh+4y,;>> 2=KЇH~NAfAH0B x1֭[W 6q3 8 Yf>ppGxL]khgSP;>"/q~(aVxq_GۮVp/V&\tƼy?|!0QPdZ(>% wy8mގaĈdo1 (G5OJÓ3_$V҄n1Dnl=XiN,boqģ/X/V㏖eVȎJݾXرðèc`SJ_s, W_4D]4Nt{kvWڿ~6KAyimʻ~j_4/!`ۀ+CFA+O:vo( 疒[-Gx"HU;wnT+989U q^jMtepBzt7C:DHh8E1M6ٳ]5|'?[*v.:~41GIn0ECR9OrJ#S@zFdH#:Cx:uPu7`Zx=XEnA 9,5LЎ% 7/b  [ΰx0@b %2Y.-]ϻM ~(7+W.(aa9EB'/ҪU+YݯAހsJ}6ޡ̣E+ ƌQ&0Z3@0Cǖi{t~@"$+\9#hxZ$8E!PP$[(ń9 +be~i9s4j!6?iosER}{gD)޽gFN;..R ϓM~2wҘ%_]kސXkI~c8JNbd~pAMH̑;nt*wrlXmz@ \AnNHp}0" a>j[Y+ߏBHMx$ڬ}{ bg-v7vztPhՁöcV`4J4HcKG}6VD48L;:ذa†ÇJ6ec-w s;JJ#;#;{,wk7֭3}^>FV-7x?_D fSK&~lDPlՊRb_?<س)d[l:/$ಳgf͜9sVHY3f͔)ONN6IIIU[x] "(ΌaO>؅rOCt҅nv0}ضm6 es.]|;!pO!3Kˈ!! 0Eso޼z衤-o{]Z})ߜmlQv-D oO)ѳ'fZh @N2Ki_$? @_S$H! ~#SIC L&X7aQߡn[N8( 9&ȝ? "(-H4?`Z?{1#@^ܲS;E` _ᥲ;_~( 2U(3i{3pñc]*PgE<-y_=Yk'._ D_2J5j-ZHZ;E8qB`ҥ܍@zq -hтK؟!*~O3 (ICߑ{+W(LR.CǯT ss8aUr;?^qb{2 pK*eիW XHD'EC~QѢEt挑4)ca1S(oQʜ ȣȔ Ko_ڀ|ð)]!Hgu-t:,=#yf={6}G7>Ey's'^ナ+"|jBO#,3K~$)ѥ3#S}_~i@⋢Ǚus^x33D=HAK`{A˽DGJVHU ʴ˖,%MtZnc[PXnnF{agϞaÆMj"PCtuV\M2H7_[E /rlFA:;OѪ`饗ļ2y&0~V@'ug)@(IA/yd~QKKC;S|fA E;qa(XaMb={(^! J&M"yw]0w!ȭ4oX2 ":t /դ!\II뫼<7X;*9 =.!͝tڕnV߻ϥo_k]inZZICb^ɓ)^;EAj֌|V8*~k9526d//Ǝkm^ёkᇆP<lЀRF'"QPq 8P2jA8qjx}vq! H,fϦ-^K7~zWr^+, qPXήꫯd$+9E&ȚkO /֟@8(B$yE;?R >6ǫ[nQE9 .=YjLuK4ǍgtST @C}j<7}?O<2>RݤيE8nMYC$wojcBJmo?Uw֭"YM6!^D3jf&8:}^>H)F%|]`wE2ο+?V:?js E@##0s2zTzV@1c2g1,-UIIP@EWd-`ԧmڒl f%X&}7 ˿s_~wS.QTV_ y\vҤI4s# ^V'N8;'X)G4/`FEk@IT1Jѷ9Rc!i m4G:=:?D@qs0x~.T T zom LCG?F^YD4Gk7j>LRRpp %Ӆ %Hf:zdh,ݿMZQfwdv~p]w [`%յUt8ΣK7;wB-(Qx|#[.١x`ZB'm" &MЃ>hHrd')(uD{aH lY(T2P,ƨgŊFCTf_5T z@*,۷oO:E Um[̙g$5kWʾj57 fY Q` e *u^/0;~Qb…N5E 9H؁ J0 XÇ(wӑy(7  /˛΅%67R[`w~$vP*E` E"dǏ. PW.8hFUyZGﲦYUɼk$ӝjpPnܹF~D1 #ɱqYܱmϼeINiz|\C ?$AP .QW'NyA"zu*u!doР=c:.U@+#伉})6~`I9l_ ? Xv|Tf})]Ti~%kPƭؒ%KRj$FUzV5T@)b,oi:~L#m޼z>g-PΏ/Pps޽/;eSHW,zE>6 U۽{7Fġ]nS`ՃS"E6a(yʯ]g'k-\B/^Lv17DYlA)+VB +3qj($tm\y%y NzEhE-?$/E:",q:W/GcF' VF)+Wmã%-[]f %5o](YR&L0pF|׌(M;ZʝkS A¯X ڸ ae޽mB(]!%t~kD ڵKX0OΜ̃GIO>IoG2!CHgPQ i!j>,zIMu*=]va-R@?$@Nj҉Aʔ)#\"A{֮]K|SbŌE:,S' Lxm>G xVR.X>rH ]'`Xp.(VQhQ%F0%`$Ĉয়~w\aF;sR 6&`ݺibxqӇA 5D˥ @#Mr,JqrEN$G$^؉ !Py(0 i !0B]4Uxee8ϣ1xQ;?Pw,TXf6-#Ώ"EjP|y~Blذ#GX+ܡY :G-R0\"f xl0p@*T1bxF@ W؉'mt~t\yH=BTF~!,( '-Z^PYwwfN~n9t,X2z֣ӯp of+91A-[b~h@Mt4t䝰 ۿZnk,DHA^JJrR̙!?sA/q(g{d:%ѹ?'(~Xe(YMLd#e\;A:RÆ U7eY@)ܐ&Pnݺݸqђi,®q2+4vX#kY0,DQ&o޼Fbյ;ciLHₑFOV'%:a3yVv,!ziLΏZqhL6rBP|-A *@V 3LGhi3߷[6!]v1?Fǜp.UxׯO5j0|N;c 2=( ˽`j)5' *V,r3 8<sehWc0¨W\9KkÝ:u;k&u C:? vx U z HSm'9 t{-Z,Os ԓ]"+-59H5i$ݗpWծ]X ^P %,VH6- L8 nX!J9] oC7*F"iF><S#Lpi#D@3(Jcp *pqp_!&!C2+(\B1n]:cﯿJ۶m}iIP(dc{~vy/w~ߋСC#qWnV@&ө,2& "a5v›_8-CZpcVJo۱Xq\#E9+pVH;Ya xm1B]3Y X!Bfs ?/zLQrnʝ`EiӦ?<**CV_ʝڜ!&PjxL#4 wEw> f),Mto8nUQ:<׋iƈ0 eFoJo,UXPBI 6##!:7|-`ҕr,>p(xD`O' %HvbpB@ΖčЙw 5K,SN5& (YȝR`'qTr'eF,GdӤ/Rw |A,=t[$nCԀvdAxaw7[FţDq*!$aX"qe}6Uȕ+QX$DգDSER2~"qAw!Y|&OX B $"`:`3Rppλx+o2 kOݧԅ)ZlIǎ"zU 6jq,tK$TG dw{ 7Y庼BժU}?eR,(D')w)FRÁ6g/B… +_.>}7 *hBw,B<򈌢( p͐# 2ŋi<4]A&MBfTG˹q$m[5WtWR_?:9;*>pLh[1[oL`&qM#^;ٮ7׎vHw^]Ν;SŊS.ob Lmqq] \hQ? C},gk,F;z0h!=KìW7L{ҫ V~TVB )]T_;CW c!"P'Qֹ~m:yndxD"'&X %mВoMpG&T XYBWW2} Z R~#%{u W" 3V~@PeBEAD$H{Z!xzP7…Umի wܼU ;Ï`ǎ" D󨢃 D "V>dGsx"p@:&ag-+2 !@!x9E-/*5S6<J wdo٣4apƆ񰞊  ނ+%K4"Dhݺu\yS(PXʫR1dB6LJR ՗EHZ̍T{oʻooC1'v+Շ_B'se7EzhVxҮwL{7Nќ%PHʥ~˖-p2~#,'OF5C&͇a;?W0 c3jmŢ`c|1+!ߺr!ؾ}1"XnQFFPYF-98ކsz("ahmwفÑ̖Ot[vmZFi{ۃyK2]VOyTNӟS4w`hi Hl aI}׌/??x9P7eX>Jr9Bڤ^:v= }sNCV^?gSʍgS^¿ǩcӼIb0S'^ben:,_KQ 8?Ν}pE")4bڇ/r78yv felE&|rvG+cE3ߪsN:歪cmi>N9`$wp5V>DYfʐ)`=Gd]vu$ 1 ktׅ¸яGm!5yڧ 2`Vk"# M #kDY={pAd()3"uS|ygqDep׈mۮ܅ 9oo,r4e(4=ȭQBb<"Dhڴ6*Ueʔ~LgrSJ4C*i[e iJ ټ=~swc[`]@/0jڥFFdY!v(WWX1ǯW:`i)8 Bt *pAǟ$49XB̧?N3r!8*s#O།)(WT">[-F!ɺ:Ij)Td>$?3C N͚53kfqN/2P͙30Ƣ[nT 8(= =xy]7&aOP(տ!@!Td_~FK@X&Lpѿ]nݺFϖ-rz;宛H \x!(D!SѡCG!Q7qDȕ+]W| u|u_$B׶)YJC 8ov>Șeȑ2uaثV.w]R~^HuFnf@QFm8cǎ5^I($T>ՎJK$1 C]xם74w]dM@,PHdOWt캾| jۢ]X G}w] HM !0?~.Nu݃/. ʪGb>|p1 p\wC|'Dw!TA஋8"*5&w .yw׍O|c4BnZv_t_R "Sl!T8젰 ]!, w]dz _q/DJg>jäV6$ڈ`ReJw} a@9ूaإ>jð4PYXv5aX:n!nuaX!_yC}aXP\QC`Ww} aXBbUƱ4nuaXFCz>ð e<0Bw} GΟwGk0Sw} Ga(;TYVn:|( VWmQ/ M8; _< )p^tG-xk/p:tG-x$}kxbpvDQ#C ۇ"tG--5{!>IENDB`( R{PnsY?% #=Vi%n. r8 wC|NYdo GGGzzzzFFFAAAAAAkkkAAA\\\DDDAAAAAAAAAAAAyyyAAAAAAAAAWWWmO"DDDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARRR#%%~~~CCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMMM,<V)zzzBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJJJ6 GW -xxxBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFFA1-0tttAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADDDL Bi5qqqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA|||AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBzzzW9nnnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoooAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArrrbX8=kkkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA```AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkkkm"hhhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASSSKKKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdddeeeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEEYYYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA]]]GbbbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWWW___AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuuuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARRR\\\AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANNN ^nnnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJJJ ngggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAppp swwwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXXXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIIIOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArrrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdddAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtttAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVVVGGGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[[[<AAApppAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADDDhhhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJJJxdddAAAAAAfffAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEERRRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBddd9DDDAAAAAAAAAgggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEEOOOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqqqrAAAAAAAAAAAAAAAgggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGGGMMMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApppAAAAAAKKK)AAAAAAAAAAAAAAAAAAgggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGGGJJJAAAAAAAAAAAA??F55c))##..u::SAAAAAAAAAAAAAAAAAAAAALLLDDDAAAAAAAAAewwwAAAAAAAAAAAAAAAAAAAAAgggxxxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIII55p"" ++z==KAAAAAANNNAAAAAAAAAAAARRRAAAAAAAAAAAAAAAAAAAAAAAAhhhjjjAAAAAAAAAAAAAAAAAAAAAJJJPPP44""pp{```AAAAAAAAAAAAAAA~~~UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiii___AAAAAAAAAAAAMMMJJJAAAAAAGGG44AAAAAAAAAAAAAAAAAAVVVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtttVVVAAANNNIIIAAAAAAAAAAAAAAAIII VVBBBAAAAAAAAAAAAAAAAAAAAAR88XAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHHHAAAAAAAAAAAAAAAAAAAAAAAA&&--XXXAAAAAAAAAAAAAAAAAAAAAAAA**33fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGGGAAAAAAAAAAAAAAAAAAAAAAAAAAA))||AAAAAAAAAAAAAAAAAAAAAAAAAAA8__33fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA <>G33fAAAAAAAAAAAAxxxAAAAAAAAAAAAAAAAAAAAA))AAAAAAAAAAAAAAAAAAAAAAAAGGG||zzzAAA>>G33fAAAAAAAAAAAAAAAAAAAAAAAAAAA))AAAAAAAAAAAAAAAAAAAAAAAAAAAUUUAAAAAA>>G33fAAAAAAAAAAAAAAAAAAAAA))AAAAAAAAAAAAAAAAAAAAAAAAAAAKKK kk SAAAAAAAAAAAA>>G33fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA>>G11jzzzAAAAAA@@C**AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPPPFFFRRR|AAAAAAAAAAAAAAAAAA>>G22EEE44e**AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEE{{{SShhhAAAAAAAAAAAAAAAAAAAAA>>G,,WW~~llBB **AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVVVDDDAAAAAAAAAAAAAAAAAA___VV556FFFAAAAAAAAAAAAAAAAAAAAAAAA>>G**AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA{{{AAAAAAAAAAAAAAAAAAAAAAAA>>I .oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>>G**AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\BBBAAAAAAAAAAAAAAAAAAAAAAAAAAA22h00iAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>>G**AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqqqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA((RR $,4}}}AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>>G**AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdddAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA{{'|||jjjXXXDDM**AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABOGG,,xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlllAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA((www|| 66_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA___AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA44e dd5w22==MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvvvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA??F$$ZZ\\--44VVrFFFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBWWWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA??E))RR@ii==''PPyyuuuVVVBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>>GTTqMU8$iiiKKKAAAAAAAAADDDPPPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALLLqqqAAAAAAAAAAAAAAAAAAAAAJJJ]]]oooAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBB>YvXXXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCCSSSeeeKKKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAq0-HHHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoooAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArrrHVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA___}}}GGGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXXX AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALLLiiiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGGG&pppAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVVVttttttAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPXXXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJJJgggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEE```FFFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA-HHHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiiiGGGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhhhVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWWWWWWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPPPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADDD4oooAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFFrrrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcWWWAAAAAAAAAAAAAAAAAAAAAAAAAAA}}}AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsssEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA|||.HHHAAAAAAAAAAAAAAAAAAAAAIIIbbbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA^^^VAAAAAAAAAAAAAAAAAAAAAdddGGGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWWWVVVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKKKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBDnnnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFFqqqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxVVVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsssEEEAAAAAAAAAAAAAAAAAAAAAAAAppp.GGGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVVVWAAAAAAEEEgggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWWWVVVAAAAAAAAAAAAAAAFFF*AAA___MMMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVmmmyyyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFFqqqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsssEEEAAAfff.AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOOOWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWWW8nnnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjRRRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFFxxxzzzzzz||||||~~~~~~ .!XI~G, En}|{6z~U2,,=sf<#\ q)S.G"c????????????`?????????????(0` |EbPg[lf pPPPQQQcccYYYq  uNNNAAAAAADDDrrrAAAAAATTT| cLzMMMAAAAAAAAAAAAAAAAAAAAAAAAAAAPPPjLLLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALLLu(JJJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHHHqJJJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFFm ^^^AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADcccAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%}]]]AAAAAAAAAAAAAAAAAAAAAAAAAAADDDAAAAAAAAAAAAAAAAAAAAAAAAeee`EEEdddXXXAAAAAAAAAAAAAAAAAAtttCCCAAAAAAAAAAAAAAAAAAPPP\\\AAAAAAkkkSSSAAAAAABBBvvv$$$$99UcccAAA(AAAAAAAAArrrPPPyyymmmBBBzzAAAAAAb3366`AAAAAAAAAzzzjjjAAAAAA??FHHBBEAAAAAANTT55`AAAAAAAAAhhhAAAAAAAAA??G;;QAAAZZZTT55aAAAAAAAAAAAAAAAAAAAAA??GXX$$||55aAAAAAAAAAAAAAAA>>HDDQ!!&&FII55bAAAAAAAAA>>H>>JAAAJJJ==;ddd""55bAAA>>H ==JAAAAAAppp--vDDDAAA""XX99Y::RAAAAAABBBvvvgg**AAAAAAAAA""$$==JAAAAAAAAAzzzrrrAAAAAATTg $TOOOHHHBBBAAA"">>JAAAAAAAAACCCAAAAAAAAAAAA,,y''Iii>>IAAAAAAAAAAAAiiiAAAAAAAAAAAAAAA//pPLLRRXXXBBBAAAAAAAAAFFFAAAAAAAAAAAAAAAAAAAAA>>J##@@38+Ixxx```AAAAAAAAAAAAAAAAAAAAAAAAAAA}}}V^PPPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA```7-DDDAAAAAAAAAAAASSShhhAAAHHHeeeAAAAAAAAAAAAAAAAAAAAAAAALLLgAAAAAAAAAAAApppLLLAAAAAAAAAAAAAAAAAAAAAdddAAAAAAAAAAAAAAAAAABBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGGGBBBAAAAAAAAAAAAAAA5eeeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArrrAAAAAAAAAAAAttt aPPPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPPPAAAAAAYYYFDDDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATTTAAAHHH{fffAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlllJJJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADDD7+dlw%#"!iO3 I -v0Tw???????( @ 'Vp0$4- 8ttt{{{8v;qqqAAAAAAAAAAAAtttD&LnnnAAAAAAAAAAAAAAAAAAAAAAAAlll`!klllAAAAAAAAAAAAAAAAAAJJJAAAAAAAAAAAAAAAeee/ziiiAAAAAAAAAAAAAAAAAAAAAYYYAAAAAAAAAAAAAAAAAALLLbnnnAAAAAAAAAAAAAAAAAAvvvhhhAAAAAAAAAAAAAAACCC{VVVhhhAAAAAAAAAAAAsssAAAAAAAAAAAAAAAAAASSSbbbBBBvvvRR IIAAA:xx<>J 55a@@DAAAyyWAAA>>J??EAAAJJJAAABBB33[[T""??EAAAAAAjjjAAAAAA??Fj OO33KKoofffIIINNNAAAAAAAAAAAAAAA22h::`LLLRRR```nnnaaaAAAAAAAAAAAAAAAOOOA>MAAAAAAAAAUUUEEE```~~~```AAAAAAAAAAAACCCuAAAAAAAAAAAAAAAAAAAAAQQQBBBAAAAAAAAApppAAAAAAAAAAAAAAAAAAAAAAAAAAAxxx 6WWWAAAAAAAAAAAAAAAAAABBBNNN\\\)bAAAAAAAAAAAAAAAAAAAAAdddT}}}~~~nlkjhgedcati_'"߀c?(0 G`NCRN91V\\\bbbZ syZZZZAAAAAAAAAAAA\\\f?XXXAAAAAAAAAAAAAAAAAAAAAAAAXXXBBBAAAAAAAAAAAApppAAAAAAAAAAAAAAAӪBBBAAAAAAOOO]]]AAAAAAAAAZZZ yyyXXXRRR %%=>>IWWWlll@@B<>IAAA@@B__99 s貜kkv@@B33fMMM 파::U ee 22hAAAmmm??||}mm33fAAAQQQhhhAAA<hh++}TTUIIYݐSSAABlllFF^ bAAAAAADDD࢞AAAGGGVVVAAAAAAߘzzzAAAAAAAAAzzz{{{\\\^^^^^^gggnMG A?AAAAAAAAAAAAAAAspyder-3.2.6/spyder_profiler/0000775000175000017500000000000013225025007017026 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_profiler/locale/0000775000175000017500000000000013225025007020265 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_profiler/locale/ru/0000775000175000017500000000000013225025007020713 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_profiler/locale/ru/LC_MESSAGES/0000775000175000017500000000000013225025007022500 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_profiler/locale/ru/LC_MESSAGES/profiler.po0000664000175000017500000001361713224121062024667 0ustar carloscarlos00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR ORGANIZATION # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: 2017-12-14 15:40+-05\n" "PO-Revision-Date: 2017-07-21 00:09+0300\n" "Last-Translator: Zgarbul Andrey \n" "Language-Team: \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "X-Generator: Poedit 1.8.7.1\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" #: spyder_profiler/profiler.py:33 msgid "Results" msgstr "Результаты" #: spyder_profiler/profiler.py:34 msgid "" "Profiler plugin results (the output of python's profile/cProfile)\n" "are stored here:" msgstr "" "Результаты Профайлера (вывод profile/cProfile python'а)\n" "хранятся здесь:" #: spyder_profiler/profiler.py:75 msgid "Profiler" msgstr "Профайлер" #: spyder_profiler/profiler.py:104 spyder_profiler/widgets/profilergui.py:82 msgid "Profile" msgstr "Профилировать" #: spyder_profiler/widgets/profilergui.py:83 msgid "Run profiler" msgstr "Запустить профайлер" #: spyder_profiler/widgets/profilergui.py:88 msgid "Stop" msgstr "Стоп" #: spyder_profiler/widgets/profilergui.py:89 msgid "Stop current profiling" msgstr "Остановить текущее профилирование" #: spyder_profiler/widgets/profilergui.py:97 #: spyder_profiler/widgets/profilergui.py:222 msgid "Select Python script" msgstr "Выбрать скрипт Python" #: spyder_profiler/widgets/profilergui.py:103 msgid "Output" msgstr "Вывод" #: spyder_profiler/widgets/profilergui.py:105 msgid "Show program's output" msgstr "Показать вывод программы" #: spyder_profiler/widgets/profilergui.py:114 msgid "Collapse one level up" msgstr "Свернуть на один уровень вверх" #: spyder_profiler/widgets/profilergui.py:119 msgid "Expand one level down" msgstr "Раскрыть на один уровень вниз" #: spyder_profiler/widgets/profilergui.py:122 msgid "Save data" msgstr "Сохранить" #: spyder_profiler/widgets/profilergui.py:125 msgid "Save profiling data" msgstr "Сохранить результаты профилирования" #: spyder_profiler/widgets/profilergui.py:127 msgid "Load data" msgstr "Загрузить" #: spyder_profiler/widgets/profilergui.py:130 msgid "Load profiling data for comparison" msgstr "Загрузить данные профилирования для сравнения" #: spyder_profiler/widgets/profilergui.py:132 msgid "Clear comparison" msgstr "Очистить сравнение" #: spyder_profiler/widgets/profilergui.py:172 msgid "Please install" msgstr "Пожалуйста, установите" #: spyder_profiler/widgets/profilergui.py:173 msgid "the Python profiler modules" msgstr "модули профайлера Python" #: spyder_profiler/widgets/profilergui.py:180 msgid "Save profiler result" msgstr "Сохранить результаты профилирования" #: spyder_profiler/widgets/profilergui.py:183 #: spyder_profiler/widgets/profilergui.py:190 msgid "Profiler result" msgstr "Результаты профилирования" #: spyder_profiler/widgets/profilergui.py:189 msgid "Select script to compare" msgstr "Выберите скрипт для сравнения" #: spyder_profiler/widgets/profilergui.py:223 msgid "Python scripts" msgstr "Скрипты Python" #: spyder_profiler/widgets/profilergui.py:230 #: spyder_profiler/widgets/profilergui.py:235 msgid "Profiler output" msgstr "Вывод профайлера" #: spyder_profiler/widgets/profilergui.py:254 msgid "Profiling, please wait..." msgstr "Идет профилирование, ждите..." #: spyder_profiler/widgets/profilergui.py:298 #: spyder_profiler/widgets/profilergui.py:469 msgid "Error" msgstr "Ошибка" #: spyder_profiler/widgets/profilergui.py:299 msgid "Process failed to start" msgstr "Процесс не удалось запустить" #: spyder_profiler/widgets/profilergui.py:346 msgid "Sorting data, please wait..." msgstr "Идет сортировка данных, ждите..." #: spyder_profiler/widgets/profilergui.py:421 msgid "Function/Module" msgstr "Функция/Модуль" #: spyder_profiler/widgets/profilergui.py:421 msgid "Total Time" msgstr "Общее время" #: spyder_profiler/widgets/profilergui.py:421 #: spyder_profiler/widgets/profilergui.py:422 msgid "Diff" msgstr "Различие" #: spyder_profiler/widgets/profilergui.py:422 msgid "Calls" msgstr "Вызовы" #: spyder_profiler/widgets/profilergui.py:422 msgid "Local Time" msgstr "Локальное время" #: spyder_profiler/widgets/profilergui.py:423 msgid "File:line" msgstr "Файл:строка" #: spyder_profiler/widgets/profilergui.py:470 msgid "Error when trying to load profiler results" msgstr "" #: spyder_profiler/widgets/profilergui.py:604 msgid "Function or module name" msgstr "Функция/Модуль" #: spyder_profiler/widgets/profilergui.py:608 msgid "Time in function (including sub-functions)" msgstr "Время в функции (включая подфункции)" #: spyder_profiler/widgets/profilergui.py:617 msgid "Local time in function (not in sub-functions)" msgstr "Локальное время в функции (исключая подфункции)" #: spyder_profiler/widgets/profilergui.py:627 msgid "Total number of calls (including recursion)" msgstr "Общее число вызовов (включая рекурсию)" #: spyder_profiler/widgets/profilergui.py:637 msgid "File:line where function is defined" msgstr "Файл:строка, где функция определена" #: spyder_profiler/widgets/profilergui.py:642 msgid "recursion" msgstr "рекурсия" spyder-3.2.6/spyder_profiler/locale/ru/LC_MESSAGES/profiler.mo0000664000175000017500000000745013224121062024662 0ustar carloscarlos00000000000000)d; #- ="G j-uREUo~   ',*C n+y  #8  6 R Ah    V L Wj * 5 . I \ n| 1 4 R h %}  D D "@ 7c . 9 @ BNF(%'  " $( )!&  #CallsClear comparisonCollapse one level upDiffErrorExpand one level downFile:lineFile:line where function is definedFunction or module nameFunction/ModuleLoad dataLoad profiling data for comparisonLocal TimeLocal time in function (not in sub-functions)OutputPlease installProcess failed to startProfileProfilerProfiler outputProfiler plugin results (the output of python's profile/cProfile) are stored here:Profiler resultProfiling, please wait...Python scriptsResultsRun profilerSave dataSave profiler resultSave profiling dataSelect Python scriptSelect script to compareShow program's outputSorting data, please wait...StopStop current profilingTime in function (including sub-functions)Total TimeTotal number of calls (including recursion)recursionthe Python profiler modulesProject-Id-Version: POT-Creation-Date: 2017-07-11 13:28+COT PO-Revision-Date: 2017-07-21 00:09+0300 Last-Translator: Zgarbul Andrey Language-Team: Language: ru MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generated-By: pygettext.py 1.5 X-Generator: Poedit 1.8.7.1 Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2); ВызовыОчистить сравнениеСвернуть на один уровень вверхРазличиеОшибкаРаскрыть на один уровень внизФайл:строкаФайл:строка, где функция определенаФункция/МодульФункция/МодульЗагрузитьЗагрузить данные профилирования для сравненияЛокальное времяЛокальное время в функции (исключая подфункции)ВыводПожалуйста, установитеПроцесс не удалось запуститьПрофилироватьПрофайлерВывод профайлераРезультаты Профайлера (вывод profile/cProfile python'а) хранятся здесь:Результаты профилированияИдет профилирование, ждите...Скрипты PythonРезультатыЗапустить профайлерСохранитьСохранить результаты профилированияСохранить результаты профилированияВыбрать скрипт PythonВыберите скрипт для сравненияПоказать вывод программыИдет сортировка данных, ждите...СтопОстановить текущее профилированиеВремя в функции (включая подфункции)Общее времяОбщее число вызовов (включая рекурсию)рекурсиямодули профайлера Pythonspyder-3.2.6/spyder_profiler/locale/pt_BR/0000775000175000017500000000000013225025007021273 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_profiler/locale/pt_BR/LC_MESSAGES/0000775000175000017500000000000013225025007023060 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_profiler/locale/pt_BR/LC_MESSAGES/profiler.po0000664000175000017500000001176313224121062025247 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # Spyder's brazilian portuguese translation file # Valter Nazianzeno , 2014. # msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: 2017-12-14 15:40+-05\n" "PO-Revision-Date: 2017-01-17 14:51-0300\n" "Last-Translator: Valter Nazianzeno \n" "Language-Team: \n" "Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "X-Generator: Poedit 1.8.11\n" #: spyder_profiler/profiler.py:33 msgid "Results" msgstr "Resultados" #: spyder_profiler/profiler.py:34 msgid "" "Profiler plugin results (the output of python's profile/cProfile)\n" "are stored here:" msgstr "Os resultados do plugin Profiler são armazenados aqui: " #: spyder_profiler/profiler.py:75 msgid "Profiler" msgstr "Profiler" #: spyder_profiler/profiler.py:104 spyder_profiler/widgets/profilergui.py:82 msgid "Profile" msgstr "Profiler" #: spyder_profiler/widgets/profilergui.py:83 msgid "Run profiler" msgstr "Executar Profiler" #: spyder_profiler/widgets/profilergui.py:88 msgid "Stop" msgstr "Parar" #: spyder_profiler/widgets/profilergui.py:89 msgid "Stop current profiling" msgstr "Parar processo atual" #: spyder_profiler/widgets/profilergui.py:97 #: spyder_profiler/widgets/profilergui.py:222 msgid "Select Python script" msgstr "Selecionar script Python" #: spyder_profiler/widgets/profilergui.py:103 msgid "Output" msgstr "Saída" #: spyder_profiler/widgets/profilergui.py:105 msgid "Show program's output" msgstr "Mostrar saída do programa" #: spyder_profiler/widgets/profilergui.py:114 msgid "Collapse one level up" msgstr "Subir um nível" #: spyder_profiler/widgets/profilergui.py:119 msgid "Expand one level down" msgstr "Descer um nível" #: spyder_profiler/widgets/profilergui.py:122 msgid "Save data" msgstr "Salvar data" #: spyder_profiler/widgets/profilergui.py:125 msgid "Save profiling data" msgstr "Salvar dados" #: spyder_profiler/widgets/profilergui.py:127 msgid "Load data" msgstr "Carregar data" #: spyder_profiler/widgets/profilergui.py:130 msgid "Load profiling data for comparison" msgstr "Carregar dados para comparação" #: spyder_profiler/widgets/profilergui.py:132 msgid "Clear comparison" msgstr "Limpar comparação" #: spyder_profiler/widgets/profilergui.py:172 msgid "Please install" msgstr "Por favor instale" #: spyder_profiler/widgets/profilergui.py:173 msgid "the Python profiler modules" msgstr "Módulos do Python Profiler" #: spyder_profiler/widgets/profilergui.py:180 msgid "Save profiler result" msgstr "Salvar profiler result" #: spyder_profiler/widgets/profilergui.py:183 #: spyder_profiler/widgets/profilergui.py:190 msgid "Profiler result" msgstr "Resultado do Profiler" #: spyder_profiler/widgets/profilergui.py:189 msgid "Select script to compare" msgstr "Selecione um script para comparar" #: spyder_profiler/widgets/profilergui.py:223 msgid "Python scripts" msgstr "Scripts Python" #: spyder_profiler/widgets/profilergui.py:230 #: spyder_profiler/widgets/profilergui.py:235 msgid "Profiler output" msgstr "Saída do Profiler" #: spyder_profiler/widgets/profilergui.py:254 msgid "Profiling, please wait..." msgstr "Processando..." #: spyder_profiler/widgets/profilergui.py:298 #: spyder_profiler/widgets/profilergui.py:469 msgid "Error" msgstr "Erro" #: spyder_profiler/widgets/profilergui.py:299 msgid "Process failed to start" msgstr "O processo falhou ao iniciar" #: spyder_profiler/widgets/profilergui.py:346 msgid "Sorting data, please wait..." msgstr "Ordenando dados..." #: spyder_profiler/widgets/profilergui.py:421 msgid "Function/Module" msgstr "Função/Módulo" #: spyder_profiler/widgets/profilergui.py:421 msgid "Total Time" msgstr "Tempo Total" #: spyder_profiler/widgets/profilergui.py:421 #: spyder_profiler/widgets/profilergui.py:422 msgid "Diff" msgstr "Diff" #: spyder_profiler/widgets/profilergui.py:422 msgid "Calls" msgstr "Chamadas" #: spyder_profiler/widgets/profilergui.py:422 msgid "Local Time" msgstr "Hora Local" #: spyder_profiler/widgets/profilergui.py:423 msgid "File:line" msgstr "Arquivo/Linha" #: spyder_profiler/widgets/profilergui.py:470 msgid "Error when trying to load profiler results" msgstr "" #: spyder_profiler/widgets/profilergui.py:604 msgid "Function or module name" msgstr "Nome da função ou módulo" #: spyder_profiler/widgets/profilergui.py:608 msgid "Time in function (including sub-functions)" msgstr "Tempo decorrido na função (sub-funções incluídas)" #: spyder_profiler/widgets/profilergui.py:617 msgid "Local time in function (not in sub-functions)" msgstr "Tempo decorrido na função (excluindo sub-funções)" #: spyder_profiler/widgets/profilergui.py:627 msgid "Total number of calls (including recursion)" msgstr "Número total de chamadas (incluindo recursão)" #: spyder_profiler/widgets/profilergui.py:637 msgid "File:line where function is defined" msgstr "Arquivo/Linha onde a função está definida" #: spyder_profiler/widgets/profilergui.py:642 msgid "recursion" msgstr "recursão" spyder-3.2.6/spyder_profiler/locale/pt_BR/LC_MESSAGES/profiler.mo0000664000175000017500000000557113224121062025244 0ustar carloscarlos00000000000000)d; #- ="G j-uREUo~   ',*C n+y ['0DTY^ o,}    5 G N ` }   8      , 8 O \ !u     6  /# S ] %'  " $( )!&  #CallsClear comparisonCollapse one level upDiffErrorExpand one level downFile:lineFile:line where function is definedFunction or module nameFunction/ModuleLoad dataLoad profiling data for comparisonLocal TimeLocal time in function (not in sub-functions)OutputPlease installProcess failed to startProfileProfilerProfiler outputProfiler plugin results (the output of python's profile/cProfile) are stored here:Profiler resultProfiling, please wait...Python scriptsResultsRun profilerSave dataSave profiler resultSave profiling dataSelect Python scriptSelect script to compareShow program's outputSorting data, please wait...StopStop current profilingTime in function (including sub-functions)Total TimeTotal number of calls (including recursion)recursionthe Python profiler modulesProject-Id-Version: POT-Creation-Date: 2017-07-11 13:28+COT PO-Revision-Date: 2017-01-17 14:51-0300 Last-Translator: Valter Nazianzeno Language-Team: Language: pt_BR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generated-By: pygettext.py 1.5 X-Generator: Poedit 1.8.11 ChamadasLimpar comparaçãoSubir um nívelDiffErroDescer um nívelArquivo/LinhaArquivo/Linha onde a função está definidaNome da função ou móduloFunção/MóduloCarregar dataCarregar dados para comparaçãoHora LocalTempo decorrido na função (excluindo sub-funções)SaídaPor favor instaleO processo falhou ao iniciarProfilerProfilerSaída do ProfilerOs resultados do plugin Profiler são armazenados aqui: Resultado do ProfilerProcessando...Scripts PythonResultadosExecutar ProfilerSalvar dataSalvar profiler resultSalvar dadosSelecionar script PythonSelecione um script para compararMostrar saída do programaOrdenando dados...PararParar processo atualTempo decorrido na função (sub-funções incluídas)Tempo TotalNúmero total de chamadas (incluindo recursão)recursãoMódulos do Python Profilerspyder-3.2.6/spyder_profiler/locale/ja/0000775000175000017500000000000013225025007020657 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_profiler/locale/ja/LC_MESSAGES/0000775000175000017500000000000013225025007022444 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_profiler/locale/ja/LC_MESSAGES/profiler.po0000664000175000017500000001320613224121062024625 0ustar carloscarlos00000000000000# Japanese translations for Spyder package # Spyder-ide パッケージに対する英訳. # Copyright (C) 2016 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the Spyder package. # Ohnishi Seiki , 2016. # msgid "" msgstr "" "Project-Id-Version: Spyder\n" "POT-Creation-Date: 2017-12-14 15:40+-05\n" "PO-Revision-Date: 2017-12-18 19:08+0900\n" "Last-Translator: sohnishi \n" "Language-Team: Japanese\n" "Language: ja\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Poedit 1.8.11\n" #: spyder_profiler/profiler.py:33 msgid "Results" msgstr "結果" #: spyder_profiler/profiler.py:34 msgid "" "Profiler plugin results (the output of python's profile/cProfile)\n" "are stored here:" msgstr "" "プロファイラプラグインの結果(Python profile/cProfile出力)\n" "はこちらに保存されます:" #: spyder_profiler/profiler.py:75 msgid "Profiler" msgstr "プロファイラ" #: spyder_profiler/profiler.py:104 spyder_profiler/widgets/profilergui.py:82 msgid "Profile" msgstr "プロファイル" #: spyder_profiler/widgets/profilergui.py:83 msgid "Run profiler" msgstr "プロファイラの実行" #: spyder_profiler/widgets/profilergui.py:88 msgid "Stop" msgstr "停止" #: spyder_profiler/widgets/profilergui.py:89 msgid "Stop current profiling" msgstr "現在のプロファイリングを停止" #: spyder_profiler/widgets/profilergui.py:97 #: spyder_profiler/widgets/profilergui.py:222 msgid "Select Python script" msgstr "Pythonスクリプトを選択" #: spyder_profiler/widgets/profilergui.py:103 msgid "Output" msgstr "出力" #: spyder_profiler/widgets/profilergui.py:105 msgid "Show program's output" msgstr "プログラムの出力を表示" #: spyder_profiler/widgets/profilergui.py:114 msgid "Collapse one level up" msgstr "1つ上のレベルに折りたたむ" #: spyder_profiler/widgets/profilergui.py:119 msgid "Expand one level down" msgstr "1つ下のレベルに展開" #: spyder_profiler/widgets/profilergui.py:122 msgid "Save data" msgstr "データを保存" #: spyder_profiler/widgets/profilergui.py:125 msgid "Save profiling data" msgstr "プロファイリングデータを保存" #: spyder_profiler/widgets/profilergui.py:127 msgid "Load data" msgstr "データをロード" #: spyder_profiler/widgets/profilergui.py:130 msgid "Load profiling data for comparison" msgstr "比較のためのプロファイリングデータをロード" #: spyder_profiler/widgets/profilergui.py:132 msgid "Clear comparison" msgstr "比較をクリア" #: spyder_profiler/widgets/profilergui.py:172 msgid "Please install" msgstr "インストールしてください" #: spyder_profiler/widgets/profilergui.py:173 msgid "the Python profiler modules" msgstr "Pythonプロファイラモジュール" #: spyder_profiler/widgets/profilergui.py:180 msgid "Save profiler result" msgstr "プロファイラの結果を保存" #: spyder_profiler/widgets/profilergui.py:183 #: spyder_profiler/widgets/profilergui.py:190 msgid "Profiler result" msgstr "プロファイラ結果" #: spyder_profiler/widgets/profilergui.py:189 msgid "Select script to compare" msgstr "比較するスクリプトを選択" #: spyder_profiler/widgets/profilergui.py:223 msgid "Python scripts" msgstr "Pythonスクリプト" #: spyder_profiler/widgets/profilergui.py:230 #: spyder_profiler/widgets/profilergui.py:235 msgid "Profiler output" msgstr "プロファイラ出力" #: spyder_profiler/widgets/profilergui.py:254 msgid "Profiling, please wait..." msgstr "プロファイリング中、暫くお待ち下さい..." #: spyder_profiler/widgets/profilergui.py:298 #: spyder_profiler/widgets/profilergui.py:469 msgid "Error" msgstr "エラー" #: spyder_profiler/widgets/profilergui.py:299 msgid "Process failed to start" msgstr "プロセスの開始に失敗しました" #: spyder_profiler/widgets/profilergui.py:346 msgid "Sorting data, please wait..." msgstr "データをソートしています、お待ち下さい..." #: spyder_profiler/widgets/profilergui.py:421 msgid "Function/Module" msgstr "関数/モジュール" #: spyder_profiler/widgets/profilergui.py:421 msgid "Total Time" msgstr "合計時間" #: spyder_profiler/widgets/profilergui.py:421 #: spyder_profiler/widgets/profilergui.py:422 msgid "Diff" msgstr "Diff" #: spyder_profiler/widgets/profilergui.py:422 msgid "Calls" msgstr "コール" #: spyder_profiler/widgets/profilergui.py:422 msgid "Local Time" msgstr "ローカル時間" #: spyder_profiler/widgets/profilergui.py:423 msgid "File:line" msgstr "ファイル:行" #: spyder_profiler/widgets/profilergui.py:470 msgid "Error when trying to load profiler results" msgstr "プロファイル結果ロード中にエラー" #: spyder_profiler/widgets/profilergui.py:604 msgid "Function or module name" msgstr "関数あるいはモジュール名" #: spyder_profiler/widgets/profilergui.py:608 msgid "Time in function (including sub-functions)" msgstr "関数内での時間(サブ関数を含む)" #: spyder_profiler/widgets/profilergui.py:617 msgid "Local time in function (not in sub-functions)" msgstr "関数内でのローカル時間(サブ関数を含まない)" #: spyder_profiler/widgets/profilergui.py:627 msgid "Total number of calls (including recursion)" msgstr "合計コール回数(再帰呼出しを含む)" #: spyder_profiler/widgets/profilergui.py:637 msgid "File:line where function is defined" msgstr "関数の定義されている ファイル:行" #: spyder_profiler/widgets/profilergui.py:642 msgid "recursion" msgstr "再帰" spyder-3.2.6/spyder_profiler/locale/ja/LC_MESSAGES/profiler.mo0000664000175000017500000000666213224121062024632 0ustar carloscarlos00000000000000*l;*  "#,Ph x" - R-  /Ebg*~ +  % 0 * 0= $n   ?  > R $Y *~    l U 9n     $ * D $c ! <  * , F /S  ' &(  #%)!*"'  $ CallsClear comparisonCollapse one level upDiffErrorError when trying to load profiler resultsExpand one level downFile:lineFile:line where function is definedFunction or module nameFunction/ModuleLoad dataLoad profiling data for comparisonLocal TimeLocal time in function (not in sub-functions)OutputPlease installProcess failed to startProfileProfilerProfiler outputProfiler plugin results (the output of python's profile/cProfile) are stored here:Profiler resultProfiling, please wait...Python scriptsResultsRun profilerSave dataSave profiler resultSave profiling dataSelect Python scriptSelect script to compareShow program's outputSorting data, please wait...StopStop current profilingTime in function (including sub-functions)Total TimeTotal number of calls (including recursion)recursionthe Python profiler modulesProject-Id-Version: Spyder POT-Creation-Date: 2017-12-14 15:40+-05 PO-Revision-Date: 2017-12-18 19:08+0900 Last-Translator: sohnishi Language-Team: Japanese Language: ja MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generated-By: pygettext.py 1.5 Plural-Forms: nplurals=1; plural=0; X-Generator: Poedit 1.8.11 コール比較をクリア1つ上のレベルに折りたたむDiffエラープロファイル結果ロード中にエラー1つ下のレベルに展開ファイル:行関数の定義されている ファイル:行関数あるいはモジュール名関数/モジュールデータをロード比較のためのプロファイリングデータをロードローカル時間関数内でのローカル時間(サブ関数を含まない)出力インストールしてくださいプロセスの開始に失敗しましたプロファイルプロファイラプロファイラ出力プロファイラプラグインの結果(Python profile/cProfile出力) はこちらに保存されます:プロファイラ結果プロファイリング中、暫くお待ち下さい...Pythonスクリプト結果プロファイラの実行データを保存プロファイラの結果を保存プロファイリングデータを保存Pythonスクリプトを選択比較するスクリプトを選択プログラムの出力を表示データをソートしています、お待ち下さい...停止現在のプロファイリングを停止関数内での時間(サブ関数を含む)合計時間合計コール回数(再帰呼出しを含む)再帰Pythonプロファイラモジュールspyder-3.2.6/spyder_profiler/locale/es/0000775000175000017500000000000013225025007020674 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_profiler/locale/es/LC_MESSAGES/0000775000175000017500000000000013225025007022461 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_profiler/locale/es/LC_MESSAGES/profiler.po0000664000175000017500000001065213224121062024644 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # Spyder Profiler's spanish translation file # Copyright (C) 2011 Spyder Development team # msgid "" msgstr "" "Project-Id-Version: 2.1\n" "POT-Creation-Date: 2017-12-14 15:40+-05\n" "PO-Revision-Date: 2012-06-25 21:59-0500\n" "Last-Translator: Carlos Cordoba \n" "Language-Team: Python\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "X-Poedit-Language: Spanish\n" "X-Poedit-SourceCharset: utf-8\n" "X-Poedit-Basepath: ../../../../\n" #: spyder_profiler/profiler.py:33 msgid "Results" msgstr "Resultados" #: spyder_profiler/profiler.py:34 msgid "" "Profiler plugin results (the output of python's profile/cProfile)\n" "are stored here:" msgstr "" "Los resultados del perfilador (es decir la salida de profile o cProfile)\n" "son guardados aquí:" #: spyder_profiler/profiler.py:75 msgid "Profiler" msgstr "Perfilador (Profiler)" #: spyder_profiler/profiler.py:104 spyder_profiler/widgets/profilergui.py:82 msgid "Profile" msgstr "Perfilar (Profile)" #: spyder_profiler/widgets/profilergui.py:83 msgid "Run profiler" msgstr "" #: spyder_profiler/widgets/profilergui.py:88 msgid "Stop" msgstr "" #: spyder_profiler/widgets/profilergui.py:89 msgid "Stop current profiling" msgstr "" #: spyder_profiler/widgets/profilergui.py:97 #: spyder_profiler/widgets/profilergui.py:222 msgid "Select Python script" msgstr "" #: spyder_profiler/widgets/profilergui.py:103 msgid "Output" msgstr "" #: spyder_profiler/widgets/profilergui.py:105 msgid "Show program's output" msgstr "" #: spyder_profiler/widgets/profilergui.py:114 msgid "Collapse one level up" msgstr "" #: spyder_profiler/widgets/profilergui.py:119 msgid "Expand one level down" msgstr "" #: spyder_profiler/widgets/profilergui.py:122 msgid "Save data" msgstr "" #: spyder_profiler/widgets/profilergui.py:125 msgid "Save profiling data" msgstr "" #: spyder_profiler/widgets/profilergui.py:127 msgid "Load data" msgstr "" #: spyder_profiler/widgets/profilergui.py:130 msgid "Load profiling data for comparison" msgstr "" #: spyder_profiler/widgets/profilergui.py:132 msgid "Clear comparison" msgstr "" #: spyder_profiler/widgets/profilergui.py:172 msgid "Please install" msgstr "" #: spyder_profiler/widgets/profilergui.py:173 msgid "the Python profiler modules" msgstr "" #: spyder_profiler/widgets/profilergui.py:180 msgid "Save profiler result" msgstr "" #: spyder_profiler/widgets/profilergui.py:183 #: spyder_profiler/widgets/profilergui.py:190 #, fuzzy msgid "Profiler result" msgstr "Perfilador (Profiler)" #: spyder_profiler/widgets/profilergui.py:189 msgid "Select script to compare" msgstr "" #: spyder_profiler/widgets/profilergui.py:223 msgid "Python scripts" msgstr "" #: spyder_profiler/widgets/profilergui.py:230 #: spyder_profiler/widgets/profilergui.py:235 msgid "Profiler output" msgstr "" #: spyder_profiler/widgets/profilergui.py:254 msgid "Profiling, please wait..." msgstr "" #: spyder_profiler/widgets/profilergui.py:298 #: spyder_profiler/widgets/profilergui.py:469 msgid "Error" msgstr "" #: spyder_profiler/widgets/profilergui.py:299 msgid "Process failed to start" msgstr "" #: spyder_profiler/widgets/profilergui.py:346 msgid "Sorting data, please wait..." msgstr "" #: spyder_profiler/widgets/profilergui.py:421 msgid "Function/Module" msgstr "" #: spyder_profiler/widgets/profilergui.py:421 msgid "Total Time" msgstr "" #: spyder_profiler/widgets/profilergui.py:421 #: spyder_profiler/widgets/profilergui.py:422 msgid "Diff" msgstr "" #: spyder_profiler/widgets/profilergui.py:422 msgid "Calls" msgstr "" #: spyder_profiler/widgets/profilergui.py:422 msgid "Local Time" msgstr "" #: spyder_profiler/widgets/profilergui.py:423 msgid "File:line" msgstr "" #: spyder_profiler/widgets/profilergui.py:470 msgid "Error when trying to load profiler results" msgstr "" #: spyder_profiler/widgets/profilergui.py:604 msgid "Function or module name" msgstr "" #: spyder_profiler/widgets/profilergui.py:608 msgid "Time in function (including sub-functions)" msgstr "" #: spyder_profiler/widgets/profilergui.py:617 msgid "Local time in function (not in sub-functions)" msgstr "" #: spyder_profiler/widgets/profilergui.py:627 msgid "Total number of calls (including recursion)" msgstr "" #: spyder_profiler/widgets/profilergui.py:637 msgid "File:line where function is defined" msgstr "" #: spyder_profiler/widgets/profilergui.py:642 msgid "recursion" msgstr "" spyder-3.2.6/spyder_profiler/locale/es/LC_MESSAGES/profiler.mo0000664000175000017500000000143213224121062024635 0ustar carloscarlos00000000000000DlR] ProfileProfilerProfiler plugin results (the output of python's profile/cProfile) are stored here:ResultsProject-Id-Version: 2.1 POT-Creation-Date: 2017-07-11 13:28+COT PO-Revision-Date: 2012-06-25 21:59-0500 Last-Translator: Carlos Cordoba Language-Team: Python Language: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generated-By: pygettext.py 1.5 X-Poedit-Language: Spanish X-Poedit-SourceCharset: utf-8 X-Poedit-Basepath: ../../../../ Perfilar (Profile)Perfilador (Profiler)Los resultados del perfilador (es decir la salida de profile o cProfile) son guardados aquí:Resultadosspyder-3.2.6/spyder_profiler/locale/fr/0000775000175000017500000000000013225025007020674 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_profiler/locale/fr/LC_MESSAGES/0000775000175000017500000000000013225025007022461 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_profiler/locale/fr/LC_MESSAGES/profiler.po0000664000175000017500000001153613224121062024646 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # Spyder Profiler's french translation file # Copyright (C) 2011 Pierre Raybaut # msgid "" msgstr "" "Project-Id-Version: 2.1\n" "POT-Creation-Date: 2017-12-14 15:40+-05\n" "PO-Revision-Date: 2011-04-11 21:41+2\n" "Last-Translator: Pierre Raybaut\n" "Language-Team: Python\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: utf-8\n" "Generated-By: pygettext.py 1.5\n" #: spyder_profiler/profiler.py:33 msgid "Results" msgstr "Résultats" #: spyder_profiler/profiler.py:34 msgid "" "Profiler plugin results (the output of python's profile/cProfile)\n" "are stored here:" msgstr "Les résultats du profileur Python sont stockés ici :" #: spyder_profiler/profiler.py:75 msgid "Profiler" msgstr "Profileur" #: spyder_profiler/profiler.py:104 spyder_profiler/widgets/profilergui.py:82 msgid "Profile" msgstr "Profiler" #: spyder_profiler/widgets/profilergui.py:83 msgid "Run profiler" msgstr "Exécuter le profileur" #: spyder_profiler/widgets/profilergui.py:88 msgid "Stop" msgstr "Arrêter" #: spyder_profiler/widgets/profilergui.py:89 msgid "Stop current profiling" msgstr "Arrêter le processus en cours" #: spyder_profiler/widgets/profilergui.py:97 #: spyder_profiler/widgets/profilergui.py:222 msgid "Select Python script" msgstr "Sélectionner un script Python" #: spyder_profiler/widgets/profilergui.py:103 msgid "Output" msgstr "Sortie" #: spyder_profiler/widgets/profilergui.py:105 msgid "Show program's output" msgstr "Afficher la sortie du programme" #: spyder_profiler/widgets/profilergui.py:114 msgid "Collapse one level up" msgstr "Replier l'arbre d'un niveau" #: spyder_profiler/widgets/profilergui.py:119 msgid "Expand one level down" msgstr "Déplier l'arbre d'un niveau" #: spyder_profiler/widgets/profilergui.py:122 msgid "Save data" msgstr "" #: spyder_profiler/widgets/profilergui.py:125 msgid "Save profiling data" msgstr "" #: spyder_profiler/widgets/profilergui.py:127 msgid "Load data" msgstr "" #: spyder_profiler/widgets/profilergui.py:130 msgid "Load profiling data for comparison" msgstr "" #: spyder_profiler/widgets/profilergui.py:132 msgid "Clear comparison" msgstr "" #: spyder_profiler/widgets/profilergui.py:172 msgid "Please install" msgstr "Veuillez installer" #: spyder_profiler/widgets/profilergui.py:173 msgid "the Python profiler modules" msgstr "les profileurs Python" #: spyder_profiler/widgets/profilergui.py:180 msgid "Save profiler result" msgstr "" #: spyder_profiler/widgets/profilergui.py:183 #: spyder_profiler/widgets/profilergui.py:190 #, fuzzy msgid "Profiler result" msgstr "Sortie du profileur" #: spyder_profiler/widgets/profilergui.py:189 msgid "Select script to compare" msgstr "" #: spyder_profiler/widgets/profilergui.py:223 msgid "Python scripts" msgstr "Scripts Python" #: spyder_profiler/widgets/profilergui.py:230 #: spyder_profiler/widgets/profilergui.py:235 msgid "Profiler output" msgstr "Sortie du profileur" #: spyder_profiler/widgets/profilergui.py:254 msgid "Profiling, please wait..." msgstr "Profilage en cours..." #: spyder_profiler/widgets/profilergui.py:298 #: spyder_profiler/widgets/profilergui.py:469 msgid "Error" msgstr "Erreur" #: spyder_profiler/widgets/profilergui.py:299 msgid "Process failed to start" msgstr "Le processus n'a pas pu démarrer" #: spyder_profiler/widgets/profilergui.py:346 msgid "Sorting data, please wait..." msgstr "Classement des résultats en cours..." #: spyder_profiler/widgets/profilergui.py:421 msgid "Function/Module" msgstr "Fonction/Module" #: spyder_profiler/widgets/profilergui.py:421 msgid "Total Time" msgstr "Durée totale" #: spyder_profiler/widgets/profilergui.py:421 #: spyder_profiler/widgets/profilergui.py:422 msgid "Diff" msgstr "" #: spyder_profiler/widgets/profilergui.py:422 msgid "Calls" msgstr "Appels" #: spyder_profiler/widgets/profilergui.py:422 msgid "Local Time" msgstr "Durée locale" #: spyder_profiler/widgets/profilergui.py:423 msgid "File:line" msgstr "Fichier:ligne" #: spyder_profiler/widgets/profilergui.py:470 msgid "Error when trying to load profiler results" msgstr "" #: spyder_profiler/widgets/profilergui.py:604 #, fuzzy msgid "Function or module name" msgstr "Fonction/Module" #: spyder_profiler/widgets/profilergui.py:608 msgid "Time in function (including sub-functions)" msgstr "Temps écoulé dans la fonction (sous-fonctions comprises)" #: spyder_profiler/widgets/profilergui.py:617 msgid "Local time in function (not in sub-functions)" msgstr "Temps écoulé dans la fonction (hors sous-fonctions)" #: spyder_profiler/widgets/profilergui.py:627 msgid "Total number of calls (including recursion)" msgstr "Nombre total d'appels (récursion comprise)" #: spyder_profiler/widgets/profilergui.py:637 msgid "File:line where function is defined" msgstr "Fichier:ligne de définition de la fonction" #: spyder_profiler/widgets/profilergui.py:642 msgid "recursion" msgstr "récursion" spyder-3.2.6/spyder_profiler/locale/fr/LC_MESSAGES/profiler.mo0000664000175000017500000000444613224121062024645 0ustar carloscarlos00000000000000)  # '-2`gvR+ 3@Uk* +  ,MTpw + 5")!<^ gq6 "%Bhq: +        CallsCollapse one level upErrorExpand one level downFile:lineFile:line where function is definedFunction/ModuleLocal TimeLocal time in function (not in sub-functions)OutputPlease installProcess failed to startProfileProfilerProfiler outputProfiler plugin results (the output of python's profile/cProfile) are stored here:Profiling, please wait...Python scriptsResultsRun profilerSelect Python scriptShow program's outputSorting data, please wait...StopStop current profilingTime in function (including sub-functions)Total TimeTotal number of calls (including recursion)recursionthe Python profiler modulesProject-Id-Version: 2.1 POT-Creation-Date: 2017-07-11 13:28+COT PO-Revision-Date: 2011-04-11 21:41+2 Last-Translator: Pierre Raybaut Language-Team: Python Language: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: utf-8 Generated-By: pygettext.py 1.5 AppelsReplier l'arbre d'un niveauErreurDéplier l'arbre d'un niveauFichier:ligneFichier:ligne de définition de la fonctionFonction/ModuleDurée localeTemps écoulé dans la fonction (hors sous-fonctions)SortieVeuillez installerLe processus n'a pas pu démarrerProfilerProfileurSortie du profileurLes résultats du profileur Python sont stockés ici :Profilage en cours...Scripts PythonRésultatsExécuter le profileurSélectionner un script PythonAfficher la sortie du programmeClassement des résultats en cours...ArrêterArrêter le processus en coursTemps écoulé dans la fonction (sous-fonctions comprises)Durée totaleNombre total d'appels (récursion comprise)récursionles profileurs Pythonspyder-3.2.6/spyder_profiler/locale/profiler.pot0000664000175000017500000001021113224121062022623 0ustar carloscarlos00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR ORGANIZATION # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2017-12-14 15:40+-05\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: ENCODING\n" "Generated-By: pygettext.py 1.5\n" #: spyder_profiler/profiler.py:33 msgid "Results" msgstr "" #: spyder_profiler/profiler.py:34 msgid "" "Profiler plugin results (the output of python's profile/cProfile)\n" "are stored here:" msgstr "" #: spyder_profiler/profiler.py:75 msgid "Profiler" msgstr "" #: spyder_profiler/profiler.py:104 spyder_profiler/widgets/profilergui.py:82 msgid "Profile" msgstr "" #: spyder_profiler/widgets/profilergui.py:83 msgid "Run profiler" msgstr "" #: spyder_profiler/widgets/profilergui.py:88 msgid "Stop" msgstr "" #: spyder_profiler/widgets/profilergui.py:89 msgid "Stop current profiling" msgstr "" #: spyder_profiler/widgets/profilergui.py:97 #: spyder_profiler/widgets/profilergui.py:222 msgid "Select Python script" msgstr "" #: spyder_profiler/widgets/profilergui.py:103 msgid "Output" msgstr "" #: spyder_profiler/widgets/profilergui.py:105 msgid "Show program's output" msgstr "" #: spyder_profiler/widgets/profilergui.py:114 msgid "Collapse one level up" msgstr "" #: spyder_profiler/widgets/profilergui.py:119 msgid "Expand one level down" msgstr "" #: spyder_profiler/widgets/profilergui.py:122 msgid "Save data" msgstr "" #: spyder_profiler/widgets/profilergui.py:125 msgid "Save profiling data" msgstr "" #: spyder_profiler/widgets/profilergui.py:127 msgid "Load data" msgstr "" #: spyder_profiler/widgets/profilergui.py:130 msgid "Load profiling data for comparison" msgstr "" #: spyder_profiler/widgets/profilergui.py:132 msgid "Clear comparison" msgstr "" #: spyder_profiler/widgets/profilergui.py:172 msgid "Please install" msgstr "" #: spyder_profiler/widgets/profilergui.py:173 msgid "the Python profiler modules" msgstr "" #: spyder_profiler/widgets/profilergui.py:180 msgid "Save profiler result" msgstr "" #: spyder_profiler/widgets/profilergui.py:183 #: spyder_profiler/widgets/profilergui.py:190 msgid "Profiler result" msgstr "" #: spyder_profiler/widgets/profilergui.py:189 msgid "Select script to compare" msgstr "" #: spyder_profiler/widgets/profilergui.py:223 msgid "Python scripts" msgstr "" #: spyder_profiler/widgets/profilergui.py:230 #: spyder_profiler/widgets/profilergui.py:235 msgid "Profiler output" msgstr "" #: spyder_profiler/widgets/profilergui.py:254 msgid "Profiling, please wait..." msgstr "" #: spyder_profiler/widgets/profilergui.py:298 #: spyder_profiler/widgets/profilergui.py:469 msgid "Error" msgstr "" #: spyder_profiler/widgets/profilergui.py:299 msgid "Process failed to start" msgstr "" #: spyder_profiler/widgets/profilergui.py:346 msgid "Sorting data, please wait..." msgstr "" #: spyder_profiler/widgets/profilergui.py:421 msgid "Function/Module" msgstr "" #: spyder_profiler/widgets/profilergui.py:421 msgid "Total Time" msgstr "" #: spyder_profiler/widgets/profilergui.py:421 #: spyder_profiler/widgets/profilergui.py:422 msgid "Diff" msgstr "" #: spyder_profiler/widgets/profilergui.py:422 msgid "Calls" msgstr "" #: spyder_profiler/widgets/profilergui.py:422 msgid "Local Time" msgstr "" #: spyder_profiler/widgets/profilergui.py:423 msgid "File:line" msgstr "" #: spyder_profiler/widgets/profilergui.py:470 msgid "Error when trying to load profiler results" msgstr "" #: spyder_profiler/widgets/profilergui.py:604 msgid "Function or module name" msgstr "" #: spyder_profiler/widgets/profilergui.py:608 msgid "Time in function (including sub-functions)" msgstr "" #: spyder_profiler/widgets/profilergui.py:617 msgid "Local time in function (not in sub-functions)" msgstr "" #: spyder_profiler/widgets/profilergui.py:627 msgid "Total number of calls (including recursion)" msgstr "" #: spyder_profiler/widgets/profilergui.py:637 msgid "File:line where function is defined" msgstr "" #: spyder_profiler/widgets/profilergui.py:642 msgid "recursion" msgstr "" spyder-3.2.6/spyder_profiler/profiler.py0000664000175000017500000001251413224740762021240 0ustar carloscarlos00000000000000# -*- coding:utf-8 -*- # # Copyright © Spyder Project Contributors # based on p_pylint.py by Pierre Raybaut # # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Profiler Plugin.""" # Standard library imports import os.path as osp # Third party imports from qtpy.QtCore import Qt, Signal from qtpy.QtWidgets import QGroupBox, QLabel, QVBoxLayout # Local imports from spyder.config.base import get_translation from spyder.plugins import SpyderPluginMixin from spyder.plugins.configdialog import PluginConfigPage from spyder.plugins.runconfig import get_run_configuration from spyder.utils import icon_manager as ima from spyder.utils.qthelpers import create_action from .widgets.profilergui import (ProfilerWidget, is_profiler_installed) _ = get_translation("profiler", "spyder_profiler") class ProfilerConfigPage(PluginConfigPage): def setup_page(self): results_group = QGroupBox(_("Results")) results_label1 = QLabel(_("Profiler plugin results " "(the output of python's profile/cProfile)\n" "are stored here:")) results_label1.setWordWrap(True) # Warning: do not try to regroup the following QLabel contents with # widgets above -- this string was isolated here in a single QLabel # on purpose: to fix Issue 863 results_label2 = QLabel(ProfilerWidget.DATAPATH) results_label2.setTextInteractionFlags(Qt.TextSelectableByMouse) results_label2.setWordWrap(True) results_layout = QVBoxLayout() results_layout.addWidget(results_label1) results_layout.addWidget(results_label2) results_group.setLayout(results_layout) vlayout = QVBoxLayout() vlayout.addWidget(results_group) vlayout.addStretch(1) self.setLayout(vlayout) class Profiler(ProfilerWidget, SpyderPluginMixin): """Profiler (after python's profile and pstats)""" CONF_SECTION = 'profiler' CONFIGWIDGET_CLASS = ProfilerConfigPage edit_goto = Signal(str, int, str) def __init__(self, parent=None): ProfilerWidget.__init__(self, parent=parent, max_entries=self.get_option('max_entries', 50)) SpyderPluginMixin.__init__(self, parent) # Initialize plugin self.initialize_plugin() #------ SpyderPluginWidget API --------------------------------------------- def get_plugin_title(self): """Return widget title""" return _("Profiler") def get_plugin_icon(self): """Return widget icon""" path = osp.join(self.PLUGIN_PATH, self.IMG_PATH) return ima.icon('profiler', icon_path=path) def get_focus_widget(self): """ Return the widget to give focus to when this plugin's dockwidget is raised on top-level """ return self.datatree def get_plugin_actions(self): """Return a list of actions related to plugin""" return [] def on_first_registration(self): """Action to be performed on first plugin registration""" self.main.tabify_plugins(self.main.help, self) self.dockwidget.hide() def register_plugin(self): """Register plugin in Spyder's main window""" self.edit_goto.connect(self.main.editor.load) self.redirect_stdio.connect(self.main.redirect_internalshell_stdio) self.main.add_dockwidget(self) profiler_act = create_action(self, _("Profile"), icon=self.get_plugin_icon(), triggered=self.run_profiler) profiler_act.setEnabled(is_profiler_installed()) self.register_shortcut(profiler_act, context="Profiler", name="Run profiler") self.main.run_menu_actions += [profiler_act] self.main.editor.pythonfile_dependent_actions += [profiler_act] def refresh_plugin(self): """Refresh profiler widget""" #self.remove_obsolete_items() # FIXME: not implemented yet def closing_plugin(self, cancelable=False): """Perform actions before parent main window is closed""" return True def apply_plugin_settings(self, options): """Apply configuration file's plugin settings""" # The history depth option will be applied at # next Spyder startup, which is soon enough pass #------ Public API --------------------------------------------------------- def run_profiler(self): """Run profiler""" if self.main.editor.save(): self.analyze(self.main.editor.get_current_filename()) def analyze(self, filename): """Reimplement analyze method""" if self.dockwidget and not self.ismaximized: self.dockwidget.setVisible(True) self.dockwidget.setFocus() self.dockwidget.raise_() pythonpath = self.main.get_spyder_pythonpath() runconf = get_run_configuration(filename) wdir, args = None, [] if runconf is not None: if runconf.wdir_enabled: wdir = runconf.wdir if runconf.args_enabled: args = runconf.args ProfilerWidget.analyze(self, filename, wdir=wdir, args=args, pythonpath=pythonpath) spyder-3.2.6/spyder_profiler/images/0000775000175000017500000000000013225025007020273 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_profiler/images/profiler.png0000664000175000017500000000265613003520703022631 0ustar carloscarlos00000000000000PNG  IHDRw= cHRMz&u0`:pQ<bKGD7IDATHSSWqNL:LiY%X@(*-/ {@ H]Bt[ز (۷f ;{s߲eK4[1HďKٿͱqNOfxadOCu)B:)q AWXxvr!fV܂ζv\4='1?7<ܸ 4,Q֢#rm;٬R7mƬӉۓ7QNHDPF )VY4=|bh9H˛ZNL GJcEJ)IP]^lBFCG$eˉ' O Jqk:r2Qq22D|3NuX:(bkbƆm(ܣQB>h% sa8JIEF>C&ب xboA%%XZqtBJمbm ǃil-\%*-Tj 6`>|EBU2 :U-_,pv2aa4$%U%ԇ_UU )&; VYI)跲(ř(S2hQt M{^ZPgd2KMGrF&ȣv:Z%C %O(Dz|*t\"X YϞjU! $(j)6ͱXuʁtﮞy58ϊq](/v諐4 ?O Z{HOjT- rXz},; z6{u=66-þ&fan8 /?~aS (َ 0) self.kill_if_running() filename = to_text_string(self.filecombo.currentText()) if not filename: return self.datelabel.setText(_('Sorting data, please wait...')) QApplication.processEvents() self.datatree.load_data(self.DATAPATH) self.datatree.show_tree() text_style = "%s " date_text = text_style % time.strftime("%d %b %Y %H:%M", time.localtime()) self.datelabel.setText(date_text) def gettime_s(text): """Parse text and returns a time in seconds The text is of the format 0h : 0.min:0.0s:0 ms:0us:0 ns. Spaces are not taken into account and any of the specifiers can be ignored""" pattern = '([+-]?\d+\.?\d*) ?([munsecinh]+)' matches = re.findall(pattern, text) if len(matches) == 0: return None time = 0. for res in matches: tmp = float(res[0]) if res[1] == 'ns': tmp *= 1e-9 elif res[1] == 'us': tmp *= 1e-6 elif res[1] == 'ms': tmp *= 1e-3 elif res[1] == 'min': tmp *= 60 elif res[1] == 'h': tmp *= 3600 time += tmp return time class TreeWidgetItem( QTreeWidgetItem ): def __init__(self, parent=None): QTreeWidgetItem.__init__(self, parent) def __lt__(self, otherItem): column = self.treeWidget().sortColumn() try: if column == 1 or column == 3: #TODO: Hardcoded Column t0 = gettime_s(self.text(column)) t1 = gettime_s(otherItem.text(column)) if t0 is not None and t1 is not None: return t0 > t1 return float( self.text(column) ) > float( otherItem.text(column) ) except ValueError: return self.text(column) > otherItem.text(column) class ProfilerDataTree(QTreeWidget): """ Convenience tree widget (with built-in model) to store and view profiler data. The quantities calculated by the profiler are as follows (from profile.Profile): [0] = The number of times this function was called, not counting direct or indirect recursion, [1] = Number of times this function appears on the stack, minus one [2] = Total time spent internal to this function [3] = Cumulative time that this function was present on the stack. In non-recursive functions, this is the total execution time from start to finish of each invocation of a function, including time spent in all subfunctions. [4] = A dictionary indicating for each function name, the number of times it was called by us. """ SEP = r"<[=]>" # separator between filename and linenumber # (must be improbable as a filename to avoid splitting the filename itself) def __init__(self, parent=None): QTreeWidget.__init__(self, parent) self.header_list = [_('Function/Module'), _('Total Time'), _('Diff'), _('Local Time'), _('Diff'), _('Calls'), _('Diff'), _('File:line')] self.icon_list = {'module': ima.icon('python'), 'function': ima.icon('function'), 'builtin': ima.icon('python_t'), 'constructor': ima.icon('class')} self.profdata = None # To be filled by self.load_data() self.stats = None # To be filled by self.load_data() self.item_depth = None self.item_list = None self.items_to_be_shown = None self.current_view_depth = None self.compare_file = None self.setColumnCount(len(self.header_list)) self.setHeaderLabels(self.header_list) self.initialize_view() self.itemActivated.connect(self.item_activated) self.itemExpanded.connect(self.item_expanded) def set_item_data(self, item, filename, line_number): """Set tree item user data: filename (string) and line_number (int)""" set_item_user_text(item, '%s%s%d' % (filename, self.SEP, line_number)) def get_item_data(self, item): """Get tree item user data: (filename, line_number)""" filename, line_number_str = get_item_user_text(item).split(self.SEP) return filename, int(line_number_str) def initialize_view(self): """Clean the tree and view parameters""" self.clear() self.item_depth = 0 # To be use for collapsing/expanding one level self.item_list = [] # To be use for collapsing/expanding one level self.items_to_be_shown = {} self.current_view_depth = 0 def load_data(self, profdatafile): """Load profiler data saved by profile/cProfile module""" import pstats stats_indi = [pstats.Stats(profdatafile),] self.profdata = stats_indi[0] if self.compare_file is not None: try: stats_indi.append(pstats.Stats(self.compare_file)) except IOError as e: QMessageBox.critical( self, _("Error"), _("Error when trying to load profiler results")) debug_print("Error when calling pstats, {}".format(e)) self.compare_file = None map(lambda x: x.calc_callees(), stats_indi) self.profdata.calc_callees() self.stats1 = stats_indi self.stats = stats_indi[0].stats def compare(self,filename): self.hide_diff_cols(False) self.compare_file = filename def hide_diff_cols(self, hide): for i in (2,4,6): self.setColumnHidden(i, hide) def save_data(self, filename): """""" self.stats1[0].dump_stats(filename) def find_root(self): """Find a function without a caller""" self.profdata.sort_stats("cumulative") for func in self.profdata.fcn_list: if ('~', 0) != func[0:2] and not func[2].startswith( ''): # This skips the profiler function at the top of the list # it does only occur in Python 3 return func def find_callees(self, parent): """Find all functions called by (parent) function.""" # FIXME: This implementation is very inneficient, because it # traverses all the data to find children nodes (callees) return self.profdata.all_callees[parent] def show_tree(self): """Populate the tree with profiler data and display it.""" self.initialize_view() # Clear before re-populating self.setItemsExpandable(True) self.setSortingEnabled(False) rootkey = self.find_root() # This root contains profiler overhead if rootkey: self.populate_tree(self, self.find_callees(rootkey)) self.resizeColumnToContents(0) self.setSortingEnabled(True) self.sortItems(1, Qt.AscendingOrder) # FIXME: hardcoded index self.change_view(1) def function_info(self, functionKey): """Returns processed information about the function's name and file.""" node_type = 'function' filename, line_number, function_name = functionKey if function_name == '': modulePath, moduleName = osp.split(filename) node_type = 'module' if moduleName == '__init__.py': modulePath, moduleName = osp.split(modulePath) function_name = '<' + moduleName + '>' if not filename or filename == '~': file_and_line = '(built-in)' node_type = 'builtin' else: if function_name == '__init__': node_type = 'constructor' file_and_line = '%s : %d' % (filename, line_number) return filename, line_number, function_name, file_and_line, node_type @staticmethod def format_measure(measure): """Get format and units for data coming from profiler task.""" # Convert to a positive value. measure = abs(measure) # For number of calls if isinstance(measure, int): return to_text_string(measure) # For time measurements if 1.e-9 < measure <= 1.e-6: measure = u"{0:.2f} ns".format(measure / 1.e-9) elif 1.e-6 < measure <= 1.e-3: measure = u"{0:.2f} us".format(measure / 1.e-6) elif 1.e-3 < measure <= 1: measure = u"{0:.2f} ms".format(measure / 1.e-3) elif 1 < measure <= 60: measure = u"{0:.2f} sec".format(measure) elif 60 < measure <= 3600: m, s = divmod(measure, 3600) if s > 60: m, s = divmod(measure, 60) s = to_text_string(s).split(".")[-1] measure = u"{0:.0f}.{1:.2s} min".format(m, s) else: h, m = divmod(measure, 3600) if m > 60: m /= 60 measure = u"{0:.0f}h:{1:.0f}min".format(h, m) return measure def color_string(self, x): """Return a string formatted delta for the values in x. Args: x: 2-item list of integers (representing number of calls) or 2-item list of floats (representing seconds of runtime). Returns: A list with [formatted x[0], [color, formatted delta]], where color reflects whether x[1] is lower, greater, or the same as x[0]. """ diff_str = "" color = "black" if len(x) == 2 and self.compare_file is not None: difference = x[0] - x[1] if difference: color, sign = ('green', '-') if difference < 0 else ('red', '+') diff_str = '{}{}'.format(sign, self.format_measure(difference)) return [self.format_measure(x[0]), [diff_str, color]] def format_output(self, child_key): """ Formats the data. self.stats1 contains a list of one or two pstat.Stats() instances, with the first being the current run and the second, the saved run, if it exists. Each Stats instance is a dictionary mapping a function to 5 data points - cumulative calls, number of calls, total time, cumulative time, and callers. format_output() converts the number of calls, total time, and cumulative time to a string format for the child_key parameter. """ data = [x.stats.get(child_key, [0, 0, 0, 0, {}]) for x in self.stats1] return (map(self.color_string, islice(zip(*data), 1, 4))) def populate_tree(self, parentItem, children_list): """Recursive method to create each item (and associated data) in the tree.""" for child_key in children_list: self.item_depth += 1 (filename, line_number, function_name, file_and_line, node_type ) = self.function_info(child_key) ((total_calls, total_calls_dif), (loc_time, loc_time_dif), (cum_time, cum_time_dif)) = self.format_output(child_key) child_item = TreeWidgetItem(parentItem) self.item_list.append(child_item) self.set_item_data(child_item, filename, line_number) # FIXME: indexes to data should be defined by a dictionary on init child_item.setToolTip(0, _('Function or module name')) child_item.setData(0, Qt.DisplayRole, function_name) child_item.setIcon(0, self.icon_list[node_type]) child_item.setToolTip(1, _('Time in function '\ '(including sub-functions)')) child_item.setData(1, Qt.DisplayRole, cum_time) child_item.setTextAlignment(1, Qt.AlignRight) child_item.setData(2, Qt.DisplayRole, cum_time_dif[0]) child_item.setForeground(2, QColor(cum_time_dif[1])) child_item.setTextAlignment(2, Qt.AlignLeft) child_item.setToolTip(3, _('Local time in function '\ '(not in sub-functions)')) child_item.setData(3, Qt.DisplayRole, loc_time) child_item.setTextAlignment(3, Qt.AlignRight) child_item.setData(4, Qt.DisplayRole, loc_time_dif[0]) child_item.setForeground(4, QColor(loc_time_dif[1])) child_item.setTextAlignment(4, Qt.AlignLeft) child_item.setToolTip(5, _('Total number of calls '\ '(including recursion)')) child_item.setData(5, Qt.DisplayRole, total_calls) child_item.setTextAlignment(5, Qt.AlignRight) child_item.setData(6, Qt.DisplayRole, total_calls_dif[0]) child_item.setForeground(6, QColor(total_calls_dif[1])) child_item.setTextAlignment(6, Qt.AlignLeft) child_item.setToolTip(7, _('File:line '\ 'where function is defined')) child_item.setData(7, Qt.DisplayRole, file_and_line) #child_item.setExpanded(True) if self.is_recursive(child_item): child_item.setData(7, Qt.DisplayRole, '(%s)' % _('recursion')) child_item.setDisabled(True) else: callees = self.find_callees(child_key) if self.item_depth < 3: self.populate_tree(child_item, callees) elif callees: child_item.setChildIndicatorPolicy(child_item.ShowIndicator) self.items_to_be_shown[id(child_item)] = callees self.item_depth -= 1 def item_activated(self, item): filename, line_number = self.get_item_data(item) self.parent().edit_goto.emit(filename, line_number, '') def item_expanded(self, item): if item.childCount() == 0 and id(item) in self.items_to_be_shown: callees = self.items_to_be_shown[id(item)] self.populate_tree(item, callees) def is_recursive(self, child_item): """Returns True is a function is a descendant of itself.""" ancestor = child_item.parent() # FIXME: indexes to data should be defined by a dictionary on init while ancestor: if (child_item.data(0, Qt.DisplayRole ) == ancestor.data(0, Qt.DisplayRole) and child_item.data(7, Qt.DisplayRole ) == ancestor.data(7, Qt.DisplayRole)): return True else: ancestor = ancestor.parent() return False def get_top_level_items(self): """Iterate over top level items""" return [self.topLevelItem(_i) for _i in range(self.topLevelItemCount())] def get_items(self, maxlevel): """Return all items with a level <= `maxlevel`""" itemlist = [] def add_to_itemlist(item, maxlevel, level=1): level += 1 for index in range(item.childCount()): citem = item.child(index) itemlist.append(citem) if level <= maxlevel: add_to_itemlist(citem, maxlevel, level) for tlitem in self.get_top_level_items(): itemlist.append(tlitem) if maxlevel > 0: add_to_itemlist(tlitem, maxlevel=maxlevel) return itemlist def change_view(self, change_in_depth): """Change the view depth by expand or collapsing all same-level nodes""" self.current_view_depth += change_in_depth if self.current_view_depth < 0: self.current_view_depth = 0 self.collapseAll() if self.current_view_depth > 0: for item in self.get_items(maxlevel=self.current_view_depth-1): item.setExpanded(True) #============================================================================== # Tests #============================================================================== def primes(n): """ Simple test function Taken from http://www.huyng.com/posts/python-performance-analysis/ """ if n==2: return [2] elif n<2: return [] s=list(range(3,n+1,2)) mroot = n ** 0.5 half=(n+1)//2-1 i=0 m=3 while m <= mroot: if s[i]: j=(m*m-3)//2 s[j]=0 while j`_ * `WinPython `_ * `Python(x,y) `_ You can start using it immediately after installing one of them (you only need to install one!). The hard way ~~~~~~~~~~~~ If you want to install Spyder directly, you need to follow these steps: #. Install the essential requirements: * `The Python programming language `_ * `PyQt5 `_ (recommended) or `PyQt4 `_ #. Install Spyder and its dependencies by running this command:: pip install spyder Updating Spyder ~~~~~~~~~~~~~~~ You can update Spyder by: * Updating Anaconda, WinPython or Python(x,y). * Or using this command (in case you *don't* use any of those scientific distributions):: pip install --upgrade spyder .. note:: This command will also update all Spyder dependencies | Installing on macOS ------------------- The easy way ~~~~~~~~~~~~ Thanks to the Spyder team and `Anaconda `_, Spyder is included in the `Anaconda `_ Python distribution, which comes with everything you need to get started in an all-in-one package. The hard way ~~~~~~~~~~~~ Thanks to the *MacPorts* project, Spyder can be installed using its ``port`` package manager. There are `several versions`__ available from which you can choose from. __ http://www.macports.org/ports.php?by=name&substr=spyder .. warning:: It is known that the MacPorts version of Spyder is raising this error: ``ValueError: unknown locale: UTF-8``, which doesn't let it start correctly. To fix it you will have to set these environment variables in your ``~/.profile`` (or ``~/.bashrc``) manually:: export LANG=en_US.UTF-8 export LC_ALL=en_US.UTF-8 | Installing on Linux ------------------- The easy way ~~~~~~~~~~~~ Thanks to the Spyder team and `Anaconda `_, Spyder is included in the `Anaconda `_ Python distribution, which comes with everything you need to get started in an all-in-one package. The harder way ~~~~~~~~~~~~~~ Please refer to the `Requirements`_ section to see what other packages you might need. **Ubuntu**: * Using the official package manager: ``sudo apt-get install spyder``. .. note:: This package could be slightly outdated. If you find that is the case, please use the Debian package mentioned below. * Using the `pip `_ package manager: * Installing: ``sudo pip install spyder`` * Updating: ``sudo pip install -U spyder`` **Debian Unstable**: Using the package manager: ``sudo apt-get install spyder`` The Spyder's official Debian package is available `here`__ __ http://packages.debian.org/fr/sid/spyder. **Other Distributions** Spyder is also available in other GNU/Linux distributions, like * `Archlinux `_ * `Fedora `_ * `Gentoo `_ * `openSUSE `_ * `Mageia `_ Please refer to your distribution's documentation to learn how to install it there. | Installing or running directly from source ------------------------------------------ Requirements ~~~~~~~~~~~~ The requirements to run Spyder are: * `Python `_ 2.7 or >=3.3 * `PyQt5 `_ >=5.2 or `PyQt4 `_ >=4.6.0 (PyQt5 is recommended). * `Qtconsole `_ >=4.2.0 -- for an enhanced Python interpreter. * `Rope `_ >=0.9.4 and `Jedi `_ >=0.9.0 -- for code completion, go-to-definition and calltips on the Editor. * `Pyflakes `_ -- for real-time code analysis. * `Sphinx `_ -- for the Help pane rich text mode and to get our documentation. * `Pygments `_ >=2.0 -- for syntax highlighting and code completion in the Editor of all file types it supports. * `Pylint `_ -- for static code analysis. * `Pycodestyle `_ -- for style analysis. * `Psutil `_ -- for memory/CPU usage in the status bar. * `Nbconvert `_ -- to manipulate Jupyter notebooks on the Editor. * `Qtawesome `_ >=0.4.1 -- for an icon theme based on FontAwesome. * Pickleshare -- To show import completions on the Editor and Consoles. * `PyZMQ `_ -- To run introspection services on the Editor asynchronously. * `QtPy `_ >=1.2.0 -- To run Spyder with PyQt4 or PyQt5 seamlessly. * `Chardet `_ >=2.0.0-- Character encoding auto-detection in Python. * `Numpydoc `_ Used by Jedi to get return types for functions with Numpydoc docstrings. * `Cloudpickle `_ Serialize variables in the IPython kernel to send them to Spyder. Optional modules ~~~~~~~~~~~~~~~~ * `Matplotlib `_ >=1.0 -- for 2D and 3D plotting in the consoles. * `Pandas `_ >=0.13.1 -- for view and editing DataFrames and Series in the Variable Explorer. * `Numpy `_ -- for view and editing two or three dimensional arrays in the Variable Explorer. * `Sympy `_ >=0.7.3 -- for working with symbolic mathematics in the IPython console. * `Scipy `_ -- for importing Matlab workspace files in the Variable Explorer. * `Cython `_ >=0.21 -- Run Cython files or Python files that depend on Cython libraries in the IPython console. Installation procedure ~~~~~~~~~~~~~~~~~~~~~~ If you use Anaconda, you need to run this command to install Spyder: ``conda install spyder`` If you don't use Anaconda, you need to run: ``pip install --upgrade spyder`` Run without installing ~~~~~~~~~~~~~~~~~~~~~~ You can execute Spyder without installing it first by following these steps: #. Unzip the source package #. Change current directory to the unzipped directory #. Run Spyder with the command ``python bootstrap.py`` #. (*Optional*) Build the documentation with ``python setup.py build_doc``. This is especially useful for beta-testing, troubleshooting and development of Spyder itself. | Installing the development version ---------------------------------- If you want to try the next Spyder version, you have to: #. Install Spyder `requirements`_ #. Install `Git `_, a powerful source control management tool. #. Clone the Spyder source code repository with the command: ``git clone https://github.com/spyder-ide/spyder.git`` #. To keep your repository up-to-date, run ``git pull`` inside the cloned directory. #. (*Optional*) If you want to read the documentation, you must build it first with the command ``python setup.py build_doc`` | Help and support ---------------- Spyder websites: * For bug reports and feature requests you can go to our `website `_. * For discussions and help requests, you can suscribe to our `Google Group `_. spyder-3.2.6/doc/variableexplorer.rst0000664000175000017500000000213513224740762020477 0ustar carloscarlos00000000000000Variable Explorer ================= The variable explorer shows the namespace contents (i.e. all global object references) of the current console | .. image:: images/variableexplorer1.png :align: center | The following screenshots show some interesting features such as editing lists, strings, dictionaries, NumPy arrays, or plotting/showing NumPy arrays data. | .. image:: images/listeditor.png :align: center | .. image:: images/texteditor.png :align: center | .. image:: images/dicteditor.png :align: center | .. image:: images/arrayeditor.png :align: center | .. image:: images/variableexplorer-plot.png :align: center | .. image:: images/variableexplorer-imshow.png :align: center | Supported types --------------- The variable explorer can't show all types of objects. The ones currently supported are: #. `Pandas` DataFrame, TimeSeries and DatetimeIndex objects #. `NumPy` arrays and matrices #. `PIL/Pillow` images #. `datetime` dates #. Integers #. Floats #. Complex numbers #. Lists #. Dictionaries #. Tuples #. Strings Related plugins: * :doc:`ipythonconsole` spyder-3.2.6/doc/conf.py0000664000175000017500000001467613224740762015713 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Spyder documentation build configuration file, created by # sphinx-quickstart on Fri Jul 10 16:32:25 2009. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.append(os.path.abspath('.')) # -- General configuration ----------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8' # The master toctree document. master_doc = 'index' # General information about the project. project = 'Spyder' copyright = 'The Spyder Project Contributors' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = '3' # The full version, including alpha/beta/rc tags. release = '3' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of documents that shouldn't be included in the build. #unused_docs = [] # List of directories, relative to source directory, that shouldn't be searched # for source files. exclude_trees = [] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. Major themes that come with # Sphinx are currently 'default' and 'sphinxdoc'. html_theme = 'sphinxdoc' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. ## html_theme_options = {'sidebarbgcolor': '#227A2B', ## 'sidebarlinkcolor': '#98ff99'} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. html_logo = 'spyder_bbg.png' # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. html_favicon = '_static/favicon.ico' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_use_modindex = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = '' # Output file base name for HTML help builder. htmlhelp_basename = 'Spyderdoc' # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). #latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'Spyder.tex', 'Spyder Documentation', 'Pierre Raybaut', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # Additional stuff for the LaTeX preamble. #latex_preamble = '' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_use_modindex = True spyder-3.2.6/doc/internalconsole.rst0000664000175000017500000000107613156675415020341 0ustar carloscarlos00000000000000Internal Console ================ The **Internal Console** is dedicated to Spyder internal debugging or may be used as an embedded Python console in your own application. All the commands entered in the internal console are executed in the same process as Spyder's, but the Internal Console may be executed in a separate thread (this is optional and for example this is not the case in Spyder itself). | .. image:: images/internalconsole.png :align: center | The internal console support the following features: * Code completion and calltips spyder-3.2.6/doc/fileexplorer.rst0000664000175000017500000000107613156675415017642 0ustar carloscarlos00000000000000File Explorer ============= The file explorer pane is a file/directory browser allowing the user to open files with the internal editor or with the appropriate application (Windows only). | .. image:: images/explorer.png :align: center | Context menus may be used to run a script, open a terminal window or run a Windows explorer window (Windows only): | .. image:: images/explorer_menu1.png :align: center | .. image:: images/explorer_menu2.png :align: center | Related plugins: * :doc:`ipythonconsole` * :doc:`editor` spyder-3.2.6/doc/overview.rst0000664000175000017500000000643213156675415017011 0ustar carloscarlos00000000000000Overview ======== Spyder is a Python development environment with the following key features: Key features: * general features: * MATLAB-like PYTHONPATH management dialog box (works with all consoles) * Windows only: current user environment variables editor * direct links to documentation (Python, Matplotlib, !NumPy, !Scipy, etc.) * direct link to Python(x,y) launcher * direct links to !QtDesigner, !QtLinguist and !QtAssistant (Qt documentation) * *preferences* dialog box: * keyboard shortcuts * syntax coloring schemes (source editor, history log, help) * console: background color (black/white), automatic code completion, etc. * and a lot more... * :doc:`editor`: * syntax coloring (Python, C/C++, Fortran) * *breakpoints* and *conditional breakpoints* (debugger: `pdb`) * run or debug Python scripts (see console features) * *run configuration* dialog box: * working directory * command line options * run in a new Python interpreter or in an existing Python interpreter or IPython client * Python interpreter command line options * *code outline explorer*: functions, classes, if/else/try/... statements * *powerful code introspection features* (powered by `rope`): * *code completion* * *calltips* * *go-to-definition*: go to object (any symbol: function, class, attribute, etc.) definition by pressing Ctrl+Left mouse click on word or Ctrl+G (default shortcut) * *occurrence highlighting* * typing helpers (optional): * automatically insert closing parentheses, braces and brackets * automatically unindent after 'else', 'elif', 'finally', etc. * *to-do* lists (TODO, FIXME, XXX) * errors/warnings (real-time *code analysis* provided by `pyflakes`) * integrated static code analysis (using `pylint`) * direct link to `winpdb` external debugger * :doc:`console`: * *all consoles are executed in a separate process* * *code completion*/calltips and automatic link to help (see below) * open Python interpreters or basic terminal command windows * run Python scripts (see source editor features) * *variable explorer*: * *GUI-based editors* for a lot of data types (numbers, strings, lists, arrays, dictionaries, ...) * *import/export data* from/to a lot of file types (text files, !NumPy files, MATLAB files) * multiple array/list/dict editor instances at once, thus allowing to compare variable contents * data visualization * :doc:`historylog` * :doc:`help`: * provide documentation or source code on any Python object (class, function, module, ...) * documentation may be displayed as an html page thanks to the rich text mode (powered by `sphinx`) * :doc:`onlinehelp`: automatically generated html documentation on installed Python modules * :doc:`findinfiles`: find string occurrences in a directory, a mercurial repository or directly in PYTHONPATH (support for regular expressions and included/excluded string lists) * :doc:`fileexplorer` * :doc:`projects` Spyder may also be used as a PyQt5 or PyQt4 extension library (module 'spyder'). For example, the Python interactive shell widget used in Spyder may be embedded in your own PyQt5 or PyQt4 application. spyder-3.2.6/doc/pylint.rst0000664000175000017500000000065013156675415016456 0ustar carloscarlos00000000000000Static code analysis ==================== The static code analysis tool may be used directly from the :doc:`editor`, or by entering manually the Python module or package path - i.e. it works either with `.py` (or `.pyw`) Python scripts or with whole Python packages (directories containing an `__init__.py` script). | .. image:: images/pylint.png :align: center | Related plugins: * :doc:`editor` spyder-3.2.6/doc/_static/0000775000175000017500000000000013225025007016011 5ustar carloscarlos00000000000000spyder-3.2.6/doc/_static/favicon.ico0000664000175000017500000001246613003520702020137 0ustar carloscarlos00000000000000  & h( @ 'Vp0$4- 8ttt{{{8v;qqqAAAAAAAAAAAAtttD&LnnnAAAAAAAAAAAAAAAAAAAAAAAAlll`!klllAAAAAAAAAAAAAAAAAAJJJAAAAAAAAAAAAAAAeee/ziiiAAAAAAAAAAAAAAAAAAAAAYYYAAAAAAAAAAAAAAAAAALLLbnnnAAAAAAAAAAAAAAAAAAvvvhhhAAAAAAAAAAAAAAACCC{VVVhhhAAAAAAAAAAAAsssAAAAAAAAAAAAAAAAAASSSbbbBBBvvvRR IIAAA:xx<>J 55a@@DAAAyyWAAA>>J??EAAAJJJAAABBB33[[T""??EAAAAAAjjjAAAAAA??Fj OO33KKoofffIIINNNAAAAAAAAAAAAAAA22h::`LLLRRR```nnnaaaAAAAAAAAAAAAAAAOOOA>MAAAAAAAAAUUUEEE```~~~```AAAAAAAAAAAACCCuAAAAAAAAAAAAAAAAAAAAAQQQBBBAAAAAAAAApppAAAAAAAAAAAAAAAAAAAAAAAAAAAxxx 6WWWAAAAAAAAAAAAAAAAAABBBNNN\\\)bAAAAAAAAAAAAAAAAAAAAAdddT}}}~~~nlkjhgedcati_'"߀c?(  2 캺~ ?KKKtttNNNYi길JJJAAAAAAfffAAAAAAJJJ qqqAAAAAA|||AAAAAAKKKIIM}}-- ggpppE))IIMTTT--v,,HH >hh++}TTUIIYݐSSAABlllFF^ bAAAAAADDD࢞AAAGGGVVVAAAAAAߘzzzAAAAAAAAAzzz{{{\\\^^^^^^gggnMG A?AAAAAAAAAAAAAAAspyder-3.2.6/doc/editor.rst0000664000175000017500000000243413156675415016427 0ustar carloscarlos00000000000000Editor ====== Spyder's text editor is a multi-language editor with features such as syntax coloring, code analysis (real-time code analysis powered by `pyflakes` and advanced code analysis using `pylint`), introspection capabilities such as code completion, calltips and go-to-definition features (powered by `rope`), function/class browser, horizontal/vertical splitting features, etc. Function/class/method browser: | .. image:: images/editor1.png :align: center | Code analysis with `pyflakes`: | .. image:: images/editor2.png :align: center | Horizontal/vertical splitting feature: | .. image:: images/editor3.png :align: center | How to define a code cell -------------------------- A "code cell" is a concept similar to MATLAB's "cell" (except that there is no "cell mode" in Spyder), i.e. a block of lines to be executed at once in the current interpreter (Python or IPython). Every script may be divided in as many cells as needed. Cells are separated by lines starting with: * `#%%` (standard cell separator) * `# %%` (standard cell separator, when file has been edited with Eclipse) * `# ` (IPython notebook cell separator) Related plugins: * :doc:`console` * :doc:`fileexplorer` * :doc:`findinfiles` spyder-3.2.6/doc/images/0000775000175000017500000000000013225025007015630 5ustar carloscarlos00000000000000spyder-3.2.6/doc/images/editor2.png0000664000175000017500000004035613003520702017712 0ustar carloscarlos00000000000000PNG  IHDR= t cHRMz&u0`:pQ<bKGD@wIDATx{W}TTEUڐTvQ)$l fp;/Hى{JxG ̵)!Y}+^IW,szzGU493tO*ThT JċO=_9M,ǿ&ϛ9ri> pnՆK9OyC@^r孷z^@f}#jR9j{UV}Zaٲe[n s+ެ_IZ^ڟEbSѰ*T Tя~t…/^2K*H5O=zTA+yK_s TZbygfll~ V֓ې/A.U?b3gH_ȋNNNJ$-gà+|r=;wvo['%E--#%X33x\uXmIruK'?9pǥwm|=Coo~gƠ/~'8goŏ͞x_Ss1÷T-M?.gfI֭[CY{˥lI eU7q#Ve{_we%3C >gNuϭ+S9}V\|.fQR?/ߍ+ʫdTp|DB4Ɂ/_?#PfYFe*Ζ/X49wӛ[rZ>^xA/~/^q?[˵ZI/-CXyW}Ͻ_&y!J̚GZ9G-RBw)m.  Θ,\խ~fZkbvUpŖ-[jy!Jz[C[2:ת>o"q,A.UˉL!)*鷞>|m߽{6{~_mqKi>yz= 7)2kΏr|.̷t_s^R+T"^ѐYR@o3-{W,}tHȁ$.A 3-jec=mٖN/ѕmi~fA.UK^NK/}+W៾R_QޥT :>Q[[&_emd{n Kn%])-SH?sվC_=LދCR(&Tե\9'.U O8Q8!Sէ"Z̜j ;H9s9Lmf^|e]RZIjNjM2[6[H՟ _u>?PfQuQs-:礖*9'&.U}ǏWL,\խ~fNjQaI#ퟕfi <<ݙ΍׭mHWɈJ~ JdVzhsK&S>lҪl+}nvk0N2M *I_T~~Cu\ \(z"uzuCjՖ?ROjݲفkݾi+I-I-e-cPхMZOO)Yw"9ǽT9Ӌ>D#[̼[/,Eٕc\y1{y_ zWɟA\̐jec=ܒְUmҜZ/z h7v-ST-gCV*Bk~zŜ;3ѿSU/Wm3̟'ޤ~#QlUHU{קڻn]P\խoTײJƵjyl߱c@g̒ Ugfv5zTtRJ*>1_ܒUVnԲ<}1CU|U{fSͮdR?yf9߫7;u/ՉGRO*01~OFStľT2Z0N.K#;8kdme豪ˣCO`"BsU7sdkiG!tszs($]%{WmBxܒnڪֶJ3o5l}a gFQ$sӍv-,WT-FGG}rC!z饗>:A/wS[画Ǽ;Җ +7UQjJKbUOme#] קU W:~՛}@rf_dbg%Voްo[J ZxֹG"@GFg"첱Rmnɸ5^7oUk[)l0;Lúq +۵LR>(K.H[Ԧ}ie.#;y}̻} uO_u_?(?G^@̥J>5y̳dTp@D~p>3rk_]JRd# ~}pA d*ﳖ鋦H}xiYrZEI@NU=rsrP (}DP[L=Xt}_~׮7}_oWM/|5}h?}.JΙemƁ̒ NUGHmܸQfk%^L}fd~kXܑ+7yriSZvX>kɎp!-R Mw% -YdddD/9:f>:LOբi',Tu|M[_ .\x}'s=!ǵK낱RCے kI0\-==Uɉp S`z) U\ռ 4T}u׉wڵʁ̒ Rͮt@SyinۿT~K|PuU͛MjokppΙ3G^-PuU͛*HU ebA 1Z^k"KZV{뮻Kъ-Z$k!#5Q5@T]p[gnz_UF,X'(۳zglS]k6{3([Dn A/_p e=?^ΉŢ#vFpHUtDVTuSAH"ư+ ["[/{TXiT*L-֦ܺMR cw9LwK@7U}'t0蹪!xK-OԚ%:v}xr .+`-Zp$[/ތ.U[=S}^;PՒ,6tu@Yj_٩X:W09EIL #7W/[6\]X<0`-@[MgT9vKaʽj@Un*)=W'u }#֢ض:4m!v=g7YUl"Vb)Θڋ ߚ I|\w~=%黚{j4UU;o[qBu?/ |zjokQLB2kDՎ?%UP+Q}q֍ܽ6 #{T#Pڠzzvc-\R@ըl6G{W]:TSXo".nU.͐:ϟwy#GP5@WU-:sSN+gΜ9wܫ>ϟ-UjT zUݨJśjrXZTcY|+wa%FWTV:wxӒʼ^U( rW;j_ dSdDHUWsMV!UOnZ,_ZV?5U[CLTuQ7Qo "kcU/v2;ZpL jIFznaQv6,bf\YժFEBuf+66ZG)ƊpI}2tM*jqe%dXWK .,\p*&RG*)_H{sbk-Fվ#YX ,'W {hH[AY9":C֨:cjO5עyj XuXtmpTms5RD=hVDieCj)Wk3=cd17[Y[ge=;A>#\yrt~gQnAZy,:s~Wm)) 8DZέfӱ|uCgx,ݺYh~i=̼qhы/F9ޖJ]2igtu!Y/퐷J2lI+#b;NovGRKiob:.睜w2a1|UgU2xÒK? eN'<~8dl1{o4$_[K^9U'gy0u&;8lLoz6a-k6²[ȵKE6i md}Ih{ڎºpS Sqaf4,Rdպ.kT7Ci=vN{([<׮TgcD{r}Tko񫶮b2ga֧wm=#jKM6}Y&r{#1iOkw6)3\uYfg-eVS{{@oXz;NPLgaa5SbW6H >hӸrC |Ԩ֯o=xnj,l4@;ޥ)bqlGڷ&MFiˆ"ˆ}]}J?b9 f7m~Zs}azTڸv]\[dV<_B[lv6LG*dn:Ucw,n;"m" ATizݡ`{_&$dTk:GFW펖Kz3y\i=vNGP5@l<}ϞUj!>2~#*jT СƕPE (2TTP5TP5@ըPuNZ;P&)|PjM'B*^W7UQ7_j%]^zPUƿJ-n~a#-_JZ Gj_K_]E&Ȼ$DƂfVzU/?zZ^kQuE6776|zuWU݈hm$mU{jP@m7urj(ٮj.kRUOZI2KK%w%Ya!U( >pT].U*Pu)U|y8jT Q5FQ]c*?TsU=Ii%A ҭV_`wKITU^#EHR'?3[^th6s`́͟GAI mfbѓ#֝7a&9?+l]u6ݵ;3p9Xf.{򔇦3Su;iw|=Q+@jWҧYU&Ks67K%yD̵Xiym/}uϧw6ݵus2pg*SwA*H~ƻSL?ډWAz8_uT$t(Z, U[ojՖmӶ dZB4l2`̒IJ',Vw.ݵuo4woZAfSv;\O+Aw|ՃjDcEnj)Ƒm;*kEG= VQUlx]dϳ<nrQ5$,g5pW, 5#DTZ}*ewrjq=Bp[j)4`-Lwmy{q;<{uuf]U-R^"UnzcU,DZӱu= 9%W߹X$ FJ?ɞڶc0f2o*憒)ݍgo{wX`@</kYx1~:ꣾϨFq@ըT!Z>UwQCJu>_U}P5@ըP5@ըP5@=W= U7V׀CVYJyr{ƪnu  3%_> m$ܟk}[Ya\5O?r:}SXtS]`ȕjTuҭBAjTP5FQ5n/ ^#3111}j<ҰQ5FLLLLUj>LLLLg{;>~`txT(Dz?e6-z{e&\{5wKZGdmoqabbU8y%瞺cj';{;_u;cۇWc ]nj_uTjvS߫zj6>o\|զ3QuTIPfc kz.Lӟ\{% Է~yϦyZs9~UǏBjk. w[z|K¬0VBˆn$ǒRFORW; Ńxp@X\?t0\ܐQ3,[ ZV `-ھxӺ:^K:r^}:~C]65c:{4'iPT?x:pgM\9k==k:Moie+/wՅsjt:Wxa5vxA|Nuzjr7w{%jj5qznzyW?R3y)uc,}Zpvl[Ԟ{f)>_o&&]5GԺSOsWeoPߨZ=^mOx/:V}wѧO]~Zm7wS55O2uw?'qpeH|7&&&TU7sGSY|zՎՁ"쳇#ixjp{Qx}_Ţ^)-5zՉނ:sP=zBw~37?|vq=]ݟn4FMT}zwl2-RKިp7ͼ s2́pTmo:{qUo oUV6= :PLT P Q5FzHT=Z6Rkvꫪ!k#]U:[m 4g`CU[BBT|fUJ2 wTjrD*~ZBTVQgU QUC|BTPu/TmWm+옪w7_NvEB{|dUzȖĺnҳ`8Y7j.+oӧO;… /^?ֲ.U[|QuIU{qy˛UsU3"Bܖښ'7)fYKwIȜFlʡxe9Ԟ5^|ƕ3{Jj(q(ѹ{SѳFK`_ 5[+G ?cQ}ˬAWE[;UoU n?DznSh:B`6Y*ѪݰtUϛ7oҥ۷oG9#: 5>eԘjK@Tsxve9 P5O+c"@ը UF( UjT̈́P5fBQ5@ը U|ʒjT ˓:~w)/U+ZG5Q5.A(1fgUVѤκ(4vl{Q)&eP5r竖 VoH7nn~ɩGU QX<_ՍeƗp #~`FUl![1eZ Tu~FdP^@_Z3~mݺumsŻU.yj?cڼCk@o. -5"'EKe#c@wE<k 튪댶,xҋQAUgn)]y@$ a3zp-21Z3/jYD0utt9gQuk݁Ux;(qKՎUOOJv0T=<@ m|qV<5Ax1UoI"|UgkZ0T zXTmF!]|ɶְݕbΰ֚DDª/^\NV_*2֝i"^;P5j,#PP5fBQ5VCU3jTP5jT̈́Pu{UǙd.KOT zUWͼiiU(o +B:N[mU<_qF@k<0^.5 ToɓP5^>+3ny%e-뢞2#5 xbb\|~z-tu|Gjے"c5j@WmZ+i=bĚBCmVڶnK=U4~{(Ӛ9J:ًP5~W}HQu0@Ug,J<1aamy43Quf$Zaa{Mδ;m{qbQx{ T `kgƿ״OP]zzq͑as@T]r+NtDeT /U'!uV7N+v&drS rUc7a5W5eTZ_׮[j@C&I}aZ&gj.[P+g\E$ UnLC3@ըsKP5FLUj&T U3jTP5jTmU5 0PuURVg2kԫ5ݻ/_hѢyͅ>GQzSTz… U*_uÝ:ӧO_^K.GMSyj@eWE&1ǔS7~u-ݕJe۽۶ܶ%Vn %.\ǽQݻ ʉiyK^x3嫎nMj V㫕+^zh{rjve-ދ-SLe>gg'C7;UzU.[j_5Br64|w'|}>U,_2&KrU?VQ VېSπ4PMUTv-]|zVme9hZgj@}J+m*8.kE !qN]@%@ըP5@ըUY܌ܹP|aYZ (j}u.Ru%m@ՃZpYxK>#!*.fjI1UQE$VnH́OVO`"Ƞ$P,. 5sL\le^pͤPX~]?jWHIĐiOk[󔗳AUzj-?0 UjOBѐxq+$ׁE@Aj_+g ˪ R'צU(ēwh:k{[~fQuPNu,X^:%TB\X̝t)U{RIVeVn3Avm " [SHm@ՃږpkTrMTIH}l&ҟ`$za9MU3x0v#[f-]mMՍڿ{ܕ}z XI˻D44cU;eQPnޏ7WeHmsa9ְ:g+w5j}R>wNC8 U4a>T5Qu1;A Q5FQ5o@ըUj@}j٢هGaO$K@ՃDS pT qt-͐p0״tq6圄ʖJ9/A)y< oQ_T[om_VםW~Y7\ilfk$,Lj&:bC 'UkM7oAk鶲j^.ƆU'd)ʿ$\QrRme0|~vցkfz&5Y5Qu7ʋj~u]<|Xݫ.^P'SE=^{E=͝zqRU*SzuJ=wGվPKjϨi2bC T KUˋᖗMTYvT+#KF*cN}U>5n52@GT-VCުڑ:)RPSH…"Je$VHX3;,z~b/^F豪9:$°,~.x{ښ=QD[PlW(U3xڇQ/We쏶 cUo L[5JԓC.?S7hF \KPP,n1ouj;8>P iUo=Df<0p )3C⚷7X:^+1Epwự| WmzD,xD[2VWCjUa#Ύ\OlAM~qbFq:d79c0^Fƙ#r<"~U::e W##QjmC2bef*|OehONF^NѠqGX"fc{ʢ 0ȵ86|nP2+2pʶݫ [Ǵƕ"Cж`Zfڏ(PoH{!ux x>QR&̟?q3Ngj(iUP5L0CܦIENDB`spyder-3.2.6/doc/images/internalconsole.png0000664000175000017500000005572113156675415021570 0ustar carloscarlos00000000000000PNG  IHDRNhsBITOtEXtSoftwareShutterc IDATx@GǥcK]c1DMKXM1[45P]+a⦆H8y[vc9g13ZD> dǏZj˗)Jd Cww7WjԤ% uy9 0¹3߼/M|%RIHRb=͜MvZ6B>{ZHy&$@$@iAC|yu}q][6txIy=t#Dzu1GEEصŅ@΍i H#XH#> ŅjU^fCQz={tzؐA0H>eN1KH>SDy4~,dzgbbb{)׬Ӏܹr$7Vmݚ62lWם=oW.[{.eHVP,҆MB=0_1 .EZ5HKq0XL7Ys]]^."L G~=!E 69yov0 GGǩ'bAdH!Cd #҆MB E 0;aᨩY:6Ξ;42C֗ẂkSuQAfժ :v7o*Xn}xx˗/^NFhHcqרN`zn:kle/ݰ~]=`7o݆YIH}D? Tw0[Q~&8ai >!mٺ? ^E|GG8}ծ*oYQ~ں-vխމ++۫[bHx*aBB`u*UˁM??qrDdD_FCn½RF` `H1#i]_# H/JF_>Z MTcFKS) @!EAAAb @\I@/j~U$@$@G`hwv_$4 d^oȼr h2OHH HHO$@$ S{P#aJ^b3f(q]*Vt[Q( 3 =8y޾z><{[߈zwc&NVVgG>\8~T_Lxo\#]GQ%GQKKcl+b.Xaߜ?4ߍ|;víֹ!qq(xB[ ٯ\m{c={BVZa[ܹ8NaE:C^Anʋv w@h{-#/'ji ንvW H3X~mxvf?\z-u+m5k!Sh# l)t7/j kcQFzJ+~+Pd& 0d0]uu_s'?Qa*je*oáq6n?Uc"_/G=Yh!o[̩fxK\qE r6e Ct]c/_bJ};;Y;qVXϽ>G>JgUCMGYײ= lx/|aL=2;!L<5(S;VwݯpƹgU^=j }q $@LÑmÛ#G[bEUY(À{HcsoG>>׵Xqg2]\\\mo[!1%c^dkß& m'i]X1!3Q!S1q8pqUÀf0!15\BPB&C\WbS?@l:gs ,cjƫU]J(PjƵ|f09uª^,q!š q$@fF4#Ѯ[CҮwuuX'ۈ?r7Y}c87^Fvmci#/x3&_oogȃ,0I:}NEMj5_zv sp8dlݍkżQb+u `)ZO* 2:ݡk3bmŰP]ҥ$z?}=CfC$j~2|>>Y}W3Qgty;6rw -y]'dz.<GcUUD„Y,M amؘ5WCOpSԹsÄIjd bBE2Hw̏]#4oy5kU~7 e[<,DpǤfHSt5xφ%I1$l?{q[GkGqil.ۋFJM7>aS!0+WT k4W&?dX Ymepʍ(1bpRie$l ٸDА3A$X`A4އcA@Հy[Heqc$I0nlt   F?goC[|{1KWge 6L_}}Cv&Ѭ$`<k-:ڴ"NEyZK 3 `d,TTM&]Wr_b R.R}Ӌ.la>y2,.LMYG'IxMr7Rlw "nnB{]ؕY|VL{y# l)`>熜}o>q W_E&rrm5¨W_!sᭅ%p]jTUxq9Ip}ֹe]ԎRg"kIW&zXSd y97!NNUT=~TQFdVVUvW b5R_Fζېy'jnnusg%A82>֨ 2CBcGB`䅑b7D*rVӃ^z4qcCͅ>:;/ .*zPS5Yzjn+ &Xiw U[C?+~ϊjX1>;o[]wb5_g! ࣞ4+vڏz!  +-\<}wW=b}'t\{6^m:駯b_~ S!Ͻ|bN65,Ër5rqYuw[ #߉ݯ;]m\aK;+g%'VpٷۋlrB~a#ccsJ:2&6Vo}:q  @;Xd0u>y +.${VW㬦gupv*\ޭėAR5$A_]0?$)V7;e[m"d%_V[b5GIOeGwWGWmu~jviWKru ܕŷfNQ+֙$`,'Qҿmw`,}r6˪,M4GNQ/ !2Ixi!fRZ"iҺ* kk39`dFvZ넩d}^J7\ qQD_RGZ79$H4#fC"cLJNPtk !jDŽ:XU S{|;Z9zgzC#K}}cCN;$` X1/T *I܊:Ul㽑Wv_<^_,`ܥq+Z_=3Qg|:+e EkLFV J`x!?+O;8Xy&Ҋ)G,<.d`tS\ a?.@ KmlX ŲX;|VD2K%E/,6̱)-5AiK\läG'NX),;W@u2b J:4!4qm,SyL߆nlw^qu jh[j,6T۠$"4 [yT5\z9-^~Hb3&_>V[^c;Fvμ>`Tge0Ĉ!:!ۛJ~a;tTt7c$^yO=҆a z1 {byC攟mꥷ.ՙ_}Ziʭ{HȜV .]"[{uNA aH2" Ϥf#zAԇnQ&8u?R? &=) ap 4EE^OxQd[NI'qq1 "JlqXs,%Fr6H CHf?7k(b4Y?\].M}8ǻ+@?|q5'&`h} ꇰV+XQ3.be#b^!' 2x m-8-so̍ЬyXMxj T"P&u }GV#6寮N-"bn+ƻF;E1vt]d(WaC\CjTS GD DpVXg3C!{(kG< 4,iqoXaHȸa-;Z<,bCϑaDf(kyZ{_?**$Ff>))S{E< "\ҩbi܈ϣGP!BGt)0(bdW}_qAc( IDAT[V'k'<ϵz\Fn\ų!ifLSĎ{i5"O ;@\ ϱK-ITqώ|Kh8TFujaP+ uj!o|k: TͿń~V,.2u8cG#9 IraykN1;xװ=5Ͽ1uS7-VYJX6LѭE!YΐW=#Ht]/],d-kDEaŸbGKg dkt\K}1\ Im$'pSn!~+ĥA:anǹ?׀W#E17>޵4|:;/uiu;%S'3:_91~iNjC1v4!qbtŻFr9K!nۋ`>VdžV~XAs qVo"5bMvQ@9WA_%K3VYAhܽ?6Ď=)57uzWADh0hcFb|I:WCDҀ> #n#77)NġVg:n^+٫#s)EY1b7Ro!8낈ZhRNBэ|s;"4RkNAh9C?<$."]c#1s0k !ӱmLQ?Qc#} RVgQ$ 0uQy@juso· +ˑ{!:{(/JwZyw%n&Š i v^%}=HbV(ƻ0͔0>`cH 9B4Nϓ @& ( XHլΘf5+g4"^K#T^$o2gk#<#tZl"ځ.ĘɫꞪڊK vB%{SbpHG4|ƣKt(? IZ! =7sƻV;7PhO{qOăKͯlٶGۆ aY5m!U)QWC&q񤽶ЊɬyHf?[dxjS;)!2^z />pYPx  7|V Ro/UbWP \+5E5 '0dxNt@ӈE#x; p`w~@oxdeޖjo{=d h3"_<'!CZheE,6#~bt+jP˄!"txK18#ag d-G;tve],سWKT&8b?"NYC۷<܂jO邀Ż6>4"zoF\DEhG"">Ng;Z1*Aq屣B+)ym&<I@-FPl~xs)B@D}*戴H&H l@`ŝR |Dp@[:#9uB8nTֵYTѭagbB'N5RKkk|B0^IqՄb!REn+++f ]#дMؐ c`xJxw <L$Vj1, qV;Z3:*11-+`:57IW.A$(Srk/DAl~DN\Bw?ݡ6Q3^n܈+~u48DI ]H8:!R8"GX'v?ȗHHE8hDmSk uǻO7< !NXr{I=?xP@IR:d4 Z,^#+萏V[cJRpl EAe[ Hj߰@8\@ û#E^\iq|>}pgM)_JHuFt_E#޵xf 27cXpkAhl(F S~lex41ߴk0Oԉw! qQE'Dw+/@ӘC"!coTDxFel ? LZxuyW.;G'btW  A]7xI 8㱆ewa4lzk@/A (<\0b닉9nE1pTO*= 06? h##.9wb}q 9X@HJ IgdZr'xg 3EHHt] ܓ(TU0OX>4[xI2Sͳl ḏӥn6eTdԖ$@$@)!@{ZRtZWUr#@1R?&#0@wzJC\q"JIDxNiq[N,+ݩO:)29ڃt)+.*jҳ)3viܱj -DWSȜ.=qCSZgݏ74QS5ͿZ h!6f!FŐF`l`z(A"dxywG1@oȎBRQ3[C,\s!vqG^pin-j܎ g Wu/w=څ;H]SWeW]ZGTRRٺQR$#< ČB4iC,s5BL/;}L1D"qJGD|e&ﭽ3GEd- |EuRY}͈xghlW $/O,FLj9t,;[HjV*+1aiy#*? -$ۗ :R|vnq%`BYg8qE1 4 Mwwſa#EuFld{*TEDtRgi9Bu cR2 S!! pג>cFȒw-,MB(IXԻkÙSl[1cgkڥN:1;[qtC"6c$I!-RôQ%ExdIQdbɅMZRO[n Cl#HgI⬑q1$HhJ-נ6E YS0Ai*B0>L OdajsѭE$倳r2[M iCaP 'Ǡ naxݕ>,l_cPY CQ3Z/ J ^'y$K_ڥl"@&rFJ$W.Ag;orRIx⢢XBo@EY|3Tac!U ]   l}` /jy:.fȄ3w}g+X?>x׊1eAAՒrk~㥜]r)s'yL )a> 0> L!ߎG; cn: K<30.10l- J+E WYf-٨"΍9Ŷs p"SGZy˅ƅJ2X4~}F][ Kl/aT⮊#K60EGB`䅑36DI^'D7`=* -F7հr;I2rDV:PN|8ʤ|F|N;ZH-W[ޘ{OK\ڐp=ODgM]mO53@BZ8:=qcCIci~[u_xXuwUᭅsr=D奘&O y{ opXdPlvo9dsm9:XHzyu-۳`6^mGG>?vo+]N:[glt{e\QOr!04Wy6hr*UZmcxgEn'!8pFEF~8,RߎVY1CR.޸<_["i)h3!l-G5sPYb:nrOl@Zmj=Y~Ei!7F{;z4'S$ Oo-h+?}n`qݫP/!leaD>Xϯ0sa k_l|Lԙ?.w%F8;2JDB.ѷz. C/a í[6b43X[$VJ*pvB> :gS@I[VՐ^$: ;ǰ+С P9jl޴͠(Lc8P؃·ZqV~oV_d?-%j4psgIJR&H Hk#Glge.;8۲;0Ǭ_x}?BKSrL o+_b.v}7ocj7%HT ۏҬUV|wCޯ%~H~̂ " cje/ud!|H`P!8EI(Ta wMz塖cƺ!/6kUڥ;KaYVZ&~6R+ ,PɽR PAE iNJn/ ~@:TEX:;hܥq%c!MOT* d1]}b㲧íF}c TzW[8a1*8Z;F'Dw+R0ٸu8 c*3^A|*ttѐY}w5n檞I2VkZv{4Ĉ4C˞}}v>JaS=mv5M@qEp灉o}t. ' +1cvF"ƤVZ*tqƔґ c4ѧPqJ9hKUIDATpC Yhv9r(Fc{OLvSa'l}(@銀 5j@:dҔ@Ss>oP ˸4yؾcgʕ6 ܣ}} ia4S+O5V\Hc!i 'K)BcQH x5jB$@$@k @!@{~5! I}IH =H?} $@{>$@$~`MHH}=xym H?hO_&$@$> O6 /X xh'}^Hڃ O>M$@A քH'cFv$@$@ox?:HH=x} @z @{zu  Ok@$@遀!{O?X:A^Yg ;?Ny\i  tK=~%dKC-7{8?ދ{nuaߦn $pm9+F$@$ '`T4ru;H>_}몭;TPg$0{OMX~1IH-CvucJ)ur:`wnђU}0nDVwc^|zрpm<+F$@$ R7.˶m(b;ws e+կkmԄ2HH 0dBbC~>OV1t.h7<,O~gg* 6J$@$@ كR.S+{-KJmZiyթ e& H TU/\L?SMXQ$@$@[V9ևHH=xgy! HQ݇FHH@qc) 07֣l h#@{K =0e{HH@mXH̍큹(C$@hR$@$`nh̭G F@7" s#@{`n= 6ڸ sQH=ƍHH[=$@$6n,E$@Fz! mhqc) 07֣l h#@{K =0e{HH@mXH̍큹(C$@hR$@$`nh̭G F@7" s#@{`n= 6ڸ sQH=ƍHH[=$@$6n,E$@Fz! mhqc) 07֣l h#@{K =0e{HH@mXH̍큹(C$@hR$@$`nh̭G F@7" s#@{`n= 6ڸ sQH=ƍHH[=$@$6n,E$@Fz! mhqc) 07֣l h#@{K =0e{HH@mXH̍큹(C$@hR$@$`nh̭G F@7" s#@{`n= 6ڸ sQH=ƍHH[=$@$6n,E$@Fz! mhqc) 07֣l h#@{K =0e{HH@mXH̍큹(C$@hR$@$`nh̭G F@7" s#@{`n= 6ڸ sQH=ƍHH[=$@$6n,E$@Fz! mhqc) 07֣l h#@{K =0e{HH@mXH̍큹(C$@hR$@$`nh̭G F@7" s#@{`n= 6ڸ sQH=ƍHH[=$@$6n,E$@Fz! mhqc) 07֣l h#@{K =0e{HH@mXH̍큹(C$@hR$@$`nh̭G F@7" s#@{`n= 6ڸ sQH=ƍHH[=$@$6n,E$@Fz! mhqc) 0+==0ecHH@gggmXH̍큹(C$@XXXh"$@$`nh̭G Fm%YHHY9$@$Fp,F$@DZ=w! Ȓ-{Preo3H$@$Oev٨qD}Q椆o%,K$@%P|·&'[իW&W!Z[[߼y#30a7 aJUQ:Y^d66Z[Yey=V=^:Nfb&O&)T̙]XFD5⌣L LWiB*AU:|Y^~l1 (=P< d]?8@+U hIS;~"/k L뫘\<24R~y Hiiyomp~O"""1eW1y;ߋ,_ZƸϿ ?j԰P)yQOs2nZmW_wSrS;w?HN>_E֭_Xǿ>΀Φ.PWMri$8՟bE(Y& *Lif+-8~͜y+69..~?+O1S{yrgwCm&`Xg}}}~ϩӇNժ~m ļx޿ov^|1㬬NG,\r*5UapP$ݽ{Ѡv_ٵ;pıXh*<17<";w͗7dnܸ9cμGB?(Yյ`uj/7WzukϘ=3##"cܱ'֬]W|]կ_^a]{,A.~?+Vx?{B\\'M7n@^/^,X_E<;ow\]jE !(SG#>z]pq%_wr IC~9@^lgQ:wM4UЙb{e˓Ƌ!>ĩ}z+Vo}޶}B~?S{D^REH6aC~7_͙6bcc?Ӗ-Aܔi3zݿI޻aڵѵիU䀟~\ž}1.Æ >}xгGիA3|{v4?SBy JLjNNNw͑=ߴǾ`>{Qę85zw:u6loZaӭw0&b@hK5kȠ{;)S?t9{c"~`(+YxR%u*\ڇ?<͔u¥iN9x0X1Fd,.գϝMvaa}Tٲe,ZO|\_'$& |˸ >1~07oyɝ 1;;۹B᫅KMDDFZy rC\08sF+_i3f]{#$-TFHH-[s2}Chz1FBjyv?# 4ӧȌyGCgKPrS&O5wϑo>=7CSB>P%Ys0x򥋪U [uk7qE{9i’`VG޼~SJ(f~ҹ€}7eqaQcs,/')׈M[u:aw|"6~/ t0cmiKgfM> qfjc,Aǎ-S`A?4?իn޺*"Y }m)j~ó7ɘ 7mD!!ICGd~Cⷁ|U*'MJ< swWbm,k֬NNࠃAhrU*Ua!_zU+f>;W{czSj!4`ځE 3A'N4&4k6ju큆U(_6W(XR׀{vm/T'Y/˂ܹs̑#{Ξ={B \b*ًi/z11/b7ҢHBjTǚ@ oRU1/ۺmG0&C _whgkk?6ޱk(+?Pbł~Мf4E~$L7F1D`p5rza$yn{|y%ڵjb.8r4/O8K9R\@L}e,^5fbL]W[t VaY#;2Ů,^bX`K@!┳HX['=a@H¿gb]"`}Z_4O#dvu\RM6ICRs+, _>{L]vJ+WlqԩĠ >O '鏉̞]y8>s@ġ~U.,W}HIY@ѣA۴C}JbHЛ:}W[|bj)ϔ#ʕ[*aWdp5MpcR.7p Unn$*Jʌ~-4_aysĥF^ 4A2OŒ!i5(ҀIJgpy}5HͰ]|UԺChpwwJ%vwMy"W~C_ /2ipP` oeLO>)|dBGIt_)&-)~ɅI1Ǩ-Ó=g!+ " tz2++9IǏa"IڵkelI 67nB/f.η8W s bZqcxѢr׹\f[ }ڤ,*o+W^|E^$M:vʖ .Gth⥱ٲm;F/_X_*I?>p% cWnܸVQӁ/BD823U*W:~K {iN|M;N=0I0 Ü`G 5l0s\&Eݼ4cveoOi/v -_/.GJ…1 X_re߁ukRsiwU\hC3V7_O^`4<},j[gA+y vҽ{>p`/MD,ڣ7u.{4xhf~jTר^Mȁ߮9]%i`_̯utK,V:$ޏ?)kUt/_a]MRCN.]ObЏ wSΤTҭ'^ؽ{c÷]~7jeº̚3AHȴf@dS,"eOu}8M6E o<|^:Ctrӂ"p.hEmHcZv]"'183~gg:YpٟpaYP\73gٴy}/>_~Ây֗O>a{|Ը!1Ǝx5,ҩf8ࠏ7_ҁ{oڼ cnjCAˠ1'MN2JO|>ix7S͘uthէ-jƘyJ+`wOsgNR57|c?j@iX^RPaLRaÕ(gSSR4;ڃO_F=ؔL>%9e7[NW…c1uiB.N S SN`%+W,O0a8;t ?qϩſ|ilc 4\E^$bZN`4椻>hڬai ҕHC+RSĄST<fZ#k6mJ-$ HSi-kO9jjdZ&g4!LIQɜ 872'nuG9rIJ4/ >˴L#iB*A583[⭱]!Mf#F[GLJ!dF]"ݪŴ i^ݽ{7s0a aJ$RNLe\\O.S,J0BlΟ>eW ӄ0Jx~ꡃ""T_JEp)%_J RH%.W0)(?$@$@@f%1K$@=0eHH yy$@$` ;[[c@QH̜z?IENDB`spyder-3.2.6/doc/images/onlinehelp.png0000664000175000017500000003457013003520702020500 0ustar carloscarlos00000000000000PNG  IHDRdD cHRMz&u0`:pQ<bKGD9IDATx Ϲ9In^z&"/U  hbq5TEYD%|]%+oYy|ʲ {kf{zzޯ|TTuշ*  |#$5AaĒ  K ȍXٿuI0N  )6R$jԬ%j%Agb˰RƄjII/YA >QNX ut˔ԃYnrwR}?$gX{AD}JaX[,5]:!K"bfUTO=by7)mAv%k2E. OX:ە>:o(\57D./AAʞV;ѳML,MdgĒ HXSƽgiX YM$ 2& φmr?:X@ fxADbb',b/$AD~bIA+AXAD!%AA~\2A AXAbIA%AA AXAbIA%AA AA AXAbI`C %AŲ 7jժg}zܹ=bY`byymKHY4ǍIG_O>5ƍ9Ka,X`AeCCh֯>]1Cj )&rhCKȭX&s[\3&O:y_^zMPF;{|aS(}k$"}!6Λ7/b~芏~٘<)QıRO 籋/^}=zO<}.!u%bIy bNyj#{#q̈́?(lJo[|xAQN?L2K׻'9sjjj^xᅵk׾h/,7l 4b{×4?Vv>ֶ 5"e888bJ׌?q-yt믽=?*//ok$c=6a?ׯ_?vؿu3.,DVXE/{Dݦ;ٳGZggg{{NjlLdE,O;]]ly3۵llІy6>u#׼*d_}ʕ#Ox?AjF򝺆3=='UQ,GGMR)Ǎ?qO=ċ/zsuo #bAn݊+:cFEWUU=0fÆl^z)H:CP%P\A, HŲ5@KѦMqzWW߿߾}B&N!zZ %vӐk /ݳrP<W^}bzT,7llp?czǏwA Gyww47GsԴ6mڔh^QλK/쏃N4zߎ3l#G]F\ erGg’ӿ?bX%/{h%X.J=Bf~Lg&YO]_jfӽxxWutz|9߼q؏iN6-QBDEPG!-px`Wk`󍅟}#mz'|ivYkܚnxlUwY]VdHM)R$+.Cd-qL<|E_|!_[W?^?tÍA-v3wK!f~"DыHc=g{+@w]Dpݏ;I,3 G5N u:\3pEÆu萧F3 ~o>l0xSL=b07ވHD_HY,xXe!3ό-an sȴ_LYGTWQ+V^s3M-o@ mѝ[Ej"MrÉ㊣0nc~yMU美|}s߾w~юEw޲G'ZwǎwIW7hࠟuV~sGu쩧 K>X5'RW-^in)FJIEo (+_=KŲG=Eg9~O!|zྮ.[_u] l'V9yn+ʫ+ƦX7cF♏ܿqagOSLӽ9c 1ACQ)or-SNMX͇M L _~qæ:ș;k s>7oӄW4Ğop_/tv"pD_KG!,7#wxogہ_r3f=U }Ҳ}ĉb`6`#G8zc]0tK/=?}#<S=1r7$C<>}ד>zre'75BA3rˮiC^OnŤk#![oq$Ļ"oxKӼ|r[{oܺkOyLr즲-jPً{Ko_{AY=gvn~SG6#sx!^B= r(;qx!\wuQ)MsR[U;636-\Uj]ӺuMnk=rg햦Monl|cc8HS,GGM nA[Ύ]v_SƋuhmqS i6숳[Ι} voEw^付%$f͘{3ymw_ԊeWð֮Ic-*a-ao_RK0,QbA -Ayݛ7ݳf]+ǭ0̳ή J(dwHc"uO8oc?i{&~w#4߾RܳΟ?B/s#k֬/W"exht )ӗ5˽t)3Oտ_~I-Wr剶B/"KDB)?WR6%x]GٞF[,ߚld1.Tp{6ŏyU' _Xl\ޥݍXD bP,6~4/##iNts6& DxUJo!Ŋ:>H!|Uʦ-ּmL +R^^kg$XvʠS.8./Lp٨QX6@S[[!CSI-EwFzj*>fU̬6;sv$Do2BMK")̟ Ē r1y#B?0KĒ 'hK @, $ Ē  K  K @, "[bں`i SϚC,>wܨ%b %'b@\mܥ>bOJT,ӋX@R˽Rh^%K(ulC(eVwY,'oC|rG$C J],%@,Q;<[K(uܰa  X K@,2%۶mkbJT,ETVV>/̙܌X@)X${]-Er;>bgJt6~!ٖb6mz=|r׮]F2X"XRUIKor% ,Yгg @%b E"΢BXKXkò lϒaX@,cbm۶x!A,DrϞ=ŋ͛'vF,IJmO$;:::;;u CXbXbX %@ɈeGm.;=clzX9|윷vTpt-_g}(bm["q/,h~M/qg/b eJZl|A,KLywፑ-% 'Fͻv.{XRY"ߊKpn"'weUaCy6wvy>ks}W]Xy.eR-h}>CY02?{J$x(P%Go4g!Y_AuDL,#W'є#_kjXa_@,|({Vl7ѶۺfnXӾ'gla}ӱO/\%e }akWGR|"X낋O>(@,L,ݥV8,]ktR6剋ezג%OH_XAo/oK[#۪).Xc0ly"ѝNUbˆXƾ~ ӕ3Tbiηc5biHK|мdbҀhkgi=ah{2eD^OE,“ Ptb!ީ.g3b螥5]Kq r3=Kߝ.ow] XzGDfX^iRhIv67K"z47}_l8}PKyOC{!X{2b9K";G<3cMOMV9Kׯ= ̋ `J@<d'(aXD,L\, @,K$D,D,D,K˖K@,K@,K@,K@,K@,K@,KpծO,v}d 8_%>qK_ JY,k_u Ups͜XR-u"ٞf 1 K+d|]=]K#[nX yӳlm󊟩7鼎[ﭵv^A,Dm[S[6poZee@=˄ҧguSˎF#v}UY5Jn:PJtO giuª9hR{3u{//%us# ojd:ƖYd#bNP|J [ϧT,-Qeze2d2k{|RCdv%~bn=Kkh&2~ %>Glv9≥m^K^,z6ٰ=ۻwVd6,b X"X"X"X"E(jj@,K2IJ&>֞|UN㐩"@XXj$s%->)~8'9byl(k Z*ֽe5L3䨦"X b8yXS 9" v絫 O XFxNXYUIUm-m-UoWGۊ ׹UU@,*H!!ЋԳt G_@*ECW EFo8z.?VCU"+MV)/\j\!Kw]wSe&˥5a쌝E,SpG0jB[X`3XfY,}aƑa4+nYuAܞt0XJF{)2Y,bXfO,΅pxFCh󐪝iKinRl&mdxb#X*H dOFa;UmE-B,Yx њb'bY_g29OPq!{KzX"X"X"%bv#ee%m7X*x,sUR:mًaB65޲# V EWP.dX&k[>Yj+h 7miTCp"vi+EWp.Ϫ*bY61Z>A[j CX2hbh$'/& ]x ɋjpO >O֠HIi< kb-ALI,7OaXMA[p2bi2~Rҳ]@J,v XF|)|Bi J0ê5.)rV[e!& ,Js/pBB,Kۢ" b,e$+JAelHr}ZczbI#Wkא˛BQ>:2aXY^ WR-8vQ V 䍽TdJZ-2)豭]Z܋k4f)K |5m$pg,bјTG89[ڟLKt.ktGce!ײ?TBٞF?O#uV \MuZtYMLY-J0|Q׆UN ͈KEX$BTfM̹XME TZ**:cX"5Cg0&')Ma ILi4&[EoKEX&z4G2LُW&z 9I1' -t'|\]^o5ҳԴTVagfdV W@,jхMMJ$fMDgD,D,D,D,,^בD,l_KNC E *KJ`XXR W,);22]‹~[ʺ0$ Vܒ4Ts{$Y/b}Ț>zSh5 CsPrC@2b kѵ~/SKK$!5i.ݚ۳pES)LjNb%by@,s:bHKZx)Zjh%!>ub1V YD/ b;T\U%ԏ8ezox7TͼLD,ˢ}cp#w1O5Z'/a4 kvISM0*n3/M0YDQ:%bY]ҝgv >!Ø-'HyurzK/$4ð4 >iKˬ<̕(A̮E7CU"brwX"X"X"X"%CX-=;Ħ_>? &_%bY*bIdQ,}YIJD.eu_¦EyZ+Q,{*{ !c]I³apa9#*mty3a|i>H#A%FhgLttFEv U "&8tZS-gim1YfX'lHq*0v^9=vn35ݪ:;@,yTA?W@#ER:fptҸˇZ2drB: OvI5SMZ2-b4rKiJf2VdKᮚɊXKbX&7\ 2 R8Lq>&5aX)"0{U-&ӞʐɩÚؙ5|un"e >NkmIv6:K]A8foZL=*tMݎu >NfjA\K2-pNCu(Kyiȴt)~.? Z)L@,KȈX& gJ攐 ^t)\$jXb*Jdkm o3qig]yjEڵDL)Qp軂$;:9Vߴµmt 4폿X˥EK 6Ytmh-CXIW0. P:% 4_)NK׊wn+(͙Y!_xeJYUܒJxbȖEC 7aW(uJbuTnXC;e@,,ݹjҵ?v""B,K"XZZi V=% ^,]ŒarK)Xp6]>FHN,=Mawh4q2]DAJʗ5qFbu} >LNB{_t5xblXtQ i5{2Bq1' 2'S'a-^KX&HJ1R,\i| NXv[!MXE8ES(]dW X % % % % g:8y> QW*zA,K̗F(JW,sh%Iy(EAeG'- tַuyr!=TA, ܢ˵]UfI4nVwyVj]t_Tꅿo֞ސ,f-񙧂 GƢK '3>DG\  SA}- :DG_ʊ.po:l12bn.AcѥZj?"2ҧˌIf"A̼ >ܔ.q4KE,S&4baX SQuf^XaO-bYŚ`y#)NgR@.2|B0N>f^X` %hUr8!KDXĒב4<i')+N*yPuݧ ? >mgE[IJT20avVb i:} R XtۢK= ؕ9Sث)fnD^'M@wKV\q\""ۃW N5+˂芬"1|}< (m_nDZ/Bi9T[ b.o* ל%~˂R4 {y֍ӍQ]34Ƿy[WZ D&$ƫj@,3/rBO?ʡn)!5biyĒd*bXEW|G3R|0Zj~?!kFaW  ZbbɢeZta u XtN/26XE:>9eI |A+"@, rQ!XtᡓB%W!D:ĒD,D,D,D,N桑fjA^풲R #$YOJkЇK'V.^9d8M'unMEm 0s6M֢K1 oM)"օ{HjuS]z"H?9Kh[y5DJJ2RVHvPϡKKs5@@,ע˥b[|-- iwI|<4b)ɳfi٢pQ@ZځXE̎x[VUMJ6Ztܣ o2_ &%eIJ-dw]FX2;K=Gor}+`I1+N\,ԻKjbY]Ce}.Ĕ|_.mSQ3:RK[KJ; M3XW0v i8GR>},y}+ђ&ys)?/W^P;K%2bYh]%aB­)zzP;KzX"X"X"%bX3 EWb|{tL z+P캸E?:\Tf&z:yזNm3;Q]e!& |JBü\hXEW܆!?@K g %b %b %b %b XBMeR;Kd0B,hegk]͍ke$tK~^QZMf0SsVjBQ}t^u^(0Gck@O{snJLKt$; V~ZlYo •QnK/ݚFE}!ศԵMe&rgX 2ܲ*eY1+-urNC>Fl4jkuLj_X%5Rj2S[-/Uέ%ISvUD,$>OHfNC)~0PN+z357YqEtbL2 '[K2W]z,1!1[0lNCF+8ð;e?~R1S+LpTK/ax'}2n) e|B7(`>'!N]ϽFi NML-0=٤B} db\'2=KðFlyRʊ%Fo%-Fh/=HyʚRHO{E 9j[4> m̛1q"_OtveI%ly~mki٢%nϽZH}_N;6-ܐ˽ `'H y_KvvE縷錄d`4U94uy}X?TT W3l-δ6=kmPn-- knfZSpP_:ba筺XUż^bi**ݢ޴E y@`דPs @wě;|#^zrλƅ@o6Z HyR^*s(;ofzySгYEc}) kkXWA_v䔗L_SuWǯz\D@  983wl8oe`b”˚1Xpay<嵠̻w#E֗Iv?Y|2z;O땸ee П_º.iZܛ6VcHyӃ<ⵔ(S>2~Q'??ޟ?GUnw΋ē(x9(@I&js6pɇL6Y/ 9A|} ^ :F=owMfvZ!?*zc.c73cbD^0.^mT4bb^wz^׆镑zC!.&{DaV\^NstUğ/UmFODI1zic /"bCظ~^᭏?7;#&xOL[wl~vGzʼn{ݟ?ԃ@3B)q 'zz\wy_^arC|;zBZZ(&bw8VKE| j}qW|Xxc&7썺wcAeO=C=:\u@(Yer+ɾ V]MTdbm-o'z'$/Kj0n]n}=؎hwdy,,<dJCoEE'>|^\i~ɴ3S zYAQ|+}fe_vW\ H71y EGoG^ 5hjxX&O&>=T|JF0}7(#>s8"'|#14OnJThq$=v~jjh⛛p'/උd kׄUBU9ʍx`U5$:[eel#ZU7ALkDSDD ɣp`^/'~6 G)&rJU~gdJkjV[+79;?};kq:o@6#^nׯ 64V\ voz >npk)onqT ! llTWWUC(!~s0{wQ@19&ɰo>qdIp3B񉓉I0Ӷ3&E99xG˶+;FC6p9 qAOAW~g~G~{>Rn'FI2vWh(AKAs!WbԞ{mf?pTWPMm;`= Vzw<`0O*hL5zpT':([#b砊w5M$f"XUUZu5rZsdܕnǕ;oaWU) ! -3+tI (<qT@h~xd*h2!<SO|B7FFv@+To'2 28_|z*+*nzN[/IJM;sJaUa_?4 c`'xE߰}PvT31,c服?! Sxwf,rZI{\ 3K2[hϳ>Zӧ^ttwpTwg+ٹjk#jikX [aZZaR46kh|'<.Vm^h:]eE1.Quw6TU!N!nVTlmUTnyN: >o3C!B \sVwDp_Ī޽*8ЇY_-3J,o"uLט.兵/3X_6vzmFzb}ػWQ^$;X oJi(/UćEjJd}y~Wټt8/ϨI{o.9 2p7=L}[7熆GRE83pddSb``O+55ֱCC0,29 !>@VJj|S6SwCΝmF&PCc%8#C aT[ 7M"A/pv_ ,u6!4 nlVUox6*6ڃ:[wE۷u04,w-K6}qll;%}7۝mm--+uuյ5jb$Z]l5`۳R^\VpJ˖+.7L_s{+*7< wRaJaS\`D0A]Av'98嫎U.b}x!/>7!pxdt\ xrc ~*(^*JaqJz ?؆ g8ߠqmT8+J܎rǺ _7+\[m&mq_`}`g"Nn6}+*slJ֜E+˥+ WE5WɆ>g[e2]z~+{p0Y^{9֫zͮ=zS7I3`}u_ JvfO?ýWk]I~ Gߺa/ZkXk\oZilZmjYoi_oly\pTuqpv O컷'lI}oݞzպ;;}*ػ 8AT%{UV"Z|U7T.-١YǥCklxsmyqv{byb{U,-e~ْp-.rVd_(vV/9K%+r- W? rV䒰Q@2xvl\(_˟ʞ̞Λɟ+Z(;u\ J;TlBaZ.M g/𔮺+@YUw.\EˮWjX pg1荒lYoJ/lTFf+?[JuL)Zv/s39 %9%{^]5]J WKпI7"Q a=%j S Xz#0~FrЫbW>5.Yc3OmmCOwN@Wo}~Zi} A87_X+Ko5ؒfVST׸غ>_-r7lIk66z9S\/Ooyfiyo:[nNO:ȅRof{x /UU/Vz**+]ҲYk9W V:WT:W>Wl-,)(/L V8[8W4[P4@X S sm_.+ ysY{6؜#gޑ]p,:r.ΗdϗŒ<\, WE{2y`lrKr`$P۞s.;W{bqlQd~2gTA u0}(c(l\PL[į/s}枀዁grwWι=ssUŚƥۻwx!|^^Zk筛X[zGTߝmp{z6`6R=Pl? O][7f ݾۻٱڲ7r|5k/).)اJ|ž"_^/XXTndNDvxfxfx13;;77m*7Xgٹ|_^t>7@b5N@`](r#8DCb~lf6 ~"5m2-s*#g:;6hr.2yr/)_)_gApjӉȯ ڳ|SiSEj*L,H*HMOffe/f/-eԌfOOm x g 3f 0bq .xXE~Xχ9"vu$hy7'%O5eLfC!Ýz7{ʳ\]iwL>HA/lH܊zb?~sj~ C>҈ bo@?nG\K,3pS܄ͧb.3u9Y{Y>*.z==p遰:{Z[jkj s @K.ޭΞ X߾Ҿ-ڱֵٳE-PPnOvGFK3P~6P]詜w]x W`ⳋ ' &`whzhZhj&ocYcY28̞ 6XLb0=g"+w2;@\:VCPe^/-[CK<+%̞LMH(˂ ہ/.|yHB -zzcUX;Ȟ.Θ(J+L+5Zpl$hr^#s}8h΍ܔԩx ;-|x0Of}60PH }N=x;R^ׯgY_oGz=<`YR u";mKawqo@>s09k(5gwF BZl;N|eYw ћƕNNx}wg޹hn_mk[mi[mn rcJcJcJS;~K{w{p+sj\744p3 [d]]]6:a\v{FS*q]"/ʗ9#?[\:]b/ @V@(??Q>=g4 (9*h gizƈe1F, |fGyWC@_*#ON|٬T.b3 "3vDy/sJH,{_,[wK D3]Oďο~7`烹 |6@w8t 볻Y#7Ʋo$Oܚ$pOc7Fg^|0;N'o`4x.8)4pg/ܧO%\{o~ݛ/=iK}Otpd0/ [2ĉOb6L'*X^>we O3|>NԬ[ĆS 厤f\|<n])rq@dq1U,O3eيor}ZsVGNWvDo:;a,:uim]Цf]o -+ k0ckݎU44RP>h vz{ 'C'`j .y<~7Ě <"ަsH&D'sp jҳeK% lβ&$=#stW@|dVt.P_ws<7r {KJ sr3 4?=; <(_pJIk }֜0δ*`vҠ+.bSQ K…\OG 9_|z';Y`>um΃>;Xa %`&b@P~Z|\a:c9׆>GP>(=q">;C 7%ʗy<"S>RkcV+~~bzS)Ý>NolY㙢eNp6S4[4W4_4]P2[d-!'V愿%P(_:]Z6WV1{kכZ]@V[Fs8 u}C` ˵d \&m|;];m-M k0 75ns+ѽݳݳݽٱֺԴPV[Z]\ x**Oq6 xFB9b\Uޝ .[ ޽K]16eG?7[i@9sCa$e$b2Q OTly;%>o'Oɿ>wn΃S`ջ֣MϽ5<o_~$g#Co"S|&kfNwɄ ߉)zEo2Gl/*Gfg=5AB3z5b)Y 'ݏ3b$ABdhńs%Ds !휆nLr/=ʪ @nmiMyjm\_JmrMJMr5چچu67m5mu`͆5׸7[Ɋ`PG^gAWƠu 2pB博ҳVU C+*Wܕ+er@;(l /q-;a$@Y< Ea>)p9 `;]$!ӭ:OB҂rvYsW]e`Np!nS #m_P=@Z ϻqM-Z;A<\65B~0%7VtG_#mĩwdMO&uby7FnnAD~:?!(Ol3 ӃAᜫ|P~47'3|,zͅ6K0@yI,, W.Y> P1C0wKۅ6g?q'Ggd7{ hwO ?4{ Fol0T|͛?l .E0*_+s?gdlZ(+W]1S9[5G,{3289)HGCra`L$Q@7 /- 8afql̖-(L,n3͍{916 ӫoKV!z>"F#ޘ~J?j4mUxJzs <+j >TxCe*j /0|y% w~c0dB?x۽E8N~t%d/' :C"n7L$$[R$Iz1 { <|%+E{~g€RiRipH| r Hbd(SY]3A j+ZeՎW*Spf>'q}O "FGP4M~eOU ^ÿ% U\@/e_#^2ީ?" m8W+8ܗAڃMԯ@lTMTs#.ހ u!?QçC  `A}:?YYZW˅W7 zS~֣SX9ĉvmx0pyElÕG#ׇJ{&ι&̹/׿\'[hM>0×_E~|rm/VWmEGV---g [Z, LY^e҄eޖ\Vү`K$[ZzllAׇE$Y\xHlPf= /8/؂9Sbi 4fphqPn S g wΆ,&!QwYdq Ž)OKkk_}M3?o3m (7hDU Z,-y׈IӚ^*/P(*FCAi8OBP(@N=RB]u}+'CW(RB_pY y RõաtوGPǂx_k'_^ުx 荅Dl} :#OQA+_r?aHy z^$< B=aWWx_>fǸ< B#EoQ=ПR\ؠP(YOc׈GPG (A1hC7AP [ikK^yΟ&tn=P(T/u~ԠOz# i(xX~{; eu(@J恿f1zC>ͺ{n\@@_jEr15S7jVq~e`}/ʣwnuQg򫫐޶\9^+%; | Z,jƙ ^HyO}Xw."uu8/rCh}!]ഖS\vk}.CU`ŋJjWJGQQ n"d`9+a4KWKx6EXVTfۮjXaAq#aPPʪAZe/>LB/{* qiel/Z""zxQU&ȫE6%ͷ}MЙYU!f0UCQj _45 S~*poz^Yx3y +7PGU U2˦ h0//omԴzsnfk;t Q'V|~T<11`.\7aO|3o^|>!y j8|:ʋCz 4qyf9 kf4jZ{sʛ!R{43틜V 3nT~b yE* #jGFyJi^1u(j(5qgBDFՊ#V1)I s ^{džye½j…y׸ؔW56+.0ia"Z9P,QQ^SpԛN6]{b"6PFl>vo=,lw8gҋgFa.ՎU"BPO#m|Ηa/˲LЛ+)+~em( u^|-7w|}k{W{Bj_(QF<₩?F(qZxk{}w B xQKOzt\7Q7a{_W~z9)Q(IKbxr_^":r\`S |¿v3Lcx"BP0KLGyK/? y55ajvJʏmɏE9cObD&8Fd Þ؄?gΆ򿉄?cPJkǨN+z(&H W˫z_ tR(\  SR>q}!Nx @x+Q>{"|B詝z_B׮y7.ݛ'UOL)KO+f`uh 4lYb}yP45zE2WAs̅B(3]PHBj >H[oQ(J76fΈjvd]l>hrF+w A?}TظRR -Uhc,o]V^vԭN&~`m(a6fQ5UZz}džzՋgPO$+@p2<`@y_0׏r1ϟ4ƟtE(oW ]t e@K \(Uf*YExYq&՝kNk蔦S:Gj*t=7j"]gPO0,ω:}ςd$ <mGmx 1T@KoRz)4ѩ͎_S٥SgH)/.Mg:0p00}qS"^16--O@c̠)**?_xŗp/P(c=A|ݗ_]BP\F8߮ؼBPgza4>΋WS>peBУǶUpNJፀW-"( us EG]C]Q( e%L Q(ʪW( WW<( e!mjD{P(*?\Yml Q( )BP'k0^BC^>kHy fؠP(~**H{Hy (Vm^6 BYkkU?wQP(ʂ_v{O^~B,#/A[t/s26 BY;f~El so]|B,H=e '=:,,)BvS~L*~K|dtUhUX=F@W-|ˀG7_{M僼/`#)ONmln#)6EDSTI_ &Ie)s| 5(R.b'H{* hn;<  0jOEE¥!Bsxy< σEB! d0= _1Ah )cl6Ü( eIʯ؝'s _B,Hy,MϾ{l H~3yS\BPϿBP^umj[_FAP( Rvxyl !b3͝1< BY~< BY_CxYˣP()?v#-86sQP(R_Z:MfO޹7חrB**ލ) Tn5{ٟl(|NoǗ_ u!)Iw̎=@cfJt-xA>[S'~9~Ŏ9 汑˜N|<*mщ?N?S~Yva}P>%IWr ?eO%0㊅94P`~QB[{xaE5hohK1ڄ oOo۵mdo{ .3WG5g~8U83Ǥ6[⬆na\a///r$X×H\~'DžwwxU叨JFAa ')~;jE9,Q5,n&SQ)vvxrRWg+ZVq+_1^?k(C_>s`W0b>Iz#YDl{6W_YDZ|)^^Ju؅fͪYFUM|:[LoHb;ڍR-eA vf(04̇oUې(j+5^ãK8@sG0Ya%!c٣KyGaИUdžb $߹KNEyR&㧧6`^Y2OymktcByg/BH*Y/55ny(Bh< s y9x 6FiX<%֩is{=U^0*~_-[/e# BśY)8;{sIȓU靨 Ӓ1r-PuLTQK1Ky<ꅏkP"`(T<\Z:_~:-{z<% !+2G6F126A^ir{Z ):Kʏ~ %7`PD7wxs 8T B%?34vn)BPݏn Q(ʲ4ywdg_FAP( R~z*c%l }Y0^%l g_g~|el Wf-B7]޷VNJ B "b( uI[Q(\R~ )BPHy B=a?{#Q(z?++m{Hy (<[}clP(Brb)BPHy B=Ǹ< BYW?%fkN>eTtWӐD֑X|n5j_/>}+ u8LW[L0.No~W.5F¶ɿ$5ȶq/X Nye}|a *zeLMsr"T "3ඇ?ϲO_y?7sK'eLS`,zܰgo"1~G~˛Gq([o`ꏲYԴ4קMYʥLS^GȉYSjc{)e)[U~( gV:-Gńע Sdg%/NUEi$${wWJ :*+/+FDUɌYs/yjw +q%\Y%DuI]GuSF ZCT`Pkj[نY/'%+b8QoT_!$hҢ'pv)lEɔˡޯ(*OoRh7Y sh8U2v^e~0>aߧajnQߧAv `\V=0.k7Ey6Έ&*`Ft(+鯪5ʃ< >gV!CI(Ƌ&ᣡhO=5hU|xf˯GRXbKoR;SFL4[(A0xB&*! m9iA=%,HSaVz[}$ufV Ra$vݼ%b\PS& }KA&w~2iW8|VoKqFCPYY{_MDl z$Y>XJjnQm nLUgb]t֪̓qòoTEICO Eqź2<Y2}ezԨ/]r 6G|V=dO~k B=A| (Hy eAʏ|xQP(ʂ,982GP(:a#bXr`0*Hp( P~Zjptg_h4wƪ"g8_OKq?O$3}6 .n˙]18gD䌽񩷟d5+],*<<8)oX9A<';O[D&(s=~KVڼ$j $f2ɡhΑ6KGŤM (׉~>2F2U{N͓~^FFbJyu]GI(N6l*=]*Y_~JwQHHY&g,3BU7SM'#3PD?k<{aQЬ!HDByu-fI XGKx֖-ң~Ykv0)̉>ςDfT80b#embr3a\g(iC ܨ k/b{;DC&qpu E"?gOyrq}kԉذÝj{%N2O&:C啍vӚ>.Q\>216!dx6,7">gO oX~yzq~;d-EIdDymf(Z;ڀQ2_'Y(0DAً"rm.YAd/UOi'$݉~Hv㙵gN㣋vYU8'~u%(w)h pWy,yv'*PTJf\0넖0CىN2vt鄒Vz*Û mFIyjj2meKwp$uT~4N0G?AL]*E"Ȥ;BO%x9IPƔr(rJo=U~gf#"cacG4M&zE/&?ccbT^8,>WO#G@[xd-8SRq$sXQRbJR.f*CTPtRI Duٲ EZ%O0TbF N eo69F{W[5v&>,K?<(Ko@긼z_tFIHq^̨;9*w3aR*Ql~,;ePR*En)ݬRS̥3xRհ^iS"7,VHz֢-_'i92sIp(hԔ؄ذ}l 1 P!21'QaQPZl 0M)OBd򜍦i͑cF\V/Z ShnG"M|T zVc3k2Y+Crg4cQdұ3<#kUkLi-n ʯ;\/2@]Jv0F8Gv)KLf4N?[5Yd@Y RI%뇨3ہ9ڻs|ӨE bYZ~x JP’㙹w/33('Vx$h/?UpyelNz7}EYy,-?=})B,H顱ɷ.BPՔk\!x 5u?<:ڣNh[Lkuqpck]h=_7xw74>}hW f`rEqD|/ԗ?-Μ"1~GU8ڸ/_Ը2i| R^I C#م@`emzf~fv~ޣlP? Sy&.tr7h֥< f0儣S|a^\5պ8fPt&Q:1|S^kLؠ'=W{HgxD󑺳iV$2\6QExI:MG?kZ5g(&]V8mπHʐ7"6<ۻkcH<8LRLKh:zg/ʓfƵb_-$Mb_s()OIJx2'iSjc{ #ljާ: ŷSRRtUPt;F3Ѫ'E:%Pjx~%ʚ3Bzc|P#cQm-r^bhko?88X؀)@{? S<R8b\!\m$h3(V.V61qGH^Y؆Ih5?&#)p%N~yi$ɽM;::~HJu/̷^Xͪhn@qAIҋer[+[:S}Q*jskSv/+M~EP.U)֓@Sd6`If͸UczS4Yxb((,9{+ R3x hn;<  0JOEPV[L$q]m>7ΥˉS9``LNѓ3P(|4dO~Eܭ( e)?~#=46QP(j|xQP(ʂ,982GP(B_B,Kkщ7Ÿ< BY{So?w B,Hٌ܃w.BP?hfǗ_FAP( R~L<6( 1IN#'% BbL oIG R|mը~YU 1ܭڢI|獀3S~J#3^0s8%?4ʘc.֖=)GQBM3 WRRZc:Hٮ8U WD[pDoP珺${:5GpJPrY]@dj+jkj| )(2]Rp)U FNw9 RB,Z7>qmKm(ڑ]m")L6l6N1ۊd)D: )7ʓ[DIy`ަ>UegK=ɸ lS W8b#;'$'(ђm\Qo "ԍC i]Ok aEԦ/)[|&a#̥m"U5hm(54vv1dG R>JՁ@xiOE?*>e}|fLH| P(rc`{m*P9ڹ WOa65u"5V(m: 춉zm?aU(2Ǎv mPkR?\ ((o0QA֜((7L(hj!@ã^omnj~=zvbt_}t|( ouk +8):eUJaQɪݽʚQ#R^!ۨy;|k^@q; Fl"{H$l#uNR^RJYxGNa!+Xd+P^6^aCKkoi=Nۦ7A#)dKH=B#XIgܘX>m+RVT}eP^z6JK,ͧlNyh  IPIG<-^jʮ!)YǕaZ34r0P^犎7-GE#ӼjM4EQ?cIh\yd|"Be(o16( (oɸ< B!J#?d+Ü( eT}݁ }Ul {Շ~Si[w[D};(( e;߹*-M(Y I Rq]9=JAjOR)RG)H96צM%V[%^} vI_ɏ @tKTNg͓Q|vKSQ4HyۛLM^K 鋖ھMNů/\FOA_Gv׶0bԸT*H48:YTS:eɲ|_^YMR^W,.ZBdPh6_] {c lvUdqMՙ٧k巌L-YF0N2>lpl|Fm|YkmxJ _6p}Yvqe8c-Y&FHyz:,8m=P9 ehZʻN}U^<RMjh{_ }AMSUA?}ۡ.}Hop`jj63۶\h?K/cVӋBPgtx6K/pE`B\I|@nyE{bNJ [d)wB/-( e%{W <䖷|~y|HB*N  A4WDRb\?~zS]QKܻKRI>jcK>Y]`Xe2\F&NMô:?T{6rqkkmnE ώO3|ɌN)8_./6]{I߱m(eej4wٚ $Uʼn_26AZ+h'zHks{n#yiH-4vi3M'@tL!\J:yL1 f &d&-`Jn m/X$` vV>~7ٳWޢZUf5s,͈^4XzDyKRF sYƆӜ)aOS0cuC5([3xyMK?48,fDU~τ)<śIud8ZV"~ڣ5Ml词EJع0\i_0ɥi,9eM@u_mu6cM)0@C1P X}I_Yp$T̙'{}?~#Bk|BIIӯd|hfQ@]N٨bmUꦰ_ 6B%X3i f,:KO+Y4bQ;'Owl}86qJGk2) 5'%;">L͡T"6Ι2,@[?G0o*lZaĺ%i>U5mWNW&ޯ)8ep &KV*o-&3Xr3aʧ/@s1ϙʛi:i\*Ow_ۏeጀ@fw_u*&z:֤\UG_$'3ރJ12Wlwg`EmQr7Vp.pV\Քag4T]Wu':ڃ G*O/n%kpuiPyyptWt'T^AqPCӓw8( w_*ķ~8TpPh1oZD+T^IIԊ1)?Dah|-cRyUQb_JKZ#-h7mhǔUeܾy]aEݳ*sq&/ޕ܊l\YW[@^ J;*і1eYq2F;lԠą<ZUj.ܪ4kKZ8j/WuHXbϩHF]ƦWFC.& $~f~U|P$r֕%ʫWd {oE oE[/Y$IUK;̢ciWyoT^aWy=ZzQɺjg3 `i,MuY[H+PyCW rDV 8hGeSZݖR֨I[1kR c \,Ts5qe-4wR9$TaLJs51>MW-s*@dU>"<}>U^{TfAn UMM M)<pBQTy Qy+DU1.2}} ytzJ.a y~~a yĤ4./<=gʃL哢g@GkQyFG-(:T|ģܜ_<"T^$$%޽{C//%9˾ 0{!'FG阌a yD~YNSyz3j*21 /ACfC>|!/KCt4x#EŷyyaW#X *?8$k7iG&|U#6T~)%u{[S*yJ\y%*b\6Z/ퟘa]+H-lI,Jή9E%['zceCc%b  R;Ⱦʇ[[qNNq: k[/)斊5o9D[Rl$%TdG"ToOOҬ_TmKTH/Wy)@)Ugُzgzfn296]x]abB8gǷW,5{0#<P>S^ _#e|xszw#_#߷{0ޫ7?[Y%Տuw_@>|~mϿsT8Ruvv]jG}DU>@*bk1.Z|_4G*T}JT;GJ( `|XC*+z͋u-OFfچLОѱa,ԑy96_\TIjyKdΦG&a*&}~`bw5[U\3`%z.[k$ e@Ed,e6ꅱ1 IENDB`spyder-3.2.6/doc/images/findinfiles.png0000664000175000017500000004737413003520702020643 0ustar carloscarlos00000000000000PNG  IHDRL5*M2 cHRMz&u0`:pQ<bKGDNIDATx pG؈؍؝ݍۈgwKј!0F`es 8d!qHBNcuUwUVU}EӴ*}_fyė'fđ1P_ @}]QձcV׵tG E.+)%3RE}E\L}P0˼荨\ JnE1vmf9CY}X/kZ lQHu<;Ȯ=zz@A>cZ2,U_~l}^QA ,B}]>Yb7ܽf͚޻w/[\Z4$ sx`2Ν[]]k׮Ah,IۥVfuU Ґݭ[vj@j}xRSNmشiu^^AK/\vmٲ%ݺ;v8q"qGk-!8WI'yUUնmP+Џ 6P;e NJ rnnu~6d*ScrO Cje)ɬ9Uj e|LGp)Ek?©XܶA -W_2ot7zjK/_im}{{͛V3Nrdm,ޙ3gyyy4{6mZv-^vm޽$ÔcSGZp,Fn5r^zz^jJSX .+_u?Zfˣ뒱<\}UIj2|Doȿ3P_frݥzSOqkx}.\x{9r[w~NNNTܹs'~qӗkoTȒW9Δ)S%^ƍ$o6Raeɒ%K.d/0|ѢQ_ǟ@CzfӟƺyY4s||)0O1H4~tSV=T)jXL7R}=6\)^y*ȕ l'][tmۊHk7_ -+/',`>zd+2kg VeN^<lʗG9O>dnw_ !ޙ8qIC萇… -:|-=zɓ%0D<.hC~mNik1T2hTWz$ NJ<'!sCu@oSzDKc/\8qT\v=??Xq&y'746^;qO6j;doIFҟ&2s޴Dl:4ƙ3gk}_zٗ51}%^6Wߎ :~9`aGt58/7 t Cn۳9; =qǺuJ78)(A̮m_ ŗ.Q$\K%gٳ7m*#G+=UUS6c0K_ww; wM{IS54T^Ģ`z݈xf76'9ϰF]'鼴nTS&n$US#k[+ulXܶAJeu޽wŖeꚚ'n\sTCyw9*#sYNIWu޸qS.ÇUi]5kuҟ4lb%sFF}6V9+uզ` Kw<|x3grgUI PG|Ozk8!~)p'" ha"%#΢>}]z9/ {MAS\\Ddd-҄ĂEsGOHK{Ǐݞ$Z,`ۥ:qX4F M @}ԗ:twzjRz?ƪsi?3דR.u~/? ?S4LOulP_p͍.l8ٞZDWǥ#GP$zYROh0w+P@ J3(p/U_K#~lUJ M{Q_H(;MPLҳgφ!4K[A}xbΟ?w{P_ /5i/ԘN.SH|qZ\I9tT5eTDLeui ZH ilM!p\|B}p{={L1gV\jժ@}H ¸P7n޹{w͚5>wTZY;fUF3H <]ϧNڰin-(XrŖK׮_# Vnݎ;N8}ڐݭ[vC4DW&~ ZĶ I1 = p=a\CzG66]x ^tWZ[o߹s޽~ys:5pqj- 3E , }_P_О秞zOO .l<\W_TUup=9W_-ܻ?'''zzFSah[&Fɋy.+ ջ?9[8/dXv]J (u/HSAaS<]ϫrsN:m[]5/e\V^NLM YWV]׍6J2fϞiS!u9zFm篣4@Uչ5E} yժ|\ϧM 4kjE23/]L K)ݖl'd&P48=/HYD2:޻bK2zxuM͉MM 7o9yMruC4SH.+sI 5;-ו PD{A1MNeI:dZL]DlK,6(8(M$g}Hɮj^?… :]ƪ[ʫ=~S hn^#=ݻkkk~n-˯L~>^ 'BeZ(覃F $EuP]vR ٻ"Rv\<"gyqeHy['cq(~{}lR}ݙiءvK4M=w-ăHʾ!n[aHlun ȋlC] ՗ O+stUe6d3S)V| kˀc+qqgRDQn bJJm_u`1aq-]U>̱(&/-s;S_sx3+f[=5ϔ lވ4 !,Br7ڌ{#3U&uܹs8=B%P9Y9v0'Ls '/S.Ur]cwLV/I+3<8>RDI!ppM_jm*p0"dff&IG1rzV`<.@'gk G}3Ճ6E<«zAogC>i>9^aDS%lRܨQӺ[ۻϹrblè.U;`U_/'Ȳ=Uƽ:E4fqg֫Wy-1*YPm7 rcV魓 cz#R_QWDP=b5ڇ^.bǰzIz=T%S% 5t{XxǬ(?ɻ9y(xLBV)-ey9J2evD5!v(7Wߜ/ .\LgX^:,Xv$ y̳jUH\[շy0~SgL|訯C*xM#Ẳ@vUx_ˤC[租~|_3˵gP3&b5ڇ륗D>ր!G%!gŏ6= T*#@&@4a`k*,Ms Rm:-%u Q'{Z{n(šw|ܓյt?s`>E,q{-߆ۙyNh̹jM&CMrb.'}h3iLtǓ3n/,윴oTrx(&n9%ƧؼP_/Khngܾt!b8czz#TO;Lư 2&wOݦiNRk9 7zKh[ ќm2`g|LJFm#ўiD6P_j / R/P_@}/ @} HR[nד䕔;}@Dx⺺:2C}ill6Ws ]v#3t錝SJ3ڻwK$kO>?2=CjN +g!cK)P_Z}oy[.#M=3#w =#m5/W<;ԷθW~o+}'[k^3__zዿ/t񢾡ݩaϳ* 9z m6777Q)%`OsI_ݾRs_o~3W B}/1o޼.;wիWfl ""諯*S\\\*@(?" csܗ!/)樫BС M:ĉ4UMMM[u^׹|r. q'Oj@Jy6 l_o޼7?_>w9o m_^]sc޽$v5dw5SbdK {gAWzm g$O9׻v_A#iÙ^ݻO<92kQسVFeOsPߨG6'M3vƞ)FIa# ,DX/DJ 塜8$x3+2O77QHZ Q_/UۤF ;%M^{D]Mؾ Է_ᛆ:t?)`Y?nA{eK5gk}>qm(Fj3}7ѧ'IoVQ[>aؾ+[뷢ϯeNxoD}.m߅^G]YzV㶍yh7N;a.K쿪GY㤾ҵcCSDlzU߷׾FnOK&5Vz ^u,ysqR߶ l+ 'j F.,/ؾ\^~}o^ׯWvY;xSֳqR6 ̅Uܗ?PLS78jx)W4}E}46ra4`&el`ol3pضېé }[}46-X  + |kr+RO}ySd6 u}Meq9U/cB{ꛊ!60 z7}a۶m۷o/)))---++۹sݻi5d(>o;R_}Xt^jpͮ:4% Çkl`L/YmWi0i3cyϧOB6][1A `12LNJ !W>(l_" pEjPԒgƮ}vҎþ$z{پ^cDW4؊l_jJ]./ Wv%vimZX'4󋑉 $P_,E|H%560-=tю4F`ڥ7ۢ!7:ɭ^&Qo oOoP_KCCS$uuu[LgzԔ~Gk|Y;vtP,;@/9haVq>4e\Wׯ)LhW`*qP_t@/ mķz+>m/b D{-<rW"O1}A˽4 ;[#7mhjqXړҔ[ 3`V8X}CtiڑiUUnTz5)3φ5_ eK~xk?aV}eeږg "9m +N,K}\WC/ܽ{R|x@}^}-SMV: ,HSfO?y.9]6$-vk m:[rAbC6dNUT+l !RTVI6Z}] >g%9]ٷY<+$ I~_IkH>B cRL"lu(i~_986&=dt|R!u*IKϳ⬱6ePжr7m_5-5/-xiU*:6βaڲ\}gWmy lFH}# :-<cEWr"NPq7|a!ΌH}*8+ol_Ue*IC;Fgs7 tΣoBtl_/@}Sew5C%iT3پԂp4=&m}fL޳#s:}0i]O:@W߆WkM(FўޏbH91dPr&{_^%qu$_tы/L-yfgG-8΃wB ӳGWڮ Mϳ08;3, 7ql_j'R*Foyy9 u6q: _Pz]cj~6|Pͦ圥P]/@}uٻF2VWW;T&0ny4/wkiW՚_v׎wVsGM5B|0/'șLҠ*PI[KMmۣ]>_@{v KZMg'ƅĈBSIpV!]M$ۗ&*..޲ef­[:T:tv5b`ڥ7B*F墟JF]& PM}I)L~Gk|Y;v`gT"Mع\~z|c2@;vVv~q/|3zTTTn:aLzEI 3}I/>Zr5k mf:u7o|'7lx\n@7El_lߤ}w,->yNϴrUq?bDcԴr;^ ŵ"Ӕ<}aX14kujZǸ̔|7QX]̹|szf/]ت=/v̪YYio4n`|4MPز[C8P\TdkH}8l_ؾ&voF//[X-V!fO⫸7d4TS1s|.8»9mgklW[n+Fm0au4m˴cE3Wv#aOnr-.RfڊT{HȬþgh-i ͬa-gi?OY<*8*P>˷\l!~ ,w  7vPM!N%Sn?Ok'$2wҎ. mW#ݟ79p^5͜}]DreWt>96gO(B[B}O*^Mwc+'3CڞH58RvC}au[ZZJ ]/VWXW+8٨ QWsL:]oZnZ.svEL[ZGpӕoFD5:&W{ɴ,/E yF:7r:pEB[H<ϓp]_^(S#=l_˰uWH7,K4=4Ԑ4; כ8/溂&榥|F24;y1o| 7} @}ajڃ?RXR/,c ZL7uX03xۻޞ|yC_9N D:I)6h.eQ1&&+<`H+"t_Efr2-*7AΥX'W@TE5alX텙XC忐l_qpݭ;jZkzl1eɸ1q܄ }vVkv]L )qpv-_~|49,rϰ|rRi5^ b /: h{"Lg cSvK]-󍤑eVuf:6+W$+rurV|}~g8tԕl8MX )~DZgWzr*ϳMqօ]Ȫ*<>N<"oپ*jZj^ZҪUtlP+܌xG#V.9=c rJFf_,d\(a/ue++:-@ƦlGfZ q;ymY--n޽yPL ?Z?^wMu@}/ld)///l_P_ؾR. 9o [6^B5_)7"gNB;75j|_}|k2a{n{ojjh9:1C7lh533 Y}e15w}fN,#B}"*}Wq4%x?d졓 Vl̦e- :RSo9f/W\0./[O{oP~Bboؾqd$& /*l)o_]'DnFn{X_Yy==}BNoL}<G+7Y^Uőn$*xB'*oHNBh5 ҄AZED'A}7&`PȩrϺ_Hi.<:TUu;>ZiֿOmSq(w& ߏHk?sI r8kjwg>v `ƌΝ7U՗݁G:Q_v5SkT1ܧ|ֿ;2' >d+e 0[𙶿mKs/ȍ7 aVZ8ZL9Y2EWUQ39Ř: cOةtU] {>UСC5¾F>= 7֭[dﶶRWWW;D#$,uZ3O "nA}P0 o/'=zȑÇ߿¡ %= OKK4{HW)X&(4DTeSPQ}oٲeNaa֭[ H}f_}I?uyE+ ,S 5;[79zI}i`_}kI?KAK|B>(s]ڜR];Wr刿4̊zLV/Io'OM@Q$Y C9qFjlr@}od]+ W7Ny+bF :B}ꛌo7mxȾ8Cspu9 D64C Š҂Vmh #thFzig6VbbKVo,lxF &[2gf{~1*| 9 olxV.r;o0!o²H%\UQ}X7T_v3L܈ /@}nAl`>/#{O~IV*O)]yfe omd >纊l`P>3b7ضmKJJJKKvܹ{nbM#h5>8e 7KM.\ٵ1; 0L[8k 7jرҥK4GSScx1e׮]Y P_ؾQ[\4ͨE Lkvwoy1Kr/l_9a+L]X'i> ; upfDRM0u%oؾaUǎ#3.Eo6G٥߄؞P_&560j&ۗZ^}äό{vdN=>K ]vmu* .[iJ66P}c`z LQ8/Rӟ]<3vvEӻxڣZmW/7r3=ɜ D74lƭ[6|Aa;vIzϏ֎=io4%E*4.X(|-I]bGhaR_i }_zny4/wkiW՚_v׎wVdP_Cw!ŋdl[phپtTۣ]>_@{v KZMg'ƅR_OJigv^nt':tc.&l`kF7FQR} 7ζ}Iɽ@|_}e_5zA{\_ *`gP}-ׯ'1&S/ξU=wTB^ =nMؾeƍgΜ_Mҙ^=***Zn0<4,c2{E#aS`i_^r5kTUU 5Է4R`TZSn}ۀ*@Է:)Ƨ/M=`Jq;}}-ZbP5vhXz(*o,pqGelřǨ͋z}zJmc8ѸI};MӎLjril9QCϟ+.l՞#b;ֳJF$֙y..}O n;ǡq"@R`&[{L<9J(N=^F]WɈa#'Y\]iL rto^YsJduPdW_ϳoMmZL7uX03xۻޞ|yC_9ȝTBD|mg.2Cn*58]0?upҢ lK&4=Y)΋mm_[*T{ fH_ST1=T;{)S5]=L`,BtAfBe|if .7{]TBRՌHl.RuWll4Qx2 b Rj\]\]3WTńv_1aO]M;j˻v|Ҩ_"0b۾ 8tf#.wY%0EV eY!BhƉl&?C}]@`M]:qEG2sO=۳ +^RCC,B}]<αQߐ)ޕmsw7 p>*[lZLDFqUUTݼ+ाaj P{3{H"[ DPO}#w9h;Ѹ] !/.eӣM'2טBr޼y+\0wܫW\} #ۥuIENDB`spyder-3.2.6/doc/images/ipythonconsolemenu.png0000664000175000017500000001052213003520702022274 0ustar carloscarlos00000000000000PNG  IHDRV<) cHRMz&u0`:pQ< pHYsodbKGDIDATxyp?:t2%6N26 '@ WK& 4N|cr@hxʌӐ2 )>l˖-XlJ=ޮV-iW3oW[Av{Ӧ͘6=} 3fNO5st|Au;VuMMNi4fZ& :59EJJNe4%q]%} ũ$1y WS% PJ)(y.v))\ vĿ;~DÀ&sH3r{6BowjMє/-~x M|~mDcSMIјLذռ%wao6hnnNM5c`!@4Z=^o*3}ѣGذEf|OCca0z1TEh\`UW[0EpkDKKcÇ6<<<44d0آOp___NnpJh,_=s6{t:f3&[ 7owYM!$If(gf`ZcE7ojZqiVU`p_-X=kY߇ׯGDpu 0M.ZV&2M4wtՕekjj.773l {Ij17dعX9\[}&Xztڝ:~g9{NF ,Q\jGNbyT ̄˰SN0gggÇ3?[;x/SdK-XFHUr[p-a5E 퓥5jܣc0; V&&X%C6;C6pa3 6,xТw-޸pВ eU_K"}+ɮՅGV5lPT2K)j9X3 jJi^j,np'Pcʋ2[Df[4uX"X\Mbԯ.a_5fQs;w߅ m' rp[{.7;J:Sٿ*" ydCuu9T̎j&&0c0`B8t^DhFq/AVrFwy3bCt~;w~>߿\Òw* 7Q.RҸYLtd2A`@)xYiԎ9R=[Uq;-s?>`M0qvK!_EcgOeqtYr;l ީ@P応k)pjVPF0]P #n7H|[ R+8^'.ӺRU+kB܁W6`0nG xi]K$ ?]17pZ, r]ERm<ЄHrzO$E m W!sCr`z6^Hwÿ̼0H^%^$j'aluD62w ӍzjRx @n2^+DSaq"nNJL5殄Q6JyE2 W@}Yis6Sz6P zzZo'O `1XNhVAI$(>>_!`k}^! N+w.~trbF..n ux@0bw! #؄?d`k >\(U< Fz pslˮJ$fֽ$Xp@J,D!H^DN1*o2:?D.!LK" + Xd *yqQ E̪"^Ę,u<d61x6mDpx&XM̏"*++[UU8%Xȕ !Op䆟Bm=c3W\ccň˗/ca1bDK0TIpNN<> M_x ƦZ/Q{aóF06l$l2N{ЋVƒ8%#=1XedL08$Xi::IDL0%OE@9{ &*V(#UNZZ^ojjbcS*mzh4VULcǎ(GbE``:U_#::;}>`&&xv쥴}Pڶ u7.FvcE``u R^O:f#3Aʩ9RN_>3(=o2ܕq84%i;#J9FqglgM^|'Y1Ayon$y]"Vx{ʋJSX5<+&^k%IKC<^iᄘLԕK +xX? f/d8x+Me+s`̽3?{Xi=^o3EM4b}M%{7[e_0#{d "d0Ǝ`^OtR3{|ك Ʀm4n萙] Jf~0<M-L7F5&Fc|oBgMI89L06u RW^'uۛj6Scכ=II)h`a@FsBB9sW.ϔ))$S&KH~5$֤S%2z&jJl4Up&kr1g7Rv}/-`d5EW,HY)/3GeVl˜ cHRMz&u0`:pQ<bKGDAIDATx흋Tŝrz3 Gۣ*>¹džjԋ:9P&'FCי1Ʉ$ >'H;f "mt]_Uws~UBj g}W\9BIP+`|/[L/"Bm p_Ap ɂe"B2k:qP_BK, ֑,dyҥ B!y Ăcɲ,E!PK5{o\]tV52k֬&Z*v%/ ,. !_iӦ}q]|6"d_}w,};k,WF,^jI]G`q ]x\pW]py_ӹ_xk̙3$W^y<BS/k]xA!K-F07~տ׶veQ+^g&˫b#b/FL|"z-ڍK/5K}QCugye]BuJE]ոmm#|7͓4m+vկWnҵ/}k M3aB޺BŒl%HF"9+ݢ \sj /{4bʅuNwhQIS.{/kݿ?{K'xæsN;)7qN?˲ȷ6?_B(f%̃FYW=ypǂs,';I쥖ӈ)R|Ð|I'z꩞S>3OW_0yUy=G{n܏rAҠ-R-7|h³<;z>R{Q=ڒ$nT.V xq;BȣSN9Es9g[,O#2F4iD2am)&yU쥖HD'N@g-]^xiS:O}x؄zISNׇMqZ}}0-_4tޱG~؄oxZzpTΞGf;OxX k< isϿ{'+-NЬ>9Ͽ4e݂Y'Ul'GҳoVnEPw[ua}7H@zOrӬ4e/W:hZz,ǓBȯ;NxFZ3QQ}UmD2}_n?Օ<*RiĔ ɧ*ҽd5{=U'Mrp^{iqr z'jyvh鳊C{DPy =[}q1727 uNe`Oc<ѮnZ3a#:#̷p>Ѽ^X8\^{q0>Dބ1'B(H{lH4dImՒ?'wb/FL^ٌ  Gկ~U_dR7H458so|ZN#B,cL$Z:v=0p 9↓kԆ 0 .ݼ#:zdhwo{Q;DWKAr_=|v訣7-[cR{$K8 2tsڥ!x!`K@y@$+B5rVW=|ryowoIλO+;4UZz'M:At[?؄5=OO$;oU}zǘÎ:z v=0sGN[SurߑVZm)41}z#EKnc2cP_jo0z-.7 '|ؓB%ؒNR^KKjI6iӛf}ھ*_mK3IR.ZOg&FL=7A<Bք Ԓm䓻n8pߚ-W雗+y{o-(?妁Xr1B!P$0Xl@#J-Fz\QO_߯{W(4yU^j9r!8B(!HV;yOr<~h6?zo?ɣBF=\H>!J`pM0/VG[؈diD8r!B@2B!MH>#L$BDdjHB!PB!B!BdBdB$#B$#B !B !!j?!B(ڋm!P;v>GjӦMwui B#۾}{5L;w濐b+ƊJ]H޼y3.cX1Vc2$C KBcXHgcX1VmGAf_r'%X!Ɗbڎ}fH.#?4XEktߺ26Z]oabF.j`9Hi᱙v*I@Bb$ǸI..+XV@?H;wK~͐CbOHuA}f`ФY_OW݇^zaK<% 9Hʱ2/,žbMXu.U]c- ɏcH U*%Auj3AH~1oYRxJEc8$ X}'/y09U/aYf<@X=2^=z8'`yDKCm& ɇ:VA ߘeo YieAeWh3QHVC4ʸ]ՅT"!UpƁh8^J ٕv-wLvYɮ|t0֡ovL, \;B'2${guL,tKAvT>sڑʏT$ :niKv/?|ʐW{SH+c ΢b/"X6 d8 ^r6 deG᜵ܣHxxqM cz) \%pXK쌒vٓkA~$l"pd'p@B9slrȗj.}ߖJ sҥ5e >ag 7Z|)ӎ>]PzU)n D#LC+%1p:HpRyT1Vu|GrQ^rXޥYp-bc;@m [ kNK.-&[p ArY9T=2璭`&/kfSCL!Lf"V=}.x&bjk}Z }A h3sM!H aqry i3Alc?FeJ\]*[pn[t{w $dݻA2 $d A2H $%%dA2HF$oݺ//$@2H //$d A2^2^2H&d Ar}ܹ%d A2H$A2H $wMX$d A2Hnɛ(B! %Kp'UR$cUR$cp'X$=@2H&d A2HnŎkX A2H $wŹdX A2H w $d A2H $d A2H $d A2H$ A2H $d A2H A2H!mEL0[Vc0$/Ye%oeWF=V#1*)D,++0eH~'bo7E;nXVKn#C cɚ=VZ=˳v%2=(WI+GF krU|QX&̢Uű勚N#m& ɫ~v\a,20nX eѭ%ɣX_ ly([C0~~jn Bvc|QʒlV-bKc|QƧX ɷcZ_a,20.vaezl*Rѡ~ύC`qd+3/'*Mo3YH"븼 g*w٩^ ERQ! H}R}*Um]~/)U]6V$:qeQ #_UPL;~ZN UO/5p-X $IHl] d6@Іxɾpjz^笸S.$A#`:t Ja& "$Tf0;KXxVׂ4"ٕ\/*6\.$6K W8$ H4ĕEs&?1 ˺GX6*Ӈdc4bqպoĕb/"qf%6-[Wc-Q J, Xx_~$+0/uu Nei \\8k5;kAVH"a'1=@Dau_oai|(ۻ4gxk̙YTגfwi2K弲s-mnzR| ex5T,6kDfe >)gwڜVo}:Qۻ5%#_*/Rv7Xm;~a:wi[*OWz1V+75l$:"X-䔯uaTo8|b#y2,Q5c?{*d7v9qI(pS+5d;Lmvrm3񇠄v,#92~a AY+poW.򹓇dkǵn­BU V!*ne^2w $d A2H$ A2H $d A2H A2H $d A2H $d A2H $d AT$w%ܹւd A2Hd $d A2H $dj$onD!P*x/:'vuQRd)N2\%I2V;]8s& I $d܍H;a-H $zԽHdX A2H /$d A2Hx $d A2^2H A2HK $d A2H$ A2^2H $dkH6q޽ UHǐ\e -ĵ<\2K6jE)A=V{XiNpuiB=gKNp ,$2v]BDžSvJa6~TDz24̖򁬿ze l_\i.<\j"yt. gY,.^c۲Fjˠ:U$4QZ<7AԲW[ ;C#ypF&/ [ض2clF+Ym3YH֙j򵨩L @rlKS$kn3aH^mKhr(ZUZYXc2|Z_L4f2<200b|P Y9VPjHv]+S\$qKV|4H.gGafj YIʹ$/:z]F 6䁬VfD:7%#_*O.T LYǑAkRAr6yܑ'zCB܁u7T$Z%jtpxƖhD+v8DIC+aQHL],Ku6"w%üu Cv'YlDN$xzZA?j[lk妢o8b 4#9 jՁk?ס-Nh:|:\A/e+RkeP81kkŠa0Kc' Kg|c|Ҷw Z;KkV,dXS]u6K[^ k͈VR-{3;OfwiNyk1V3Zrh՝\іIektilҷhh4gx6}l!n:;yܹCPz)ɡ!u>wbA 5P092ᇠa)&,k%#O!m&Ԏ* C fAl[rW;dCPJ Sd T9(n­BU V!*n2^2w $d A2H$ A2H $d A2H ܂d A2H $d A2H&d A2H $dLEΝa-H $du!ݓdwj%?YBYǑLϖ#ԲӑErH>$/:αzX GreKd%,_$#@ X(4^$W=n*l\-qAD*S. +VT,KK Er||_5L]*cԡArkqVO5]U1%wE$ ymA[UνdwzmZ*VSY^@flJzjmep_ZW:ҲkزQ)4-KME$޽#Y8qMn \,uHҩ6SvAc0 \Wr`>}07Qu`-Q)|K:QH~w׮];RO=}%Ry?/mmݲ}>3]RyZcu@9 l>=^D-hʪDmWrlYO.bKۍjz12{ö,^e:wiw||Tli6}êɏe%˩L!Ǣ꧸l ߿wyП{%bO?-9$/!xQ >%f&R=i|ҏ5qd}H.%FmZrgt?e{O1|s lCPW\bTx ;tJT ITY $s V!*[tiJ{H $d A2H&d A2H $d A2H$ A2H $d A2H ܂d A2H $d ;wZ A2H y, $d A2H $d S͍h!J%?7\%I*)N2{IqCUR$c*)Nzyڃ $dH $V츆 $d ArWK $d A2H $d A2H $d A2H$ A2H $d A2H A2H $d A2Hu!m]YQo*5f|ݯ[XV.0 eKe5V+MYFKB ZQDz2þmRz 52WRa6ϸR?qRIVtO6M!ydq@FFMS cQHΖ||dvuӱL3X4/(ZUܖ fuK$H+erK|qzp[:B+ $1+=_&Ƣ=hUq,ky;@ڴ N4e/j SCy챑Zb6X5۔J 7Jd%k3QH.eXk`db@n$1XN;FDICr= Pfy!ٕiZ47/L$2UIBb_8%. ɮ|?Yaj vBT ٕv=V~z;7lݵHV1E}&q֢u#9^r$)h6q++.$!]dc4bWXi{W|$æ,! KV<>k ×\,¬]]uczOkeio0p-HvbmD$;s}[1h'ɣC㵽KvJx]NY-۰Έ6KsV/P6m\Cq{tkStilm:AK5gxɑO.Y!lZc\WjyE. /}vKZ*WV͈+\*۔} y1V;%h V7Wf9h݄~jLGd!oQC`)$!m&T qYrG\!(k{`ɏ`)8B䇔)_㬏:>qgsJPt`)ʱC\ZIgqZX @]9^$$ŭBU V!*[pA2 $d A2H $d A2H&d A2H $d A2H$ A2H $d A2H A2HsnX A2H $?E$d A2H $d Ar"BPWIqg$K$c$IX}HdpH$ A2Hɭq kA2H $8 kA2H $d A2H $d A2H $d I $d A2H $d A2 $d A2H $d ?e i?4{Ra)#Pn3G)UH`Ն߱F&YR*)i!bJ՚,[ڗQR.XSir01faґluciKrNa ޞ[GU渾nwy@̶>$ $U|QSAh75vNa +=_,FJ*Vl6 K X(n$g5+_ 8$"Yg&=_<'_XݔMZv~9o`a#6I~[~]_֐׮neB Ss/jƢ-[Rt9Ey"Y#[K4u|Gn+Wgˍ"G4et!;YǑ\e358kzm& bƲ]m=G"Y&,ZA} d:n[+UHt!Yz 4RA#yd#%aRK1E+OkWo8^r|æ,H (wX3d~=Jnb}5\Y xqDÐl,N% B ѡ~-p& S$; f.T \zwbf(XMjL;݁렠Ɏ\ڶw)H֙ bwj{fRvԆ7w,䃷ҬXRKZ*_,o1.ϴ!gAW߀mfw]b!i Vm_Aa@${+NMJ.=^Xӣhl2KXշS:kStil2vVXգZbӁޥY,(1_΁It_K3yf!m&6SBPSH?%V#dB]OF%ZaHԝ80ᇠE_$o<^r`6J 8d'ŬgG:x;O<ڴi]wew3P*[pn­BUHz ۾}{5L{H$ Ar\- A2 $d^$C $dH H @2H$ Arۑ|0@2H$ ArۑKd I $#yΝB_3) $@2HmGk{;w $d Sl9$6K"X A2H 9eH~Q $@2HEI}77QB( CrK;}$pJdUIq'X$M& I $d [ւd A2HNw޽3Ĭ%Z A2HɩAhڵ#1f͚Vh?BEjeĮێ;vOu-CH~aY"Y,n#fe@+R=Lb_Rm_B-RnG>[N $dB$j<,Z#ټ;n_"YzоVhoZo3# VIeG~u;_|ׂ"u[OaH~}\%<|>FHECۑ"/A2Hn!?AH~Eۑg3Ye> Q $#$ò LX7*ںu+ݡPj>FKҪaf̯ҧ)̽$!9P|_?#Z&X*$jV !?H/ |6l4P (˺ gRTFBj=7nj%7ʲ&~íHF!PL!j@2B!B!B!B!B YtKHBjϫ#Y`ӦM]r%%ѵ^+>qPļ!!yׯpݙ.I_һK7;?H_b^m//?V)ߩH% tz Y&NS2;żF$_|{>NG/]إӛGu4YdvyH\ H٥#=~E_:=qѹĊС =T"Yż^$ر#qWӃ7#>BM!y6MX1cԊcNx5}-8Ҫ[)˜@QOң]yՙ eN*VYS3h*nPZgyF :k a%,)1grԔGүK~`Oo\hexPyEwDrXAx Qdzoh/ܺ e1fZOV/´YWң7/,VNTYm-Ay{Kx'Ƙ\ 'tgdPi+Ҿ-JX-@ >[-[rlY Amd6PG(儐8!>d d&Y%HN;QɄ 0 4nS;#(hCH4b&h%̶ b6(ZEdmԱ+zyf[P#P$mvA6z 3h5ө(plM%sLojzrNK(ضjv~qnlvW:1eq=یk󗚺B>|Ƃ?wN毼86vPSxu= AXZf[PmgypW&o̧;ϲ}S`l|`KJVZ}ڗ"lPg\GCs A)w-Uz(Ūʦc:w{阞=~Ka0_5춮Opӧ'VMYqZ;]ؖ_mqoSLm4]i^ NLR&֓lCŶOߛaɅ kطCG|{mVQ?M "v‹ئwe,,Amݕ?6? &i^ z5,zo-)z(vezz-6չvXy'H6P bTPQ 4ٿ r,5LBm7AsHuJPmݚetkzn=trYk/QKM:g| -\(fAPZ&wK]q~u.=g AWadR l (lch͊j%B!1U/:wss3om?A}aܤAP l 6l *qۉ𫮮یQFU&iiam` `m0 m`0 m` 0m0 ñضbŊ1c<_#F6 bĉZkΝl[Vm0 gXض l` ŖJ̶ư,?lK%ۚ*$dfɇk6m"%|ʰ)`[mfu+WG#z FjcbUQaiKM|掌C 7'mTWٛC=al>>8`+Rö*})$t])hT[ɼQ*@r) #eFM2++ H;XLCb{ޘ@8&7L ay'M_m64gxƅJ%nctT\ef 8>469\|J[ŇG11: +*E9U2NT~D=6Rz:8$BL+6M+LSyeЮY]{^{wq7n)n˫Wou׷_cw-*EadiORB0n ڜlC kTRK-dT<5nS#E lS#Fёթ!'vJ([;*M̽˴smO߰{3Bg wsm<6!<ۜhI)B!igyN_16D2B7U%}J\恨MT3si`ƶe>ltӶIAV˴.1Ƨ ?rqP¶W}뼛g8OR|-}H^H>IkBI l$p $)9۴{y pJC#I&>"ow t۸26)輅b'^vU69ѲtLZuzΞYGg,|MGRRqbKƍ1QfLX~\KX2NrLpwtm zaPmK91 ۠6UۖznXllhK]\=nkuú Kg3T p6ͫ|4,mw-w{֍OCs{`7`8ٶim!ٰ|d c-_|+j۞6 l>IC¶B1]ϻy{bXW$fծg<(`0mǦ]µFt |mza^:絭nu_韟u{ l`$q彆_{!6 а[;= 0 'mÆ ۷oXZ!7:ull[Vm0 g۪&NHߤl[Vm0 gۘVX1f̘kĈ555 l`,%. l`^s $ qtmkZ`4m0 m`0 m`0m0 `0 m`0ئjSu__|ѺO77m`p(oPTnr#%?ٵe˖m`pvT/=Cֲإ7440۪%E:5m` aE}ި~wîׯY1Lk(6_}8? my/Js7xJ틢En;"s&LHԺaRaie[2#daE_ߔ{.2U1JIUf 0m욫]ER^iCjٵ^psW"Zo,; LٕRQ!0idzed-<"QR4zK ϛzh-KWEDb[cy{1lӻ#E <>AHAD8'\k=˷m2򂓗܎\r]Ƥ2e`z\(ιXeG9ʶ }ٖG_5vXv/n[T",2 *6XL;iFDg4%O2+BOW^_xV@v$lFi6?t aܷ)d{a+L 8T4rȪoH/.?~8g9v\+%G&_ﷹ]ˀ׃ؑK :K/fnpQ*P0WZkD*G} `Syb7V6||}+w埇yxѫ^|"3Sm!뉌mz=ywN6)*9-:H>kG`l杊%ckǾP6g'yg_w'[x+ Uw$GsD% 6Ǯ2#AΤ){:`In}z]YU=?+oޞWq["cIB6ĕmXcI~qA51$|g0L)kme8Q9Qhp}[qxLA 0C^zn߽֜ym۫SO^n02ݻu)̿WxƤ?0SSKٳ`0>Qgү^^&yر\~0J1t}W@K}~ƓXm` ab&66 l`6 al6a l`6 lalVϩ ,m\50 l66 l`6 lal6$mɒ%O<ĉ?kѢE#G7om0 m555<̤Iv{n`0] f͚g}vڴi`0 6m߾}{b3 %Mfnl(T6NE#m-Ī&/i8AMy".;Xc[iii4ݴifX%Ko"nK7۪M6vBf?lR\ $;U&+ U&c^BusLCbCo1N#F<裬263j> -mr\$0E+bDc=6r(#' 9](8$T3Z`8Z2sLa8~b>aN~c2-j§mCmrAEd)nS#E l(`YXZa`z8,+ ʴvx6pαm… Xf6d7V(ZlYYY[DX%ƒ\  lAmpzol6c(ꓴql+Dwj$er]J7z>IA=`ې!C"3̞flcpQF1 'Y!ƅq)'&%p-,7Xщ6%y  L"^G.LkFY&6ɥ`!-X`РAdcl?d] u$;}#jRƒp1$"vF>Dt.3:oAKUɲk8~38 #6;g=1N۶ne1ٽj*7vˍF-0ѣ^<pq Y6?a摷~{wt?~"6l-܈lfmo߮gk׮]E,mx$ !c&66 l`6 al6a l`6 lal6 a l`CǶzNuAd!nCܖY06 lal6 ({{WW,&]]SǾEE6 mÆϺv˻?qǿɓ'_qՍ7m`p(ضk]~m[ʪ.\R>K;^vYkrmUŒV6 ᐰE;]zoq>S2dMu]_M]z%𱍑-_fZCY~gmUillk*͓tVZ(wVjyνyɒNI`FU"*/jOQpn]/m.muw[q_u˅mשMNw{qT\mMSXf%q}.5v,-"E&ȜjZs+ XZbH+m2bC]&yDn.U"St0klk6;w[?1m̗^5|G1){?m.Q=MJJ %BݑLvWIa s$ "n idrcv9Ab)A[7-g*q)*omO 6A\pqߢV-x`+}3gN>}ƌ=:D7?lt-*>I$ڂL;iFDg4%O2lcX:= u~?;XܦFEzI,yD®W[^%gœ`Mf5^1cnuCzt&Lx7#Cy~s~Wf>+sﮔO26,h.6m3-X:!;[zil_T(9;̜ G$UK婽m0ضw̚]y74R<~o;m(V◿nuN6_=m.$)f:@C".Nw׬7x.vl|EZlsmK,~̳Z?SoT{Ͼ9s̞=y3~zg?zf\lS֘}iL`k $DRhqY2{6B*SfK*ɖq *F{KAwÏ )e~sH0^8NZ8IgNnG!΀pwN:$u*JD0jXID) yl޼y۶m۷o߱cΝ;wqbDeO%0 )ߖI6 la8؆Im` `0 m`0m` `m0 m`0 m` 0m0 m`0 d[=: J!nKw܆_0 j lq0l{fٌ-*{K[<_f>}֮01W1 <29{^Ϙ3i;*uX0Ïcnp9l{L>:v~~!<}>;q"5}6@H6 >M\H|.lϔRJ6in?ݺgݖ|ik?jɖbͻygA=md1coXZ&"션Tܛі965Yf d6֚ ўd$~K"J#r;Y%jmb>μӭ+?޴붼4U-X^`/ئLAj3+$:6\D,WOe7W:qp$vˆZv7N,2_U^0ϕ2Do-GDg 򷔏3yHNVgZ)UlSOr|2 l (n$zE ͹+&K4/$-gqU+V_آ4BN0N\ߕ?i9ăsm"c ":75s?, AO]Xg+GD;Y%jm W45mnnn޶}cڳgϾ}8p:zǾg٦.Ymyy/z9kZIkxp*}X gX?8:j%c'D3U:-ܼݣݻw`# l mWm`["l373h0T:aVIu5|@e  BV^ܙL}j="A{}AIk4D*)kT˿=tEl_kclۻwm{'43ykn42\$$A%A4Vr?"ѱ{O$NfO Cm>/믿޻wo{[ lǎ? 6OnM-PZq®E1%3lu: dYVUlLq啯Ʉg1uoKminD8 Id[5+Yg׻ⶲa l+6sǹ6&qM ftdUvQ1KM۴_A6n%vYmA~v{r-ӃElm*f,[m lKX,R҃]AZIq’I%)))P3hԜҸ@V${_ =K ۜYA#љ^R*' p+N<7߼RJw,yϮ'OljF~f@ע9_Rd"8ȩlSQ%lRKKvfKʋ!>19aʾ'ۈ$egT ԳmJFk Rm<^J1…m،! éf[%li'͈,&ۜmN:$)nKU$63t꺹ߝ_;9Փg-4kΟe9NҬgq$S!d9 ifKg=렞ΤROs܈fqy~2 m`[s+A[% X턓0 }9<7i0Ǎub5al+9nY,a lے'7^]{6 l l,IBsܸOkZ`0㆜ϴ&` m`0m` `m0 m`0s $ q6m0 #naF6 l -۸7xZNSkॗ[I09q3 irLxR&nǮ-6m`ؖd'?Ʃl1M1o!5p C'ĴR:]ycN=Rr[ löhDrq#+)Htl.~":c_] 9nrؖ{kSk6]cژ$]InR]~l25n㘤SiHm}YyHh&;$+w9:6'^Mƌe!{<ͭc7#:gd$2wLeF[~;ۼq3&Lz%a9dnSY;ͭc&u~g"##|/cgt[ӉNL$]ș3W  1r&yDF2ZI#KL`ؖl#fOOkf˫|ąhDrG96;{b sP䱓 9OvT7z(Ř)ֹmZ6H03m`[f-FJk?$ůyޯmܻBw!!(J#./ B'=ܱǘ]Jł}7Y\9,%V) L`ؖq$XoHm]FYE%ti3jJ#_Tg5 sGO4wr.X؎ev!y`q9aƞV4];`߯A l2m[&<]p9kZ*ognhD.;t٥m>6\<Xmv!/d4RG(3Dgy0}~j&fb*xl7חE/jl)t6Zc>$5 ; DfG&ECۊ $읜H$])Azѓ(y SܑR lK)00x-NG[^ccL6 lzfF}Ad30m(77PFAf$n!,73-[5G11ئcYgz ]5H%E%RAycFvWt ᑙ s |iK ,ᗍmܟTЌI0 6F4nBH6X:i${+}͚,YIQgDi` `>IiaC+xݕ#r3ƅS2 mh.m0 g6jCOI φ^l1$0 4D[mqIr 11gh@bvH%`':Kb=Glumt>`q0 m)g[H$er| `[[i{/ ˪uVf{I`6؆Ia6 l&0 m`66 l I@'0 m`0m0 m`0 m`0m*0Bs $+lS[  (  l 6   l  6 l  6   l 6   l t Rm._ƍ; %,֌8  V۷+!oۂb[9[d`G7mA- țؖkgAi`[#M`[Pl˵3l4m_ѫ׈UrN`[PlH҉l4mVKZdLh}8\f)IQٶ9'ꇘ$" butը_/)T3ѿ<}6 -bC>{G3''$Ai`~KX7 ;`5oj%˨/y$nVs\G0rfٯ̿=jO"nrd/b4z>'O<9崬O- gQ,uzJsmIls^b+ bY`\b\JUnӹ,U.YlihfKfNj%lWIVV?KY<%%6:d_$*(_vO+'[*,ٶ6XY$dCU懭3vź<`m߉W[2K12fkl+/)U.;gtm)5_ߚpBKwMf 6k9"R 3qҲ .Gɖ9gVZY<<֙&A6>llH2Ol3ἚpW%K1L@قB<l5lRMN8dT#9D%ۓDhr%ʶgAŶ#bm|Z7j-|@Rbz၅ڒ(Q2,)m[X#s?׾{wff-c,=z8I3r6>TLD#km"V!Yl km\,gC7Db,M;c,ibQ6_ 5^H*n2ε\Z¢MmԌzfd.vgR{ ,.в.$sv+.Rf+4>I %'19b;C3>_;WEYDK<`mLS +:OSEaw*Ϸ)WE6C'I,KXu$u,fQ -G, (lcXcJ#|lHv?APzva m9uʱC (lfM8u.Dxd%ɑS={ط J)6nNUWq5 k9iƾe@PRʑ_z|I𱅗d͈s -S~}7ֿ+vhݯ_  bWCaKIENDB`spyder-3.2.6/doc/images/explorer_menu1.png0000664000175000017500000001331413003520702021301 0ustar carloscarlos00000000000000PNG  IHDRN. cHRMz&u0`:pQ<bKGDUIDATx xUKs|}>3#|>gG\dd$,IINHȄdl- $t:IgNw'=w+T+$T8Jus!ƐgE !NĉB(iX VRT WjEhXܧ4su؂ H3ꕦVUn]b :ᱯMFcrZnlZ}EYGW0$b  \NI.kn֨z.60 vD 0Y^8g{{;8u*@?KbsvO`?:?*_ew.Kp zn?:1 -V|e ;1N%Ω^Wճf3ȩJEV%Jn9Ķ-W(It0N緢7w7䃮N{|~󏯝G(.x۠o-K K,/hL8+[غ+U(©i'La^ 8__sg/йblُ~kY#fMO[ӸhK?^v&xz\;3l?"^c8^(su߷~W+nk[KӦM钀LIPr9{ 1 >(BѴ]8.xŷӸ{6lуP8Ӟ[̗;i )5k>ހ1 A}9(2ɒG~w~GVC[[P0#{bP&.~C[SS;3jU.l>!|G&6ʴo^bn 'P8Q NRNu%]MMMvAA,K$3g` 'd:7 Di 2 ]# WP 6LQR8+$a]eC AQspWq'Љ/8GW蕅8.u YiC XYtvQP:N'xZMA[*+V(^8A]v6Js}p@t8av4rwWȱe0GFf EQ(o+`̮҈7NB 7-8+$$~C\{t8q%-( (ĉB(ĉBjmjnJI0JjvJ g[{ۆ~{QƟ"Ȗ|>oSZ2J08/]9?j]Oz,=^suZD͹RsO8.?yƢU'_^i悐0I-("{SK_8eN3?oy4yNCoT=){wKY^j[fP-PzGx NIN3N8™ ݟw'q\`0RY  7ĝII9ĤCwI 򛈹ĸm~į]7Gݸ #nIp1"{6ԈpH qĽ$A$7m *@Aȷ\J@x,K?NVw]wԵl@Qٞax`W9/'^CܹVrB3 ޷][XoThl-T"8=SQ;}6%ALᾘ'?+&(b^'HɡYpd O>}VL|_'"&Ŏ4~N\' ^||뼜'߮ _(^xۮ3T4!(e%[M8Q8Q 'MJJ?eҔN11AlX$(7Y<|0#[9,̔c삡7"]X'X$l&#!.OHvNΖ_gp0X2+=qD֭J{GMHH9NH-|ޫD?geeA9\r2f ֓8ᒙ:%ѡa P]H8b^G:"qp q gѣzIll?Dhnüv:e ctC DRyۺe+-Bq:ߨ8d !'&.@4%%- @D!dWg,80(ƴRȖډI7t#Gl+*~Pa2(666<<qL8C@HۦAM)M0⅃ [C!D!ND m۶=w={4lAܿ?LЏXz:c/UӰn(p f-P`qfb/fp’و>RLfVoXY8CBCY9rIQQ\ {zT"m[gkN$[8!Spg/=/a q_=QgUg:[6.d94;qֺ䢧o\VLIxXk/wۉ8PHQN8  ΤR_P3z=䬗TN}kdˈ9qGB17qvٯ]9 >yrw|X֦2 '[0bI48 [LmĻ{_ Ry\2J(Fod+)(< O?:a|7U?;驹Yo̓ʕIO=DUf Q^~ n(j\OD/_-F sp턊mڶ3ld gUq '@XLސ`ۢX}!{B`, Ȅ8Q8QqN䵙0p'/^l0pՉakl657B,H#{=aHѰdBu5Ja$&_Lmݚn؃ͅsNXL]TXAJ[wQ:^8C|r :vS 4!S"8e2`:Rmcu: ` &_!d1ρ d 8IpT)U]]d[E׵s&%nz}?$NGNȰ%-N`6-az NHz,-{- RɶZLa4Z 4rճfHf6T^^e͕gn^Qbb(J\)=߈l_@p8EqIeodrUPQRR6\/K+cS,;u,q#9lK,|9z[7-}θɃ_{(aqV;88vÆ]]v6$TpXLMŋ O{d̙0xp /C3?yl3<[Z~BuuKD%#Dt+WegkW-`g[ӓ\2i{׳B%MMJ-,LTqpbήݬqzl_KP]X,9٥⺎"#_7 VdY;[7oZ⃓*!)5g JOU]T^~߰pd̹Zӝ\~ -}'(񢒋#|<]NWg23+Dզd\E 8k꤅%E%;;QƉB(ĉB(ĉ8Q&7rL 5ćq:,"{}SNR}82p2;x,9.(E8gfH7euWgߢ /|?C? lL9p/kM `Bj<:3'vG U̸'7w\@=cɴ29lc{pҭsgkɘM tlA]@ŹhCbgGK6ǑaU:8+7*(ĉB(ĉ8!' q<ÈbTv(ĉB8Q8Qqs%=ڦa# mj@488ݱ-`%="f2e` v9qQNV<ݲaHJ=w=Gzc'ɏ?KG9!r#L:y-,Q0Z89j^atӦ+sJם-}+Ю1u2]kS9`SXL֨x߉B(ĉB8Q8Qqƴ/䕨ʛy#u 7] W>I=2L9`p0FFDAfZs,>'u2ee\u7Ru^L ]c\stlNFv?.:KvddLioPn ߓs#`Ljzk 7S6blr3%PụLttU/P8+B(ĉB8QYQQSٙp&1#,~%NjeL]u^7 P)PbNI{-f89<8|;p@EmU*զʣ/_ңՐg!N_ >PQ)=Zms`1S==RE:O'pdX|lFF88?WqN8u:ml\} V>oJȟ lAaXl/~|2yGDZWeGj[-8a&v6667H$zjMD"mhԊa'b :NX 8E߁4&J TE"˗}' q' q\D?򶐑%eIENDB`spyder-3.2.6/doc/images/texteditor.png0000664000175000017500000001401413003520702020525 0ustar carloscarlos00000000000000PNG  IHDR~y3 cHRMz&u0`:pQ<bKGDIDATx흋sU*tYFJ$&JwA@-  D " +Vf$+ƭNYkV]wYtyDu0VNwtK{š}}w#|/8"m?~uuhJdY޽͛'C=4 D%YD\ <APR2Cd2IMPD_g2O;w. K$fLIdHk2;v5jT)**jEiJE_dzVVVaHoD@C}8>ŢۗNruYs9jB*uԗVH%JǸqDu?iʺHl:f͉ hAdw/,o/,Lwz3g@GjR| =HsK9tVܱsrnRS{)j]K(qn۶MTuEqL.,… |8T7VoqEɳ V.*oXie6ft#OYwVŰǴ 2$xqcT3woWwIEklb';H&(nCL2e\|?H" rz6N[- gH}iQD6Lj#^y<w}wȑ]vX[KOßu̪|df]k.^?{nQqx}SrdNk]{dfR}ssf?TwXocͬ%#)'@Oefu=ˆE!63w%zK!FwI.8eXՊ;Hpt;_xDl}`{R݆! R?3$䢲SjKgI˽,R_Z9A._~;vȚt;wK&Jdg}oUR+Db]_ֵJV{ aƆ8zmevI70KV4]Z=nKyhK:ְW"|IJU޸X|$xG3sxcG ,S+ ?z16o+ k G<.Ź]q">bS݆T!̌>ă߿`9?"8[=Add/>wxfsR_Z9A-7a}uu55koMDgɋLYc[iNLj,ml+ERĴؒ,#z–s޼VÚ4ѸuSR5wV8śjy 9Sm]k}aUeb_-lհn@u1.ҭdkYZڑ6ʍM}L9fsK_b+`%kGfWvIǵ4*!2Cd/Kې*+3V60͈VOeC>+p9IrVN׬y'Nlk]]_}֎]}eu /׸e3P29d?.N(;C}i޽vw~!ND^+'lw݆q7Mn?D\DC}DVN|ڃ]Bl p믾Zwnݺ Rĉ0qi^4Q"_X.y}ҭӞȒ[6-gW_Q8UCE`>#\c9^UMsrzG^].Ttv':[5]i14ؑQ'{{zyF/o1\{S?Q #o3㣂ݮOWN.{Ϻ"o^-mjې*rrrZ-2i$ L H,Ϟ+H}iQDV#//?~ז/[W_Μ9sD.N}̷;zÖIbqNўJaaxsܟ\ƩΊg߼!nwaf1̫˵0*.;-\z5zD44lEL"?)Ld"s>k`tޒ%Fͬ'+}A0TwҌE!6. +rS݆=~x2~}$?גaA'wӆۑg8( -ܲpW^y}Ŋǎ;}ɓ'U\vY5/S"_,2co{^5lУGٰyMu7=n}]du=qa]d~9Չ=5l)R]-,Ӄ}XWM6^Y%!OȜ w3hкGCm;~݆!A6"/m G riG<:,oWSZ9ADS|yrJR9ROo-߂4PukfݘX/7ucUnT! \z8≣T[͚F`n rz97zXuT=y멣JP7;kk=A#3څ'"?nCJ]\$O3{i%m#cp||Y.yTEeviQDG#gϹ͑/o{76l޼Y~/S^7lذnݺ5kȟW#KQ-aT:77tH+i 4#G4o*SF4̺~*:¨9niNt]dh\]w]Ϟ=1>T-pUOrNKVV^H+i [pꁓKOTo,u_-.=VѪ*_媂Ԕ p7;r1MmSK{zzU_M2تJyBu~XK+'% ?</#Mk.Ey\.nʿ߾V^e]:u'Y;rd }RDVmDd(\"Ad."ڵYW$D&t 2D!2@d "Cd:^"ȚD,9]s55 2D " "â6652Т9Kj:{^Jhr+u*&YEEEIMm𶟁VS[.m8$MEʭ>?"3:j'/CUsKᰶ:6,^VI "廰W2:z[qhDϭVyxuъb+'a-[Ӆ&'ɛa0kbQO'o@*:;R$FH_NBOj"?:}-B\M|߬=sC*Fz>ǿp[9uBzѱ!'Ef`v;!qu GFڵ ڇcUg.}Ii+/uYPN|{4߾r59PDfʸAcהU[Qm6΋BL|aC'?q'2}h`ON}$Z9#shwi5qnēxyYK(I8O23R;#s( ϩd9LjB֊LH =o!ҟ]}r| u["sNdn؞V^d]KȒ6|e,-"K*|}kr|Cc{,Wdm;?ȴJvv &=# !-mJE.dyNhRߛuFѽ7W߾oO2w4h6Vu&u<>ȓ{{қx \dVOb߫Ndއgo.1n ,gS#p8|ؽڊw$qΫ/VoMg d|~ ِ'L7({Q R3Hgd+sD?!8o'?M;9s,U%ֵ$"kǀ4g7Ly'@d 2" 2D "Cd 2D "@d 2D "Cd 2D "Cd 2D "@d 2D "Cd 2D "Cd 2D "@d 2D "Cd 2D "Cd 2D!D!2@d "Cd"D 2D "@d "D 2D  2@d "@d 2D!2@d "Cd"D 2+'2+@; *"@d "Dt#98"tFNzbEd4sLNr$qDi.իW_8.K YLAzl̘1?KiQIIva"뜉#2HOSB%%مs& mEv&-g+Zd0qDi+s_8 HY'LAڊ7^HFW:a Vd\o HUg]Y$ mEvbߣgy~HƐ?형aRUޜZ$9"kcF3f8뤗Xo먵aTGd"r_u^bWDd1fM@fgYEvfIM "';ۊS)_]E̘Q>xpw[j-6%.YH.\jv=)1T % mEvS=ޔr>Z5hЪ\Expg Z T"ϒh)r穙TЫuOC9>m l}%;YV ' "hȾèyP;gĻֻe;) Sɿ,m\?*ZdmL}FCNzeٹi%vƖD3sXMR8"Ywػ`9wMھ4##.u[)yE٩|Ln+-5ԓuֵfF#=IGd"7B2A"넉#2H[^1&}j ?),щ#2H[?xOzqtGhu,9B2:hN:a SdDoA#ۆ95H 0qD)iӦUWW˩~5}0uۙ;w| ͚5+Qꄉ#2HC--tl 2D!2@d "Cd>uP:.tP,th ZIENDB`spyder-3.2.6/doc/images/new_project.png0000664000175000017500000003400313156675415020676 0ustar carloscarlos00000000000000PNG  IHDRi(sBITOtEXtSoftwareShutterc IDATx]TI&, &P0 NsB1b 3`DLg,'SA"gUP8  lj{R4=V~!@ńĤ|6)v-E"WzBϏi#=a$hm.;x%tH9Jr~t!P0Hw 7jE;;' @tnjC q2TZaZD‹TlnCG$$$,S.̨Ȑ;1UTV}')kÌ\שYfV+ZXNE1*9K*_%CF~ I>&850}ʕ+zk'[¢1~ЀN]$QD=$* Kϙ ,ҳ%-g-x?~s;T(N\gA;4k$,b0KMڷ˥D@0y̺u l?wRRT1FjѯV]J+8پ][n6\ZYxضn233gCĥȴF ,Y4`s)!-LF*_mlZeWQ}-arVڂՕՔemJOPhXNiRcK_o4ҡV&5fJYSݧ`7h[,yI> 8&?yl:ѩlٲ|equ\'֮UgϭO[ at.+Waq Vh*U|UϞ?U֌nUzھY[[{ΓHiPl(lj>(D?;+G_HJJ0>tBtf=p{~-:ߺm];{YU=ݬ,w}m{X3f׮FPں>{>ulm޻ŋ{vb:=}`Nn51əlk)AzZB=e3]iW>fdk2 ?;$4ʜki/>e5V#8zdWRSI6CL4UO(9zFem5)̙uޫ4׮aiS,^ 4lwl$|3SRRxg$ ak]A*نe ֥'/[5mL/]_6 t[ 7C0Bv`iii>kVNpq_r!;(iiiǀphky[L<O: i_'xn7n,CCx>xW-j߼uKWW7ի V,! +yF?goSODgf*df+TQ>$=K6Ye3]ee#O?fVB[TW/z8x#A,X(R@q{.DyfAI]/h͸m%9ַ aJa5 uu#.jPp?&FFlw3h>zu]I;zmJcC>}6sa򇏦u.J޾}=˭"Z6]bӾ5hP_C]>[%!=p}+JCŐp9`1Wqߎoۦ5[j#6ok[C;'~Βlm߼*1s/Zb՚w)2m+Q0jӖmF % ^|Ǐp`I [ 9ޤlI=a?c j(fdzSf`LⲖŠL|f{LVIGfjP"Ii dl-߽{7nKVVq _WUfMbu|BsYG)z]]\)j@s-_BYnv- "2nasJD1o{V#bZe_*X;Z)h|)WVXWN4Ls9?O`;$q.236x@@kq˟Yf<=s`+U/C*ˍ<1Xt啜?{WRԇc`z,;P<(jxI>Ҷf᝞i"-$INATYJU!dh," xӗ%8F *;@5 ŴELxW=Rw/NKؒ\s~un!ф!EzYwp ф! );$EBq }ddΒ! EHwU1bF'xuC=wļ/裣Sjբ^zn>so|K΀8 :18q̿qY&OZc$d!ѓ099y޽o؄gee=` a^xq3S_KA|r 8kh||f.1ܑ]:FEInn66[w@exyy}72 {>rSM_D焄=z =p/_Uuʼn O&K_d]8mK! Ǐ}Er,ٿUu/^-xiY qeZjwtj׮3D^yU1(Ǐk0x]u7~1=;^|p.^8qϞ>6u+fHQONS"OS=6+JUVVBUuXc A_YK^$(<ps"@ۤIkexex\!"$gO>:⿯N8GC S` 6<^O.~QCJIk g5Hs|H ^ WU]Syd͡5lk P1HB|:J_x]~&c diӦ|TȓRBqLu d4iVQIW\qt|E*U I' ccS qV8w,>x]&Nd\y!XP)%G[9{Q,b)tx鼚jضcCKw88`b T&wܟxTC}mۺ5(8D,P>?-@x')X9 6%Ek6mfwmk:CZ2y`0qw+Z:$ vxOpr>\8aKaV}mf(ye䊦l9#2"&l~rKwad@ÖM4]_ߠc2t(|СXCp%mڴe=?Š/*65-`RƧQN0/-Epg`g/q]Ւ?֭[x Fc(y21 ϟ?wf|2b0U666*z꩓'CeԮ7ɫ VX~ߟWN! VZAqɭ*<, 0 9jnammrNM|ܘ>~̮>{6;x SJ$n+R\4&$DcSbyp*+ܹsX[C]#|]@ةzcR[*ٽ~yn`.qce%BKx(Fq,O & )ߜx8fq>΄1R0ay溿|XJ-]>֭[8LJJQweh7ӥh@fbiavZA/Z"B 701ىVX077;6#Ǭs'ZP0%0Yz͡C~a ,ŎZ7٪JJ|WcׯCNٶ,M! lظifK[".#F -=݁n lkk;=vT4]ûAlIˎ]v *[,-,^rΝ;Xu{_˖S&ïQzumL7I2eԩJxԦZKZUmT?L# Ӎz5|KCyC 8$0 xٸaâ?dKlPMM)`e1~yy(ocPN"Fl@!޺w 7چ[[ t %;:a tBE@O ~b| jG ! 'HKN$ȇCrIEPtLvx| rFtGθC9sCÊ#( +-Zc{JKSDr_cJCFs^1|`_稅|~}鳐0|/[RJ'cݻtJIM]2"2nh _D;wjZdъk߿֫_Wz-22gHE) ?yTxLڱbamZ_t #"#7[1oۦ 8̹vX'? 'V* xG|)bOFM9xFNp_NmjGhPkΓ+WNkY{]W'>hD@F -tF#f A<|ߨ>nv}gỹog[|yvv![CqE9<'MUSUZ~ݺtbn]:laԔԾ}zQCKA3l~wmߌ6lP^]koTVӧOGmDzD922gK& W} /̝CTPmBiipBTFϟBYMkc!awh34È@Gajg9'7d@aԤdUZ<``z0D!An{1B 4\+hB( o7aj]G8/{%t!g{IMn޾ ^u.M?BPLHL*nb߾}ܘyG{ujcݱr \PSA1 T"]:-y2AbEˋ,O޾}[_Ҽfd٩nF2;H! 9;{KbT˥"=;.'!'N2; (#rr4 )#@Cʀ8B@N !'N2; (#rr4 )#@Cʀ8B@N !'N2; (#rr4 )# w#88cRF1^y~L?pBfUty!jԨ1h@qݻw#^N].t$dx!%%f|䂒\8qZȜ6.߃QR͛7=ڣ{ "dmKڵk;˗Wz]Ӡ0kׯ#) *l22gL҇5:}{-[dήi&CHHHiii իW2eh[F,s.EFm͹BXZMM}vNBR k`hiaajj*ы/>/rRF~RRar1wۍ?'GG#?~.,,zP(PNAoܴZj9 .! gϠOEcGA8xp1ܩC(W>zklC"EJUJALZi(v! x`_`i0* Fe&J݁>l^n'.IIx3%S;M6X`5sX3#3 еjՂWX=IDATbEL{0ǎX~B_,[ %b(T,'L!PjuGʕ1oݺeh3XSK ؘuL:kcccH"""6iR9--'-X)ǎLtiӦeؾ+~e#(AJ^ ,F`Ph#C .@a= lxc~zZ OH@[0'&&rHB޽{O=Ê ]#x:4i/MLfٲ1oޠ ll["DDE Crc,ְG09}֭l_^Ϟ=Q%Xog2n݊(DM N ss,Zh,]-Zݫ^ڽ{Estֲ EG-~lЅYѯPTy1ř`Jbі_vׯu [ Oa@Y Iݺ'ѓ_еtlBB^QHJHiT=/v %;;eB*]tZ eDE'g RQzzSYY=;+ܽ)3mY41Na%i36e7obXL9gnS8:_Z)C/0lfo nC!8zL2S !@Qc0̝yy}7+׬0dБc}҆pLJ.-\biao鲕oݾG6>Wx̞bwBbuGˠP-$삩I;v[-E!,7 WBkc rD`-5b>mUyHߵ}3fĥsslBiMa0zهtF];q]O6_~ssnz;~T]3иφM S\r`jQWVTp)! B@bxnj44t)ڶe~u{h>iMI k|nZC] D%WQTIcBDŽdrOpe+haټaDfiBhη=l!{Ӹ1x#ZK%! l oRtR$ɥBYηh(D< Pjs,ţsOd%BF+d|*AFC(~/[1dPZ@F 3#StpF=|Hhan69 s\WnA!aSBH=/){͚5Ə-O㓂-ijQ/>^>kZn/dd >z ߡnYʸE׳=n!'m;gNheؼSf?sɟ ^ > jGZ,'f%)KV"T7Wf>;wi^Q#֬]ܶM3 F#kaYӧX7'L^8zh )˭>6v]Zk# 96ZG{.>H.g8cvQ])+I4?Γ+WNkY{]^6ݻ]yǼ[w$Ƀ|Uz.<ƾ]ۧMv  ^f|di:tPխqM(~rs=/[b5 z>:s8a|ٟ͚bOMڵ: |"4\彮o6~|>E/r>>k:o22gl:Ja Y=cjf,av2*9693GM3 utTďm v%c7$VgΙ{hnn[!ld$'1žҖ- ޻ D.A%* iVތ%x+\J*b}NİVuls0FZZƿXYr5 Fw.¨`@A"Ȇ]-XC ;gϟcQ|d6z@@OWi+ ) c}oeof;/Z╖W$9hnec\|jfnп׮dO}>~$M Aat4lTמӦL@Z:|fGc /mon1otVdzz]znٶhl[wk3҈3kZnw: R~7lQn޺̈́/d̔8y;dKa2;csbB@ _ -v(CF8kA (Q @CF.pl&Cb5Xx rAtG.P1!@EtXx rAtG.P1!@EtXx rAtG.P1!@EtXx rAtG.P1!@EtXx rAtG.P1!@E@_zqĎ_XY\9cc<و LPFyI_ٌ9sCD_#q L"Px'N9s.H5lXڍLT%GveBl??bר^Ѵ}A&Z/gDZ8m9J(RLGgukVF^O?GJ>N~%R^G:O崴W _zrBr_amsfN]&zIxP!}'l <}pܒݙ\ %Nr|q- X=}0>C‡gj viW }a)ȖC~ňHj1MLHh$)\`PC{\ܦ1A& _ TaW|ӂ8Å035ygLn"#ߔNwfnrd\}D% S(xH˂ 졄X~.c[063iL: 22s{&l h6A%9f2! 2+ZZ>|1'ͪŲ!0^~wl9T saZZڸ1P*H׆,B~q0qt^4.9;%R;rxz3xp:aVcH]ic[Tg{m[N?a~cb2bQQZ=>1Jl|ebE #gxV)ć x?6yu'/ʐo@qXh@إ?@kk+K.$qHm duv>{q0O5;} {wpG "vB6/\Dk[ "=b׊G!T༸YupBC@b3g5® +,\<֬Xv6|.NaR@K /F7ήSR-dpm waYvHx4[t?yz[T򕉊+C p?f6zucg0 735na]}x 7pHtH3.hh-q,M~ɒHR9f  /: У&N.Ϝ  ŪK&Q%@3E`(<;x, p޾}[B%XJD̐MdZwCpHH-O \i[0 L-*kcc:Zイ8i! ׾RiHr9Dt^t:eB@ $Cd߱a&9tʄ/'(4lB@>5|^w:kB(,ԞOHwu& "H Dt|^w:kB(,ԞOHwu& "H Dt|^w:kB(,ԞOHwu& "H Dt|^w:kB(=2=!@J5FP3&>HG>(tLy"'1!C@iͼ":$B OD !@PRSR!!@y"ԯF< ;x!!@H&b";x!!@H`"&B!@D&b";x!!@H`"&B!@D&b";x!!@H`"&B!@DW-IIENDB`spyder-3.2.6/doc/images/explorer.png0000664000175000017500000004627213003520702020205 0ustar carloscarlos00000000000000PNG  IHDRIZH^ cHRMz&u0`:pQ<bKGDLCIDATx} řQ'I&Lfh6c4h4.OgLѠF5qEA6 x.e\}sA@PdVAdڻ9}ty<з7҅ H'M6<p=ѶB2e $  q s~m@ M>%hMI66fSGf26n ;S H֩OLL:vl뚄弴VDGO6g,:4wE$:YPuʍm[Dw3K3w:nSZlm2)6Yo^X%O& -ܦP63HEw2J6-9ۂ[l̷yC%Ilwba$ǂ|6j嶐IjגHIS 'kҸd.gp@-/VV26H6)6 ܖTIy @Xlٳ>5ׯܹs4p[:cƌIohѢ:n` ; oիx;ixW8x n[bt{ڔƘ$y֮]mܸy>}: ]]/T@*fpČn<{W\n|͟-n{w^bc6^ &X"BbRay{i!ɡe?ӜZ7\?K"ws~ɲ&L7~|:o;qnÔXҏ5Oi &Z.8[T v KE۽5ꢣ~͟ÂviѠmOMN7u?)3W[]MϟwfVŜyhsUMAd@3m4Yen6FL}[eMVm޽|7zu]+6YuϺm{6Do6ܖئL2k,JjժτpQ;icMHbRaj-W: 5~K/R?7..k?Զ~Oq b(Ƈ.L=~zbYv9eg_}lԦǾvG9W_UyȀ=a,y{޲Xp6-Ye s߰(q;1Mo6fYl/22K/nc{9wTۨn֛UZp[߸"=5¼~GoZcmv鸋CIwVo3{_3?Tsp=;~WײxNapʕ+mns1}u/_cV.o6k>m@smi j5/ &MpݑkQLMNV;'21<.5+NB7gX, i14-9sԩS,T(*I"e^7w\aY谸;ҵk/e_~;w_%[/=yG{;n"7g ܹ\'::wZ8|o_3G:^y+.z/!_6곳~ME(riGp\a™ /Ω-I7&33f=f;$iv\,YDܢ!,&t>I$ʑJmQ>alݒ|oOqr<E[Q:/'7e^x 6K)NhsN:n+|%߽kw~]?k嗝;;ugt'tZU#Jⶑ,;wٳg>8A؎=v,Gl--Ƙ9LƓ[%qp6ܖͥ6ҥK`WBRfNm*֒0ZEb+x0}K  NW0{%B1l'Q Mm̢;v93)x;=wVgt|w|{}_}}c2'ߖ̍;gԙbLoՉW!vm4lOx~"r6ܵ3ok"]bh2?{tzgrQHaubEaS}>=ڞ/vnmh^zyQwOw HŤR].:ܮ~s^:k{Rjuի ?ܶS=?{s̥>}+_{|wyD>n,?7-w,>|[۾mblz?<,fr`s婏?؎#s[>E.lm¦Mha-Td*x ?h7jkWt-Ag'~/wFg {v3vԅ'Nx{}Øk{c}t-'-^[ 6&zh?ѧl*  yY>4auՅ_S;Va$)7 Ӭu/Y6͐nmF>:n=dAbbK͚~mb;n0pMl~[^y+mupo%6|駟&(0q&L0iڨ8~/4H3iN=4[$"T|#O+v&Lx +n#9F}[m6y6|s^%b̰|Ǔ̳7|cOo>DootĊ3'd]/ FLϏn$n[bu}#F3{==`Ȑ::^|-w}U iժfo^]"; $\Tk[ny衇z_?4u!p͢;{oڼIt۶\}GMlrE^d^jvi -ԴAĒ "Gl+ɹv۷tH;طoJ H͛%=ڥE,\CO>S۱G=yK_ygP_w;ͺ%i(^>lOıp7[lj1NX(s6fWbmnW@W~ඒm„ǎ0fsFٰp'S=7_}m=<ޯ_maEؐM˙aBZQ[Afm\{Ý$ۀdxrlݺwÆ 4bcNZod-Hf%)Ap33-ܶ$lğfΜ9z w=iІ6ujS=a}8H>I>2r[>t/ʹmN6mq 7F M%6ۨWɬ 5>(׌mXf컟/N~K'}vxE7 kaOB MԢ72Iu ~ŀmnYPziT>\ٹ1X$$DWL8ч. 6 7un*MlA6煷!paPm+kB`8]<*LږiMdF|nsl!ėۺ͡1:q`Kd`E b7>ߌ#p[ muu Kyӧ }Ъtm,jݜ?$N3f[g9HU+im+W$[Ƀ mnt xAvzs. MFf'{= n nPI<~Yc"ma66XKsM)ӂüvA*ns; Y2UhԆ7* _n ۄˁ4/7,(MF15f ש~꽀 n}0kќmLCJ$34+҂ۄqg-K{ #O]ɷۤ&(ϽI~$!} XL TKQ4tQL+M,mݺu('m6FӧOzk.pnmqAg#̯enzS:W^xd:tVe n\A$oB9صeeZSSݦ/oI:^ 6[ЇD|ebH> HqEU8ɜT<bkݖP@rEzS܏أG 6on^nm2 iIgY9ċ﹗Dw%]NZ˗Adg4񝳒-4- 9][?'O[]>ᯒF?LFª![Lxm@d& {ְ6~8C^D1W4ޕ"\ڀSޒ..KC9twfCiHKd-l~'zS1B}m'flcZx™!! DmR5I_nJnd"_/ ror.ka&k%-춐6*y;@vkbUͺ /[;uj:G=N7--S-m@%E6~#TnSql= vm$CΝ;wqժUҪȖWhͺěwz:;O OW$A䞹Kn1I2pl1v$}BU ΂,4vmDfW~7h_}ҥ .4&Ոr>Ɂě+OQpBz>@هm}Xxm6p!iVmnde_v&y-x w;/)|@)0ӵn n[dɴi^~9L4vD5o5߫}$9.Wig5{I(-6 !ܦZm'4{Ѱ3C34} FffHN@uL'm4ʭ {Vmq-m՟uف̨ۂf ංe_VLZahwlcQw}iU$-96rEFvqZpjm2X@mIv"Һbn`^bP6vp-inmTo6nKUд߰? H A v[|Pa74npwn~k)v^NԷ`UX nmoo CVV5hߌBnF6pBo㷻MUjDrFaj"Nf65.$dEfI s0]ֳ.(pԅ-B-xeVjQ_-FM(@_Kے铄~ 8muLQhL.٦X!v .mvAG L)$,E3%%͒7W${nobO@->v[of!73ŔX&sAJI [('\"|T&C<]@}gJA_-qTVa7 fYpb;LS*߶&mmgpq! r r\%~uv[iC~m?;PMp=@m6@ hdz #ko) F͊wrL*ddPx#2Os6v[BW.1P,l-IFS~2n*6nKUZ跁p-U~ R646۠->~4 H1k<jzl̙%{C-6i+ۀs(7s/pNͬǦ)@ mqۢo򳿘5iޚʪ|n3[M7XXgmRrHTr6Z7nZM"9 zobp Ԧ`/Vv,VNBM7O2Nv[eJɟ曟;!n64usOFfBS"8Q32m:n7}Z @nKڢؗ"lnx=mz!M3(nZ͗D$YP$ 3V? f-B3Y[DfcSeLA-v[m~>IqC,W-` r[%ufd5ALRWK#o3뱩2wTz'oݖ$6cĘ*ZRzKzn} u:`E-:_%ۢN~fJFVtFM59ԉOԖ&n~M0*\d+Ry5 |*l ˨Wg2YnKIZ跁۲.eM/]()I+wMp mnIJ^ak5>Q\k`ecr֒<\afJ9ua2ג跁ۀd=Jp v?߆m@ m 跕2ۀM4vʛ!o3o?22~vMmL 60 +v&=YFyD94UH|mZYMcST mo+yz7F.ۀM+grJ:RPl^\N6MT!oV6|ud\ _qK6p[)X_n+~[z6(*kUFm# (?+3Mbf)({J]!*oUF-ۂ.!A>IO.0[b3;%}unn~[(~Erޞ~[wlڵK<駟POrH> 2 n L'#/|T+\"=;zO8-6 CʪPMǦ`$beU@-#%ǬRenJ2R;7n؄MgyS9 ձ1\+f<|e>+Tg̭Fώ ugLV!T+~R^Τ^WU뀄+-j?d1bzeΑd $ >y)`ETB m 鍢^@@O,ozC6P[Ҹ PmU 9assp6A vn}ZnK-UiCo/J 3*yЎQg3La&Caq~[V(kmڭ;`ª6+iaKeA+&EynZ=6ELF[ɬ_7&šDn+(<[a8ʼm2uܦJZ\4zl|ńmn#Gˁ6ݑ͛׭[Gki_*mUbUBM1_ޝAC M,E6l=8ȬܕXm1o>@zlJ m{[r۔AMA*$T'i[Eߖ'1o:A9[V0o~Z1zlsZܶfm&n~۠YDo&g|751.ɬFFcU\MyD'v2mO v?UR͇6"6]V"%rӋTXMn S myTnmpgzQsN >I%eFXmAxQ0}؂$ƛ۠ߦDmJ6:ג@ T@CuZz\616i;S`ߦ,x}֡>OoᶨH rSv L[~6T춸mRm۰N2 ^x! _m݈:8r"]8q㚚 v[hv.sv6lћ*TjGIY6&7NVMan5S_ڥL*% h*:cN3&-Z[MmmRVp<ƍXO듰m}wWwbyCJ6uҲn-܌l3=a^DbIiٽ!9~U |ЧOz#Fٿ ;66Z iqk)6\sv[(vI9a߿hUć~Hk>|яr`SdmKB;O]:VEc#W$YlDl]wCEO]½{*ӈnKj j~sAGZ%&k1`?I֛rż7/igk S)|ҵr]h-u>Ic*:TB٢l~XH4[ؓܦ6ܦHDA'>1mIjI,V[ܬ@ѿuSN8 Eqz#SvmY#n3LkUl h?FaƏ$Fr2tn>#rH*v[6o@ o.hUd+f݈hM;zp rmZ|/ƧLv'_ ib ?dmqAkOFܖI&T/]Ig|$њR-5Equ' ]ܦh桽'~ԫ6z"N\'¤2%)h%.D=(nm\rY={u/:6^K5,f3#MſE$qyKemi?j{w7Kz Ą<"Z1oyn +$o`U,m|m@mfvRs6|D*SnKV6qHHz{A*E$,X9'_eJ-6jmï~ǤcSxhfnK~[V4=hvR/1'T]ܖH$t{>D)6S@ydnv[ 跩vD͐>\mo6YXM2ڴ%rW>Rm|ml{q[p|\W%۠㓔ː6 stiI~R[=Qt-( N'mL4%۠ߦ!7b&ɂsZ=6ޟ,ϥa- 6_n~eZI4Ku99!7~!3ܖ~톝rѳwɐֽͧ?o3ۮiYe˪rN˼3[ !HېnP,St)jzG-c$; ]s,Z-#VMCOXMѠurk`UczGUa`?~I_>( bܖ), 4Xuϱh4TLzl%"3D&$:?nSVMՠ0cGo>xW:kw}!_lYsiˁ-~ou{tݖw_gm{aO}󁓿p{Ag۲em[6깍FbH4}"^yAmUm@vOK/S>+5'}N+]^7(F v[bҳ9rݿO|ᶓ> KGM>}ȑ @ pmҖmnK[$ᣵ ּzͫQ"|M_#⾖*j<4u-5B-oC=4J)-fmț_pɧEuoN$d +o+nP n30lZژ0|[jCpy3LʧEG\aCI 6h v[ut6qcXJ%o [()U߼}&:?BڷWt14ۊ6UqmY! tBnKR0괱ʗN<1'ɿ)uNaI<' o73E&tǦ̃鷅`鷩*(O붲Fn7iPz ،]gv5rp17-E{0go -IiKogVtܦ4|U0B6(vEf|uײ:#t] JIʵ#y)*yZ6bݖ0&WMɌ$iP}S$8Pz+ڤaZ\2wokEA(r7ꮘURƘ‹#o(PܬqSmJ[~/R$Ř&/-dr*1Lņ[mAG0O\M"qUKYdmP`U*E(Ŝt,K$-Y-0t OV-nK[ZnK-mi-m~춴-U U)43A-V~춪EmxdU0Aկ:QNYߦD {c7iH-IiKoUf<me~QGјNM?VTmBfj(r Cv[P~%q#(nXT$[McA-j gJCe;@Mf추-UWQ8"#.pSoCOzTjd[,#x M~iHۼeUaۤK;…Df֗:~l-o٭YBM@ݫ'"y:gfB5&(XQ#LvyqBmے6-e69 &3td|ws~[na)MLqZ$p$!d6A-C̩3w嘴5^$[ܺV*1=umj9ۘg?SeMzoKmnKXRd,r7WIIv!gH~[Q-~b|mzammOM=?1[v[PyR^q~ƣ ۮMݖo C[nãU mҖmnK[ZnK-miKo>6K%2+Y1A v[uT6- YfExo+k S%A͢oڴ?MƆ%cd^-U Ӡmoh`o)uξA͢o kL鷕g5mIBmMGl]=6Dڒ~[rW~lpyT7,H 4v۪)mmr9.8 m)$ߜd7~Ǧ'ߦݖDߖKޘp6[m} ?FȚ͢o3"f$,2U]io+  *mtJuʛE 4ê:Pa6mIBm$@- 14ۢ`A $o~JM9ZRˣ+ A;mՖT$TZ')8!VT ZFWJYIwó.F--I~,C$~Amm@~춴~춴mҖmnK[ڲ4|g(5D+@ v[բmq@E0fL# ZkoSF.T-@*J[v6p[:;WZ lSW*6 ~'Q)\v[!4WnD$~PVmy/Åo7(GoT*g}#oSfG~U6 6oG:;8YyeCݫ-ۢ|$:ͬG~lE(T,F!FmY~&W&xI6.@|+V ncm-UPmݱV]i#o+3=iЇ Uk@-zZMa:VeJmN&7mnp3+†FCmRToB،anKXHnSk /{(&>\BmAپ2kE&//T-@>$!mPSH,ے6mU)m `--` oݖoݖ6@ v[҆ }~Vy@ v["L6G_;\l6)C4thX0=6nty "na귙; s@-a`7~[zl-}!S-IAM>Z3(YaK.אa 12q9b~[ zl 7~v[u-Yߧ% y[OR&]ble'9?~[娍{~[C9_pQyB<F7ev[҆)|;B2*u*IbliNV[uOwBOܦ**C .l%DnB$M~dmxpj6 t@ v[B v[6miK 6mi`-mm2]YJ`m۪a^%dTlPp6uHm:[<~\OUn&}"o>-h4=kDŽVamIIkHrw mYltm榠Q_FP׈LoLC1aUA-}lyݠPC1g.$:6ŵ;@J{9jG0ra+aA)3xV3:6s{s[Gߦ)(vv ~(ۀ"mc*3o r[P6uHmAMĬʧ SM7N[71)A-jd`6eHmڶ|6fp}<mGmcK;%g*E7 m#7n\Q~v*aLWߦ LSORVwSÅmDco!v[ӆ16 m5xf+DM ZMq\W_Sη)>B6%3#m*nó.,.4ʧ~4Am䶕\b[v[6ͦ`U>-6%`Uo0 =-` omd lŁVioo԰RCmq{po }C޽E6H6СCOT7 Lsm۶5jT]n@y@`܆(6pDmorPm)m6TE RnZ(V#\nbr=#y6pDm /f.xjY>(Ǔu9 1-fr[!* nX{饵C2e nr.=^ua^zO_Wr.pբo@NXmD6`bΙ6m)sQUL>QoNN.Et8T><:MVfӧsw|.K]1/\niɾ3}vfE)6SiQ~ ¸MI66B6{f \EE[QO6YI:w\M \>M鈽bsL8{iB8|=k+Y>\ P?R^I&ma'xjn$ԥ);5 yi`;NO6g, m갦_5ޖ c q#[#uӲZt\&t3 |ۊqsue]ɩ6Յް\laU|fj4\NsOʡU(fNt7'qI9sgm n;5~$$p[@& mmȝ))\FxqYs+ot;RͷC6&3`z2'Ʋ-9~2&71DEI@lk\d_MgrQhE)dZq6.D ȧeuCnsɀYLN"+i_.Pc7,t),_e\0)[UH9X{arTt,dnS bmnjX?v!]:h>2!v3:sIiNd6g^ w*wb0,:]9nI.YSXUhJV>0Imsn Go-G#۪Hh*$g-D~{pn>|(1b9DZ.-VA+Jo";=7$267T1m&% J3(͘Ta%ʪU>ɖ0}ӧ_gs{"x1b뎝T&Tcpp۴ifΖ-[rm۶fGjC߸i׮]k֬ZzŪU+W|֯߰6;w%gW)@q 6Цq5*VKYYafg>ss9S?IU|Oâc烇n/1,1ff@ONMMD֦M@2Bhɴ.Z/mmml;_}! }Ͷp7844jAkO+کWlV$RWOK}鳕hELLFAVkm,^Yt|)P٠\eNS:4N:~cJ?N@~J&{3J?9{ﻏ餦D'HtSs' "QElHK)Q5|9*VT*WUT S%%/Tid҃4Bu'['Z]"P NL҆ y%y"6qҎSX,[e/Y X%ف9uѼP>u<*$*KuhO6l^Z>o-a~#<|0d[yX6٬SVr⩔ tǦ*%*U4J; @U6klQ 5XBi5ةbiwj(T1C<Vc'(h;oY/LY$a8zzxudlh'.,J^W%eMw2}:=脡SH`$S4d''tyK8GDԖ(CTܠ .\ ɝx#yM lGZڳ-P/9[.T&Ti$ͳiMNTKDžz-TTʩ].* *gϞG9{d|R6knFPګ<1 -ҝ;i67|tz,[%U4EkUdߩTlSVQJT|Jĭ$ԄTV}6Re դD©P . U4T_<ɓi>xNzkICt=Rtu+fY-sHƈ\}*y'J(*TYT];5jǯR\NuNuU\] a/IߟwlB+N :Y*~&>缶})iiʕ̩FD T4J&u:5ZAl2cs1Ӂk/}w|Kwqۿnn­rV­[+,R2ʣƄDIK<Yra=vӺ=brKp͑#G2àEb& *iU8USSEar{U*lлi. mzJUqgTw7P~k&@ŽHB+!*@E v*Paߣ6*66عGu.Rs** q,T_+TǩN # թ^* Aݝjn\QQآW}ؾ_8i@Sh:}KМ_WvK¦edJ0j>f7 )juercQqf89G)]ZJBySXw|78~U귩ܻC~FUUst|ZЛ;~ o:t 58of23;48 nFҪ|4NuqЪsSBvЪǩ65tjB^_W^ܳOs?o?h MoiکZmS޽~8\wLs^~,eZY;p8o޽ZCw|.tѧgeǣ p=9wکν^rJo&}]q*wPfR4J~I!Tk5TNǯpj@ǯ,TPC~ jT"Ԭ~G}})%d 4U ~C[ũB/<3Z<6O~`X|)4yhNtK:E/+IŕVl#qigJU\OW+j1fdYy@v* I^:>mPC-{cNYSE#Ut :(G-Ta*_^H*5yȣ̉wR5~Q;~LM.M·h:}ɅX'oO+۩1:S_VǩU-iu29εW7~yoпt9%.Uչuj߶\\0֊ZR v.9HrH˥\y$5sMRMc\8Bu:~)D#'UB5|Tk^01TXsB4Pc<\-":Kpkc b@BZ:Zs=N xnU?,[*U uQ3.=5|ģ=t:Eܦ4ς"-?,'CN f*?X*{Qx ZyLs[R$.lOg'VbaA¬jUzLy9=+j{ӪUuMЖq)M-CsZB]Kv:[T+Tq?չJ=57X]PlC]5k-R^YYɅ5rr-ś%O:nt S}*D& |&0&(~PMJoSֻEsH$DhGmZBe%e+R7OBH}Vs>fyL~YW+3ˇ.#]LەΤ郕YvwYK7yTi\_7VCo*V2UJWO{e ӷ4U4Rc>$B4\m?EwS_ŇlfB@O${l u`=&ڨGFbMe W,OI:û9vuZbfĨNhSgbJe&Q:T\7PZ  sU$P-B!4D |q(R_|e߾lOop#W]OW_) ,џ,}+tv;2]v3ݙL+-(RC9TY ͛1jT JI7D%^ϖO>=[yӷ4͙*wjk3Pn^q#[{/wK%šEe8 u[xsf8]g^l!_'eo8w؛f߸ffˢeG|L6'wO <6UT.,ߦ*p4UZhJrjS?l֨o8o 4R6{!  ̧4H)7lJ}\" P#kvz3{2}ݙ~J=iדfS^jK/%f:{ ES"J3L-ٚhaSJn[¬̤ΜʢxTjlʭU`V) Ъ3u* ?_})_N<4K˖` 'F(L9|EKb?{6 t4.񛜑 3BcS+1r4 ?j$0eUZoF{H>nB]6d*?@oNC, pwR_@/L.KMS:(e:z3۝)Zl铄GkNI)ovofU$ן$Ύt{S!j%nk̴7Wi-)&oj0TIO߿?y3Ox_>wX:M-Cs zP z5n{ӄ_C +w=Ga|@bHry,_=맞^^4UlNe3bPr8N9ȄJtt5IJ{y(P"eDʦyJz:sݔ:r}]m}J}tKR'՜SO9ifZ,+D\]=̣-ݝ]$?R`CaP)5۹/)5Dk;;Xj&RnK<\mJ=ɬ:}E<ܾR)f#S]V|#xsn.+#Y3F+4`0*CrphJ+fjC%iH$C##0Zlн.%TeMv6RN$NQ.$y sXn[ݝڟf˚Ԯm%ti*EޑG?2k5jU-_ϊo}_Ev(*mrFe_ /_8%MN`WGl2f -?BRۓցXY+۠h]S4LM@:SB(c TH j Tq uWΓ* `B ^1,@uE #;N7RG ,Jm=")?cehJ!T;\/|_ѿͭ/2GJq_>7mt7wL% UNS`T0EXvRz`ݎ,m_v#1Dӗ߹҆]#1 hBjjj)YTUTEiB-_[wZ/||nǯo\8B͚-*H Ћ󛟼OV~ɪe'&m4 2> /R:zg~O\wcٿrc箎_ӴʜEW^}뭷|Wo/x)kk^y_.O_C_;=>|핋mHE~ ^u~)iY+shNȝOUwZ?O>П4:] BxyJ=Бwx⡣O:|摣gw%}on^_!O{~r߱:%}OG|EG* dT2SW>EZ.}%bB鬊 Pc6]|oP'ḾPWm5P)>_,[ˤcң9zБw<5J(TI./ޒ|6l~ػY/^-'˷\ W#PTdTߠt)0wCՌ+&mjζLo^D}|&WB'JBPs48s=/K׮]{W_ƛl- upW"_K.饗*_/_z瞻J ӷ~?er* umX[w4wIo%Tf;4*TyV&|;L&S䉮ۧW-O-ѧko b:}?i"}BP)o͏ʕ+ -N6ońQc2D xJg({nݺU}c,OmCIy2˧۴U:%1WOM{d$PS_WZ>_lJ=MieuIT߿Sg]{zw_'yzs۬{*tm{a>?C>⯜~j]gwQGmtcCAˍz4'{"^&P>eC>ϟl~l7WDK~C~^1~/4fۿ~[O粰._|i)$OR)W.]lŋ `p|(67>D}q u5Rx0R lK6E4mPnܿqזC]衤%+WRZr0EXeȖ]n]f/Vo\~ݶrdNJPW BBȄuBP uKWBP n;/ moK(\d>"p&14¹s.^Ho KzÅHj٪/TeYfv ՏzdH.n3꺟䫂>5t(]lB..X54Um3M"uWt1?7Pm U85.!/|յ$|uݺ5Sr u˖->Ck DSu%=أ|44CkE47uy`,I_$~Tľ8YGHx[<(k3`j!xm&P7l`%ԭ6х:*ɦTqu옄BM!BEbPl T3lHi-!/mB}8;'󰊓{QЃ8:ܻw%Kqh"ŋ*tM\Bݾ}p05 Mϟ?xW\}+/?{3g>pҥK=B]iK#P*#ԅ :*}kԷK}=sO9uCGv} {~f\Bݹs `J n> =w3'O>qÇ=_7oٰyP T0yxق@޶GSn)WgW݋! #+X\ =u$lz򕓧8zG{m۵APlēK{_'Y!/T; .(#%iWqC#eȄ~Yسv*7?ѻGʜlKS1$yDeYE:XmIX1rsV4dQHC^9uTvt{z"H*ԝ[wn]m AA"%y9}}d(TL V2*NZK-m.jbkG J>aDp$Ec|{[JavSGޣhB-XI0Um.\BcUm*%}!Pa挅W{U9cb%ޖPCSP>BG%Tu J#=$KrUM(a׉.U`7:aL! |5^[LT>{Cy?~*1Vm)r` A`* a%m 섚8̜ }x\Bo3@B}d^ Tj|y1\B=x B5=zBEr B5cǎr TP:zB#]SRzBcGxr ɓ*DG%Qj"c'N?qKm TPO:uԩF]B}B ut$KO B5'Nf%36*DO<O>uEB}P J*}3Oruzܹj"ԧΜy>B y ubZܬ MLfR>;38Ygt%glBSQFag,0Z̚u=~M4BUq?`Xy0Es"z&9!?\efTn1uI#r#Y5jٶP 7lZQ.gSWgϟtwT>ͭMAWܾvs ٓ bP J+ ߵr5˧lJi&P =FڬfPkה:]'vSG9Ne QfH^TϜ{%K7p}I$Tv:'\syoUg՜Ʉ!6<$?e[V ge5 |:&]\t)Aau}@-G!N Ӥk/P5NUuH@ٞqLE^tI$K3f0PEd6 IJ,T˻9N-Ϝ͐o:x6R|Jf\RnPc\jLN.TeS,]Mc-w=B!\N>>=k(Y3͙<뼯v'GF{TsU;9y'C8ŬqT.6!eb#t:,AmĀ 29]uUkWR=Rۍ4}GtХq;L>aȆk7nzӧCÔ 5Cp`|zϿhя~껮>ezz{)Hx.g?-w>e3] UZҹg!rl 5t3u> ;;PM흝*DË1~jg&ӑJA TC-Z$:&CM.T:Pxa(+Y (]ĈsT 1f\}Bgw|CI]jywG#XŔ&ˤl&&{8= PJ1=Tza;3 5QvA +构 e0qp':J_p4jܘ'TW0,ơ]Z#1݌fM7B&ĞjZ2.fC] s2]6+^k3YS U?kE6@_ :&Ci16:ej-P#!B8KUp1MM(0RHmn3nV!XB4pK-{H]S>C{fAB?k'&,0pyL7Hm^ShAQS*SYl7MEJ2(K=R%MtІ6Aф7<_4R-xB©SIFE -u\#,(p^nƑ~u;9l&JD4 8UVGA3o TTPsթ'uu)['.[AbTXB+^{Κ?kE"/X|tIP2]©.l ( T<[*`b ~f͏>hPSc n)F6Cת~i3|eX;/4Q~F:sF' %ķʜΩ_ aGB$~F/TĮ\R_G6b,_Ř|/?VJKHT3?p+!19ɐkQvn1)˷5N 3fTGA폑rpK}5?<:~`dY@M-]kG*f͚3KWByMNB BKBNu &PnMS:b$*P]Ϩ^o4WBc$jQKg79]r TPct R*P:eY=C|!Eغ7PCTuQBPfNP -]ZE282Z<ۦUT g4W·TOMovBmkm%nٽ{# fX#%- BW A `]jAmq)!y@|z%joo/ZNCiJr0.BNu f PJ BB$j}^wb}V`gmTJY-]yӜVciҜRT`U_6˧-٦žɅi{L-qY*G04TL4|c/*PdfB 8eCR) 54SK\2%hꄉ#2<U%TZ-,'Hb]i4a=v8)]:^X>tj&D =xcU+_?w ; +R{ݣq@*Qױ!a4D.<(9N'oQ b{ࢍ$¦ R_nbKx 7]E]~]!+ nurq%J ԬNP%@㥫e4%'I6PT{ kt.FjӬH=B*Th*GP K3.iY.BBȾLV jwܤeyVBTZOUnzQ7#](}la4+B-@>N3Bg2{b֬XB 87 Z(3Ŀv5i,~ɰi^ V#OVsi,B6vKh"%,]Y hȊ0^ʸ['{mrջ#gR Oe\}+l5}.KAa*C St+P5.B7+bj̭:eBV YXJ'P qPeiǫd*ic:qQ?=djw@YB.* BP T>e7Ɗ"-3ΑF&OGܤa+]I{B-P_}y ?&bdHfrfΉrț)!ԈUnBMe, W:VZp(]4ͣkiC ) NЊN3 vI^Qd1e&kKr{CD+IܙoS"ClCKI7BUwy6*v6U)/OcfHLG3ZzcO@:͠4#ydYLYFV{n4nP̓oӝ2}Z_{XBo0 BM*TU5T>Q7&eA/4B_!?.K џRBue/ &j\w߲9k# \>'P ߸ fYjp5R1+7̈jv^Ī/ԇ_$$e+Y 0ر=Tݔ/(TL):5wT8u撷jK9չ$m9P~)KH@&+vSIäMZWny'nEgf;eX%DQ/勫g~te)XcϐհXF*OPoe&T6Ux:Sc{좤P yO&‘./[ F_jNseILs)lNi,yfBr:fNu~ wےޟ'oT'=5vF9u(F>N&kʒP=#-@Dʪ|{r"MMJfltBHcmSPa]쳉+ +2o[+fRŦ^f&jPYypo Kx@Ui={F4ʒ\<#CuU0׀=\NU:br,f|Kbe)P+r"ȝj!$ u̙3RPGsQꈕAmł 5QZdJZ[* >6jS HEHM]TU}vh~-P#mgᅪ;7B]rt U-<%(zծ@mB5j# 9ꌙ3Sk[kk{k[{[Pwmʋv`z ._CݏW R/Ӥ HLc"i嫻(TNU:=(߿.TM dg]fBUWO |;4jH Q>,Fp >dzMГw]/B؏!j uV0+|Ad5yW)XoXQHvXݡ*Oݔ^r*W2Ck12#tj%vj.?T\9QKƝ<*K44#Tud?i.Tn\ϔlgX8RoTB8k˒LO.Pw#t+*SWMy^?zTW_[PGilX]$Z{aRN0){k&ԆvT[3VTUSP5R)_9Zu\A@h9Wٔjt6P;,^wui^yUs+A~=JCt:%:-HCBomNzꜹ̛=wޜ1 `jPum$ԶvPgϹiBU8B3l:w.Z T36ԵRPҼys͛WY9Faxo7kcw+8i0>ChBinNu :@A/-M2ۅ%K?E5Gd{(*1_< jussMs 9l`z:ERf|XJфt 0Z,j u 6 %%PUԁT?5fLJDR "&%xL+R*C)=w8 7HR I8uLf̰_9yTEQUO)Xln9F8jz^1xvr^UA Cs`TP+ɩMPEt*R:ܰGO9geF6f%%(J&%nȡHtobwDy}QrBj P=R`|`* 4-j 5r5^B56BU S#5‚^XB-f0>)$y j oO6[Q3P7)qH]DzFU-ᓫʍ7 -a0>I )'ԺJBuLi(P#-4.^P7)q5XiaAL/u&ZhzFB5 z(}:Y#a0Մ:N85P!Y+2|[JIA;o{BBSS;~#n`BO(A!2PB*t0SOkj֑S\OZd )ݰUx u{T,k׮KdgrO>|lC{{=[P fwj `J ¦/?{gxQ2莝o޲]'THu (B0u_/}ʕ稑zN=q';qȱ={{ rCC6BPwMNgp"nܸ#ԻkNǧH355*#s]xի/H_j’Bv ՊZYE Bu1Ξ3w\ 2^ PMʝ:tל̩A Bv uy͛S*5P=Թt P@q*JS xB5476@ 8B;45s0R5PЃmD{{;6IR Tj|34 P,0N"`܄%P@ mP\WrZMcb$pƑbivB&PULtґ8B]wY*IB%PV#!TK5*3[(8+w%PIlik"Tޖ .PNܩBfƫB*uju BM$T&P ` UL2t?-$Z ZS jOO@©c B5*w* BM,ԚZP j"95"f!Tj֩* P BF B5*O^ B Tέj__p* B5j]pW©*L C hBI!TBu^]P@*Cp/T,yFJqz-^j"Ǝ1y,_#=A T#w4:0 P@&Bmho'慚"!|Hmm *U׮]S 5R-xn… !TSS??G>򑊊l6KӕBkiTP Tnr-_Wkkkޭ[Pk[Z!Tpjeec 47׶S{L `j ҥK?Ht9[^N@(kD#~(z$FG{{g{Gg{ggGg#E>П웎ֶN~ݞ3[[[%LƦzŵuvtL2z2t&kc?l#;hӝt*Ҫ:ښZjkkk*VUΙ7one%*JUU,745 c̶ʢf3746YzR%VUΝ;oΜ̽k;gϹJl %jH4Qa 6[US]ŗ[YE3?rC;J;T]WW[PGE[GΎN;]2QODcCS}]c]]QG;^f?ibC= Ok 6v\r )S]MDh9tSTkWgs>Znnk99٩ƻ:lvҝ <9ShWJl!)榚-ՙL[C)֜joJ{D_c*0g.aO%w^*XVPLS :5V +Ze'Q)^{^N^c_K86Cv,p&(̼pܝ{̢ 9OϡYS~=9~7'kGMJL3*/:uk̮tWUUUw,UאPJNS6bB>-Ma)2ϦRv"hcXJ[?gK) An&VjJm`'CC2KH5e7mf~|;MۙʤdACSC}cCM}yK(jul ep=0eִ6 RYWfޭ:՚#.|V%V`y$JMtZE]k-6'oki65|'vձqT3R϶]tk$Iх Trf ~ Ԗ +ZgzyZB-SM@۩\f}6ReΚ`N:cѣc}LgfjagKXt\YaQZ[`8 %3g @*(h?J3g4=f\Rnao@P*T͍ɿ` 1s:ԌO 0> IENDB`spyder-3.2.6/doc/images/editor1.png0000664000175000017500000011013713003520702017704 0ustar carloscarlos00000000000000PNG  IHDR[u cHRMz&u0`:pQ<bKGDIDATx}xUE/ss=ѫqtDVts鶝nQUn(حM(J44$H٘HH!$d1DTEu뽪Vk}zv֪UUkW}K  *nBAA-!AAP!̤AAE(AAE%!AADAA"Lw̾;p  G&Bb>.M"tAADB|X!AAP6P^@Yák#tCG|f?jBAA`AukcJ 5YQ^c7! KGeD( iP  JJ1 D!  cOU?B[A: Dhye^c!AAP0gt3}1% B aJf"EAAPqDAA"BAAAA B! bG`d "  DAAPO_sٲe77!(PB˼/^|!-~ ѹ^(:Aj>}zx6i&_L "E"  bsNSu֬!X:rB… b>`R._bWUoE+^/_>oam[^`KZ7l@/5zm۶-}hiiimmݹs'GAPQ)`;jTj۳/zd@չȑ# %S B(40oJI[WmԷ7_U~eIԸM.~鵷wvm]iIu[ަmZ|Ցe5ڱk R_}goib;ʙO;::;v/ 77~Wh-AEEq%BwNhͦFomϿAP! +j#}Ci#'>wɽGN :tTGTnlH^?OM!7lї&")*%a"'sh磏>;f~ ؈B$º=ґ^}keeM=b}dѣCO<7ga㮽U-[ei%6-^ޮZO;hʍ\vkպ;vBIYF?Yby} }?ڴ0<0~CK6[>vpƈ@o=&")*JMgDBFAALuO^)o-ۼ+WjNKrP"\'ޱ`GON+]Z^ތ*}%Nt uEOL̢wM+V7hmڹig^i{Î=6wtvV!$E8hny u^7&OoeMߵwvwӶ{wooo p _LRΔ?BeQ !u$0Q RGȉ;~_% jU8"{FVXkn38,%i}I}H!SU&C9F(>i[/{ݍGVl||ڛj_Vy|ZHgȜ͕ ={G&I -}3_|!+}a+lض񣭿~\%ݓF"/n=:7࠹gFirGCCty'GF>O?/~:ۓ'—VtӶb`lWyVvպs#B9ST E%R! ٻw/9 >L}w?==d%=eSLA"F Z FHeRED2ϺJ r-:!Anֱx__~6soWi//8cѳek~5;VK[v6gݓ~uWu 89ЉE9 (웊Eu"82tbã}IrY~zsoщpۮ0'®Gi_3׬bcc:-m:y07R.j<[\Iet(FyRΔ?BeQT.hbtHFM;'L|~F'hW<ⳚY.[`]Cb/S0oTt]HV m0n֩+N:[&9h*j⹾_SbةgO뒅)9y2g[P(!ЉAn[BH "\/Αuavm;S#?7PZSЏմoH+wߍ^Y{(?Iw>O/[鵕_y[{̖R>ď6^#ߪr<)g *J:'Bk?$,ҖQSW3oYL|މ*_}}Ru( 9i&s`@,\&RH×F-;Qb"\54s D(Pl&e#-7VM4)h++ZeNzɲX:KSOWi_ }4+T>-Pvбp8(쫌rcAW_̹?~{ǃpO䙝;[R2XBmvmGdہtC{{$BB@?kߵ$M "TOFVH'5? boPcΌyvkm˷a+\V k.݁|ϟϟ/w_3oCTmt>RJ?Yzx[Ƽq<_<@,ڡrtCp"?3yF8xfv!hkuvo^c)6c$皛 L;^27O3rE?˅~_VN1/Y;ަ'j_G蹄,ey98'Nyc~ՋՓz"<5qX,~, C_C{)YБ%)!B!%-BEGmA'OX67F̹AJ3~}Nѻh໋te?^>0~a_~r# -Pv۰ijٽJyxG^'&^?GZcpvs) gͻ{7!a暨ޘjq8zh%(e݇vh?@Q3OPYT"Xc7<x~}g)COFcw2G݅*jdW!i W<(~{ϻ=δ" b5qeai!6A1a{,:C\91g@wy$|q*>#KD" @A:Aݽp=1gS۔_YWW&ߧ9W)GS~ԬȎIvr} V9u(M;ԽoߞϞ9evڳ7 %z('A3ПL`}oc3=|ɼy?|w|՗_]Hlv'ID9gYzjmii֕\-U>W7jVL를:@%&0aMM I=8qLs9rPxA8ڙ.m&jU{5SbTLA2\\w;g3ͧOgɴSVlƢ궷)N}cC_ϼ1Y]$6׻^}c7\{cS'{Ν9iaGgw@"fqH =q|#K$@@KőX4~DXYk쿅x%E.lq>xoRm#$E>/ˆǫGLRΔ?Be^%jZ>kkkW\IH&C}"OWk&hkmwhG&[5bQW\bw۟bs 3~ Y}ZϿז?`c/b4k]_N_R߼_ΪoIZvYl9{:D!H BRiiiE,͛7fTᖦ1q4_՗ ѼƺC*].U60p_8ZŎrxJ`pڵ|84c cfƍV@MD#BҎ|os3no3i&Xwas.}6_CvwWNӌc$"$B,aƶg~˞5~o庍[߰e{7Ej7EڍVUڰqKæ[ؼq B(DeQ,BALw֭[G>͘12+?8t޾#vQs; :Υ@PpC !B ([}/v:s)!@As_kΜ9A MzBAPQaZ;kD g}grY B j4md{w=z&C$BATD61S+~dw-AC? DAAPxjOv/< ]! "'.X[J8ha:D@ycǎ x54[R?p\x zP D߬~g/޸c~^'ЏOVO!0=jhm( %^#oզ[QR}]^x zɏ5'eȟN_wc||i&;Y+ ~EOsp h GܱBLn:H8ʕ-IDG!ХEc___̔ƻcȱrX+\N;vqC龽[dڰaæMhyF"foiiimmݹs'}C`\jB?ҏ%ī́&짣>Oz3N|YzH;S};ch!dl"%B$.f"h ЇO:5l("$ 5ԓJ*"{A!k'fROv2ȃ|SZ$?.z5!ȟMSЉ'Dk"SB~\K7L4z :8x?Cպhmi裏$\!Bq!}l"$ 5fA8,Ҹ.~0ڡh[_yi@xS]wﯕnE b!{ɏ^M B'Bj_ٹgz1R@/BoKsBˆ6z%Bׇ],' i/ a1=?Amur 1w+׬YW@zpEO~xtMpYo])o-ۼ˼>|'?|u2mCq63dSZl?1!$B7ׯ5D}pқӴ&D|?j"Bj$'dcDDhzdHKbr0 ^[E^۷7*D֭B4Q#:!vq`e k^4G؟H!MdOOgYߞ36s,9:J)-ŸbazXvdvvyT8[aqk[9'+7kG^[ndsUDH{>LlO5ws;;e?;^/}GGwh:@:6̟{^tOi߂{]W|?1!!,[/j%Zww͢х0D/Ff6Wx.dl1D;tH]Qw>nԔO/sR?Iz@+3Ag"?<`ZϟTzTpBPZmfBj ѿPQ[r̙8Sm /]#~I# Vܓp+DRϵmxgA;}FobI`DbΎW?6)5,n3Hƾg %iL$i80Ο2/v)*"LSjPx |TϧIv23Q[gpyLvFnO_n*f'"t?*4")~J٧Hϡd3wԏ*sկÊzIzP$#%޺?1!FeĉP͆*xk6WNǦCNfڽ{7S5 €P!B8Iv48^k>+ y~hGYR[k?^QC瓕^Gt:sS`XDh.c-@!(Gmt!-h" 1@$}M -9HcmㇼmfQEbR N4Mh__8IMuץq7Oti;V 8O6FDN& GDZX`|#%4ɪ2;hGH;tJld {SJa6?I&#͜:g_5+UnHm[0~b B!; g&@ni@}:FO2af=fO 1檣ꝡǫoW;p[tLza98yJcO흚(rG;Lth͕\VWWDI{\n,A OWk&hkmwhG%* :؝ùO#HzBz㹘3T=yί S|NO DAh#tנrbb&pãa apȖ1k׮]bch1c7vC>gyDfdvlrIK{'BEUDPt{^Oi@1 01h#$80DJT !"Fk,FXe2D{D" I+B!($Ba%q YlC4ǰp@!B}# 6B(P%Btx=o **"]"4NF|B*ׄh%{ **"4sp܎32k#ľ춽9qM~R` W¥3M"!B-۲#NceOBAGGq@P7eFпU;گ9s~y:GHQ ¢$B{е6B An[Bq_!Z)kC_|A-:w~ڈ(8%,HȏUp.g-43}T՜ [D0#Ӂ89w1ߧ ோeFhh! $ϑh4_PU%oy-bA:@0h:)Qjd<:;V) :{V):Į9))- |`/11ށ yK&\W^Ժ纍͘y })<pl_\/S:pgH)^ƭFD>DASI nd;ΞeLHQJR,qf*Ȓ(ǎ!n4#KRxxcWΊ|4D" @%Jq^Ų1sKCR`#!A4JKK+bi޼y'Ő5KHovAp$l " " BO?3CDNgΜy^Ν;W_7L HJ" @B B!A"E"@ Xj%!-毼D xKWl !Rtwl%'-Ts\I,{ql*MV^rc `pzZ\}F2ID~N-71!וz"TE"T?Nb0? ;,a텉!3$\n+Ѓ:`21 6B"$h 'iE ZnLӮ[:opkCHQq!;kjηYfNH0dgh9sdnZaPoJnx2 6B?"$ܿgg'aGGGkkkssAm/Sn%"}7'RT|Da [rI4O*Ʈ:P;m:=9%NasxjVka!3 AaKK͛ׯ__kο MUz[gM2C 8?8F nD(sCvX޹@zs+\0ФV"ϗN8fVJ 08b٘!h)Ov"  aF, !7D;r`Z)9x\. @XBA0gmDAs!!lrJw)m3AP!l ,95C`+vqcD J)kۘe0O6B?ek{&7~j,>8+>S:AEK0D/PWYɯbY67"K⚦.G8\vM>>O=&]t& !06't<i6ڡüi3 ]"rO L*iLbO$*V?U@M%YyrDRbDX<>r&#n{ؙyM)0nbwe<a\<(a?@XPDл #B,T҅B$Kj O" *bw !F 754jG5gO8=@8XSG)*mx ´!!w"Ab!Ez)_Shf_ ٓȣqNܺKL20jf6B8!6€DM/ Q jnxpԹ F,hFc#o*I5g`{w\x2fV3.@ 84)%p9yso*'HXɬ٩/](og ȯ$a"`# FTa^ 7t=ml̫sutHxU鯶Hذd}3u+u&/t$-D2"9i(qb`fdtܒgY:fDIH2gVdv{9T!`# H d8xryD\Lc?:lƋ}EoSg7A< "澍!=I+EQ/>xKWl !R?BRDesxC.BqG3+7LVIF42@9XcoBDSuiWY'uƬ+Ο|[T3޻;so?FiYsuh ]Ǯ$Vs{Y@E=5fFH8p.OG+/jsf̼p>W^JHQ*aTߗ`54+m.>x}(SI^ǞHeV=}R,juH4ߓC 5$g͐=zK;YDV%u2T}R MLCnFitOL 8H3V3d#$h '9E ZnLӮ[:opkCHQP %L؁S" EA)n}~qpk#$ܿgg'aGGGkkkssAm/Sn%"}7'R_ү"D=EIy*OI!>K]!0{ipA~q?DnaKK͛ׯ__kο MUz[gM2C XD(q;8w}pC. ɇ~labg44ΫX6fni6ڡC [x7! DU&, 7D;r`iַ! DA B  ʤ! a.!"[E'\:7d{^^9SZn,]fFx䚮#WF;tȉd>q]cj|`oRYj"tů{.sUp*@IFJIN͇3WySƬg.]Lze_1ر]dX9K_R @T6„#n{ؙyM)0WM"mR +tVf&c|\tnt˜cρ6r_1:3K:[ ,J$ a"v>U ~͙k8:@KCO7Aڈ@ ͆m"ݰ\,~DؐX[d9ƥY-'CQcLB 9OޒA(6@!A-:w~ڈ(|߶^߇bә3f/i"E|?Nk#\Q:O˱ :Ն<gcqa~!e 5`9xJzT6 !sFxՇނINh4_PU%oy-bA:@RRϘ5^ yp/i/Om˱#2{6BAжy @%^cp )N2s/sA !$RjQu[Aw =Ñ8"@I>B^ 7t=ml̫sutH%=" ;<$uF0J g=z: |8sZby%"L|p z "D ^7i-7]ADrڡC &B_qi悍3Tg6 P^/>NTD[2 %DHHID_PK.na[icߍI])Kďd+3 0+6B!0OFz~y1C5l޼yjjj K4iQEp٩uD.c:@{/, 'VCh7c!ő%y96"e1x_KCA ¤mGHy- F;tHx~ra# b$LYB2<$+W]"4O\X D6m+f?h:@%ŻXpfU+_8 :K m97%;A0l;:<ˍb)*\P3^"dW Hʙ| , !$KA"; >]+׶(bcci6$.OuBLC2w _%!VO:nnެҿD^%˱ ܁7%;A0lxY:mmDhJ)ʟu(`ADR'mŎݜCw9w75[zK쇞BnoVڏPp,i!A"M OGysX==W@6& dzMwO߽آM-շۏ)FȠ^%mO-o #B =GU%Gl U3TCAl)ʺOϫ C D(e^cף˸\99OӬn>^c)nBo)^1@p>f:%s!AFH0k=4yȂmCHQf<ghkfaKY<ŝ[ [[GoV5A B D,Y;q޿^;mC'BA0kЅgu! !5@ B DX6BD" @HDeCJB;<B!}AP!l ,J5C\ '#_*N"4U^/}---. !UVIWKeJmm mÃA"Ikz4_Ia?:HPULK&I!B"ZF,wpIvd¯m,o[j(&M}˾p;<A00cn{ؙ7nܴw!Ҷ05DhDo|Q0Z֡\?Y kbX_+iq0"BD_BfF84jG5gO8=@8XSG)*Ӽ" "$SfC ||SDJ Y3}!c 4pcD!B@hl BAOQsÃ]6bAs6 (mBpnV#(,4gQy_5_Î?Β[6cD2y K˯h'u!vicBl!?X3΁<=*?_-@0 ͇()"]ρ(F6:D 6έ-]7E,HHQ r2^^zX?6[C G3k{t'K>_g P[jXi1 (f䠪jA}@hEa WN8Xb"BxDhGJ΅ޔ΃ 1APQM(T}:Z\yQ6_6cUR:@Ry6!DJgZ8l{VPH<D$k_T5Pb d vL, R"$c}7, DZAНfiyF^" 0VӴꖎk뛮 "p9!RT!υ= 0P>̙z8zpdd!z~ߏ! 6m%Uw0yʭDӱF@V"%+=WXp8l1 Hk̖ ah2aU!AsFHPiҢSo칉\tHGȉ6FDcX9uH纇<܌c,d%ց'<DAA 8q^Ų1sKCR`>4w"  aF, hGn J4l=! !5@ B DX6BD" @HDX4ςiFrJ#BAY&Bsikj}MNNTYEs,>ZPh4EyxŜa#*+ˤq%uLͥ3qJ½i%'9& aa\`JhsL- ~*eRO.'kYECLJ)N.v0[%?ʋ,:L~BsFݶᑱ3gGTO~R`y.axfmГ!C_eY$X[g:ǬsyP E !phxՎkΜp^{p>!RTM' %BB> %D= m#~  a?OxH)"BEdrfuA FXU}I[zogX)Mc/k6*VSÎ4Hƾg)scbJ'*5v/k0h#Gs6C& xĆ_xa4`""j a>M(T}:Z\yQ6_6cUR:@tK]f{!H,U޳|}Z0_0sk+1A(;7))aI8.^%T}*" ;UG Fzݘ]Wt\[tֆi)YÝ44OKLzԩSÆ0C5f+{.c@׏m%Uw0yʭDӱF@V" x,,fK6m1l\ B3TC",H!]BݦI*BN&r!RTDA1"BA "B B!A"E"@ B(s"m-0`@B Bvikj}Nz,\>KhtaJn<@6BDh#`Ye%'.^b⛋%RܙaB5˃17Fx䚮#WF;tX\D5=7;q]cj| ;{1+υs\]8èR*_@f#n{ؙyM)0^:q"Tg  Cir@Pfuew0U>8ʙ DAlq[U}I[zogX)tXEfQldOx$`'>tpMS{ GÄ˔V^~*2ӥ* A0l&>-uu/1*A\]{)R E)lA ‚TK.na[icߍIJ>D(9<ޓCC@ Ԛ !BP A B5.nӤE!gs)*",QLjdI4!E5CC 9_@cN@ =Fs۳ aG8228b٘!h)!BA0kЅgu0'l"%"9AAC B!A",!"BA \$BD",RΫw4P) spV)e'8kwBTD!0DhggPLInK)NH9&0܀]8P.41 a# *+˼Yq:%[r_JAyY!FdB !D6't<i6ڡbyDT 4{K&މ{ֶs̈bvxlE씖rIGD(/+Kr<W]%¹5a%=O== w'sa& a^?<2vhiC L#~DÃƢs.;~dw| HF(d? {<7tڪ)BM\"Uל9?`M}C L[@9A+XB|Aơџ^cVq "~c2OWuE6:[@Jvw^E Zmc樍eQ.OCRh7-ȿeѕ+ nʳKɏlKٗ$ #&:a%l?BmAB0N+"~M,O5{ }A+vA"EaU%oy-bA:@R)|pzD3k{{:6=@L%{*IYlA#Dj#PD{WF~PSJuKPe~}4`ry""w^n0i"̸ЄBէŕnce3f^E8Hk/C (/"%Bb/.2\+cT6V)f=ᬢ B@(A/z-;N 5e#B^ bUus=yŋ#Ks$YtY"}ͫB欍p1Mn鸶 "­ R E\(M쓃ࡊYSl1C5TDpa*Y@ۏm%Uw0yʭDӱF@W"$gJsP30 9X$AParL!D6BMUz[gM2C xP>DNO5$:ekdˋƜA9I^!JuE9AiT@*5228b٘!h) DAA ŒYBBov0e~85O`Öm`&""AAذa#@ Bl B!6l B!!0[>^-9Mdآ kR@OCF|P$*'ٽHjb4EtOVD|Cɏ_b!l ´95Cn1+O"Lp .JqP^D(&vB|mqbk"rg^ސmb!"LUVرq%&v0M'? 0)Z!YB>kY"X8!Խ~baj=~rMWσ+i:bRM|drHdY'Buŵ(m!!PtL;| (}RuPIih笣B-M'I/e,n%zə[n(G(A5L3MfmFR)6Q_tvGΜuS=m]tHid0}D(z"-oA~,1h92U d̏`$5guTb,=ʽi=U6Bfڥ)-(y2۔??V[ϺFjyJs"tm4"/DDžjJ$~ÀI2LKƄ懼AP߱.3SL' RtsbajmU՗tq)JU u{Gno0uf,L<'8[  z%)MTcQ#a\PbB-uu/1*A\]{)R E 0)u|ATYsp(/J AI"l<$!l/V `OjQܑχW*bU#KS˗S2ߊbdJ˔ĝn }C#ciV Ƥ+t*p, 6WӴꖎk뛮 "p9!RT~^eLYSa Kdz𸡁"žP][zɳ-grvS&zC0 6lHm/Sn%"}7'RTD(,lHc|1|0Hk$dFh!,)k&Ep'isut6nfƆ 6TKPiҢSo칉\tHGyʑ%~gbƏ?DœjU!V+Y 3T̔Qi3BV+A!6l&y- F;tH3%,<KDXl 4ܐ!ذFsBov쀛oy`V"BzJKK+|tҲ2JDAA98}k 唒|@ATDI!"BA \$BD" b'BAY&Bsiwj}Œi  !lP!_Yef ;,k'[ @yd#<~rMWσ+i:,G'RxWDh2c1dsȐ{ 棍/:m#cgκ橞6.:4bVw&E63.b3ЉMe[gAF84jG5gO8=@8XSG)*Ӽ" "t1юx7 槍eQ.OCRwh7sgk7kgzta&B%7j;,$VV5켘p;7fev<'Bw+=Ǡ}aCށ @yg#-]7E,HHQ r2xG3{Ge!Ji$^c߳3٥Hg:un>~E٘i'=3 mJ{ 掍ЄBէŕnce3f^E8Hk/C (:lBDOCE"A%\+̾XPD΅} 濍p1Mn鸶 "­ R E ,BΙ/BYyN E?¶T]u)NǾ)*":X}ϒk.p^(ΘIk$ށ @yg#K4iQEp٩uD.c:@#KDhQ,)E+Y8p9`|*Fa$!;A0#ihWlmC_ԃ%)Ñ\!A3f ]p!ڑ[2;.''6Բ"BA Bk AAHlDAs!aa$B+.zߺJ{+KLG[NF1fAECLdƚu)WX^f"tGk";q62&OfQz|naɽ(/L4+'R2DN^eVk a!"* UVk11IpMBD8uO) Y$F!¤˺.4 ", kz4_I!"'B/9Cvcbw6Q! j%v`IoJJ,bU(p X{_͘H[0s&q);}\ CNg r;W=ͼnR'aReJ Rf~SO$>IUD(څݻt?M<" a_tvGΜuS=m]tHiۻx]b9J C=vc6Пu i#4/b.23..1 m"dg\˧6rW8V[urv=Xm=n%{s;V-~'/<+A;})M&VTe_'.2/ID~EksV՗"@Ei#^3' qtH/s]Fh Y+C0kb8 Ϗ$PIVkX9,n0zf2ӇfxP^y%zrk\ݢ vKl ȉPRK~QJg牀\UR] UMnØ A "6?<8܅i#4wh@R-fnl=0׭SbWFI;O'8ExK:lcdDc ۏ5ݔE#6Do]q&`#[[]"d/i"`vȯt!"QU%oy-bA:@Rcnwl7_} {3TDȼQ#X Uf:`F(uŞ~DHklPP=嘨 4&S!Bw]=InA{qk,G%ߣk,5l̸K 5%Bj#%ЄBէŕnce3f^E8Hk/C (MmwXGBDt_[y+Jɼ>;Z!oZir]fHχ:#K !lVӴꖎk뛮 "p9!RT!Wyq}Л}fyj]YrkŸ*;1",pa@ힿ&Ov:HHQqC,UN"B)fsB`Bao "}"̌.nӤE!gs)*",!9KY)#yљ hXLi~ "B b BDD144ΫX6fni6ڡC ,We]) B ft~C#fBNg;! D@A"̨! a.!"ƒ ն iZA&O٠ 0- A B!9%Z;djk#BZDK1$E$ u*Zy;4ƢB"*j"$+,c'a56xP\.׈0Zq4&7˟li0/ D$ӧO_pam6ya#<~rMWσ+i:ZS)׉ |*vP\՘ i3xl=9V^(9(< Òi wA B"\pa___ ) }a_tvGΜuS=m]tHiDJ/ O%A><(k̺@a ܚ1c# 3G F(ic^)q7I%覲 13J#`_ B@ R/SN 8tGi!Wh kcR Ee6T?!o% B_C0 "`J O4(Y aDӓ"̌[u ;Q E>r.+a&,ǬF\ȟ:O,;F*a>YT"zPJ=D} B@qqC%/>xKWl !RT9e;lFE+tӎ'S+fallAf_LA#`N+c~׮+9/0qE4'R1NA^c@') UW^Ժ纍͘y })6N0豒tFqI DC9Qxn3dld k/L5C΃.0Rybd WIGꔔ%Rl#\nLӮ[:opkCHQqO>L ,AX3d1A D888x (M#l=I]7Lr+!t컑>)6Y0=qטq'{a>klA B0mc A B"WK.-++ 56MZT"|vm=7˘)iQT#K\J78%k,Ӎ"&:I` ZpZf-ATDXxk44ΫX6fni6ڡC LA#"  a>kLB#c юuk( ?,! Du!!AFAA0T(ӵvW?e!AP!l ,9 1?E5fbb2bd$'E)Bؠ f*+Xc5Wc7F0NaR)\> ,TDIn=F;t9ǮbX % 嶥;&;]kec:łsLg =y$>IUD(څc/ғ&{Sg6>c@2\R@ٵ.i%h4_8^V[N[7yR@Rwgb@{>%"3=(Ih{%-qWxe; M׬(ؗy0{:8& Yg;{D|R4xgBlR}&n%;c+1jHQj"d帐yA !R"? DCDՓ3jJqsdllV:įJ,\L~HExNtY=~$BB~rZ~'!6B/>}'NW-R_ГݛΊ-R}R!a!fΊmӔe AJoLߢ>0a&,37c޹&3flqcQ#1Bi7;( "KT@ʎAE$(.}>uW/lݿ NUSUV0???///;;xAG&VDI˘SfLU0B! ;G8Z#MMM=uIĤ$%l^>֥rI`sZh6)vc=KPW[ԳF#HxoLbWW1wyр/.B+IW*9KB9hE>:#116F`0B0hF#{*F"P0$a0jn>c‰Ds`{1BÜ%kb'1B0B>+.in]K &>xv`§g8:xqz7?8z-BhyJN#"#§$j"O%FP1g[s mR"7FFh =.J(Enŭ1B$rixGBzj]Z#won>u+&Ykz{Cv:EsСb5oߴ)ϯvoo_W.!F#D;BȨ^5)or9$)9wl#'a@aKKKuu5}ۦ*i1BZVhiWW!װ=K`@Ν;LfHБ=!Jmrrźu3iڤD|`<1¾2g 9 ݙFZ1Ѝ'网?2 #_J#h!FfLj.5B1BZzG61B` #,FX1ҩȑNNedd>o4NJϽrw}@yvDFg)@2B?~i!J@-F qw%j0idGwhZ#dgH6O*{A2{OPӁ!Zcb s6;q% zDv8iz;kZ7&«m;gW@a ^1bv7,K &>x5BˢV!|,v!+5V#DIdHyк`0j$ J}5*urk8N`+\e R8%'br=Sd Ӓ9y]|#"zu连t8@0^1r2iڤDRd5hP'zyi;i;<.wn51B #|H!_^Y ӊF'DqB"${JLӧ1뒗3:̵*zEgĞF( ##䥰X/=!|S~MJ]]!r,#,m%1Bnk77Fq[3F(:YdNr! 7BjIa(ɝQ$bT+pIPև>MX/T:J[%R9#4&r0Bg_>/aŪH/AH_vj(v~ehL7Bv.ck!CSIC0tFhV4&01Ba].1?? vmeA:#=rP/KLck}HSS}|Qfw2d#g: #RWόQa7zBK)F~+ jD{ 1BIHأCCB&O[2B \6^h?alK?QP\+F"i7WVTBrd(Ҁ4&UKp?z 'VJTD!ƍc;F2wQ@uVt_],mMfURweE_A엒7aP stCEUm1a/U^a4e;wq;MXZ~MW9si #aZc h55B5F1ַ}w}(-BHL\ KPk,Ⓞ=KQ-F;]@>#lnn?q B+I6rVAVFa@0B. #pt`0B#0B#0B#% pF`紴TO0B7h˪*5Ga҉2M|UԩSzRUx6aScgW^@3º:!hf8~{[>ܻwk*++yUVW.sj'3?fG_h-( َSp@o`k*je]cn 8{o]f=f7ق6IXeaÆ۷F 7 .$8}`\\|íƛ ޻ٳ'O=sLVVOü c|ѡ+R?:=ff_sSxϲofKr_27n444ܾ}޽{4K= СCAGsXA@`-e-)!sxLs_?<)$<\Е"$ʫ57(mU\2ۍ3=jsϲl7}nǧ-O[BWܣ5+[F_ٵ(t>a7:8?qOu>[LnM۟]]/]dR| ɓ';qXFa 7mT{FUuuMmŋΝ/(V]}Gmm[l1Qn^GkYuvH\Yo~v=xۀ;}X\I0ųd+yvqrFB3;tŦFhbOC{ .ah!GH5}N(f}[޽ZkZAm;.)ھYR9>-¦+=SϊvZYy.Κ${YfTN +Brl2} 6Є)-#F I!mYk|@8~~~ꫯfddpd#߿H)p}յuW9}:zL Rp*zf1l׋ߞ/]3w;%6l_/O--;}WХN̟4xif_ZH )%$Z#,//1bK/э~wrr'#l诣I;~z~ś7=J}J(FL!CjVH#""?s& ^yO?۳kse_M*O:[vrw?ZVޥ\mX΂ Z ofȼT8mkmWgKbo}*_ j.0.hD);ٰ`6,ɇE+\3v&]Br\N%< uq7àLW:mCf..|/E.+m6en2 7BW@Bm -(~Ux{Oz< lq3lD =MK.]hƅRYeC y_{FX_>]R,F}}ٕ¢Yw+,~'O%]^S[3EICs}yF'.sf=a)ې3[ܿΝ7yc{Y}/&) fJp_!=XO6v:t15gbۥuץ%nwv@`}JY6pR`FHڧd 9j-yrUvS5‰^mmvv6ߕ[N̞I'l5_W/~0BKuMTceee?v,Q?*6H\\!8k5`©F;G;cǻgh>O 痁o'@s%}17FaD >eIhB %/ӳ#]}m,]҅ݸPɘ4BP_+l#96!5_!#Uԏ.?1~x=<׽E} 3l!'\XVUj;CR$f2FHOcRo2ٺu7^ {= FaAQJ%4Gm7d3%eWhē'K] 2xoĪ~dl޾KL[9!~O^h+SSU˲ߨozGq9-ȖŸPj{0J)|A7:J$X%8XΜK OjSu[g5 h(߰S5V>m7@[uf%6{ gRoޡimm}DCY=~lMfnŒ<}N~؝왨L2yHrݖ66.1'D-,2s0kk_A%FH?Gߎr/ZU>>>0B`R! VVw[.^$M^s>hރ1l#},y6o(m~g2X-eo&OE,˖ŸQAfgƘP)DqAn(MS~GgٶgҕKp2|Ҋo=KnRVo)u.yʇ cKp^"YؤOoԖި)ׁ o#K=oRБt0 @c)ClN晸dN1[G <&a?2l#3歷"){߿eOĵ2[ReaY/ƈ8 ]@Rw-CmϴFkC:Hv+|g㶏5sI׻,ј̸~^=Wlv&z'>=N˷#)"l{Bsԃ_N>} 8ppVۏoր*_#0BҵZa!$?`9TFaPC(P/;b tv cHRMz&u0`:pQ<bKGD4IDATxYǙ`601C0hز,v[rF+tl[%7I6JMZEҝ-2AnVFdD.q*"3#?_VqYdX]2?#@ ,*beO"7@I|ӌbJ@ :iF44_s{p@ K:mW<㊐Uڑ2"*_=@ }_[JI3M`}Qۮ vwUz˅g~.oRs?UL֨ڀ7Ƙm* {އTxjقs=g-uĊHUq|Rv*Um;3e';nϤ͏|sus{[p7dD6^"]r Kjۙffn;3e|2Rgq&pWrxz75i Xy˃OOX*m;3`;S"ֿi"fkcza5CvNZ E۩=0^I?&I<}0c{kfUld˃E#}3vLͨcwKX.W-9s߹MkfHh%]HE|QtvrۙK,} {c˧MgoO8Ų'\tG )lO|6$iFlVlkf}|#aBfvGOm³B&LmK ZmYw{8p`ݿo7pÉ'RVVɓ/ l0 h]z'|zŸgyfk©SL8w\;vȯÿ?wwh=~qo-y3ȖߴhlmPR8N]k.va;.&b|+.ɚwY>>gq9n [l9JwW(aM̺qnzK{7b.̑\$v_;3{wI.|Y/{3lӶ;0mkӧb{U]d&5\ey2㵻c#|napd'<;n+dkˋ%Ep`'936E+`;vg'\Vr\ض&p뭷f˺16?ӧvu_+^.\Buog{/]Q$%sm\\c5g#v γk\XujoNV<^\԰m7J\OrT*֬|6jL!On"LcS%ޜ)WzmeJH7='v7;ڛog]w޿}f/.]V{5+I˨mCi٧ 5T9ٮZ^m^턖`٫jenk0z2c;vO\fS-O׾&K?Odki;%|fWf]VݛoK_?V4YݛqF Tϵmu2m{NjI v0Tg.L_^xA-rM7}_oadY:ϟ^PݻDu~okdv捳mS*uko7&ݞL=+qە*b;&ݤeVgȫ>MTfc<29KRlo|#JE]v헿evoǎ-lw.ʗνTwo[Juj}$JN;Jtlkj/-7 Gϐ*v5)4я8~%l;QHԴ].Gs1&{NW'Y'v7/0?\uu~nv |Yn]}v_v~u?o B1B&OH=wf1H]kØ3@ls1vݲX6+Ϋ~]λ{.]|'k#jt.|衇2~Gy$w'&<(*٫bַZT{?n[6 R/}-vO%[=A|a;e.TjQed|x0۬׮÷ޟyͷ7޶۳{onqpɣB;vK#{_m׮]7%ݓc6ו Uvlvvq3ɓ'il}?X.mvg'TYlݩS*9sv/q`;{Ll٘Kh͍`$h8h-Ɔ#DXSutX˯h.va:eD#ݔASU[f"|em'do궫Rv3+J7JV]TҶ Wpm;*wvN31XW6Q*K?!dkFiII7b2 wBZ,'on"C[VmyHŔ&D8ueYΪ>(bKJ\Z}[.5kz)&FCN?3Lͺ-bys6dLI^6mN|qʍF5`;plܚE^n+ 1WoBЪ>]v-Wgm?EXN {[k{?ԋC9jwތ:-\jtbb ͠ŋ/uq}UCU?9]GƜ_N< ?"UH:#ֹ.{2!EOb"ůP1yJE: ;u٤`;lvl .c6Wvlh+`;Xݏ=жv@m;v5Ĥl/3h&y Mj/ >ͪ=)OfwM/x]4ZM[rn{y<ٶX3>OsNhyMB:gf5υ5f+&qn٥vY^yu<o9t]<ÃvY6&Y ̹=V[a(aAbm .].n84{:F=Wn,&nMygHضHJPmr)XѶ˿7W9j68FRulQCA걶 !e+xx{{*w]NgU\F_D?J hv]}du;#> X[F\`['M^ \^7~~Eӗ[ 5j1 X%91$Z\ienuʽt0!ev(},sOfuywOSl4J^MZI8)>xajQ4?MX۱) g1R?ۑ%xFv~EJ\7Fܫu-!s.I kQQXHcتma۩R%F֣X~m')9E?y;!{B?b* sF;|M'J g;.cμ%8Ϝ~Ţ[fݏڍ*jRVZyFBtمm(-cd*%hNOv׺}neU>d1Q×PUn@v˝EO؁Tpw#nۥzQQlII#Um vyם~S>GGpF }3۱n>y% ?Fwя{.G*HGE:|I(tׇv^mЄY[ {t[ݫђ_W (߼v歏Pñ{j=z9|]+oY`;l}υer{w;F\ X+9a,Plj+sZK~d_iCp ]ffqډy=3oM㌗6i7`CY$ g0NQ(}hI~MtΡP v"4#YAZ83!zo6woAa? vKݶ2?{W[|)'߁{>G~iS(@޿VH ŔTBQNxx&ӽG?)G v@ `;@ `;lG l@ #v@v؎@ kc;v3v`;l`;la;vl& Ñaksccsۭ*v&hƍ[~=\F/26+ؓ9I2v|is2usԗn;+]jݦiO6Bz`Nݸh7gAB΍7Tr)˒Z&h;C z2[%NRo#og&g%vfFvuq*'SRo߷'>@kk$nm7n3'vNze v+ضszn8.Mh`4E+8gi"[_Dخ3vMٖA-6hWC3~qt m%:?j޶R6¢'v+iv1lmaA`ճ]lBsIɬ?M&m 0gp:yNa Vv o+Q c36DRYDc Lۭx<l]`H}uv+^l4nmWѶvخmd,mg)Y8Z(-Ss'dNN*uvc0fsp^Bh\aB rA足"6*umRO:vB{I~7b͡;Btle34(+3xKp@]>=%~l]n {2ۘ֓fhUnmfm-'T خRi|K9@sm[7&cS%`;RY*5N;` ?.e43ζ3ޠQwaldhb 11G7v=53ed;o涋-zd;kL}I*龝`;ErbxsNoOW즴ړY7666gQO=^nsODf-2Mxaj@]/ <vn[oy dx)eYF/6v/,jwՙ\oz!P-asخ1IӲ'TK{y)!;Ƌ)'4@zz s9|絓+``;l`S_&`9c(`;lb;o't LY;#K)Ioct͡ʽ:*o^}b -!h hY(;3<݄R#Kو\v?V'C71Hc8MDdgʃ[s[?w-G2 ];)BJ<&ٞvFw&YkHbܚ>3_!!<`f7[b:9QAe7/< 36?Å>Fv^&kL{ mn'ӛ@C۷NI#Dʂ|z{Ii۵ڶʞqjTUڿN3' 3"Mv4eN,2}~cF'4XƭQq+ZW 'm ;D.[?]}O;s;<݄rPzί93$ׇӘZ\Aj=qmO5phÎ,U;3' 2rw&ӺʿLpin(*C4lWso/vW 䧙j~ʒ|Ǟ)ϞfNOcnx/-⏶$gfֶB)j'x$VAv"v=}ZmUvN KC4yz>B1g3]u?I.WŹ[?rg3#M^!\q" oz9ı\@\qOD܉WPBϏ`Ùg;ۙ=ގNHl'>x$VARS/Reg*[bBY}FR1J~dK^uӳ/<.c)LwcqELC0FժL7QmJ2,n߷ wb3cIIy&Q~_Ag":OA~y6P<1@c[9ғ)ؙZ OHc;rh8lBtj4vvm0/p߅Av.X S|V3Ͼ5Q]B[H^a #͏Dގh;jgs؂a˃w$r38݁78a46;4lC]`aîe$r)kpqJ`F"ofbil-'77fΰā::~?F48|<<(m;vyJ`{v0ڥ)L .4/G1JKzkv}qFla;vڮxq75d#p]5 ϻa陵x#cG10`J7ϧؚKNڵ+f&uhWVG)A],vnŪK}Uv&7݃'`N LDLzU<8WCK|]A܄sE7r$bIx]+ۮyX@qls9op(W(2w3ij(+1>ip6" sݔa~Nە_Զb(7d)l)'~d9N8J3f1z4oE ]i3sE7$X6.unw'ݼm'ֶ~qg`O ̨ 4t7,o2]s=vuPa3g2jy0vL>Xl?6C sZHD#|&M|^IK~:*!bvT]ʼ$v݌V~ ҝimGƒک9=S&XPݠLLAjQpS*vCdəߴ?cPpZ6Ff{%jn:*%b亰ntb䘮/v 5O]zw40C]_m8kH j/aX?u]V#`PsqXv J#ַ6}!G"泴4b}]om:{ȧ=yy?rz2)L&[#3ι %MfZOmvGcl9U,sD%8Z$v6Wxuzd4 H=4!юZ7_7#7œ *j+%r\  {ʶߓ~HߚJ<)v&PYT#Ts(g{XiIvz$5̓iN8`\W\ #cK-xIG8+>TgE0z| lֶ[ýr=kqd}ei|mZ߳SM8Plz98?n5U ܶKI_79Chx\[lxNmg?!rtr-7$Z\5H+izKLina dZ7[6S$dFmIky(,$D_70:hk7ȕ,𦝾A'SO_۫ 5Y'?\[ԧT܇TZ޷K]xZa< gFr3є\{#餧T=^U|hc.v{ebg ԩSޜ9n)ӍfL3M&R$} ?Mm'T.v6e:q :b^v+T KyìRsb;l0r=Zjb8,{*FCP_XT1޴WVqǵjQܶBN!3&ypu8|kdz-^Ǯwz ?0F~ڻ6,?cKt"1@ HjiF_UuUeVeUW53:fefexeh %/eFj~ Q#t,F9zwb_r $o܉}۰ž6k1jYY٩¬۔x lahh79&D6ٷMdzY]]rji])]+R{}\I!>V1 *U\Yn@vF.-Jqp : 7Ҿj4o򨷺vFm*C5euA< %[>Zͳ Iue49-`[7}#[?6ԫZ7C В1g}/ }`_ w޽{V?R򾇾'goȝ+ /Ȕ{v7kGI9}\:$^r.ZYxymڴi۹2\Cn0c=K,ʼ[W2eJW.X.]T/Ν;qEP X<~FtwL5א;5 =$d͛7oٲeNo~z9zW;cYoFs{;tUz(BA]1+Mre$O: \C0:[<_[̈́v%S/`ou?/ȍrǎHW/JCu~?I Pܩawi6eM}{&}']\?JRFwE7ŗΝ+.Xp%ݹe˖-_bU\NV =yx~_eԫ^C0b߮E+^XR>/X1,=W?|$}•/gQϼU6}^'u웺 xןnO}-^}cؿR6e]&y>gob__i4u_aƼ6.l7wݐ/l}xkw޵+mD5uWQL=n5wjoXeOϦk׳qַ-다?3p+7{Uvx͏vx{Sxb{1ipr`KEr˺u/9rW]uշ+ӟ\c6o~yzW~mǾsskrNW\@($Rko߫3Wk|Gf:2*wm↑ &&t)]{RŨ%k Y٩{LEݳ{(WɾgΜ9؎}}Q7/c/|A*GH|,;ncӵYOkϞ=}{wAycȑGJMS'Nr96{}PJp[w~LO?thĤ1÷ZC3ōG_p!Q,ۣ%9RsԨn=b=e:JB΂l_Url&Ppb/~_׾w%?O~Kӯ:Y'ʲ񥧄K)[RŨ%k Y٩vv~jf<S=ɋtCX_]`_ޚ=_1aFM%/9r@I/ R/\5cڮ$w7$3YDzOs\uc$u3m?#h ?c@OYA]|ާ߿{tɞw'*U, l"y%=FZRQZn/-Wl9JS4^qR9ߊۿSܔ)*m3)I+9M) XPnD`̘1wq]w5~?˸q$qرNK Q5m?yrͣozOgod-Z; )eb@߁bjƳot)T'cWF=B Ofev}aWGpOc,챞b^(z_X˝.M$7$g󭷎} ۷U":Wmvz_Dm at(NgM})_CG>8pо}罾=;vٱSj+mg͹e_~}Ŝ}Pgߘ< HS*JO}@ kXT]`_bF*o?ozgΞ9xX/xcKY j}6྾6&WwXܧ oɅmz#?$IkcfZHAbmV~hm%{&<'NK.\(52kmʮ"rZ4:ZdyNZ~sYY]l}}cf:NΡgl+Ul֮]+";Aܩam ?b-SoT }U^C0xǤ'Y3KVt=kޢg.҂g^Z03_ťuWs/_\l'W:`P˥rŋLfHit`w5(xRTy SÐDi?@#1g_!ͳ"\WlҺR._^i{ ==6< | X ]@"5e_v9t22U7 2[9 $Fv׭{fڂݮrKD+*% su|c>"cuweZ\Gx{FƾJ2Tb|gFm*C5;坺ڼ뇱 Am;n=Řd(ͅ_ouz]壊nu pWVIA8ֆ¾8>͝G10(mpc%7=_;y{{GȢ$*0L.w߾}b @- /}/`_ j 6tww/e…ϗ@ fo W\}/ƾK./.]R/]x… Ν}Qa8z'N?udXjžPwE.K j}ڶC7fEs&ʗ ϟ={V,Yž0lh|߳wu[wiivr:N*Q쁝@RpA ¾WwYs^}?_?>X8Ɗ}5Nti];OJڛ7}O>}~㶟 Csؑ7}`wѢEe`G狣nZԽNN'žPPVȑ'N}Sߩ}3z;?\`ARk:H'}`W*i8o=i[FG2db{]CsYae_ѪԩӞG&9}Rߍw#?~Lr`_hP{=7ݚ37+zzyA{7~+`_ 5{{ەs޽wwJo,0w\[} =]ޮtݹswʔ)3O!M>m4Y:U>S˔ɓ'M4cƌ͛7cQmؾZ=Hv'{D.rJrrsHQN9-B;NsLoP~Tf_h}6flTzmߝz޾A+gFA}HYN l9~SO¶cr֡EWtCP}ϾJ0GQu|J6PH 6.-yDѯSSs~ijUvG#"H+W(,<ʲ1e*bMȨ:`V}gFLzbt{n?g%5 m@h>% QuN2Wz@:>Vz}޾BX} oN(׽j~}g${)k߄U1hxzy*W.s0baouVb`.Ħךh3R &3¾Ik[̖Pve iTU:s%e0oe[ط c_UEty.ֹӕ~ ߦc?ӞBd}|ӟ'bm۶5 E Vo300 >'Ncԥ9sY/ޕ i^j՞={޽1pqǻqٜ?޳]4E-qs^//07vU`IkX1f)c`cv6ۤͶ6[jt%' Ri&Ύ+'mطRSZ;|m]gMHh_oۨʟxVZFjs,hf5V4?8aio55ϥ|[y+k.Povui=UםfNݛ*,Q)!<[p9mطr*͖7&DͤOe4쨅a=W g 7]`_-pؗ6/ž}/ž}/`ڍ4Y!Όvr@ya&r`Ǿ22}Xkx.oIѳ:^`ڷ m]Jk%82w76}g:;VJ9m U633d_mN طb_GrYOIeKǢ~57|WhA;`}yei  Ѫoi9Mi߈o3ǾµhRnFWi }3;.c_MVX΋IkŸY7%늚g[[nkJW*3lKwp%s6<nΎvGEz]`_FHWo`k_%ZLaؗ`_ `_ `_۪u'7c6_m!g ҙ8VڟBy}eLF9ٝN7̓ e)Pw34t *(پW D cb'UnY+mOؕ)ٵJ7-R ӕO ط7}`žRxic_CwZ3)duz%\ Nk[m6&T->t7ko_|tۀR\Y[ayN5HN}BRk2FiܫLu{qfb}}!%un%}/ž}/ž}/Ⱦ0e૜ro.kd|g :"˗h88j1`ֱoib'f U0n#m>b/xQ\ywXb} oq"cԓ}UF͏[qmXo7*Cj}MjS+-f әǼuJ}%w!z3[=Sm>ϖkz5J6 Cƾt`W}`_F}/žb_~7zz*`&}!A}Y2lAe#m4-?=#:(9 Z/kBఽI ?b}WKͳh7_ڎםs&RIjw}ڀsYg/`r L`ko>8e4#Lyav:rr!_GoM훚8ro(x5B/ƴ-[%A pjtZzPNl$67΂ֲѳI}VJ־Wajo^.K@kzxt9^n}m/`_}/ž}/ P9ujzY`hƾeMeӴc͕om eWGb&5r嵎MYPO!pN$cQG췜MWc_ag_ .5Qӫ %[Iə^[f1 M25Ǒ\"}oMMKPLrê<`ߚ75qPjޅ^zii[ }ٿ'NMZzPD ,=Ծ_}yJ7g׺2dT^[n|P*lgu0]od'/Pywhžb_ }/[9˯,#ڞF}[TQ~bfb ط쫌c͕cˏ徨͑qX3im6gNjz^^렕u%1<#K ط8'ܭLṆLko0M- =&I+6o-ejgFV՞:[D~CW}SǾ7#(n^amR\7gVm}+}ϾX1q[^zii[ }zIP^k8R]%=K]Knd7gqMj/_jF+"6[_sQܗg721I\QxL-}Cj %w} :t}t9_z]eFGq6mžžb_ }//`_}/ž}/ž}/`_ ط[-vuH5ڰ} 鵦{OG{jO ]:z{rJrrsH7p r7u(XM܌o+WncFF{/YYtBzA |fiǍG)QX .@d97uBm>*F! +K?FB(KKBW蜸_ZA zHzģCr"\heUyITy*bM:`V}gpbt{n?g%5 Fm@h>% kBd웤iK]]iDoׁ È1`GGRE- !$SQU(=cľ;P^5پAoªrh\az)F)Tl ̔=oUo;iҤ;v$,$7\\My}A}BOXa$ݿ-LM蹲в:rω1Vm:~`WHU󀍣ywlٲiӦ͛7KfO\s+csM~=(MIB =]nù%D_9=Ƹs]˗㜼qsEu-YNVxy=ls#5Sgszm )ʛ9q5JhhPzW){JBXR6 觚BE ]-'꺥!nݺ9kZ6)v`G׫yv٤Rc/"yD2`_ Pz5`یThpj>ѱ/ht;Lk_> ].&d:=ߙist6>Fﴖٙq.=z5;!֧A.ҕOw)07R2L67wj908E+)Pە Mn!V oľ箸 .{J_^V[ny3B_tV?trΜ9S|p ,Ύo^eFtu eroNأI^Zj?lNrN~'̔w|ގ n 1ѩrT@ط}O<)uOdhRVIgVϲ1ё#G:MbU_~GjEsҿIonZ.ge~Os };6a„g!o<䓒r7ǾZڵK xE,\'p2c_*Je;dl˝](re#"_w Mb_m\g"vm!3'2;MgVŞѱoTJگw'֝ SdP3GcN(G֋S^,{%WrkSX-'D-ߒa:6 5AA59LfR|ΐߛ2/ұU7r#pdzczt9 3 ,eVf_P{]@W."1VT`_}w-u>])Mcߘ]i3߾ʾj%}˔Tê VKn *N-|^þ6nM5RLϯ^VkR25iVVƖ83PU,ǮMV i՚zZʵyڗg}7xu>M9P=8+)'p6"\>&ܸߨ^W@dlIT9GM ڳ]nopZi&J&<[:C/yEۗ^WPm",Ԃ 84R5E7Jϋ7Auv[kmcjͧ^;Qm@k޾yž́`_ `ڷow$} &<P(޾PZ2}"3gN])kS}@ETn_9`_/m#!IENDB`spyder-3.2.6/doc/images/help_source.png0000664000175000017500000003550213003520702020647 0ustar carloscarlos00000000000000PNG  IHDROk>v cHRMz&u0`:pQ<bKGD:IDATxۯGH3a$4r?`FstdOg @8D@6 /aH$W68$;px1vܝWu{zG-kvuץU]]{w^UDizVt={Vo3"} `1#v`񜇩b-llllllK̥!jw?lN&fcccc[WnI7W]tNTf'OOooCI馛PFvԷ[Aغv%QXZWN"*݈)̝Y`jGcwwCywɓ$i\V:`xCEODU]hԮt.X}oTG~?{WWO]o^~ˏ?ߞsv?j~{yK[tS}Z 6?=d7eAiwjIZF8`I=>j|?~3}%ʧ}jbT!EFh .\ܽ^t_W_~/ʫo yق2D^JLoU(Y ΏM;CWw?$COD>,=PWEP;hvb>q)Cٷ{sD'?QR1?O7Q]p~祉O-_EMxzkԽ7ߺq#R~zCPF*OtkYY ykԥZ,uUM8!QlWpCLy.\򐹞EFHN%cڝ[v%ijBDlv?Kzu>8yPݕ+W7n`/ J3*TMԯXReIdTCNyJt N9~RŮkpFܱF~A|}'~; ٤ow!u}'nwbzuk7nuߙ:vfGIl)s\Lj".9ANv 6jI.uN;R_h$O:ϕ+Wx_J7z+wI|q̩,oW;K;ZMdy$ӝz˄*U%_=/E^[;Ev|` %u=>j/})R;G?zww6P?(|ij*uj3:'?Y?KEת\K(q$vy{KFsHu).'9>%LqhJڙvBxW6/En4ԉG/jo~1:uj_jˏE^Ʃ }^.=Q (ZG(Y*Hfͷ XK.rgɘ+v{Uߕ;#jU_|q墳_7^7oܸ;oSnMڲVU[:^١v"j'Մ'Toy晧c~ߪ**rWMhNvԮg:}ţ>_v;zn?9 EZ*X)T.Y̅_kD߳q#C~𳭃=ps6Pۿ?9 ^$uP߫mll@uDk@P;@P;@P;@P;P;P;armv/0ڵkΝSs-7ǎ۷o_Ϟ=[RQ!Q;yFjv˨vl{U#W-P;6666Ϋݵ %uv6[̰ /m]I'ےm'p4MllQK1%%ݠ7oz񶧺NcN ?0oוW3v4=K]TDb4 mQjg~xлm8FEvϟE;a%pX}gv҆URhnw\\bWϬ 3tZry{*gY̤˺k =zoL/9N@2.+O=|q?y1jVo˱}<T\HvV!LyQ*{ OI$Aӆx6f'QK!{fM\*ÃA?/2%dSuT۠wjO6-u=@G.Z,cwvN ,̙3JΘ{T픪,۩fO\glU5ɭ*fN5*o`KTLI3FQ^Mқr<z]V=RFۚ=pU符 ?xL.X`QiB$W'Kg j'א%QZJJ=1v꒘MCҩBb';cDq9ǨxP.]5KvdvfoO6S;2?`'z1jMj[(GktZt=9_.=سV%6>j@ݓ %Z)2Ei4vunys&5U;1bsԥ#\ƼCNÛ}gY4V {BO! [6K+`ͮ6Wꢢ˵@Q"׌շF`Oߒ1|+zB/&zp6]F7G-ήK}&6F=?]wSv7j7q'ɖ'2_ x]HoH|5vxه[@3UEoMC튡$5#T&Ԅy%ޑѾT9&w2P!h0P~M}K=z ͑vb6ZWWjUeuQňeY0vc${9`V;m͚2ЛDt t^nsCÀa@x" lpS<ܟk""xW⥼/D@ޱ;! }{E~lڈz_Y* ˑvujX7}$ B*G)ӝ鼕e.0zb- 6jx:T.oyoxaesM.\vuݻ˨Ri;cKWt95p|jV|7Fi vlllll]쪿-h믿j^z5Y… yO?t.W+W)uQVMLD۷{[d IAa@4ޯn6՘Ujs[?rr-%.J }/j~+,!V`k8܎3P Y#dlK;';.rLfF'1F|!E]KZrpNG_|*[ʦx9߸[aw %&.v R;yM|<%͖ț|gmQ ). !cR;4l GY_A:g4;v|e,nGUN|])%̑tJ;óyRrdq9]26{<NP.]!,~Gwr?o,J2P iAbt2Ue]EsFi3d.Z!spjΊqdz Qvp)6qRY}]`[,@:%nAjWj?gwwGH8Ki6CYC#SkL}r F>N8fi:וRQ.g\)>R^9)q}RJҜ.{,/CznM+7ٝ?ֵ-zUٷBZ%Rȴ?&,\rl }Lj,b{M JN|ek+Gt%>Z?̇);9`UܤON_)U(" o(+rF畣R]65 ,yJ+FTin:Wq9fo E4kT_&]ˑRl5Ŀ&v~O5oю0>Sa]lɰXՊq  Ttj(.>I+9]/% b:"]Q%Ay&uf:QXW[Ny3 f1A1h:רB:#W<;xdΫ  j;%^Q>yAze^U/gҩ*" 4ߢkM)Y9r]!"0韪NBo_#9lrJ>VZ> E+}5Ih۔^jξrTΑPCk2jH1 |#5Jۥ'j,kj05 Ԝ=JBVFF fKb A`իbZ*ڡvڡvX_xgpQ;n̻?\KΌ%(Tŕgp6al4[-6?Ul*!#L-Jr(υ*|u~ϱ2vÆ.~Һ[kx6@.`B$$^4qHȍW:.3^BNuy8(UtYjwwh/%G6ΑZE"H)"Z!9+CO˿[[=wćːծqeS^y/]+%MTV+@u|&ޫyX3Ȫ%рABH^ ߛ$eal/;-!]/C+K_Cģ~X:o_u+Qqd/hÈ^neN% rH/=y * )XN]yNĐ6@QTےVus47\7NKJ|}$w6b)G!\u^kZ;Rv!N-߫+lrw PH\O~VB䧪i<8mZ+sfomRPr iyo.K;檵Ӫi /q⺝R?,gw֜T]˛ Uːǚjϕw(ҭA$Fg秋ҭ^Že`?H ٲzWDf4+_­N˕UᗸŤ.a|ejHǕ#k75F(*I`18.d&֞203 5 !ߙ\mW=]Un`w\wԋ*K2 3G'LԍNM#bO,%jMrKHFQ*-%B̙i!-5O+2^Ԯj'JK3yy*uQv$W~1)xP;HHイ푒TE]Rȴ3TJeZckҥ(jjjjjjjvڡvڡvuS&5N@P;@P;@P;@P;@P;@P;@P;@P;@PfmFv*Vyhjuׇ>o ǔvkvV{m89cΝjOvR̢óSi=;QpUt.`-n5NSaHHjM9NS;ó[wF 걫(NWWqwr2Y^SnJ^,jj)GљJ.S8J;]IJ5LITM4.1#ebƃJ)j]}x)ĝ$E:ĩvh;0ggđf혥 ݪStn\/$STs}&#Lo374/F)K KJ^%NԎ/_ v+L*r0nNdN'N,ڭڕ K8o{H Y#[ZH[xbP% L3X2AjuDV}-p]0j"U?I66@`8+/w 1TDU?I 76@Otݣ A;I,]fDZoҁ!( 16@Oyl.Z#{𼏨 YcaIQ-7^1^K.j, i NN:O;CndZ jx `$vݪ"d?fjjjjڭ&8v˂X1q;LO \is?o=""ܚC4\s_piі\zSҶ9Jf"[PG0F i7q&*b/-Z( m5.:]$Jy)9,:g/iWUU>NOR q'[O+7d.BKevƙH_`,=>rhWt% vEqRC&9uZ ]$ӓXC&1j#ŪHޙȌQoNUۢ+Γ*%mlkhtv׮]NO./ZCn}ԮE.3FmK)* nwd$I??r6EWWJ2*WӓsrSTC\梋P;iLn/:8yw¤R\J-lEq1g8=I5ęx\+ڭڕ;\rg"mCE 7PD\غTJ]QRorM;܊=" TZ9=I5DJ$vvvvv`-rQ,\Z[ykbuUܥ䕣BԶF3HmE[!oy9ç2X bfyw̾vWր9 =EYH39A1*%!GF^~J9+ƴCWS0 Yo$RR%e##<[p96[[#f%6*#a$V)Q;.X+f.g_Y4V6jK7 K|>l՝lvvvv\3@햚uvP;Ԯ1rY tC:ɼjVwHj7cYV1Uij ¬FeE#;}x!K; ?{jj':Ԉ\QlzcJ0,QŊ\;+Uj7$^gή"1YRTvxZFN1!+1{UP;5a ZJ#Yc64dTzgޭ×UP;LҬ˘o a"TJ["~f4ڡvMvW1{Er֨ [j7$=^@PEny gau9vvv[BDձnjjM%\ձWaӱ]vi3Id6@ٶf>>!EW0r dUJB ڡvYZ^NhT3=Ģ*%~0ʴN^6@mRK\Egw^Rvbxǣ Zi$EJ*& ,:èdys^RJ0EC& h-t>~*NUl_sV)@P;Svfm\}|N*:J@9CJIڡvP_ҿxjڭ;=%/>> Eg.4StbH|>6B)9ZU0)4*6adB]9&7oCP%Q*54ic!i:d9{J 㜒N+sTSTglTd+V˹rzRigNN%|μ 5į\LBuT͒vF,%]/Wc ƿ:7|jj'un*4G;ya[ \m2aƦOER D<<~wM}ڠAVn1dEoijH` LvN)4SmJgZV0W`uߗxx |wH9o]BVC턊7N%OC?Nʃrz%T ~t }|OXwr>: Eb%#+2Ζs2 ׽dU)Y!-+XekkԐzIr3GShCPeE?}̀&ɇҁ5̅"K- O鴢oTyxC TEۃ7)#"_"W ,:5`9vAjSR`;7Wx ׯ$6dλͻ.vW;fiu>'< vE@DOlI8a 9 *=f){{˭C4iiWx@<dWJS)yY[Jj2jΐ2<5m{щL®p1NWJ^#6D.%/Y;D4i#nuԮ!uϲҮpQ2ݮ"ߺZRmF2G]{CuD:{&vE 0s2D,|)"MXlkPҐ0}:[͖vE!FI%o),yJ@)=v]v98Ǐrsر}%!Q%e2cZɬMsT~0:v?{lmHFD햩\joWaF% @:P;ڽZjW;#k&:vJؒRFijC!SC`󹼕~'vuc'U hZ%Kr9d&\>5gWN_XfvO"lOiv1&I_f" SesK\9: F4y,wvjw&vp,3EQ%$y=:>5N:L?uKtpg9rL9zZGZT*t/%\CsZ+l.3kvhd@t/\N:G򲙇uH49|gf;c@ٸXJsz 5:,ډڥ9R}mF#$~esҩ]u Jw+^1稺힦ɝlxc)|t ܙpP*74QY]S2}0m\oh=8W88fns b i~s${ͦ*iOΆ%w,noE~CR@vi#ޫ;ƌI O\N:.痒?]d{ IXMڥ%QzCo\) g:ŧ ;(U\e;ur\ŋPaA\jPmv~r?RǑlsJX]\33P;4wb7 947|U5D:gߐfvuݻwVvƔ[vvjvKZ};P;U%U;CCrhIENDB`spyder-3.2.6/doc/images/console.png0000664000175000017500000004566013003520702020007 0ustar carloscarlos00000000000000PNG  IHDRK͝z cHRMz&u0`:pQ< pHYsodbKGDK$IDATx UϹ;-6 BKHB6 (H3B3~373" Qqބ}'f$F 6&a[,:Uun*۷k=u?+|AJ)qp??T˲>>bg!LebrWkT|d ȿ:s7L]<%-y|i 6{ZO03\CHٲʂZ$MjTDooۃ roQlOFx1_n3&3k].kYVEgϳWPהAE6Zg+u}L0laijjl#֖*3Pa%>{ǿcϞokߵkWQ &K,UOH^uwx̉aE|4 &&~b/L9BF*u[V=3;71,(PJ (TQ섲G*[QUy_rd4\E7EI}\߇%|^=&_ѢY௩=8'7Dn,)KRWRG;.{;LaL'phgGG㯘bk91 e5ҵqp2$W8DAzp"Ć?> 5n E-euְh:v\jqrR_~|_2xu>'c,PMR(BQq0|V'ةئƯaT~Ƽ M &Ұ~5ij ''lnG?|hOoqSՒ:Mf s' S l6Q-h4au%is{5q v)4F- ۥ,ڱ1klIV2P#SjWz&]+P=D"`I#N+ E&Nmey[>R[$g;O!CG4-,[j5)Oe4;Ҭu .50 YpEZl*NiRT#`W5s@G S&q|Ip0rcbaiLe7ްlݲOw2i\@Oģ+[x[p[l$m_ʭ{$r/֌P׮'Vh@ =L͞~LF`lF,GcehXVBOL%a vULM޻d!'6l@԰8p[يka 6,RZհz亭z8z4Ֆx'"TSYh;d/xE7.8!eVB6YkNV%[^w*K׽8\4V[xڡp)붆U(X 9ȂU-rzjɦp(+Vn )Ms{N3wלVհ0pH54ZTj21G^GԮ/o*  \zAp-f8mAQ*M4P:!аj8*c#J+xnNݢu؎Ml\$b!4f_ד*2& ;_ q-`'cm{ ݡK(VSP{"zupښIvb/Tyc^SrN4H_ JqEĕ*Do46`C]d%" Z|滶TZaVѰRVhXy-JW{^6? g.H-4/:j^@* }kSVp;V$GS~ yPhoh & ,kOu ̣MMML|Pۉ葉2NM(n}| ^5STȪ%Ta+ީ<-Ku۶ J)w G3 n}6-Rmo_e:YpZZ)U2}%G7ԛ<2Zm{s9۔q,-EhNB7쇓b.2 pN ˘Ltn /}}˧5Ұl)cyqyӈGwXBMEKeo>ζ _8o˿^ŅSMNk =^:ۼV5ְɟrj/=຺ب'{0q~?܊"t+:R'H G6j vFKA2WB.C&nSZK R )eaXUPeKpeA,6Djz~Wn %_pEՈ!P8hn8MPX B&e bOF8J)"Ob|JNm:rQ/o>g_/nb/v5em WTXlט46r;,jIveLk}oA/o~uRk?ASq1LC`Ze ZO\QhxӦ'ExOoxVV&6f)tl"P*VjX[$N[I\ᘺ@-mzje) 94|Q1Ӂ,*.l߮Qf?X".#Q"NbJ}#^YNR- ef'70/ch 5NSݺA| F0q%u m{£yR6HMDռP)U,BD=? DZV~itfǬ$TețBצ'(Mdj;-{5wajq9 nvppyfp206հ޷y+Ѱt0[Y jvnSOgŷ+~eMCM;1Ji8X V{k'^o/1=L/鑭XUW7j[tvv2 >|d dCb?YL\ёVQ5LD$\tˊH'`.Μr|pOc55zWzB73I#d)z;< w٩u:M_s*T-E$jw*حǙ{,\ wXR47~ta1MaĞݺ3Jk-fWNҰ ka{S\zc``%1ZpN4oe0:4f]cJva>c9QûnAOJKBh=i7Vo kQu`seҗ;M8-=Bm&%JyecBcvsi{4 mo&3,c: ũZmGfe[,&^jYD̒nn7bGN&7 Qf ;-2gp7?\y@]Iӳ53Bʹ)ٲ_\JZi)wX5ܖ,ޭ4Sj826ѰYzut–O`SoS˖5V=_7wɤ?MbfrDƱ6&&l8MB=eb2H%11"&] 8 5F,fff2п?/,Ц" X]N'D/,v)'K nM}{9DɳZ6S8bP44V`1WQl*ҝ" VrYmS-pGNgg-Wc鍄ԅ d^W6PhkLdѰ,7͢^։,B(=Ӊ5cqp?`V"ɘ:227!0`uX-O.ޭbyȰn8{W}i7ZXiK&V9N*w>cL- JyoӆU&Mqj3G2 GM@Bd,9Z E,f:< Kh>N pA| n;]5W..U?)R[(U5u1;~<,ȏi uy4,Z]^)A5\SIS:3F 'XԍmbRP^/EYnDe|YǐLâ-[qc#Rð8mm#"f >'Nr1fLObF9aA(9q~Ȥth8TjGҝmCO$T6VIp%fn>Tni@ ˰jpAU.BiDK@t.+,la[v*VݠYIlSM liQ۠ӳkbM`ay ^O_i2Ɔd,ZcەD\a+/]w4\>efU%~"Bh+΁));Z,fkpͩs% PjK(Xa^R0ۑhTp uDk,3OY%WD EQMt&&n:tLQ\ 4ђ-]Y3iV:8[Jb"Yɦ$Ca5w]Xʆ.l8 ad;gW?qv]UF̢|[qD1lXmr*XB"Vy[Diol_:破 BKwv* `_Q+lkؙ6D6.{ԭ=.ˮ?T4if<}qKe%LdnBĆ&{D3=gBWczT/VL?'qIF86vL@Ns4̛I iU͗xTnqLQi vCbA,8g7ѕըT. J{5[l'LƢ}I i¶KA/Qc~YY-CQlSo%J+w>f9|yˎelo'xi&GERFMR6լC_Ѱ𰙆SXKn-jaV(MCFägNtYT&CH[{9@]:UcN( `!\,%Qg-ר3U)e*|[^Kh9N?->^Y4H ~-'11dKV ѰD!B I%j/w.uPFR%òU-v";l%^;kvA`i?3"^ iHlaqrIѰl)͛{ r)sV?Os1Q_Snp700yz \󪒆Iu nN✝c b&-o;t`12m%XJSe\dnIl+3,bCnk@/^Ӯoa9BVǣ(}FCOj]PIĈ/J ŋt۹VFԢ>I8a2 Z ?ݡ\F=vatܓ6ӔFGȩFH(iO FzEQw<2甎ٖ0J$:4Q/[PԗGꨉq uM??Nąn-]W{RJ=)ѝ ɋ6H"G}=^@a0ۺ:|$eeF /M>ә4 ȡs'/,;Lc]s5cƌɯa#61 ÚMi)IAL}o.flR/ζ~+Q>ޏi)wm5K|_b)AWg߼ Aܫ?z΃,.v_/} "gG?'fZ1K [1 7y˭qGJ;xut8hM8~%{ߩgX @ytK#=Wlbs3+deuwwL",:~c[3&\a/ڿo.8/m3 `0|{ȉ|*lxO~ws]4=|`Q8E6ү|5wAIXy[mOZUc˃'rܮ};ڗɾv'c?8ny)59K4~~G ' }tYo1&?q׶\,ֱoV.䒑#G/)_'L/Q~?fr9r\\[[}Vʹn2yDm2.f^DnCI_:Y5t֨*R/6Dy]]//ͧONڳ}?krށ%Aų mݗ׾.?~߿@ݓI\ wai#>7x͋ǃ_1I)~?_SGdy1~+vO8~U4V.FVhHR1U|cKL~yhcR79z iP-[x͵r.#Tc&O ?JՎϿN'+쥸˄x BʅoC_-BIBEƣRK/p9a+0~p]U8qyZUGֵ}ډoe~e~q/bJ1e6 blfig^qޡ#{v )&?0|c&Oⷫ'|FFLo36''W^wu4S/ZyEޙc;-,2|N{q:kugz:t놽Rb[ıPZ~f ֑Ib3d -W?R)gX z0WXW"dB_9%",i£k[?9e{kKoe_RP@K/>u/]3CR歗 x5|߰Youw+mßyvؙxӧݻ́%Xw fF=ڹ{N8'SicvlsȀe~mV1 Cdmkx>{gӻb72k,.4  2ap{0]8*2ەi4wW΢?qʣe4OtՆk/O5/'_Xڿpw)#=cצ]w6QxGv";w4dO=O~"h,{Qk"vYO^Og]N:$_7MO.n}Jp+2cvg[U~x{lZBi@_а"W_=qnNW7|Cg?6QeMR6RR o}؟#>\j?;+A'ws/νx/J~^xaܸ+wrʩ, lȑ:;;vl?iIM0>GzGsrQOoݺ t#[> &ZAhhX-4rhYGc=Jh38HD 7:Bim sE47zXI>W-+n^Q~GzOSGmexwM|kմkuukor,+.}_0հٱj_1={=榮nw{X1}kǎN8a}C5̶C,',%Jd Z38#E6TM0WtY0(8mJH/1|q1밤D^KieWq`y_f^,TUL:`dѓN&_!I"yG_?uoB hxaV.1a&ڦfEX=1$T⣆ ;U~kW2kzb|&c2"[Ęj_9{ī_=K&fx߹h LIȐH@R.6dNqY W 6ђ  kr5lYNâ'1U h֡' I\l Ç^jToү?_l~送Viut:>ʫiz{?yK5h2Z,iQ,*Xjc rhq?\T*>?~ o a4тkx0(cc~0P% olǔ;Jp{=4 TQ2tܨa.&j $t < L>2-锷#qVjdӅÊЮA_eYmr*Y9"O0~ϛgHeQDž6۬GE'-0QUӳGh8RZ0c4rtﷄ4m2Ѱ`"ːI܌ern~ߦ}Im$<ف32G^sOVi LE-_=ߎnCK3U>(پ <6MdQ`k'wBZ-A]A{`|9LWOᔷҒgH6)^\Wf ( VZÇְ .=h^A;/eiؑcmƸDQ M&3g{*u^DnRJvW g\m` _w)/i*!D<…ioC}4 vy0pwH܋)m9oC]L%{ubrY |3b7fSc WjNX;5P'.åҫhX;qՂLګ2ղ2n@ |X=4;j( >zix i4Ljg9t$+ ĨIʴ{3/&eX(qH# 5|Z%Hdyt]y'yԔ.IIc[ ҙ5S(mmaL<#oӘLkX(qoXP ofUNTM?YJ#2^ifg#fkEO")| i>3@2LV>9D3qr%Wdjp95=3%&8s݆:?L"ܤm$zN3ꌴs&fZڥU0<+h8 3 4 5diFߜ0U W cF]\ =\5/rϧʉWN 0?~^ N/΂8Q5L0!P[ ۃY:A@5D0 }ZaÆA@4=ݻ-a/[썢oŢa`BiѰ3Zj ov aF-6_4PK Gh{(Z@u5#Eoݢf>:Y6t/ǫĹvzJA%r 3H; i6mˌg,o rMkX- ܦϴ7C{[ԍ[=  ҔuSL"9qR[wuQEDž,;=>A#WYK?i+3ZA|Ѱ(LޱʯӘ(ef ~[}I/U#5qFΒ4FnBt̓™ξ䁝̓ {[, &EDc#K[-'كGj86t#h=Mw(jGKOy +$H"jM*S ;23 IG |%{ɇ\~K4\'Jx+^D|[nu,"4?#Mһ[,침ц8M xT8qu "4b5SM ّ.PKJ"/fw 5>JQ{Ju) =ct%+#W3m5ɵuҰ.{':KjEU,4eA+Sk-&LÔ9ѨZ4v T=Si8Gn1P:GӼIڿh(ץNyBiŃsjxeY/zI':rGھL Y˛hyf\Y38v" 7_H!o;IOd5nS㭞N|Ó5maFҾ_+ǽ_ܖ%ehI߼i| 7W/5\= 4ԁ˴**H5js]tgְEs'%d,jF/'=}iUoR6j[Y Eb''Xg]Ol-^ÚKp 17_e m,2kaHuհH:WA-d,/D(Gxwc )f-K@Dбk.[zHŧHFҡl#/mѽ6=wnգ6̓?s]L4<|GdZjF/~W3!{FnӼ \{sjқ.:QD4kXߑ g)dj\cQ] ^Ш1rr#TBn,,L3[o%{_14\B#&H]S ^9Qrr?yaarXh83a! ="IK9>I  )U0"4ѮZk6Q1caF3wCB<d8ᖠӦMcdfƨD]m曏4>aMErJD9 @lg7r rN3\n|j]hmoT gTvZ"4 47l0!W]װo86Iϕuy-!9ޠO zy4L}޾}\4m50mplb>5%qEY2vL&!F7cm_Mdig.]\uDkSl D+M4\;Úvtc8 21D8}J1~Lup:|c ^78Rk|<,7ܦ.zF]@jxfհvn;.#t3Ѱ$5H5\zݸ zgښolwmn3ZFjv9# SÿY*av: 0eL6?)].쇾lu0Uìn8Bì+̛hΰV1`'m{n|v93 Wytf Ji|5QFfvkrBx4jT7ÚnT !i=rڧ~Ԓ̧arH D%mj'Zhv9pPq /^ޮ+2hXG0A ,0:|gp=g6rպ D4 jXߑJsA@ Zհ;|GhFM֭ _=a<4 Të֮ K σZix1+^'9$WOkx:Q&MB@4-AM&d `%5uv sf}:문hx% d&WOkXNаt"l l_}SóyKg֮hx7|S.a [L_pF #2kxZt nȡ׬MNRh) TDìPzĬuȪa C@55Ӡa^k6Zh+~jZ6314 GÄ OZk E/B@4k 0 ?@@5,~JŌ԰oao8?rQh`0Ph[5jkS;@@ 4ZY7 uӰjaV(=u@5N"S'P^NLdA@]ah [TZ C@M5Xnj9K,:hxΜ9,^v%Ja& av6B' 5u`0P s  0PS /Y~7|+aV;vGaYlh7lduA@5,h}d<[aV^뙆y< 5MP#Wj daFb&rq0P ƍixܹlg7n&dcgυjx3ʲafҿhfu@@-57A4 @0 04 @@0:,0|qcnjxo7٣hA4 ) [|Ch)j[΅iYQ(Ǝhsu@4̘hhah 0a4 @haahha4 @h05|}0P hR 0 C@m4,=쳡aa@@/0k5m4hh0 a@4 hhahaahh0 a@4 hhIoa314 GÌ>a@4a u;khhakLs94 @4 0 C4 @h믿ξB4 @s4 @4 h 0a4 @4 0 C4 @0 04 @4 h =\ïak Td o=\˗ =˲~o؁_ş-,l}jfjd*KG-ݜ([lr|HbJg\?㙧1p]A/qYk4i"+Yn2۔фU]ihTw1FaY '.FxIiOR&)bڸ(uo3{y ާ o et s5l9,h6#$h"[j8*ßo1.hN_>hX~=3@(a5~ /fW/㰘u-K4U.0A8Kx&%uWI;_/+qʢnt(i-%J宮RUl^4 h  Fi`X9RzajH1R%gDZ9g3 iDBĜgb7,v>ce-\4|wwq}2k$uɞ9m-T/ cE^y!eؖҖ(dҰ5UȚڷO_7)'4^@NE JOkqY;fA30EIENDB`spyder-3.2.6/doc/images/editor3.png0000664000175000017500000013133713003520702017713 0ustar carloscarlos00000000000000PNG  IHDRZZ)| cHRMz&u0`:pQ<bKGDhIDATx읉wם0tw3ӧ{I`;[c2I%1y`cLlcLxYd@,$$H Mh pͯ^UuoխԑUݺ߭   aAAAAJA  p  8tj@AAeN|ϭC lA)1,p  (8SN:􃃬дG\'AAP2@it,v1"MI鄓Ŧڋ  ,^8hGD8hsCyd  % 8AAo8>)DpJz6M&AA,v~hF'X3WIAA|q! ! AAp8AABA! a'AAAYA  AA2  )AAPDcquu6WUUU͝;w$dsuhƅK?\-Y;7T2ghg⒢k,߰hEMo:pjȚp8sݻw755ٳܣBAPhѢ.Kྃ"}S-{{{KoU[JmgI5;WWiӶmWy8E~imc[ŎۚVZQ^\Ï|\d Ue;thMrG{S3677?~իGET7o$"~#.A%}9g-XU4wl;nҒ%;w5^t+WPȚtJ4SYVjk>~mż6'nOnUh`s}Ӷ8rHqkSW66gB(8p`B@RYFS7w==#: coqF遝taGF>?]&v>ߴ!# !|iۚl뜒-L`UUeg[ ׆gܶ;xrr"Ѹg Nqꁉ}O]ͭ^'мS'O>}&%ϝ;g]t+av8v6 :{cͰ7aLP(, Hkk+Svww_vb}ΖQONctd`LF yY"`J,jA(8"[-iXԌ/[ٴw}kKE_qךS][o|-pp}}s Ǯy|休4Sم ^NY޸yS㠤?YU߬ܿ=("Xy8,Y$2\R"Y!OP(, ¥} ;LFvAm2RFL5#',k\ᨧf;ǣ8]Ycp/ 14B4MCCA9G.?=4Qc!V[ニpMgg痷ntk8>ur/\Qkd,CA884tAnݼIJj$h+28x"mſZ|kAh/?:͊i)u翷nhB%%k<\ygC#K}ky$ـ(\ Y'N-~~kG?y?c=v:Ơr@`a 8s864"3TOXC4OFYI,0}a$4}pP 5t!: du&*`3ɕ ^ܜJ{=BN?mI2 J-2϶OR,y's~-mSG~Oy`.e7m?YNgG݇?_:fOlm,'w'N$||ؑsGET ^7oܤKE\S|V WR]EGY:[V_hF0Kz_9$L!T?v}ߏ?a||#?g--8 B8;b R￲~/9,lbIJHYtlRiWM!ݏw|;>B~N$"P:Aw/^Hk//RS <WiS<&5M*պn^]]].zW&\灃W7,31༑\v5Ƃ4Gl 9۰%|sKwzJvwVgZ7rI߽U})UWwHAr9c{+}O=\b7|&) Bp)t_Ғ$ Y:K2z(?}T9}r)VzFS ?pЀujYJ)H`d^.% =Lԛ㜩1keB@葠uFzbO;vwknAPjq!bAIl:B¾яuO]䛋7GOM~'_}@in$R}Q%Bch !Χo̠bJ={􁕎ÇM[-Y%}ߘS?5"5}b,++M/KL4*?W:V.)@OMG!>9Hsp)n9AyTL:dA%[͸9|iޣ\Ucay{s/'39剀G}ٲjǣ"AA^ 37'xnk;&[55cm A8AAPE_(,,\)9sl߾]򻃹"` AA9$ AA  AAp  BAAA  8AA!(:~x_{oaۻޥBu BPE,xn^Mi[vn7j+APv ݩ=zt۶m ?*++koo? y^6۔۱eFeD%Ƃ> y GzpYZK.]|abŷx ;w߽{wSSӞ={nAi (- pi嗔Bρܣhܣ&dBT TLW^E_8nGâ,YmZHSy ) Cc߁/?zײNTpPɰ_O*95#56'ӓ(DB侥ĉT@ߣ߮}ڑ|n0sةw23N1Gi+1Gqm>07#53 Gtc[틶p~Z r{D+u$7i6uq:HN45:,Ymr]d>'6 .Ae]~>QPâ/Ǐ_;7r|Κ )_r1q Eeg_2蟤TͧOE=gDb bN1qZɉս!X $N9Y&3'I X*oj'V*ZÅҫ|4Q>ܒ\E[u A\vc4;,%F{|g;p^N-hLr{pE5Z)C)SPݫݩemfrَٟpqj(.?0Pu?7,O:H0=sa$z$']d[{X{ix]mk;(b-M$q'q._j/5] WΞbw-gig\OBF= z@?T9s^ktIIgnpsLܼ]+s֔%;5kz+?G펩 >xPO9eo+ ҁܬ;V=q[N?qPAy4qP}^LtIڢD>G()o,ΆRieڎ2[PQ}3Ui[uCNNywly./dJ=*uIθeГ8w]DqPƃ2 ;HrNJK;A۵>gMYpTՇ/zT9kb%7%&=q}Vq$FOd")deSvWIC)o,~qг$Y<uZ O?䞇ܾ=ON҇2FOc.S`ܸeГ8(?pj/CI!}-$S6o)MЊTuPrڡtаwIIwUn^[HW֔i.ZbJ;}~*?W:V.)㻃U/^Q_`@ph;y'9EeU"z^P O4r0/6h*'yp'bDz]s2[; )÷q,U :vڎX)egijetIJZ֞CO.ɁS[OJͳ yrLwol'ԍvtoH]V7j9G!o*$A.{}:EҤl8i} mju睳}-y2d@H[Fhirls,'S:B\ԣR۶m[qqqII $񏦃rgA Wș> yMو&&S uuvvv;~+W\z5}}O>;]M݁ l (-z\yxetȊ 8C8> y G+<+;@Vd\ATWQ[(?*@^`YqsQ]G!oGBeV&~AA '٭t|&@AP)#$P(===DtmbgtΝBAp$#\h-!!A By~! 8-zƗN.FZ}yTT d衱:6O  BPq.bAm`b+jX  BPqtT jiFAj$,! BPqנ@۾1a|8A!(8h_.%Ó,Ř, \lkk#k=Qdԍ(c 8AAw)i|"b|h BP >C A!8 BAAJ z! 8! WziΜ9A ByDx}Ũ.]t+W\v_DuƍAA By4S|֭0UUg; @@ BY_DPA Wa0h*EQRPҙ"Hy:.OM^%}rYs @ɕ" Wf)44A%BuiFqи0ޤ}=VQGi8sm CT-&(i#oI{D2$zx.L\!ּerS8AArk }U__߱c>L :tHI$w:A^ϩSDLذIL(9I\8RGp ((`H#/t.ȫܦ= b(>r]IrKt.Cvق{LA(lfA!(p#8]s˦[`H525vDr\Tb(h_׻> A;mf36XRjpU8h) 2# Gs+ڸM#V .$؝K6F0sb8ȍ|¡` CaUopPI=7$A^ 50yh@A<U.:R>}@8 z_װ e B <ݢ#9mZͫk98$a3AM4n &]v2R1h)Mn+?3KӧuGl<{,3t:LQ~=N9AX 7Zd"UXqAAKkw-"g2Ļ-s('( 2h@A2`'1Fs` t肃nb 2bـv+$NDI%"M8+as[x-l!0LBc/ђ \0ƴ?b+Uv_AG[M YkhW drqPFyA^8ȵVL{(9\[+.,G%dq dzTꍜ-w-P!(8H uz)͋ԥ ~qPZ;k:d3ֈ64tԳDd8V2p0?*,',)NʙD92r%u&-tng`=>pG󪃰اLu*Ip)wgeuajpRjEꊋAzآ(qƉ:7A /G88zc+yAN/lߓFP4 7J>1a|?x9/9E8ȾwU~xi=6voG]t1ZWdr$GwVG_%ALGd?4#L˝g߀dkpRX$9_8vd ;YrqmOQ `xZ ` @Qf$-gҊ/"EvlP+jp!'iA1oA}J# +'p! 8AA BA A! p-eE>f_L蘮|2 p&sIԶc pDv #R|AJ+EfAk__~6YWEf,|̌9 LҪ$|Egz" (c80dS^܏P˚qwi]cָVWw =^,,[.dA85E3(c(;m2m/<>DqAӱ(Ş$X_<-a )AK5!+`pshe]_\urX<v.mcgnKqIK| Q[0Nd(lגD}f-Y±\@P L'PPc0+90 BqY0t8kı}vrq,orк8?uY, :s^y?n8qP<9CY>;99͙^% JV L3A L=A EA;_q lr ~< A9Y/R~f|\㥝6؊83Ғ嬃#Yüb1O@(|1p/PP Y> xDsxʝIC<q0A6YQZ_4 ЙLpX8e>% Pn%mGwLQY?̋'dL'| ' &82oRr* ߥU իx_%I hrg@N'&!`.YlʀWf̃(c( ' W7 xҰ= 0BAAMw,}Üɴ9]y|]DnxqFI`uJS븞v[6se7aKאEߙ1f,q'C AA?C_|>4A)fКP;p!PPFf+}Qȁp8A o<BLaÆ o02[6lAlذaÆ 8 8Ć 6l؀؀Ru+(jSUqʜkSmK(%ytE%3e>si;6 6lAΒ$Ӭ0.`DioEҀPØq2CG)qBIgnHJ4tˁA6`2V%!Ylb8)T˄H2LО8 88 8 p05'XTA0`jcSWJPӰ5ˍvDr\Tqqw #,*,`FPkLlz`)6OlAl؀ًذaÆ pp08AA٠p8LGA BA A!PAl/nx:~{P}s"aPDL^_|3`!`zqP]D5v @ɕ" W8X&GpnKCD`yEU"ܬK_Y!8AV%GxԩgV.`$eIr Y, i慃,6zKY 5he džQ%2W 3&b4VqXiS+s̸0-Zb̛~TĀ#1'ɘ\):"^aa2m3Bw)w: 9:pTnsVEaD}cޙKk.5#l9W(o !8AqPAuP%}XñA]!<5Jcv怬6v:XByUS7An| dҩ81ƚK5{3LDbRCՆ_YCƃzdM_, |U*rT?15 8A8$~ںN]*sDtRdJJ-|g<zqKAAv8HUY4쫒 # A*P`%. 5=pPe ǘH Œ9XL&ե P<2:i K~Eڳ_ߘWMO]EqP?!&s',+ڲܲ4LR8hH.uI]/xQYSIY.qq f{5&W,VBA]d;f1}[^6: ׆pțubٍYq%1Y9rycWNs|AnO}"Ҍ;'Eܘ˛19I'әKn&v;Q]R1huܪȯA~Q&<b$ZA8AAsItō8c I3tà9prn ȉnRi,n`AAA4+1z!x8(H7&tW4;IGIĮtVEnMSKa! p0zF5f -Þ9.0'q8'}89p :,4C |)r%?3Q:ۜFZ9 8!8қ&tq|8(,`:-k@s m3P 23L6"n䅠Mw6L{='!p0?*,dLL_.qJ6,Wë@pUޛf `xqPGa4K+yAN 9 diɏMYs敝|Ae;g鈐g&àKu މ-^eJr.ٯ7lbnp(br1* ag̭UI67kحb'!88LqP8g88 L&8M e 2L!pA BA ABA A p Bp8A!8Ȓ$yJAAA$#ܳ/RT A{dEwĆYgT:W?XA(@ۉNĠ%9/#AeęKxi5,:l~ˎl47ؚD/qXE̢0L,n0IOqJr46Cd?uw?Mt aQItO7`PCW;}C&R X=7e'_UaxlM;㍗vHvACK'#5$8Q{ LffdyN 83ج>PALII8 [Ua013d)b[D.ByL0~BKts46C$p'ppP}9 'Am~&$xϜVv7-=qdO8Sbnt\kAssI{S'C!Qc8K1m)$n1: 7,w|0-|^ALBP21APw˼ ß*OμAWyҥ5>h₃Aœ"d;* ? 3\m}Ԟ5 [R_E?["%~2#xq΋?dϜ.<чfxY %38AkUI6O}$,N&ըBsK[2>( gHc `㠸2׭A LV.Y7!J3se3RĂdFQːT5@ #BaZW?4*,Rcl%9< BA A! p p8AAA8  B_q-!s=d\IvS'Y'MJ~:ze +N^Lzb?Zp4wdLSXd}ArAg2_v]V-RG_ $Kr Ve#0z (Q/&WpI 눧мdz.83ff/Zu(cH[p1Y1Ź; 91Tb~: x.I # ș"GJ̈́_f`6'F(Ul%#^1 X/)UDgWG_it'Lvـ>2l1[ s}_x6a2q GG ]9ۭ|,⠉2L1R`K`tF[iEbO7dV'8'!`Xb~1?l}9jiC>$cqO֤_S ̴¶Ɗu<䆞itV$Qx瘗X| [!`ʀ쳃1$4%xmH^πa:5K0& "!V:`$ E qh~w_QGXPAT|7mGA88h>1h!8A<;0Ɯ<(M~lF$kaϛtj)- L?dSh`Hecr?IO8(uJ(ɱ$&  p_2yڎp0o[A $ iq}{9KQQ_SL8tfr30LbHqG@9?Tc9veq ^a^4BO~~+7ܷ`QrĈ!dZ_L^# gD~#31GeH*s"df! pUa6,ߐh+CR0Of# BP\צSB;BA A! p p8AAA8  B9.]|0_L(#ӱ!'!p&sIi5ٯS!w³u*$&F!.K =9ohDq0t|`9 x%.Jr<!(q֠s.R!QYVu"8f[qP>drSABp0z<& pr{ZM*)`y$¥4ֶcy6Еp:h:6Xsl{Jb4rhz2ϭbۻ5(w^LʋKrM&A8ko[BcdD1]l擀ֹ+a(hyc1 =S& [lsڢD?]KTq<*XFlUo3LΊ|#M9g U0n@.w[7.Aˍw2̆'7Eyr˂ Iq!H/\CDW]]Msj.Ps#cNfq0)m!CҗuA8(-ܐK "c 1BA8AAA(oq𖗀Az 8AAA(qv;U A|A"?m;v8A?K'[90נS} U184gהFt|q=j,W2p?S:H=9JfZ Z'4uR͑!OHz)BQm҆}B$1 V dw=ӎ d^Kӥ"#t:DBJKvWNB=凨2WWWosUUUܹsoЩB辀z.(DKavuuɸ$gu3!*k`ʍ ~lK[vnd΢5μ%EK.Xaъś>ްuX\tA7(555zΝ;wԴgϞFrv em˱dHoTaZN*+98XZ]~ZWn;K*wعBK_WUm Kk*v(ִ|׊~\%%Wl*q pEk?j۝ %Dz.곚?~ϣ"7oRuG"4](k[Ow7NdcUԖSf/۲mG-nǛ.XaJTk.^Cۼ%*K}Ѻ+7,.޸5dDNB+ݗ+]'/vl{`{ك]݃տ#CCǎ:zk]"Q/,%6%g9x8y ])gB窭vuRsԩsQivΞ= emzUBiEES85{e쩵[.Z?+6lؐ`]z=jg6lQpP[}tm&':Ut\L\egӑ>ܿP_]K}{j#;[:rW"Q/\PLYt򃟦j[zw^z/E=LS(V|=MdkOh[kZ[67۷o?m#G$:p(rT{啍)gB(8z.z-V*KuMgxa]ϼw;rAT0̫`*/w+4BLKϕ47_q^+]sv|6OWi =?m[𡷗mS^i*߹,̴pKVu|yONN6ٯ54vk8xľڮz?ѩSENŷqw_uAH:yd??wg}vҥ+WwT׿PAk's imoGfXʛS0&LS(HVΠƝ->)wHzcb lW7$%Hcp^7D&Y8 s_8(JOOws*LZu=?/o~OXҼ^M;xgطTYwY9E鮽G:;c[o|-TѩSMs0j;pG988HF.ĺkQ7՞fo=Wsi;Pukk߳",呇#Ҟez[w%kI ?rN#`݁=}z.6(=,H6WL.eFkaKmv%vFO{umHGUt_3mu[]n #.ܱCIcmz7|ւЂp)t|ϵczna)_Y?bΜd6u[֑Jӿy\3lwllc v$غ6`K;Fh `yG]=‚ eZ>hy-&Od{آ|y5DO0Uqχ6=t헓ɴ}c^x޽/)3tOYxt@.z{j?~X+9}*:UtTE߮}hw_&oS5>3g ]8⥋n7ݖEɎd<mk6Fvꦮo/t|嵎NԝoL曝cӑ}ms>YtlRiWM!ݏw|;>B~N$"P:AjȺx"e'n"e1ewʱ{;c^uF۰!*L1o{-pTt's1j@̮m'S6(t<JZV){P?mi|3v)C:xC]OtTѩS]劃Lüb>C]KahscHu>zjXWvqg荘$7ލ{_3-4u7tmogO;{{W!T|#?gB(D KpJӡCQ3UNZ(|*13sUm=*z7OXKA[>8c.N9zH7gkK rׂyΛI1Ngvqc*?mL~ଇ^{߳Ƽ^.znV# 3ǽד?tE83ܐPJ_pBT;՛ioˑC.j遃m2~SEN5%A!teva}199cKc_Ft[_{u침5~ .mDݳ>J8|شU["ߘ|={{S#WCG!J^\eee<6=`DSez&oޟ+w+۔O.GHHE.ɉ@Kg:Y_ d-f_4i^.Z[KUر=_N7fB?sһi{D58ԸKgTOLCNju5ԗܷU \nx>xAmodI]g|Ԙ|&) KlUZZJЧ֭kϠA96FiC_Xc=Ĉs6\|y65Ag44?|%Slzzҵ^*MOZ8m[>xe q͗l掦}v j*Y7K :UtTSM?\`}[i·+o\ƋDD|iV-|}z;SLS(}~B`{M6}'TJt%M8֭[ׯ_O;7*}Jn>" Z;K+vX̷7>֢6$ͲUTՖo)\}Sv-+KʊKʷl WTV_mkp *:UWt_fTmGm6o+޸uƭ+J+7ϚZV7nI֦Dvs7-ZY``y6zv+VV%gS&i9|&q\ڧlnTY\\\RRB_5T}};Z'iΦ}ͭݱGwЎ{v*:UWt_~( \@ș *+炠>QXXRBsپ};pB BfASh:Up  BAAA  8AA!  AA</'g} [:o |GF{F]. jf 8Am۔۱sQ׫8q>@t#gZ/=7K7"**zӧO7J%}lٲʿۏ:zmVA"' {٘[oSoǖ~}}}U9 gZ˽Ⱦƈ7 sE= ̪*,+p֭8rtRCCuvZGgϞ7"' hŷx[Ꚛp8sݻw755ٳ7[Pb.Wՙ3gnܸqS :Eș֟rA4F< sFu_8/)gQ TEqֳR(d e$ިh^yT_DE-P 򗿤L)r@δԗ{.%?pKN`|ݗ +%EW|6iHŜ,,D[mm-^׮]SN;w,$a>'wS)Wڋ)r⠼{.%\rT\vWmܸ -e5"/ H4-O}i;9giG&=.?Rw=!,ʻ !K4"'bpIOcĂdݱcG@tvF+BwEhxB:V'9uS{;^Xp3tг&:mO-N3gOz&T^n>_;FVmN V{O0K^+FA .i,.8Hp0+@I ^1tҩ۷b;.bo@,^.}fq7zȦniOnl2gHNsg$tH3Y'NA+n"CO:H9sNjiuRۧSA=^üḰRSWsi8%E`W gBNIT]]/b/ԕ_&jFE52̂_7jԥR;6zgٮ*ny KW8NhE(gW'm>|ER6|1xt=qÔWtti?9`qpostmm^kDND8G yŀ{뢢5Z2Wkqo=zk)P|+=3W%%3Q.I) F[ZZN8AF0'3Gz)3Cʑ{, 5#UjAngȄ vGiԨ^Y:z}1)mtN/T@.F`SAýӱͽƘfF1~/`Vug%5{9\X88L$J5A^v@q-:~âߢTN~yۯ˦?de:|Ckӕcz("kNm/&}n`gGhn9lf=S 6?-U($IwlT@e_(*;sʩt')#U y^v(v졃"OlWļl pn+5M90&3'\I {?>`9`qP޽S Yj~d;@[ŨF5ʥK,kDbpIbVp0+dJ\#t/m8hFX8W"QOcd zϗ1T. KEgSp/؎yLPVz~fW7dj4kt./RS <WiS|C$真b'KwSO۟wω'ĥB.|=@Qf*&UB3e4NFqʃ"/ȷ^D&E Je!Qg񕘀⠞NE/%̪R $Il1sE n.\,,^¾ bbȢo )uWEOA+MY}Җ]˫DK4Ɵ\Qe ~β]͙EoE#4caoTOo|(v._OiwsH(t{뮻hbĩo]/;;3{WsϞuUB7ސfݧ>hoW?OZ-A@+1C8eh(+GET n.\J}IE]xPړF]__җDՓ+#=ݏ}k?yYnıwo|8@ۛ8.>W: Yq^1x;J;Y7rYճ'?'?'?'? ~\[N{JL@q0~q  ͥr8}"u1RD|' N8?;vYY,C8]+V$n}}`l6X=h-;퍽uCsmq&KܥDBd?UmGaV@+1C88VK(sYA2.rⴋ̴?Rqvm[[["Jc$v5$P>i@+1C8˔$ n._,%GR nX \{Gv_ d6>8qL qf%pp94|Zp,.֋Їn;+%& ?m4}qz_Kr5 βh±p{[/r$Oÿu]xq!ieb83 l APm8\hzqz*_ARb-ξ$8eAm+|ij3g%v[n2Oe_A/ 7~z뭷B 3ӈ)MƾOF8AДkq`>N,MgYmb.WiD{f?oƟ3.{x} k꧵ԏ ,="y6ɿb*D,o/IHzVվdzsY^V'<1#gܦB['zt/GJ07FyF+v*.qCr>T.txu<ǒ 5Ϻ~:o#{q4"l XrvhI]U:鯐_ |F\ھJӆfl^kq@|c}ܐ: yՅ*ހWxsUir Ϻ~GafZ935sܳS~,[ۈ,Y2_ձ^p  uaq.G!>Tpj7?!S]▦S_h;jHnfU]4ɷQGa+;eѽ䬒=Ok=#gpX ʟyc/N?[b3k mngQ'z#\jt4mϺmri3-.eJˤJa8SL^cq"JYiYPꢰf,Tod~p^A\dgtjJGI"UnSɯya,TE/T^;cVY>ppi Un8W}=`*3͉ "KϿKg^03sn*UG҅3Mz%wm> Op0 ʑQO~TEVɚ 0;Y#^fד=Rwrzr8늳={Vۨкp0 M(ОLR!1AIv 'fJX}WU*g?QB[S F?io!ꙓE]5uʵU/ pp$8}ޕ<2*X/xRIݺI~*,mQzW[?g(Jkv]mwNw;ΓG䶂]P^y͠|zd1쨘IېzYs)hƟ!z 処~ Ӳ̓E(@8h gD,'0DG:a8U 6mT8XB?̘>$+$trkGh<^#_nҫmQ*n{_9N9f[²rq?U nfTt;8gZ׳܋9"f®'!f=F٬1,{$7R<È bT}hzo٨=3PtDDRǻw)IƌJO}2^a@aAhlO(*֘\sUWsΝf#k2ЈQ'ߣ+ ҾOK?oM7tA&k_AOEW^yW_{7x7|+ו+WVB4%B?BB?BB?VKc: 3)^Zp;6#Cԑ~KC]W~sh'4bpЌ9mo,ԯJҙ$-Y#QZppARD8.TÁ ;W?bӧOPL@35KNӢƼhZX֔DNAlyTZ{VkZMzJT&ZГTsSM/_.FmxO<=ЩS|l]P*vql#gPFRڑiGbÍnG8v(SJd:ɮ,ycosg7&*a;΁9Iw 1U_l#AӇ>cH_/i 埽=N@ZCR4?0)P$ 8?dVj$P[Fh<At`1GŞŦ{-R x4B4Uk8h̳Op=m )2(Kanz6H$U=DjCߪ9%?n3!h#pP8 &$Au9s !h|8_|tpbm?A5䒟lm",)Y4`bKѽ`$k\D^>#!btP|FtYy { ]$ $  _}w@?ÃEkdW.D\. -'6 qf =;s$wE;M&:(?\P Np%qKޛ ^+PuPoevW2WЕm y#0˜RNHlK&pHcfBR88Y7 u8(kk=zȑ#;a[ZGqpqQd*Gl`«A6NP8X;0jC?B45l4Np )p AA6 ~  h88YAh#1Y}`1←'5KI9M4']-6Gd8ԦW0Afq)Ʀ^'"Olm`|.[#>̤,uI-)MGj,uAk:ҟkqpoB^rvB׺ppzΤ̬?]V8YӢ1-$ M"(!~:d :ŋnNߨӺ0% LduiϷz$ tGi{<͂穧ӿ$(C`僡M7-<?AG $&qHqZC499Yw}[JP$C>{oM`YcF:KJ|tw.d1=pNWE;#Y qf и31]I4^pi Ap8m^7~@:,6MPV"KZULA~!ɺ, i96$l\Xq]XG ρY0R]ErYw-g=Z& lPL"QeTҁ]-ITbW^,^vv/jWi{y]O,65jB˺Mbyc+ WU#ed͊#`_#A~'oGvw eMYTsGin+M Tc̿ =!ًQ$Zy {zhPrX6r?o ql8' ИU}M6L*\̷gVљf&uKO{7\iR?q$(̾p08wVW{U1': ZqSmvK6qПW_dMeQ-HUɭJA8YpM+?Ef߭eySy8(LHS֓}S?\HQ _F}N˗67ͭ"0=d/[ׇgͬ<Ѳdaj!Xy+~^AĴW< y-L̪Zi˪~Dk^\$sumv荿j'UQ%rRqR12mb63n'U{9^uTs@j[>$Uyw8iɃ=ܙ5UVg] ]G+.heuT̋˕5"u5;B>eXP {"{ؙͶg*'bAc ތSAf =JSeP]~.L*MMxYebDN^.FQƭFJ9ʹif٘.'d-:~ީ |`=Q읉.ׇUB':s:o p؏dω'.5p0t#K8κ6_žP%Y[KT/72ibԡ ` 9 $haP&ppd8hdVLE8X>{Ojֳss3Kܧ9Vsê$Dn>绂\``5gDx0]{ؕbz/( wj49^MdIUɿKϺp r*ɽSQ}Ygfxc]Q&/WyHҞ2#\6#Q O [F}u3cĿMoً?p-ńD'aȀs/Äq:˨|Gp,qn$6yYpLsgj`c-E"Tq0Z^;o`llG_d/ '7hdqS ̧-0E{8މKK$n_(ࠞ;5% ˥_|8!~:$- 'ybcqe/j:9 jLR|% mvW*G y(: 5 <?g~f쀿2?!h{DK.tb|A2)8;:HKaQK}q+: ,f.$ytx1 -C;2ӵ,v8tHC!FMWEw7d0CIyx-~TOՁ"(x>[14dni·$kka+&.#d!3Lݎ =?oxFlt ?Li!&6͆dF*pg8(3/Xvޞ{i8B/ C),R FA&E1F*kX5 8 8=Q^ @/ p ppHTӞLa_A `_A `_A `_A Ap>9v&K#yYc[Y'ڎ̐b8 CƷeu3lkϲIr>T$q|g~ru?zwz:uSAfKMpJjvZ5-5PkG˦C2=ggfaw4:##MStjp 8uebsjl0z"huYow'miɳz5(F CRNN`n8w_~/e_;W/>{++^'{سvZL8zB8 w̉Qt VI ^M:8VW,i! (:2m~qTS?e umwݬ\4( :dx8{kOwk]iI8K[olg;~\Dz_w񶏮p>A`b?i`\H.Ϲ3P s'{&cp8 a8-A>t4+׈Ћ&Imx+qHb[syC 1mjv]ߧ{n|f} fwL=!;g^WÞC$$owT 6A\6.ωJD\v*}'Z .ggUr9b6K1kgbأֳōqP_۰:q0,Y-᜷y"/$;L E\Ao;bvfn(x_y2'sYh~Xw,/N)6 y@,ތu qYqQWrQzu`-_ߪWZ*ft%Ǝ83cp3zXM%p K> ǽ{kkWAO#mw% ~w]g pgw_yWy\s9KלkϯyC귣מ1{#ogjc٣=|1{K̞8e?Oe~2{Oe/OrKLvL^~T~{?>fW/|WB6hy뫅L1pPM#f߲4Ӄ%i sׯ;+ٷ~I7~!Ofg_looeF|ٽE?{݋ow}wߖ٩̎ _ߑ}fJ7#g?\wպWo~8l˒O C&Wt3ٛg?Gىd_S _ (|!$Ql:q,'%;~g"'N4yWgr"GdQ׆xyܠ۵&v|A|MGeo!?\Be/}YAL/ʴr3ُ"SKW7.Rve[r嬄lŢ巗@8A 8A8Ap8A8Ap8A8Ap8lд1~9ⰻk׸ )ppʏ! dmʜCm7]Ӂ7M,9UIhx/to6KŜTtl[TLZ} h8ȎCM#>B>$h8a%=sܳG6E啶"uv㈯Y"O7F tibQ:ڠ$Juq@ evMhMEMf۸n &'a:dS̖ e,'pJG"ZNK/`QS̩o텀}C:ڸ_M”P;0{V۟ad G3dX)yȗ4nfp؛ny79o_*܂Kg;53UEhh1jp8Hn4JJSb k8! 4;=C}-^} ӏDU?8j곙UetNLcj'xkN NmU짋U9\Jhw@dqpJ >-jd1pp=ʡJ?_Sb;0g8 ڑjAK3~jo!\y/",tA {T_[sdЄbXI8cVߟ^д23[Iu"=!Ja! sZbX ĝ_{#Rs8Uv&d^J\ˉ|ˁV8lJdn 07y-zfH@t]I$z7CxU\x"; 7p Q#~GÃK+q0*$w ^~&:LHB/Bp0.5]J;r\ ĵ 蠏5v~tP>܎Uh qfg #! \ $?)Q/`?Ʒ|]D|A;c^@d1pG$QÑѢwE=}om 8d'5@CILF5BYyP.jV1:ndlgRk"z;~#8\z$A Cjt B]A +dA OMB C !~ no?AA'AA'AA`_A A/ Ap@h,T?>A.p7UDJJJ[[HT[qO3mSŁ8yli5 ,j"uLMxqE]SŁ&a,YELKAe+bw4ȉ5tha_A[GmnCA9SŁ[ 6A?Nտw4 ƇVvAp838hiv@z$'u87RvD a_ h#O}!O}!O}!O}!O}!O}!AiHGckE#-UQ8vRg@z!ib=Kw9O3"k8X ;]CMV#Q{Gvwwac5f&_{˵:>4Qơ:痏q0\nX8Ȗ Y]|gҵׯ;̶.sCLey-Z+AUq4*JBEjρpp' Oͮ08P6KF9 /~Zn& ZQ^\Xlee򺏃eG]!!6Y7$_ $bPSF!fJ{DMKU&U@ϱ )>$5pp jr/ yXҨB"B5WIyaؕ( ~tyvyfYp0 $D`3mTOSe" N UuMUv_rl8Ff/!`D2YY@F0HƷ6UpP r4J>ӽ.ˤMb,HKT@|pU4)cF:KJ|x+L04BK_KP A@  pp8(,DKb ֕i !qP$93+E1,n`t 2PjPppu,ts0c `ʰ O$XwuA?1s$hxP|%rKMt/QtJ7O?_<%_yfއ6>_/Z짎vYB,6Q^ = )J8s5 2*8HfJ>V4&0(쥱Aqγ}׋N_jG.9L1,fףh!h~K/9sFXNXw-RLGEƑd/Cc(8NjODя-,f,pΘWEF`&S S?4}DdVC>ӯ8@/fƏa~JI&~t,.]R|yӹE@J4[ y~M* !魷ziĔ} 7 ͺƱ/VB= ;6f=MnT#rlS;>;O]v+&"Y37RG㠈h`Mx{VU408}aAʎT 124r= g-[v0ߠ2mPa9ִJG) 4Ӛ}u9b WWZe@Iq0-pp'VFu+on7`p o#/٢-A&f_A৖ ,.(9-A&f_A৖={Vpp 姧ri-N!}!Z~zRII[Ah)3>%Z þzbT3 5]hw;*=AP~ZXIO= ;Ř]e>Lv1Oh#J[[*&òpA)lMAZ+:8@`2v1Oh-GX5ʱ?U]1KQZLIk{ l Dp4Pz14!6TLKqSe'ixbʅ TжP_!sב+ɱ½KR.g,(^kEcs&53U{!&@aGvO(mB -˄pgY.9%$'†AN}⃜HP*%LC/%g( ``b:t'3WAOϝ;wNbt%^fn /lttйM 6ANտw4ݚʕ+B'8m^ZA*e_%  .K| A*\P~ik.T!8-4"28xH6j:Kyzl![:T!8-428^\+/ԫԣg0p wBc/ɤWq_t\v?~.Μ GZ\G8؏W宓ia_- .DK\aB y8oqA=J;#:~Lu8{ڛcᴰq\zIpW17!GQgb-#TA8-M.R  E0)h-~ZkkZA*N žx,Zj1CLM9 {b ~.>gQ,T^Zkfᴰnqb~ U9oCPjl] LBqAL T!8-4t7of}f;Rq`5jՀDj@jգGTM`5j@4 EPrr X 4ۇ̤lViIhVX k%`5 `-DX 8"W`anĸewmڲbVq89W[ St9 ˲Ϟr6j;+U,2괴*`=w>WĜYKFR79e҄RT'BM<ׯ222g]:u8~Pfz_]NL4[ѯ^aH#St}ɹݺ&_JJj}eڵ45TEEEO>ڋHU7؅ HxWKKK5od䉕uua۷m 86m߹V!dmްͦukxqefMKOO?|Yn6|e?AV}w0PA'+,\o\z&x8y 59FҹSًR8|`h$صWLEUV~b2۔TEլYHpH(-\wO3 qBX؏!ת9~XҳOn]LSSSwseiS&oCPSU]lɾ"Sn+Q-/{}fUiç^׮]kYʔ$?9|Ι5f  |M[תYBsȱmZϙ9]QQ9RR߂غqt>ffr0=_]w"Tbb֝S`O4dgg8t[]Mڊ*N_x޼]hI#{ x/ՈaC 7kiv>nh>9 7n5c Gj0 JKK2i^Ș2yb0a^rRU]JJ=z8ֺ]{g]'.^9uiղSgF L) rv(ӆ5luF4eNP "PTnr` 6?PYIi $yZ^]1^2rhQ>diբNq@Ϟ[bi-Z8뎝>:eK~>''/?7nZK-ω?<Y.W;wWR'Omݴ!yy'OΟ7%+K!%5)[6X("2r-h3sN9G$;Q/mP]fN 0FQDu@c݅yI:p*8t$'7{w=wA uEа1)NU{r椂<~ K=b=^e+tz¹]R>~hblZjn޸L)糤HPЛ?9ط7]\8 1O@-""-[4'Ƅip@!9|`=z3.q<2~LĞ[ |˫[WsxEYEKW?x}ޭ+iew-7EDNO[|jwzu=x 닛]>~ڶ[igcHǤo^LG.\[?E_#$ӢKsoIWKqXC޽z¹}߷##Ԡ)Ʌq<,ͨ& ϒJͿ4  #=nԾM7SON<牉p`gcNWcnjB%$p͝=_q"R0(95?ԦW_hn&Ƅi'˫w/;4YG!«pW6\7(g_vusAdѢzyp۴nEj~k֨Aܴ(:M+NNN#"NPGXB`Y0,>\ UVEU554bc(:QQQty-UwP4Α;I"0 s.ڲq~?Z S?P8_O|ׯ]CG2;݆MT =j4 !PMYY)6.VO8:G: 7n݆*S! Tj!I|5mbbOQ5Æ 7fC1Zͯ70s8E/]6/.a.̘ݺeg@W>~mZķl 2hQ^'BZ*E@kUTDkvJ9;z#(Rw, GOڶm %Q!~ED0q.*%>22z ϟiN Rl$!WSF2O!)> Qߘ$zISO# L]CH_۷.l_tt jMM tP,&:'DzuxqPh/\޳k>OfavfM@uR3.*MiLV 3 oTw"]9MxUїڶc7w3OˎF^TRP WVRF ߍ?=}h֥ ]GǷ _ܢg[t#,li?n3])sVc0;1 c4T4s͛+bZ&Moߎi"j 'K2AAA7nXPYVX ſsOAt7^1T$͇yX { %ZeUr;\VʓDPXs'e(t)~,n <0kYC.E_ze@F.""ꋥ_9 HpC]xh i8eJQj{l3P)yrde_Xn>fL2 |SNs<^m۶߿_yB{ƍo@!ͤ0&T pbbcachwIw0C") @nnm=HwEB]C2-u@m0Zjժ`GGGW`cc %/ x[9Ug.@1jBg>0U n$_Y16N}D55%pl>v;[PDqle!j.޺u3Klrɒ%tBꆁ@zKؕHXZ-GNڤ d2aUtVD[otk.y",WIJPIp2}@2MVc0sKEN :Mw^Nx lڵdM;SH,[4@T]h%r]=R_ݩlRsCr)0R`(s Z>\R"ZtⰐmacgp;L; <_^M0dop@dQ֭ǺX+V  ;#͚.\ (tqLa9|nՊ%>H.=nbj¸1nbS)=i84tr@. F"r"m-m^}]t!__v_I]sUfN`аx*59Ϝ ɯI߽oڴW;ϸ6jt`NlLt1MְA@G>z԰QC2X(dg`(#/hI#֬K':]{[nZldb"v !Do!4[':!SBWt7>O:Z.Wblo`t0Tll8C4V&(_,v ,߂ڵj.[?c|?UOJhs99sUb* Stl 3D+#RJS0 JF.@Pr6c9%A] K,={ZRE"'TR\ڦ'i8E@@.I#J˙AAJ8JJdLP`@ %BiPRW0jʋQ~bYʌ.}UlCY T@ tY  **$+"UG.,ZJXrUKZC;]|flZ$z$bj{ITʔX Kl#a91ѹqBWwPՕ6*+0;j0،7.. 0>w MMR;[|ݤ&^$1gKpc˲'Lc֎#B]2?fӷwILY܈>JB+;, aFˍz*-,ZHRvldgtiA=P633iE+ Oə|w"se* gR,_P3]c׳?uɵh]`s2b v_~+T)~+ZΘc pr 1Ƣĩ3~ &8݈1 jF/&6vmzOFm1{;Ҧ7P5:r>q 6h֝@fԎĦ#mDqR)S'SB?}^J]<+]|<ffd>{,o">,~)c] }4jq `H`Isf>t}AܶcW֮\AUԱӭk?MI鳆߾ָQClvbނg]N_>Kq;:*ء}MЬ b;wZ:sbceK3%[H̗sRL0$ 0{䳟հ/!+ZΏHʞm1FMPEt^IW/ n^'VT#o_( ɹIIYA/jP5Ƥy=74%Z IDATӱ%j_}w14Bu1mSb`H%n\nQu*%)vWc-;rU6E;#JfeE~[(FhnBBjGԎ0O$GmI=> Gr"g [%UԓH)Cgg6S(y Wy!&%'2 W&//cac`޼#ݓ Yu͚|>s0GT wFۮm ζmZgBvy`@;w=﫡ݺ=>{^S&c[  u>Nz6 L<իWs S?"Sη(ޤHGMKrzGҲ6kI|ڛPQA jJs3sگhpkׁ)ײ5w*UΔʲ5ZzH5k<~#+%u m/ϐ8{҄i/?ܐa% Ƨk^/lnoőS 3}2>trٓ\iR v$b 6nB3>@1ahxC2uS۰Yo^rl#Ca ae 'L∱D_X(CHVO,Rj8mn|i @,pLZmkSS4yԃlzFf_vQ5*l?M-߁+;4~ R0I޼;%k`7mB!߿_mD a-Efb ѪWͪwm^/bj3a)07obdE5|蠀O0bAx݄o@%`ԙs18eƜd͝5=';|yۏ-7P { Ə,BE44u˗/#3׌Li8 BxG@AOzhzARj\uB)["MPϞwaZR$`%g>RPZ=3D Bh ``IX K.Pl6)v N;S5c^۸i\i-[+X-@I)* 7Pej"p)MITDYY9a9Qğg^ʄ_NvĤs3?QY X;En\>m):""xW=z/۷o3gE!^ tK=vP)& #DMM8k( $vi)G~Jc&]9q*w<㇔&&*+5Y.Ao\A8'.NC:ֽTf:Hi"0#' 6O;{;w f"~@#$pdwnF`)Vm5{}@H\?+yS |g'~*Q[r/lGڙ92U[)^@/1x+wa,rܹ]-Lwrib"|$ }r{b܂>~< ?v%V_X(ͧCj] $\k%X% XrP;Ii:lrJ+݁-]򢵋-j5GҊ\,Jxw13 ۽#4yH4k^%ʳC0L*$(y >|@ g)Y U:e%J%DE@ɎAlVMM* Fx>, 'e J~>S4oB6X:C%u?zxDT-?U(]B޳'E,rB,T#9,\r+hJl&\d5%P9wܼyIhdȑk6n[+?+ڵccJhfFjɉ$*.%ܸ3D/'_jc͟?u4_;SS$~B)Y %9vi٬ oCO> ȞJ"""TTTܿXamx&CcΜē'es'+d}=k\m휘ӳNX{2'؉7 [GVVK}*:xĉJffҕ*0PO++Ց#k1{vqpQd-gwO KD3((ƍ-V- yDll\dE֭ۥK, B |̒޴iNt4:Gx/]*TsRR02bp)$$PX8xp_ijR6a_CK]FS~|UU kFuki53gHI/oiLx1uo 0*'\x7m &k 1rH{{ܼ6ލzI{# 'wiʭ[q6qKkHquoLK#۴/el d-޼}7l}>KWfϜ3wJKWzla<߷uAѮ-o5O׷o :|x0֩w\:TAoDax Ʋխ+? gnɗ/>\3*JK0OᶶÆ2dHQ}%jҤqݥ>}LM:thLI(TxB?ݾlaFFUsIL_gg~S߀"/^(Uiފ]mmkb~` S'+Kre5fu^32K̔_Oի\Q,BP{F8(R rd:}ϾS'O^z+E`:333%"YXpI *s̻V`]<O`޼93ڱuS:rtYbA>;%-Y2h i e}^?Y'򼉂s xf Y DϞ 3wq$%!@ިĦTml Y4Sc5s̜ 3?ٚ5=bdW׻ykzR!)%נW:b VZYYukI)B Ít>;鴀ƍePq~uuqGbWLus2էOťʫ -^ tѣGb4{QZo Kd%%%UU+n د^:,6]5]߾}-O>wN @4E_{'a jca֘;KuUy"˜'!\|AT$)#(ސb~ '[eNrBGz`_YY3lp\]ɒuEBys4L!,;qmR߇([OyS 摯>~H9vl5oo3F >afx/Z;3O) .:&W:e聽%@G1'z.x~)**/3>Q3f|SQA)9) ^B yC'K⾔yQ3%$`e3^'9BY!!ps1V( 6a(Q<<DRtj84e+oϵVGӧh\{R뉀c%Dkѝ$~_?/y ;y)&0ܙ?ZתUElBJQ(t}W.[ q`ϥ} (f6!y^켃ZkTG\vj޵kBUZF?-kԈo#蹌̈݋f ^t\VppԴi0ȿuyz"{x,CJ ''4*԰?a8 jGP -!#-'*%esx|7I3?~L~]s|XTcat{74vv!U 9xun<&MC/IM Ӌ1j)Vz=ݹ-ͅ!l[$"6nĸ^pj1K `cyyVH5,@?4D_?ve;;.q&_Rn,xsE CtuҢc J}eæm+Ts_}axjy ]@n޴ *XUc#$ o*-%rN&  A_)tKe3 *C67#&vw.ފJBo[YieEw @,7X x4(T?DO%s'O'*޺Ji,xJc5j@0ݻrK^%o$$CfǡJݬXV*X U2{ʪX UVnVAl"yqqqǜlgaa!z|j_dY( ̛7ajfo6i w(ﷃBh@UUy]vŶ>ѣG!ʳeA+vp 6QVN-rK|44[oG9@P@6d` |yKJJb0;o*Eİ1C>{Z5p!P 6(X_> rܨ ~cˆ#pipV*Y %vS'MSVbʻ68i ͚;p"⩧ϜòAoWDDd򥋰L϶w+ϒr׶ j5yy8SBIPXXvX6pcv3·=ƍʂrtկwϿQ+[5\kUՕJB]A!ؽuP @%ժ :_-NBkppj@Z(*UMX-K'+쬭mL(dmZYsK3#E8:Mw^ҽ[NxvZrr榝1G(/VV%*.Z8wa7kt]IBz5gp;L; Y_\, !-8f5jx5P>T $wu+++ע4FVVE@P Ms+3{Z4,uA*,5lƋZ> O'DgD#.*&J_%+aԸu:cFg-Q5+W6m$G.DQ;kDEVEYF>SQZ2*I.O4P-?)[iij"OLe+OI[AKIFbbfḁy9l] H6lاO _իW?2Ȑ? `ȝ;wLLL)&6LMr(c-㌜ ""S~f:.e H勿?uallܽ{)S`:BYlj344a6Zt@ג19]p.KYe)R>`cN:Ǐ&ISL ) -6ŋfff%dp}9rҥ9%VfY@@@:4mg4 <x:bR@ ,"ht)rVVV+5 u &%p%aTzڵkaV`6;|@ڱ{ߜӐ #îڼuǣOTUT͞ Sܭؾ|:~; *aiNȝ9g~}N-&Xjs~j0l#MQhB9N+ 1ydٳM6m@122GܻsڶnuIRu:9yO#Č c>~䞗_?ة{^{ ֯WoϾu5+Zgkmv׃'EW3Yy w0w}m%r % >uk)C7^(rpu[xᅳk5uysfb .h( 7*06j3L@RP }=O/o-[=|M5&22֮US ;͘: uYUP' 2Tdel@@yP], ,Cr䇬ѣoli;TGF=>rb{tOQ<H=*YZZxvZ5aў>{%s eTEl@E@ycklu55>oܦn@::= mש]&3+˽a_B2@C79qڨaeel:6{Ws,&zCZ 1=e5jhYf]WhV=Qދ@:ECF3ar/[Ny`I|t IDATO ͘:YUU@[qKf&wn]߰A}r}@tvabeԨa@h;k 6jO H1ܟ ^M)Ό4f?V`Ѵۍ+_S-;nLyW8xh%<jfԾX짚)35;+RHIWuMM;E9Xc0GO1m[M9i-m\ⓢԳ$ơ3*f͚paf # ?%.LE>'(J >z<J|޽ " CRB=|BS;z<Ӆ3>G'JHFAZALs]Fji#mlt"N_ϒh3F %Wv!߿;̙E녭V߈ [k1DnݚNS*7ʷR_s%*PϞ?lR'>̀yB ߰y"ӦXu@L(9|`ϝW,tzJ/,t9.]k(רR{d͑TLșnMUx{IYIqK ;g};yq&t߇}ި*I:_ QצMծ)_VntQT:oIkk i >~:(^ r6pxP*7vTxob ,I\TxIп~S鲒Mɱ$hI-4j]uL~OZwC!LϷ6t3\VŢv0W}(ʒX @JJ z`6m>;Hвe 8[?oM|6TSt:m~_jeȜj^fg#gH?Or 9xd0HӚ7lr2a4urK|\q[[lՒU];*N)UwCypfT!o^x5APDVJ`&Z݁l'_ji 1 G=x EGu^ 2٤CmYTp w%U$bכophyv3Q,]ijLվ}{ZCuCD=fJ*M;ov7{^=^c> nC>a - 1#pGl}M6[&URPN>Png7 |x-b`/SJ֟\g/Ъ CT`G"l %Lπf 6|<*_ZZWX ` V'_>PE[n<07j#NЃ6Va3SPSH(p8o uLgνz#&(~sTE(W-:'RZ}P/N8QM*l)^3JvIx _*LE^reMCwOl 4j)Zj4CSȒgqDVq W|1`6 [dSφ'܊7 oHAқ OzP@kԊɈ͈%OI@rLfLBuDeBG<̃Q}ʵSH7BĔ7lwtѦWN斃}Oe8"^CFˌCL~j 0m﷝> /ѨR0!:}s`u:c _\{u'j!}J#〈Fo=>b4d0%a~2ޑި0Ƥ̀MDtix"tfFÄi5h6&'ՙ$Y}TQǾW1&tlzF_q˙LuMA8J4}z|0 "DV &u 8=_h~\lUtL̖ kk|emJ S&wM[w؂en݁x>Ѫ6i >>=;))vvv 9*숇_&佪:ʷ+=-N1O^c[[Vk#~6^``jC fN3'nKmU[ pū k6B\M&nM=07ݻxEKWSF@LLJbQt^v6` 8p( o\g8\ yH1X>j(Nj 7o?lfvI}DM7 zC uo@ :\0 ?\L}.ZЪo0~uaz1h#5q(<ˈ.m-0vDV%`@rʿʛW.9%+˽4ČуR2}f"*:; cDB8[hMբ 0@{F am6굛$DJ`c™(Ξ((oq(7wN& ?DSZl3^Ɇ-۷kC9/`l ,^9{ހ}.>dО!_~#6'Cى1<>cѥ\aFg?J-XWEC.~E3SDkP:EQ^N̴3cFٱ!#Nx""]  cc ܷݨJc_V߿\fQ]]ܴ3&@MYE`Ruޜt}Н2~ H߿700ѣCX; F0?b2!rsex0fL45P!JSl]@!ؽS:3r ''Ǐ`Wz;o8ܠw½@8܇ @f*M$чO" ˴0 c- `.bnVxI ^V 3M$ч*eJLJz򥿿?V$MڵUW ,M Hyiꎭja'M֭[Mbk/v U ,% a'g~jӦ }CѣG@_V|,,k,X=ij톢R&zɱcǰ}E϶ML H%@K:::`I?}3lhݚ_<}TCF.]Xe?r7@촴4# ap6 :~t7iiժa c]qWK[ ||U>`<Ċ>l1ZQ,P8%MPhwPliX($)L`ĸư5 Xa'eff>Ģa?W?|]͸XdŤc̛ha`d6ObGZ h 9)2cD. zΚagkMYI6I㹫R1q8,`doٺc'`,yb+Op"ĢNWWXr5ǀW;!/@YC""zt⹙iݣ;w{iݲYãǝ(N$gattb"`NG{䛷>xy,FcأmG׮\ԅjj@r4Pf|(1U tRϏטF,ഐ`Ƶ HL/^jݪ%B_rCG^ *sjN;DJwJpgPP.@D~.jU=@8Z[!nO*U9W . `5P4P,jbbJ07ؓmS Sx~nw=DЗn޾CY(P`Əy];@VGT0UgN8e=G>{y"` NBAǠS&tԛ\4]mBf1k(fa^{^pwCE& 6%$&O7 A˛-Sf &ztX~EFQbS8`U=R<%L}||Bl :Mu 8F @ {0nJHHNA f&^l0Cر pty;QjN, {t99CA!] ֬D+e]dEDDBqjbb29說*^C†77 6[E]0#`ninܺcÒΉ:w4q6!K-1nefډhs|(1㡣Yw@S"` GɳYYp;s՚ mza@ }Mg٥kGs---w,WǶh@W[ȒO}*A`)Xj(r2x`PXJ-#!>}r@-vR1ɾzbj]$Z(qWXg>Z+&!(or Q+یRǏׯ#Uj5Zf*~ C__%Cc$((f{S_6Q< HbĻw,wYf((K!H`)™sIy 8–bY (K w v#GwN_K`9Y W^@]'IFc"5q6gbOY   E$9"nܲX+jjXϝBWSm[:4nH8}kX/@,jtZ.'0ucF=޹gi(n;:*:84p,t b4!n }vJl@4Pf,ź[ҧݎ'W*.CiWoʺ:xn Y {v}D c/0N̙9-W73'P Μ{q8̰}tih`gN\g#4*e(& 8TWaC*ǀpҒ9 t{!twz LޭC*3yaUTF]60OH4koj{XUM ]x1 N[N|('叏P/9 9^~gkYȨ(b)G$+22 ""#qo._Bg&pu`j>4O^M}HlH5n8L]~͙Sܒ %s"q3JBvYzyBv#\H\C %R@|:d%_~aO===bhhȌNܜkгC4!3Bv`nCΘ%-4麄#-ˁ9>9ɑF8z͸r^ℿqd8sF]K{NC=8|5k"##-,, Յ_1c%VF ___\*7|\tzu_%0@ v]]Mϝx68 YK!do&'l=m?ԪU ttij3ٳg͛7g~'jp,pѪ,Nh֨q> {yyA rd8+9an(U }9ҕa|s˯ég10hs.4MRTZK.988ݻ E0N6q°/dE6OFyPݲqbLد~T`` z64D`n~4p^tΆ zCjʌ9n #l->bm˲R'X%@9rPH36h508oi1鹋ILuđSL tJK<&;ęc3ы[ျԤ/7JSAǡC{Hc 4p+lN;pD@íW}`P0W$E{҄q#TzNؾeuxVN>Q[aŨ&FxnjÇpI.@҃$#J6GÀ󙓙I(ir*7>T_`P+WXzjdTar2E%e$Z(L vpq`T]`#YbIkÇ#ws(YWWY|E\&}8jqd8JQ)r4kp8I G_u|EjժgBX~DD(8UVV޸qڵk\2aߡC(IPəv^oZZVH`cor7t֒K\{=Ϝk8ADN\N9L9U[p^pyi㞡'! zpZ v&MQHsss\Š+׃EQggVZREp`+ZZ-$߃.;zސVm+...BVW[ׂi3ihﻛ\iU^\'㳃kﳟ%J 2~Hje5sNJn߾ # 7nܘ={6) EM8QTu=OwR(:/W;)*؍sK\(z)$чbJ9`kd5 D "IR[@r~e|!ؕ6ʒBA6gk߁C;w]j-!~<R ],z78-IILL?mP^D,8MHL\|uWK[6Lm;P U ,Sw92SVҀ$^}f`RխS{颅\b)$a?qj̘ʱo8C&oS#'J(xF]ʼr ^b;zĤhƞGO7JR%Ŏ{݂AgOAap}+wN=Nc Ddffb<-Z5dW;w%rSf|(Lz0׈S)LČiS&VVU]MI:,=26jA?~4160܉FÈ۱mnb3f;,KgY ]fƶπx@׌83б^a2™ߞ~G:ov`Ҧb &M .;vl%={o߼:ERb(7eBYumYC0O(-Z0﨣SLf'N={.93Tݳsk؏q6,]iya֭Z-y]Qư05>|8 iCguNϝ9dF`Ҧ+w( IDAT/k ''@G\DQ%rS,H!VEI'|/J!H H{TAAA`ׄ"Dzxer.yvNffg~c5ó׻=:t^N^@$hj;RΝ AQ"ÁSNagΜ˫|?|f~ʞ!]>̷z]~ۗm}mڎ~c'b[lھNoDҶгι@$3xpݹs)޷o_aLCL9n"/V\)'*uQA!z {xMFO>{b .l${QոqcA.;V>PjUV$ `AvpۈBvPqX ug0 n*saD'PU6 ܶ1]mnosgpN7MZ597Ԡo"7:w3)(jݪڶneA#BOtv+|"R^dPN~a2JhOO'H*8cΈe@]Į4iEdg(%M”Ph3ҩÒsAŵGŁw@7z*ٲfYt :2آԂ#n |Bo ­:mL~}4Y2MaKvN%pԩS5/^z_"v߰C֪ϱ*W O}OO s|!}?X԰BMd}7{}dRG8'T( ޾xw?g[g"t+S$R P^uƁnQC>C83u!D7+q] 6Ĩ#G@m> l4 r믿&W~ګ&m(7V3Eaj MR\4}ʯ;;-y6zȔFta:W_|&=0ghh/]8W4|}s$@upz>pE)w(V!Rі_؂ѠjJP-y} Q&,R٦ЭP.)eڴiwR2eR A#cBƢCM\B]w܉hv-.fEѣSPLc ߁:vp l# 0qrJ)m"iw/('OāJИ%yZ[}r eN9K/!z7q}Uٳc4Iq${?WM7 _i]09&-=7o31!q?!p]-ZbfV=:n~d(oFA`FDP\}%rzQpY[X[7(7ϔX[_M888kP*X&R;` &  H:J!Yq8J!عߐڭ@qD`wW3+Qr8yJCdG7c T;^c)N%{7)hv@ӉU*/]`ځۇ/=vv-rQȥU#z ڞh :t g8x 5yO /T#ape$6H^1F}R%N>E9K6#he+V0ɴrA'OCi Jܹ.[J(^7Gv9tyU53hJr8`"hŊj:\#VD%q%1qȯme !dI z"~4iR5Ϟɑ/aSFci|".U mڲC(7oH;V!.f/% : U]ԙs aZyk7oeq@YJ dC$?x: J1xqϟq].?wU*nܪyӬYhg0m ^6}!4čHj(UƦ6*r&߲3+W?;^[q?V=~8Wωagԡ߁B3e"*$<8"%1Zݑ@48=`88TPʩXQI,OP# iIQ$ÝQB`G Qlٷz{:"9)Ή~ L]OJ ( *ppgC);(CW` x,T%!@UrJ?~?ty:vT رcef-ag̜ ]/&ۉ]׺m6JJQp=\Wo<\cǎ 9+TAӖ}[ 03sکLݍ^+RjV kWQr}D<ܶmqӾt ȑ#eS6ˋr;5jIhoYNƄ |}}jذ!jTdȃ%7oNM=:b Ț]v1O 0駟fΜI{bfP"5k]ʓF$L2BYժQ9}3+õMFZ:3$I>|tϻwASplI( dA$C-%Fܔ]zW3(K.mb:ㄎo GQ>BubEDaob!ްUq3Jqpܸqx >5T" UWڵk¤ST .!%3"qYWxkV|SlO9aJ(Mv/4B bܵ[H(yͦ%RlY!*;+y{%',[fыhnҤɓofb:c%YcF8%Qh"> D;C XD*` "s>}M.\HALҾ}{xp9PGqff-GF 8!w~E:NsM6MhsBP~->&OM݉(F(RpTڶ}LJ':V۔i_#;JP/7xgV{uW w!8SW¡#rj-)ڱ)|zh;]Z"R q6x&Oi^n,fj58V3ld{Sm#{N 8@=XImhWeutV@w2lĭ[3djjK^ytñ=~vdr!Fz}͐ Ȟ}ǞM:+@bBK r|ߣBo'Qgr^!ؙEQBE)$}%$f<=PPpi8 Uq`mn@G)8ԐSF(˫tD-CjTQwF E#Gtm=ɟ᪺99̲wNtϦMe̋pN۴iCPt H^UgP .am<}5I$sDF" qPu҅\v^Z%ŅtXysAJz%%DYǓgԡ;Tz>`][]"Yiu::DN^ ̞>5}t"<=$!b9` `q>rM]rQICv{e`J /9s2y+V-#2SpEw-G@Bih߸Ez{}H&٭q֍JQG;`Ѝ4ii7mڥk9G^3|mڏeq 6إr ];s3K%q`=wX-1Pb%b)ݔX1I(_;]|Enՠ^W )dmqK/Ϟ;nv{Rm^IDE+V82H~+~s`i38lq-?@5")Gl'OK%,]J1 Pg\NoSq99 u~+Ι:.Μ`X$o$tZ&R7?Hh:ZOCnL2ENd;>4vpPʼR*Kziݲۛ]:k(>Kֿ\̟B hڤRЏ8Ͼ}4(uT C";uY͚4a߲M{OO&ۿ_^JlXJ(; }bZ W!YFFq w"؉rԨ-[-J\ߕ5y~gԡ7;fS"F%W\TQ*ј%T4n#.l / gM:wy+*VPiSmƍuuX4f̘XEM+ŋK$A-? o<'\ c3E_AxӦjSٓT"ex_|E菞>x`2nŠAfHHC(LuUć~A*cF0a7|#J!H%r6oL3POO]۪q1<5'&4%p( NBEidu3 wKgOe1\RQ_>Ǐœo6'V͛״iS9BB~QnذadSv&(nJ"KJt4 \D@A18NA)޽{3s…) נA&D>?ploݺum۶&%0(]ô6tiZ*,OiPAwJM8D;DɃ;xx8c<'R}(՗K?$Eܙ铫/j WF/]TgTJ8$->H%Pxb>4hpcy2sΝ9sf:!V^MX/DU;4@% hS$_CH!mѧj3!rGڣ^z=!w(MKsΓjQi>UT80k,0(pBb8T3djW֬YHg:fc٠Pt5:թm.C胦O؁\Eŕ$HZ^ޝm YV'I 'QÝ,4xZhfz0 3q"9Rzu^#84`f IDATpkQ(GIaGS,#m(j V0NKOD;w EXdѡ$%2e{7zv-p:ʙ7\xlB۩9C Bܝ;w0Px t\QxQ[x qW^`#n vҥu)(t@'1FT! @GkԨ0~mVA@ 6^ʕT1i8؆qڙ3gj&P3ݴHشDr_'NO]FB6V2֠v%7Iou)YonáOUsŶ?~diR}Gn>n'ia 'W[OV&f{A=ƽso?ɛm7_|4Ǽ˙R{8|{= p蠪$K,gΜZF `>1Bb&,pk>mw~)&$jA'I'1e˖;]NwQ;aa+HtL>~j?PdG)pfJx䓤j$l DƿtLɌX2w[[S$ /y4K "瞸?cTnߕ~񪳏>SXwÅJc7fIOYwQi(8p-ܣpSu֓U,}/7t^YZAp֋pc2c,=GĭFċ&4'u~⣌ybqE!Ӄڎ]~  '<ܠ_yT)Z iR,-P7mdNyIITmOcU]xk'4 ^{EBiݿz9͕{'>:5=?Knnɞl=.EOrO/&#!w:\ˣ&醾ffk'P|X#}z cnE̩O?%u!ZL bFϰD9RssΓl)p:Ȓ=K|xSlI\8|-cO5f+/P8ff$k+J28~Ro +W (1P8FivNMq=//}›gBU5B~KS*y;;Oxk8~ q#.onǣzB!%\NS&Lo=y) o~G8%/Q E~ilDپXqx1{lRjFA]-DlIct3Yyu7S_qvm^->lNwCt!?))'1?归}EID89wUVټe۽P۹fwO_hN:~)2r^^Ox'uc_L&gas/LY2قdz5GJJ>m 9  w?.ysaJ!$JGb/[,EnG课sۋQj10T2c+T[kv`:[$l? GՋv6{;yj.I3m3_}|Ԃ B>/uHN;)<3¬!aۢ~(QrM 1D‡>}H "97nL9rn )7"Y\9y=K԰aǏCtF %wb-u hx`N {ċ/<l u3b^Ƕ/nqj7UNLmW} ۊ4 N49꣪w#?#O;JWRaP5=uVu[UгV̺GkOJ*h-aƂ DdeѪHAifxC!ѡR뜾P!?`36Xۭӷt=y޽zWј4Ds@; SQj< Yb3QhI'Х"!2.9ʸ(8-z*rJ7}c>Ֆ][T[wle~;lom[2p03Sir~ ݿqPa:]R+`uJ7*v@)"5&'N|GTbChm>E>!X 3 *6 UUAg5Jr7u)8_<~q`[5T 4psDjx12e+n+>ww{Ye: }7 Qjƣ{i­ko;?|2e-#{V J" rF9 ID0-N߾}c b I8M a)0W @ dh4JBEjH|s }KT5Z٣R~.]7iL/=;*o9f:_=puN9dƴ\Ӳ]jZdc&L<"Z.`O"5?Aǭlg#R1 kLBȸX`tbLX@#o@83Q)#oSϗ(5(: ^gPQ\(S I3fYtarV)xj0Ϯ<ۯ_3;UwsE2"ȲV* q"Y@C,R)Lb0kQƊ$97nIJ&Æ5kj7$qץ7R/_Nr tYL٥5?8rxbPtqΕ:W\f}eAL°wp;NteGgK1i#OH;w`BU K4 4t 0>Qx#lMPJWJB5\y`8{8%io_~O4l`峦Na+&N9b D\@=QfZ;Wy]KҠI]/߿6ۍOq3JBxv Q[$';ܹ[o#@kI<9OHH\cV":5m:t@A_Ѝ1<==?BOtcL.{O7nTO΀ӧO%ۣd)S zBRff('%:SWNKr)~CtrTāZڞ ]ܸ$:P8̙3E$D?;2БW4C'}ԏ@yJK c)UB5)K,k۶-2HA'N 4￧."T?T2p+R(/E^ r DS2'Rc„ 4N=TBd#qCR].;3' |>eӠ DdP _~4ѣE;v?3zf)EgN$\Ie-N8 Wʗ/탃@sbn"Ys̘1={SeHhG13SћP *<ȅ `Mt֍tm&!|Inщđ4=аaCcBH?@AzVTI&bf&чR8UA$'9!(PtFAFn@v7)30\6OYvNp,X48bfd4+44 g *{KT#9P}`h?:KӦMQf͚%9A&R)$tqu׮]HLl7]gqJ!jzTLI"7;c FauJbdTtT$_hБYذ΃s0\rU2UCnJBIVKrHݻ0# ݤH+Rb._-[699&%UfSwyG=) @ĸ%Z(dDZܛqx ұúxp0b>9s`>' V@0a3򎟷(\H"6Ig~C 4۶m;2 >RE#Iq bFjtһwo$n6m,8+군UJ8%\XlYʖyEGSlXSM9t|r K mޘ9Ł(q O7ıN#%"(Mq JU+8㥚Iq98c9^b %bA5>s`d{t7^jw1^B=zH-~(w l<inge阦NCQ7-rxKxM| R,6==%9_TSnxx﮳`Zz,g6g[݄+έxa,aAR|VJ4u v(pBA z$HPO\/m3.H-ћG_>E{ go!|VVc0E_!y78<2cZmj#?@NJEjEEx=yv~Z9~&"䅗8 ~bry^+\ {, C$ѮXkߍ}U2dY3vȽor?iə⎺秧QhY!A?wמ|c r#ytlqۏ{6xgd՞mX>WJ;Е<06矞/++>+O IDAT %9SIy!ܜLSðgɍ*7A-NrΩ)si|fTQLt\tG58ۛ߄w޹~C]mGosE748,⽋7J"<5㞽B鳶=CzWR/nW^}[gL1Їv%t,ɳp⺾AaYW]XT\pm5k@՞jj-<8>5p+>++/q aÆ Znsb}x&K+/?yǮpM[T4\=,l}mUFfqJaa)Rf絝e2adf(W(G }r3QUXNyDuGW3[R7?4XnP-E)l}ġta/wrV{FD"#\Q-YYPZ&+qTZI9Hry7]RwI8w_ B~K Pd$]z=$KZJ4څ{+K0;o댢tϘx}ygε}D[I(#O58@(C% @I8 `]p]G }tDS@ U0$eȁ!h~W~tԐD#w_n˻ KSj,AcҮ[,{Lb,B6gʜ x;$<{~b{?hȬ X0YI(ԩ3rˆB lϑw^Lӆ^يsG^ZEW_XO?b虜\r-٧N:yR呧8}hX2%Ë0RBz3"qpĴN>A%'V,g6yxi#$1ґ?(kNLCQ ^'nyٹe㎎딫[tvt9)|O 1Y-r<ţ?&^6: psT,> }:ꯔ.]H(@^`NޫQ3z+*^10tt~=eËJ>F ]U6A(p%!R2~x&ٚL~er}n#N{7g1}-=#ʛy|9ˢøR y?mI%2.mFU+_nyAUSF&^/K=Wm `&z-Q|V+F.)JL9Wt<ziȣjc56qS[r϶0%~~1G`'FffCEK@8@)]MƗ)Fwl󫰈g`dֳ&2a").M a6$f{ENN&َ<HuPPxaPꅱ^-8pBcyJB3r H&qw1H)0۳9NoP"7jQJE5\RN&K<ݻloj^7V3 W}ilQ @+==zTݻwSYf۷'owګ6gqb5s\ H"'ZJB1䏲@@ q$Z\=bb "Ss"B Nlgɕk7И⹉[/b Z q-i?{!Wַܮwef&OxHCnmoݽ'?id'4EV X':IGA* %Y.^IX@P+ݻ7ǒ~+Wb"A@%H&k/E"$vE # ĔBX e5 .#%)|8pڥWDZA4B( ej]Nc+PҦI,& 4Aa@_|鮒˨,Y\NXq₃^|244g/ }.g;9ܔu}eUUE#TP@8vqt@u\bD2+f|^[~<>(S؀^,)G⠍'0c5ba } tEJKx_S֙~iW+Xj+Đ+pE͚5 x*U*ኺP-F$ST܉&ysq&H8tmi|5> #Dd΃u^;{CUT'؆ӾGh\הuxFSCINr}… Py)U)Jlݒ)T}jc"uW>Z[= J:M1RLaOlAS?w`VAC?0@84P@B_1jQ+V_G }%2&xsݿ?EfxChvOɺ+VP-ʋ XŁsʫ+:\`97(E.gD_jQ:K}.YCT: |IjJB%گ^ݸ p@I(]D"V*CdgT't `Ν׮]K:uٲe)xAjS%gΜjJ23yD4q P*o@ϳ$F'kA-w7 i7b`EuxҷYfn%L;=PhY!ٹi+TP'ɓ*Tx׋)b 5ŋ/_^\;j+F~%sOܹbEUtHH퐚>5dA Ivk%cCdB[kg6w@1S=Q|? pTQC.ЁyjDyܔXEgO.-yo~ڙk1?ݝDiuNE κҡ$+Té9p ` ǁÇqtFW`iW`9J# +\RK-mp!8J{2{KЯEƽ&w pΏ_XNk,/J1D:# @<)&yXFƌm!d4GB|'x%+-1"CY!fa6*jw[^{hb>RQ[eM8D՞M7F0M'S~7B4,jJBiNʁ7ʕ PV8ИhB*_Z~}ܹ.!"Vp_*Adp"DUS$.gͦ=GwFaTu5Nt9)0iZY%mP :oxr _Ţ]6sau)8$=Ob7kܸqLC^u"لYD|=;$W3=KH&u3ILڧ#mULq]@WLmXj϶߽~p8[u`Abn 2M]TptPߘN8.F=QpR@f]/++Ϛ7@ 8tP͠88WP*8UP99 q凊+ΪycV+,qܹ VVMƚj%^W6$ PD={vp޽K}H͋` ue9<ƭWHC6m6N+%6;*I-ShWjԨaM `ʄ#:m6C}5v3(*fS+Zs@P/ PGZH,b8h'IbTGB‒P LbN4ITOXlݺuK.]B1%j7ݵkW-[M;++r@\[S{VH,P*|>\JBⷦ8X8$Tb}&PqJB%QErd{tlSw|BM1^~(Ŝ ,DS>wyZr}%44"TǏg9r G/QQb2(ۢǩAruvL]PK3lpŹ?YI(ԩq }*RjӦ Cmڴq{j4m|6.f9)g\[)Go~eu3 go.rɔ1M:WT>}zp (pոzMf+ϯ]jn[Y^{sU̫z(X~׵]H9&P.䅗8 OL_5ϫB`kaD, mM~~#֢X5!s@f95j}n.~:̓3uz]OOruNuONoluaVn$M"~{q1lg:p3ϕ2LcsRⳒPZs@"达Yf=h@[ћɩ#e3lߣJlgbEXc<3Mn}ggBA_|vqݾ+6\/獒OލXk r^I^{mM1%@VlإhY)D麋bY'gAR_PqWagx ,0r b_9`rJ>K*sB&nrD[dW_\;Un9 =H"_.(Nzt(-Uy9ʜ9s*U#G0-_ҥK͚5K4`,'>\ ~#(ԝvΝn#Oڍa 40In|i4DF$'tB_Yv˗[hlr3͗ӽ,:+5~>3oܖT^ l4\Eꖷ^Q x)pIv_]uMU),{vqXG_tTҡ$gT8`D_?~<:V^aHؓi CH&iG? zB9I|={=e=,rB280+¼>co!W`&fsxCcj&o-0Rh!p{"왯g\_ZnsޕC #jQSd{:rHСf li_#4T.d:L<#)Tҡ$'Uy9`by7n$K,gΜzqwP-F$S]u뎉qkۏn&OSkm-x, (x6H1=ZԊn:Nw/;[ "no0kC"2 }EX}e}(J͹v|+cIq>1&뚢XA(+/&VcP*S.p?K3XA(ʥ[٬ҡ\rm*$EŁD%Wn:Z;;Mkޮ$$MW?(Tכ_?TP̀JBi+ZlY `ӭ!DMcGLVH&bqf;PHN :((ym-뮭{QX"sG['T< I#fBWu)GEGNJ(2'b+vcQS${ꤩI\"iqI:5t+.lGDCBU^Sm&)9p*Kjpk@38kP\xr5dVYsqrPDouZi?.7kp 74%b̩Fq!A1Duv.9DucM$;oƉIJBY(N ^HHHjaF2Q U$;ɵp~Li8\R }d4JX5LQ6FҽaDŽ Cl3wH1t9 #Ψ̠5t`z:ELi DtA$UE Ҩ<SF-Z4eʔK#Ȋ+^tD:*J1`82ך]p(%ِ=@_]B^F&T=#l# Q(zOϓF8T-HFyUI( p^9r޽{)[nիW/.nC!,$4@@4=E-/$ D7ob҅>Yz-vVሗGh)C@ɝ2w\u'ڞ,s%P"뀞E;WN- Cq}޽{w3fRIJ6xDw`>BFh&r .$4* (* ަ8K[ 1GƔP. (ٚf;QߒQ\DB<"'N'O%$$<@Y+׬a.!U5ki<ճߠa2m%n)))?~rcEDh^xsYWLLLgժU?~̢WPfdӫ;w_fMݖ,ȩg]hom t9}m{.ujjs$Ź\gƂpsf֮DG--mH!x0eFF.N&9ew^^?**DR)/XީB::yV>Rqxyݺu}R-SmQss7o+)\rJH+W 4kT Pn޽{ףG䦣S(yLWWVyb`\ %$$ֶ4Y-V߿_M~xFOF˗5jԠcAP.,$i>G*Tzw5ݻW~/2uz.\X\9G"o[ j̔)uoQFmڴ|<"PD WWWyֹG]v4hѣ1/_ 6J^"d^e>~ҵgG-ԩS~fϞ-yk+T(SSI@qF@Z#p71̔pSC]y3yHE@"j&68*Pݻpk?y]R{ii8;yx4ih݃ۻ}? Ξ/=<;dui`>ܣ[׹oMbϚW?Y1a>EN2qnH,W]YGHZB0ЇO>Un0040xrzHC-MGb+.\ڸa${_x{9tZ5kD70k$!!W5SnN?0ڿ-^bI|(ⷎ931^=pz ՒU<Uhʄ0u=fg6>3Siԏi7QTf#kh㼑)S' x$3jL If}꽀_ɴ_۶m[hQttF4ƍQR%???4tR!R,$Y0z1@iAcSڶ9xִ L TF::عoڨQ i(£GNq޽ [+`/bVLx Ze7יLf36(3K؄P鳓u]a/&6]` V^À1b*1*f3bފ=:eʔxdooOLnjSvmD>|s΢TiTSZYYy̙l .Qxqvm۴2b $mjkE6VF?*7kocڮ}𛟖 do߾ ]fU[ F{A&#鸞Qf\r:eF\cلuf n6_d\b}8.tu] 0>[Q֭[  ar b6=ǭn-D%b,\նomuH<º׈a$ o ٭ >#֬\݂Vو!''[Es@A>,,l! *LL\($F15d FYoI~*Mҡ622B n {l0z%ZZji=^qsRj\da~ jA+0~ &_5d˻x] sْ]FӀik|1{Q:#Ȥ-Ptg;b޷mM7ox7!gF`^ڠAtv~KK]ߺUK M[Xjf^^^X+A詺c1 dfɥt<=v&]?\&1Lsc-X봉k&`Be$.]`Jd ܹsx1zO0a—/_BK  4?@[(K{6!$RWSքmMՔ5A6VX sd/o;yE_?^i"@jTGքܾs{7.zj7gb 6Sg̶бmaشERH^~1eM[aۯ .l~ب~p^ ?xi0lb-E\dK5zgL[zݢy y1ZZ5ěް@]$ص]aӖiiG`yÇ8N ;bh{`wK$U}[+xz[`78yH1eSI!d[HYq~]杜ooDJܺu늴&N0 vƌ^\ْ-ͭ..N͚aIQOZAEutJiemb$h M#0;=cN]t*쫇^ X+qfH'SlS|)1ѢE'8$WM>|p\\~ts๶ #aUCd8⋋mβ=$†{&5)+gW.NC^z`}c3f Y0䃳ex+nc$_1)NѡoǘmGdbb"R_Gq~d0rH69'Hձ#6oL"Z|ߢK!&9ܺqU`Ldܽw <},y`~:4o9 ؽkgG1 g0D"OA&ז8 FԸ}{9Nwnk˞*6S.e-[Of6a; m`nn`6g"+WY׷f͚pMa}f0F$jժ81b h8TƤjBvl|,IIISN&rCQɓ:9S$$].`ܹi ӧ-U\j5`٬HDFtT0[y"gG\-m;wǢM7ĥD!~ jn lb #a,(Rf <+f v){5,&030ۼ!lCe|||W^J{u87'NV_1q ufvvvHHzi~Xh 6F/xb8s^ZvGF.Կ۹SD$N?}dfQFf&^0HֲueΝD^󍌌m3LAWH~Cr_`IldaKkTCv5g2kTebڍ;(Ah[L B7pOJ"u*3߿2)_c+Z*[,Bւ ?O}5ײe>}7GU0Đ >yNX;ݐ1?ADeW]'҆|sdw.AMYvwޡ)k-Xcjτ۩\9f} mcm7eL[lAwGr_W0νt<W:]>҄qc9c$oi?d$v^yB:s}tS_zp3/F2j% mm&uիϞ=äuxNSϟ?cFj-I@2x0Hm<$A+;Đ00" #{wpu%c^ lٺ>\$v|깳s\`qp$p `; > TXS$,@@"_1C`JO Q.Y ֚c;YpDw"6rĚ<&D F%gRn]u̙>51-LLL֦Mp5k kcs AϏ =jGA||<7ExbTmtlقRN97o'\eMׄ @*Bܩ|V =3Nfm6Kbslfb93dҋ>~ 5v 6W 1(  :֑*`^ Md$buŋihuN6gΜV#gyXcW}^ZMeri) H X-v5ew^-)+ToK(:j4[Zj @'+{\r-E"PXHK)kBa}C4@^(xbMxLPy@V_-Z0;$'1&-c¸!pIvn }r K>܂At!L-[67=bS(Rrg޸yWazbJኦ!Swحt߾}?...=!PZ1Q|5oCķHJ!d8[ =e;28cpRli l#L52wO eKp.s@^(x^Y8o߆Aiq\\SϞ_y8㍃\$ @:x%?A"[V=ȥY y }I ܥg_?l;D .OQG fI8 ~|h>:m "(+||7n05\uhbvaI 8MnϞ\ ݏzye ޿ׯW@A!xٱ-q04p'a혾8ˮV{ў4M??ŪmXJ'4^QI$^߾s6¥sjI>jք]uunt%Á6?! #k =Aa+=a1't^_`Ͻ) Ξx7(#^d'\.u~b`6cb5#f7\*RGp GՍauЀd30: F^_%D@v4$w&~H< 6Z5\9`Ď5Ȩ([@Naz,si '!AxDX$xi0?3jժ?xb %b.^hFص/^ClOwfVVsߴu>޽o԰'/! Z@L- "eg$&00@rkaU🇬h!t0( !~5c**mZ!,iwC}LΛ.IHb*nbRf7x*PJ \l~"<C}@ϟ+8jpX/tBWCd Ҳ477Wj@N i| @-1gi"Dd)kHXh$EHKX(| ehMB(P.?9h>v8VM9" +YZ#pʚALDT@7%Q<hjʚ7 -جD<}46@[_Xen ~Γa!}w!"  ,`&g8c?O%}0:@bDiY #5psd8#X;Vpl ȺVbX?f\ czڃ@6lꤤo {tb@r J WPN)/XީBX$mN4" %(kl)k~NDCYDB#)G@ZZ=7@p~5WEP򄀴M==j8̈́_o&w)%KL,"WUEnk֬=|#Pjl4'c?0fwT:t g?WJ1`iIAgcbL7YZ}5-)sܛ]pE#$@qh MMM #PZ;k'|p$(ԃ.I*@e (3a_ +BɿfR#plbyAuD:vqĩx;twtR }p@pa%Rm~!#v x3V~ZS<(::ybrn.\r҃˟  sΰ.lsVEWK4"q|CC__+>/y9 9Vp:=|7/]HhSغVAVM> \ΝxE/JJ̝5qʴS!ܽth^UUDd4RBJŋxq㵎oKhX<Î ziboH-F@|0vݪeD.ywB mV 7FdK ]Pވ>aI/ButJ!wKV 9has:^5)xY9 xVM_y{ѐ;U^%&HׯjҀ69D~ӦMI.SiӰaC۞)ee&#jd(ix;v%k']%&k%'R uȃq~Ϛ5x{aƍ`GZTͻ>>0."aM"&N8sLᘌ ?7-j"rƙ[np+tU$,\ ~ɠCZ}uQQojTZ :e1jIڹӻ ',1I6s? jhAGǏy~9D>1c͚5 N|VK.?FƯRNn.q^/<%,( a"O5' .V`:33IKNwb|q (,Y'Ǫfkm߾=4 ZI8RR'&a(\"̿rJbZpN`$eZ~ל0zkxꁻ$)S(*MˊטX a:}/~a hѡC` 76}bbw8o!H7$O⚓SS5 ˗QjܨJn)Ǘ Z+J.7I Cc{237sT3g,:\}b" \aٳgO6"rKR@N3O95{FµDa?)0YB\,L_n :]J.X UЌbIep5V=Wy'7pHN3A>!aχ#֐2'7ǭj'ל$9ZD TՇoj96;F޷rC]E%mR'iP\JeDdQ^hRRYTZDFxRsE%jqdNOoq*<մUQHΪp]YT.~̸˾,ʩ33NOUG"$DZbB0AfmL،_%ϓKO6 { jժOnDBNիg 5px%/, 8Aș+V1SJ՜qJ`VX@=-QI*ؕW^UQho7b P}ji@WqtD(-jW? (̪z4,-/V#rԐYeՙYfXO:WTQU!SWƷTjQ+I+4K6eTBԀ3F63THOLgA[OO5ə茆 Ҳ̼JȬO)%u%\S}[1lrZ*+9b ta\*I)vA݋Ls ߘM/Rv&=(.SG5SE% >8>TZG)lD&e\_2kV;6o옯* Ƨ+&dPze%AY%{{` k.$ HʔVP%kŗ4cm*~\Hu7h鏟:J7TQ>SU0߆R`bnFfؔS.!:$#99?\ QՃvᣯ誱Y"ѡ2kjViuEmQ)+j*͍/ScZV culgՔeXjR0 Lb[*iXۡR(U/2WCyXbCU4&6%r:x95kwhZlJ֣Ydi]>!}V=U̓Ò&]."8t jٝyxbUx}l0w3*%ԿbZ@xz9؛i=K+?~>|{uϟ?/]4*#CZz5krD"{kfoe!` f^=ᅏbxWX> U:@H]P aKL.1Ίw6m8 QW&①̫̜_ LZ?N^;&%F㤵u/8+چ pQ Y%~vx{DyG`h83k׮ 8HZ}5j [)6o!5u X_~Cp:eԨQ0n6LD&O%7Q)S`!;;;ii53T5'Z0'O;1cF8 Q~i~ Wy2yXeUiRR)8&&[1<EBVa8oS`` la%[F#G80i=OLGn ג)虉i4~><͓&Ȋj5Hh_ ?1欵:1X!T0E@Sk{  6B} -[` xmzdܹHxSi `aL`JZ"ͽ sm,xŠ$(`I51Sb F؜Ìo= x 0S(a*Ck*J)ܳ@`6%cٰ>R*f[|#gϘ͐EkZ 0g9crӧֆ5mHr 5 <*_+.^^8N'^2OV6d )Qc: 1XXD@G,>{0f8b@VWq4iboիB`SF??CGr? 5U:##s$-W_~uq..NWy}A:҄juQB,U#׭S[LAW& N99&b$xs0?X1蹑c80,۫|-Z4y /^-[jUb4L (+;i<X*GBBx iq쫁t)X؀G֬a~06N3"SᣭZm s3σӋ" @ҥǎJc_.@ gEcZ B-Z Lie"=eY+кCG|Վ&Miv" ~6N ge2kT,o%2!ł+q"& r,Hɉ46ӧl6=c C$l `pIk@E/@ %.챠w⛆Cs}ΜD CxL` 1Hzy$}D+!0S@ EKO8x1CR7H>8NIa0ax)85‡H0Ĉsc1i1Ɩ܀/_lٲe0Z*HTjYDW WEʂQWPPЧOLԱ ai/1F@qp%03 An$߿?jcq1)"U.L i\IlkoV &#p %/6x `aa*7Z1S -"?<TEj~7f!@:TEj~7f!@:TEj~7f! Z-: (-;wxNh(C@:=3s7qfDdRd{[[.EodjGEᧇG$F`&L/#@~Ǐ7t@_Y?~$ѣ%r}=zģ!D@ވܼy3_ax Rk$򐑿Z†Q1 "qFxÄ,誧z ~9 Ñ5H%^{J(RG`̘1gqVBWWW|yP㐐L_~-&>!jЧG桮/^5zux/&j0&4" ]kȑ .$*]7p.9 9 P+T"P`(~կ_?cc kϟ?G{5ZغmQ#<*OA6mR?fWoV"P V>" P/V"P V>" %2$_TME.[_o123E]˙VcW^M41B̲eRSSgΜ9u߿ 9ט/^:8w65 =Ltg@_Ӿj|rfݱ`:886EU&%%Up /_xUU[7|ȩL;wvOd>4" g2Lդ89:4zٳgȎx7nXӬ)d3'lkٚn۱{ITpA2i۽^S2kIK*oa`kҽY~Fl12%dq[Bmxff6B9.]n0}ҥapm6v`{=N޼U8< y0f$ SS?O>M),ԌlŸ 5m|+vGM7!~E11@rW c0733_>lӅ%EƜ8u&~C**S:kVW&R򇀗:: sM] bc7++(bؾJA x9뫹fTkc J]CHrM=|H~ݻv.^wn P@I4tFSqZ RweQ_$X??8>8[XH|Fe!i5̵DϿqo߾=)"ߪe 橇N*1 UCOUj TUW7#̃b8ƫ&g#ի_|܂*iT`!+\;X&dŹc7PW9|g 6lqBCq+΍"@T%P {I)كN<%I18^ABϊ=떪{=:,I.T"@6JkU&ByES^R p|I")i~TFR d`\`Rzv:8dm3wsZ? i*@>%U kjg?q9˙uGALRd^_Zգ19 yƛ/Lj>,wٷmoQ" }_}ŋ68FWXѪU+~$` MF Z?2޾!Ԝ[BX! }u``… T!&'=乧azG{i>sBD" !rկ^mpzzpSئMx2eJ4ӦH?=E)i1wb<:wC[ p@rzK(JUƏZ`ll'#&22j܅KͿp8 ۵/vycsnwhβ5xΞSNHeUU w u4z"/w-zV-Yf=/E@f[7,Z*g뿖oƕ臡α+FmyݤIr6h pFB>'舿p^gq%1lߢnɺ{}|AZP#a64865Z-w ZaF1uĢ)#|$Yk!g\I6љkuhUV-4] ™ Gy5TE=󠵥1Bj|}_Z;FT" _P֖";TsLjJP }RrGjuQ |!@Z/Z[@P#*A/LgΜ"H*_-Eȓ%Ξ=ʕ+[nV ,/^~[֓\JNrχ)A{23 > A|7m}HG9E@j4FArlٲ3f)([A_]b֭ZyߒV5e+8iim7~#N$%}k԰>XkBK=yq̨:ټYWSF^=ֹoJHHVʲ |>veݻt4/Rы" =丯&* z5.;0 ĀW}|M7zM{e̚0> =ydz/nd9X458?ul΃ {H\>wlxȁw ?ۺqQ//_\SHO! }5{.biT `%8 GEr* t̆ +LkW5k2xh(R+11q {W @7/ܾs7( cN#[RQQ[[YBDʤXPkג3I3r9. *wڶ 3.`k3L<3J.>ĀCIWcy |4p;0~{`c͘cCLʖJ߹{/k.^|@B3ѧ{,?ylJ絗`Bwc?\ǎԭWk'-NF 0~(klΞho'4[pqv Kc\#~8wb /Vl}#JHhaӦM~<&N@@@ 6ߖ-l WtaL WS4\|spc4o DŽDc(|k}zp#ί^>U~y, ,XFE>+]Qm8hk_-" <4657rp8w䵔s|p>gh__+T" x{w\+ ] bc7[5VCVH[*@(L KiTsg~0jЧBF !=+b!9^0;ФZaE@筞.Ճ|fe߁&|cKR@ zzT'4}*x^j9ДS(\h" /JAFꂠGRdղ:Q ꂠGRdղ:QrB {T{TsBSg/\s%%V Cc(B5_&,9/?(AEa $V@iE@z% ~K#hnp^S\9(C't +AGeF!IjG ʝ \.\;{%wнwCG%>z{ÏUnj Љ5Ðc@<%%aGYD"=:2%'bs ]p}WE@N۴jy^O`'xxμEpqY'G 0C{kD`#4u}۫X1yJR# `/7439ѩ@x =+[ȹi58 s(lA-J u@蠨-?SS٩8|qthoU(8É..N<(I>/E +UOWK~Vs bՀ̮C?.^mρnᨨ2eJáG@` )߿7__|upSD C$IHz&'s.\(͚-X5==(-^mddG蟯\Vl6~C!ѧg/if>IIMeM<wYk־Êsqaƪݢ%;q@G^z,& qX[ }Mָ<\C]a̺r3Db o 8v#rǮ=zQ88{~82}U}C5ÚZ59|c_ ؉S,ؕ/Wv-alv@@OW׸z5 :fkV\uNtmZ[GOl;w333n߽׵s' spqF>Tת%)69nͅr|Xh" }T`Rq^]|]V+qqnQoֻx"P|ˑŷjx|S@!`$I:'t)B+gFT"AS@hRЍ.jS~!Ыb/gnp+aJ-ĻɪEFszUxI))$' aip`pG"orDV-854)eڹu ?|PC/^=}CX;v>]7d7?hhbh8gg?~oG3xBnZ$F|h" ̮=ՖjNʵ C.XY– 1ÿ$6mGyZ M]}Ky,1YBGbK(K[oat G\Yݷw?F`.7}5;rӅXd0b_`G|:UEJՙG$VH Ü\e6m6LvrF2TP 9s .$|E_y{_c<5Ö3#+@`b͉\1k5Vfb\=2J_` x k]Mw-9zR-ah E6[ (͎"P#PwE߻sǶ'C\)3mgz!gO*BC@먳jP]tU$^QK,*ݻ_UU |pzCTR-#P (p z&&?~"% 6Gͦ*YR pم0(N/߿z؞|~̥^ZJC@[[+!!: ;َxۘo#R%&hqܠ*-q;)Ei>g 5XG9PN;ay \U2U*Wz anMbcbCWGዉ K"#aV"| Z]ϨޕWbKҐoŪ.yc˗!:}[koݎt$B OȊJ4HO bKҤ}{Ī;8;t߷ v6v{l'D ]:9a ^o)H>4-E@غaᧇcK.4PEl!KYr.hҊQdղ-:P Յ&͋" Poց"PP.L4i^Y@j,| ! @EO>;QV M*ML{0mНAՀ5E5b(b-˞O-i_-H Yf5UT9[( 1˟)zṪ3ݱaHj/51=Q½g佑ЕNf;ӾÐ(RG3s@C-T"{407ix򚑚_ܶ0hXY³mW*=U7IoJi]&LH4ĭI!CLfTE(|j]Q娄Zofe?VËFLeI@YAYV R^Lޜ]0_CR%/uTe߇ST.+uZ?h*@ |ӹk#9k۔[A㯏E*rb FK!nSrYIe;-vD>ŧAKOJtc,+g2GGaBrЮ*Z b~]x3栓;{ؤy-Xup4uO!g`ŊFBpx@?a4?NSF`UfeԪ^zW\Ji~ 'SE^j5aTQ׽Xol^7m5f>\oO߿z>4\aȑgF czp+b>ϞuY4:ecRs䬯Ojt R+ݻ^o0*nݗwܫKL4@ G9)<xg~k>NПC:jaib3ꬱgF6x'.^I֟0Oמ}m_B8읻9uFӹGi3$%%xd۽wx:r웷o ;w c'DG88w H 1ң/ 0dDvmjRZ?zҿ򅀜iKiiNm(ǞЋ_]ʢ%~U4 և WիB8(8Դ@7oϝzG4 G__=t!{ͭXŽUU%ٳx^))))UH@X$?uh7fps F]+jJc 6݄3M,%}@[{= "rnN>9s}[)aKO>M{ƅK2ǐ=?2EGu=$HXr/|n6kj:b *_-ZJ7.C4/guc}VxE)9u'Laz[9B@.YM۽mc]װ覣vkԙQxvxŖNΎm._9~4ߋ迸D ># ˕GL8Ne\-^OE_av{x<.%ZZ'ۛlٲ޷z#q3]@Aoo@xXaPɗ&J/ LopߴSvm-[ <~S_UYa 4@!@GE5-"P"w6ݩV6 yTSmF|h" kx59dQ.2/0jLH0, S(1rW TRd ?U=?џnh!@GÍ.Te5Í.Te5Í.Te5Í.T}7eV@܃𐍽SKK닗 6!] ع{6 08a\*LhEܜB`9{ܹs[̙3t"C<//FEo` wWKwmuEq "EbD D@Aƒ((F1/P$"XbQ(Elcgٙo;{`/0^i-V_-{(eh&Idꫪ\IX}CP666nnnb,uSbĈ9 G{8YϳTUU[҆6G~/A*bڥ &TFd82__gŊ$GFFrL^f h+8K .N6nX}#j#; 0_ȡ}v`!d7#] ݺ= <_6m-((ႹT f>!?{=|.iй1ʧ!PJ5sT@bP]VVi @N323-R@֭I@81k^^~>|72oL'/C`$rZ^C^=@M3hXAOYe]l3JRgCA`Μ9+++ÿS12bX^PXXRjҴ.n$W99#{< ;* .XiN. oqgϟ#q󼅋}b/!v2S|e$W8 ^[RP^^>BD5=:!;$$^-*.9w_<,P(Z.o멦$F么vʕ}'ʲ`/M2O;| ZaC [#OϞ=tuOsnI :Ba {T<<]vM\5=WTRyZ#ppl33 . o&0q{\bTY|DaA^8awtY7P7D3|""($R]M7iDM46c9 (*zO Ƌ08tOb`%lmTݾ;^¥0?oس-+Jӱn9 A Pnnޕ MbqKM(=^WOĤ2x ^q7nҤIN- ! peMV V:?=&+8+?s*[ \ʽ4`` 4joFc׭ݩ6j YMB:*j=]fjIX Ys:a+=+wD;i EtS?p30#<*kmBl= U5DAfL@ocOy{5~aplv.<[{>7>arSe6^Hh1ێWh] NH8C:*wLzˣԚ<(~PRQ2(bBO5 ۣ\OwB^WCDդbZʷ9EkglhitP0xb@x57iV-3;Τ#p؁lHLapǯW%&\1af HKjjZZP~}1JU )aZW~kݢ^-lC- ) 88{|{ˈʊWtkiuhv;KWWIЧ`<-@ԫmBc$e/r͜.\~'ĂYhbӦ'캒LeKj ZٿYz u-3%a |Xkfx8!A{/wZ}i_-l7C- A .7]rE̪X-}u- HS xHbC$cBwy <`=$h: T!@Zg}5\ڼ{Ĉ@\:4HU@[L ZZ`a5oF *D?|kN|.ߖwf-p{555==ǍŠpr akߛoJM5o,_M ),/:;tWl-.\@$bϫvg/_U%) >e鴬OifUL,ղ&o?{(\dˁ=t  B0Fθmn]IȂW?Z\\9KQ8:˭۰%︱g#O} j ߏ-Z8/:"mH]D$_.оSݵs3Icd'W iI.߾}<+~U _c _NkI,aɏ vq줏WE:mˁCG-\th߮Lԗ,k1u-cb7\$ptEthώR1|c=b8`a4zk%%zXP"R('c'dkZEEmJGx}vGE6PDN_ "=xdvJbcx)9P(8)%:~7gaM ASsR#1Ȏ\B!:p+\/_._K.nC1O^b ]Vr9v /08G@ڷ`Cx,-9JM_6-TH$ fHjE r*@/aqÞ0OtX~si죎K?P((Pj~ jC%w _-=q_ ?*:z Ln1󴷳~8j_ҕ뼚إUIx E?A+3gy^#-xZVS 2i2y[iW7O/^-6A[zu2i2y[iW7O/^-6A[zu2i2y[ix(EoVYg^MP?ش\lӧ ͮJQ8w"gGմצ @*"4n-3Fe };iPktA@F=`gL j(wƾpRrJQUH}\hX@Vˤ FI(=c.8{. YcbϏ7@G`$>m#]UeJvN{~ZKd ظiꘔ9 TVVb %}/]򜪊G-Ds&LD P+ߒH6͘5wϾ{HU4~t[msDFE ]{LY$AeC93hW~BޣA  nCGk!5ޣ^09D*/GqЀIfy&$^-*.&WTYz H}7C p>q܅QC3e3;Tdx爑x I쪊?S6vwޅ>b#-\@4;"Ff5}5m҉򏧩0m({^7&; `wd4y8;ZZtWRT<A'9HkS¼]ez@v1a` 6[9b*>{YYp^Ægd>{20K3C"KS} u^-(0=/m@VV ^rfdUe YW^QNx G,@:(?A~}A;~P="@ՈjDyK0TTRļ˛>`?P$"!3u((0| Da6C."8kTWݼ1sVUUG(˽{MO*([G[_ͿJZjsF%DE1Xsx;ak^}ku3}0W@_v5A_ ,˻U?77Cl͝=VO,9˺5[9;`̌}˶@ :g/`SlAXf 2<'7S1ruApOB~_P# vq??5jlƳm[KD;[S#Pq gȺRd0D]=wF'>5>ihhfڞ z\2W3@bbbjj*Qͻu9aٳg?~:::vvv***:Qɣ '&&$ydђӚi6'mZǵRvVֿUV-JՌ3fvhڨ|cy$|~0*$A$l2+ jP&Oa-[DDD"w d"I`+ث1}9siiu^ ȳ=>Z  flI&І3SbninFޤQhRDpp jJMwx%w`9p\qze ٱxf4UA6оZYh,2[2ԢE?xl&m<cc#Jժdյ2,F[ :[IB-ԫ_Z@,@GvG="wb2f̐]24q^qvjl;1xe]c4( (8 X@NLTíC6Dnwڌ@>NNNN̤$`'tU1+zPnNL|~Ց#GJuV9:y}9;1E1YU}WKh avb޽{M B$L2,U˵vbjkk6Lhĉܾ}LMM- ^Ѧk`vb@WWTTΉxURHS9?7^ⅭIENDB`spyder-3.2.6/doc/images/listeditor.png0000664000175000017500000001461713003520702020525 0ustar carloscarlos00000000000000PNG  IHDR;5# cHRMz&u0`:pQ<bKGDIDATx tU$x#(ر;OH 1,#(1!g %8"A=1( xY@ <&"xz]]U]]$;$շU_~2%nJZTZZZYY ݐ#Y)Z R!*1o޼B@wC&d%I:dBd#-g, LV!CSXFb4 J0 ԟl; j$==P-L:7??2-99yA |Gߞk^+|jYY*N,R*I""CS:ujJhsA\"WGzqL'&M 1hxs<բm/-<^Uʜ+ )}t.K!Z*C%<aHQ"-#큥Q,{"vE;ןҒr*̙BۡZT׷\<ۋN_xW3N+ǖ̡L9Ok +LFcx6;7ZwEgAJ-#' m411Mdkdm#-XӸ`Rc s֕M{1﫲^L9Ok _2j 0Ԍ+ք ,Zzعw-{3<~.961%M܈5<5rqy⬦LJWlY(ֲe*OԌ͒|B_M21s{Fͼ;sJdfff1mjQ]FZ5S#-Kg.hFI( IO婖Cbl[M;co~AfܘŏgĎs^cػFͺ;eƽϼ\48qڳ^˱v/Z}SGD+CwxN@}}bטּ7ҪX9ԜM3DzsZB# "FK}GsޔYw͌?|?oIS\7uGgMT5[{=^ۭ rg>aMkY̹*dۍvKHMmOQu7H:zP-{#T*X_?}LRT,$*OFc=GI"oz+Ho?0o^OF9>xvqmMƚq}'X"lEbbϜ!lws^!n+tsoj|"s|\[M&[e73(ݴVvFa-mm,i jڵDϭ J7~`5n(.%%eTkȐ! SiDX+k.?e %NYS-Gc#ދE6(?/qo7bcClA{#鸱|Ve4ٛ6OrpYK"p@0mGĸ mu?dg\dvg4m˵ދ>]; Kn>T>^lؚPeoj&9H=|,$61XvUlJEZY#-#U}$꾊S-c; 2$stQ4~-{T\kqXIͩ>1qjpŸ*fu<4dfnVjpa_N-6Mlٶux'+]؇]XΌ 5˓3@7gl6gi:(Iu=5⥱FL>3<Ȓ*9Tj 0Ԍ%-3´j\`|=vL)"/z5T  .T($ JOS4:-/;l߶urhhЁ}v_bbyEcc(no˽[9hkW;Q4vSLZY#?{6ѳ)( [g(Q0vwLZL%,43'(7;0-p͓;#l %bc-at2HPd? ƘW!‘$,4>hGPs|և;ʋYa-6Ӯ*xY* p )i@^M_vrGբ7ؠ/fϊ??ikN%ٲ,Q>u<̊ZB# 1JDEEj@ i KE>L9γ}3y˧[&Yҋ+O+@%<aH@P_Oӯ{dբmdYƂ(nYY4s2KqreX@婖Cbl8Ƃ>~@,n TjuF#9oO?lßu;YP!$Z0Կo?τ[V|-C460ۧOflVa҂X=`,0c0  X`,c0c kѢu---ݻGݻw^tׯ?y ]DC@ Ifk`lqAcl+16t$c caV `ƶHɚ6 ?3C -:\wE,bcܘy5]{k^',hkV{@Xɞ+Cc (cǧgVwt_0m乞 jZ{~+:^N~#*[fX~aYtcB1cξ̭jTzr{ഉwV z0Vcq+ўƻOٚI<طByK`l/b0VJXKTUUxUaXmo XRNuu_W0c7~]!_Ce q {ܹs:3 ~7~:co\*:u[ۑ:H\3tyU ca,0X c:f:X ca,E0XXca,0 X cu:v_kFXs\U5vG/ZV4v]6;)%!K2SOjcUN1|){?$4)]5k.:.³ ܍-O ONcEJukCTh]wev-v1L'c:7 aQe,;eŝ'mR֋%rly1hX%Aca,0X$ ca,0X c`,0X ca,E0X ca,v c1b0X ca,0X ca,0X ca,0X ca,1VۧbmG,0Vlbo+֛ƞێ[^WbJaU0vXecu8綣T[>1"X)$iHW\XEcu]G+pX4vLYU0V<1v$San;OP0X ca,E0X ca,0 X ca,0X$ ca,0Xm1c,0Xca,0X ca,0X ca,H0X_cŝ8ҟFێqmcULY*pn;NW 4~jz*Vg綃0VX61ޮ=cfLcX#k0VrfaqXm?[ELc,椄{ź}sǠsIû;0'( mlKKK}}=u{QeݫWfa,fOLu":c XT Ŝ( ZV1a=Ys>|I٦)4|&Z_BS \!:gʖ eYEqytȨca RJ,Wgo׫9sfXY30R/SWzhSDLzr˛67o:%36Q3pnXDOWu06̅O-*\tc&IťnlG˅)VXU*[Uu06zy3QCpuc0pkcWğ3s_3w>L_1DN {QSvd2gwdV7F0rETآncuo,X?6ҮKFHť~8ս3gάslDq͚5˓8ս{a,' KW+ X`,c0cп}ZEyh0*gDIENDB`spyder-3.2.6/doc/images/ipythonkernelconnect.png0000664000175000017500000010613413156675415022631 0ustar carloscarlos00000000000000PNG  IHDR2ԧsBITOtEXtSoftwareShutterc IDATx`G!  . PݡP\  ·Shqw !]ݽ.d1;f޼y&z6^&/D@" bppu0,%D2SoJ<$D BpMEX2H$j% D@"8D6b%ѣg˜1WL&H@}>|S/] f%' G;;)Sܼ}G I HFܒ$nѸ>BְKW>xi%rc./n+rI%a"Ws&Jz嚷$2^"  ~X&w];%Ib5r__s4c@ݣ)̚%8U؛aNN%Kh5i-sQnL>HbŊYwE K8e~矃G޽/ի J9ݒ&ھc8JaȆY>GnJdT)֪l{9vX)szdcQ+L U*dɔ}UC)Sc8pxppVY0g؝{89ҳs7oBܻo Qر{u-n{nܺ3gE;:kZVnIMW=x4Ib ԧΞi"W1bN|߁x D-֫gׯ_?z˗2d\`A``@:M֨\9+(MҖ\bMBIA N8 jUk٤AUʏdu&nzw,07&޾}]`Pv-Rnl߱ (zBU㡣ǩr Z4W=bv捩6~D`M96:oݬB#IyoA: \qy^b mf!- bߪ)rضc'=6VJTo6e|!gX 4U#^\'>VxރjĊϝ{[ub>OH8_^0Xp zv옴~}Ǘ/ŌMME;i#{٭ː-d˚ DHcMI:%{s/>6u*/L3+}s9O4ȳ.Z 2%`eِKBgM<,ZiڡPo4aI 4v?s3#GSE63*q={ 2 `g>;㠉?vԔYЛ­ߴa!#?n\Y }7n5J(4QهD7 K - ˆ6?Q8νsiS;9ɓ;/^~:ރ"-<1Ega6i; ҷo6/^'Db#|ҕ|ΰlT󟃇#kU7 RQ6$M"śb]؍B=? BN}}A;T46-lܺ=͛˔sՁݹw?*~zĦ=e9#k&p۳ pЈ17nTdŴ 9s%Gֳҧs6Ǎ& eB߄ވt] NN?Θ1cܹ^g˷n9>c?l*Л0Q~#rV6%z9~0G|͂=AD}iG ~-+)Hg{;{xu;a`u_)!J#}ZA7s]aQc6URt(zl"_Sr}cF YaC޾so̹5V_ҕk8eBi7T|Ǐ)xafA+7FU'^ӭCutﱵHo[`^Tze&`9J+U%|md܅K3|=~4CAG,gΙUA%sKNgg44 \K9Tץ׺ogϞŋd͚jժ#v I_6mf-\f7 5٩mo[VGX˗,ZdrB%a'O5 طlXZݭ)2l~ L4!ўcUE&Jyx" ۃ0,jz Gk@E*ӯIPJeiQl˔,k?`- \71S?vpm4ӺJ a}i+1F T_l6_V-%ԙFSe*߳ C .^PiwGcS{`iAhϓqiфK ab'aV %4tڳyY{ag]xRwڹm^_X cG"wgϾaL0 @gg!LEԿa(leM۶3G & Ъcpˍ[ RG ǜ4r$AfN a;KmܰAiʟ>muMi޾E> Yz=u;t-ۻc'N ~k-e?/SaS2`{d35DiORBd'c+^ѹtjHg=:w 5m.y$"$yצjp" "xͶwس_;gZ(Ox߳e}51s ,.\ "`@sa8̂]_ֿϘC@Jɋ=|}@lE0^FJ"30 Vz\S60D"Z+x-o[H[#oܼe&z ,<ZnC7ol[5B< [io#`Lu!`}q۴}=F߷tp!} {d>&OL.m —{R%KP خs)Ry?M[ӥq_@f˗/.X`1cTdkYɰ@@!z@o髬ٷ/(1mZhؠr۴#nۨaC8vs/^7EK}|Q g͙"lk_%$O,cwMQ%K&bbĈ)'~xI'Y|dkT@!*-B-,xЀ/_%AGݻv"w.u1y :| (j=m#G+VhҨ[QOC+=]fڵj(eд&lcČ1{owwhҸAU &맟 _nm}*_|g /kҨ>w0 רsTb:NOPb7z3"R/l \`uO;=}ZJ/^< 5w%&?:wl7w1y +_^vm[#зgLK&]4?IkZo$N>dƬ9v>kbF@vYsΞ=wʵeլ^ z}CK.n\1Gv)S$SQc{a WF>>&w\x6&kESgx6 ͛=., i2}=Dk:5ccG g`6nX>RiJ"rK|9i4WQk/^,\t 6Q۷룆ԬQlR ; ӡO9Cd#)S@2ʼn'e;wVV%~UDXQtC"T-aJE$I8Cq.[1Nu. ˢ /\0ݻ&w?=}zjV~a}l M:%L7:iʕRH]{ލҥJ!ga 0|X1%sӯEl]_4)az==nڸ!]N-tS)1 0Ou$;{;#sGT/^ѭ 0 a.&;q0 ((ՙѦ-[Q-YG=dΫZC QcNj8 )˖|yLߟtt)aO &uj5 aW!)NCDŽ'S0հFDsEt0!H}` k"}֭`"4 RCIozMҘ=V`% dQ-v4Eucϟ 7wΜDrE;>d-/Xn2]&FXRH-2,ޏ}Byޓh>_DlOӦV(y&jdq҄ln(9j4F%aV,_ o9ot*SFu0! ̥ #ыG̪T_z<%H !l =vD:aM!~i 1yDӧu wcN4k(0(pQLns9\2v0^UTH!V?&LP-җDR炉ʣ I#l"ްe߮cxDD+S ) 70ƍq o۶]0r4@!{`"+W,B{&;, u~CAAFhԷ 8_~A":iO)V9{Mvd5-^рƅcG6FHr=(VLr^4sܞ>{_b 8992SJĩSKhY7 H+~  IDAT&4ž+¨$Sz !du͕b%G @o'moEn֪M՚uo$sx7nߩk%9E}u^W{Wb2*U,c~ٻ0$2h}vF5mfSMcsxw!>Y[Ϛ]Q3,ĠǾPux3z2^hEIiФEæ-Ϝ;GȌ5WHOh!F/CtlT]sH&iבMj']f!@1mظ]ǮE b'FJݚx%lS\l&ؔJɋ \:4ɱݓݹmZUwa:v9k.ۧpF̵}^^Lm:5?ζ6QUU=D!Sw~kZ|2Ts@4 XJ0~.i*hX۷Xi"7^%`d5MH8-gXZxId,LՐK"!!i>>Ͷ/Q"t6)H" HBm{YsD! EgZf$D]m/k.|6)jjVk16xJ&CI@]L1ɴ !xWJ腧5'i2ppքS+𹁏̕Al KT%pd(22Ed͛6xXz-IMVUJ:M_qES+VW'?**WG|@WnlO LVA KJpSڕK7n4,P ||, ^W @l}1S8xDm<ޝoV 3w9 U\^aO~kiШiO1Kai?a$sSV1d־WLt5lcs~K+U(ߺeswg\yKxѵsni?6x _vC eS'C*_k$/M۶`(ת77o+Ra~'ä+^.TWw88g9i6G_pjRΚ&N^Β9ۄ%<|wi<9%W獂I7nZzM0{p#|Qn逬wRNzWDҦ㺳"p,ɫULWfA˖׎qj |ep񒩓&>wجXO߀i#ķݰ3͘5cŎժyx5_l/Ҍ>"_7`йsqУ[g\ti:|vҝ cG<_>{߶[Q)%Pl~};v$I(zb V9UǤX8+0Av[ur+?cg,EMWretx;u Xp9nD[DŧaՑD|}}yD7ک} pOHE7fNk!e 2 .{ؑ&j _8߸V+ 9]™B0B ]-مtУ?yb*";_2~|pp,\Pr 1"Ԃ߼ukH7nY"g.[ZR 3gkh ]:ݷdURWuzZoD}Ozpt0>Lϙ5 繀@Mnqgq6myq'-ׁX gFRlִG!?a $dk"UŞ=}Ƥ bv"^ܠ :@3wEx_X ;|ߺJO¨Gu6jzuDM3v7ml4P=)mtҥ;+2KpW4"ZM šMZLXa5"E߅G 9S&|Vʝe9gJOG`@$ֻFϗ(3.]ZE&!pss# aҥJVLs\ wJ_![ELAE4έqηnZ8Rba`er[ZT$iҤw~¸9WWMFrЦY #i``FDB~˗-Iz?ӆ)py$hq䬦 -C zJBsB*\imd34LWhKФRz-N8-R跆Щ))ԩSoyt W/te0rbBp&֬??Ä@t᜙Sq쉾́1r"CΔ0 w6$̜9SlY|֜Hw!CV_5@z٬9ՆnܼjP0 T?qckP6fzhlp ۽y/ţ:dʯ 6Cnmi%*0`ιbeD&PXQPI7n\$ 5_dU/~<@fMZ~ݟ'LuP1>uϴo',t4oi89ƘĢc8a mf͛6;^T8V:ouUhCZFhYp'GGaR[9݅K"Ju8Ibr݁QțlZw9ΒL8Hd8$iIЋXk`Qn-7 Aw.@0lA ?P (VEAcλ3.qlw%$7b^pL9*U?&Zv7/ ?_(<;SĿbcn<5y4 uv\QE"'kPaNP"nnI#xX?tC݅ b3yм:nݺCu+ 8t{Cy1`tU i.!7o)]~S( S*@c~M6B㱂l˛Ǔ?uaWb`ڴ!yFszxЗRN:AeF+RڲwZ 8lqƊhA(bH}QZnQ<89U] %ܶuˉSN4%=1wg6=ݯO/ScC`ma%%Y-]dCh6s"<$ :ѿuXFmŎ~ {q&2:pͰ3Ҵ_2س ǦqLu۷t ?tP`de0Έ!P >qTN <BkԘqlԠ䛢<|K:,8֛HlgÇ `9sْfEAT7Zi'_Dܡ?] p΄xx.\IH,ؾ8ᣇj=Cir0_I-|Nׯ[=UVL`bk3Fƹw>HSƭ[M[e.^T>#qkBiܼ3mA)w0Mԏ#Jyx\i\3fhX1cJSHHŹwbAQ%V K{bʼnlubtlP;6S- E:%<Ѵ7w%Rq >]:ŕB`SKzbG ȜS!@Ԍ͛)ow}*ΒO"5,Bs|kEHke Vr%ک3 0bX4B2Ys6rp#M֚WK͟_FeًY7EX?~LeO1~|Z[!џ21c\gS#(_6|Q$DE^d%HQk+b^" ،6C&H$[Q;x؈(j5F1455.m-9?5R(ܭr BVo9mZvMEN 8}p -%"r ^+-sƽVy}x_]YhFԟㆭRZM Y@|#k?emRLҥJ5t5m\N- {aCΚ3_o|/kmkD޶?1CCHqqKZI*uq'\AѪ`waJ*nIޥkW.SH\(9_H-]J[ k 3wnG_% >Ee$2oqWZœ-[vJ3Six=G;;JN7^\CJs( Bp0Q!`iAqn%73b={tz 9"2_q_X*'<Y2l±=>s╛OB|Ah\n'M֢;I4ߎzDK3g?y3ܾ][>/VSL9´nqKSѩcl(""5ki'0u 6'tڛ:R|hEPcF˥R,XԌtvﯤEs_@Ipo%7kE-.Μ;\):͑X;b&3lgb`2tM[oO>k1|5<'Qz[]A+p_e,"g HO9jO `4x8愱xS+X 0jT/%UKkP2J_ڵʼngBO=r|E ։̯~5e'N0v$r֜m{@CB[qs \Dĩӹs )Q([|~صI|+#s8_hTc}3!̅D0D>Is߿:O8kNH' azuzvzmV;7¡6 uЎs&]| GDm<.(0>%Q1C NpJO%+ZE2>e>˞-Kլp„?_u:tb)Olq}ixF֥cp4f4Sƌ{vcK|܃QKy(Qoio:譸(V 8uTpB7E`daJWХJ@G@U9.URV[Os7ŷ}x!mF`-vnPpRsC55^N-ao@,hG<+as5`{iFÇ ̜m{TF%\BAEUT;͛22yݺДj#a d2es>Y-B d.zRI9eI 4wql3gD^_KTHM  eݮN'ZlUXN,m۴Zzq<>0jԩC!` GGGbP Ξz3b\؇Ih{]P!+L,{Ϝi.Q2CJ XvMă"W''daJWxxc=gϾlٲdz䢿{>EK A>xS4z&œ-޺e3_85V2J. ?ZcU)RbkpNڳ85F'6mɸd]Fxa4#fJZ%`e9s`SR)ҥJ mإ~HN)ptQ#klAɈ?2n&mfM48ގ<~U?aFFX'+Hv^zѶ;8(PnAC3%Jp^d݀xm 9WM/-h.,`tDTmO>;T,iԤ*׮_kpM>-ΛL<ժ7w4 K-d5kɆvp$ IX3.;3e>΁h1l|D۠FrLaXw޳c0&-/fɜIYk<4,zy9I_fq}d-&!#H IDATt߷kޤqd4MW۵G*a=ŻWZ1Ň3_i`m,,|qዃ. D5j-.+|,%Ovx!?$+H>kE-d꥛pEs:t>H$_kE-EK7hPW8ǖ͛N9[Y%@En\ UR8\rUO>OqhvmvM8Lqp_4op 8y0sXF8ƍ_wիUU|&`}^|ѫGQl5j:~ԩLz%H"3۵i3fm *?u#Z8yjxeX" `@\nO?n1d!kH" |>VԾ[lH}nC2tTw8V)_ŭp <LH9vrrRɀD@" $,jY1RpDO__x>U1&-8,10ϝc`㘎ǐD@" ,jq=<*,569ƃ>9Hi"?cwÓ+]+!%@$D V2Iџ!/D@" H5 x~d~$9_ /\Cd"H"khEt$D@"!`j.k$H>>[dFDC@oMe$HId$o)j65H"RF&H=TH" tHWHVW>dő|\\\ww`իO>6"]]9;On}u{ce%rgi!U)%DA͛7!zyyi⿽ǏG󍾾RcQ1ŋ(2D #{^}1L}c1wﱾRRZUn`LG,%*YzTfbc%)%@8Zm8$CVkX}sRԚCFK$D *H[vmB4 6mO>Ӹy: s: oOo'ϐ nϟw^ ۦ- -9zGjE_aah߯ y#'O|۸E#eӫ,_ŎXylj>׼ppȜ9Ӏ39 ?~dti9լ^5e6SMs/lݲy:qs!vo~0<˗>L ׮yDl3D* xpgzEV^2R;i M}۸Ǐۨ˿pдekѣŋ/G];&ssWAݵ{+WlѼylr-Y@;ǜϚ9=| {B ZlV|w=k#J "5L6 $qbN2e̘1>C>O1bĠF'ϖ 3b.JcNN79||>[* V3fخmreE(}_r-^|7W_i'N"N5U~j-,'sxdճPX-:\6%k)g3M}|8뷜=\ iRoٶ=((U+Ղ晿(KR%;:;+5Ϟ=cM9_iӨK>iLs|wE^z}w d;'caK ȇE LGɻ lYxk7w܍+fx؇#ikbaqXR Bu6ձ'֯ ,EI$yeX⃉&['O{yƢ*In޺dbnnIoݾCSH2GNJ <ԣ>: {֫S[ #{Ei8=#(bvpN\ғL'ܹ ,=o7nXj,S†+c+XT~IarqC8QzKعk/S)ȡquuH0)w$<Qf՗G!4jP_/g_z;w: }ӂSg4bDѣg.R6MN׎]9gkҨA .Vkw0S^|e͊%ukոwCGsu+Srx濷o1cf>yW\σO9goZ?矒% }ڧ/˖޺qm% n%| 3fL s:"%!E-&d-q$P$\<$ZYܽGxΝիUv,Q#D¶ef(`+5wQoR%sq]#(Ec@V(_6] /! \dӉGl3CK e/>aLd&UJTc~:$kSӽT\ <~x<~38qbcr[ЧH\щ|y_Dt\œ-ς?LzR!R]&e)*\`.m]0F_>3dH,-;_T[45(Joٳe%93P)& '_QHp r߅ٻ_2Wy=&WMOnO La}>Z _̝ Q 񁃇:By]M:/{,hSk)VM*tx6):I+D."ziE_ c9`eYJY!XE`nhٳ"/ZW)5.4Ԁ@<8-H2+bqǎ[$ePHn֑ۡ[.AbPCښ>ư< |Wz33O/v!" ög%Th/^TchȾ[. 5 ;$U.]8VL1c<Ÿ0f+O\cO|FaڌAA˜AS'O`Nkhբ#DmMDYOƋoRD"ܴ&9{Plw"e2+AgѣEW)a}z ̴=*?F'˒)#2T@~فرc'=?^޾M4IzWR$O8QU'Xk@@b4u;wos?)Ur݆X 8/\@,!r m7Z4/e^Xg5/oo.箰2 +@v?rA=vƒL" E"ja㗅 cի "%T,3_ EB7nOF$@8c 3v=XdFc/psLIuwErAjB*$+ܔ<ʣP* rȾ{>*nݹaL}J[25#DȈ}GYIK0J$/^Y -HO= v)Ϟ&ۉɚ% yd˶vB S _UkaU L?p2 "opww'XO!ǟM`V ӺkƊsђ#njNJ~lYK*Ac:J^/Ν۔=Ĩ H@GW̻0qMZ@С]ɓ5iT3bnG;L,\׷wO//BZɓժVrKBZG(֬r`Y9y U *b{?r(I qƌyHb%Xl%-1cFw@yV yBP E*S$l9eװF(4w(Me*"Pdq -b0zѪ4Ć4M !E?`F[CΑ?RHg,bƈ!a V◀[?=|X 0| {{bC86oW.lxBPvM¯C^O4Lן֬YtB"#~2ej*AX&ۻe"߶w=jjVkH$j5P#KQDH$GVYKOοKQk/Q`k Ogi$f~3l4GKQ[D?1GN")0  #.CHY-oPM*k=#k߫c'NDqdy8/VS]Y_]շ/{Y']Y!w(I"Y0,+??_çF$,r=̫5J$D@" ?Ҁ~dJD@"`%RZ $H$G@c'SJ$+J$D@" ?RԆ;R" XV%$@6ɔDJ(I&HNH$V"`K/4V 88sdD@" X+js'O~FH$ e%|W5 1v6mTFMi+W%GOq%gD&jmb&nҢ8]\]ᱣ\\g >` >gR%K|dFׂ@Ef^/X6WGZCla-5g pD+B E-8į 0ܹ.. {tÃG,('O;pЫׯd4b"Hk w*U,7VXJ/\\|g /kҨ~ufy 'UZazPk^~9P~ƬAiSO1b``شe˗/ڹYﱏ6 4{cOqfT=ydJԁܼykȠ8ecǝ:!<ժې;>m4PV߷ڸy/rxdճj/ YȰD@"pQk;w0vT̙7n2e̙&+y% oPY+i ׼Y1btZٳxSb٢yG鎝fޥ{ 5ɸ4a 6;M6c҄wϮ={˖.EvO8>^L|HI%/^ѭKxbƌcժJ(vASx1seʐX"cFfɒY؝wSz5q4͛s7U ,U*Ux2j'O^f!ҽ]G>]4ϜM5HFDL<)XYn H" _Luq}w:$,Z2k<6 h ;.K(fN-iXbH'.Yb_ΗǤrŏOЩ:a{;7o&UgȧO cut)]M3k<$f8qz맟? PMZJ9MHT2,|YnIΙÃUs -kVG=LhhcG C1k>atU֮jT/[,Li#S{U=zy4&NhBM5_/]>s.::::bH8^]ZE?e!J%/%yv!RJ_RY}U$r&\ kS-.-$,S =yExXFQ?VPW輗._ssuqޥ} i2fϝcE]'1 wBCn2R" Vk2~ƌ BZ5jP/IGZ 4u2l${iҤY6D?jCR%=zC.ozyvJ۰~6:fʔqaT{ -=zB{]Ä[L=w=nYy`Zy28m4# Rp'T3aD Bcǎ(5zKk}Xٔo_x2D3#`Ȓ1wLr򠠠sg:;;{zyyo|gϜ$"֭^+j^O^ka'N\BEWW?~Ր7ɒ%]6*0ӧOK4iZW\>} .zXZq|r˖mΜeti/\yLL(Q5yǏ@,XH0@!p"vv)KqK<{޽MhX2g'NtW 윜Drm߭[RJNNMMr.m:DHeqxM"]J> فÕ+W2emSކ%kV2sNtH=ztܧ:Rv1cH6+ ޿w/?ܹ$D_8w<~&F3g3&ȓ'>3^xBܹ* &{ o".s̠D*__ׯ I {Rݽsg͖ (_,(y7JW?efqK_<P ]t IDATP3fH^Ȍ'M6կ_Μ9f6mz{_С# oA ňc*]tX<==k֬Yfb/_nҤ ןM4eK/^=ΝkٲK,FK^嘐[7o͗رc#.^0ѣ3:>d&39! p"-WնP|l>W[:(Zj e a 2@FD|slg $9~쬽}bN~׮]t<vɤ]\Fzzz]*5KGoٳgiF)[jie~Ύ8]OƳ]%J ps( Q"Y}fZSr7hHmZ[I6RPf hkoP">2& FU*gJ*ZW l-ڥomiW10R^BýJ[M\f[g6=!U3rY2aÕŽjsfM''xMvΙKjHΘ1#%%8i;:.>i!ܜ,Z1cLcU4S5orH&ԴT"jϞ$5{%U3Bg18^SSS/~w"r\¡Iq5YM'\%8$Y)NrٌqM _AK Lx@H6 3zRp(hpH!/2m$- (NԏFB{yPCYXQb ϟwIt]]qLja:ۃZ8WVR?:{ƤLYyZ>AB+k:QRo16%ꐘ ֢y&$N o:S05: ZCXeCnj͉)HKq Uע2*B=<B$ǣ3i LAx:mtO`$#CݶyA )i#q. ab@>76ilۗI$(lNmbID~yVɃFz. g^mnXhP]!l]UU7 ㏇GDhl0ĘyJlD.&FD0מG^hCbfT$E@v^`6oH`8\Hi  ;jyywIiA@F$H*#w #l]VaS,<o{3jmH$A@=@=jA .AjAM `Bv%‚ 8P#IA@BI?7S_gje/W/~㛙|'$8yy]Ӌk4g| u\[A@0G4_gO0e[xK8ﭨp3zg7R{@9z!%%ƈ9v,k9H7v7H `;QcS3B<+AAѫu*)&6 <^ `\AOpeT† 򬆊Y7e9v6:͟vaaa,&䔔ǏW>͊mN ­b16D `؞Ve}|RSS?s˿[:Ύ;ylۦ榛n ~gyV>7~dSff… ́޲esHH({3f̤`^^ޔ)S5mB3b4{xxrI ǵL>LRUTפs7ʇ i aa))㚛;=f? `H---TD@͞=đl$TӠMMptJJ**5%[7ѣGbP *,CZBby\qM CA"a_ GѻnSx=(6ûLgg?pdd$2'O Ə'&ƍ=tс]]9sM ?\;qIqdny>ۊ A*'̴4ta;wB+-BXw-Yt޽׿xb"NgJR2pVڌN5)D;&&v˖-tqq E*II#+u]\!k8,2Su )>H&b.-%vl(NW@ռSy=fC}=8Sq4uiJ-{l)(2Ή@oWfu=螮nn@H]͛7765AD/ ߌs{_K/ z '?J C3*b(0x'1rNscV0|Syi 6.)Ï&z@-p8e$ [KÆ @|abhfg2G,3bEm%%SŴeA~~wttNJTTTT^^4Сa1J־AKL<Ҩ:}1c==2c͟:뀵kիp]:xq-PMvv6 BKh{ż4ϫz_|sKA!j'ٮO$ :tir1'f敚BAA>+JB|GƒDe$?q.Jxc1<[V& IIxgC]\]yKPgt!7(5XڬK#m9{y UVm'3qFA JO(ATtq>4sLtm)*..GgN+VغU?(hٲeYkWڵk_'`eW{l޾m r'~XcF(iBb?4ͫeՀ M>n6[Z۴}~>3q)"+6P]b8A :"I`6kH[G *rF-8|qnS tT >c7@$mAH-"#@j{y \e nUa3Tzp! A`x#`Ѯ.SͤT蟗3)G) weQ++x@o~v;/ˏEe/daAs?*)"8,?Ͳp^( ᑉ? 8)H  {XX4 0rL Pлfb  9j%A`! T;X,Cg|T_be!w`@||8^lc8ڎH "PUy#>VuFvN{HAL߁l㌱Z~ XC.&qF  OV^BR Áj_|'ڽ{UπݻvV5eEEƃx41H3;@XjJ'&-XPCr̷5=܃CXf4j__~A4~ժ;jkk7nGVs"SRZ[[O?^yt,; .4AdG8尪r۶m‰'2ۼӳgrvʔ]wݩSoF…7644,^ >`o_AO>?~܌3ȇ"?oٲe3Xȑ]vfw+(h( nim!ŶVe._PY~xCȂu{G;^plLl ._;d'N +=y{bT̽ Gy#7N?vX !axqqС "I0GekkRTsh|EEN91)iԨQHrOa kTiuf6sdIiӔd^^6VqKJKcHˊxEE@ l /T[_{lX &u9::;<<^Fd!cɽVFeNq`*yJHHnA'[Jj*mRR >TW9 }W+{Al_7ҋ~ 3%%q V10_sCBqg+q[^ r#O˲2AJ?^6QZZ{1ΝHG±©a Μ͖/3zLJ,@'aLkAg!M8aLip.p@ M>+~TUA| R1lښZ! Tᑰ08&Յ)ԩPA!eYEJZ1LBBBɁ!Ve"66tcVWsɊV{ULsxAjkk87W %Q[T4PNvAcq!<炶0xGBBCJ>A>vUL+.--ōUԩSן~tR%Kݻw/^Lo (//s,Hsfh`vIЪ 8u*`B1LVUz0_Q^itf:yA~k|| هdzZt8YXB[?ִyx*F'NQ&}i$N] q 5ASO+1H-9[,bD?:;:RE=v(wEMM1z/xss|0!0<&.-UsxQ˵VIF5F %Z?s%ZX8FM$^"`WkRkvTU 0'ON?NArqcr'Ok+++S-NVI `z p95WbiQiF)O 9/"SmC4ps ϝS$al$,_٩5 ߸"{B vj(@U&3 %&NdL?ڍҴ(55Å&VP)MVs22l!!PO[TJXP^R6*JZpN':A*綌4 JnE4.뒔 kzE+*]Rl" =v8 ?O$88S@Rv+Aq(W]tQ}O+>.. ;2YYYZgzP<&#i GUy*0SQϬ͍B@8.l1D{qr6(>Hع!Ǥ1DZNaLD7`|hb0. m2b IDAT[dmatO<ɡRHY" 1-&ac^S3׉~sx trh`12!KB$g >d ԪAc=J w1coϞ=D ,KF GJD."}4::ά-i͐Nhh߮sJR^A:ӦMSbcޤa":?76(wAVU94 ʪG{,R? 4iy+*:0BXX8eLZUTToA &2ڡX{ Z(F!c=Cf!$&%'bO'J"44zJYC^eId:2WIGs uKAB<Iy&9Wgb;y!D`E! !4|*9FW}۶-r2)h?ٚ9kDi|єх3N֘czV.Iz@p8)2_&m³L-E Я*Я/8❯/֊UD@*?& f +]6?iͫhT";v|c{]Bc% nZ@W. Aˋf]MgY_LZ۱IAel"bP1zL~uu} z@uε#{_)An TkwTXWTVV3` RS wjjΜ9kUcbkMMM޼zsd'u@hs􏯿yp6 GEE'Oh Rs @ӧi+|ߏU5S*~Μ=?Kzʆz>UQqmWO|@^㭹J۷+/%=oO47c kIO?<}ںӕOW!㏥8UV_;3O'&ٛkb5Yfu^*Q#/ B@,Aa z Ȏm\E`` jT?LL?Aα⽹Ӧ5uʪ3z3O7v, E-V1~8wwfqq...˗-ݽ'S=J/H >\_]}Ç-[^|y{Fj6ᬉom]]LL Z\UUuf@a`gg'ڐ`ckdf޶(|YbGZ?P΋c-%eo{4{dDzdÆZRDO-TrGL?w̘6X[oSuK,DʚiErB>(0bAEHp|Be_ߔ_l\"E}~@^<7߮[}ݫ 77'{ؘR8msZgͭy[ZZ 4owr}-Tf\l,luM}9xvמFaqIyYM] X8#^P$Kp~j V󯿾lkk/~UQQQ?=<ܫ/nm dmSbI߾npAd?-uEtTԭrs]]bZf\m^~Ok=ͯ|***Gy}ёI}" ߫E G=4pqftmK,IuWa`nXFī(lC&:zMzyrcȞ>Iu TkF`˂?(XV",)86u)C@x j-"usOh[ |CX!v՚c"9$vwuWT1+Ic͍=:kGfXsZCFuPܶ2އ&vWu5 NZdƛib?P~mcU򲗍@ `8լ+8Izh ³7GY~c/[XOwh6ׂl\|sVj#ق ܾR4  `Z+H }Pma)A@P`$[C@M XA@ 0-@! TwX&A@ TkA;,E Vd  wI+ZFA@;jK$?ɨrFͧ,IENDB`spyder-3.2.6/doc/images/explorer_menu2.png0000664000175000017500000002021513003520702021300 0ustar carloscarlos00000000000000PNG  IHDR3:Kn cHRMz&u0`:pQ<bKGD IDATx Xgyy2gv뎙&xb29&Q3xd4 $k<</TW *@˩( r6M7g7M7Ծ]GuW@C7.~}oUBZBB 1B!F(wHwtt577Tں Q0jllnVaF׭nQ +Q0QY;R,A;sYڒ6;a`$yВɭ+z{T/A9 FfeUܫ>jU]IJ\^]]H`cȅ0ݬmWw[!Lf"bJ??{,? Y A녔z|uZjyU64²9a:t2BÈr8F\3> ȋR[#S(z+; 9͍`c@̚aβ~DS FW[ &o?oN`tZYÆܦ+?rKP#jSwn;Acu l~}mko^ӈ/\(pQ򲨛{St8Ȼެer%]a4Z}Օjekʖ)Z` TW&oO(L( M a CFvf\ðx B&<aȯjٷ+R|d׹_1|KtKms0bݳca<֞[ BlS n;1E6vtcUWRӬDٸS{jͿӐEi4=jvktѮUS36F XF/8|o:O/o}Ӏє/=t"60b[M0a Z1s oly*:ykS<3~ճl VZIׄoL0gcdF9s6yO]?tںC41`xGC=X2wTΣi7A4w3DS#ku ]#.7fҷgHZ1f-Zk#~ /6F6M뢝sd#k!c2f\u2#escܵK9s48`BP 1B!F(T1رc^vlv޳}{ %h0{Rk̓V[a5,A Faԥ1&0e'FZSOO:US;`֫{w4v=YZ !$60Ҷ6j@ybI DĜǗ,Yz}CǍ7g܇9)))hH'&ۋëf+%S;hḽ &KK[DJ b3 lo|޽= _ߠ FjXX>nntFFZ6K?e#!ҨY`9'F|AI~Ѽ+WH%DC#+qAƐ\Nk5mɹ%.9┆h%(12IŲe r|FGa n]KIIEEsK@@||<-F`IHH P1Bg 1B!F(ĈQ|BO.|tKb/_6t xhPZFFb',bdQˏ=د~_/~A'2k `ˎf,c̱']zϬ?YW'ۏwtzu,oi9s㜿n d8#Zo ׿5LATĜ~t=ve@dW>N K#r E8:+U{{{#bmD87̅r}^|Eh&Lu s=OkСC yꩧe7FV-4il~d.k6 =!,?DK21zg4i`3P-m|b&X&Q.wrF"Y]#ϱQ_`$brJgWf/FBY)v?"/EJc9&\z̅Qr2Pxњ:u*A n$-!8u*!V%Gܩ@m_&i%:oH ha &RzЅbϚ5 z>,X`ɒ%_|WXc Q .E yhyB|rNR7BҲrEIia"Q~~n^WRbbc#ĈHD`ZREeeuuu]!6L^6w  eF(bBP 1 a,p+f=miԅt$dfc܇*x718vNcgw^l+BَHv1w6#x paHYƍZ֎^l"aVfSg^ҔJ;Qwg Aܨ`X3SճTXP(#H'o؂$.f:& (-~RvY~7hKxnԸKKRwlFu,r~*Ϡ@<>Z*VVX9%F8!v@bZPC(BP 1B!FFFFF/Mj ,;q3gEċ}60}րz:/b^l!,#!/C:?jĢ|9&b$n~s`/YǤv^^y:jؔ3˪Zr/3I z/2bx%:e ~ gn z׭30{75P^l)!C}y5;X]6^l6$җ-ްИ.܈b'mvZ_;cdbSlc伾lw'v]kaߩjЋBP 1B!F(T1B)Pب#bB!F(ECGGt>&7VoQ57&%_7u{1ɠXuFB&kPtȓDNyZ5F֬[ I}#%?\<@$by^:tdz?)yLˆLaq<,#\7^ff33g`G8O2k6Ȋl{p!'%e!ne$75^VWS%ƈƆa8kHY691b"Dhȍ=6`h$Dݨqm\+ʙj#;FeRZ vuu{%5bB!F(# 1B!F(W:0 5bB#bBP #[b4 ^g29]A# *|  FF|-@=T9o F>פCLj s%#tJ z /C9# qi/BKHӀrF=a{}H#b#rPk@vm]5rbY95EN d+)rrF(BP 1B!F(bBP 1G.#܏~Euo]lb3hYJXB)fml.dV2_n&q)#N+?s,))f6HyF61=k#'r?-f6kI R$ym,l9qf3$l#"1#rF9Ō r=HnL^KɺN~$ B!6Q#Ķb6Hi%:v:UY7 Q(#bB!F(50}vrreQšX(2FW^l%()) f˻tz}gg',IOOD٨AMI֮4HVa ,A(yXApMF]&As7 _yu:V 3}Lb40bЙS>lFZa&CTl[]1̄[zҢcj31Aa'&zFFMkAF耙컹lU__y.6F"=(D<`(!!f j*jK!`ʬɬCjQ)mmnAUtd}/O`Jb֌IRS)(g̍}G7oY*|Czb+x[{R#W궣myC-ZcCì߼Tlhmm5cbbQbNיOZ.5=bEf=S|S]t )cbrEiY6/P(-))/(VD1***##""ῈG#G`:38p 22X( mk(# K? $q}IENDB`spyder-3.2.6/doc/images/lightmode.png0000664000175000017500000005053013003520702020311 0ustar carloscarlos00000000000000PNG  IHDRFR cHRMz&u0`:pQ<bKGDPIDATx|睯ܽݽx߻w&&{8vIM\blM6S){*@#7^1)~Fsyϴ3yg7hʌauy ~5sB?bUq[#*1U%O@*ϊm :+6HSoVv<}E/!BT*nʿJ "cJ%RS ڕB!#VaŹGtiiuzzڼ)sBH#nÊgŶmߨ- BZN>Gz1*Y oD<+~kuk!e}{\v`));Xɴ9kDEF.RK;.b@)%L%jK$־{wloN}Qi)6mL,O!*S'{J `%"3rTN T2Ϊ)oyke""Sfd:~SyB!$PUW.?vT2m+9ag'}v~Skg2z 򬔑R^i no s Աpe˖Y'B_fFqA~dV"OrQOg9_T̟T={~@=%edZB5l_i솄FTT_},v5v!Mme#u#S}ǾJn~XV"-߻l`A+>.eG|QOI))e*OttGpŽ!Ą))FJHH8qɓ7mڔ"P%ena#> )G=Im>Ot]>Ȍy*6gʗ_yCklaYlUI<նpz5ujefr}^lkQef6 xBN҆";x$;hvvikƻe*\xWϩ6ZT(-ճd@ﲾQ?Kt+h2L[֐D8޾I٢ސ]{Cٷ'>=-PqqΝ;ssrd^.=lY~FjO0!7ȁ)iBv ۧ&kmܴ.䩧63y֟T&Nݹ%Jb#F~ѷ'*˗W"" e6n~g?d6bX)rڤXǤ {=ex6s;vŒWf!yb2,#e>s5W6XBo#SɴJת}bЂQҷghOO嘆O/w2LzMb[qn}eGDGDD%K3.HLL3g\{ͮ Iys̙6mXpAdQMLTJLtCZߢUs qAUi~v7TlԘI2^>US6+-/Yhb.g:cpBHiCQ j+5_mkTg_C%۾u+= HyJ3J8޾ĥGǥE&$$f?o 7ʹsKΎĝ6o>2 n%(JWcMQʀf# /ϊ۔TUx;s1532>.uq'XLc3$1 ?ӫ_4*Ty0d'zNa?kCj{E^1TXtB|N iC8PzT2WOS*q6;۫T@}W Jye߸#R[o{g'ٛ,Io^^l%ܵk&QsgyTKnJo^~A])w6ydTҀCaz-D&`bA~]&oIIYO?*,ڄZ Z7K!,2Y%&,"vT6SE0kYLaO?,͂{z 9M3^ '&d6F(~p ##i#ݗ1cd*J_=UJ&zmQidrK2RRT2Ns훞q$%=7՝#u)r图Xj:<{d5,?)H>)SO8]!9E^)W;jkÉ{2dx݆nI,2Gՠ/l>:驘U᾽Yo3g,/BCv<:Yp˪' kҲ?kC< RIr!˥k!4I8"ñqLn*Q~4YUIJה}sۭ^^Z)^sŹhj5rlB|Obw O(55DrC%UA)3P fgIv.Tz__)&i̬ǃ웕W⒲G:thCW[n]hQvvvAAQ~AY~Ai^#ԥ X÷_a[j6hfgD] OɥJᅗjryN#w˳={~K?5VS٧NJ*Rs(E`WϛyekòJjVZ}[&W1,^B_dd嗅DYCd*ֲOVqb[ovy5|]}RFJJyJ,)z(.(>Z GEbiWԗHM>b__,])")| jY񒬜.!`_#=wCt%UUUNd[tBvdwf˜ݙq 2ҎȘT_3ηطG/o >u>׿Crsr;y?n#z:\W]eo;rdĬ3ĭޭd.U}U"[S%a_BH[ollCۡ}lt~yXߖbۄw]^vǕmoq7,,b%m(;V.=(<jΡs͛6mFh.A:GLYZq\wz/])ˈ {ZєiV6i=݀}?T4Kn^>&qHydzK}rhoBH2i˴Ǐ8)C乳.\t[χEHHDzŏJq>ik'&#@3w55'JM>rJxeeի}CRYYy\wԫW.ֺ"l5ϕ̼3%3׎]z͹s )J 地\]|r}O}8ɮuWy5VvvuyW\% KKkhSW~reٷN#@߲cI]hPn_ފ3奒:c_BHʡ}_fg9zTmuGf|HZ\|TZU+2"&&6772YEho>\mŲȀm 8Li}u3ǎ9Qsz^(m3z}ouMw}V-o:7Fg]T;2?y]̎fߐ0i>|ԩL\OIN+[lkncwu.ӕQrs_1ue.cʦ~Ek2 ]W3qdɨYwwXuwWG+)ʊGs꽢)!.) |ץ5.qs 8㺋S~=;\ ~=f=žy('QJ)iR&*2O*~ӕrm}wUW{N3k6|է]Nү__yѯmĹecuߎ3Vj}l95쉹N3iR{x٣W5G/~ 'FsEcߌrι 왺gΩO}쫿&%5\m傏_-nwt-;2 N|xG~_$Nʕ+Xbu]ӭ̎.^|钘+2~"+;syrMg\+nqeqZ}k]3sMk?}JnZJcIqiQQ؇c_u X*klK/ r:Vy栍v_57s%JCWۮ]knt'״ya4oj3ם'_ΞbˣaBK/!]W"f5qq }4{\3`_Ki?1~rbYZrqWGC:eaCHԶ]wDrKM6/ݸs&7|Go)i/ FņGEDJbwEĄI+:, <}/žb_ }#(}yk<9'ս&*x9#N\55?p-M[\mо&uk;>ÖkmK=7xqXLCFje]`RXMFڕ+ݵMJedxY^) 䪘;N;WYTR,C[|a{2F֤z *|bF:\^C۷bXvz}!sm6M [Wm Q7z?7}MkCds9gU~kޫբ>WI 2%Hc-7[N 7 iH)̫NSżgI_R)2ldcɾ5o=r[t>oM 1I ޾- {mZy5߶fkeV44gOLw4-%wT[e(ò%7OrDR𕷓s\H^# ݰg٨ԢԣjԿd\QrB;aZ3L^`摆첛eY__R6ÊP<{2'9trPk=r <`woCc;pTy!Ѧ4ɛ磷l#vmllm_k |@cUړڳjdWӪ UEА:K†]A[NPo ԟth_?۾ 3&W5ϒv|%7z75f?gw0H>djdzQ՞V>0lci_v s-<j6;w1D;.~ =}`23棢 y{4Le G'l}&z@~)^Nn Wfv~1_G{c;<Hy:'eV,UoEQYΏ^d&V{:ZB rkpSH,Kjb d[QAֹ}e=DNn38YΏ!6D3hBΏ6M[-[̟,[yL}mompwѷ5=,찥𓾥}-fO5}ZΒvmM6͛X}Pc _ȇ5c9'-hmsa}=k8:C bmv*ux iv_ӑoa־XS8קesk3f5(eF;wpm~Vzg%[R j)hm1=UeE,N;ઑwYMt%Ock+rk]Opؿ!Ӆ[,'ח_PE̳}[Rmh2aosXnw~Ilꍠp^)3ϖGE 9?yϣxW׷FNFv]WkPMp<5,,7K0rrC%UyWbϕئӥM}Ӳ׼~I?X-gvwdO!+D;) 5BӼf {*i~跈ow]Y~겼6j1_y9pi)nJBy6tr [ 7Z _p6/Ԣn(va`1iXhԏeW\.^9|'XvP/-OXeW\YY ?_LQp¼bDFݺ_g1CͷsȲd[ 6OǼ]KjW?tD{g1mSMg;?BiZ4gMW:K˦wϒiWas(\uMrX.ִr=χ-O]ei_2%.,Ϸy-9W*>9D16oCmgvkӜr{No{*w`_}5 1ִѹ}oˣo? YMWdĖ|z9}.|[LOKdSs3VhSiIg}蹯طiڏ$w7YSIq9M>ȧu۟lmp}۰1kE[zDΏ >r,{߾MsXh_UOs]q:(ts,q%-CⲜ%о=;VYnM=UbDgަF}ɼeHZ*uzD>,|Nzlc=`_9}d-3niB<͒'t?gs6/eW\d>-TEuUdMB@8ix 밬ڷ\^\\R>N4gho| |d4JHC\tu@-ؾW ߇q>҃h#eگ>mݺUjjd@ȰTՀªIuI20m&S{Ӱk)Ȅ}WQmy!`j_MOr>Y#R/])5R(ZΦ٧ u_*2w^SUWbzy:ˮ5%ھ. 'stf_?d<˕}56՛O ˣPwRz64a-tn_˙Ӽ솒loh:WZʆ驕 }-g`_+s~X+Z՟n+hp]jr,Ӿ:ncY۷yђHDnPʾڥb}uV;? J%J Se wlټV}-Ӱ6 +V%[—o+Ov;&OmǾx/`F:ͻ՟/žb_t/;꿔ף[}U?e5d _vWu@sط~m۔#iԯ QTSddVo+IGV?H<mOF#1wzhA7@MimJy!M:᥇ס ;dɟ:i4}]˂.ƲWkmھfOV㪧dgߙAwTWJ]Yj[[yj}<m= Dlȡ}_ОRWCU;ӵvм,ZS\s)e&]iN~ }UߺZӰ۾]%uܥlپ#)&}nzU'h6u_TkMɖYv;z4yV!oK̳L}Sn'wA;3d@,>7Pw]Y=pWOˎ,tz7m. 3+O~.Y㪻۩]WdvL#tM6F~jU}F \~|kط-/M`_뿥-b_/۾Õ/žMi_l*fz'q_kB-U~=uh7@˞-m}oKeAH w^, "P=!Zy;5EQ@օe*'D:ٗ{omJS5ycھ}'8=!b_*{t]ލk"u; f. ,{B3طU󬺮 7ok-+*+m^l܈uV|`ߖl_Qoj9)[Sk@'Kؗ_`_ `_ }/ؗ }/žb_ }/}/žb_ }`_}/ž`_}/ž`_ }/`_ `_ }//`_ }/b_ }/`_b_ }/}/žb_ }`_}/žb_ }`_}/ž`_}/ }/`_}/`_ }//`_ }/`_ }/`_V+`_}/ž`_}/ }/`_ `_ }/`_ }/`_ }/`_ }/`_b_ }/`_}/žb_ }B!>/!B %B/!} !} !g_nc#NnNnYx !} !} !`_͐m`;ez*BaEľBH }e3ɧ>ܧ9O>9D\Q׋,\b_B/zmV_'B?oWK =_S{w)5zUon>/ii?1⹪YOW}ʚ];vEuvEvvmε`ϲ'GC˲vHoM ؟|wicA@dg} >}Y~P0G'yy_j v9d5ov{o#^; |(¾oȠ ]Kɂ^\s {v-/{}p=Ћ@47k#W%~ɾM.&%N\ pp3qhi~  /ҞFuw{Y ;Ns+{nyw9X6 k3}M.&%;ya`_{SPIsRǭ5js1j=-ѾN H)}۷A\ƾikڛmGf=N5#_yda;yQ/-~Ѿ/jvKa_Ҩa_} ߭-o~-99xCO{WSy~TzIKv~ưOv?,ޟ|˝ )?oX~V~몥6v!`_{G'>~}>|}kq+?BH+ٟw !oqk+j6 B@a훖G!&G$B!m ɾ3퀨SV4Y}\s0}/ž}/%`h_žؗ}/ž}/ž}/%{<`}Y+[Ӱ/ž}EB򏖻F0žؗ}H+2Ԁ}/%/+']!5`Wѭo˱ 9]6<ۼ߂m[q+>}&i%WLUuviѢx,uH2~p%ҊR6R12kNB/wK۟}ݾz:oyl;t輨cIĎerQbSʀN7X'!Ӿi >9_7|+:7-?j_宫&+Cf繭 _ 4}#c Wv gnqo][WK:>77kkR-[3׭u}/%ط*? V2|˭ދg\k\nwZ[~0{BH'O?MyƗ$ɵ^9,eOKG}/%@}ѻc?nzb͏̻W7M]ҍWK?G?b_K!eyw{щW{n荃Zc>yn?}/!̾±y7w ž>!jN5;5? |իiFb_Kic ML^=52xЂ}/%1Jf\>DN {+F'hwiBڞ}5>7<"YK@5ٗ뾴}iBhb_} !b_} !ؗb_K!b_Kb_Bžb_BžBڵ}I>v8=pjZnyb_Bi&$$eձ cFFѸ#7񱱱b_B }/Աौ"v8Bgdd`FoPj]Woؐc~۶pܸROId=;ܦdw1L۱c+S 5KaaP-\"˒-%3|}{jbgo4xA[}}7s6m;t7xWܜ՟jm_gH1}þڙRiyk_Q:9ľ jݪ24s ڳjr3}uZ.36$KmJz> i=SǤI5.\?'x8۾zתvrپ5W9>mPz gˆ} /l'/'jEu_yVL/gw)huu/hX:s괟%Kؔt> i=]ǔ-Sl]qvWB]|Y4}[}gol" NkB@VCqiHòϒu\CI'!mվ!m ~Yb-X|\1UfVYRo]3oX3ϣVW%iwp/s9 ʁZvh"bY]ƾ~r!֩2 *hH6,e֛y?O޼kٗ]ҿycYN}/m>2k[|-Ցryr90 k])cnxQpȓʵj[-3F'Ln2Z~{7l) \b7ZjeY(wpz"Sfߢ?٬%Հ?eÐԥfh)yhȩ%dv-a-5[-'y-Ʉ64[ْKK{1Ǯ\6}'55Lrb_i,Sݱ)1ok9:/Asϳꌟ:jVm_×IuU:kI[uJ䖛C}j&{̪yRs-Ҳ>wԧ}DǍ9fŲUط7sKKj /aJ48NĜ6jZjľÇ}:oyG -駣}tz^fs@:K'Z=Sh쟕`-߾b_ .XdI_L6tEKǾ,۞}g͍HVM[3uVw !M`aC\|2㏇ȣ Ȱ?]pI}tۘzl: Fž);wdh_^em[wc{d?$V|`Qsyn{;yRَo/!ZwOXQrZ.}Β=3gΒg4Bu>vr=b_BH3wЀ mHpWZbhƤW ȝYyƾ4o¾Mˎe FmƲNBڟ}Cߧw_QsoYh9,&V[/;{>w]5=6w]էyvrkX`@c_b߱`4jo3uN+~}|ap$\sVʳ=z1+qo]sی?Laӱ'6jo3uN+_ݲe⯗,^tU+W^jͪkV\jŚ+|9I}/n]m{}yTIH‚’Ғⲣ%TJ/^ѿ/mܺ~=p9־c4vo36u`_}[;4U6NB/žطvXƦmS6׭ e$b_}!s{ϾmƲNK/žؗ!W}/%`ߦoi -b_Bm iBoS7<"YK@5W Ղ}/}ؾ9ٹz' LhXk[]/@웙@?/^tKr~쥗ľoOxY˜=;>ҫ 0':yF%ǪjJ^=>tV).rtj[⒊ʪGx ƾIN~lش5=P{p/@`;]&J*L*L̏ݻem 1{G {nmov^^{ kn8pʻ}^ouvw}ߣ 0펻o[n}s,xK;;{n[o;c_{︫v݆ɓN8i3k~r 0M;xmۃxn>bԆ ֭[~a#Ft=2R}f?>M[g̘._|ɒ%K.0~};}3|[UzտGs̙5kٳ{O~q_\qǟ ϯt 3ne[lټy<O?þwyC?2b}z!Æ >tFHdtڥ;}þwU{ ٕ{8hqQiIIѣJ"oqq<%/m`_b_`_ }/žžư YNѫwD~u!%q[#`_l[dni$@Aª#S+ W.+;*8k%ۢK$3vgƤ,;PYvDgGdq_._~GWUU?~ɓO>{ .]$Dþ~7m‚i1ӻG*++?~^E.]u7< kߥ;N=/1Ӣ\Qb㯚R[+ք'b_۾;cѣbn>2㑚w_tVy[}PcǎUTTTWWל9uTz/^|NWDqo#+*+۾39ssΚz؆T }IiN.};xDZ뾪o+W8qbZ̴ku /]rL]/]>z7FǾ~7,.boVh۾Bݸ#rЕ[Bo ^)xƝ7ɿkFHܴ=zM}}ۗBi3i%B%B/!B/!} !} !K!`_B!`_B!ٗB! B!B!i"~i&IENDB`spyder-3.2.6/doc/images/variableexplorer-imshow.png0000664000175000017500000016164713003520702023223 0ustar carloscarlos00000000000000PNG  IHDR~*'] cHRMz&u0`:pQ<bKGD0IDATxǿzW@TD4 "h4jDMb_DT5JlEQP.q.o73w{ǫngiSL tV~D"H$֯_. h׮ 8?uV'}ʕuܣ]{L|_|ů ՝?~yE"H$U_6MOnYD"H$U_bs#?H$j. թH$D5XO$DK,~~uz'D"Q$?:w=bD"_D"HT3ů1]O=|KX3f3 ?w%~91~ҚiMG,~"H$\?.`Wmuj--ciс`} 5/rT4\ v3gn5 ߎQz/~&ƗyGuNP-hK}܇ 6 K5n&-}jE94.U; G9&z5=. `Ċy߲h3KsCĜ :u A#i=ڳՖfPz{>}o5omVXe_jۙ[p/Σ~ &8a}*g6{vַ02(Fԥ[ܫ/?PWėkh9!>V^ԇΑKxk3J#^:kzy~6r6_ fa`?@F GA KWb]S:gq+݃aǕbg}bs??P˶i{j~b֕=?OfܷmũϞ*\2 J㵭_ᶶ;r*58w[Oų EXV|u[[2 U +C&( Y067ZruG_i3/- B&VnQWUk~=_YiDOa~4/|tz>.C@~hNo9f~mrz9ҶFeUbY,ߞ5=6u6qK~UH>MHTXĶ5:qS5/ҿ N!g44`bf<Yzq?^vx]7Ŷ1x}{^ϖpTM+~QA+U[ۣիWK/K uVi~&uXߑ_:{ܾYackhs+/KߦH:*4#|WZv pϳrU=6u6}ݿ=t?U>t~\gJ.W}WaWMТ L.~Mh׋bW T%{ d廃rX1u(lX+X:dcZPqI$0,/Va/ڨK׃ўVkkcQvnV.E/rDJ=kz\mlT> #v@BUDg~S]U,=WoML>s\ih-H2û~vů2BwN:C]O>>W{z[@+T3X] :W>:F:tUi*W:Z=U"W,V\\,'?iC?Յ;c_&9``||n]WvWZVA7: uZUm_2>rMqyUE\~lu*u*a|`Bof kk+at䮯*wVǖBmZ{ʋ9Bjj&^H`ژ]akuV|ֱ۬*YeĵQx8'XdN0/+Ws쟲q`N_j sɿ?5[`qa5b5-KO:uY)IC}4˗/ֱ9Fe/F^:^2Q귚Q0bxu8臅CKX֧AHGsّum-H՞5=܃a&jEb}*WVV3f >>v=,|4 yyyHOO_.$#6>c>7l 8Wꐪ_UͮJ몳U,"8&m}b+ŏoW\?~IsA+U:~doҤIx'N$;;_o7 G}uur֖X -V 8"q]MZT>}:FǣzlaatG}#GJÊ ~?3RSSѤI(ܸq߉~uWWH$WZZ,xW_}? &q>7x㑝TT U3 N7o5jVZ7P?:s=WH$_`*pp(c+o ~ tGx=k& f͚}mڴQ>wnڴIOn\XD"Q}?]uUAs\8x xMU[UxTNރ̙3mo''WgG,~">_9̐lقKoG úz?c\#+h9CcfVfA>XO$usݘ;w..B5Ư}+ v; Q|W/̓16^? սH$Ǡ/af-m]UHV>]? չH$%ԥ۵kW8wEn!3&lYvqqq7m4\{~#? չH$7o̳ؽ{n ,NLMDGcvo!hO۩f0?%:'?:w=_|k /;vp+ugi2E[%{,l')>nc<kϟh Ν; j"H$U_/??֭y|j'ݼ쒒d״iSL|)D"/ ?ԱfZŃ˖j 7L˟97?(-[ -Z@xBQD"H$:7fnܰ{%[čxe x@ <}O$'D"Q>2OZl, y8li =׸qciXH$DuD"::4xaOC$sR$';uxM9H$XիWcƌ NT5yEHTų*D~"x`.ϴD[W={D~"6lD[<~#G99]W˖MI'|~2H$ӜN׏Nޢ0!X .@߾WNF o+9oEh8A(܂M'$j|3aD"?Q7}ʯ[gqNĺ5?ײ'HOHOLx|7Op\pGo'qQH)Yۮ+ɧ& //eRv*綾wWmKp/?u1?~~-kϼ^yxUp?aK1/cst:?| ^q=WzfaS0? +%%~~yo[+]7pXx}?dbm&duD3=*hXCca*zfAOOxEL'y?:S _DWOt4iC{NY(A@T?V-˞: XN@ab#XXDU?ћG7/aи*o_>~7gDŽ;ƢE?x:k(^7+]N\o7xq%`SS0wbd_V.ߌGز7ecE/GƦyDR G6L_Kk0ÇyWU|:L+C]._U~VuHO@nn.a٨4F[O-.''w 2E}Y4[i޿it d7)-- 5{냉z+iE>* yȑ_e]&&'~)y"Q=[4i"':*ˁIO-®;މy8/]cm8I&ẃ={%꫶mۆ2?@9):bc_$&GQ 4(,ce_}mڴIADzh`Uw7|#I_43'uDRD"??H$'cO(''D~z~,rrT-F D"?Q]?HOO$ D"??H$'7o~ Wpď4HMF q[L(}A!HKBzm(^zk~>[c~~~z~]tIo~fa }.E3Hm7VEaq:^ 돳V} !r^,q[EڝfZY)ڥ5gg&Hph*_rʰ0_n>بӛ6:֍ꂟ_sWbɶ_0yhFy,gض|o\#8z`׮]j[XXLvѷړՔDv퐒(pa~1lR$^|{*mWx_{\\6lH\.&~"Qv"i=akOiJY?/*?&a=1c~~~U WBhvS>O>^R-?4~`t@)#px<' zQRz{Ȣ>RIJRL[T\ں)niq.}~<1xxHcD|o MbC~jdfU VZŧz*:`y`sHhOp%7 S Y|o7.&}dɞC̹~QP:./->,a܍ ,} իuVu~ 4Ν;}={ХK$'' +,&XNpU"1Ω>K??wl36gq?JOy#,IVApi3#0zX_m?م("KK=R)@[Ĺ7 jC>9բ%lxxE1Y k B\< ]N[LKߞK Z4E\ ;wAx$>,8l?xkecI\NjZωA.ez<ť!EZ>E3M(Y_!TrssѸqcu'g>67AXj\soĉ2eJ6xhF;}vjS;1RչMG Ͳ/1>^6܀ICk߬qaRM@-g$3%m3R^$W_&hK&g!1)WFں=$:*Y];vmД=i9n"}}/J MHKn'ͣ顮)kn$4iI(8\9CpmVvXrK˔#?7{]6^GOANmѦQjo_T"/[DՆ )hVm!5Նqp_Cdl NBn~?~WL xw$` v[©k d=e:^|)1/cMn! K^QQ \tU;y˽ V!?>6&C] lKNS}2H%-}-[D&Mj-5z vFݰztlmZ4urz,_,MOt\>nJCbq t x gjy i6$6J om孴wkpNJ0gt@3aokA>~ f;GqdsJk4!aVˡn~ g{렶[嬍|Kz+tc>7 J_]?~1dIƼ=m܃=pPx'.޿i]>w E4b糑۸)5k 6@ù蜔vſ~7u%9;Ɏ7(3~/Žmں Sϳut)E?RV(҈p5?VYo~9\7\^'gT\òhմR&i8{92"ji'ٓDiۻ2;p| s[{/@ɡ_4rvoǐGyԉnA]1E\ѽ23uywO]rio0; 򓹀zz1w2xa8Sۨ`m6n t ڷo>fwo&G Sk-1 [ Z4MG$4!t)j|Y_ r __s,^e+sμ|f{VHz/z~yyrK$Q ܺ[4@NIQܧRB] ~~S `w?%Xy[6nܨvܸ꫑D?-| {֮U8- =X-~黰l8D[D.G<,.q(ٟC*])'zNs5lmUexQ헱y [5OYZ>` _7.^.hXg67r'nZH.Q}96 uC\q>qѨ)v5f񋯠փ'8z u{Ŀ3mi  #^rWJ@/f ,n=?}0{nDw>z!.h$bYp-" PMK?nEc _aGJI^vmP%+&KęKآ!nyV ;&ԓМf2xp~ڌ\S*>ۺZ"d$RJjcM)ei.q[ NG^jߓ?͖v0fOy/>,v؁F];>ÀO`sZ\fB~?vnæЯ&uTW6WBK*?.>mV]ҽ4 7pپ-loFn|2g4~v՗!ƈg9g)+oK׿WdۢUn vn_=[נ@Kę~d6ޒCf_,ڱZ+OlchZb^;5RWc{0Hm߬רh3lt8ꀟߚnLHrn": ~^~)zmT) ՟kɂÙg_:ɒI[4?Zͱ2 Y%a*_٧K~Y1/ ݛӃ~Og&]kځݱkT(+;f/{9 4ܙp'z\,y+A0ûWp,9L5}+Q_ďܸ=Z=(#?؈on9 r\[6m=;2WT} xKÊy[sY~!]p2={{vA &nPN.=0ʁؽ7-ٽ)o* }B.cBfEjJ-7Cxuzk?31F/cvKO;K܆~uX^?s&ꍅ4v77K ֔0Ż6lWހK7z.Kvy IuhnhL%* hkm?xoDm+ěM";k>L^~}aHr"dlkdxc:/AKuhW)q]+å0wC6Z䇮m3rӬ^6MMm uyMFxgxwb?uzr&,2HOGfѧu[ktD̯wt^r-={J *{Mνo} oEqz~v/Mo>nhb؁[cL/ƜܑWfu*ˆ)Lavp -՗R/Ŵ#i1ȓ;vv4R/ cRUݥrpGuwD;ʨͅ?/3'{yAٞ׋G?O\ " '6}XCۮQ2uxq8<~~6\:ߊ+msr3Ƃߪ#rُS8xiFl~[^Ah^̜xK4\D%k~ٱf0tovNZ>5^Nb\Q? w5MNZQ^S/~~& fNp-rhI;-P\֢BUL].;֦ۗWv}J 1D9bqȹno>ʰff,-oum߾*\%&VV\ݻw#{OI>uo\~0pJ;W_}5 s`uY|r=aøO7pEj{. ,}hLd,yhFBE#KXM8kqn ys=9s樉͚5S w lydN!xojehK v5t@?QgHw#M_ir#~" ~=z"PvڒKi٤qar> 4kRl=X~5i fWFCqjd0W5a+åm+q+&P&f|gSFc.Żc[A":cF^:˹ oԛpv>g48#*P菻b?w$uEmqhJx7_"߁3俣 ZvDkGݍNZK:טoړcp]Opz7yi˽/@A/(8yݍIuX';0ͦ}^ŜȳiN[ѧn%d흷|͂>;N~'^t,>W5xD~~߮P4Z@~E~C󎇱phuIh۬ o-ەf&z,y Yj?V#'s=Aےeȅ4/-x{Y09l^Rf7֐S^T h[_[䪿B]vKT/CFȋX7K@x. ~We[t)ۻwoyj[ F4@FJV} c:A^t?Z>2>`,;~n5'Sěe*:}nݱjhڻ/]|0رŝuX7t Ғ;) ”C~93ki꾛j'|XL׋o ׼Ukk^yL [ضMw) j+rC: #).Tu+`d]>$DL⫨ޫt@Dgz~0FA2G"l~2W&D$=5k3Ǹ:N'-um *suжI$Z;qڊ_`h{~jrIhiu=<}tu]vkXH>{M !|, IЋTm ^y~٧-R?hi~lC;sѹuKժ\~jIs{XsGKХM+Nc SPou:_&6‹s&5;o%= Ed4->^*b.p,>H-q{^rtq1;sO^8LxyaDMOT灯O}Q5o>m +DK~3#^rX[&O[hՑ-? _mR}HOTǀgxZ|G莘aD"??Q߹^6XK ~": ~999j,HTo_#`J8A3chB3&cq~" D"~Ztxm\*)t;GD"Cң_6͚{Ķx釿9E)-tg0iQV|z围>&-?:P?=Cڏn|sOs$s]?DN$''D1P>4|Z-Zoyn-~Noe/ٳ2hmz>P&'''' }{mmZ]ȝn$'UзPZ6w/^u3;(\?&bC~1q2-zL:؊x iСY??6m* %d@44KF,qj经yFw6㋻+ ot/8߅7[-<_i=SryC\g950 ;83m316Qe-ur+ KsҲ,/?x_LŏO 0pP@Z bqj[)df3EY1< D~c |{  |]+|弫:8։g[&ƚ AH$':k0{::Ȫg{Usz/u۪mtŴQʩ?8]uN3ؼlLUc@ڥ ,]"???HOtD ٟey&mDe ʟ\[/&@ /D_ΥBWݽb`kO/-'D~'K}/-rM||' D" U |Zeҷk;D"_t Q|# mZۣ*ŋnw6$HzҥzyD~~"Hߧ |q~M*?ߏ4n1;w.zdD~~"H(Ч-M-͒ripO8Q/޽7n"!11 nw ;_z9]O$''~k kd Ut?Q/mٲّ2lڴz*آ_rrͫ/s,l-?|D"_5o4Ki+6y/_;tY6]T;v<~Q/%%,~ ~=c_!h?3'CqH$ xFTvahoi^Zelcb… 1h o3:uHaKgW^1/SL?dDB i? _ȃ:r]0I s]i,>bm":fE[$'WGe(Qȏ1^b ,;Lc}oCLg3,eJ}KҢ). 1Y;f4}-2rHTKP ~㿬Ulwj[KfYeu@o\]0嗏%)b}zG?v0ɺF ,6:f@C!gѻa_}($89EQR p!l_$!)) N(T.E/BN6 +;1OjRCæ~43^}*kxsi*&'ǎ.tJS|X؝peYnZ&L  V\^‰ɴzqpDz{x7FWou;QO[Owq} ~7 ؁__w ZE?,gA:|m11O1| f't'aÆXny&KJb_ӄMѺz];"+ Gga {i&L:ca^Ex;^8,~IqE W?O0 *CۂG` ]۳gرG-j*tE>^/f.% *]EC r.&w,bO ^__=ylݺU=lxH??h?􀧔/poLkŋ]d iΆzsZ(Mm)xgyc l6}"K|  Gz޽Ͽeʤ?Q?=>]=駟V$}r@+t.`?WxJa t&鉖D6_ƅbTˈ@W y`=Z  L32}#<^.Ϯ*0@GJ3b{ K c ?<9τи>a^7t 㱀Y-y{cK/[cGv6ۇBxe8ukeKMMI'F&M1E~~Sqq18p}]NF?j:ȑCCak|=8|-RS(ix-A^j|Ը|ufpfb־8 Qz0-^MZ*_6*)ſ;~{# `/}FhWi{5<;[G:֮Y͚/ ';:>CcSNQ ~?~8 ;N/g4~1+?$GNK4O -JlUiĂHVAG?sX?=R,~() 2a<y0ʐsSm-Y"[[ӵ$Hr)K+P~+?7\ }f?;NWs>JB0XJ?fc}}zB^%# g3^H$'w11τOqgt|r9~IHP0W‰F8 '(?!Ĉi|kf7FiACb  0`̸W?gw/ QgCM*n i0py7Ğ/)cw"UdW9vf賦1&; u8ŹJu3@8.0q`^Vv~GY=O>ZE8'ʓ\O$':A ~N ?Ks{uSm6ύxO6e BflUR.z`t~sǀ=/Lc<~=\A GD v\V22;[inSRhw1ر, 9l 5]2] nыWBhf3X'w,|{652Q<#''SW6mH s{G~We,V0~ Iꘀ]S8{XfWp 3i *Gq_1Ч&{ c+3tCpX!P(ȕ8 Ǡ;Jrq͈D~~Z|zzr~88FM Rt##?NAqIЧ@&1 y(hfM* @Sf21R5zY6xC=d+W0"QNPtK,8f~,#8{9vg3J d0JNy*;>_jߑc+3Æ++y2 *K܆ r q+7`> 7J4m`yv6O L,6CJxYgbÂ| |iGh򄮽78{Ol8CkFp`zBDxo|2y,ZOE74HO_ϢK1f̀?o ¶x?\ v^RtsxťztKqzqy^yT\Ai浇6?[r^@;S<=nb}nʼ(e&(+0EuLyi=/jo;rNY39^[b粗)ǐ粕)*.F݄!c`N& ᳋;#!lz̠W<ˋVɓ߫c/ǀ}fgtG?ԏS~κ\4܃VX[he? `-OHC> {[4:t3̸]_PoGT w*;g'|V Y3gaӧ ݽgGh cȫCEP:Ca^2)|<7,q#vNGY`(|#̠y95Kke<WpgόhAhIt:>~-|D-@&-2^[4Su^!۽ۉ{h)(vҰ {4!1״3:5PCĘۯ bb1ꉵHO~m 3/W.na8ds9|ؑʐS4SzG c+S K/e(4 Y@/B9[!A^}S>sZQ yqod D/1x5/p,TWS:U>_ 7Ө`/!CJ7`D=]$WVSY!=tzv9EiM"!WWBCDү6mLTRR2f̘o9U]7J-~~XO3 0,/R[jW 0}W*uQct򸬑NqRyq !`O^ `_/Cebm&/ceCbI:A ,4bI ++cZ!#ka, ~t8Gj@#M;K@(|8T_ rf-VcfhdЗ5`X`',n-%YR,&3EFznsQwZZ_/9N_pYw氖1<{n0EĵrKX~z(3@At4O[T!c6/?O7~KKC_߿Fo{D{Nض0^J -N#mf$gdg (v{z&$ϿWVM^ǖCk&53ǎ&R8<k_g̋ ~ ,Wם1d`=1@Aг[0[Lk[^:aNw q+Ӻgs Aryrlyq/ϫ|o)Ga^AwH=təar /0c˖RKqX3US: -a}!Oj}s@ ܷ1O(0~Fz, %` ~|ϸl\hҷ[㬓;,?hk7SoDqKQh0(2?ǰaW??e3-bɘbIZ¸AV jM21ǚa.U >K6)bjPˇ l z u t߄@=J7ЭyK`i<Ə!_kv:q{ּ\G~ZB[V.qk!6-.iKq⦣tW@t]q#̾5>ﵫ.фZ 19կ 1,~Ψԏn"[~_[:aQoo[Uy?{KpFv(O7>CED3g=PX?>3\uUU4 7h#v [Y)s-~AKrUPO w_ X@/P"4r K{x5C {\:)k@> M/E&9ASgMSrq ABZ2 ~ C`Tܒ1±N# }{[)~#UO-Oz ~]NZ}4 Tۛփ/vcXA0BJOO'g>ꚁ_.)6g&4z!S-]:bMX>7Oπ95Po)c^ASg:T^fXְ֙:.f/]3xyU ~) O۰Q׮yF8_G>soM9ˀGV@/MEf%\L\8MsZFZ3?~ʧ΅ @=OC>##df\˕ j_9Zl]@F4KFW.Y_ 'ӵ~?4k} {5J4ϧk>Mo vrfW9Yf;ޅ,o`KSWCb1uT-hcO BhIW:: mf8-$?u3/XHyh۵=1|%^+f2 %p :̱W캯K!+ B9cO`3T6̉Ӭry 8 7ÅNù-yآAWa ~޽l~Z|Y{ U/wC'õ v=Keް2kQE~~GKLS5@W=yi敃</dǰk! ? #NgŘ TՁЦv}B[r`X9A3L <ۖ/ ٟ_O --?Qiz^+(.*XOrRb˹D~~1A.ÜJ+4_~99tT[©f.5{@VnihRefa1i^qrv#݄ aΣ>eq]R0r |agM$B߽ګ%“| F" E!F QB炢AM|EEe"1JHa LL^uo;IBD|~S]]XfW!J={ _ )Vy'g*xhl06h6.O?|?'JKppÁ=ܱǠ7tG]5S!>(U< 쎟vpsddS k+1)KJKJЋmrv^b!`N`N2']VvmG@tm} zT;boOx"aBPg mɑ ؅].bS.zUひ!.FIT≂ɛIyk>*{H MGϭY)"|p. ~w? 7U#]L +zgZe_u Ç>p@! 6qACԍ|DZ\bϨNrdSwp!],Gk 9nžMq fqanF`XdX_xHRoViإe@.b~\J䉿_[9Q8g"ڡt Pm?I W]ܩ-֠z_/lB>^bx['vxdp .Ƚ; ~= !o\A`169˸Dں&'K`gk@4C#4ȌMzfe ּ7U+ >lnezR я3>} ʭ|X ~0DmWq7_ ]@dFaK('dѓ 61*gD@IPk6Sa梩xn^vXqv^\4&フͽ2Dt)GZ!1kԵM6qё.c ݤ6߄4#Ü-=A~~;5nҧq;4!uC{ -]}G?G=G7~0 p47"0x{Bp֏o}[W>{.E~Wᴵ:솕͐GeLAS_0gC_'Ў_ `ʐ:2HL%qc\kЦǴP=\5SŊ7SQ]QNvGy˱:" P"m򤉙;IQ5ֽ%,[5Л0ܑ&kob'kHW ~yc1Bؕع÷/?7ݭKv߶:a߬PΏpƅ' /-}ģ ټ.ٻ )79x .&/·s <?~vpd׮] }}sK9ݡㇰ 7PTr/_~ς2WLǯ(C=PrjM-J J+t1#g\uOpÂ@dBǺ򹦌!~EDPǺ/iAPȏ`NPjSπ^E2fcvk1K Ǧ|hCq*h`@7 ؍է\_zk>z VjMzm yg»Gchƻzpc;G#)?Oq3T}^Jxso OQd!\6B8{*\PNv~H+;F^K/~wǎ_qAoSAB*iM&+#K`͖> m*ٲ&ەG7S 蕾 Ǧ V,]9 AulQ 9'>A(Bi t2;&w:ȝuhPb+% usxoQS@_mcB5d<@TC=AcǛ8;{G.'mw?]{ǃƻk}[]? k/ǻT{׿/MwNwݿ|yτՁGտE/^^s(J\MEckOx:Y8w:cc+uJ nJ`1Y/kb_;ݼrkFO h~PȩaO庼ح 7n ]qwx)ğ!8A_k)>9xiLN~ $<ñԵ>e7?~KA=*8΂0qƅḽ©l ;.*ϵq]G~8nw<׉~>M;`/0Zy 'EA`](, Ԛo`eJLv!w8g Y`'_,|L4/!bCz r$cG,-RjqM;yzxhp Wze8ep)o7kt wͶ` }c7S"5ҍ!o yÎv86 ֽlq?{̵k5?}??~nܑϿt:|o÷ s/ٹ2/``Z_x vx_ x|ǟ /waqm jqiǾN"8;'\)vXf|\]`g@.039 zf6:K<ԑWv2a꼉)~]-5Y:``7ܥK`G6k0M,Mc|^?e@w['?^µg; }Lnq׀ i6>.a p\}v*>dz2f]v ^YE!o9\PH:kGfnjZhC % vN ^k/ls_YFiݝ61X;{w<}RU#}kutNύ;.y5b<108 ·o<xk|<>'K/z/~Mo>tou*v]m;ػ=N[ρ]>t`3{h۱ޘA7ŀ3WS+e@`/,;<)mŧÜr9Ĺ1SiS;xc=c_Ӥ 1w07ǻc|s,*k?8-;3a~i:}4/B/ .^džtuM|qgoXMF8ZW!;Gݾ:'?'=V:s^z)\c??N믇O= \/pG:S0Ùj#T W7w؟suNSn8sw:~~xy}+^oxFkVq p tnn˻(镼U=_0MF+1䏤1g*@ X Wgxu!g^W 8Tgk9 | @]==[C?]=]71[9`nxGԎ߱w?s%9ύ)e?}"㒌M{^1BoBk-p>χ'ϸ' ~ǽo[p2A\m 31ژJ1Ӷ޾__z8EB=D,\79XuauT.6F1FA_i#* C^M\~grYg@r̀^;(sno07SC핱UyޠS] %@ HP:LN6UOU=Kgpǎ~W~~hww]?~nG#{r)~U }?n-㝗-o8 P79oƐ7 X}є;x v {-;j F\=)%D_'\3̉T6v$kcrM08"ر5;d[ɓ0' G+#[rR#R~no*@M(|o54ۺ(=j! å ?Bڣ Jm;~_W?p_t%۝sƝ~4Fx?9ظu~f'z<utTDleNTϣ3b mmף|1w%G-PG::~_}ӕl߻^~nYG#ƃ?}p5nX\%? Ɔ{"pw*e3z8f UZ6B/+ٲaz }v :Ir$@~9<:̱O2&C)h?T!OOo(!YT6ž5(Ak%es11s<. 5gjh_6x u"h xE_cR]Sc-S=^5o+W"}9|9X=߁pÁ~փ_J7RA` {xTG0H1Ǜ3}a526ЕP7֎o;vGw;}wH~ҧ5~ ~n8s}4AoȠWI5Cûr}?)15D0КOM'a?Om/8GrS9=/Zj.^KOnRpl%uw\i~?Ϻ?7ύr7|zR-~8Bc%?[F2C0XLUO/[U[~D@o ͩؤZ@wA y#41hPw;i]Z[ ]v%W:~Swh;r ( _93<,;EbN70֣ZC7VSgCM$cp6{K_61Fk71=e!K uG`',s6K<_Vd.IYR?4v zc< 09@ D/359j|2ODk~@y[djA\c3$G7P#=h\S`Ǐ/ rx àׯlƦZ52UvLtfR8sÁn8swX}{}w2ԍ25tM>b7&TaYپ⮦nhBV6;ұ_gx1/ÞƬ\À`,]?zP5 v;o{ 𸛧s K8왼/m#{?ͪi Elh֚Qr zd˴/Y ->H8~rد=~߿>׃_0E,f=U{qM7i7f^ }]:?)iMV>zOqsGDC (;Y*;4q9\#+q+oyr|%/N1=Q-u`3WT#qbBSSF(9U/;~7J> s sw8'S3\Gpf#l>׎rHwz'Cgr4"ݴ~ʵ}4vrq/u7 x&2Q=r.\W{R9S1/BB˺]yO{nPթ^?֦۷iTzyM߮H6K iNmQ/(9Q~Rէimk?R~n8s ~}3փq|̰GvD>B\㳱V1!.i!۪ܵO,?Yͷ@O6e^jhWo gs@@CܸQ/mgjSWe\OAP >3I-EK;*Zew&kkm3y6啶kV|Bz}=ɫ7H0q7;i 1̑f&Iʫdz{  79;>est <9FCN> ua,yq]l3ť~ĚxRб-Oz ,k&^:y,X71!lI,R/rXOK6,tmѦkcsxoHE#PyƇLsUǫ8A;@]W]K($)k{ca u&pG`G6@r3'9.fSwB:I/;h@/e8Dnb8'Q~e4/u@g!:C]C-jΪSkjߟ_ 79;y׃_}JbV,YslʏvFQ(HŒvP4UL=Q G\¾p KScbԊ'O|QGB_1ة"ƊЇEK@oю6aF[" nB_Ӹ_V*76DԞec N kg FSdzkዟ?7?~ǬӔi=X]W[r9^w63zw)NzQ1WosG芘H-sC=y;}N_?Z,rw1c? dM>"D35w@G7G!cRB@]v47P:?vay>Cj;kwy%LD8Pml [r(E-m{pg? ~nρog H9jQH~:Cպ(s˞Z69ĺeu F/sbK]`|o44v\4HP)1agcEVa0˸mj0Ԟπ-fr7OaL 5@U@8f@iG vICis >qat<ڱ@XdzճsW|ށpÁ~_nO[HwtU8u ͣXL|S[L5S mU"9B-Ap.K_C1\*}r+)"l8%|Ydi ϶cAk܉?51MS5%M a&Pݼl{\ӌ/P]8ž.k)&Ai&-i"}:J-x\/8sÁn8sw8{t,J1e־ZԫtUz"yg. EuQ>eЋJG ӕ|ÉUTCHۂ5[c% ~F 1JKrAnM)V_[k0W_R!;m9<`zo_jw3Mp2Aݸ)cAsLlU TPoTpț;pJ` YO.qO ;4~{O bK/>ɫqāk^^җ[Vρ~|ul[}?e^KExd RRt(3č"4^jKzXz{=XtNzZƮ 4QS׏Q..57klAu9 !ŪU86inqWqĂ׾5\S|>K@Xd׽ng;p.9T o߿Nw饗K^{8cJ_ZÒ6_a<_N8g)|/<}+9;2o4wO+Ë‚.*$Fz5&W.6e{n=d{3՚9(|d3!3;'}H#졝&9CsCF `kDjuM.^0&CN,L+(@h@z ޚ tCioZGM#Љ$kyes9Q:?f8s{0)>|V;~կm>co#@ǜtp;>^=x8 κjq{S/q]G~x{o4ko{ۖi+A^C4X7PGoCx!ns.}x_-1l0 MdS,cb֩Pt >޳ѯ4 Clc=`7 ̡f&/X55=lX$ÈRNb~k Qo`|X/)NZf_56F]y,:˜ᎏ)$N~d⚣3׍.Z~nwu!;_/c:U .:~@=_ih[z5(o]P>8`NRy>sÁ;|+_7W&s* o?Prݣp ʃioC%loMbEC MA3]|t!o%.A-0ewW;\f]\ '`p7_T^4漣AeN W3\W:~O;~6Z5$ o uXR`?-'K0|o+b11-Vlځ>/b>qĂߵzZWSm{gܶ5~'-?NGhWm-M7;s7p\~ooÙgGDQ v3E% WB^O//_H) uό?oE/N].,O/T;.nt:tm?ыR7tJ'C{7e'o VI}YߧR 'G>CB)vZp=9#]&NbE5-?P3ڶjتW;~cV=)|~nw?Zw-QB =^Wu+C9sw<>l8cg!P"c@=G; mt/] YAccB( 95k(5~&|Ŏ߮ 3}ST/]݋#+s1<ի7.0=AahbZ%3{hzّ)[~VCwxw?~wS[olE݀]{y=֛uKnk  2 2@݆;H*ġ@"ԅ%6XвG7`΀ g[kxOq2rYg瘕ow%"i|l >kb7&k='س|_F{.[Ƒ ~7tStH{g^<eqs٠ƌnW>Ɓ3}8Apq"v@~Ct:쯓fO/ʴnl`pZrnH~#^arGV-{drz uɩ_wW_$ {a(%]h3QRk^<<RzxWm B)fx6_(6 ̡n.o?@Nkh#5Hx^}c'1~no~=~C_G?wݱCtjzƮ)( @t 1*a<z౬1y~Yf]A0۰bdS.c[Ə&%<`/v]W.^QS`݆CrlOGO Z7ClEExNؔ`F|l7(V@#Ď_03IĤ1GqD]6'=I679oޝ jJyE>_G K:%jǯ XAbG/^ /7`7f- (.a#'P'glS'`[jcSώӮ^:zuca 'ċ@@g ik@aFgx'oM!;uեol<~fCuv)DZwrl7NS{&~nq%PiQ zy ~}IG!W j,ic/V[|s;g1'掟' 4֗x,p[0BQO6 yLm;F5%t]^sIm!۝- A ˜@_~1z`ȣk /Jէ+n*y|3Z~߁K.v?7p_S6^1ͳP@!!πuҶ@"IJ6%G-& w ؟T>uJ+ Q`Oj._INҕ]U&GWխ| jludU$Fz΀5ˌbN' lⅹ`ȫ| PhZ.A.@mC#-Ҵ4CǛ;.v7w 79;œ`gi)A\/E ,qM4)ڗz7R~n8s ~o+䌾 vzҶy--?Z ~U]o*MK8pZa7~ܽCc#+/l@u {9vo`/˹'puRa$3̶ de!ߔ']@TRc[u?CîiPڍe+FRCNсpÁ~>e s>B7T'ǐ6ͤ15%*#v MI;O ~rv|=%- {x~|lE>۹Îp=, :%) KIRZE#%H4yEͼ%?-Y18UnKcQ]};JX׾x;sÁn8swXԂWX*eC~S cHy7{ iqǯu=8qJV @%ܑ0]&~ž@@ .)~B\V=AV 8nk:m7x{M nTRlw~!? ~4n ws {}ݓ?~w!/QN'js~\|s7WCߛ.u0?9;z+>F+v.S]2oIQ<W<ŸoHg|qB]v Q,FKhu]V;V$~x}B|ce9._KFݶ|mz?7k7 75O8Ǹ' ~˧bxŶc9v"f yw E%(R7g-p' zs?S(T~{U-'{n+;R颬!Yމ:vƟ-Eto*: f yjBa}}u fkKG|];bGk~꘯8sÁ~q}O?gۗNx=so{pSf}Av@tR_1%U3b <P(!W F˗[;[Vl Jm:}|6uF^a|?Ǟ^Kɷ )YA;Xuy S=gW;v~fOo~s >^p7o?6#X;T qa{]9с>3nGl%&Ӿ&.S-Yӧw7c<ھ`St"9^S&N3Smip~7~Fcx[8p1p7;O9~|}+~O.oƃps`KA-9s~xw%ENrXϬ|kw tMY×4Ek5" v\m:Þn!?c 4q-BߒKqѹڤ%u:q!\_tQP!#2c[]k4W$ {-kUkN bI ~_s~~ wˎ]xI`z|h4#9Lķ}OՍ4uρa?}?+6 km\ Ü:=AZ:H`Ak+v <;flRC;J`0JJVfִ@@o7*t(W3kȦ:PC@ XKM ;WV Pm졝NҁG$=/n8x07CzкgZ-3vlk``:;}pd;ԗDUg=9,}-5{ ρ]%r**8xV:~xE`7o ر^'!WGj r t31 הu h2 ~%yU6923^V)*~vFR}=e_N@W|z |%hG˼ VY\Xjn5=cqDo~:|$zx=.fu}(vAA=u>t.D~wg,7 |m[z .< ޷ʯ[뷺ķ~mb.4 ?~yvRy[5s]s][o6ܪC!j*4 =Ek+2֠^km oKQSF.pG`3nv.  @σ`cp_.q!Tm #:,.aٍR Qn v֘\Ə$@G0Ƿ{{_bUrouzlf/-W ekm6Ӿ[~܁G m| o 8O:?s>6rCٸ-;tM5{^gj6}'UڽUzW>_1.|Z|uMrʛ@m %E`fܬSK(419V.BJўq=i(5~kn@|Z;gP1ANW|pg-]@7L*pȱ;~9 =;Oa܊«/p ~26-oε;U~nqݸ7“Ip_]i/~>mR]D`;.N< +5~ct vǧ{p+?EgJnKā~{w|+ܕ -UMiŢUS+R|TctmGf_'~:^9`c6ӻKq]~}tvסv@(J iX.6 ( Y1)PsjB/W@%W%@]}t/mhJ]rg4ݟr?l7] ?=p]p迀M:sOϑ ~ow]+NZVv~C:;nyZy/]݀]xoz%J#]g[05RcS6?;t v=j-zQ^sWS+X WO%yK_B[ȷmw " { 7=K.|$r?~wKwe?PM;b "ߴ'RKEt5:MXт5 T> hwrW֗f:gk&s:\S$F~SuCr>BAoj~ZѴK, ! Wr2ܢw^35 Vck[@ZyWyO~pw; vuÁ;~㭗 ~ sEtcEiߐ nS2핶gj :7 /aЫebd 2@F , vye+x]%_i - J_46ɞip.PMOLA/8W+B÷~W$*k7n^4^4KNq?77|WA35{G=n8swoO>򔧔ɵ գ\aV,-/1صee*qÖ6 f}\ר73B ōOZA$WCyuGFpWT q+y^ ~5eۮ$ oxW 793Fg~𒗼Gt:S  _v3Q/G2RmbÑz <;_A/턡гlҞl@`%Kʠ _[! (¶!k;~S9: Ǯ'!}~!\QWc(ۢI<[ؚWۀ\HzĊ_$z}Ws?7p7p_|v?cilMH"Aݨ 8j@ϐ]&ьb, )w-C^݂*W6^ǐ7Q!luIis>2fs_nz- ;~*Xezg A_ ymOڡ`T嗢/v?7pW_}5caAA])U ʘ\kݘdh4<|4Eic=9<טsՀqTG ;(=+ ٮba9fxG4(h7h+ڱQR\7ZthhN}˛vquÍ_{P[7~Uӵcev8V4A&=)ve]c('z)6 D!c^,DĖs\CH p?3Ho帮]O@fOvbu'kj-c,/W˗)C_N ~]j<lāﰀi?9~c LJnh,I0EsM)큥M@RW ,5z50D W9ڳƬxӝsQF%Fӑ,a;[mv' # wqe[~~VV !6GQg.cMkXvrfhs+V<~ A={21ew2,nc~i_> ~nρaS~w?k,#U706,Ca1#С^zPQ5B- Ps}uH]lS>y=tvA6^_K-uTOpBukQMR9y@AEPM~)~qV ܜ0)>h=%b *cI}*k=;ܬk8-φ@;M>w?7pp tA@ӎM`3kJ؅k an3x  uc/mژxp]Z :vkWۊ%Nnh" }1Cn;C\M8YSo?"aIl&Đh-A C{vZ|7J %K-1_b1(yi{[lӥXBa_m;&:Nxp' 79;,>!kЉfk9g 門!mP|H>TC5II %D#FbSXjm:Bܠ05[#M^ I-zSt^q\v6Ao;]A:v6P$=s\텧na s\u z.MMwY {2ն϶;v#\k 79;@]gvu[DjT %8 9T,ćO7E#:cqDCC_lͲ&6:nhRh4 wM}苽(ege~(KMiqV_c<1)逧ٯX':]m섧d:@@m.(ORBD.c^bA_,N-B<éyS!;.?7?~=pQA !ܑM1SŠmbZPnt`N*lj˸1M}6Zs(Qk^D%;~vsn6nQ"3\70;56OJs+IRkK5n>IC<ƨO}:'}*N8ħ 4 e[BX5?^>g  [p?7pp3|A7Bt:!];|Fj /;;\_ǜlk ;(% pSDԁE-ď9AmCt~}3h~!zɏ:^iO@ɞ'g&Wu2ٜzGI llM,zs#)c_l z|'v^O@^0hǷ-NoVv6 I;ߣ~kpƭ΅= ~;?xsCC{ x=?R 'o Em.TA.ݜuySV$~QP7ek!ؖsM8[-& SQx5TS٪ѧEDc9hyC|ܴ'Myi*w ml #B*b/izV̊+mX>7lmo0o.şs;=©۬9a)#Ĺ?~w[_#:3zǠo!7J6"q<\`Epg)`/>14[ЈbhSpP]'|l~:Ny'Mٴ qSDسIKb|3C ^#Di$)hCˊ@ 6  vf7Tõel v562_%U =%0F-]:psݥNWP#~} \oD"t RֈM׊,1BٛjهjlQo ءjosgZ7׺ƎB >acȫ+eK5~1ޤ1'-mMQ̡?8N@QZ9k`k<לZc9N xjL\#{Ss#qx|E xx>u]6Ҕ *~";}+o'>SԳ΀ {mp2ɇ9>oc:fHPmqV ⲸZXBS "TQCF(PTCrd! Ea~}ssٱysy2yor_<@tUz|Q*p_YwxVrUZ@ nyyʿ&; `.g*)?Z`mo`P,[4ت)P'ڶ/m&5~Ձ:JuF| Z\znbi!f }Ѓ$)6 b [3?g>3 ~QVÞ/}^>ء޾׷LbMZiz>ߓ ~* ~*{. 9+V|[py/ _r8A!w Ϩ[ iu֤{,8IѲM?8?g_:B9Cqi>a^^gVf*|\rgh¼і6u C,7Q)ר宁srO@6?uM\T 9SPr?!orl 0;d??ৢW]MMM3ԹWAZysc\.--ЉE[t}VS^㲉k,v'7 9+y.oȪ^jÊ`˜cdŜM1zȕ&6=ۯ#v(<xG^baH2mV"Yф_\]!I@_n/?Soӏ~+? ww> yʼe-8ap)ȢGf \艽f{7=dw=qiP$@S.N۵YOW==pVoTlѸ`SVČ2m2EodqT~xm֮cU/?4ϹV]l 0T9U tU< [1͕3.|}F z5c%7 藔x<[+yi 8ʽ}@<![nkG__d. pV0-qu6_|+xO?9_. ~_pǑ#z%⎅Ր?{5gym]AUlY]gsҤ4,4@xw-nTٙ㈱GEVsX\b7(05x3ʵI^rqc92k<6k2P-Ql&?ׇm`ApP۪ə7p_ ƥ,ǩ qbڭa =Thcc 4I>3 =K???~ttD!@RKrm[ rŏPtqj~\%&o7v9YdGȕQb+3Y3W#W\W/ +bF13_4=TTT.x؂84 ÍC7/=!, f줰 ;h/ y,`.v}h/j6 j0?8C1w ȍ,ЍlKy|'#  |>5^=`ۗ8YU0΀/@kO Cb+wq6ˡ/[ v?OTOEOEEOrl1l$pbhT`b~a;nXl砾d~Vo>69?\igV 00ۑ0&c\#Sd]L.`]@7sZ̍m_VJoIO6Nx^ rq%1pO,V jb%Z.":'SSQSQQSx?>`շ>-Y+}=ZʟpknB/+ϡ+)bxv޴ӶHV@_9c%.BZH|80RyX/wߞXw\4 dj v`qM}};o%΍)%gs6+y~NNQb?Elan=[>thZM P5lD\c=g 1ڡ;82m\ Ӫg-v( F:whY٨Y{;׭e𛶅t?PSQ9ssҿ?>?/}I݁ߙz>yt5|>3&itdے>ja\V%=掮2s>_BCVMڬN|mغm5-0WJ(IصO3`b}mEOb{Mb_sxs =κΣwf ?|d^?ITEvSqui/@;=ImOZSQ{Axfi'ioZEmqZiT Wh2w~^$ã"_iy?RL{vpzżl|(W-P<0;a~_~d_U t'GBׅߤk*xw9B^:{y=W?U ϓgһ+)]~0=,ܯsb a8X5[D%t v%c%/mW*{5G5-`Oں 9+be,>2 ^ae9t'~mMV*:fmڬmSfuO{H58#~-uL5/ qPC\ ~* ~!K0&=x4E+{2>R/UZØ^u_!:UR@{O*y]& ;uxcR?)^~3A {i jIXt ^*غ@@A yj`R s}9pHEndϤ U$ |ϱ޺kk!5fxlaHMcׯm*5_g_7}jߴyoVͳg!/)u>?viV((]Z:4? @ =qhE͝o CD{s]$<_ݛ\:z 1e̻@H[y]}AWN 3:;}B{ѭWYDw$\bxfEXjjm-|9PΟ9!g6F!y}lý%]90WvտO)`AP5gҲEnY˹e;ڶh,7- qQNci[VFo,_lӜB;_ 7nv=3<վem2K*~}T.aoL,@WqnW?i[Ip_[?פckww>s2kqy_nxV%OS޹٭;h??/G֎QbU]{Ys!С"x>[l8m`HT(ZtycJ=(`sW3no5kxyg!/Ybq]\>)5UCڵ|M *~ŝ(UA p6-((]uu\E7^3Cq~X'.z zJ-ACoohᯂ1`$ oy~^,PL[=6soPB4J6@>˨16XvݰimٶQ@fha60R 0:]v$3>U>0X vX[]:ަ]I>ںO7Z{nU>OC 185xg:FB ~"ɀ]=w.(jW _0ɕ+QO`0|cq_l}dsJ<ouǺpU tVc@]5`mb 4F\ MM&Dz6ndmdԝۓ/.߬TTT.OL?9L{#w1[iK|xW99k ?} {?QP51CzU_m48 tr 2V I[ghql`:y?4`8n`-*{lc?n9T@9 2Xnbڼk>]ꮋ)[b\~m3+վqwsF???~G3/!hB϶2/YbcjfׯYCOBa&_{=,tP_P;@.l&{a.׶fl۲>嚩v~<]˱g[4 %\s?C3:Zl-+UۆQ{vu,bݺ?`; ; qs&D>m;S8k f9W*[ ; ,C۵pr {܆~z# w$8k@P>(Qckr%='W/p]nG@[9.os<@}lZY+~^OEOEEOrk w wՆ.vm̯zqT7@'z#<w>F8Q[6/y b6,9g'~k-{wZr;S;5zu(ϡ}[l2Yy a=Ax;S|ў ϛ4P6ռ]=,sߏTTT.̬U-̕-U`3CzSxzu>j|=m+oSků3~?& ؇"CIm?@~d{|3e|K Tৢ-rc7 \?????? +819k|6egنwQS o *))\'`/$Iγw ^O\{w%#+)))))\,1Q [9Gk/ i-@Ā% Lm<@5΃tt5iPw{M|xiU |>܍KEVSmŶ=M/ }!-vI ~3]zc৲ B@22z z£g౸W*_Oc)9wݓ_ C6ׯX~ޡxyyInNS+ 4^C???))l/rG~ էi1ҷM\ x*܅߹jys~D j~BQM#lcbh8{‡l?;m0ƻY?t5/Nhyg|}$,t$& t~ৢ7. ,85LjZZ|8Btw% ]\sқ^Poo5`|z~-{iYd~>TTTTTzswᕾB‚QXȐBx9Ȳ _AbIܟa<}ڲþT.~^wpDwԧৢre ! ~ ~-lz)z_Ly{hnnnoh47 ׽n[8G>*Jݮ>~czO7pö{ssSumm&[nIOOEOEOZ'NWzGi޽WzAF}Y{Ķݛ[<o~x<0 EC~ |3׼^W()(()]o}yzN?0ӛm}0wCGx^6B﷿mZXXNJ׾5[oUޛo! Gѣt7 lw:????kӓO>Iz׻@_mUz-?%b-2|{ߣ^җn˽yx?1}CORqۮJ/~ W*C_ehWOOEOEO?~~|@o*vc=F_uNyd{yv;駟о;SvmWr[}q(97x#]TTT z!~ üju裏RVanavoy[m/f^#}Fz}[C<͕?^wcۀWOEOEEOOEEEOEOEEOOEEEOEOEEOOEEEOEo*ৢr-_rIJSSSQQQSQ{p.KDˋ'Ϸ@'wৢৢৢrł*-˴Ojס}Su䑘SBx1i?NKrSt Y_+d5F{'@5s}>fq/AV8Nta;S ;qS{=V&GC'//H*)(\sժ-4C w[py/iRKpr|2jN!_{ub2,>ôq$_\Ś' jOowa)w+~3H' A_ꡂ5~9ad,Wry Wd;QZC|Er++jܤk'}Nڳ%Z] tRvUEuo9VC'=V U.()(\g|~'=\U A:CWi9_+eκ{M\!:PxV<7x+)((0W aӆz%Cfu0Kwq9?lYƃ]ơ\iPVh.!=p()((]:BS\!~a)sțWwv cHRMz&u0`:pQ<bKGD2IDATxŝ/99J" _?)*!~8iJdXI$@Ml$!  Qbژ1=53U]U\{G/UtoO|ǙMmxŋ=@qlE>}ıh=0M_]/^xU2YȈ& ¾ŋ/^+anO]Q{/̂ /o)=`lQV:`};[r򾝽c&# .+}IKo'Kӥ_H8B@&g驗S);3zL{H3clF/ys_tW*{P^\, bzA0ݗNX)ʾ`;["G fcb"KMCv}@;lW]v}ʵe5w&[wycoi[V͒a驗=d3og2vlk*QM77;٪O:o&tLcq@zhIhBf %>W1s&;7`PΥbo|!?v| S}3, y2MW>`lOO~SxŋW^nS}0˄Qqybzbmu´{7wa;q 7?~\Yͬ݉'Uk.iƞ}gyO??s[NC=#?k4Ïz=}:vS'=?>gӫudW^]v_=_ B:BSMDRF2+~0TN]@aLRnΝw뮻Y]^{Gv^W>xGTگo6sX:I_a;䣏>j|Ǟx m߱cǞ?̢b~Znw[{LnɓJ3v/\)ژخ39Zp%ԌҒ6TeY[wVS\źU_$>o\f(|b}qPe>k4HBNjSy)MKru hӭZ׺m7ÍFCkZzEc?,g)pmM(IѽvO>ۓ.nfj;|*e)lx!_}v^2i[QcD, Ip YznhҬ5]{svb*o' i.j3'JW@Dr@yR휡׊_5UhEuߠTV!߽r1wM6ϻǰ.׺T3HUmғ4[M)י}ZҀ{H,PuAO6WwZ=ZIȑRU⥼{7 @Hdbbz:lJ*vY:~k]DUeӪu7UIQJIL=;('0ׯMoWJ\kv]vbΝgϞe.[ Ӊ_lɉvfGYd1s1똕':i;ZμyQgc:u/˱cD*O?617;wylHTU.4&ZӾ!r-q27FG dٶ?۵v jW<4cS -, ]lIRJS*LBE7x y>O)3Xu!#1LR@}G=KIJ $o0@Bca `dƚ-9JKhНo8AE8P˛'2HZ&cώOl5fO*:@h2p0)2uNN|8h&Skۮa&lײPԉvi3'L߷SeSt@͞jILs-(/-!ԷT{z>يOFۮq l~ip`RϠJv_iub8KlMJ+?p% ~m彲wG0lMeQ(ޮ>>vl/:9bv)C0o5`n>)E~bl[v쨁lABRI9c; Ե។N$5 h.__\ln=CZ`;lvvDsla;vl`;~]v`;lj5 `ns8pmE_cn6I7g$Sg;waPTʣX]J~u^)J^]ځW׺׊u)~.N0otEWڊ/o {_Lv4GraRՐ jܧs?M[ŷmr~o2"7S_ 7C+uK)<.bT9R/-J^@ćR.[O. ~yJvmeBɕ?/or[nH #R CMv-mC]ъGVw~[PYCB`w/GF~5@v`;"4ge>,;`uN?_}S gsjAyοz\J`U$[c^R_޶[LkaiQ*mW=O=;V?e;UL@ ۢK1wirKٳ]}T ZSH.%e=~6ʨ~WI"@=sՐEHKȑ2J۵)*SyFUZ3NKo;e@+qal6pu)){B~9β^˨'ۍBgɶkv)R.^JR[&km'$>vŵ ۉ=Xa9TxX KnKx {RyT oMCnU~-~Od8[r.!NEb k6)%)'$\RS?5wq|4C٬ @?+{B<uv;9=hRxo+`$ҚESQ˺"NM dB$vg&:u .MvLM#4>h~ `:33c<e.]cBԶ]ӈ?U R 4a, @/@/vɌ#"7#M:hN9,C3<ӧ¬TQEĠ(c= >QI4d%)Pc7xc׮]{tM?Di>@ٳg_7&ooL/0+=la;vla;vv`;lvla;v˴pP0\~ffk1ma;&>=ϛÍѦYeLšfpchhX?۵,:$Ƀ2vͲdIjx=fY<2@|Htپ۩!}'9kNכoj$k`MٺG2텂U5C$NZ3ԏ|nsSٮXSl|s;f֢()35]Ƀ&LaMvebLỳk<u9`;la;vla;v,Bv`;vla;vlk&30 Ĺʶ37F[alU6ս8l63ZgVw !ss1ڜf,67ߓAg;Wn<_]N#}b,[*.6vdV[H ͓wMuvvOj^ObI:niRӧt:7lU#xsOBIdۍ<Ft2)ﳆJIlP 9a$sr۩ _vŨᤛ3}G2I|:,/qWLy]`vӯskb1s`;lvzfÒٯsoWvawG^ǚĉX=}/ ^6vݠSݥ #Σb]Li] ސd(=`dާupPD .lAAVOFخKlҝ)`;oYB۵vB28# <蓴FLخӇױGćL'W* 9uI\F`#l؎_ v=qa;vlcMlDJ ]l>v* r)Cvm$|Ovg;/DX 䮌6'q^xJKɉ1pԅ@v};Mt,BWFI'JhSxCخ6Y%nH:B>v^6)["uƬ6QFC\l&۹zH:^5@< mU*Z!]a;=pޔtq|nx[i:ƔKLv̥|elz9kE/a;vlvD&vm]qyD/b jif-,'S8Sva% DZ%mZVhe`n$n(Ѕ8+恩_tpEb\۔Ȧ+݊gCFzL<vEQ9+6ХطkRtV|gDخy&1 Hm:ShRv]R#؟*d)NFN\J&/ᢋ^}޹P R v]ۥM=D˴]BeJ]"e8Ml8D(Qi;@Bv]ڀXjG&༨jەVCMrFfM^6E'㋥Y$#=:w|;ht'2Q3V_VTCNɥU<1=-~`U fpqw?PJ'vu9`;lv`;l簴0]C!vnZTs.evӁcp,D vClW}{E1?PuDsͱog/(OyU$Fi(1LhDUs5] W$6to^"g?.әJq$>f~F4[[P߮~f{bׄv=ɜ/Wh#DyMvbBϊ٬g"Ml?n%;,I!bVIAlsg*VQV)~m)Ԭ&hNZu$Y(ۮYˠ*vJKxzNf,+2QZ!M{.pF /N(l'Q%UJu\CJU.hV_iD+PePۮFv s7/+2BoxE35ur#uRm w]K9°Xt6KO#eX%qͪYK8ST&b~"۹jcK޼aPvnbC$71hvn_7DBȞ,%>"F0@r `Idž5 $^>~錦K|2V(Z?uIkG4gS*v6O5%Gj2.$^{(GB2h/8lǯ֍O1a;\gJ/Oala;vl*ۭsvuΏTZa;N$4`NP#.tP#$b Bo, UO"Ǟj).i,$⩈Nm "&5)ސ2Lo~ Ű ʀ,' ӋyvsaAto(:]mWL*#f8iJ3ګTbP3{ybTm@lxLo1&0GPX]@b넣`;vKm]xla;v.l>-LȜmae9(OlO3m寱ň?rؚJEWQcE*lN5dyN  [8>ۺcEΟM4Pk600&B_QS^ǝ˻Sɦ;;0rT%^ fStrg#l']hs衩q#56b)EYU_+T!\hܠ v];ܠx9R1>SɎɽG&r"*7U -VLՑ.F`;l'nv7:;BzO-_wnM\Q RFzDOM3Lu+r/PT"5Bl`ۊjZiCW8lm]b)\TP8bh!'5ձ?Rc$]m;qs;NAHOŃw6> jOZHGVvD&:7M+XeW=[*ZE(ymp֦S\pĉ87wޝɯ;-N-?ĩhn8~xf&Oc,6P@e!vʕtvU{ ly񂋽@mgĖ(-v0oKɓ'sg̛2`ܳтg5T{jB.[ڎ< v ݓ3r=^k%؅uaulGBH6C G?s:!QԥO)q2=Vk<]JEqJ#l6 W߼*NKϻ>$Wb@}ۉh#Nd=G2sB"oJͳ.zPNň*%+0HYJ,yqok1.i#lS%dYb#jHSu%}^BE u)ͳl;!M`^ڮF@p7#&ԛWΝ>^,xHRS;=u]Dr/MbtvO>YYg%G:Ѹ57OP#E?.%/]Q%#&1Gzd;î]TsEŷhs@vv`;>/@plW7/_'IENDB`spyder-3.2.6/doc/images/variableexplorer-plot.png0000664000175000017500000006172413003520702022666 0ustar carloscarlos00000000000000PNG  IHDR~?<4 cHRMz&u0`:pQ<bKGDc]IDATxxW/&fS7M PӀzjы`i6ŦM1 ˦j+L1s,Ye\%94%uV4M4Md|%SNݼy-n#G>򑏹x$迼4M4M;o"~075a5^R}y\_8l@~- ֎m~ϻ&3zib{_lO챶\wǥϹ m9sow9/u^rߌ+i'whίS40A;v:{t r_yKϧbqN{x:ֶ+no4v.~nX[Ǻw9~6c38clg}&?jj7ܮt~cOx4Rߺ1NGoဟgrYcOu:&[@ |3 0rέ=s;a .tygďLj C({i3ӯ끟kO‡yTAG@e0Ćp2 r7dchX cmuk9[V9pnm|c]T{wF~?'"~7Nu;^sOR?ss}{)FKn΃^gCyv\̹hfm9[ֱr>`_.w#1@=:F=J^Ömzj`tomkF޺(q`@gZN;~?֎6y\ Mv-TȚߴrlJ(`a^y+jNi8Vw*u+-6~yʔO%mbu2(t`zy{){=}j >>Zc}nm9ݶ$Eg].ϻRN6)^P;vۄ/gY{Ǻ0w<1EzNC܂ڲF@YiQe"9jwtZ%#蓟˭9i z]?{U^ӝ "VnN{yg/7'MC ~ YlԭS۳ ז۔C|Ţ?uuP8Ӯʝ/^nM]4◂YU _*R1g:BorXۣe˖)@w]嵌O-g$Y 惐4+g AΝ;sQҽ7o?#~7hmuV"[ձ/Uҹh`xG;w޽{ ]t Ɇ1L: oj<:u!C 1GcDŽ4mls6SV֩q@e9)5gQ=ˈt~,֐۷o+mΟ?8kWZzr~@_B|r !#1Wl-ϴ@X5rf6M3^z?ݶHǓD-LQ?}1é^Ј-S?F~?FP@t%((YV 6`ZpX?ɈvKt=ڳOՕ.njŌ3i2"(-aS7?#~?#~@Z*AŬJ7xV36xV :=·Vב97nnݺ`(?Y B#i o#MD_#Gh'OŸLyk'S9սi!>fmib d$#~?FhRqAw3/_Vƍʣqa֝VSXFYXAcďW#~z#>Z? ww-qEdeeڵkʣ|_#uBQv?V| njb&M4M{OFv-1nxW}aO_a^kE?فСC1w\\[>}EQ7\sNG .]`Ŋpe[s% ^(Gl3G{8qDG*dlcAK?(*~K–C8rRqY9s`0 ExeREQT!E((GQ?(c6taGQEQ?GQEQ&QEQoױU4i34($=zD v+jƖ34@&Mh O7-,Omt/Loo B?s׷o_t=4Mׯ@G\“Pg!!C ύ]g}/ Q#(KE۶mi!Sp)2⧟>[@x?/w׭[74nܘiM+Z{ RŘwWOy?4%G/& dxIT0;"wN[Fh"Qɕ*Uiv{u뾉?KOЧ,i"~ (kײeK+_UQ~4֪ꡦ(/O*ԭ*Vu4]M+z'#|ǏwngSK*;&K=:Wcaܻkg_Go?Sgިh&yݿ4 ~Χzͦ~?E(+~0%3Ci'##~/"sތG.µ[{5\Bu0p|YO/#$r?F;sg2p)4&wlexH$ Ze4My4/LZT3)T{uVs }z mh_f] L(/ mžrh/2nax&~[PG.S]LH@Jbvu o.nHvt=鼚nYҦQ>c+}鷥:SlgM?WװaC|V95jupbTdu^5ω_Ŋ/ |Ѿ XΦz$#~?"'(?#+?Uov DlK4]&9+Wg}EPTKgz;@fh_!_z4M ~|%lV|eKU9~4Ms[.>CZi-ݹs{]6oրMDh*:.GWmcN>M45j>ԪU7sPŴjWi_GQE%io9ϩubԖoBK~?i o.ZDjJ?Gi&WE@.Z~G4Ms\uђ'Es;{,ց鎁B#;늶| >߈M1z`r] S=c`V`|&sӁp(իÝFk5LjJ)/rRNh4CcÙ\shnؖ2$\`AF2gTc)؜߰(5a>?GW½C2;iZ|6.~ڔŘ1'RN\31|sR;~2o}_\\BBB0uT+<|0l% `&=yd8p~m-ىbqU6^MQ>Z+B1g]9Ojj*N<#G`۶mXr%ߏt$&&bǎHHH@RR: ~?ϊ)h- ~SwZ.ki$"V3E x7d?g ޙoa3)x9Nd|78n>ou]'iʺ \{q{G/$0G)P%HT6P@UTRk׮ѣGsNYժU?+vfT1VqxMD Ck`!'o_tcϔ;v /_Ftt4̙ЋT>A ~ML׏5xhl+QWv]{2~Zzo4 F ѹw͎HVNj50>8"h<<"hm(ߺ>ͰXW>|#f}\s)Yź ߆=GL^{ơiTآx}b^9-"2hOC/ďqOtb~ʋ _ eč''? qE۝FaDX7}~_"$7 ހkFXK+"cq+0 4{Ahh(ϟ-kQc| |7; ,ŋzj+WZE3Py4dݼ7n z>ڴ[z#懯(e$>j5 }ܲp5&Q@ ~Lϟ?D0wޭL#(}"9%0]c/ƒ7_Wk=m@~vђWXoWXF_ėxw?o(eE}3<^<]UR|-9~Fl˰*@h~~&x,.[~8~5Aޘn),X 5=}D!<>>) =<毵qB[QH2_g/fM9ޚ [wzcü_Jjcwᥖ~9j6kHDàmt<kGރwKAؼq 8R"#5*)AQob<NGih3k:Kfy"OF38qE{3UB)~& Pg/h!M%n;^oo4h ^B ZM}vCG%LYϝ;[l!cbbؓt[ìut`(H>e2؀_~ֻh)}@V>~m:Y"hJw\m{BߣVß17:zQ"~9&VJqZzNzF%>" 6;ԷO\ $Xl?7*_݈_kaH^t 8*dMi)P/!4a&qŞσ#H;.R LBbzqFܵfVRƿOBsh(zNh\zlx}apf9i9m9u1Lx1gBG}dsgw7|+WK>c1zmA۵k"""0a%z)"06h>5#13A3~>,Аu~#& u%~|Bٝd(~n~fd,|WK{pMe="6n|$f2վbp:|"mEk~:g/aH놈|R( {LD7nz鋑 #Q׏x-iŧFǢsR3yh"Ѩ`>u_Oi')?^i˧OHl?v,ӧc….}~aynCÖh#ZTT<DnPx43 :£0-,m*, 3%hcZTjA5(78P62`(b5G̨ Ǐ+)#?e0{ۯ^0nU7/#ZI蓐~Rb T?{;t s{5"+R e\s:OOӗØQj r'糞}<ZD'_i=ovGOXIS8Ţ+ h }Gq]<} 'cxJ!Ǐ}ḍhР&McJ5oϞ=1Rh?/CQo'?"Nxav/\U6Iˈl,'BMOT+.]ZxQd{߂Ѩx]b7= 쌯{鷥>[?"y % Z)"ݻd:7mz1SުUv+1HMNˌ]`=m9 aGO!&Ch Ŧdϋ(=bV#'RPYߛS*ջeʤte} o3Xz3r6_EDOTqj%"[o3L?SkG/-X'*"*Ȅ$M_}*;IBD<"LPR/5IV"OV&P5v:2>)|5TT7g ~G쀟I$/#|uQ*z ~TQM+WTn? ]EP ~=."Qn$`LN_ [ͨjHyA \S);ޕ&KirLyHmVm*0+o" $!^cq I}}ihHn,娽d#.ߌƢxhC(o$l%H-uDW-+*tK߈~2-lw >S6Nj it%??j='~u[vb}E[3})E!/ ROvgEFqqdjF[7VǑJ{WGӉ Lt/ ?GP`Ğy:uTs2+e.ӧO?|.#.vRvصtQ!j#WD߰qxvORpb5w ƈTZ$ϤrNԵi>c%l=#eB`:u*i䌥w(ѭ?Gdq%~+/ -qHUD^ßz㹮߮cc˄X5!ӧ|$wZ?`2^uKC1XQ{ )5_E?Q@tjJ)J:˸eKw,| E3l2T^ZRnݺxkpxJ}vRM"(FX\KV#8L ]#0c -tFq7F%cbЫy3jc9BiDss(_Kˎ;tzq^Wuܥj?i"1I8KV _9{cDA9O]a3yˁC0ve)ssCPw,=ޢ·/l8;2毣৤&ؔ}&"\qB8IT<>&Ȉai8$ţ38v#:FnذKEy-erˮd$Ik9]!0d2*go|]֭D~OAlߗَOo};<^5hW:?Z}o>s~36O3W$@_w.ZJMw.Z~gOD)ZWh)u l3#Q?Mh?]-u.Z$ +'N}Vy.1Di!)v|BF"gmd4nNvm)Ms2.Z'/ ^s<쒯%}ͪ~?M4O-_M[]Oo،x }"O!&Hs~\Z; }FgKJୠˈxFSy3=h5:S礂\ qzXu0G#4MrnQsqo%' ޳D"~iI3kh3j'y?O4MeYa.Zd|ݢjh;󹍟UG^{-dff4M/\P(gw|ݲxR-QՋ CEb1ܽ{Wjc ~Gtq] ҏ ZlRno=rf͚y!55UI,ZJ@Γ={6N:LgΜH7&X9  ͙97R7"]f%`o}%,d^{ͶO;k= n9 D e#S ?~Uĉ C*U(/^T+Zl,+yCiCA5[KJ7o?Сz?^ÇȺ~Cn%w5\;-ƍ샟OyOGsj5?G˷Toj2doߎt;ZF[h!*Uٳ'xciNmB5?lD;4V/U ^vƜuD?dd˪%*{DvF:6W~~)?r'|UV?a͛cʕ0`Z/1t*g}9:V/U8w1O|RmGܽ޹T-S/5?ҵD/qW7ydߡCiپ޽{v}ݺuѣGѡCev)?$zн{wrѤI\rnq}kР;oJʗ[)\kQ>vd^pOFdQ[Ǜ8+F>E*ݹX+0"g`"r.>3O7++WW_}|9믿اL۷/>s=:_~er^xQin:u1c,""em4A彠F|}}\dels]lE˙Wo%M_x.]R ?`6N7_e]Z"\;w?y eŲI¹IFQ+JŋV :c+fٝ O!{c!v)#Jre Q_E c)z|}HKg~, ~*c(n=s ;⚑H xr[С%a??):hQ& ƴ@^Z&$˗I.GQ(}K 9Y@{9dϵO^111⻓LSG(ڵ-妠Úo Ds1(GQn(Qdsn/Ч7#Q?^? ~5Ǐ.lݚCw.j~6JA9̛L~"Q =zTF|? lˊ] tҲsKQ~"Q ?.]݅|jkSt j^˗.E~?rE{? ~E~#b F">> ۳ ۖOĦiHN "~UM#0(/d`=X5fcfȼ%F/OŨ ؏E#((% 96 H?k~AR(,>M8cx܈Z$ڂaj;E#((%Z1#$2V`j1wݺ,F*Iƴ?bn i&_hs7~/E#(8iP`n'LϷ*X0iizѽ[uW.^yΟ?/F)^i5 ~(䰩uw܁ߴ^>Hwi47#]–!x,_ZQ$!iE+˦!''j#g4$,K~?hɶ}͚9޶GS?cX<JOC ݂&hfe{;o𭛷d/΀uj; h.'d?7YO<2H#(XaF 砏G3U7 6uQiJ]}"sOw 7-r*gTߓP, E#(ʝ4lDk/G#kJkB 0coaȶkBV"""QV5%ltG4q]sGW¦qe ߂ſſoC +-\rǏ"<|EO-,krhPˆC 5 ~?*.V s>K#kr9)E֟bB8sҒS!:q" 2 ~rI|l|>&^B-;rW)L~?rm t ~?ctF4FXom'⟊[7p.Xl9/FG#QTA]; )GMR k"cylW~8}ϜSߺuK,H~?*(ɴ캥}{]W.?*?ΕX3~WOenݾj)ݹPGQTu sy[gO!3 `r L 1%E#($3k3g}=?E~?ran[~a="Q?|VC~m۶HNNV;Uƍ3"]`\\2L%Q=|4hq|G3enHz kE-u.U8W^;_#K\te% kѳZVrVʙ"l{8p :v;vuJToJPN'F&GQv-ĵUx#u|.E~ EweW#Q=lS [ʕA[ċu'~ ~mp%ľ}ve^۳gazB(J}}ӕkt?ow_~_|hPN$PA ,?"tT^رc:th|>L?~by/J#֯_{VlGQ%7k]eďgMD{iVöW^¥R_A*xPgd S*V~eU/E9#ٖo$`6gKۖ"hpn !-[`ޠزjn"QCGs)(GQ(4VMDV ~?"~Uà6m DF>~E#(%FRm2hG(GQ+!*~?E~IKK+W~~?s.L~U,tФfWGQ~U4~GQ?YCٳ]"Q? H>a]o~?"~ U޺E#(G(L_kH#QG|Px8P&p2G(1D˄hr"~v2i1]Nu;G({Y.ԩ^]E#_ZZΝwQGyWHA۸w.ٮq}wZpm,ҾgskG(5ZƎu"2an}?5C~bLC1-Q!ݿw_4qxp*g޾ZĢ?F~?E9}@<~j'z𻒩2{CE~?q}b^h^7>YA~+g"3~[+(G#QEٓ. 6Dom:ؓi^G9~)S_.:GtD ,QG UWv2{n N=09(K=bݞ<B LC~.UƑ#G~T U.x1p.v{?*fwtO퀦(ӊL*R? _C}+ZEDDϏGٌޝ9:l,\ t&Y|hkp*h;s,F(E-02iX򂗑5<_nH#wލW_}DW8Q/eLowޏ[X!!Lk33K u*II}֭qo,u͛+V6.NЁ,`sNlذ!gP6$*ŔG}om]{t: -VGc4L&łhR"se-rg2]YPu9-4fĴBb>9$"r%Kb͚51b!'OѵkM:@+_x%E$+C(F(g׼╳%PHh~B㟣PeU96G6hLkdMšZ[g bZ3 `fP.: $LJEoɢ1~ N:EsB2*a0w.bױ#Уc( x3.^ ,*w ϷgFݟڙhx*ZdDuQ{u5d3YF/@Pk5X3oWx~^ H~Υ$ݾ =K.k'Q*hk0!>^ ޘ)‹%kϣšR8{s_4iq!HySIE xY֊;RG˫$܍ 4kݸA~??hGxig |p%|YF4,"d5u(Gs!^+w?6"Q?\2' 5d~. )OvدjKxӛ(TcR?O/9Bv{~\GsW;+6OlzApf4DFQ?_?9vB uBQ?;E~?3Ζw*T S&Gؠ(GQ?ouk]bp"~E#yɨ?k~?E~ ~ׯF6 x"~E#yɊjՀ t)Gswi0M#dG@ıGQ?#~ňOq33>}__A~?"<$ծ d7-G(#O;pbH`f^G(cOǪ]G#Q19Ë"~E#y,-Ztܼ "~E#y$6}8\E#(GT zH~?"<doY3 ^Gr6<i<?kl'#}~?_B|eiBĤ3'hYL7.Q?9e}G#o6l6}G hdO98_̧FI tAEӨi뵘l_~x[ת04kYe&+fH#oʔuLQ?Ȟ!ϧdÑr PEr^ &ρ8[:ljO ~ViZ1l(_uP*9(Gs&'KtHejMo2=(* GWue>PtPu+oE#9~y?9RQl83FmTafď":vԥy(6~}(lNURfa~di4" O}VR9`eb~MEϤސGÇ7`BE(gOyq-%tP5*1ÐVa¢6KsXMC'# J5Gx((-aݨ(E~?˗W_N`~"<"#yaQ"Q?ǂ~8Ν'OxaQ"Q?_ .T`ر>0 IgE;w M(A|Zh3楁%={yye[(FߊLXe ~9T>K&gSagNT%<>hS̟*^"Q ~aD1H+Q=[Ҏ8#>z—jҘ,hF>m\ ~?9:_/ (৒ԧ?̀J~ͥhydpevPCL9if3 l{g4ގ6~gҖGsw]*>YAQrqStKXIδGZXikgO-5k͖,RB#h_@BoEܩ@e•Um!r%ڷ׍KQ"#p$~v |=pO[7c"Q\KQ%_1?c(G(?ٶO0>/"~h𓕼m@~e'Q?ʃo,`b^E#(w6@f&/"~XNOQ?"Q ~2'vm(G#Q?/.7_|"~hQ~~b ~F"#۰hЀóQW,l0b8r|*Gꤤ$:t)))댌 ?~G5LKOOGbb2M>N:>q:_|e4k?>_Χ6F|Ç5W82_W;cH#믿Ʋe˔Z-ZѣѤIǎ ___q!k0}teZ׮]1m4kz?ӽWD/'OtJ7w|7%&&G#Y?;(0 A< P "Q#b<GE WD3TA2.*.:BpIP$%xztWWW#d+>]*WSOj\kIdMB6$ 766Woذ?ݽ{ٺAvtt>d~ȑ̵?/?KVE$j3y 7%)%"cOm*6t}MRP.T3Ra%1 >_{HjkVɢCoůDaZ[[޽{ݳgquuFVVZ^~njuW0#8fMvl2xLY>}zH݄ ܋/ܨQLׯ_ڵkwLϫ%Nzݖ&~Vk)T]-xWf+uKN^H'+x#~_j;v[`{UTرI5oҥ˶M·yfi&{΍UޮgYoU7ێSK/V -{jo߯<.' ~_E@uϙ3޽뛐f)/Z{f':c|m7o{UjgΜizA]uuu6^tv7nhcF}l3|jI'4M:u;w xy֬Y! T8.i\D-Úv&WZb3růdH`rKe=!~na._ܖ{UDt8q.NWFͺy덴a@۷RkUׄ޹sSJ=ze_>,Y޿V\i?)o޼V.^>ߵkUDѣǏ?*Q%h  ?p챺޽}SA=Ξ=kTzmXKv-E.=_ 7kZA>E緪*ת:tȭ_ڬ%R|Rڨ í*^*!~+QuD7GUޟG-;n8 6[l=Md۷o%u>|hݍ:Ǐꔯcx jL݊+ܭ[lrr׊*~ oc[aKƉ'L\%ْs8?!~׫ը'O؂/_fʈdD3/]d2Uqv_oIfQ@I͛|xuu%jRU[%Ujf:R;Q[cluMHm"~ ~0ďB?C!!?B|B?cK6 O7cMjnn2!}]kxg"~Q~}ft#ք+UbZ5;# ~ЏOiʟtf{җѵkw&GA# ~GA?n,## #)X!`?BA?BA?BA?BA?BAAƌc8 !$Cz*~I!YPABC?? <!9IENDB`spyder-3.2.6/doc/images/dicteditor.png0000664000175000017500000003000713003520702020464 0ustar carloscarlos00000000000000PNG  IHDRf(Bc cHRMz&u0`:pQ<bKGD/IDATxtTսZguxKD04ODzQX DGW0"ՠE6>}Vʋz[ͭD\.o=E/! R)?ծϜIfB2>}99mJ9Gɺ3f̲eV\ @7dNJ'귤?xnQo9C2'I$yWtsC^iO*9 ITϤO"@B'ՓiO~IL)cf@B\pO҇rQ/nn 1ߝ7bXg^{!KC҈Ĕ)DH?Ǔ|c=c;EgL^V}Uߟkky3F n%uf 9%-fz]˲߹m[>wO罹|B6P<4-E}vPkWz[~o\o洹6\J/j>=>;}(kT 9:Nb4 jb(mJO?]eص^L5yy]yB.Y=PdɴiӦ@nA]OEyCKPpNSz"P?Ubʔ)\_ykoVqŝ玨,+qb7.|TzƌjdkmmeG^y9/|~YYckn6ns&~j ] 70#}(x\_HJ 9rA«U])ws \N!E%~tz=[rq/㧝noOo?۽'yv-/dr=}IEg5{翋 #J yYl_&J%X?]5tS_0mmV_":}XAѤ[n;!DQ}/j4\}iky|dn^>K͸'Lp? Ч.g8>?$Ug/\N!3HA^?+Wr )fw)=z˷spSnzqaAQ;Ixdb[-1-,ֶ񋃢 V빜-aUYvK++R.vpÌ Ί1"Y#Wc%^<ݼ](1"ƶ+?/[l'*s}qj2bnrEXQRvQqgci5ֶC( 3͎E#G`4>j r@FyǾUO]r9hDyE~oQep{x1;{~J7\9 I\YXP\R!^~s=7튳޾@ Og/\N!Ea7{NZJޗtW3rjKz,)$g;o绸Jpg.bFr91tIE={33=>ga/ܯ`4^z%}O_t]I_2 p9b/KEy3[plMH@ }>@>@ }>H@*N8~r /| [n}EbHׯ_oQbHh͍:#~BmaQWgvϑ?BH9"OB S__pJBe[NA/A(5j6CT/QHSE"y!s%ZCFT9]7~F1$ ݙYr}]̴ tuѩX:-w 釲Bmw=!ض Op 5o=.jzRjhOw$7̳>`:ghR/Bcm<1~V9doְcQnFQ Q_u3]Ng]?UWS%>8~DFg}&zsϫP7xԄkv3o0f_c۶mvY ?{7) X:;P$# 3w>!}<>f҇ry?EB>B3}H@>nB҇HG!}C@\< }H7r׍DƯkv^9_2,Bzi51RAj%7mO=lQ7Վ[۔]73TO*Ekc dU*"c HS_=hM}f֛^br#v3\Ya*L$G ט r''#-zpFSoUPRW|f K,}*}"}f|Km>juԎ20JkAqD9piuc ApO?7旳JtN[.6Tqg{ D2H_%bU8p!wen&`MH)@.)5,ziNS)eIL|eV9L:]sΈ㎌G= NӀh&vnI~>Ə>?>y䧟~J=9_|?YBmߚM;z3zi3H3}R}DτR{WVZ/hINIC=)!}Uoj̨Oygټ^xi_F \މ[M,t;vy/ },_ HgY/}UҷR@K:Ԥ+dh.atuuƒ|Ś5I+$&S{*ֺ4V$-FG`둡{$NpDSNЀXi_hj,T K }H҇#@>!}H>H҇]b1GL>C҇ }H@>HG!}# @> }H@>C>C.u#뚥W61"_+Q ڱck+xI?Ye}5ձk*ZL)S0Ҹ?MgjVl`! )& ' O$f/m#7&c]{JMxH}-Ys1Q;ʜ:X+ɷ=Q6z9HyphLd擾&ȴ- ["^d8m2;yE~8'{',OT4^RTbN7,jQ%SLCg"#m+HuNvguŒaԍ7n[ov1)zQc[TmkA^a;V c34u @f$o9!7#sw+}E) *%XRi/?nK +JkmKvO)Hfq(7/ʱ$(dsFT$u-wdt=Jw9لoi@Y- C,gI /ְ1ZK$&7vYPsWQ^N#}J`ЖVVK!iRSҍK/wNXKV"0uXI4 S2n\z}{nZ_=6NcԔt'YYӗmcv2,dAv!E**͘So@-A{Ogz) @w~m; >Nr|i] HvWqHĉt֚7X(}k۹M-eCM 2KFj"CJ_S_Q9;Ձg|ffp׵5K +;5"Jm;H$C7 m6c.\eh+K]]]u𻾱$_lrM m۷79ړU-nON+be;.GƧ"S;N9AbbJJ3KK<% n,y ;ݗ-CHE/.d tR#0@҇ }H@>HG!}C> }҇CG@!}HG@wo@f3}0Ӈ#@>!}H>C҇ }H@> }H>C>C>BK1qH4~ټnu^Pl$"퉑^rE))xO-ƀ4T;vlmSvP~zEkc_NVEy9dWNW/cuR⺘ՙU%^#U*]ODC=5rc"Ѩ,}L' iˑwzRҧ'K_,}J(&Ajg1m)!pZhE0~;Z9'6ɻ.F)+ ϼ- ["^d8m2;y%|T$R*Z!o])*ML5Ivqg:LƜ6dp{3FVI_}#}i.5QltTfEpoRn/"=rQ{I.}6[Y;Jg#q׀Ey]Ӕ>8p!wUKlQ#}R\{&⬨HK+#k'JWiۭ}=lkSVD_УWcU1deDH_F15|pbd}k.~g l*/]~&7{zKKe*XBZ&cR튧wgIn5yO-}L?xijttIHI2eU_z$z%O:z&߾ 2(H?+k@UY+ߝ-^}l.+)G'_1Zz$c^G$}LU׀i<82(H? ;qK)}穌R^.f3)e4ea!1K_]t^)R{$7ǜ/T#Kp~i",^a>}ګ]/&hH>%n6eH$!i{(}!}H>C҇ }H@>HA!}# @> }H҇]%Ё>L3}!}C> }H҇#@>!}H>H҇C>C>oLD"yx'nf7N`}rS%M/So.ۈ sczF)ӂN~SرMٕ~Ce9<¸/6ayʮuPn+󚵪2,}yk.]1W"S!G)hghף κ!s`[ҹ9CP:T{iN ^މ[M,t;3k(ΧW@H髶T%Wg#V:[ Iiڧ]p I עulMS ֮KMG6%4z*75 L#(}ÈN^@q yAv5vBm,f`6Ēu#S4mbJ1J|ZroqԏgƧ|u扩@lݹ_rV7rvbfOAƮ2Jxd~F4#@># @># @҇ }C> }H҇#@>!}H>C҇ LI6:0wL!N>Ot }C҇H> }H@>!}C҇/KYj>!} }CA7&"F׼n7~]e'>9M1V񉄔*7~]\]/-O)\|~SرMٕ~Ci'OxSBm> %'N߿_xٺu>(C҇Aw~0Y(%- }C @Ǐ'!@҇AH(g[1>!}#?p]6H@>q,@ό8%qKtio@#=`0@wF@8%$}=> }C)}->!}H>C҇[[[A҇x`C#*D> >>H@ }>H }H }>{Aq"ס>>AjغuҥK暩hѢE;#:,-^xڵ'}4zgԣCM&:$}{}9#ꗩ>.JS;iסC(e8__ҧXǩG/H`G9A=~K9CF?n]܂zD }h=$:N=~AG4Qw>5ƭ}G/H`p߃'އFl>׊N|n1/~.RuGx dT7I 쏷|w͇Yvldlm!(VD3 ؋KϞ=|Iz7|tu`TG/H'˫:s͚;Ez73uaTq+>-4Y`E.wjEV?u&Kǎgj:ԻNotfM;H/,C=~A[]f{F9+sFhtN$\N /xLNt3jMζeKdI ^\r с.~ccÇs#0J}#>?{w9sY XK#)w#0Jyeٻ /G*^Y,g}s#0J_uɑ?L|1$XWs#K~bopxs1o.+Ho__UUrJc׍7hH@!}]t/Hİ2k8$8@^C_>H@ }~9~ WQ 籤 O5nQ1IENDB`spyder-3.2.6/doc/images/pylint.png0000664000175000017500000004164413003520702017662 0ustar carloscarlos00000000000000PNG  IHDRK(/} cHRMz&u0`:pQ<bKGDC-IDATx ՝&y$dLf2yNMfi4y h%1"fHl$,$*LT4j@YdƦYd0 t5l#Hso[u,ܾrvݪ:WS_JKo&} ( `_e<`TiȾ¬)'7:})&zp{(Hb_Piӭ.P+t83B ž.~9̾i] :P{2/tx^}۾j25]@(Ǿ2B` ޾ޤ}%21q8tm̳_p}32['}-a{d_o3Ⱦ}ڿ}dTq Pb/}/`_ `_ľ@*־ Ο?.y=#/"žVx7x#Μb61sRn޼y_Ó3G u,Zְe˖ oۑ}lD3'occ75jO_ok[_b+DoВ &5 پ }g,Ӿӽ}!|{;}ҵ^1bÆ /^pK.Soq!\mݳ|N|,M(EӴT>uȿXMʎS!wYu<{"+wR{*Ss7W>y}\zoF,e%?jժ9sL0k֬ć)S NAW4d)ӹP"0y@3w+XTƥ"/hCfNtg1o_qxȘ~j?U7sc򍯿6^m?6 Rlz>Cw„ >ʕ+7}^LݿǍ'4,fS8eX,æ4fd?},\;-,Z7o1&+DžԡPMZ4(}/Eޔ]bu_?E/W>oZoM zt[6M*D:=ڷ3O?СCE>3_XU)5Nfv5ᮐgmtm0X(QEY@)16M)A)jb߷~SmC`t[}~'͕=s63sVTSi ;[Iʾ{3\coyJ|>W7_U?~dՅ_3Vn__>4_~p윧&p{.lOc\Y'3l@]֟V]{ソ W^TM;r pZ_b~Ws%CdfpZjhVafoV (Q-_gn1)N)I)oh5Mc,=>Fq3z͖]JlOuhWmV,oG_x?u}ջoڪR_|xΆm+>tozWnW㆚XO_f;9"b_Obyj!C 8PA`#9DWmv,6l~A"c^<_..*\ +=r@k]g~fxa_C~$(1Iı>K'dVw^}C6,`^X?iԡ]wCOJªM+&eH' Rչ? |C\dT,_;E?xƦMcbxW?c@-X@|p/Yz^,llyi+84;vgXEX+{'8iNK3F}MtrkcgJn5 JS>df+yBEW'}E7lR_SտoTˆ|r첧?U]w||7^ ]wyBnVvpt`Ao\?e {¾k֬yׄwō_⦯S 1+ d~ި_ fUue@%6t}Ҕ-m+·}lMc|U;GTg}\>ه?T^#< D^(!]?Sb8Tor 0R4ޓ,e-=RKSJ~6!')λ}u/U==Q ?zQ/x2O[Xjn1 v.bŞ%^V}|+h,͍ujv\~ӫe;ͯWL1YdSo#! ^,T}w1[6o]au?13cD񧘸|2x U%/@ !4&B*"g@RB{/-h2 }/ }ϼZpLG׈okFnz ^˺~N_vn"ga 6rGv[ f_ץ>iU}į{8+_{ ? s⫙z1d=gނ7Jc\B*HK 6Cnlj : nY-ҤjKm{ Y6Tk_F/_\dTewjpbA|)\bz 5 Hޙᛖ-FjKJ3vt#Z=X$#˺󻶖?M;hRL҄O ȳ?gnA9֣MD})[)LHdH8eߓ4=^Q.f.vrhlѶRocR܉]4=D݁V}8=/eե?[[ /|iφ@ RžE2B7y{ 8H\VUORuȿXMʎS!wYu(6"цkkb5:½I T"lJv'phEUJ Jma\*R1d椛_@a_(}'X4̒VҸpg|훷XRb|P(&-@dNQ2չNgu&ߝCkaҐLi7ll{WRjjr%JVZ*QEY@)1 .+z)jb߷~S͘t[D3I~>S[ڴSt@Jtm\`hbPf-;eLW:9H7~ۗ J/dx RZjfOK+uvaJIJQ~+F TǷpMMM7YsF)za~}g/^|bߟ4W7ow7x X nWY$mbuYz#F@)c>eڰ1zmyDRN6bsZtYU,=iO9`T.LpA-Hg~ȵD\V/?^yPҁ`mklWAKc_)O'}.!N8g;پ!nh0V/w|z~̠0[1~qS,,0vsDn) z%Lی^` n_*=N6L)I)*cZ'ttX'lƨs&wRRp)`F]I-RzQKr[*MkcM)pRvB ,&T8cJPzrNn^ҥ1v!qsҿ+TG]Y ))ğHqطX9v9]8UUꏘ(j+;EJ"8'ѹe?ygϞOKhӫWV8Q9iVm0D9,` Юk+V ZvlrO1C&IO> KIU=S /@;H+ժ}ݟCAjc,OG˗^9^myo޴7Mƾ8(7?̙3o޼744,Zhɒ%b,F{-_\ԓ ľVsN~S ^%|իWw}pط`,X@1-h,`Ǿ^vBa8 Eһva/w=厑W~꾃xIΙ7 ,I 7;$Nߴ!.j,h*`bľrjBY .C]a?0`rg5cߡzzw;;+.3f)?mVfsm2li/-Re'ލPd}ȑ#oAHz=y[Ύo8{98/Y9}mlg4H4$(02- E}¾q]V"~Ǽ#_rJgeΒnjކSْFWnK`ߢľIo_yQ;7cqv]) V{&V3zuƾطIo!g޽{ٓޛ:usw# ľ\vԩuWⷘҤIB"[S_wurV]l# ľcڴi6mw|+ţGsΝ%Ծ^Sg˗D9EhHvآ@5m jMjDn_}vyAJuc`\|VJFٔyZں7YcceR|M@nj}|zn`A.c0W饛,ӻw16Oq̘%PǾi-L0gsx dj`KҜmIn }5/)->wCq= fNb_M7-ZjzѮǔOUO_==mYVzkW4\2.9Kc_m]g?cRW;žz & MٳgE^½uu ztO:f`3͵P8=~+LÆH Ծs5Lnyd!SOo]깜9xXE^k~WU{D/5֍׌湥ϝ}ի9@[0,XuV18YV|ؽ{m&M;Nf9@[Wt5]U;vugo~Nu^.]> wKYa[Q;E-^ѱ,+b\{!oA6Ǻ~Ze/杜Tvk[aHAbhUccpݲe-}¢uW6Zks̙9d8~xHAbT}E+zg^j4dwO~7W>56?,/05eUslX119{0lERοa7p<+Rxhݺuvrs!T=w.w;WԭGOrμ4uwV`ɢ6$5 [6\(cUsV k`YTa){ Ta[nѣG455 .C]a?0`rg5cߡzzw;;+.(ΐ`M?29m0˛9U sL~i Y۞->|XĻiHfa 6$^>{qǷ bUZǞp-g7ͽ]?,F7xBp=4AU޵DmO ۖ `r}n_}Uљ,#ZĨ搂ċ`+ m[c^\W/zqv]lx2gNcFjw%ajdZmKj1իݝ FIb5mH[+ eT͚5kf3f̞=; +"*s xFv>#sKUJQ>R)=p>l:cvY2fV 5 }>+oŢYƘ_Nt坕R.áȮUMe:yطoӡo.?^wU|()5O~t8E^if o+J6z6ű: ľfZ[1;[nqWZwM{wmލlC0Vva-dfߐ޼kKqOoFQ%NMsc>S&[=÷Vac&&]W%6_bm9R3㽔vhE=~zqޖeܾͧ <n_9b.T7 ;lI&Lny-5Un;1ͯS~-&spp91ľEбC7Po`{Ķs:IĽ< @[W$+/SyBǔoo<&/ `_b_b_۾cߊXBق+HV@! 3/}Ŝb&fD} w;VrW׏uo͵ǎ8!/!cU$彐1P/BZڗlmRKǶ] Wi2"o]JR[$͆z*܄g wl:[vb)}-Z64”8COxiC-3Y/}MyR7Q~_cnݠJfKQR&>k*e V!hKT/~l2`_VY,Eo +ط/o!YPvo~w~;b[(/@I!RnF }~JT~q)TP^'_*dCS)N 0i?0~|$@j4+)dڛCܼ+ ^Ak[b9`){{YVػb{};H;~Ҁ~^g}V'@;iJzҴUZ-Z2Ǿ!_\ wӇ?Q~yπEF1r蒡珏nuznC ͖3gF JܐYCmLCZ%4mm2WʚUg&JךQS [ԦW/?$ VN)RbWrG+0w~] Bؕ}1s[J_vjE/W;@[qy請M?#^4wOd}HdZӾz'f56RR$! ez ~O}577GVjٽ㵥h[v*GW)ڼKä0=cbJSW(٠fbWs<_#\'K~2p 6 s'uUmEZoLɷl4dm)k 7tFi[xͩl-mQc_sm diKk/slx~t;;agƦWڄ}+,:wjWߺ7{5͟?Zyhu}x:UگPeZ@-i}u'|zv =@}ol[4@[9}g͚5C_Lߌ^ERg^KSP7CܖFmtO7XY/]s6KŲE7Q+^()T-u~CM:OzbU5/v1f[F<7θ?qo[mR>b1w19 6t up'/}=Y&uey6&1^Y_`xǫ:]^m\MZFKKw(/v}gϛ=fz+t^oCQ/NK 8o}Wm{Grg#~#]ص6^ۻB7w]/y =9o~wG}/1do\N=zx=G7fSyo9bThM*`˶ۆjߪ8-RhӞWRfs_AͻRA.Kf߂73E9s>Vi=1%4joU{Wj#ĴogKd_o! _[+V}]p\طeH*|dzIoG}[[1;[nqWZwMt_,@$2se06FB < nsCs[IZ}Ҫ3 {l`{1PiSjb/%6&_;*XU}VY^vy‹J+$<^J?BFAɬt? [}wݐ!Ϡ c nnd LU|]F2i-|3N7d+[M="Sٽ5h[̾ZM SC](}gH?nFUZ?kMKt)R u11&g}~[a}w7vEM/gyqF{HmХJ&ت[z+fo=zڶx(JϳE{#k"BvcQM%{o~+STl ΤT1]M$mױo|ZԌx/]/uQ)=zo^duA}C[N>U[wz§վmΣ}+8^kzC9(#%ۡ={{5.zA+&:u*wɈU;UMcR;vGuU*BHyԆ_ڧmkMzkԕټ:87-5Ux96}3[*H7~#<y_C޼:B]淋:@H{9;wNtJw@䳋:Diw]%zf4 lݺU Nv}m۶aS?~4,]k׮mmm;z[7Sz为h(r2^ۑ3TX"X1iZ]qc]` -lڑ}۾ P1m!UYHw˖- ]u[b_ @k͙3gf:!Q"QmyӐٗ=\udugx$o+I]<Z6l Demsoyž'2 >kHAuڵͅP=l<1_wP=9YC[%O 2ʹTH|po0-V!bsL e Xa[nѣG455 .C]a?0`rg5cߡzzw;;+.(v}sdNtjԒdUr7UI96T6Mo!g޽{ٓޛ:uswXS]ߢI& PXtD;oMq6YYu(_2iӦmڴIu2t͝;w+İ9@[0zEcN8qժU}oľ6<+~86}K ?D!;7d\?֓7 <Ț\>?sRГ7/@VRĖ'*-V&U\&DvkߤY׳oxPIC{R<[YRE0)fOᧇz>7bEW,P$&(}C_ŵ ^먆q~={@=W5/e $3IۖϜOILv赍Zڏ־,)E3}_!WɅ'}p8g4mX=P hJ$&(=ͦ {!l߾rr}9 #u` ǟR^ۘ$&:ƾ!ᯐmOip-_RZ68Q;m$BJ>%-_pQl&&}mo@y.^K^Sx,!PZ(PFcm#0By_[sgK{|3}*LmV^ﺊq PY-A# '}{يc7r57n8=k oQbߓf=~WN75_sC%!*gwmƤcQoFG:|Uwz\{K_~Sz^+:hɔakYTƿ7GGo#ӟ'ZƎygvǥ-xnc[?yqZyNH΢=< }q$zK%V~covۧNe 5g1ߵ?|G$C}8rm3B:un] .|Ot<۲Io[Ɖ{Q95ϾIs ˺?if䑑os\dG9ԙPeeߤ9\wtRXvʰ_,[)SN<8BL|?>uk&C}8:+¯O~鄉K?{ٲ|v +ǎ=6lZX΢(ί}8:9v/m}y|'`A剣}ͣ,1=gQ}PվI߃K?w^z[_J?|;VQ.*#C-{O>d$`2`_,`_}/ }/`_ `_ }//  y}`_ }`_|?yv6IENDB`spyder-3.2.6/doc/findinfiles.rst0000664000175000017500000000045413003520702017406 0ustar carloscarlos00000000000000Find in files ============= The *Find in Files* plugin provides text search in whole directories or `mercurial` repositories (or even in PYTHONPATH) with regular expression support for maximum search customization. .. image:: images/findinfiles.png Related plugins: * :doc:`editor` spyder-3.2.6/doc/ipythonconsole.rst0000664000175000017500000000551113156675415020215 0ustar carloscarlos00000000000000IPython Console =============== Spyder's **IPython Console** implements a full two-process `IPython `_ session where a lightweight front-end interface connects to a full IPython kernel on the back end. Visit the IPython project website for full documentation of IPython's many features. | .. image:: images/ipythonconsole.png :align: center | From the Consoles menu, Spyder can launch **IPython Console** instances that attach to kernels that are managed by Spyder itself or it can connect to external kernels that are managed by IPython Qt Console sessions or the IPython Notebook. | .. image:: images/ipythonconsolemenu.png :align: center | When "Connect to an existing kernel" is selected, Spyder prompts for the kernel connection file details: | .. image:: images/ipythonkernelconnect.png :align: center | **IPython Consoles** that are attached to kernels that were created by Spyder support the following features: * Code completion * Variable explorer with GUI-based editors for arrays, lists, dictionaries, strings, etc. * Debugging with standard Python debugger (`pdb`): at each breakpoint the corresponding script is opened in the :doc:`editor` at the breakpoint line number * User Module Deleter (see :doc:`console` for more details) **IPython Consoles** attached to external kernels support a smaller feature set: * Code completion * Debugging toolbar integration for launching the debugger and sending debugging step commands to the kernel. Breakpoints must be set manually from the console command line. Reloading modules: the User Module Reloader (UMR) ------------------------------------------------- When working with Python scripts interactively, one must keep in mind that Python import a module from its source code (on disk) only when parsing the first corresponding import statement. During this first import, the byte code is generated (.pyc file) if necessary and the imported module code object is cached in `sys.modules`. Then, when re-importing the same module, this cached code object will be directly used even if the source code file (.py[w] file) has changed meanwhile. This behavior is sometimes unexpected when working with the Python interpreter in interactive mode, because one must either always restart the interpreter or remove manually the .pyc files to be sure that changes made in imported modules were taken into account. The User Module Reloader (UMR) is a Spyder console's exclusive feature that forces the Python interpreter to reload modules completely when executing a Python script. For example, when UMR is turned on, one may test complex applications within the same Python interpreter without having to restart it every time (restart time may be relatively long when testing GUI-based applications). Related plugins: * :doc:`help` * :doc:`editor` * :doc:`fileexplorer` spyder-3.2.6/doc/spyder_bbg.png0000664000175000017500000001571713003520702017220 0ustar carloscarlos00000000000000PNG  IHDRz cHRMz&u0`:pQ< pHYs bKGDCIDATx 3*(c!2JJR&"1HIPEeqDE@AEEPD]PE A@@Py>-~?|6Mogܹ䞢RYz},]]EvitAm۶[V. O>+o>ruuuy?ȯ{,\ gj2~}ELve}V!hPiCMGE$ :lY쌿ug}5JWp|U:?΂m% {Y N?0z%;fNVLiNWGk*pe0lޤQlDU] /BG7 fA̢_}L))(#L`,pF* &}pYVe fO&[.Z ˈS6㲗ɔ6ّRzL㚗mo2%5`cDEE"׵e"#e`j>s=7o޼~A^?yy,Ytҗ^ziٲe˗/WXrUV+jkgv2ðZpa˖-;*?mذ!!'Ldt1`Z mXaжo>:Ju˖-Gydvܙ%_؏>.]͎Yg%w;C\Ӯ]~\r%5dxL0Ft.-a_ymZ=Qau} e\֧OeP^VSN/>#y,%aXCzh"e̘1zcNm۶emJ`aMx ';txdOc=X]gq$N`[϶=ܣ\?vظ6npZ+"l dȑʻ+tYˍ[p Jðz-ӦM+]6:[gx~`aE +Y*'|x?/m3~ ðzm,ʍs)?SyoQ{.%I+M`aۧ/R^0yd²&o?9͔4ưS{<CusKyt9z'q뭷bo `s*:tec j{K\ʠ9aTCL|;oh~<c":ujIp71g=V^{m0G}5|sڶ 1 B? FSV rt6}D2,Qр!i[.=kڶ߹kK}^xkuyQv6 , {*D"P]v%Gtа?.Z>yTZNĘ_:Z۞8}q Actwq5SvBL`$P*tb oO:$]6`"|ɥѱO4] 1a:??Q5n\@O 4&cO0gO=T37.a%HDh#f Fz̍Rl֭_Op.O9׿6sDt)ntN'W{Emhuo%<N!A_ܹΝ+nݒbJ`cݙ3gFF?[`l;lO٧w> _E\7ujr)LPѽ ;B*)"vdr6k1=Iy*LOTe_ivpG@ aDb"w<`@yԨ$OL;¡?9rϟoƉq.z|wptXWCɝu6#2Q[</3a isĹ֭nD%]%)t+ÆEFV۬1΅Y޲D/6mh[ BqRtA6~nнPCw; \ Ѿ#{W4k'?-*eR"z,k\197mٲwțL]t?[-q6m ox@Fid]rv-S Ӱqc}FkLh@ziۣO^g555{~hB^O:i8AݱS nt(I=-?"{]7xv?Y޽4kV vrWW?ڸqf͌Rf&|cнȉn SWl( "&dY!Fo}ƽzrJ67I;lK m)9a%q 69y\\WJK`1A-= _RM ٘ilIK`- @7#r146 bؿ 9vt+lx޼{.Ӿ'ҭ[1kժ-B2;K: ,j!䌣j\SOÁ2oqm6@RQ^u~fhOb6E-v2q3m%d5kB=L2e{vLVW]xacnW KS¡`A(Q2rzU,RWLQlߨ \&a۠AʻnS"l@E@#$"f%Kv/ioMz -/Jzet1CR}Q JĦ3)}`f|ƌ8_ mG=d#tˁ:W_`y16f=s4meY(iDÓ`itRPlAwM<ӤI?Ylc$o[Lf]ҿD/+پ=!sJ.9]L3J"3R&M``2u]gK+Bk#`ʿ`QvԐ`Z:+`2 1!\F9+cSyV,8,c0S1 M7dz^ 9ؽkQ ʸǸԦxKJN(f]*+e\uGbYK1XRHw؂#7Y2@,šb+j!mtQ@=ETW'"vn<C09R50z!m[JGDbnDw:( `4M`#!Wi$My){_#Q:h[yR+hP)l˒pMo].kʼnqT>5'0 DžɃ:B%{ HEt #)቗Z GvWXNT]ƣzJ5c(([a=(ٓM60>9Q:n٧F;A)1Fk*$ùR=pٔp`uly)0JC/~*QX:6fǢ+tP#̐s zh7m/ԡVMd+ *Fq|~ucH6N(O (wwV=>^?DU jqć9HNih;OXݺ?&le1[mmww`eZxaa. ~H)铂 *1+XJ_OJ`?Z`r"zlx>}sn$0jAQ1#4|UHN \zr#nhUx]]=o 3RZ20Ưx `s!`v&[r.D("U͔?4l[6>l0&ҏ O(vpl3uԓ`2G uhj}f; D?3Xc@TE'gHMPD7#,&cFɺ?P)L\H7"d),c9JU1]ZI\06򉁻`Fe\0{K&` fM!Bp `2V.=-pva| ypHfIp&Xd9ZawAG!.;pas.gU_x= &.0sun"LJ\N{"GNe ߿?eƈa>|8a4{Px/DRo߾OC$r1~\pUdEp '{`E.9D E 6Z䫑[(&N{x U`8yE3ȡb$B u 08jQ] ু5e79^:dkFr T)y0.>j{P9jj΅ w{^]v7[(OI'HXVnaB~FAlE]I A̜961 Lbz1,J! EByTVh9UG-*-2D uXzQ"_VHD(@ԪRC9\芢ƶ6\ci#%3Rn'K|/kB?!_Y;Dx=C\ o"9V.h ^,ΉtR65=tP$O!C)e} ؃gftk_E1hxDq,8m.1gY dbsQ:%Lb b3!l%BC:ʿZ-n' 4>4*Ɖ$ x&C4^ Ó q%V*D4ݲd) ˗49.-a *?+, .b6 zBa%a_"< 3_UL*YbW/fՔOfcƁyΖ\Ϙ _×$.?c WB7 XF&pI~3^)BiX/(-aNʷ &Yᡔ%4|Q 'CvfN1aB6\A`|M"h FAG(^elqʦdZoa/HeBߢٟ=| [a*Hrlb?`Ibr:9!g26 3]Laf܎)_Y~tCx!< &'KQܱ<<ﻊ`,mHVBU.la@A^8%=hXtEo X>:P1/ ` K^vc #Sv#6wSED*!4eG[%wM0."=I!JOo[IENDB`spyder-3.2.6/doc/historylog.rst0000664000175000017500000000031713003520702017315 0ustar carloscarlos00000000000000History log =========== The history log plugin collects command histories of Python/IPython interpreters or command windows. .. image:: images/historylog.png Related plugins: * :doc:`console` spyder-3.2.6/doc/index.rst0000664000175000017500000000250213156675415016244 0ustar carloscarlos00000000000000Spyder - Documentation ====================== Spyder is the Scientific PYthon Development EnviRonment: * a powerful interactive development environment for the Python language with advanced editing, interactive testing, debugging and introspection features * and a numerical computing environment thanks to the support of `IPython` (enhanced interactive Python interpreter) and popular Python libraries such as `NumPy` (linear algebra), `SciPy` (signal and image processing) or `matplotlib` (interactive 2D/3D plotting). Spyder may also be used as a library providing powerful console-related widgets for your PyQt-based applications -- for example, it may be used to integrate a debugging console directly in the layout of your graphical user interface. Spyder websites: * Downloads, bug reports and feature requests: https://github.com/spyder-ide/spyder * Discussions: http://groups.google.com/group/spyderlib Contents: .. toctree:: :maxdepth: 2 :glob: overview installation options editor ipythonconsole debugging console variableexplorer help projects pylint fileexplorer historylog findinfiles onlinehelp internalconsole Indices and tables: * :ref:`genindex` * :ref:`search` spyder-3.2.6/doc/console.rst0000664000175000017500000000226013156675415016600 0ustar carloscarlos00000000000000Console ======= The **Console** is where you may enter, interact with and visualize data, inside a command interpreter. All the commands entered in the console are executed in a separate process, thus allowing the user to interrupt any process at any time. .. image:: images/console.png Many command windows may be created in the **Console**: * Python interpreter * Running Python script * System command window (this terminal emulation window has quite limited features compared to a real terminal: it may be useful on Windows platforms where the system terminal is not much more powerful - on the contrary, on GNU/Linux, a real system terminal is opened, outside Spyder) Python-based command windows support the following features: * Code completion and calltips * Variable explorer with GUI-based editors for arrays, lists, dictionaries, strings, etc. * Debugging with standard Python debugger (`pdb`): at each breakpoint the corresponding script is opened in the :doc:`editor` at the breakpoint line number * User Module Deleter (see below) Related plugins: * :doc:`help` * :doc:`historylog` * :doc:`editor` * :doc:`fileexplorer` spyder-3.2.6/scripts/0000775000175000017500000000000013225025007015305 5ustar carloscarlos00000000000000spyder-3.2.6/scripts/spyder30000775000175000017500000000007613026261005016626 0ustar carloscarlos00000000000000#! /usr/bin/python3 from spyder.app import start start.main() spyder-3.2.6/scripts/spyder.bat0000664000175000017500000000003513224740762017314 0ustar carloscarlos00000000000000@echo off python "%~dpn0" %*spyder-3.2.6/scripts/spyder_win_post_install.py0000664000175000017500000002447013026261005022643 0ustar carloscarlos00000000000000# postinstall script for Spyder """Create Spyder start menu and desktop entries""" from __future__ import print_function import os import sys import os.path as osp import struct try: # Python 2 import _winreg as winreg except ImportError: # Python 3 import winreg # analysis:ignore EWS = "Edit with Spyder" KEY_C = r"Software\Classes\%s" KEY_C0 = KEY_C % r"Python.%sFile\shell\%s" KEY_C1 = KEY_C0 + r"\command" # ability to run spyder-win-post-install outside of bdist_wininst installer # copied from pywin32-win-post-install.py # http://pywin32.hg.sourceforge.net/hgweb/pywin32/pywin32/file/default/pywin32_postinstall.py ver_string = "%d.%d" % (sys.version_info[0], sys.version_info[1]) root_key_name = "Software\\Python\\PythonCore\\" + ver_string try: # When this script is run from inside the bdist_wininst installer, # file_created() and directory_created() are additional builtin # functions which write lines to Python23\pywin32-install.log. This is # a list of actions for the uninstaller, the format is inspired by what # the Wise installer also creates. # https://docs.python.org/2/distutils/builtdist.html#the-postinstallation-script file_created # analysis:ignore is_bdist_wininst = True except NameError: is_bdist_wininst = False # we know what it is not - but not what it is :) # file_created() and directory_created() functions do nothing if post # install script isn't run from bdist_wininst installer, instead if # shortcuts and start menu directory exist, they are removed when the # post install script is called with the -remote option def file_created(file): pass def directory_created(directory): pass def get_root_hkey(): try: winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, root_key_name, 0, winreg.KEY_CREATE_SUB_KEY) return winreg.HKEY_LOCAL_MACHINE except OSError: # Either not exist, or no permissions to create subkey means # must be HKCU return winreg.HKEY_CURRENT_USER try: create_shortcut # analysis:ignore except NameError: # Create a function with the same signature as create_shortcut # provided by bdist_wininst def create_shortcut(path, description, filename, arguments="", workdir="", iconpath="", iconindex=0): try: import pythoncom except ImportError: print("pywin32 is required to run this script manually", file=sys.stderr) sys.exit(1) from win32com.shell import shell, shellcon # analysis:ignore ilink = pythoncom.CoCreateInstance(shell.CLSID_ShellLink, None, pythoncom.CLSCTX_INPROC_SERVER, shell.IID_IShellLink) ilink.SetPath(path) ilink.SetDescription(description) if arguments: ilink.SetArguments(arguments) if workdir: ilink.SetWorkingDirectory(workdir) if iconpath or iconindex: ilink.SetIconLocation(iconpath, iconindex) # now save it. ipf = ilink.QueryInterface(pythoncom.IID_IPersistFile) ipf.Save(filename, 0) # Support the same list of "path names" as bdist_wininst. def get_special_folder_path(path_name): try: import pythoncom except ImportError: print("pywin32 is required to run this script manually", file=sys.stderr) sys.exit(1) from win32com.shell import shell, shellcon path_names = ['CSIDL_COMMON_STARTMENU', 'CSIDL_STARTMENU', 'CSIDL_COMMON_APPDATA', 'CSIDL_LOCAL_APPDATA', 'CSIDL_APPDATA', 'CSIDL_COMMON_DESKTOPDIRECTORY', 'CSIDL_DESKTOPDIRECTORY', 'CSIDL_COMMON_STARTUP', 'CSIDL_STARTUP', 'CSIDL_COMMON_PROGRAMS', 'CSIDL_PROGRAMS', 'CSIDL_PROGRAM_FILES_COMMON', 'CSIDL_PROGRAM_FILES', 'CSIDL_FONTS'] for maybe in path_names: if maybe == path_name: csidl = getattr(shellcon, maybe) return shell.SHGetSpecialFolderPath(0, csidl, False) raise ValueError("%s is an unknown path ID" % (path_name,)) def install(): """Function executed when running the script with the -install switch""" # Create Spyder start menu folder # Don't use CSIDL_COMMON_PROGRAMS because it requres admin rights # This is consistent with use of CSIDL_DESKTOPDIRECTORY below # CSIDL_COMMON_PROGRAMS = # C:\ProgramData\Microsoft\Windows\Start Menu\Programs # CSIDL_PROGRAMS = # C:\Users\\AppData\Roaming\Microsoft\Windows\Start Menu\Programs start_menu = osp.join(get_special_folder_path('CSIDL_PROGRAMS'), 'Spyder (Py%i.%i %i bit)' % (sys.version_info[0], sys.version_info[1], struct.calcsize('P')*8)) if not osp.isdir(start_menu): os.mkdir(start_menu) directory_created(start_menu) # Create Spyder start menu entries python = osp.abspath(osp.join(sys.prefix, 'python.exe')) pythonw = osp.abspath(osp.join(sys.prefix, 'pythonw.exe')) script = osp.abspath(osp.join(sys.prefix, 'scripts', 'spyder')) if not osp.exists(script): # if not installed to the site scripts dir script = osp.abspath(osp.join(osp.dirname(osp.abspath(__file__)), 'spyder')) workdir = "%HOMEDRIVE%%HOMEPATH%" import distutils.sysconfig lib_dir = distutils.sysconfig.get_python_lib(plat_specific=1) ico_dir = osp.join(lib_dir, 'spyder', 'windows') # if user is running -install manually then icons are in Scripts/ if not osp.isdir(ico_dir): ico_dir = osp.dirname(osp.abspath(__file__)) desc = 'Scientific Python Development EnvironmEnt, an alternative to IDLE' fname = osp.join(start_menu, 'Spyder (full).lnk') create_shortcut(python, desc, fname, '"%s"' % script, workdir, osp.join(ico_dir, 'spyder.ico')) file_created(fname) fname = osp.join(start_menu, 'Spyder-Reset all settings.lnk') create_shortcut(python, 'Reset Spyder settings to defaults', fname, '"%s" --reset' % script, workdir) file_created(fname) current = True # only affects current user root = winreg.HKEY_CURRENT_USER if current else winreg.HKEY_LOCAL_MACHINE winreg.SetValueEx(winreg.CreateKey(root, KEY_C1 % ("", EWS)), "", 0, winreg.REG_SZ, '"%s" "%s\Scripts\spyder" "%%1"' % (pythonw, sys.prefix)) winreg.SetValueEx(winreg.CreateKey(root, KEY_C1 % ("NoCon", EWS)), "", 0, winreg.REG_SZ, '"%s" "%s\Scripts\spyder" "%%1"' % (pythonw, sys.prefix)) # Create desktop shortcut file desktop_folder = get_special_folder_path("CSIDL_DESKTOPDIRECTORY") fname = osp.join(desktop_folder, 'Spyder.lnk') desc = 'Scientific Python Development EnvironmEnt, an alternative to IDLE' create_shortcut(pythonw, desc, fname, '"%s"' % script, workdir, osp.join(ico_dir, 'spyder.ico')) file_created(fname) def remove(): """Function executed when running the script with the -remove switch""" current = True # only affects current user root = winreg.HKEY_CURRENT_USER if current else winreg.HKEY_LOCAL_MACHINE for key in (KEY_C1 % ("", EWS), KEY_C1 % ("NoCon", EWS), KEY_C0 % ("", EWS), KEY_C0 % ("NoCon", EWS)): try: winreg.DeleteKey(root, key) except WindowsError: pass else: if not is_bdist_wininst: print("Successfully removed Spyder shortcuts from Windows "\ "Explorer context menu.", file=sys.stdout) if not is_bdist_wininst: # clean up desktop desktop_folder = get_special_folder_path("CSIDL_DESKTOPDIRECTORY") fname = osp.join(desktop_folder, 'Spyder.lnk') if osp.isfile(fname): try: os.remove(fname) except OSError: print("Failed to remove %s; you may be able to remove it "\ "manually." % fname, file=sys.stderr) else: print("Successfully removed Spyder shortcuts from your desktop.", file=sys.stdout) # clean up startmenu start_menu = osp.join(get_special_folder_path('CSIDL_PROGRAMS'), 'Spyder (Py%i.%i %i bit)' % (sys.version_info[0], sys.version_info[1], struct.calcsize('P')*8)) if osp.isdir(start_menu): for fname in os.listdir(start_menu): try: os.remove(osp.join(start_menu,fname)) except OSError: print("Failed to remove %s; you may be able to remove it "\ "manually." % fname, file=sys.stderr) else: print("Successfully removed Spyder shortcuts from your "\ " start menu.", file=sys.stdout) try: os.rmdir(start_menu) except OSError: print("Failed to remove %s; you may be able to remove it "\ "manually." % fname, file=sys.stderr) else: print("Successfully removed Spyder shortcut folder from your "\ " start menu.", file=sys.stdout) if __name__=='__main__': if len(sys.argv) > 1: if sys.argv[1] == '-install': try: install() except OSError: print("Failed to create Start Menu items.", file=sys.stderr) elif sys.argv[1] == '-remove': remove() else: print("Unknown command line option %s" % sys.argv[1], file=sys.stderr) else: print("You need to pass either -install or -remove as options to "\ "this script", file=sys.stderr) spyder-3.2.6/scripts/spyder0000775000175000017500000000010013026261005016527 0ustar carloscarlos00000000000000#!/usr/bin/env python from spyder.app import start start.main() spyder-3.2.6/scripts/spyder3.appdata.xml0000664000175000017500000000266113156676663021065 0ustar carloscarlos00000000000000 spyder3.desktop Spyder Scientific Python Development Environment MIT MIT Spyder Project Contributors

Spyder is a free open-source Python development environment providing MATLAB-like features in a simple and light-weighted software.

It contains a powerful interactive development environment for the Python language with advanced editing, interactive testing, debugging and introspection features and a numerical computing environment thanks to the support of IPython (enhanced interactive Python interpreter) and popular Python libraries such as NumPy (linear algebra), SciPy (signal and image processing) or matplotlib (interactive 2D/3D plotting).

Spyder may also be used as a library providing powerful console-related widgets for your PyQt-based applications – for example, it may be used to integrate a debugging console directly in the layout of your graphical user interface.

https://raw.githubusercontent.com/spyder-ide/spyder/master/img_src/screenshot.png ​
spyder-3.2.6/scripts/spyder3.desktop0000664000175000017500000000043013156676663020315 0ustar carloscarlos00000000000000[Desktop Entry] Version=1.0 Type=Application Name=Spyder3 GenericName=Spyder3 Comment=Scientific PYthon Development EnviRonment - Python3 TryExec=spyder3 Exec=spyder3 %F Categories=Development;Science;IDE;Qt; Icon=spyder3 Terminal=false StartupNotify=true MimeType=text/x-python; spyder-3.2.6/scripts/spyder.desktop0000664000175000017500000000044113156676663020234 0ustar carloscarlos00000000000000[Desktop Entry] Version=1.0 Type=Application Name=Spyder GenericName=Spyder Comment=Scientific PYthon Development EnviRonment TryExec=spyder Exec=spyder %F Categories=Development;Science;IDE;Qt; Icon=spyder Terminal=false StartupNotify=true MimeType=text/x-python; X-AppStream-Ignore=True spyder-3.2.6/LICENSE0000664000175000017500000002543013026261005014626 0ustar carloscarlos00000000000000Spyder License Agreement (MIT License) -------------------------------------- Copyright (c) Spyder Project Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Included software ----------------- License terms are included in any software used inside Spyder's source code. Included images (spyder/images) ---------------------------------- [1] Spyder License Agreement (see above) spyder/images/arredit.png spyder/images/dictedit.png spyder/images/none.png spyder/images/not_found.png spyder/images/matplotlib.png spyder/images/options.svg spyder/images/set_workdir.png spyder/images/splash.png spyder/images/spyder.svg spyder/images/spyder_light.svg spyder/images/whole_words.png spyder/images/win_env.png spyder/images/actions/hist.png spyder/images/actions/window_nofullscreen.png spyder/images/editor/attribute.png spyder/images/editor/filelist.png spyder/images/editor/function.png spyder/images/editor/method.png spyder/images/editor/module.png spyder/images/editor/no_match.png spyder/images/editor/private1.png spyder/images/editor/private2.png spyder/images/editor/cell.png spyder/images/editor/blockcomment.png spyder/images/editor/refactor.png spyder/images/console/ipython_console.png spyder/images/console/ipython_console_t.png [2] Crystal Project Icons Author: Everaldo Coelho Site: http://www.everaldo.com Contact: everaldo@everaldo.com Copyright (c) 2006-2007 Everaldo Coelho. spyder/images/advanced.png spyder/images/arrow.png spyder/images/bold.png spyder/images/browser.png spyder/images/ext_tools.png spyder/images/font.png spyder/images/genprefs.png spyder/images/help.png spyder/images/italic.png spyder/images/pythonpath_mgr.png spyder/images/upper_lower.png spyder/images/vcs_browse.png spyder/images/vcs_commit.png spyder/images/actions/1downarrow.png spyder/images/actions/1uparrow.png spyder/images/actions/2downarrow.png spyder/images/actions/2uparrow.png spyder/images/actions/auto_reload.png spyder/images/actions/browse_tab.png spyder/images/actions/check.png spyder/images/actions/cmdprompt.png spyder/images/actions/configure.png spyder/images/actions/copywop.png spyder/images/actions/delete.png spyder/images/actions/edit.png spyder/images/actions/edit24.png spyder/images/actions/editcopy.png spyder/images/actions/editcut.png spyder/images/actions/editdelete.png spyder/images/actions/editpaste.png spyder/images/actions/edit_add.png spyder/images/actions/edit_remove.png spyder/images/actions/eraser.png spyder/images/actions/exit.png spyder/images/actions/filter.png spyder/images/actions/find.png spyder/images/actions/findf.png spyder/images/actions/findnext.png spyder/images/actions/findprevious.png spyder/images/actions/folder_new.png spyder/images/actions/hide.png spyder/images/actions/home.png spyder/images/actions/imshow.png spyder/images/actions/insert.png spyder/images/actions/lock.png spyder/images/actions/lock_open.png spyder/images/actions/magnifier.png spyder/images/actions/next.png spyder/images/actions/options_less.png spyder/images/actions/options_more.png spyder/images/actions/plot.png spyder/images/actions/previous.png spyder/images/actions/redo.png spyder/images/actions/reload.png spyder/images/actions/rename.png spyder/images/actions/replace.png spyder/images/actions/show.png spyder/images/actions/special_paste.png spyder/images/actions/synchronize.png spyder/images/actions/tooloptions.png spyder/images/actions/undo.png spyder/images/actions/up.png spyder/images/actions/zoom_in.png spyder/images/actions/zoom_out.png spyder/images/console/clear.png spyder/images/console/cmdprompt_t.png spyder/images/console/console.png spyder/images/console/environ.png spyder/images/console/history.png spyder/images/console/history24.png spyder/images/console/kill.png spyder/images/console/prompt.png spyder/images/console/restart.png spyder/images/console/syspath.png spyder/images/editor/bug.png spyder/images/editor/close_panel.png spyder/images/editor/comment.png spyder/images/editor/error.png spyder/images/editor/file.png spyder/images/editor/fromcursor.png spyder/images/editor/gotoline.png spyder/images/editor/highlight.png spyder/images/editor/horsplit.png spyder/images/editor/indent.png spyder/images/editor/last_edit_location.png spyder/images/editor/newwindow.png spyder/images/editor/next_cursor.png spyder/images/editor/next_wng.png spyder/images/editor/outline_explorer.png spyder/images/editor/outline_explorer_vis.png spyder/images/editor/prev_cursor.png spyder/images/editor/prev_wng.png spyder/images/editor/select.png spyder/images/editor/selectall.png spyder/images/editor/todo_list.png spyder/images/editor/uncomment.png spyder/images/editor/unindent.png spyder/images/editor/versplit.png spyder/images/editor/wng_list.png spyder/images/file/fileclose.png spyder/images/file/filecloseall.png spyder/images/file/fileimport.png spyder/images/file/filenew.png spyder/images/file/fileopen.png spyder/images/file/filesave.png spyder/images/file/filesaveas.png spyder/images/file/print.png spyder/images/file/save_all.png spyder/images/filetypes/bat.png spyder/images/filetypes/bmp.png spyder/images/filetypes/c.png spyder/images/filetypes/cc.png spyder/images/filetypes/cfg.png spyder/images/filetypes/chm.png spyder/images/filetypes/cl.png spyder/images/filetypes/cmd.png spyder/images/filetypes/cpp.png spyder/images/filetypes/css.png spyder/images/filetypes/cxx.png spyder/images/filetypes/diff.png spyder/images/filetypes/doc.png spyder/images/filetypes/exe.png spyder/images/filetypes/f.png spyder/images/filetypes/f77.png spyder/images/filetypes/f90.png spyder/images/filetypes/gif.png spyder/images/filetypes/h.png spyder/images/filetypes/hh.png spyder/images/filetypes/hpp.png spyder/images/filetypes/htm.png spyder/images/filetypes/html.png spyder/images/filetypes/hxx.png spyder/images/filetypes/inf.png spyder/images/filetypes/ini.png spyder/images/filetypes/jpeg.png spyder/images/filetypes/jpg.png spyder/images/filetypes/js.png spyder/images/filetypes/log.png spyder/images/filetypes/nt.png spyder/images/filetypes/patch.png spyder/images/filetypes/pdf.png spyder/images/filetypes/png.png spyder/images/filetypes/pps.png spyder/images/filetypes/properties.png spyder/images/filetypes/ps.png spyder/images/filetypes/pxd.png spyder/images/filetypes/pxi.png spyder/images/filetypes/pyx.png spyder/images/filetypes/rar.png spyder/images/filetypes/readme.png spyder/images/filetypes/reg.png spyder/images/filetypes/rej.png spyder/images/filetypes/session.png spyder/images/filetypes/tar.png spyder/images/filetypes/tex.png spyder/images/filetypes/tgz.png spyder/images/filetypes/tif.png spyder/images/filetypes/tiff.png spyder/images/filetypes/txt.png spyder/images/filetypes/xls.png spyder/images/filetypes/xml.png spyder/images/filetypes/zip.png spyder/images/projects/add_to_path.png spyder/images/projects/folder.png spyder/images/projects/package.png spyder/images/projects/pp_folder.png spyder/images/projects/pp_package.png spyder/images/projects/pp_project.png spyder/images/projects/project.png spyder/images/projects/project_closed.png spyder/images/projects/pythonpath.png spyder/images/projects/remove_from_path.png spyder/images/projects/show_all.png [3] GNU Lesser General Public License (Version 2.1) spyder/images/qt.png spyder/images/qtassistant.png spyder/images/qtdesigner.png spyder/images/qtlinguist.png spyder/images/filetypes/ts.png spyder/images/filetypes/ui.png [4] GNU General Public License version 3 spyder/images/pythonxy.png spyder/images/vitables.png [5] MIT License spyder/images/winpython.svg spyder/images/chevron-left.png spyder/images/chevron-right.png [6] BSD License spyder/images/scipy.png [7] Creative Commons Attribution 2.5 License (FamFamFam Silk icon set 1.3) spyder/images/actions/collapse.png spyder/images/actions/collapse_selection.png spyder/images/actions/expand.png spyder/images/actions/expand_selection.png spyder/images/actions/restore.png spyder/images/editor/class.png spyder/images/editor/convention.png spyder/images/editor/todo.png spyder/images/editor/warning.png spyder/images/filetypes/po.png spyder/images/filetypes/pot.png [8] PSF LICENSE AGREEMENT FOR PYTHON spyder/images/console/python.png spyder/images/console/python_t.png spyder/images/filetypes/py.png spyder/images/filetypes/pyc.png spyder/images/filetypes/pyw.png [9] zlib/libpng license spyder/images/filetypes/nsh.png spyder/images/filetypes/nsi.png [10] Eclipse Public License spyder/images/projects/pydev.png [11] Creative Commons Attribution 3.0 License (Yusuke Kamiyamane Icons) spyder/images/actions/arrow-continue.png spyder/images/actions/arrow-step-in.png spyder/images/actions/arrow-step-out.png spyder/images/actions/arrow-step-over.png spyder/images/actions/maximize.png spyder/images/actions/stop_debug.png spyder/images/actions/unmaximize.png spyder/images/actions/window_fullscreen.png spyder/images/editor/breakpoint_big.png spyder/images/editor/breakpoint_cond_big.png spyder/images/editor/breakpoint_cond_small.png spyder/images/editor/breakpoint_small.png spyder/images/editor/debug.png spyder/images/console/terminated.png spyder/images/actions/stop.png [12] Creative Commons BY-SA license (The Oxygen icon theme) spyder/images/editor/run.png spyder/images/editor/run_again.png spyder/images/editor/run_cell.png spyder/images/editor/run_cell_advance.png spyder/images/editor/run_selection.png spyder/images/editor/run_settings.png spyder/images/console/run_small.png [13] http://preloaders.net/ (According to the website: "All animated GIF and APNG images are completely free to use in all projects (web and desktop applications, freeware and commercial projects)") spyder/images/console/loading_sprites.png spyder-3.2.6/README.md0000664000175000017500000001507113224740762015114 0ustar carloscarlos00000000000000# Spyder - The Scientific PYthon Development EnviRonment Copyright © Spyder Project Contributors. ## Project details [![license](https://img.shields.io/pypi/l/spyder.svg)](./LICENSE) [![pypi version](https://img.shields.io/pypi/v/spyder.svg)](https://pypi.python.org/pypi/spyder) [![Join the chat at https://gitter.im/spyder-ide/public](https://badges.gitter.im/spyder-ide/spyder.svg)](https://gitter.im/spyder-ide/public) ## Build status [![Travis status](https://travis-ci.org/spyder-ide/spyder.svg?branch=master)](https://travis-ci.org/spyder-ide/spyder) [![AppVeyor status](https://ci.appveyor.com/api/projects/status/tvjcqa4kf53br8s0/branch/master?svg=true)](https://ci.appveyor.com/project/spyder-ide/spyder/branch/master) [![CircleCI](https://circleci.com/gh/spyder-ide/spyder.svg?style=svg)](https://circleci.com/gh/spyder-ide/spyder) [![Coverage Status](https://coveralls.io/repos/github/spyder-ide/spyder/badge.svg?branch=master)](https://coveralls.io/github/spyder-ide/spyder?branch=master) [![codecov](https://codecov.io/gh/spyder-ide/spyder/branch/master/graph/badge.svg)](https://codecov.io/gh/spyder-ide/spyder) ## Overview ![screenshot](./img_src/screenshot.png) Spyder is a Python development environment with a lot of features: * **Editor** Multi-language editor with function/class browser, code analysis features (pyflakes and pylint are currently supported), code completion, horizontal and vertical splitting, and goto definition. * **Interactive console** Python or IPython consoles with workspace and debugging support to instantly evaluate the code written in the Editor. It also comes with Matplotlib figures integration. * **Documentation viewer** Show documentation for any class or function call made either in the Editor or a Console. * **Variable explorer** Explore variables created during the execution of a file. Editing them is also possible with several GUI based editors, like a dictionary and Numpy array ones. * **Find in files** Supporting regular expressions and mercurial repositories * **File explorer** * **History log** Spyder may also be used as a PyQt5/PyQt4 extension library (module `spyder`). For example, the Python interactive shell widget used in Spyder may be embedded in your own PyQt5/PyQt4 application. ## Documentation You can read the Spyder documentation at: http://pythonhosted.org/spyder/ ## Installation This section explains how to install the latest stable release of Spyder. If you prefer testing the development version, please use the `bootstrap` script (see next section). The easiest way to install Spyder is: ### On Windows: Using one (and only one) of these scientific Python distributions: 1. [Anaconda](http://continuum.io/downloads) 2. [WinPython](https://winpython.github.io/) 3. [Python(x,y)](http://python-xy.github.io) ### On Mac OSX: - Using the [Anaconda Distribution](http://continuum.io/downloads). - Through [MacPorts](http://www.macports.org/). ### On GNU/Linux - Through your distribution package manager (i.e. `apt-get`, `yum`, etc). - Using the [Anaconda Distribution](http://continuum.io/downloads). - Installing from source (see below). ### Cross-platform way from source You can also install Spyder with the `pip` package manager, which comes by default with most Python installations. For that you need to use the command: pip install spyder To upgrade Spyder to its latest version, if it was installed before, you need to run pip install --upgrade spyder For more details on supported platforms, please refer to our [installation instructions](http://pythonhosted.org/spyder/installation.html). **Important note**: This does not install the graphical Python libraries (i.e. PyQt5 or PyQt4) that Spyder depends on. Those have to be installed separately after installing Python. ## Running from source The fastest way to run Spyder is to get the source code using git, install PyQt5 or PyQt4, and run these commands: 1. Install our *runtime dependencies* (see below). 2. `cd /your/spyder/git-clone` 3. `python bootstrap.py` You may want to do this for fixing bugs in Spyder, adding new features, learning how Spyder works or just getting a taste of it. ## Dependencies **Important note**: Most if not all the dependencies listed below come with *Anaconda*, *WinPython* and *Python(x,y)*, so you don't need to install them separately when installing one of these Scientific Python distributions. ### Build dependencies When installing Spyder from its source package, the only requirement is to have a Python version greater than 2.7 (Python 3.2 is not supported anymore). ### Runtime dependencies * **Python** 2.7 or 3.3+ * **PyQt5** 5.2+ or **PyQt4** 4.6+: PyQt5 is recommended. * **qtconsole** 4.2.0+: Enhanced Python interpreter. * **Rope** 0.9.4+ and **Jedi** 0.9.0+: Editor code completion, calltips and go-to-definition. * **Pyflakes**: Real-time code analysis. * **Sphinx**: Rich text mode for the Help pane. * **Pygments** 2.0+: Syntax highlighting for all file types it supports. * **Pylint**: Static code analysis. * **Pycodestyle**: Style analysis. * **Psutil**: CPU and memory usage on the status bar. * **Nbconvert**: Manipulation of notebooks in the Editor. * **Qtawesome** 0.4.1+: To have an icon theme based on FontAwesome. * **Pickleshare**: Show import completions on the Python consoles. * **PyZMQ**: Run introspection services asynchronously. * **QtPy** 1.2.0+: Abstracion layer for Python Qt bindings so that Spyder can run on PyQt4 and PyQt5. * **Chardet**: Character encoding auto-detection in Python. * **Numpydoc**: Used by Jedi to get return types for functions with Numpydoc docstrings. * **Cloudpickle**: Serialize variables in the IPython kernel to send them to Spyder. ### Optional dependencies * **Matplotlib**: 2D/3D plotting in the Python and IPython consoles. * **Pandas**: View and edit DataFrames and Series in the Variable Explorer. * **Numpy**: View and edit two or three dimensional arrays in the Variable Explorer. * **SymPy**: Symbolic mathematics in the IPython console. * **SciPy**: Import Matlab workspace files in the Variable Explorer. * **Cython**: Run Cython files in the IPython console. ## Contributing Everyone is welcome to contribute. Please read our [contributing instructions](https://github.com/spyder-ide/spyder/blob/master/CONTRIBUTING.md), then get started! ## More information * For code development please go to: * For bug reports and feature requests: * For discussions and troubleshooting: spyder-3.2.6/CHANGELOG.md0000664000175000017500000102070413225024455015441 0ustar carloscarlos00000000000000# History of changes ## Version 3.2.6 (2018-01-09) ### New features #### Editor * Make `Shift+Del` to cut text if users have some text selected. * Make `Shift+Ins` to paste text. * Make `Ctrl+PgUp`, `Ctrl+PgDn` and `Ctrl+Tab` shortcuts configurable. #### Variable Explorer * Display date/times in human readable format. * Disable editing for immutable types (e.g. tuples). #### Under the hood * Fix installation of wheels with `pip`. ### Bugs fixed **Issues** * [Issue 6169](https://github.com/spyder-ide/spyder/issues/6169) - Error on Maximize Current Pane * [Issue 6163](https://github.com/spyder-ide/spyder/issues/6163) - AttributeError when resetting console namespace * [Issue 6152](https://github.com/spyder-ide/spyder/issues/6152) - Not able to change layouts after resetting * [Issue 6115](https://github.com/spyder-ide/spyder/issues/6115) - DataFrame Editor raises TypeError when editing any complex type * [Issue 6114](https://github.com/spyder-ide/spyder/issues/6114) - Fix errors when entering a value for a cell larger than the max int in Array and Dataframe editors * [Issue 6098](https://github.com/spyder-ide/spyder/issues/6098) - Consoles get renamed when moved in the IPython console * [Issue 6091](https://github.com/spyder-ide/spyder/issues/6091) - 3.2.5 fails to activate Matplotlib Qt5 backend * [Issue 6080](https://github.com/spyder-ide/spyder/issues/6080) - Variable Explorer throws an error instead of displaying contents when attempting to inspect any loaded modules * [Issue 6076](https://github.com/spyder-ide/spyder/issues/6076) - Spyder not starting in macOS because pyopengl is present * [Issue 6075](https://github.com/spyder-ide/spyder/issues/6075) - Update to 3.2.5 with pip fails for Python 2.7 as it pulls pyqt5 * [Issue 6060](https://github.com/spyder-ide/spyder/issues/6060) - Spyder crashes upon typing `net(` in editor * [Issue 6032](https://github.com/spyder-ide/spyder/issues/6032) - When comparing a generated and loaded profile, any negative deltas show (actual_value - ?) 1h:60min, not actual value * [Issue 6003](https://github.com/spyder-ide/spyder/issues/6003) - Improve how we detect that Spyder is running under Anaconda * [Issue 5973](https://github.com/spyder-ide/spyder/issues/5973) - Shift+del should delete line only when empty selection, otherwise clipboard cut * [Issue 5953](https://github.com/spyder-ide/spyder/issues/5953) - Tuples can be "edited" in Variable Explorer but changes are discarded * [Issue 5636](https://github.com/spyder-ide/spyder/issues/5636) - "ValueError: malformed node or string" when evaluating code that contains Path elements * [Issue 5477](https://github.com/spyder-ide/spyder/issues/5477) - Window layout setting error * [Issue 5426](https://github.com/spyder-ide/spyder/issues/5426) - Segmentation fault when trying to change keyboard shortcuts in Preferences * [Issue 5384](https://github.com/spyder-ide/spyder/issues/5384) - File switcher error * [Issue 5080](https://github.com/spyder-ide/spyder/issues/5080) - ValueError: not enough values to unpack in the File Explorer * [Issue 4842](https://github.com/spyder-ide/spyder/issues/4842) - Add ability to change Ctrl+PgUp and PgDn shortcuts * [Issue 4111](https://github.com/spyder-ide/spyder/issues/4111) - Keyboard shortcut hint is missing from menu item Search/Find in files * [Issue 3674](https://github.com/spyder-ide/spyder/issues/3674) - Tab in-between find and replace text boxes In this release 23 issues were closed **Pull requests** * [PR 6173](https://github.com/spyder-ide/spyder/pull/6173) - PR: Fix error when trying to maximize plugins that don't have a dock widget * [PR 6170](https://github.com/spyder-ide/spyder/pull/6170) - PR: Catch error when resetting console namespace and no kernel_client is available * [PR 6158](https://github.com/spyder-ide/spyder/pull/6158) - PR: Skip some tests because they are failing locally or segfaulting * [PR 6153](https://github.com/spyder-ide/spyder/pull/6153) - PR: Cannot change windows layout on first start after reset * [PR 6141](https://github.com/spyder-ide/spyder/pull/6141) - PR: Add shortcut to Find in Files in Search menu * [PR 6138](https://github.com/spyder-ide/spyder/pull/6138) - PR: Mark introspection test slow and re-enable it on certain CIs * [PR 6135](https://github.com/spyder-ide/spyder/pull/6135) - PR: Add test to verify that the Automatic backend is working correctly * [PR 6134](https://github.com/spyder-ide/spyder/pull/6134) - PR: Run slow tests only in our CIs * [PR 6132](https://github.com/spyder-ide/spyder/pull/6132) - PR: Fix TypeError editing any complex val in DataFrameEditor, and bug resulting in bool_s being treated as uneditable * [PR 6125](https://github.com/spyder-ide/spyder/pull/6125) - PR: Prevent an error in the FileSwitcher when all tabs are closed in the last focused widget. * [PR 6123](https://github.com/spyder-ide/spyder/pull/6123) - PR: Allow tab cycling shortcuts to be configurable in Editor * [PR 6121](https://github.com/spyder-ide/spyder/pull/6121) - PR: Patch ipykernel to avoid errors when setting the Qt5 Matplotlib backend * [PR 6118](https://github.com/spyder-ide/spyder/pull/6118) - PR: Fix crash and error dialog when triggering OverflowError (too large int) when editing arrays and dataframes * [PR 6108](https://github.com/spyder-ide/spyder/pull/6108) - PR: Fix renames when moving IPython console tabs * [PR 6106](https://github.com/spyder-ide/spyder/pull/6106) - PR: Fix negative deltas on profiler * [PR 6104](https://github.com/spyder-ide/spyder/pull/6104) - PR: Avoid a calltip crash when docstring is None * [PR 6100](https://github.com/spyder-ide/spyder/pull/6100) - PR: Fix mime type error detection in the File Explorer * [PR 6099](https://github.com/spyder-ide/spyder/pull/6099) - PR: Remove unnecessary flaky from introspection test, minor cleanup * [PR 6094](https://github.com/spyder-ide/spyder/pull/6094) - PR: Make Tab key properly switch between find and replace fields * [PR 6092](https://github.com/spyder-ide/spyder/pull/6092) - PR: Fix segfault on shortcut preferences when using mouse * [PR 6090](https://github.com/spyder-ide/spyder/pull/6090) - PR: Improve how we detect if we are running under Anaconda * [PR 6089](https://github.com/spyder-ide/spyder/pull/6089) - PR: Avoid errors when importing pyopengl at startup * [PR 6088](https://github.com/spyder-ide/spyder/pull/6088) - PR: Make pyqt5 a wheel dependency only for Python 3 * [PR 6081](https://github.com/spyder-ide/spyder/pull/6081) - PR: Fix error when attempting to view module contents in CollectionsEditor * [PR 6062](https://github.com/spyder-ide/spyder/pull/6062) - PR: Add expected default behavior for Shift+Del and Shift+Ins * [PR 6057](https://github.com/spyder-ide/spyder/pull/6057) - PR: Add coverage files and Notepad++ backups to gitignore * [PR 6044](https://github.com/spyder-ide/spyder/pull/6044) - PR: Skip several failing tests on Windows and one on a specific CI build * [PR 6042](https://github.com/spyder-ide/spyder/pull/6042) - PR: Add test coverage reporting with AppVeyor to Codecov * [PR 6000](https://github.com/spyder-ide/spyder/pull/6000) - PR: Display date/times in human readable format in Variable Explorer * [PR 5992](https://github.com/spyder-ide/spyder/pull/5992) - PR: Make bullets/numbers/headings more consistent and add Anaconda for Linux in install doc * [PR 5991](https://github.com/spyder-ide/spyder/pull/5991) - PR: Properly disable editing in Variable Explorer for values in immutable collections (e.g. tuples) * [PR 5746](https://github.com/spyder-ide/spyder/pull/5746) - PR: Manage types that extend str in value_to_display In this release 32 pull requests were merged ---- ## Version 3.2.5 (2017-12-25) ### New features #### IPython Console * Improve kernel startup time. * Add option to show kernel elapsed time. * Add button and option to remove all user-defined variables. * Load `%autoreload` magic at kernel startup to make changes to modules take effect instantly in the console. * Use `cloudpickle` to serialize/deserialize data between kernels and Spyder. #### Variable Explorer * Add support for `datetime.timedelta` objects. #### Under the hood * Add `pyqt5` as a new wheel dependency. * Add a new `--hide-console` option and deprecate `--show-console` on Windows. ### Bugs fixed **Issues** * [Issue 5988](https://github.com/spyder-ide/spyder/issues/5988) - Update translations for 3.2.5 * [Issue 5978](https://github.com/spyder-ide/spyder/issues/5978) - Remove 'DMG Installers' option from documentation * [Issue 5944](https://github.com/spyder-ide/spyder/issues/5944) - UserWarning: Config option use_jedi not recognized by IPCompleter * [Issue 5885](https://github.com/spyder-ide/spyder/issues/5885) - Error when choosing rename option after editing tuple value from Variable explorer. * [Issue 5877](https://github.com/spyder-ide/spyder/issues/5877) - Code from one file not updating when called from another if run directly in the console * [Issue 5791](https://github.com/spyder-ide/spyder/issues/5791) - "Real-time code style analysis" checkbox in Prefs > Editor > Introspection checks for pep8, not pycodestyle * [Issue 5776](https://github.com/spyder-ide/spyder/issues/5776) - Return value of EditorStack.has_filename not checked properly * [Issue 5759](https://github.com/spyder-ide/spyder/issues/5759) - IPython console missing features with respect to the old Python console * [Issue 5755](https://github.com/spyder-ide/spyder/issues/5755) - AttributeError is thrown when trying to get help of an object * [Issue 5750](https://github.com/spyder-ide/spyder/issues/5750) - Improve working directory dropdown box * [Issue 5748](https://github.com/spyder-ide/spyder/issues/5748) - TypeError: disconnect() failed between 'sig_prompt_ready' and all its connections * [Issue 5728](https://github.com/spyder-ide/spyder/issues/5728) - Missing python doc in help menu * [Issue 5718](https://github.com/spyder-ide/spyder/issues/5718) - Problems with backend "TkAgg" on Linux * [Issue 5707](https://github.com/spyder-ide/spyder/issues/5707) - NameError when running isdefined * [Issue 5703](https://github.com/spyder-ide/spyder/issues/5703) - Save after moving editor tabs with split panes changes wrong files * [Issue 5661](https://github.com/spyder-ide/spyder/issues/5661) - Symbol finder gives error message * [Issue 5640](https://github.com/spyder-ide/spyder/issues/5640) - Cannot run static code analysis on Spyder 3.2.4 * [Issue 5628](https://github.com/spyder-ide/spyder/issues/5628) - Error when trying to explore empty numpy array * [Issue 5591](https://github.com/spyder-ide/spyder/issues/5591) - Variable explorer broken because of DeprecationWarning in ipykernel * [Issue 5588](https://github.com/spyder-ide/spyder/issues/5588) - Close parenthesis when unmatched * [Issue 5587](https://github.com/spyder-ide/spyder/issues/5587) - Crash on profiler because of lack of profiler.results * [Issue 5578](https://github.com/spyder-ide/spyder/issues/5578) - Can't open preferences anymore as I get an error message * [Issue 5568](https://github.com/spyder-ide/spyder/issues/5568) - Runtime Error raised while closing IPython Console instance * [Issue 5559](https://github.com/spyder-ide/spyder/issues/5559) - AttributeError: 'InternalShell' object has no attribute 'is_running' * [Issue 5557](https://github.com/spyder-ide/spyder/issues/5557) - Keyboard shortcuts reset button cannot be canceled/undone and too easy to trigger * [Issue 5552](https://github.com/spyder-ide/spyder/issues/5552) - Explicitly stated default Russian encoding on Windows not recognized * [Issue 5541](https://github.com/spyder-ide/spyder/issues/5541) - Automatic graphics backend throws an error * [Issue 5535](https://github.com/spyder-ide/spyder/issues/5535) - Can't enable debug mode * [Issue 5514](https://github.com/spyder-ide/spyder/issues/5514) - Spyder crashes after typing plt.plot( at the ipython console * [Issue 5495](https://github.com/spyder-ide/spyder/issues/5495) - Change --show-console for --hide-console * [Issue 5494](https://github.com/spyder-ide/spyder/issues/5494) - "Replace Selection" Erroneously Removing/Interpreting Escape Sequences * [Issue 5475](https://github.com/spyder-ide/spyder/issues/5475) - 'Show in external file explorer' on editor menu more than once for split panels * [Issue 5402](https://github.com/spyder-ide/spyder/issues/5402) - ValueError: invalid literal for int() with base 10: b'' * [Issue 5386](https://github.com/spyder-ide/spyder/issues/5386) - Error when replacing "\" by "\\" * [Issue 5373](https://github.com/spyder-ide/spyder/issues/5373) - Add Clear button to (find) entry boxes * [Issue 5360](https://github.com/spyder-ide/spyder/issues/5360) - Don't set current working directory for external kernels * [Issue 5218](https://github.com/spyder-ide/spyder/issues/5218) - Error when drag and drop file from zip * [Issue 5057](https://github.com/spyder-ide/spyder/issues/5057) - Fast file switch and fast symbol search do not work properly if the editor is splitted * [Issue 5036](https://github.com/spyder-ide/spyder/issues/5036) - Exploring variables in debugging mode is giving focus to the Editor * [Issue 4186](https://github.com/spyder-ide/spyder/issues/4186) - Spyder always opens a new instance * [Issue 3612](https://github.com/spyder-ide/spyder/issues/3612) - Variable explorer should list datetime.timedelta variables * [Issue 3242](https://github.com/spyder-ide/spyder/issues/3242) - Spyder is not installing the PyQt5 wheel when using pip * [Issue 2883](https://github.com/spyder-ide/spyder/issues/2883) - Outline explorer doesn't work with second Editor window * [Issue 2179](https://github.com/spyder-ide/spyder/issues/2179) - Breakpoint doesn't appear in gui (red circle) but is listed in Debug > Breakpoints > List breakpoints * [Issue 1492](https://github.com/spyder-ide/spyder/issues/1492) - There should be a way to donate money to support the project In this release 45 issues were closed **Pull requests** * [PR 6005](https://github.com/spyder-ide/spyder/pull/6005) - PR: Update Japanese translation for 3.2.5 * [PR 6002](https://github.com/spyder-ide/spyder/pull/6002) - PR: Update French translation for 3.2.5 * [PR 5997](https://github.com/spyder-ide/spyder/pull/5997) - PR: Update Spanish translations for 3.2.5 * [PR 5995](https://github.com/spyder-ide/spyder/pull/5995) - PR: Update Russian translation for 3.2.5 * [PR 5987](https://github.com/spyder-ide/spyder/pull/5987) - PR: Load %autoreload magic at kernel startup * [PR 5979](https://github.com/spyder-ide/spyder/pull/5979) - PR: Remove/update outdated refs to Mac OS X, Mac DMG installers and Continuum.io * [PR 5952](https://github.com/spyder-ide/spyder/pull/5952) - PR: Skip a test that started to fail on Windows and Python 2 * [PR 5950](https://github.com/spyder-ide/spyder/pull/5950) - PR: Disable renames for list, set and tuple in the Variable Explorer * [PR 5902](https://github.com/spyder-ide/spyder/pull/5902) - PR: Make tabs drag behavior in the IPython console to be the same as the Editor one * [PR 5878](https://github.com/spyder-ide/spyder/pull/5878) - PR: Several improvements to the IPython console * [PR 5865](https://github.com/spyder-ide/spyder/pull/5865) - PR: Fix missing documentation links * [PR 5862](https://github.com/spyder-ide/spyder/pull/5862) - PR: Add PyQt5 as a new wheel dependency * [PR 5792](https://github.com/spyder-ide/spyder/pull/5792) - PR: Change pep8 check_executable for pycodestyle. * [PR 5784](https://github.com/spyder-ide/spyder/pull/5784) - PR: Change for file save on split editor when tabs are moved * [PR 5780](https://github.com/spyder-ide/spyder/pull/5780) - PR: Disable smartpants quotes in Sphinx to prevent crash with MathJax * [PR 5778](https://github.com/spyder-ide/spyder/pull/5778) - PR: Catch AttributeError while using the Help plugin * [PR 5777](https://github.com/spyder-ide/spyder/pull/5777) - PR: Adjust calls to use has_filenames return value of None * [PR 5766](https://github.com/spyder-ide/spyder/pull/5766) - PR: Simplify how pyopengl is declared in setup.py * [PR 5762](https://github.com/spyder-ide/spyder/pull/5762) - PR: Add a tooltip showing the full path of highlighted item in the working directory dropdown box * [PR 5758](https://github.com/spyder-ide/spyder/pull/5758) - PR: Improve how Matplotlib backend is set in the IPython console * [PR 5752](https://github.com/spyder-ide/spyder/pull/5752) - PR: Catch TypeError while executing code instructions in the IPython console * [PR 5742](https://github.com/spyder-ide/spyder/pull/5742) - PR: Prevent Editor dockwidget to become visible when clicking on the outline explorer if the Editor is in a separate window * [PR 5731](https://github.com/spyder-ide/spyder/pull/5731) - PR: Skip test_load_kernel_file in PyQt4 because it segfaults too much * [PR 5714](https://github.com/spyder-ide/spyder/pull/5714) - PR: Catch NameError in isdefined * [PR 5694](https://github.com/spyder-ide/spyder/pull/5694) - PR: Add validation for mimedata2url in Editor's dragEnterEvent * [PR 5688](https://github.com/spyder-ide/spyder/pull/5688) - PR: Ignore warning generated by ipykernel.datapub * [PR 5674](https://github.com/spyder-ide/spyder/pull/5674) - PR: Skip test_issue_4066 in our CIs with PyQt >= 5.9 * [PR 5666](https://github.com/spyder-ide/spyder/pull/5666) - PR: Set focus for filter line when doing symbol search * [PR 5662](https://github.com/spyder-ide/spyder/pull/5662) - PR: Handle 3d empty numpy arrays * [PR 5646](https://github.com/spyder-ide/spyder/pull/5646) - PR: Change position of data loading to prevent not calling validation in the Pylint plugin * [PR 5635](https://github.com/spyder-ide/spyder/pull/5635) - PR: Change default behavior of --show-console option * [PR 5634](https://github.com/spyder-ide/spyder/pull/5634) - PR: Catch not found file error when loading profiler results. * [PR 5632](https://github.com/spyder-ide/spyder/pull/5632) - PR: Skip some dataframe tests on Linux * [PR 5624](https://github.com/spyder-ide/spyder/pull/5624) - PR: Add validation for attribute 'is_running' in the Help plugin * [PR 5619](https://github.com/spyder-ide/spyder/pull/5619) - PR: Support datetime.timedelta in variable explorer * [PR 5618](https://github.com/spyder-ide/spyder/pull/5618) - PR: Catch search regexp error while doing replace/find * [PR 5614](https://github.com/spyder-ide/spyder/pull/5614) - PR: Better feedback for regexp errors in find/replace * [PR 5604](https://github.com/spyder-ide/spyder/pull/5604) - PR: Do not overwrite unmatched braces * [PR 5585](https://github.com/spyder-ide/spyder/pull/5585) - PR: Fix ValueError when switching Python interpreters * [PR 5584](https://github.com/spyder-ide/spyder/pull/5584) - PR: Fix typo in Solarized color schemes. * [PR 5577](https://github.com/spyder-ide/spyder/pull/5577) - PR: Add confirmation message to reset shortcuts. * [PR 5576](https://github.com/spyder-ide/spyder/pull/5576) - PR: Add handling for RuntimeError while closing an IPython console instance. * [PR 5575](https://github.com/spyder-ide/spyder/pull/5575) - PR: Fix syncing of line number and plugin list for breakpoints and add unit tests. * [PR 5560](https://github.com/spyder-ide/spyder/pull/5560) - PR: Make clear line shortcut configurable in the IPython console * [PR 5555](https://github.com/spyder-ide/spyder/pull/5555) - PR: Don't unescape control characteres in replace in selection * [PR 5553](https://github.com/spyder-ide/spyder/pull/5553) - PR: Add cp1251 (default Russian) encoding on Windows to be recognized by the Editor * [PR 5538](https://github.com/spyder-ide/spyder/pull/5538) - PR: Reduce row height in dependencies dialog * [PR 5537](https://github.com/spyder-ide/spyder/pull/5537) - PR: Add clear button to find comboboxes * [PR 5536](https://github.com/spyder-ide/spyder/pull/5536) - PR: Fix bootstrap.py --debug * [PR 5528](https://github.com/spyder-ide/spyder/pull/5528) - PR: Add validation to not publish pdb_state after getting values of variables * [PR 5476](https://github.com/spyder-ide/spyder/pull/5476) - PR: Fix EditorSplitter menu_actions and add test. * [PR 5472](https://github.com/spyder-ide/spyder/pull/5472) - PR: Don't rely on process name when detecting a previous instance * [PR 5341](https://github.com/spyder-ide/spyder/pull/5341) - PR: Trade ipykernel.serialize for cloudpickle and remove use of publish_data * [PR 5221](https://github.com/spyder-ide/spyder/pull/5221) - PR: Make the fileswitcher aware of split editorstacks In this release 54 pull requests were merged ---- ## Version 3.2.4 (2017-10-18) ### New features * Add compatibility with Jedi 0.11 * Display lists with all types of elements in the Variable Explorer. ### Bugs fixed **Issues** * [Issue 5416](https://github.com/spyder-ide/spyder/issues/5416) - Cannot get past splash screen * [Issue 5361](https://github.com/spyder-ide/spyder/issues/5361) - Sorting by column in variable explorer * [Issue 5330](https://github.com/spyder-ide/spyder/issues/5330) - Error in variable explorer for dicts with mixed-type keys * [Issue 5324](https://github.com/spyder-ide/spyder/issues/5324) - Spyder crashes because of race condition in ZMQ * [Issue 5317](https://github.com/spyder-ide/spyder/issues/5317) - Error when opening a new project * [Issue 5313](https://github.com/spyder-ide/spyder/issues/5313) - Not all lists are supported by the variable explorer * [Issue 5305](https://github.com/spyder-ide/spyder/issues/5305) - Error when pressing Ctrl+C in the terminal where Spyder was started * [Issue 5296](https://github.com/spyder-ide/spyder/issues/5296) - Increase kernel_client.hb_channel.time_to_dead even more * [Issue 5294](https://github.com/spyder-ide/spyder/issues/5294) - Variable Explorer: sort by values not working * [Issue 5289](https://github.com/spyder-ide/spyder/issues/5289) - Checking/Unchecking path in the pathmanager is not working as expected in the IPython console * [Issue 5280](https://github.com/spyder-ide/spyder/issues/5280) - Enter in IPython console inserts new line when big Dataframes are in namespace * [Issue 5271](https://github.com/spyder-ide/spyder/issues/5271) - Problem when closing files with split editors whose tabs order are not synced. * [Issue 5254](https://github.com/spyder-ide/spyder/issues/5254) - Variable explorer crash when viewing numpy structured array * [Issue 5253](https://github.com/spyder-ide/spyder/issues/5253) - Profiler incorrectly detects recursion * [Issue 5232](https://github.com/spyder-ide/spyder/issues/5232) - Variable explorer raise error when try to sort dict by values * [Issue 5226](https://github.com/spyder-ide/spyder/issues/5226) - error when closing a file * [Issue 5225](https://github.com/spyder-ide/spyder/issues/5225) - Error when trying to sort dataframe with duplicate columns * [Issue 5213](https://github.com/spyder-ide/spyder/issues/5213) - Error when Selecting Fig from Variable Explorer * [Issue 5202](https://github.com/spyder-ide/spyder/issues/5202) - In ipdb, the up and down keys have a strange behaviour * [Issue 5200](https://github.com/spyder-ide/spyder/issues/5200) - pdb.pm() raises an Error * [Issue 5183](https://github.com/spyder-ide/spyder/issues/5183) - Issues with recognizing directory renaming * [Issue 5099](https://github.com/spyder-ide/spyder/issues/5099) - Closing last open file while being in non-existing working dir raises exception * [Issue 5053](https://github.com/spyder-ide/spyder/issues/5053) - AttributeError: 'NoneType' object has no attribute 'execute' * [Issue 5003](https://github.com/spyder-ide/spyder/issues/5003) - Error when trying to edit elements of a float numpy array in variable explorer * [Issue 4856](https://github.com/spyder-ide/spyder/issues/4856) - Some issues with dedicated consoles * [Issue 4156](https://github.com/spyder-ide/spyder/issues/4156) - "Save as" dialog extremely slow In this release 26 issues were closed **Pull requests** * [PR 5467](https://github.com/spyder-ide/spyder/pull/5467) - PR: Add an error message when sorting a dataframe on categorical dtypes * [PR 5457](https://github.com/spyder-ide/spyder/pull/5457) - PR: Make consoles to start without an stderr file * [PR 5450](https://github.com/spyder-ide/spyder/pull/5450) - PR: Update minimal QtPy required version * [PR 5445](https://github.com/spyder-ide/spyder/pull/5445) - PR: Skip a Matplotlib test in PyQt4 because it's failing too much * [PR 5392](https://github.com/spyder-ide/spyder/pull/5392) - PR: Backport PR 5159 * [PR 5389](https://github.com/spyder-ide/spyder/pull/5389) - PR: Fix crashing of the fileswitcher after closing the last file of the Editor. * [PR 5388](https://github.com/spyder-ide/spyder/pull/5388) - PR: Change spyderproject for spyproject in some missing places. * [PR 5358](https://github.com/spyder-ide/spyder/pull/5358) - PR: Add an error message when failing to serialize an object * [PR 5357](https://github.com/spyder-ide/spyder/pull/5357) - PR: Skip some tests to prevent recurrent failures and segfaults * [PR 5356](https://github.com/spyder-ide/spyder/pull/5356) - PR: Prevent a race condition with ZMQ during startup * [PR 5342](https://github.com/spyder-ide/spyder/pull/5342) - PR: Fix history browsing while debugging * [PR 5340](https://github.com/spyder-ide/spyder/pull/5340) - PR: Add handling for OSError's when changing directories. * [PR 5337](https://github.com/spyder-ide/spyder/pull/5337) - PR: Display all lists in the variable explorer * [PR 5336](https://github.com/spyder-ide/spyder/pull/5336) - PR: Add a safe getcwd function to handle errors when the current working was deleted * [PR 5327](https://github.com/spyder-ide/spyder/pull/5327) - PR: Show error when trying to sort dataframe with duplicate columns * [PR 5320](https://github.com/spyder-ide/spyder/pull/5320) - PR: Fix editing floats in array editor * [PR 5311](https://github.com/spyder-ide/spyder/pull/5311) - PR: Sync correctly the closing of files in multiple editorstacks. * [PR 5301](https://github.com/spyder-ide/spyder/pull/5301) - PR: Wait until console is ready before executing code for dedicated consoles * [PR 5298](https://github.com/spyder-ide/spyder/pull/5298) - PR: Fix some execution delays in the IPython console * [PR 5297](https://github.com/spyder-ide/spyder/pull/5297) - PR: A couple of fixes for Jedi 0.11 * [PR 5295](https://github.com/spyder-ide/spyder/pull/5295) - PR: Enable sorting by values in Variable Explorer * [PR 5290](https://github.com/spyder-ide/spyder/pull/5290) - PR: Prevent unchecked paths in the pathmanager to be added to the IPython console sys.path * [PR 5272](https://github.com/spyder-ide/spyder/pull/5272) - PR: Fix recursion error in profiler * [PR 5259](https://github.com/spyder-ide/spyder/pull/5259) - PR: Prevent hard crash when inspecting certain structured arrays * [PR 5246](https://github.com/spyder-ide/spyder/pull/5246) - PR: Don't show errors when kernel_client is None * [PR 5245](https://github.com/spyder-ide/spyder/pull/5245) - PR: Fix some issues with the Editor Save dialog * [PR 5244](https://github.com/spyder-ide/spyder/pull/5244) - PR: Apply window style only if it's not None * [PR 5234](https://github.com/spyder-ide/spyder/pull/5234) - PR: Handle error when using deepcopy in the collections editor. * [PR 5229](https://github.com/spyder-ide/spyder/pull/5229) - PR: Editor historystack improvements * [PR 5204](https://github.com/spyder-ide/spyder/pull/5204) - PR: Fix calling pdb.pm() in a console In this release 30 pull requests were merged ---- ## Version 3.2.3 (2017-09-11) ### New features * Add a button to the Variable Explorer to remove all variables at once. ### Bugs fixed **Issues** * [Issue 5167](https://github.com/spyder-ide/spyder/issues/5167) - AttributeError when using outline and split code * [Issue 5165](https://github.com/spyder-ide/spyder/issues/5165) - 'Execute in external system terminal' unwantedly uses python2 on ubuntu16.04 * [Issue 5158](https://github.com/spyder-ide/spyder/issues/5158) - AttributeError: 'super' object has no attribute '_handle_error' in IPython console * [Issue 5157](https://github.com/spyder-ide/spyder/issues/5157) - Renaming file containing folders yields IndexError. * [Issue 5144](https://github.com/spyder-ide/spyder/issues/5144) - pip created executable name changes between versions * [Issue 5114](https://github.com/spyder-ide/spyder/issues/5114) - KeyboardInterrupt error in waitingspinner * [Issue 4680](https://github.com/spyder-ide/spyder/issues/4680) - Debug: "Run Current Line" past the end of a script doesn't exit the debugger * [Issue 4313](https://github.com/spyder-ide/spyder/issues/4313) - "unblockcomment" incompatible with "automatically remove trailing spaces" * [Issue 3390](https://github.com/spyder-ide/spyder/issues/3390) - RuntimeError when using outline and split code editor * [Issue 313](https://github.com/spyder-ide/spyder/issues/313) - Variable Explorer: Add a button to remove all variables at once In this release 10 issues were closed **Pull requests** * [PR 5181](https://github.com/spyder-ide/spyder/pull/5181) - PR: Use get_python_executable to run in external terminals * [PR 5166](https://github.com/spyder-ide/spyder/pull/5166) - PR: Fix RuntimeError and AttributeError when using outline and split code editor * [PR 5164](https://github.com/spyder-ide/spyder/pull/5164) - PR: Stop creating universal wheels * [PR 5163](https://github.com/spyder-ide/spyder/pull/5163) - PR: Add handling for IndexError in the Editor when renaming folder containing file * [PR 5162](https://github.com/spyder-ide/spyder/pull/5162) - PR: Don't use super in _handle_error method of IPython console * [PR 5129](https://github.com/spyder-ide/spyder/pull/5129) - PR: Avoid KeyboardInterrupt to raise an error in waitingspinner * [PR 5089](https://github.com/spyder-ide/spyder/pull/5089) - PR: Exit the debugger if we are about to enter to sitecustomize.py * [PR 5017](https://github.com/spyder-ide/spyder/pull/5017) - PR: Fix unblock comments * [PR 4885](https://github.com/spyder-ide/spyder/pull/4885) - PR: Add a button in the Variable Explorer toolbar to reset namespace In this release 9 pull requests were merged ---- ## Version 3.2.2 (2017-09-05) ### New features * Add a button to Find in Files to make searches case sensitive. * Extend Find in Files to select other search directories. * Add an option to set cursor blinking speed in miliseconds in `Preferences > General > Interface > Cursor blinking`. * Add checkboxes to PYTHONPATH manager to enable/disable paths. * Show the number of matches in the Find/Replace widget. ### Bugs fixed **Issues** * [Issue 5111](https://github.com/spyder-ide/spyder/issues/5111) - Unable to save file in Python * [Issue 5074](https://github.com/spyder-ide/spyder/issues/5074) - Editor - Cannot close a (vertical) split after open * [Issue 5040](https://github.com/spyder-ide/spyder/issues/5040) - Word operators do not have a color style in the IPython console * [Issue 5026](https://github.com/spyder-ide/spyder/issues/5026) - Increase the limit of DPI setting for IPython inline graphics * [Issue 5019](https://github.com/spyder-ide/spyder/issues/5019) - IPython consoles can't start if Spyder temp directory is missing * [Issue 5014](https://github.com/spyder-ide/spyder/issues/5014) - BUG: Error editing element of numpy array in variable explorer * [Issue 4989](https://github.com/spyder-ide/spyder/issues/4989) - Spyder Issue when using ctrl+P : goto line * [Issue 4981](https://github.com/spyder-ide/spyder/issues/4981) - Unable to start Array builder using keyboard shortcut * [Issue 4970](https://github.com/spyder-ide/spyder/issues/4970) - Console slow to close when debugging * [Issue 4953](https://github.com/spyder-ide/spyder/issues/4953) - Consistent layout in different panes * [Issue 4934](https://github.com/spyder-ide/spyder/issues/4934) - "Replace selection" adds "\." anytime the string to be added contains "." * [Issue 4921](https://github.com/spyder-ide/spyder/issues/4921) - IPython: Run Code at Startup - Magics * [Issue 4881](https://github.com/spyder-ide/spyder/issues/4881) - Force-stop does not work on hanged progress. * [Issue 4879](https://github.com/spyder-ide/spyder/issues/4879) - Run Configuration per file: Working Directory not remembered * [Issue 4851](https://github.com/spyder-ide/spyder/issues/4851) - Error when trying to load third-party plugins * [Issue 4844](https://github.com/spyder-ide/spyder/issues/4844) - Pressing Ctrl+Tab wanting to switch to another tab raises an IndexError * [Issue 4839](https://github.com/spyder-ide/spyder/issues/4839) - Make Spyder remember tab order * [Issue 4836](https://github.com/spyder-ide/spyder/issues/4836) - Kernels fail to start because they can't create stderr files in non-ascii accounts on Windows * [Issue 4829](https://github.com/spyder-ide/spyder/issues/4829) - SPYDER_DEBUG=3 is failing on Windows * [Issue 4819](https://github.com/spyder-ide/spyder/issues/4819) - Find in Files should have ignore case flag * [Issue 4814](https://github.com/spyder-ide/spyder/issues/4814) - Extend Find in Files to select other directories * [Issue 4684](https://github.com/spyder-ide/spyder/issues/4684) - Array editor: Change default float formatter from %.3f to %.6g * [Issue 4681](https://github.com/spyder-ide/spyder/issues/4681) - Debug: If a breakpoint is on the first line of a script the whole script runs * [Issue 4504](https://github.com/spyder-ide/spyder/issues/4504) - Exceptions swallow the prompt! * [Issue 4444](https://github.com/spyder-ide/spyder/issues/4444) - Add icon to mac dock when running with bootstrap * [Issue 4410](https://github.com/spyder-ide/spyder/issues/4410) - Editor autocompletion and help extraction not working in Spyder 3.1.4 * [Issue 4277](https://github.com/spyder-ide/spyder/issues/4277) - Option to Disable Blinking Cursor * [Issue 4221](https://github.com/spyder-ide/spyder/issues/4221) - Spyder stops executing commands if Variable explorer shows complicated objects * [Issue 4001](https://github.com/spyder-ide/spyder/issues/4001) - Ctrl+F should show the number of appearances in the file as #current/#total * [Issue 3529](https://github.com/spyder-ide/spyder/issues/3529) - Spyder 3 opens a command prompt window when running certain commands * [Issue 1105](https://github.com/spyder-ide/spyder/issues/1105) - Add the possibility to disable entries in the PYTHONPATH manager In this release 31 issues were closed **Pull requests** * [PR 5128](https://github.com/spyder-ide/spyder/pull/5128) - PR: Skip package names that end in certain suffixes when loading third-party plugins * [PR 5125](https://github.com/spyder-ide/spyder/pull/5125) - PR: Correctly move to first breakpoint after entering debugging * [PR 5118](https://github.com/spyder-ide/spyder/pull/5118) - PR: Fix error when creating some error messagebox * [PR 5110](https://github.com/spyder-ide/spyder/pull/5110) - PR: Add handling for non existing indexes in IPython Console clients * [PR 5109](https://github.com/spyder-ide/spyder/pull/5109) - PR: Add more handling to actions with reference deleted * [PR 5094](https://github.com/spyder-ide/spyder/pull/5094) - PR: Deactivate editor actions when Tab Swither is shown * [PR 5093](https://github.com/spyder-ide/spyder/pull/5093) - PR: Skip some tests in our CIs * [PR 5086](https://github.com/spyder-ide/spyder/pull/5086) - PR: Don't run continue when starting debug if there is a breakpoint in the first line with code. * [PR 5079](https://github.com/spyder-ide/spyder/pull/5079) - PR: Create Spyder TEMPDIR if it does not exist when creating new consoles * [PR 5078](https://github.com/spyder-ide/spyder/pull/5078) - PR: Fix cwd issues in the "Run > Configuration per file" dialog * [PR 5069](https://github.com/spyder-ide/spyder/pull/5069) - PR: Increase waiting time and repetitions for tests that enter debugging * [PR 5064](https://github.com/spyder-ide/spyder/pull/5064) - PR: Fix 1D Numpy arrays edition in the Variable Explorer * [PR 5051](https://github.com/spyder-ide/spyder/pull/5051) - PR: Make inactive paths to be ignored when Spyder's path list is synchronized with PYTHONPATH on Windows * [PR 5048](https://github.com/spyder-ide/spyder/pull/5048) - PR: Increase dpi limit of inline plots * [PR 5045](https://github.com/spyder-ide/spyder/pull/5045) - PR: Allow values with '%' in config system * [PR 5042](https://github.com/spyder-ide/spyder/pull/5042) - PR: Add a style for word operator tokens in the IPython pygments dictionary * [PR 5028](https://github.com/spyder-ide/spyder/pull/5028) - PR: Make value_to_display more robust * [PR 5027](https://github.com/spyder-ide/spyder/pull/5027) - PR: Increase tries for a couple of flaky tests * [PR 5013](https://github.com/spyder-ide/spyder/pull/5013) - PR: Add test with non-ascii directory for consoles stderr file * [PR 5008](https://github.com/spyder-ide/spyder/pull/5008) - PR: Fix setting SPYDER_DEBUG variable on Windows * [PR 4993](https://github.com/spyder-ide/spyder/pull/4993) - PR: Fix handling of line count in the fileswitcher * [PR 4992](https://github.com/spyder-ide/spyder/pull/4992) - PR: Prevent subprocess.Popen calls to create visible consoles on Windows. * [PR 4991](https://github.com/spyder-ide/spyder/pull/4991) - PR: Remove regex escape characters from replacement string on the Find/Replace widget * [PR 4990](https://github.com/spyder-ide/spyder/pull/4990) - PR: Fix shortcut to make array builders appear in the IPython Console * [PR 4978](https://github.com/spyder-ide/spyder/pull/4978) - PR: Minor fixes in Find in Files * [PR 4971](https://github.com/spyder-ide/spyder/pull/4971) - PR: Stop console before closing it * [PR 4962](https://github.com/spyder-ide/spyder/pull/4962) - PR: Send Spyder python path to introspection plugins * [PR 4961](https://github.com/spyder-ide/spyder/pull/4961) - PR: Reduce row height in shortcut dialog * [PR 4957](https://github.com/spyder-ide/spyder/pull/4957) - PR: Clean Spyder config before re-running our tests * [PR 4955](https://github.com/spyder-ide/spyder/pull/4955) - PR: Change format in array and dataframe editors * [PR 4954](https://github.com/spyder-ide/spyder/pull/4954) - PR: Unify layout for panes and widgets * [PR 4914](https://github.com/spyder-ide/spyder/pull/4914) - PR: Display prompt after errors * [PR 4880](https://github.com/spyder-ide/spyder/pull/4880) - PR: Preserve order when saving/loading files from a project. * [PR 4822](https://github.com/spyder-ide/spyder/pull/4822) - PR: Extend Find in Files to select other search directories * [PR 4820](https://github.com/spyder-ide/spyder/pull/4820) - PR: Add a button to Find in Files to make searches case sensitive * [PR 4758](https://github.com/spyder-ide/spyder/pull/4758) - PR: Add an option to set cursor blinking speed in miliseconds * [PR 4756](https://github.com/spyder-ide/spyder/pull/4756) - PR: Add checkboxes to PYTHONPATH manager to enable/disable paths * [PR 4443](https://github.com/spyder-ide/spyder/pull/4443) - PR: Add icon earlier when running application * [PR 4060](https://github.com/spyder-ide/spyder/pull/4060) - PR: Show the number of matches in the Find/Replace widget In this release 39 pull requests were merged ---- ## Version 3.2.1 (2017-08-13) ### Bugs fixed **Issues** * [Issue 4943](https://github.com/spyder-ide/spyder/issues/4943) - Unicode symbols are not highlighted in the Editor * [Issue 4922](https://github.com/spyder-ide/spyder/issues/4922) - Static code analysis produces error when running with empty filename * [Issue 4873](https://github.com/spyder-ide/spyder/issues/4873) - Error when trying to get a very large namespace view from the kernel * [Issue 4862](https://github.com/spyder-ide/spyder/issues/4862) - File execution fails with AttributeError: _Feature instance has no attribute '__len__' * [Issue 4843](https://github.com/spyder-ide/spyder/issues/4843) - Error when attempting to close a split panel in the editor window * [Issue 4841](https://github.com/spyder-ide/spyder/issues/4841) - Setting QT_SCREEN_SCALE_FACTORS is not working as expected * [Issue 4831](https://github.com/spyder-ide/spyder/issues/4831) - Error when rearranging tabs and multiple Editors * [Issue 4824](https://github.com/spyder-ide/spyder/issues/4824) - Error when trying to print source code - AttributeError: 'QPrintDialog' object has no attribute 'addEnabledOption' * [Issue 4816](https://github.com/spyder-ide/spyder/issues/4816) - Error when trying to change to non-ascii directories in the Working Directory toolbar * [Issue 4811](https://github.com/spyder-ide/spyder/issues/4811) - Editor line number font size does not increase when zooming on windows * [Issue 4810](https://github.com/spyder-ide/spyder/issues/4810) - Spyder crashes when attempting to define function named setup in IPython console * [Issue 4806](https://github.com/spyder-ide/spyder/issues/4806) - Change color of matched parens in the IPython console * [Issue 4797](https://github.com/spyder-ide/spyder/issues/4797) - Remove scientific_startup.py * [Issue 4769](https://github.com/spyder-ide/spyder/issues/4769) - Exception raised when running file from project explorer * [Issue 4763](https://github.com/spyder-ide/spyder/issues/4763) - In the Editor, tab does not switch when ctrl is released and focus remains on the tab_switcher * [Issue 4754](https://github.com/spyder-ide/spyder/issues/4754) - Shifting multiple lines of code with ctrl + cmd + down-arrow-key doesn't work properly after first shift * [Issue 4734](https://github.com/spyder-ide/spyder/issues/4734) - High DPI scaling messes up placement of breakpoint red circles * [Issue 4453](https://github.com/spyder-ide/spyder/issues/4453) - Crash when opened file is renamed/deleted outside Spyder * [Issue 4442](https://github.com/spyder-ide/spyder/issues/4442) - Segfault when closing with temporary file open * [Issue 4304](https://github.com/spyder-ide/spyder/issues/4304) - EOLs incorrectly switch from LF to CRLF on split editor panes * [Issue 4039](https://github.com/spyder-ide/spyder/issues/4039) - Sorting order of profiler is wrong * [Issue 3166](https://github.com/spyder-ide/spyder/issues/3166) - Editor line numbers dissappear In this release 22 issues were closed **Pull requests** * [PR 4949](https://github.com/spyder-ide/spyder/pull/4949) - PR: Add basic pep8speaks config file. * [PR 4946](https://github.com/spyder-ide/spyder/pull/4946) - PR: Fix error when the selecting an unicode word * [PR 4928](https://github.com/spyder-ide/spyder/pull/4928) - PR: Check that combobox text is not empty string before emiting valid signal * [PR 4918](https://github.com/spyder-ide/spyder/pull/4918) - PR: Handle truncated dictionary of namespace view from the kernel * [PR 4899](https://github.com/spyder-ide/spyder/pull/4899) - PR: Remove capture_dir_change method of IPython console shell widget * [PR 4875](https://github.com/spyder-ide/spyder/pull/4875) - PR: Separate the installation of Qt from running our tests in Travis * [PR 4870](https://github.com/spyder-ide/spyder/pull/4870) - PR: Save a reference to messagebox in EditorStack to avoid memory to be freed. * [PR 4869](https://github.com/spyder-ide/spyder/pull/4869) - PR: Omit editor split menu option if its reference was deleted * [PR 4866](https://github.com/spyder-ide/spyder/pull/4866) - PR: Remove TypeError and AttributeError exceptions from SpyderKernel * [PR 4864](https://github.com/spyder-ide/spyder/pull/4864) - PR: Fix Run option in File and Project explorers * [PR 4863](https://github.com/spyder-ide/spyder/pull/4863) - PR: Fix sorting in Profiler * [PR 4861](https://github.com/spyder-ide/spyder/pull/4861) - PR: Install qtpy and qtconsole from Github when testing * [PR 4850](https://github.com/spyder-ide/spyder/pull/4850) - PR: Update only current editor stack when moving tabs. * [PR 4849](https://github.com/spyder-ide/spyder/pull/4849) - PR: Prevent importing packages that raise SystemExit exceptions when verifying if an object is defined * [PR 4847](https://github.com/spyder-ide/spyder/pull/4847) - PR: Use Editor font to paint line numbers on all platforms * [PR 4846](https://github.com/spyder-ide/spyder/pull/4846) - PR: Use QT_SCALE_FACTOR when users set only one scale factor * [PR 4845](https://github.com/spyder-ide/spyder/pull/4845) - PR: Set eol_chars in cloned editor on split editor panes * [PR 4835](https://github.com/spyder-ide/spyder/pull/4835) - PR: Delete print test because it segfaults too frequently * [PR 4830](https://github.com/spyder-ide/spyder/pull/4830) - PR: Fix error when printing source code * [PR 4828](https://github.com/spyder-ide/spyder/pull/4828) - PR: Fix error when using non-ascii current directory to run code * [PR 4813](https://github.com/spyder-ide/spyder/pull/4813) - PR: Make highlighting colors in the IPython Console match those used in the Spyder Editor * [PR 4799](https://github.com/spyder-ide/spyder/pull/4799) - PR: Delete scientific_startup.py * [PR 4774](https://github.com/spyder-ide/spyder/pull/4774) - PR: Fix shifting code selection issues in the Editor * [PR 4764](https://github.com/spyder-ide/spyder/pull/4764) - PR: Fix tab does not switch when ctrl is released issue * [PR 4759](https://github.com/spyder-ide/spyder/pull/4759) - PR: Fix enable/disable spinbox bug in Editor preferences panel * [PR 4749](https://github.com/spyder-ide/spyder/pull/4749) - PR: Add icon to MessageCheckBox while avoiding unclickable issue * [PR 4738](https://github.com/spyder-ide/spyder/pull/4738) - PR: Update pixmap height calculation * [PR 4733](https://github.com/spyder-ide/spyder/pull/4733) - PR: Avoid visible_blocks to be empty when first visible block is wrapped In this release 28 pull requests were merged ---- ## Version 3.2 (2017-07-24) ### New features #### Python Console * Remove it for all operating systems. For an explanation, please see [here](https://github.com/spyder-ide/spyder/issues/4524). #### Main Window * Add a dialog to quickly view all keyboard shortcuts defined in Spyder. It can be accessed in the `Help > Shortcuts Summary` menu or using the `Meta+F1` shortcut. * Add an option to set a custom screen resolution scale factor. This option is available in `Preferences > Appearance > Screen resolution`. * Show Spyder internal errors in a special dialog to ease submitting them to Github. #### Editor * Add the ability to reorganize tabs by drag and drop. * Add option to only replace in a selection. * Add `Ctrl+Up` and `Ctrl+Down` shortcuts to move to the next/previous cell, respectively. * Add `Alt+Enter` shortcut to re-run the last cell. * Add support to run Cython files from the Editor (i.e. by simply pressing `F5`). * Add syntax highlighting support for Markdown files. * Add a tab switcher dialog to navigate files in most recently used order. This dialog is activated with `Ctrl+Tab` and `Ctrl+Shift+Tab` to go in forward or backward order, respectively. * Make `Shift+Enter` search text backwards in the find/replace widget. * Add `Shift+Del` shortcut to delete lines. * Add `Ctrl+]` and `Ctrl+[` shortcuts to indent/unindent text, respectively. * Add a *Save copy as* action. * Add a context menu entry to show the selected file in the operating system file explorer. * Apply smart indentation rules to Python files only. For non-Python files, the Editor will preserve the indentation level of the previous line. #### IPython Console * Several improvements to its debugger: - Restore the ability to inspect variables using the Variable Explorer. - Make plotting work with a new `%plot` magic, but only using the `inline` backend (e.g. `%plot plt.plot(range(10))`). - Add history browsing with the Up and Down arrow keys. - Make the *Clear console* and *Reset* keyboard shortcuts to work. - Show plots from the Variable Explorer. - Change the current working directory using the Working Directory toolbar. - Use `Ctrl+Shift+C` to copy text. * Add the possibility to run a file in the same (dedicated) console all the time. * Allow to rename consoles by doing a double-click on their tabs and setting a new name. * Make drag and drop of its tabs to work. * Make the `%cd` magic to change the current working directory of the File Explorer and Working Directory toolbar. * Add menu entries to show environment variables and `sys.path` contents for each console. * Make it use the same color scheme of the Editor. * Automatically load the Cython extension if Cython is installed. #### Find in Files * Add options to search on the current file, project or working directory. * Display results as search takes place. * Allow to order results alphabetically. * Add a spinner as indicator of a search in progress. * Simplify visualization of results. * Remove previous search results when a new search takes place. * Improve file and string encoding to bypass and correct errors associated with codification. * Inform users if search regexp patterns are incorrect. * Remove unused search options. * Omit binary files during a search. #### File Explorer * Add an option to show the selected file in the operating system file explorer. * Show icons for different file types (pdf, image, video, audio, compressed and MS Office files). * Make it change the current working directory of the active console when changing directories on it. #### Working Directory toolbar * Rename it to *Current working directory* (it was Global working directory). * Simplify its options to make them more understandable. * Make it show the working directory of the active IPython console and the current directory in the File Explorer. #### Preferences * Prevent assignment of `Shift+` shortcuts because they can't be used by Qt applications unless they are hard-coded in the application itself. #### Under the hood * Use `pycodestyle` package instead of `pep8` to do style analysis. * Add `pyopengl` as a new dependency to our pip wheels on Linux to prevent crashes related to OpenGL in PyQt 5.7+. * Demand `rope` 0.10.5+ in our wheels because it supports Python 2 and 3 with the same codebase. ### Bugs fixed **Issues** * [Issue 4730](https://github.com/spyder-ide/spyder/issues/4730) - Update translations for 3.2 * [Issue 4725](https://github.com/spyder-ide/spyder/issues/4725) - RuntimeError when closing spyder * [Issue 4722](https://github.com/spyder-ide/spyder/issues/4722) - Indentation changes after zoom-in * [Issue 4721](https://github.com/spyder-ide/spyder/issues/4721) - Add tests for dedicated consoles and run config options * [Issue 4698](https://github.com/spyder-ide/spyder/issues/4698) - Fancy exception handler does not show exception * [Issue 4694](https://github.com/spyder-ide/spyder/issues/4694) - Disambiguate dedicated IPython consoles * [Issue 4693](https://github.com/spyder-ide/spyder/issues/4693) - Change "Path" option to "Current working directory" in Find in Files * [Issue 4692](https://github.com/spyder-ide/spyder/issues/4692) - Make file switcher to have a minimal width * [Issue 4679](https://github.com/spyder-ide/spyder/issues/4679) - Add IPython to Help > Dependencies * [Issue 4665](https://github.com/spyder-ide/spyder/issues/4665) - Don't register external plugins if check_compatibility fails * [Issue 4664](https://github.com/spyder-ide/spyder/issues/4664) - Detect external Spyder kernels * [Issue 4663](https://github.com/spyder-ide/spyder/issues/4663) - Inspecting Numpy bool arrays in Var. Explorer uses deprecated '-' operator in Numpy * [Issue 4648](https://github.com/spyder-ide/spyder/issues/4648) - File switcher is changing size when changing from symbols to files * [Issue 4646](https://github.com/spyder-ide/spyder/issues/4646) - Setting Numpy threshold to nan in console makes the Variable Explorer really slow * [Issue 4641](https://github.com/spyder-ide/spyder/issues/4641) - Add a check_compatibility method to PluginMixin * [Issue 4636](https://github.com/spyder-ide/spyder/issues/4636) - Focus doesn't go to the selected entry in file switcher when filtering * [Issue 4632](https://github.com/spyder-ide/spyder/issues/4632) - Spyder fails to start because of UnicodeDecodeError when creating kernel spec * [Issue 4619](https://github.com/spyder-ide/spyder/issues/4619) - Scroll down/up scrolls down twice * [Issue 4615](https://github.com/spyder-ide/spyder/issues/4615) - Lists with None elements don't appear in the Variable Explorer * [Issue 4611](https://github.com/spyder-ide/spyder/issues/4611) - Goto previous cell behaviour is different than other IDEs * [Issue 4597](https://github.com/spyder-ide/spyder/issues/4597) - Editors not gaining focus when changing by tab click * [Issue 4596](https://github.com/spyder-ide/spyder/issues/4596) - Even more improvements to Find in Files * [Issue 4595](https://github.com/spyder-ide/spyder/issues/4595) - Editor hangs when trying to open Spyder's own CHANGELOG.md file * [Issue 4592](https://github.com/spyder-ide/spyder/issues/4592) - Add useful commands for working with branches to Contributing Guide * [Issue 4584](https://github.com/spyder-ide/spyder/issues/4584) - Tips of the introductory tour pop up when window moved or resized * [Issue 4581](https://github.com/spyder-ide/spyder/issues/4581) - Multiple whitespaces as a separator in variable explorer * [Issue 4575](https://github.com/spyder-ide/spyder/issues/4575) - Make a unique instance of the file switcher * [Issue 4553](https://github.com/spyder-ide/spyder/issues/4553) - Spyder hangs after Introduction Tour * [Issue 4526](https://github.com/spyder-ide/spyder/issues/4526) - Error in syntaxhighlighting of decorators * [Issue 4524](https://github.com/spyder-ide/spyder/issues/4524) - Remove the Python console * [Issue 4520](https://github.com/spyder-ide/spyder/issues/4520) - Line is not being highlighted in cells * [Issue 4496](https://github.com/spyder-ide/spyder/issues/4496) - Shift+Space shortcut doesn't work * [Issue 4490](https://github.com/spyder-ide/spyder/issues/4490) - More Find in Files improvements * [Issue 4487](https://github.com/spyder-ide/spyder/issues/4487) - spyder_io_hdf5 plugin not available * [Issue 4481](https://github.com/spyder-ide/spyder/issues/4481) - Auto-indent Incorrect following line starting with return as part of variable name. * [Issue 4475](https://github.com/spyder-ide/spyder/issues/4475) - Inserting a line-break in code/comment with parenthesis deletes part of the code/comment * [Issue 4452](https://github.com/spyder-ide/spyder/issues/4452) - Add more annotation keywords to the Editor (e.g. BUG, OPTIMIZE, etc) * [Issue 4421](https://github.com/spyder-ide/spyder/issues/4421) - Step-by-step debugging with IPython console doesn't work in 3.1.4. * [Issue 4418](https://github.com/spyder-ide/spyder/issues/4418) - No option for dedicated IPython console * [Issue 4411](https://github.com/spyder-ide/spyder/issues/4411) - Part of file switcher always outside of screen when full-screen * [Issue 4403](https://github.com/spyder-ide/spyder/issues/4403) - Debugging hangs in iPython console * [Issue 4316](https://github.com/spyder-ide/spyder/issues/4316) - Spyder looks terrible on a very high resolution screen * [Issue 4307](https://github.com/spyder-ide/spyder/issues/4307) - Additional shortcuts are making the outline explorer to appear * [Issue 4285](https://github.com/spyder-ide/spyder/issues/4285) - Move to support only Rope 0.10.5+ * [Issue 4282](https://github.com/spyder-ide/spyder/issues/4282) - Create a flaky conda package on conda-forge and move it to the spyder-ide channel * [Issue 4268](https://github.com/spyder-ide/spyder/issues/4268) - QKeySequence not defined in the arrayeditor * [Issue 4259](https://github.com/spyder-ide/spyder/issues/4259) - Display file path of file in the Editor title again * [Issue 4257](https://github.com/spyder-ide/spyder/issues/4257) - Numpy array copy format * [Issue 4216](https://github.com/spyder-ide/spyder/issues/4216) - Delete unused file formlayout.py * [Issue 4214](https://github.com/spyder-ide/spyder/issues/4214) - Spyder debugger doesn't terminate * [Issue 4197](https://github.com/spyder-ide/spyder/issues/4197) - Find in Files not working in 3.1.3 * [Issue 4157](https://github.com/spyder-ide/spyder/issues/4157) - Implement simple indentation fon non-python files * [Issue 4134](https://github.com/spyder-ide/spyder/issues/4134) - Non-ascii characters not displayed correctly in Find in files * [Issue 4132](https://github.com/spyder-ide/spyder/issues/4132) - Spyder crashes because of socket initialization errors on Windows * [Issue 4061](https://github.com/spyder-ide/spyder/issues/4061) - Find occurrences backwards with Shift + Enter (inside find or find/replace mode) * [Issue 4020](https://github.com/spyder-ide/spyder/issues/4020) - Add "run selection" icon * [Issue 4016](https://github.com/spyder-ide/spyder/issues/4016) - save file doesn't work on new files unless you change them * [Issue 4013](https://github.com/spyder-ide/spyder/issues/4013) - Variable Explorer and Editor are not updated when breakpoints are placed in submodules * [Issue 4010](https://github.com/spyder-ide/spyder/issues/4010) - Pressing Enter in the "Replace with" entry of Find/Replace should replace the currently selected text * [Issue 3986](https://github.com/spyder-ide/spyder/issues/3986) - Write additional information on 3.1, 3.x and master branches and how to do bugfixes * [Issue 3959](https://github.com/spyder-ide/spyder/issues/3959) - Shortcut feature request: re-run the previous cell * [Issue 3945](https://github.com/spyder-ide/spyder/issues/3945) - Cannot change local variables in debug mode * [Issue 3940](https://github.com/spyder-ide/spyder/issues/3940) - Spyder crashes when pressing ctrl-g in editor to go to definition * [Issue 3825](https://github.com/spyder-ide/spyder/issues/3825) - Improve icons in the File explorer * [Issue 3771](https://github.com/spyder-ide/spyder/issues/3771) - Error when hit 'run file' button in debug mode * [Issue 3711](https://github.com/spyder-ide/spyder/issues/3711) - Variable Explorer is not showing variables in debug mode * [Issue 3673](https://github.com/spyder-ide/spyder/issues/3673) - Error when trying to view the contents of a binary string in the Variable Explorer for Python 2 * [Issue 3573](https://github.com/spyder-ide/spyder/issues/3573) - Create requirements file to ease introduction to development and testing * [Issue 3555](https://github.com/spyder-ide/spyder/issues/3555) - Spyder 3 can't inspect values through the variable explorer while debugging * [Issue 3406](https://github.com/spyder-ide/spyder/issues/3406) - Add Ctrl+] and Ctrl+[ as indent and unindent shortcuts * [Issue 3405](https://github.com/spyder-ide/spyder/issues/3405) - Cannot create Shift+Del as a shortcut for delete line * [Issue 3332](https://github.com/spyder-ide/spyder/issues/3332) - Spyder can't start because of problems with OpenGL and PyQt5 * [Issue 3275](https://github.com/spyder-ide/spyder/issues/3275) - Print all keyboard shortcuts to cheatset * [Issue 3257](https://github.com/spyder-ide/spyder/issues/3257) - The distinction between "working directory for newly opened consoles" and "working directory for current console" is hard to understand * [Issue 3197](https://github.com/spyder-ide/spyder/issues/3197) - Use pycodestyle instead of pep8 * [Issue 2963](https://github.com/spyder-ide/spyder/issues/2963) - Find in files results disappear when search path loses focus * [Issue 2850](https://github.com/spyder-ide/spyder/issues/2850) - Adapt the Find in Files so results display is flat, like ACK * [Issue 2730](https://github.com/spyder-ide/spyder/issues/2730) - Find in files default include and exclude values should be empty! * [Issue 2628](https://github.com/spyder-ide/spyder/issues/2628) - Show current file in file browser * [Issue 2238](https://github.com/spyder-ide/spyder/issues/2238) - Preserve size in status bar widgets * [Issue 2122](https://github.com/spyder-ide/spyder/issues/2122) - QSyntaxHighlighter and Pygments do not properly interoperate, leading to occasional mis-highlighting * [Issue 2030](https://github.com/spyder-ide/spyder/issues/2030) - Some inconsistencies about the use of "working directories" * [Issue 2020](https://github.com/spyder-ide/spyder/issues/2020) - ipdb freezes and doesn't allow to debug properly * [Issue 1977](https://github.com/spyder-ide/spyder/issues/1977) - Error in Variable explorer when modifying nested objects in wrong order * [Issue 1962](https://github.com/spyder-ide/spyder/issues/1962) - Allow to rename IPython consoles * [Issue 1833](https://github.com/spyder-ide/spyder/issues/1833) - Provide move to next/previous cell shortcut * [Issue 1787](https://github.com/spyder-ide/spyder/issues/1787) - Debugger not responding after copying text from IPython Console * [Issue 1717](https://github.com/spyder-ide/spyder/issues/1717) - Spyder hangs when calling pdb.set_trace() in class definition * [Issue 1706](https://github.com/spyder-ide/spyder/issues/1706) - Breakpoints on continued lines (with \ character) don't work * [Issue 1555](https://github.com/spyder-ide/spyder/issues/1555) - Find in Files unusable * [Issue 1525](https://github.com/spyder-ide/spyder/issues/1525) - Show internal errors in a QMessageBox instead of poping up the Internal Console * [Issue 1352](https://github.com/spyder-ide/spyder/issues/1352) - Keybord short-cut to switch between last open files * [Issue 1170](https://github.com/spyder-ide/spyder/issues/1170) - File tabs have unconventional behaviour * [Issue 1049](https://github.com/spyder-ide/spyder/issues/1049) - Update the cwd name on the working directory toolbar when changing focus between consoles * [Issue 916](https://github.com/spyder-ide/spyder/issues/916) - Add color schemes to IPython console * [Issue 564](https://github.com/spyder-ide/spyder/issues/564) - Editor: drag n' drop (movable) tabs * [Issue 358](https://github.com/spyder-ide/spyder/issues/358) - Find/Replace widget: add option to find/replace in selection only * [Issue 43](https://github.com/spyder-ide/spyder/issues/43) - Make Ctrl+Tab to navigate between tabs in Most Recently Used (MRU) order In this release 98 issues were closed **Pull requests** * [PR 4791](https://github.com/spyder-ide/spyder/pull/4791) - PR: Update Spanish translations for 3.2 * [PR 4785](https://github.com/spyder-ide/spyder/pull/4785) - PR: Prevent Jedi and Rope to open two previously unopened files simultaneously * [PR 4782](https://github.com/spyder-ide/spyder/pull/4782) - PR: Update Russian translation for 3.2 * [PR 4765](https://github.com/spyder-ide/spyder/pull/4765) - PR: Prevent potential problems when importing third-party modules * [PR 4755](https://github.com/spyder-ide/spyder/pull/4755) - PR: Update French translation for 3.2 * [PR 4752](https://github.com/spyder-ide/spyder/pull/4752) - PR: Remove startup options of working directory plugin * [PR 4750](https://github.com/spyder-ide/spyder/pull/4750) - PR: Don't set pandas.core.common.in_qtconsole anymore * [PR 4746](https://github.com/spyder-ide/spyder/pull/4746) - PR: Update Japanese translation * [PR 4737](https://github.com/spyder-ide/spyder/pull/4737) - PR: Add mdw as markdown extension. * [PR 4729](https://github.com/spyder-ide/spyder/pull/4729) - PR: Add tests for dedicated consoles and runconfig options * [PR 4726](https://github.com/spyder-ide/spyder/pull/4726) - PR: Fix error when closing window and we ask users if they want to close it or not * [PR 4723](https://github.com/spyder-ide/spyder/pull/4723) - PR: Update tabwidth when changing zoom in Editor. * [PR 4719](https://github.com/spyder-ide/spyder/pull/4719) - PR: Fix running in dedicated consoles and other UI fixes * [PR 4713](https://github.com/spyder-ide/spyder/pull/4713) - PR: Remove all code related to the Python console * [PR 4711](https://github.com/spyder-ide/spyder/pull/4711) - PR: Show complete exception (not only the traceback) in error QMessageBox. * [PR 4706](https://github.com/spyder-ide/spyder/pull/4706) - PR: Revert PR #4651 * [PR 4700](https://github.com/spyder-ide/spyder/pull/4700) - PR: Add disambiguation for dedicated IPython consoles * [PR 4699](https://github.com/spyder-ide/spyder/pull/4699) - PR: Set width of file switcher according to main window width * [PR 4696](https://github.com/spyder-ide/spyder/pull/4696) - PR: Rename "Path" label to "Current working directory" in Find in Files * [PR 4691](https://github.com/spyder-ide/spyder/pull/4691) - PR: Implement dedicated IPython consoles * [PR 4682](https://github.com/spyder-ide/spyder/pull/4682) - PR: Added IPython >= 4.0 as a dependency * [PR 4670](https://github.com/spyder-ide/spyder/pull/4670) - PR: Add detection of external Spyder kernels * [PR 4667](https://github.com/spyder-ide/spyder/pull/4667) - PR: Update ArrayEditor to correct deprecated Numpy operator * [PR 4666](https://github.com/spyder-ide/spyder/pull/4666) - PR: Don't register external plugins if check_compatibility fails * [PR 4661](https://github.com/spyder-ide/spyder/pull/4661) - PR: Fix fileswitcher size during its setup * [PR 4651](https://github.com/spyder-ide/spyder/pull/4651) - PR: Avoid comments to generate pep8 warnings * [PR 4647](https://github.com/spyder-ide/spyder/pull/4647) - PR: Set Numpy threshold every time we run value_to_display * [PR 4644](https://github.com/spyder-ide/spyder/pull/4644) - PR: Add a check to verify compatibility to plugins * [PR 4638](https://github.com/spyder-ide/spyder/pull/4638) - PR: Implement "Replace in selection" in the Editor * [PR 4637](https://github.com/spyder-ide/spyder/pull/4637) - PR: Give focus to the right entry in the file switcher * [PR 4634](https://github.com/spyder-ide/spyder/pull/4634) - PR: Fix several issues about the Working Directory toolbar * [PR 4633](https://github.com/spyder-ide/spyder/pull/4633) - PR: Make test_calltip to time out to avoid long waiting times in Appveyor * [PR 4631](https://github.com/spyder-ide/spyder/pull/4631) - PR: Fix error when calling keyPressEvent in keyReleaseEvent in CodeEditor * [PR 4630](https://github.com/spyder-ide/spyder/pull/4630) - PR: Move Spyder kernel spec to its own file * [PR 4628](https://github.com/spyder-ide/spyder/pull/4628) - PR: Backport PR #4627 * [PR 4626](https://github.com/spyder-ide/spyder/pull/4626) - PR: Create a unique instance of the file switcher attached to the main window * [PR 4621](https://github.com/spyder-ide/spyder/pull/4621) - PR: Add git command for changing base branch to Contributing guide * [PR 4616](https://github.com/spyder-ide/spyder/pull/4616) - PR: Display collections with None values in the Variable Explorer * [PR 4613](https://github.com/spyder-ide/spyder/pull/4613) - PR: Move modules test to Circle and all pytest's to Travis * [PR 4612](https://github.com/spyder-ide/spyder/pull/4612) - PR: Add same behaviour for go to previous cell as the one in Matlab * [PR 4607](https://github.com/spyder-ide/spyder/pull/4607) - PR: Fix unwanted scrolling when selecting tabs * [PR 4603](https://github.com/spyder-ide/spyder/pull/4603) - PR: Add break condition to Markdown syntax highlighter loop * [PR 4602](https://github.com/spyder-ide/spyder/pull/4602) - PR: Update Rope to 0.10.5+ * [PR 4601](https://github.com/spyder-ide/spyder/pull/4601) - PR: Add pyopengl to setup.py to fix errors with some Nvidia/Intel drivers * [PR 4599](https://github.com/spyder-ide/spyder/pull/4599) - PR: More find in files improvements * [PR 4598](https://github.com/spyder-ide/spyder/pull/4598) - PR: Add more file type icons to File Explorer * [PR 4585](https://github.com/spyder-ide/spyder/pull/4585) - PR: Prevent hangs and showing tips after tour * [PR 4583](https://github.com/spyder-ide/spyder/pull/4583) - PR: Add Whitespace option in the import wizard * [PR 4579](https://github.com/spyder-ide/spyder/pull/4579) - PR: Return value of fix_indentation_smart in fix_indentation * [PR 4573](https://github.com/spyder-ide/spyder/pull/4573) - PR: Invert indent shortcuts * [PR 4567](https://github.com/spyder-ide/spyder/pull/4567) - PR: Add indentation shortcuts and simple indentation for non-Python files * [PR 4562](https://github.com/spyder-ide/spyder/pull/4562) - PR: Add actions to show sys.path and environment variables contents to the IPython console * [PR 4561](https://github.com/spyder-ide/spyder/pull/4561) - PR: Use Python module to launch pylint * [PR 4558](https://github.com/spyder-ide/spyder/pull/4558) - PR: Backport PR 4538 * [PR 4549](https://github.com/spyder-ide/spyder/pull/4549) - PR: Stop loading the Python console * [PR 4544](https://github.com/spyder-ide/spyder/pull/4544) - PR: Fix font size for the Help plugin * [PR 4541](https://github.com/spyder-ide/spyder/pull/4541) - PR: Remove connection between the Editor and the Python console * [PR 4539](https://github.com/spyder-ide/spyder/pull/4539) - PR: Make Shift+Enter search backwards in Find and Replace widget * [PR 4537](https://github.com/spyder-ide/spyder/pull/4537) - PR: Find in Files style and UI improvements * [PR 4536](https://github.com/spyder-ide/spyder/pull/4536) - PR: Hide the Python console at startup until we completely remove it * [PR 4535](https://github.com/spyder-ide/spyder/pull/4535) - PR: Change Editor title to display file path again * [PR 4534](https://github.com/spyder-ide/spyder/pull/4534) - PR: Force current cell to be before of current line in extra_selections * [PR 4533](https://github.com/spyder-ide/spyder/pull/4533) - PR: Remove connection between Help and the Python Console * [PR 4532](https://github.com/spyder-ide/spyder/pull/4532) - PR: Delete extra shortcut for the Outline Explorer * [PR 4528](https://github.com/spyder-ide/spyder/pull/4528) - PR: Skip test_values_dbg because it times out too much * [PR 4527](https://github.com/spyder-ide/spyder/pull/4527) - PR: Fix error in decorators regex in syntaxhighlighter. * [PR 4525](https://github.com/spyder-ide/spyder/pull/4525) - PR: Remove connection between the Variable Explorer and the Python console * [PR 4523](https://github.com/spyder-ide/spyder/pull/4523) - PR: Add "Save copy as..." to file menu * [PR 4522](https://github.com/spyder-ide/spyder/pull/4522) - PR: Handle socket creation errors during start up * [PR 4521](https://github.com/spyder-ide/spyder/pull/4521) - PR: Register spyder_io plugins correctly * [PR 4511](https://github.com/spyder-ide/spyder/pull/4511) - PR: Fix error in message about reseting Spyder configuration * [PR 4507](https://github.com/spyder-ide/spyder/pull/4507) - PR: Restore Python 3.6 tests in AppVeyor and add Python 3.5 as well * [PR 4500](https://github.com/spyder-ide/spyder/pull/4500) - PR: Move some tests and coveralls to Travis * [PR 4486](https://github.com/spyder-ide/spyder/pull/4486) - PR: Some indentation fixes * [PR 4485](https://github.com/spyder-ide/spyder/pull/4485) - PR: Fix indentation error when a line starts with return but it's not a return statement * [PR 4477](https://github.com/spyder-ide/spyder/pull/4477) - PR: Disable tab with setting when indent chars are spaces. * [PR 4465](https://github.com/spyder-ide/spyder/pull/4465) - PR: Complete annotation types in Preferences and Source toolbox * [PR 4456](https://github.com/spyder-ide/spyder/pull/4456) - PR: Add more regular code annotation types * [PR 4454](https://github.com/spyder-ide/spyder/pull/4454) - PR: Add an option to set a custom HiDPI scale factor * [PR 4449](https://github.com/spyder-ide/spyder/pull/4449) - PR: Fix a couple of errors in our tests after Pandas 0.20 was released * [PR 4448](https://github.com/spyder-ide/spyder/pull/4448) - PR: Fix a few typos in the FR locale file * [PR 4414](https://github.com/spyder-ide/spyder/pull/4414) - PR: Implement go to previous/next cell shortcuts * [PR 4370](https://github.com/spyder-ide/spyder/pull/4370) - PR: Remove misplaced flags from re.sub() call * [PR 4354](https://github.com/spyder-ide/spyder/pull/4354) - PR: Delete formlayout.py * [PR 4352](https://github.com/spyder-ide/spyder/pull/4352) - PR: Add Markdown syntax highlighter. * [PR 4346](https://github.com/spyder-ide/spyder/pull/4346) - PR: Fix tests in Appveyor * [PR 4337](https://github.com/spyder-ide/spyder/pull/4337) - PR: Add 'Show in external file explorer' option * [PR 4302](https://github.com/spyder-ide/spyder/pull/4302) - PR: Add a tab switcher dialog to the Editor * [PR 4301](https://github.com/spyder-ide/spyder/pull/4301) - PR: Avoid tab scrolling when changing current tab. * [PR 4273](https://github.com/spyder-ide/spyder/pull/4273) - PR: Add Contributing file * [PR 4267](https://github.com/spyder-ide/spyder/pull/4267) - PR: Add missing parameter to copy contents with the format defined in array editor * [PR 4252](https://github.com/spyder-ide/spyder/pull/4252) - PR: Make Cython a test dependency in setup.py * [PR 4229](https://github.com/spyder-ide/spyder/pull/4229) - PR: Backport PR #4198 - Cython support * [PR 4218](https://github.com/spyder-ide/spyder/pull/4218) - PR: Change from pep8 to pycodestyle for style analysis * [PR 4211](https://github.com/spyder-ide/spyder/pull/4211) - PR: Backport PR #4210 - Improve Cython syntax highlighting * [PR 4202](https://github.com/spyder-ide/spyder/pull/4202) - PR: Fix several IPdb problems and add some improvements to it * [PR 4201](https://github.com/spyder-ide/spyder/pull/4201) - PR: Remove u function from py3compat * [PR 4092](https://github.com/spyder-ide/spyder/pull/4092) - PR: Add the possibility to rename IPython consoles * [PR 4056](https://github.com/spyder-ide/spyder/pull/4056) - PR: Several Find in Files improvements * [PR 4045](https://github.com/spyder-ide/spyder/pull/4045) - PR: Make status bar widgets to have a fixed width * [PR 4044](https://github.com/spyder-ide/spyder/pull/4044) - PR: Add "run selection" icon to run toolbar * [PR 4040](https://github.com/spyder-ide/spyder/pull/4040) - PR: Show internal errors in a QMessageBox * [PR 4033](https://github.com/spyder-ide/spyder/pull/4033) - PR: Allow new files to be saved before modifing them. * [PR 4027](https://github.com/spyder-ide/spyder/pull/4027) - PR: Pressing Enter in the "Replace with" entry of Find/Replace replaces the currently selected text * [PR 4000](https://github.com/spyder-ide/spyder/pull/4000) - PR: Make IPython Console to use the same color scheme of the Editor * [PR 3974](https://github.com/spyder-ide/spyder/pull/3974) - PR: Added shortcut and menu option to re-run last cell * [PR 3964](https://github.com/spyder-ide/spyder/pull/3964) - PR: Update load_matlab and add test * [PR 3946](https://github.com/spyder-ide/spyder/pull/3946) - PR: Make Editor tabs movable * [PR 3906](https://github.com/spyder-ide/spyder/pull/3906) - PR: Don't show TextEditor if it fails to be initialized * [PR 3491](https://github.com/spyder-ide/spyder/pull/3491) - PR: Make Pygments to work correctly with QSyntaxHighlighter * [PR 3464](https://github.com/spyder-ide/spyder/pull/3464) - PR: Add a Shortcuts Summary window In this release 111 pull requests were merged ---- ## Version 3.1.4 (2017-04-24) ### Bugs fixed **Issues** * [Issue 4372](https://github.com/spyder-ide/spyder/issues/4372) - Update translations for 3.1.4 * [Issue 4284](https://github.com/spyder-ide/spyder/issues/4284) - The message about the removal of the Python console is also shown on the Internal console * [Issue 4233](https://github.com/spyder-ide/spyder/issues/4233) - Python console is stealing focus at startup because of message about its removal * [Issue 4217](https://github.com/spyder-ide/spyder/issues/4217) - "Unable to connect to the internet" problem * [Issue 4191](https://github.com/spyder-ide/spyder/issues/4191) - Kernel dies and can't report errors because of failure to read stderr file * [Issue 4174](https://github.com/spyder-ide/spyder/issues/4174) - Add our required packages for testing to setup.py * [Issue 4173](https://github.com/spyder-ide/spyder/issues/4173) - Add a message in the update dialog about not using pip if Spyder is running under Anaconda/Miniconda * [Issue 4172](https://github.com/spyder-ide/spyder/issues/4172) - Add a message to the Python console about its removal in Spyder 3.2 * [Issue 4170](https://github.com/spyder-ide/spyder/issues/4170) - IPython console fails to start (Ipython >=6.x) * [Issue 4161](https://github.com/spyder-ide/spyder/issues/4161) - Create a test for finding print statements in the code * [Issue 4141](https://github.com/spyder-ide/spyder/issues/4141) - Code completion breaks with Spyder 3 for modules added through the Python path manager * [Issue 4003](https://github.com/spyder-ide/spyder/issues/4003) - Debugging seems to break with recent versions of Spyder and tqdm * [Issue 4002](https://github.com/spyder-ide/spyder/issues/4002) - %matplolib magic command in IPython terminal needs to be executed twice * [Issue 3985](https://github.com/spyder-ide/spyder/issues/3985) - Add CI testing with Python 3.6 * [Issue 3967](https://github.com/spyder-ide/spyder/issues/3967) - Hide calltip when a matching `)` is written up to the starting point where it's shown * [Issue 3926](https://github.com/spyder-ide/spyder/issues/3926) - File switcher doesn't leave focus in its last selected file when it looses focus * [Issue 3823](https://github.com/spyder-ide/spyder/issues/3823) - sig_new_file error when converting notebook to script * [Issue 3195](https://github.com/spyder-ide/spyder/issues/3195) - Test stand alone widgets in application * [Issue 1855](https://github.com/spyder-ide/spyder/issues/1855) - can't run doctest - unexpected keyword argument 'nosigint' In this release 19 issues were closed **Pull requests** * [PR 4389](https://github.com/spyder-ide/spyder/pull/4389) - PR: Update Spanish translation * [PR 4387](https://github.com/spyder-ide/spyder/pull/4387) - PR: Update Japanese translation * [PR 4375](https://github.com/spyder-ide/spyder/pull/4375) - PR: Update Russian translations * [PR 4369](https://github.com/spyder-ide/spyder/pull/4369) - PR: Add encoding handling to stderr files in the IPython Console * [PR 4361](https://github.com/spyder-ide/spyder/pull/4361) - PR: Fix some inline backend issues * [PR 4353](https://github.com/spyder-ide/spyder/pull/4353) - PR: Test conversion of notebooks to Python files from the Project Explorer * [PR 4345](https://github.com/spyder-ide/spyder/pull/4345) - PR: Simplify Appveyor installation * [PR 4342](https://github.com/spyder-ide/spyder/pull/4342) - PR: Decrease test times by moving Qt4 tests to Travis * [PR 4341](https://github.com/spyder-ide/spyder/pull/4341) - PR: Make jedi_patch.py to work with Jedi 0.10.x versions * [PR 4321](https://github.com/spyder-ide/spyder/pull/4321) - PR: Add all tests to the distributed package * [PR 4311](https://github.com/spyder-ide/spyder/pull/4311) - PR: More robust username query * [PR 4293](https://github.com/spyder-ide/spyder/pull/4293) - PR: Skip and re-run some tests that fail too much * [PR 4292](https://github.com/spyder-ide/spyder/pull/4292) - PR: Backport PR #4286 * [PR 4290](https://github.com/spyder-ide/spyder/pull/4290) - PR: Add support for other plugins in File Switcher * [PR 4283](https://github.com/spyder-ide/spyder/pull/4283) - PR: Don't fail while running tests if coveralls fails for whatever reason * [PR 4263](https://github.com/spyder-ide/spyder/pull/4263) - PR: Add Spyder PYTHONPATH to PluginClient * [PR 4256](https://github.com/spyder-ide/spyder/pull/4256) - PR: Some test fixes * [PR 4251](https://github.com/spyder-ide/spyder/pull/4251) - PR: Add pytest-xvfb to our test dependencies * [PR 4249](https://github.com/spyder-ide/spyder/pull/4249) - PR: Run our tests with PyQt5 wheels on CircleCI * [PR 4248](https://github.com/spyder-ide/spyder/pull/4248) - PR: Change how to add removal message for the Python console to not make it steal focus * [PR 4247](https://github.com/spyder-ide/spyder/pull/4247) - PR: Added sigint argument to SpyderPdb constructor * [PR 4246](https://github.com/spyder-ide/spyder/pull/4246) - PR: Make %matplotlib magic to really change backends * [PR 4237](https://github.com/spyder-ide/spyder/pull/4237) - PR: Don't show internet conection errors on startup when trying to check for new releases * [PR 4230](https://github.com/spyder-ide/spyder/pull/4230) - PR: Run tests for PyQt4 and Python 3.6 on CircleCI * [PR 4226](https://github.com/spyder-ide/spyder/pull/4226) - PR: Generalice previous is_instance test to search other avoided patterns * [PR 4224](https://github.com/spyder-ide/spyder/pull/4224) - PR: Add warning message about updating Spyder if installed with Anaconda * [PR 4208](https://github.com/spyder-ide/spyder/pull/4208) - PR: Surround deprecated IPython quick_quide import by try/except block * [PR 4199](https://github.com/spyder-ide/spyder/pull/4199) - PR: Move all tests to be pytest's * [PR 4189](https://github.com/spyder-ide/spyder/pull/4189) - PR: Fixup MANIFEST.in to include the changelog * [PR 4185](https://github.com/spyder-ide/spyder/pull/4185) - PR: Add testing requirements to setup.py * [PR 4177](https://github.com/spyder-ide/spyder/pull/4177) - PR: Add a message informing the removal of the Python console * [PR 4123](https://github.com/spyder-ide/spyder/pull/4123) - PR: Add AppStream metainfo file * [PR 4121](https://github.com/spyder-ide/spyder/pull/4121) - PR: Monkey patch Jedi 0.10.0 for numpydoc * [PR 4019](https://github.com/spyder-ide/spyder/pull/4019) - PR: Handle errors while debugging code when importing tqdm * [PR 3984](https://github.com/spyder-ide/spyder/pull/3984) - PR: Correctly hide calltip when matching closing parenthesis * [PR 3956](https://github.com/spyder-ide/spyder/pull/3956) - PR: Add missing signal to convert notebooks from the project explorer * [PR 3952](https://github.com/spyder-ide/spyder/pull/3952) - PR: Make File Switcher leave focus on its last selected file when it loses focus In this release 37 pull requests were merged ---- ## Version 3.1.3 (2017-02-20) ### Bugs fixed **Issues** * [Issue 4139](https://github.com/spyder-ide/spyder/issues/4139) - Nan value in dataframe editor crash Spyder * [Issue 4128](https://github.com/spyder-ide/spyder/issues/4128) - Add the version of PyQt in the report of the issue * [Issue 4127](https://github.com/spyder-ide/spyder/issues/4127) - UnboundLocalError: local variable 'img_path' referenced before assignment * [Issue 4122](https://github.com/spyder-ide/spyder/issues/4122) - Spyder closes after completing Run settings dialog for a first run. * [Issue 4096](https://github.com/spyder-ide/spyder/issues/4096) - More issues with autoindentation * [Issue 4088](https://github.com/spyder-ide/spyder/issues/4088) - Crash when saving an image in the IPython console * [Issue 4086](https://github.com/spyder-ide/spyder/issues/4086) - Error when launching a new Editor window from the options in the menu. * [Issue 4085](https://github.com/spyder-ide/spyder/issues/4085) - Crash in "New window" when opening new file. * [Issue 4076](https://github.com/spyder-ide/spyder/issues/4076) - Add tests to verify that importing .mat files is working * [Issue 4074](https://github.com/spyder-ide/spyder/issues/4074) - Identation broken after statements with closing parenthesis followed by more code * [Issue 4072](https://github.com/spyder-ide/spyder/issues/4072) - Case sensitive replace does not respect case * [Issue 4066](https://github.com/spyder-ide/spyder/issues/4066) - Spyder core dumps if an opened variable in variable explorer gets deleted * [Issue 4063](https://github.com/spyder-ide/spyder/issues/4063) - Spyder crashes when killing the current process to start a new one * [Issue 4053](https://github.com/spyder-ide/spyder/issues/4053) - Spyder 3.1.2 cannot connect to kernel as 3.0.2 * [Issue 4052](https://github.com/spyder-ide/spyder/issues/4052) - Maximising current pane fails and hangs Spyder 3.1.x * [Issue 4050](https://github.com/spyder-ide/spyder/issues/4050) - Wrong binary in Python 3 wheels * [Issue 4041](https://github.com/spyder-ide/spyder/issues/4041) - Create a way to add tests for the whole app * [Issue 4037](https://github.com/spyder-ide/spyder/issues/4037) - Tabs as indentation - characters being removed in editor * [Issue 4030](https://github.com/spyder-ide/spyder/issues/4030) - Inconsistent icon for "Find symbols in file..." * [Issue 4005](https://github.com/spyder-ide/spyder/issues/4005) - Find in Files not working after 3.1.0 update * [Issue 3992](https://github.com/spyder-ide/spyder/issues/3992) - Remove unnecessary newlines in run cell * [Issue 3972](https://github.com/spyder-ide/spyder/issues/3972) - Remove file path from Editor's plugin title * [Issue 3970](https://github.com/spyder-ide/spyder/issues/3970) - Error when editing markdown * [Issue 3917](https://github.com/spyder-ide/spyder/issues/3917) - Failed to import data in Variable Explorer on Windows * [Issue 3476](https://github.com/spyder-ide/spyder/issues/3476) - New breakpoints can't be created in the IPython console In this release 25 issues were closed **Pull requests** * [PR 4175](https://github.com/spyder-ide/spyder/pull/4175) - PR: Set new breakpoints in the IPython console while on a debugging session * [PR 4171](https://github.com/spyder-ide/spyder/pull/4171) - PR: Re-run flaky tests several times * [PR 4165](https://github.com/spyder-ide/spyder/pull/4165) - PR: Loading spydata files now uncompress them inside a temp folder * [PR 4152](https://github.com/spyder-ide/spyder/pull/4152) - PR: Skip matlab import test if SciPy is not installed. * [PR 4151](https://github.com/spyder-ide/spyder/pull/4151) - PR: Make tests more reliable * [PR 4148](https://github.com/spyder-ide/spyder/pull/4148) - PR: Use an older Miniconda version for Python 3 * [PR 4144](https://github.com/spyder-ide/spyder/pull/4144) - PR: Some fixes for Find in files * [PR 4142](https://github.com/spyder-ide/spyder/pull/4142) - PR: Gracefully handle ValueError in DataFrameModel * [PR 4140](https://github.com/spyder-ide/spyder/pull/4140) - PR: Disable some tests on Windows because they are timing out recurrently * [PR 4133](https://github.com/spyder-ide/spyder/pull/4133) - PR: Add an initialization value to img_path * [PR 4130](https://github.com/spyder-ide/spyder/pull/4130) - PR: Correctly stop pytest's on failure * [PR 4129](https://github.com/spyder-ide/spyder/pull/4129) - PR: Add Qt and PyQt version in the report of the issue * [PR 4125](https://github.com/spyder-ide/spyder/pull/4125) - PR: Make loading IPython kernels by using their ids to work again * [PR 4113](https://github.com/spyder-ide/spyder/pull/4113) - PR: Add a validation for the PyQt version used to show a message in the Python console * [PR 4110](https://github.com/spyder-ide/spyder/pull/4110) - PR: Add more tests for the main window * [PR 4109](https://github.com/spyder-ide/spyder/pull/4109) - PR: Fix maximize button * [PR 4106](https://github.com/spyder-ide/spyder/pull/4106) - PR: Prevent some crashes and errors when editing objects in the Variable Explorer * [PR 4105](https://github.com/spyder-ide/spyder/pull/4105) - PR: Fix hard crash when trying to open files in a new editor window * [PR 4104](https://github.com/spyder-ide/spyder/pull/4104) - PR: Pin Jedi to 0.9.0 * [PR 4102](https://github.com/spyder-ide/spyder/pull/4102) - PR: Added Matlab files import tests * [PR 4097](https://github.com/spyder-ide/spyder/pull/4097) - PR: Add a validation for editorstack existence * [PR 4082](https://github.com/spyder-ide/spyder/pull/4082) - PR: More autoindentation fixes * [PR 4079](https://github.com/spyder-ide/spyder/pull/4079) - PR: Add a flag to use case sensitive search/replace * [PR 4069](https://github.com/spyder-ide/spyder/pull/4069) - PR: Fix executable name in Python 3 wheels * [PR 4043](https://github.com/spyder-ide/spyder/pull/4043) - PR: Use the "at" symbol to represent the symbol finder everywhere * [PR 4042](https://github.com/spyder-ide/spyder/pull/4042) - PR: Unindent with tabs was deleting some text. * [PR 4034](https://github.com/spyder-ide/spyder/pull/4034) - PR: Fix error when using TextSH (default highligher) * [PR 4006](https://github.com/spyder-ide/spyder/pull/4006) - PR: Remove unnecessary new lines when running cells * [PR 3975](https://github.com/spyder-ide/spyder/pull/3975) - PR: Remove file path from the Editor's plugin title. In this release 29 pull requests were merged ---- ## Version 3.1.2 (2017-01-24) ### Bugs fixed **Issues** * [Issue 4025](https://github.com/spyder-ide/spyder/issues/4025) - Error when running cell for the first time in the Editor * [Issue 4021](https://github.com/spyder-ide/spyder/issues/4021) - Spyder fails to import numpy on first line of a file In this release 2 issues were closed **Pull requests** * [PR 4031](https://github.com/spyder-ide/spyder/pull/4031) - PR: Fix error when running cells because previous_focused_widget is not initialized in main window * [PR 4029](https://github.com/spyder-ide/spyder/pull/4029) - PR: Fix fix_indent() when editor cursor is on the first line In this release 2 pull requests were merged ---- ## Version 3.1.1 (2017-01-22) ### Bugs fixed **Issues** * [Issue 4012](https://github.com/spyder-ide/spyder/issues/4012) - Edit menu items greyed out after update to Spyder 3.1.0 * [Issue 3989](https://github.com/spyder-ide/spyder/issues/3989) - Spyder won't start after upgrade to 3.1.0 due to an error with QRegularExpression * [Issue 3987](https://github.com/spyder-ide/spyder/issues/3987) - Errors running or importing code because sys.argv is empty In this release 3 issues were closed **Pull requests** * [PR 4022](https://github.com/spyder-ide/spyder/pull/4022) - PR: Edit menu disable error * [PR 3997](https://github.com/spyder-ide/spyder/pull/3997) - PR: Enclosing quotes of sys.argv clearing instruction are now consistent * [PR 3994](https://github.com/spyder-ide/spyder/pull/3994) - PR: Use QRegularExpression only for Qt 5.5+ In this release 3 pull requests were merged ---- ## Version 3.1 (2017-01-18) ### New features #### Main Window * Add Introduction interactive tour to explain the main Spyder components (in `Help > Interactive tours`). This tour was announced in Spyder 3.0 but deactivated due to an error. #### Editor * Add the Solarized Light and Dark color schemes. * Add support for greedy regular expressions in the find/replace widget (only available with PyQt5). * Improve the use of tabs instead of spaces for indentation. * Add `Ctrl+Shift+T` shortcut to reopen the last closed file. * Show completions for Numpy and Matplotlib compiled objects (e.g. `np.array` and `plt.figure`) * Disambiguate tabs in case users open several files with the same name. * Add the shortcut `Ctrl+Alt+P` to open a switcher to select among the symbols (functions, methods or classes) present in a file. Also add an entry in the `File` menu and toolbar button to show this switcher. #### Variable Explorer * Add support for the most important numeric types of Numpy (32 and 64 bits int, float and complex numbers). * Save format for floats in DataFrame editor. * Make the index column of DataFrame editor always visible when scrolling to right and left. * Add support for Pandas DatetimeIndex objects. * Show empty Numpy arrays. #### IPython Console * Be able to load kernel json files anywhere in the file system when connecting to external kernels. * Add an option (under `Preferences > Run` and `Run > Configure`) to clear all variables present in a console before running a file (it runs `%reset -f` in the associated kernel). #### Profiler * Show time units (in seconds) spent by each function or method. #### Settings * Make all keyboard shortcuts configurable #### Under the hood * Add the `--project ` command line option to load projects at startup. * Add the chardet and numpydoc libraries as new dependencies. ### Bugs fixed **Issues** * [Issue 3968](https://github.com/spyder-ide/spyder/issues/3968) - Update translations for 3.1 * [Issue 3962](https://github.com/spyder-ide/spyder/issues/3962) - Update Appveyor Badge for new username spyder-ide * [Issue 3961](https://github.com/spyder-ide/spyder/issues/3961) - Add devs to the Appveyor account * [Issue 3949](https://github.com/spyder-ide/spyder/issues/3949) - F9 broken in latest git master * [Issue 3943](https://github.com/spyder-ide/spyder/issues/3943) - Qtpy 1.2.0 breaks Spyder with Qt4 * [Issue 3932](https://github.com/spyder-ide/spyder/issues/3932) - Add verification for 'text/plain' key in all evaluations of the IPython console * [Issue 3925](https://github.com/spyder-ide/spyder/issues/3925) - Go-to-line dialog shows a question mark button that does nothing * [Issue 3901](https://github.com/spyder-ide/spyder/issues/3901) - Incorrect use of "it's" in tutorial * [Issue 3896](https://github.com/spyder-ide/spyder/issues/3896) - Spyder Variable explorer crashes when double clicking a 2 line DataFrame * [Issue 3883](https://github.com/spyder-ide/spyder/issues/3883) - Error when executing argparse in IPython console * [Issue 3875](https://github.com/spyder-ide/spyder/issues/3875) - async and await keywords highlight * [Issue 3874](https://github.com/spyder-ide/spyder/issues/3874) - Spyder freezes on new project creation * [Issue 3859](https://github.com/spyder-ide/spyder/issues/3859) - Extra selections should be ordered * [Issue 3855](https://github.com/spyder-ide/spyder/issues/3855) - Add fuzzy function/class search shortcut * [Issue 3848](https://github.com/spyder-ide/spyder/issues/3848) - 'self' not defined in DataFrameView.update_section_height() * [Issue 3843](https://github.com/spyder-ide/spyder/issues/3843) - Spyder shows blank screen because of errors in QtAwesome * [Issue 3830](https://github.com/spyder-ide/spyder/issues/3830) - Add a command line option to load projects * [Issue 3818](https://github.com/spyder-ide/spyder/issues/3818) - F1 shortcut is hard-coded * [Issue 3809](https://github.com/spyder-ide/spyder/issues/3809) - No call tips when 'Automatic insertion of parentheses, braces and brackets' is unchecked * [Issue 3807](https://github.com/spyder-ide/spyder/issues/3807) - Directory with non-ascii characters throws an error when it's made the working directory on the IPython console * [Issue 3800](https://github.com/spyder-ide/spyder/issues/3800) - Auto indentation of line following indented block * [Issue 3794](https://github.com/spyder-ide/spyder/issues/3794) - Create menu separator instead of None * [Issue 3788](https://github.com/spyder-ide/spyder/issues/3788) - runfile with path containing apostrophe will not work * [Issue 3772](https://github.com/spyder-ide/spyder/issues/3772) - Configparser error leads to crash of Spyder 3 under Python(x,y) * [Issue 3764](https://github.com/spyder-ide/spyder/issues/3764) - Problems with default extension in save_as * [Issue 3763](https://github.com/spyder-ide/spyder/issues/3763) - Replace contents of Find widget with current selection * [Issue 3759](https://github.com/spyder-ide/spyder/issues/3759) - KeyError: 'execution_count' in IPython console * [Issue 3756](https://github.com/spyder-ide/spyder/issues/3756) - Verify that the interpreter selected in Main Interpreter is really a Python interpreter * [Issue 3755](https://github.com/spyder-ide/spyder/issues/3755) - Redefined hotkeys are not displayed in menu * [Issue 3753](https://github.com/spyder-ide/spyder/issues/3753) - Saving a file is not respecting the encoding detected with chardet * [Issue 3748](https://github.com/spyder-ide/spyder/issues/3748) - Bad window size in spyder.ini prevents Spyder from showing * [Issue 3746](https://github.com/spyder-ide/spyder/issues/3746) - Menu view/toolbar has empty contents * [Issue 3738](https://github.com/spyder-ide/spyder/issues/3738) - Spyder crashes at startup because of errors when importing Sympy * [Issue 3737](https://github.com/spyder-ide/spyder/issues/3737) - Fast switch between files gives error for unicode files * [Issue 3731](https://github.com/spyder-ide/spyder/issues/3731) - Correctly report the encoding of files in the Editor using the chardet library * [Issue 3729](https://github.com/spyder-ide/spyder/issues/3729) - Define tabulation width in term of spaces instead of pixels * [Issue 3706](https://github.com/spyder-ide/spyder/issues/3706) - Spyder fails to create kernel.json files if jupyter_runtime_dir is not writable * [Issue 3704](https://github.com/spyder-ide/spyder/issues/3704) - Create a get_words method in introspection utils * [Issue 3703](https://github.com/spyder-ide/spyder/issues/3703) - Don't replace text in the find widget if there's text there * [Issue 3700](https://github.com/spyder-ide/spyder/issues/3700) - Wrong autoindentation with lists that contains strings with parenthesis * [Issue 3680](https://github.com/spyder-ide/spyder/issues/3680) - Autoindentation not working in first line * [Issue 3678](https://github.com/spyder-ide/spyder/issues/3678) - Weird behaviour of Save as... * [Issue 3672](https://github.com/spyder-ide/spyder/issues/3672) - Profiler is not showing time units * [Issue 3670](https://github.com/spyder-ide/spyder/issues/3670) - Dragging and dropping files in the Editor is failing * [Issue 3651](https://github.com/spyder-ide/spyder/issues/3651) - Improve indentation tests * [Issue 3648](https://github.com/spyder-ide/spyder/issues/3648) - Edit menu shortcuts are invisible * [Issue 3638](https://github.com/spyder-ide/spyder/issues/3638) - Variable explorer should display the value of numpy.int64 variables * [Issue 3631](https://github.com/spyder-ide/spyder/issues/3631) - Edit context menu appears only for utf-8 files in project explorer * [Issue 3630](https://github.com/spyder-ide/spyder/issues/3630) - Load external kernel json files from anywhere in the file system * [Issue 3627](https://github.com/spyder-ide/spyder/issues/3627) - Spyder won't start because of "ValueError: unknown locale: UTF-8" in macOS * [Issue 3608](https://github.com/spyder-ide/spyder/issues/3608) - Syntax highlighting of decorators * [Issue 3535](https://github.com/spyder-ide/spyder/issues/3535) - Run ciocheck as part of our tests to test code style * [Issue 3508](https://github.com/spyder-ide/spyder/issues/3508) - Indentation issue using Tabs * [Issue 3480](https://github.com/spyder-ide/spyder/issues/3480) - Editor doesn't support hanging indentation * [Issue 3473](https://github.com/spyder-ide/spyder/issues/3473) - Incorrect auto-indentation * [Issue 3461](https://github.com/spyder-ide/spyder/issues/3461) - Click on outisde of tour should exit tour * [Issue 3459](https://github.com/spyder-ide/spyder/issues/3459) - Auto-adjust rows height in the Variable Explorer * [Issue 3458](https://github.com/spyder-ide/spyder/issues/3458) - Feature Request: Clear Console After Kernel Restart * [Issue 3452](https://github.com/spyder-ide/spyder/issues/3452) - Interactive tour freezes Spyder on Windows * [Issue 3415](https://github.com/spyder-ide/spyder/issues/3415) - Can't change Run Selection keyboard shortcut from F9 to Cmd + Shift + Enter * [Issue 3408](https://github.com/spyder-ide/spyder/issues/3408) - Find and replace: Greedy regular expressions * [Issue 3407](https://github.com/spyder-ide/spyder/issues/3407) - Sitecustomize fails when current directory has non-ascii chars * [Issue 3395](https://github.com/spyder-ide/spyder/issues/3395) - Don't hard code the Ctrl+Enter shortcut * [Issue 3380](https://github.com/spyder-ide/spyder/issues/3380) - DatetimeIndex types are not visible in the Variable Explorer * [Issue 3322](https://github.com/spyder-ide/spyder/issues/3322) - Spyder crashes with Unicode symbols in editor * [Issue 3249](https://github.com/spyder-ide/spyder/issues/3249) - Regex is not fully functional when using to find&replace * [Issue 3160](https://github.com/spyder-ide/spyder/issues/3160) - Disambiguate Editor tabs * [Issue 3141](https://github.com/spyder-ide/spyder/issues/3141) - Search for backslash (\) sign * [Issue 3026](https://github.com/spyder-ide/spyder/issues/3026) - File save as: file is unavailable * [Issue 3005](https://github.com/spyder-ide/spyder/issues/3005) - Getting "Spyder already running" warning when it's not * [Issue 2927](https://github.com/spyder-ide/spyder/issues/2927) - Editor: "move line up/down" commands broken when moving past a blank line * [Issue 2907](https://github.com/spyder-ide/spyder/issues/2907) - Modified file flag ('*') disappears from tab in the Editor * [Issue 2728](https://github.com/spyder-ide/spyder/issues/2728) - Add the default format in dataframe editor to user preferences * [Issue 2644](https://github.com/spyder-ide/spyder/issues/2644) - Editor: Popup showing function arguments only displayed for 3 seconds * [Issue 2563](https://github.com/spyder-ide/spyder/issues/2563) - Enhancement: add option to "clear all" variables before running script * [Issue 2512](https://github.com/spyder-ide/spyder/issues/2512) - Index column of Pandas DataFrame should be visible all the time * [Issue 2415](https://github.com/spyder-ide/spyder/issues/2415) - Add shortcut to open last closed tab * [Issue 2392](https://github.com/spyder-ide/spyder/issues/2392) - Current EOL status is displayed incorrectly after changing it * [Issue 1165](https://github.com/spyder-ide/spyder/issues/1165) - Console tabs are too big because they display the full filename In this release 79 issues were closed **Pull requests** * [PR 3983](https://github.com/spyder-ide/spyder/pull/3983) - Update Spanish translations * [PR 3982](https://github.com/spyder-ide/spyder/pull/3982) - PR: More fixes for Appveyor * [PR 3979](https://github.com/spyder-ide/spyder/pull/3979) - Update Brazilian Portuguese translation * [PR 3971](https://github.com/spyder-ide/spyder/pull/3971) - PR: Don't run pytest tests when running modules_test.bat in Appveyor * [PR 3963](https://github.com/spyder-ide/spyder/pull/3963) - PR: Update AppVeyor badge in Readme because of move to org account * [PR 3960](https://github.com/spyder-ide/spyder/pull/3960) - PR: Ping conda-build to 2.1.0 for compatibility with conda 4.3 in Travis and AppVeyor * [PR 3951](https://github.com/spyder-ide/spyder/pull/3951) - PR: Add default value to clear_variables=False in execute code method * [PR 3944](https://github.com/spyder-ide/spyder/pull/3944) - PR: Change setResizeMode to setSectionResizeMode * [PR 3936](https://github.com/spyder-ide/spyder/pull/3936) - PR: Backport PR #3577 - Use inspect.getfullargspec to support annotated functions in the Help pane * [PR 3935](https://github.com/spyder-ide/spyder/pull/3935) - PR: Add validation for 'text/plain' key in all if clauses of handle_exec_method * [PR 3933](https://github.com/spyder-ide/spyder/pull/3933) - PR: Catch LookupError when encoding in encode() function * [PR 3931](https://github.com/spyder-ide/spyder/pull/3931) - PR: Add some tests for indentation with brackets * [PR 3930](https://github.com/spyder-ide/spyder/pull/3930) - PR: Use encoding.encode function in run_code_analysis. * [PR 3929](https://github.com/spyder-ide/spyder/pull/3929) - PR: Save file with original encoding if possible * [PR 3927](https://github.com/spyder-ide/spyder/pull/3927) - PR: Remove question mark button on the 'Go to line' dialog. * [PR 3920](https://github.com/spyder-ide/spyder/pull/3920) - PR: Incorrect use of "it's" in tutorial * [PR 3918](https://github.com/spyder-ide/spyder/pull/3918) - PR: Clean sys.argv in our IPython kernels * [PR 3898](https://github.com/spyder-ide/spyder/pull/3898) - PR: Get the proper encoding for the header text of Dataframe editor * [PR 3893](https://github.com/spyder-ide/spyder/pull/3893) - PR: Show calltips when 'Automatic insertion of parentheses, braces and brackets' is unchecked * [PR 3886](https://github.com/spyder-ide/spyder/pull/3886) - PR: Add a way to handle font errors in QtAwesome * [PR 3885](https://github.com/spyder-ide/spyder/pull/3885) - PR: Add async and await as keywords for syntax highlighting * [PR 3884](https://github.com/spyder-ide/spyder/pull/3884) - PR: Hide tour tips dialog when Spyder looses focus * [PR 3879](https://github.com/spyder-ide/spyder/pull/3879) - PR: Make Spyder not to freeze on new project creation * [PR 3878](https://github.com/spyder-ide/spyder/pull/3878) - PR: Add function/class search shortcut, menu and toolbar entries * [PR 3871](https://github.com/spyder-ide/spyder/pull/3871) - PR: Add option to "clear all" variables before running file * [PR 3866](https://github.com/spyder-ide/spyder/pull/3866) - PR: Add code to cancel active Appveyor builds in a branch * [PR 3864](https://github.com/spyder-ide/spyder/pull/3864) - PR: Extra selections is now an ordered dictionary * [PR 3861](https://github.com/spyder-ide/spyder/pull/3861) - PR: Show kernel initialization errors in the IPython console * [PR 3854](https://github.com/spyder-ide/spyder/pull/3854) - PR: Add disambiguation functionality to the Python console * [PR 3853](https://github.com/spyder-ide/spyder/pull/3853) - PR: Move rope_patch.py to utils/introspection * [PR 3852](https://github.com/spyder-ide/spyder/pull/3852) - PR: Add missing 'self' to DataFrameView.update_section_height * [PR 3849](https://github.com/spyder-ide/spyder/pull/3849) - PR: Support DatetimeIndex in Variable Explorer * [PR 3847](https://github.com/spyder-ide/spyder/pull/3847) - PR: Make regex fully functional when using find & replace * [PR 3845](https://github.com/spyder-ide/spyder/pull/3845) - PR: Install ciocheck from the spyder-ide Anaconda channel * [PR 3842](https://github.com/spyder-ide/spyder/pull/3842) - PR: Validate that Main Interpreter is really a Python interpreter * [PR 3840](https://github.com/spyder-ide/spyder/pull/3840) - PR: Make conda respect channel priority in CircleCI * [PR 3837](https://github.com/spyder-ide/spyder/pull/3837) - PR: Catch UnicodeDecodeError when trying to import matplotlib in sitecustomize.py. * [PR 3836](https://github.com/spyder-ide/spyder/pull/3836) - PR: Ignore some superflous errors reported by ciocheck * [PR 3834](https://github.com/spyder-ide/spyder/pull/3834) - PR: Add a command line option to load projects * [PR 3827](https://github.com/spyder-ide/spyder/pull/3827) - PR: Don't run Pylint with ciocheck * [PR 3826](https://github.com/spyder-ide/spyder/pull/3826) - PR: Improve auto indentation of line following indented block * [PR 3822](https://github.com/spyder-ide/spyder/pull/3822) - PR: Make Spyder documentation keyboard shortcut configurable * [PR 3817](https://github.com/spyder-ide/spyder/pull/3817) - PR: Fix "move line down" behavior in the presence of blank lines * [PR 3813](https://github.com/spyder-ide/spyder/pull/3813) - PR: Fixed encoding issue when changing cwd in the IPython console * [PR 3811](https://github.com/spyder-ide/spyder/pull/3811) - PR: Make index column of DataFrame editor always visible * [PR 3808](https://github.com/spyder-ide/spyder/pull/3808) - Patch Jedi to get completions for compiled objects in Numpy and Matplotlib * [PR 3806](https://github.com/spyder-ide/spyder/pull/3806) - PR: Added management for toolbars in new Editor windows instances. * [PR 3805](https://github.com/spyder-ide/spyder/pull/3805) - PR: Backport #3803 - Use CircleCI for testing * [PR 3802](https://github.com/spyder-ide/spyder/pull/3802) - PR: Add missing menus to show shortcuts for in macOS * [PR 3796](https://github.com/spyder-ide/spyder/pull/3796) - PR: Make running a file with single quotes on its path not to throw an error on Windows * [PR 3795](https://github.com/spyder-ide/spyder/pull/3795) - PR: Use a menu separator constant instead of None * [PR 3793](https://github.com/spyder-ide/spyder/pull/3793) - PR: Closing tour does not freeze Spyder on windows * [PR 3791](https://github.com/spyder-ide/spyder/pull/3791) - PR: Catch error raised in isbinaryornot when trying to open a directory * [PR 3787](https://github.com/spyder-ide/spyder/pull/3787) - PR: Redefinition of upper/lower shortcuts was not updated in Edit menu * [PR 3785](https://github.com/spyder-ide/spyder/pull/3785) - PR: Change file switcher entries to unicode * [PR 3781](https://github.com/spyder-ide/spyder/pull/3781) - PR: Backport #3574 - Improve style of scientific startup script * [PR 3776](https://github.com/spyder-ide/spyder/pull/3776) - Improve highlighter decorator regexp * [PR 3774](https://github.com/spyder-ide/spyder/pull/3774) - PR: Delete references to the 'xy' module. * [PR 3770](https://github.com/spyder-ide/spyder/pull/3770) - PR: Modified behavior for the Find widget to replace contents with current selection * [PR 3765](https://github.com/spyder-ide/spyder/pull/3765) - PR: Set Python as default file extension for the "Save As" dialog * [PR 3760](https://github.com/spyder-ide/spyder/pull/3760) - PR: Define tabulation width in term of spaces instead of pixels * [PR 3757](https://github.com/spyder-ide/spyder/pull/3757) - PR: Add get_words function to introspection/utils * [PR 3754](https://github.com/spyder-ide/spyder/pull/3754) - PR: Added validation to window/position config value saved in spyder.ini * [PR 3752](https://github.com/spyder-ide/spyder/pull/3752) - Backport pull request #3534 (Solarized themes) * [PR 3749](https://github.com/spyder-ide/spyder/pull/3749) - PR: Fix View/Toolbars menu * [PR 3742](https://github.com/spyder-ide/spyder/pull/3742) - PR: Use chardet as a fallback for encoding detection * [PR 3741](https://github.com/spyder-ide/spyder/pull/3741) - PR: Show time units in Profiler * [PR 3739](https://github.com/spyder-ide/spyder/pull/3739) - Utils: Make is_module_installed to catch all errors when importing a module * [PR 3733](https://github.com/spyder-ide/spyder/pull/3733) - PR: Fix EOL status after changing it * [PR 3719](https://github.com/spyder-ide/spyder/pull/3719) - PR: Spyder wont crash if it can not acces jupyter runtime dir * [PR 3717](https://github.com/spyder-ide/spyder/pull/3717) - PR: Load kernel json files anywhere in the filesystem * [PR 3715](https://github.com/spyder-ide/spyder/pull/3715) - PR: Add disambiguation functionality for Editor tabs * [PR 3709](https://github.com/spyder-ide/spyder/pull/3709) - PR: Don't replace text in the find widget if there's text there * [PR 3707](https://github.com/spyder-ide/spyder/pull/3707) - PR: Disable languages whose translations are outdated * [PR 3699](https://github.com/spyder-ide/spyder/pull/3699) - PR: Remove logic to delete last dir separator (\, /) in find and replace widget * [PR 3696](https://github.com/spyder-ide/spyder/pull/3696) - PR: Use QRegularExpression for find and replace (only for PyQt5) * [PR 3695](https://github.com/spyder-ide/spyder/pull/3695) - PR: Set English as default language if getdefaultlocale gives errors * [PR 3685](https://github.com/spyder-ide/spyder/pull/3685) - PR: Fixed weird behavior of "Save as" * [PR 3675](https://github.com/spyder-ide/spyder/pull/3675) - PR: Several fixes for the Variable Explorer * [PR 3663](https://github.com/spyder-ide/spyder/pull/3663) - PR: Fix some errors of Indentation with tabs * [PR 3659](https://github.com/spyder-ide/spyder/pull/3659) - PR: Improve spyder.lock pid verfication * [PR 3654](https://github.com/spyder-ide/spyder/pull/3654) - PR: Add regex to highlight decorators * [PR 3653](https://github.com/spyder-ide/spyder/pull/3653) - PR: Added support to the principal numeric Numpy types in the Variable Explorer * [PR 3640](https://github.com/spyder-ide/spyder/pull/3640) - PR: Check if files are text files using the binaryornot package * [PR 3620](https://github.com/spyder-ide/spyder/pull/3620) - PR: Add Ctrl+Shift+T shortcut to reopen the last closed Editor tab * [PR 3611](https://github.com/spyder-ide/spyder/pull/3611) - PR: Remember format for floats in DataFrame editor * [PR 3604](https://github.com/spyder-ide/spyder/pull/3604) - PR: Add ciocheck linter formater tester * [PR 3498](https://github.com/spyder-ide/spyder/pull/3498) - PR: Change fixed shortcuts for configurable ones * [PR 3487](https://github.com/spyder-ide/spyder/pull/3487) - PR: Add hanging Indentation to the Editor * [PR 3296](https://github.com/spyder-ide/spyder/pull/3296) - PR: Don't hide calltip widget with a timer In this release 91 pull requests were merged ---- ## Version 3.0.2 (2016/11/20) ### New features * Add an option under *Preferences > General* to enable/disable high DPI scaling (disabled by default). * Add a menu entry in the Projects menu to cleanly delete projects. * Add the shortcuts `Ctrl+U` and `Ctrl+Shift+U` to turn text into lower/uppercase respectively. ### Bugs fixed **Issues** * [Issue 3647](https://github.com/spyder-ide/spyder/issues/3647) - "%reset -s" is giving an error in the IPython console * [Issue 3618](https://github.com/spyder-ide/spyder/issues/3618) - Removing a project deletes also the files on the disk * [Issue 3609](https://github.com/spyder-ide/spyder/issues/3609) - New release dialog is un-clickable * [Issue 3588](https://github.com/spyder-ide/spyder/issues/3588) - Files are opened twice at startup if a project is active * [Issue 3583](https://github.com/spyder-ide/spyder/issues/3583) - Error when connecting to external kernels * [Issue 3575](https://github.com/spyder-ide/spyder/issues/3575) - Cannot press Enter after underscore in File Switcher * [Issue 3564](https://github.com/spyder-ide/spyder/issues/3564) - Error when reloading modules in the IPython Console in Python 2 * [Issue 3561](https://github.com/spyder-ide/spyder/issues/3561) - Working Directory toolbar is not working for IPython Consoles * [Issue 3553](https://github.com/spyder-ide/spyder/issues/3553) - Spyder fails to launch because of Unicode errors in create_kernel_spec * [Issue 3522](https://github.com/spyder-ide/spyder/issues/3522) - Dependencies diaog not updating correctly when installing dependencies while spyder is running * [Issue 3519](https://github.com/spyder-ide/spyder/issues/3519) - Cannot set Maximum Number of Recent Files * [Issue 3513](https://github.com/spyder-ide/spyder/issues/3513) - Spyder does not free up memory after closing windows with datasets in the Variable explorer * [Issue 3489](https://github.com/spyder-ide/spyder/issues/3489) - Display problems on systems that use 'display scaling' * [Issue 3444](https://github.com/spyder-ide/spyder/issues/3444) - Reports of Kernel Death are greatly exagerated * [Issue 3436](https://github.com/spyder-ide/spyder/issues/3436) - Default file extension should be .py instead of empty * [Issue 3430](https://github.com/spyder-ide/spyder/issues/3430) - Update translations * [Issue 3214](https://github.com/spyder-ide/spyder/issues/3214) - Indentation after a line with [] and {} is reset * [Issue 3127](https://github.com/spyder-ide/spyder/issues/3127) - Spyder fails to launch because of errors in spyder.ini * [Issue 2159](https://github.com/spyder-ide/spyder/issues/2159) - Built-in 'print' statement is displayed as two different colors depending on indentation * [Issue 1669](https://github.com/spyder-ide/spyder/issues/1669) - Menu item and shortcut to toggle UPPER and lower case of selected text * [Issue 1665](https://github.com/spyder-ide/spyder/issues/1665) - sympy shadows matplotlib in ipython console * [Issue 1373](https://github.com/spyder-ide/spyder/issues/1373) - Editor autoindentation fails after list, dict In this release 22 issues were closed **Pull requests** * [PR 3702](https://github.com/spyder-ide/spyder/pull/3702) - PR: Update French translation * [PR 3694](https://github.com/spyder-ide/spyder/pull/3694) - Restore icons in the code completion widget * [PR 3687](https://github.com/spyder-ide/spyder/pull/3687) - Increase time to detect if an IPython kernel is alive * [PR 3681](https://github.com/spyder-ide/spyder/pull/3681) - Update Spanish translation * [PR 3679](https://github.com/spyder-ide/spyder/pull/3679) - Update Russian translations * [PR 3664](https://github.com/spyder-ide/spyder/pull/3664) - Free memory when closing a Variable Explorer editor * [PR 3661](https://github.com/spyder-ide/spyder/pull/3661) - IPython Console: Fix error when running "%reset -s" * [PR 3660](https://github.com/spyder-ide/spyder/pull/3660) - IPython Console: Simple fix after PR #3641 * [PR 3642](https://github.com/spyder-ide/spyder/pull/3642) - PR: Fix unclickable update message box * [PR 3641](https://github.com/spyder-ide/spyder/pull/3641) - PR: Fix error when trying to add a non-ascii module in Python 2 to the UMR blacklist * [PR 3629](https://github.com/spyder-ide/spyder/pull/3629) - PR: Add shortcut for Upper/Lower functionality * [PR 3626](https://github.com/spyder-ide/spyder/pull/3626) - PR: Added management for delete operation of a project * [PR 3622](https://github.com/spyder-ide/spyder/pull/3622) - Fix connection between the IPython Console and the Working Directory toolbar * [PR 3621](https://github.com/spyder-ide/spyder/pull/3621) - Some corrections after pull request #3580 * [PR 3619](https://github.com/spyder-ide/spyder/pull/3619) - Fix another error when connecting to external kernels * [PR 3615](https://github.com/spyder-ide/spyder/pull/3615) - PR: Allow underscore to be valid for Enter in File Switcher * [PR 3599](https://github.com/spyder-ide/spyder/pull/3599) - Load default settings if there is any error in spyder.ini * [PR 3596](https://github.com/spyder-ide/spyder/pull/3596) - PR: New warning message in IPython console when both pylab and sympy are enabled * [PR 3590](https://github.com/spyder-ide/spyder/pull/3590) - Fix builtin and keywords highlighting depending on indentation * [PR 3589](https://github.com/spyder-ide/spyder/pull/3589) - Don't open files saved as part of a project twice at startup * [PR 3582](https://github.com/spyder-ide/spyder/pull/3582) - PR: Added a verification for the existence of the 'text/plain' key * [PR 3581](https://github.com/spyder-ide/spyder/pull/3581) - PR: remove spyder/widgets/tests/__init__.py because of error in execution of pytest -rxs * [PR 3580](https://github.com/spyder-ide/spyder/pull/3580) - PR: Set default file extension in save dialog * [PR 3576](https://github.com/spyder-ide/spyder/pull/3576) - Fix autoindentation after data structures. * [PR 3572](https://github.com/spyder-ide/spyder/pull/3572) - PR: Change deprecated funtion QInputDialog.getInteger for QInputDialog.getInt * [PR 3551](https://github.com/spyder-ide/spyder/pull/3551) - Add option to set/unset dpi scaling for screens that are not high resolution * [PR 3543](https://github.com/spyder-ide/spyder/pull/3543) - PR: Change of the label in the dependencies dialog In this release 27 pull requests were merged ---- ## Version 3.0.1 (2016-10-19) ### Bugfixes **Issues** * [Issue 3528](https://github.com/spyder-ide/spyder/issues/3528) - Cannot see numpy datatypes in variable explorer * [Issue 3518](https://github.com/spyder-ide/spyder/issues/3518) - Spyder hangs with big numpy structured arrays * [Issue 3484](https://github.com/spyder-ide/spyder/issues/3484) - Fix menus in macOS * [Issue 3475](https://github.com/spyder-ide/spyder/issues/3475) - Cannot type left parenthesis in ipdb when automatic Help is turned on * [Issue 3472](https://github.com/spyder-ide/spyder/issues/3472) - Cannot connect to existing ipython kernel after upgrading to 3.0 * [Issue 3471](https://github.com/spyder-ide/spyder/issues/3471) - "Local variable 'reply' referenced before assignment" on debugger exit * [Issue 3454](https://github.com/spyder-ide/spyder/issues/3454) - ImportError with create_app.py * [Issue 3453](https://github.com/spyder-ide/spyder/issues/3453) - Update docs for Projects * [Issue 3317](https://github.com/spyder-ide/spyder/issues/3317) - Console/Editor lose focus when auto-connected to help * [Issue 2284](https://github.com/spyder-ide/spyder/issues/2284) - Very slow boot time on Mac app In this release 10 issues were closed **Pull requests** * [PR 3560](https://github.com/spyder-ide/spyder/pull/3560) - Update documentation * [PR 3550](https://github.com/spyder-ide/spyder/pull/3550) - Prevent WebEngine to steal focus when setting html on the page * [PR 3548](https://github.com/spyder-ide/spyder/pull/3548) - Fix some ipdb issues * [PR 3546](https://github.com/spyder-ide/spyder/pull/3546) - Truncate all values shown in the Variable Explorer * [PR 3544](https://github.com/spyder-ide/spyder/pull/3544) - Don't try to get shape and ndim for objects that are not ndarrays * [PR 3541](https://github.com/spyder-ide/spyder/pull/3541) - Update create_app.py for Spyder 3.0 * [PR 3540](https://github.com/spyder-ide/spyder/pull/3540) - Fix problems when connecting to external kernels * [PR 3501](https://github.com/spyder-ide/spyder/pull/3501) - PR: Handle Mac menubar icon bug * [PR 3499](https://github.com/spyder-ide/spyder/pull/3499) - Testing: Pin conda-build to 2.0.0 In this release 9 pull requests were merged ---- ## Version 3.0 (2016-09-24) ### New features #### Main Window * The *Object Inspector* pane was renamed to *Help*. * Add a new icon theme based on FontAwesome. * Add an *Introduction* interactive tutorial (under the `Help` menu). * Add new default layouts (Horizontal, Vertical, Matlab and Rstudio), and also the possibility to name custom layouts. * Panes that are tabbed next to each other can now be rearranged by dragging and dropping their tabs. * Check for Spyder updates at startup, and also if you go to the menu entry `Help > Check for updates`. * Add the shortcut `Shift+Alt+R` to restart the application. * Add an option to warn when exiting the application, under `Preferences > General > Interface > Prompt when exiting`. * Add Portuguese, Russian and Japanese translations. * Remove light mode #### Editor * Add highlighting and code completion to all file types supported by Pygments (a syntax highlighting library) * Use `Ctrl+M` and `Ctrl+Alt+M` to visually create matrices and vectors. It also works on the Python and IPython consoles. * Add a new file switcher inspired by the Sublime Text one, which can be called with the `Ctrl+P` shortcut. It can also be used to look for classes, functions and methods inside a file, using the `@my_function` syntax. #### Projects * A new menu entry called *Projects* was added to the main window with all actions related to projects. * A project now saves the state of open files in the Editor, so that people can easily work on different coding efforts at the same time. * The project's path is added to `PYTHONPATH`, so that Python packages developed as part of a project can be easily imported in Spyder consoles. * The project explorer now shows a file tree view of the current project, as other editors and IDEs do (e.g. Sublime Text and VSCode). * Projects are completely optional and not imposed on users, i.e. users can work without creating any project. #### Settings * Keyboard shortcuts can now be entered in an easier and more intuitive way. * Add a menu entry to reset to default settings, under `Tools > Reset Spyder to factory defaults`. * The language used in the main interface can now be changed. The option to do it is present in `General > Advanced Settings`. * `Syntax coloring` now has a preview of the selected theme and it's able to change the current theme for all plugins. * Plain and Rich text fonts for all plugins are now changed in `General > Appearance`. * Add a new entry called `Python interpreter` to allow people to select the interpreter used for all Python and IPython consoles (this was before in `Console > Advanced settings`). * Rename the `Console` entry to `Python console`. #### IPython console * Drop support for IPython 3.0 and older versions. * Support the new `qtconsole` package instead. * Communicate directly with IPython kernels instead of doing it through the Python console. #### Debugging * Enter debugging mode if running a file generates errors. This is not activated by default but you can do it by going to `Run > Configure > General settings`. #### Profiler * Add the ability to save and restore profiler data to compare speed improvements. #### Working directory toolbar * Get directory completions by pressing the `Tab` key twice on it. #### API Changes ##### Major changes * The `spyderlib` module was renamed to `spyder` * `spyderplugins` has been removed and its plugins have been assigned to different different modules (`spyder_profiler`, `spyder_breakpoints`, etc) still distributed with the Spyder package. ##### Minor changes * `spyderlib.widgets.dicteditor.DictEditor` has been renamed to `spyder.widgets.variableexplorer.collectionseditor.CollectionsEditor`. * `spyderlib/widgets/dicteditorutils.py` has been renamed to `spyder/widgets/variableexplorer/utils.py`. * `spyderlib/widgets/externalshell/namespacebrowser.py` has been moved to `spyder/widgets/variableexplorer`. * `spyderlib/widgets/externalshell/syntaxhighlighters.py` has been moved to `spyder/utils/`. * Variable Explorer editor widgets were moved from `spyderlib.widgets` to `spyder.widgets.variableexplorer`: * `spyder.widgets.variableexplorer.arrayeditor` * `spyder.widgets.variableexplorer.collectionseditor` * `spyder.widgets.variableexplorer.objecteditor` * `spyder.widgets.variableexplorer.texteditor` * `spyder.widgets.variableexplorer.dataframeeditor` * Modules used for configuration options (e.g. `spyderlib.config`, `spyderlib.baseconfig`, etc) were moved to a new namespace called `spyder.config`. * Modules and files related to the application have been moved to `spyder.app`. * `spyderlib/plugins/projectexplorer.py` has been renamed to `spyder/plugins/projects.py` * `spyderlib/widgets/projectexplorer.py` has been renamed to `spyder/widgets/projects/explorer.py` * `spyderlib/plugins/inspector.py` was renamed to `spyder/plugins/help.py`. * `spyderlib/utils/inspector` was renamed to `spyder/utils/help`. * `spyderlib.qt` was removed. * `spyderlib/widgets/ipython.py` was broken in several files inside `spyder/widgets/ipythonconsole`. * `spyder/widgets/externalshell/{sitecustomize.py, osx_app_site.py}` were moved to `spyder/utils/site` * `spyder/widgets/externalshell/start_ipython_kernel.py` was moved to `spyder/utils/ipython` #### Under the hood * Drop support for Python 2.6 and 3.2. * Support PyQt5. * Drop official support for PySide. Support for it will have to come from the community. * Move our settings directory to `HOME/.spyder{-py3}`. Previous location was `HOME/.spyder2{-py3}` * On Linux we now follow the XDG specification to save our settings, i.e. they are saved in `~/.config/spyder{-py3}` or `$XDG_CONFIG_HOME/spyder{-py3}` if `$XDG_CONFIG_HOME` is defined. * Use the new (pythonic) style for signals and slots. * Test Spyder with the help of Travis and AppVeyor. * Code completions and help retrieval on the Editor are done asynchronously using a client/server architecture based on PyZMQ. * Spyder now uses the `qtpy` package to be able to work with PyQt4 and PyQt5 seamlessly. ### Bugfixes **Issues** * [Issue 3428](https://github.com/spyder-ide/spyder/issues/3428) - runfile is not defined ? * [Issue 3427](https://github.com/spyder-ide/spyder/issues/3427) - Spyder is opening black DOS windows now In this release 2 issues were closed **Pull requests** * [PR 3451](https://github.com/spyder-ide/spyder/pull/3451) - Update Brazilian Portuguese translation * [PR 3450](https://github.com/spyder-ide/spyder/pull/3450) - Update Spanish translation * [PR 3446](https://github.com/spyder-ide/spyder/pull/3446) - Some fixes for Appveyor and Travis * [PR 3442](https://github.com/spyder-ide/spyder/pull/3442) - Avoid showing cmd consoles when starting IPython kernels on Windows * [PR 3441](https://github.com/spyder-ide/spyder/pull/3441) - Update Russian translation * [PR 3439](https://github.com/spyder-ide/spyder/pull/3439) - Fix profiler * [PR 3438](https://github.com/spyder-ide/spyder/pull/3438) - Add an init file to utils/site so it can be added to our tarballs In this release 7 pull requests were merged ---- ## Version 3.0beta7 (2016-09-16) ### Bugfixes **Issues** * [Issue 3419](https://github.com/spyder-ide/spyder/issues/3419) - IPython console: help window hijacks `?` keypress * [Issue 3403](https://github.com/spyder-ide/spyder/issues/3403) - Error when opening project and cancelling * [Issue 3354](https://github.com/spyder-ide/spyder/issues/3354) - IPython console run code lines not being saved in preferences * [Issue 3109](https://github.com/spyder-ide/spyder/issues/3109) - Auto select the only IPython or Python console after startup * [Issue 3011](https://github.com/spyder-ide/spyder/issues/3011) - Cannot connect to existing kernel with full path specified * [Issue 2945](https://github.com/spyder-ide/spyder/issues/2945) - Cannot locate kernel json file when connecting to remote ipython kernel * [Issue 2918](https://github.com/spyder-ide/spyder/issues/2918) - Spyder always switches back to IPython kernel from IPyhton console * [Issue 2846](https://github.com/spyder-ide/spyder/issues/2846) - Import runfile() produces errors when using a virtualenv * [Issue 2844](https://github.com/spyder-ide/spyder/issues/2844) - Spyder won't connect to kernel / IPython console after switching to an external interpreter * [Issue 2790](https://github.com/spyder-ide/spyder/issues/2790) - Make "Ask for confirmation before closing tabs" in IPython console work for all consoles * [Issue 2696](https://github.com/spyder-ide/spyder/issues/2696) - Enter in the IPython console inserts new line instead of executing current line after kernel restart * [Issue 1860](https://github.com/spyder-ide/spyder/issues/1860) - Don't show IPython kernels in the Python console by default In this release 12 issues were closed **Pull requests** * [PR 3423](https://github.com/spyder-ide/spyder/pull/3423) - Try to fix plotting on Windows for the Python Console * [PR 3422](https://github.com/spyder-ide/spyder/pull/3422) - Don't try to use "?" to automatically get help in the IPython console * [PR 3421](https://github.com/spyder-ide/spyder/pull/3421) - Don't show a message when users press cancel in the "Open project" dialog * [PR 3420](https://github.com/spyder-ide/spyder/pull/3420) - Skip testing the Spyder kernel for IPython consoles * [PR 3386](https://github.com/spyder-ide/spyder/pull/3386) - Allow plugins with no dockwidgets * [PR 3368](https://github.com/spyder-ide/spyder/pull/3368) - Avoid eval() when reading config file * [PR 2878](https://github.com/spyder-ide/spyder/pull/2878) - PR: Remove IPython kernels from the Python console and connect directly to them In this release 7 pull requests were merged ---- ## Version 3.0beta6 (2016-08-30) ### Bugfixes **Issues** * [Issue 3363](https://github.com/spyder-ide/spyder/issues/3363) - Spyder wont start unless file ".spyderproject" is deleted. UnpicklingError * [Issue 3274](https://github.com/spyder-ide/spyder/issues/3274) - Text not visible in new file switcher in KDE * [Issue 3211](https://github.com/spyder-ide/spyder/issues/3211) - Edited syntax coloring preferences are not applied or saved * [Issue 3128](https://github.com/spyder-ide/spyder/issues/3128) - Project Explorer filename filter (minor) * [Issue 3099](https://github.com/spyder-ide/spyder/issues/3099) - Can existing files be added to a Spyder project? * [Issue 2887](https://github.com/spyder-ide/spyder/issues/2887) - Make .spyderproject a textfile * [Issue 2636](https://github.com/spyder-ide/spyder/issues/2636) - Problems with filename extension for saved sessions * [Issue 2595](https://github.com/spyder-ide/spyder/issues/2595) - Spyder project renames/creates folders by removing first letter of imported directories * [Issue 2460](https://github.com/spyder-ide/spyder/issues/2460) - Design for Projects in 3.0 * [Issue 1964](https://github.com/spyder-ide/spyder/issues/1964) - Project explorer doesn't refresh its contents * [Issue 1947](https://github.com/spyder-ide/spyder/issues/1947) - New Project not getting created * [Issue 1642](https://github.com/spyder-ide/spyder/issues/1642) - Files excluded by the filter list are displayed in the project explorer after start of spyder * [Issue 1554](https://github.com/spyder-ide/spyder/issues/1554) - Add project's path to our PYTHONPATH so that it can be imported in the console * [Issue 1320](https://github.com/spyder-ide/spyder/issues/1320) - Reorganize Spyder repository * [Issue 1317](https://github.com/spyder-ide/spyder/issues/1317) - Make Project Explorer remember state of open files when reopening In this release 15 issues were closed **Pull requests** * [PR 3377](https://github.com/spyder-ide/spyder/pull/3377) - Completely rewrite our support for Projects * [PR 3370](https://github.com/spyder-ide/spyder/pull/3370) - Some improvements to our CI services * [PR 3369](https://github.com/spyder-ide/spyder/pull/3369) - Remove some old files and directories * [PR 3356](https://github.com/spyder-ide/spyder/pull/3356) - Remove icons from tabs for the Editor and IPython Console * [PR 3355](https://github.com/spyder-ide/spyder/pull/3355) - Some improvements to our file switcher * [PR 3277](https://github.com/spyder-ide/spyder/pull/3277) - Finish reorganization of the Spyder repo In this release 6 pull requests were merged ---- ## Version 3.0beta5 (2016-08-22) ### Bugfixes **Issues** * [Issue 3351](https://github.com/spyder-ide/spyder/issues/3351) - Spyder not opening because of problems with spyder.lock * [Issue 3327](https://github.com/spyder-ide/spyder/issues/3327) - Drag and drop from OS file explorer is not working * [Issue 3308](https://github.com/spyder-ide/spyder/issues/3308) - Variable Explorer fails to display DataFrame with categories * [Issue 3306](https://github.com/spyder-ide/spyder/issues/3306) - Spyder unresponsive, requires forced quit (OS X) * [Issue 3297](https://github.com/spyder-ide/spyder/issues/3297) - Pressing Ctrl+P twice opens file switcher twice * [Issue 3293](https://github.com/spyder-ide/spyder/issues/3293) - F9 does not auto advance when it's at the last line * [Issue 3288](https://github.com/spyder-ide/spyder/issues/3288) - "Quit Spyder" menu entry doesn't work in 3.0.0b4 (OS X 10.11) * [Issue 3287](https://github.com/spyder-ide/spyder/issues/3287) - Spyder can't open a console because of problems with Beautiful Soup * [Issue 3282](https://github.com/spyder-ide/spyder/issues/3282) - QApplication is used from QtGui instead of QtWidgets in app/spyder.py * [Issue 2940](https://github.com/spyder-ide/spyder/issues/2940) - Variable explorer can't show Pandas objects containing timezone aware columns * [Issue 2629](https://github.com/spyder-ide/spyder/issues/2629) - Use XDG_CONFIG_HOME for config directory on Linux * [Issue 2465](https://github.com/spyder-ide/spyder/issues/2465) - Images are not rendered by the Help pane on Windows * [Issue 2119](https://github.com/spyder-ide/spyder/issues/2119) - Spyder doesn't render well on HighDpi screens In this release 13 issues were closed **Pull requests** * [PR 3366](https://github.com/spyder-ide/spyder/pull/3366) - Fix "Quit Spyder" action on OS X * [PR 3357](https://github.com/spyder-ide/spyder/pull/3357) - Remove lock file as part of --reset * [PR 3353](https://github.com/spyder-ide/spyder/pull/3353) - Rewrite computation of max and min in dataframe editor * [PR 3352](https://github.com/spyder-ide/spyder/pull/3352) - Use XDG_CONFIG_HOME to save our settings on Linux * [PR 3339](https://github.com/spyder-ide/spyder/pull/3339) - Fix dragging and dropping files to the Editor * [PR 3338](https://github.com/spyder-ide/spyder/pull/3338) - Testing: Use Qt/PyQt 5.6 packages in Travis * [PR 3336](https://github.com/spyder-ide/spyder/pull/3336) - PR: Update readme and organize badges * [PR 3333](https://github.com/spyder-ide/spyder/pull/3333) - Enable high DPI scaling on Qt >= 5.6 * [PR 3325](https://github.com/spyder-ide/spyder/pull/3325) - Fix further freezes because of pyzmq * [PR 3324](https://github.com/spyder-ide/spyder/pull/3324) - Make 'run line' add a blank line if on last line. * [PR 3319](https://github.com/spyder-ide/spyder/pull/3319) - Test Spyder with Qt 5.6 in AppVeyor * [PR 3315](https://github.com/spyder-ide/spyder/pull/3315) - Fix showing images in the Help plugin for Windows * [PR 3313](https://github.com/spyder-ide/spyder/pull/3313) - Toggle file switcher when pressing its keyboard shortcut * [PR 3312](https://github.com/spyder-ide/spyder/pull/3312) - Fix monkey-patching of QApplication * [PR 3310](https://github.com/spyder-ide/spyder/pull/3310) - Fix error when Beautiful Soup is installed incorrectly * [PR 3300](https://github.com/spyder-ide/spyder/pull/3300) - Re-include plugins in setup.py packages * [PR 3295](https://github.com/spyder-ide/spyder/pull/3295) - PR: Fix/Find in files * [PR 3294](https://github.com/spyder-ide/spyder/pull/3294) - Add keyboard shortcuts to context menu in editor * [PR 3285](https://github.com/spyder-ide/spyder/pull/3285) - Japanese translation * [PR 3273](https://github.com/spyder-ide/spyder/pull/3273) - Testing: Don't use particular tags when installing local conda packages In this release 20 pull requests were merged ---- ## Version 3.0beta4 (2016-07-01) ### Bugfixes **Issues** * [Issue 3267](https://github.com/spyder-ide/spyder/issues/3267) - Spyder 3.0 Beta3 fails to start in OS X * [Issue 3237](https://github.com/spyder-ide/spyder/issues/3237) - Unable to see Float16 in Spyder Variable Explorer * [Issue 3231](https://github.com/spyder-ide/spyder/issues/3231) - Deprecation warning from IPython 5.0.0b4 * [Issue 3230](https://github.com/spyder-ide/spyder/issues/3230) - Spyder is failing because of wrong qtpy version * [Issue 3223](https://github.com/spyder-ide/spyder/issues/3223) - Spyder 3.0 Beta 3 crashing or freezing because of zmq problems * [Issue 3219](https://github.com/spyder-ide/spyder/issues/3219) - Pylint report not jumping to line * [Issue 3206](https://github.com/spyder-ide/spyder/issues/3206) - Local variable 'backends' referenced before assignment when starting IPython kernel * [Issue 3188](https://github.com/spyder-ide/spyder/issues/3188) - Spyder crashes after creating a new file from Project/File Explorer * [Issue 3187](https://github.com/spyder-ide/spyder/issues/3187) - Spyder crashes after deleting a folder in File explorer * [Issue 3186](https://github.com/spyder-ide/spyder/issues/3186) - "New -> Module..." menu not saving the new module file to the disk * [Issue 3159](https://github.com/spyder-ide/spyder/issues/3159) - Cannot search text in Help pane * [Issue 3155](https://github.com/spyder-ide/spyder/issues/3155) - Exception raised when running script in external terminal * [Issue 3150](https://github.com/spyder-ide/spyder/issues/3150) - Fix external plugins import * [Issue 3116](https://github.com/spyder-ide/spyder/issues/3116) - Console panel resizing itself as new console tabs are opened * [Issue 3020](https://github.com/spyder-ide/spyder/issues/3020) - DataFrame editor should first sort up, then down * [Issue 3010](https://github.com/spyder-ide/spyder/issues/3010) - DataFrame editor should do a stable sort * [Issue 2995](https://github.com/spyder-ide/spyder/issues/2995) - Variable explorer - Sequence break with wrong mapping * [Issue 2976](https://github.com/spyder-ide/spyder/issues/2976) - Profiling hangs/freezes Spyder * [Issue 2915](https://github.com/spyder-ide/spyder/issues/2915) - Problems with changing keyboard shortcuts on Mac * [Issue 2914](https://github.com/spyder-ide/spyder/issues/2914) - Change keybinding for Replace text (⌘H) in the Editor on Mac * [Issue 1462](https://github.com/spyder-ide/spyder/issues/1462) - Repeatable segfault while editing HTML file * [Issue 872](https://github.com/spyder-ide/spyder/issues/872) - Quotes and colons autocompletion In this release 22 issues were closed **Pull requests** * [PR 3271](https://github.com/spyder-ide/spyder/pull/3271) - Fix introspection plugin server restart and timeout * [PR 3266](https://github.com/spyder-ide/spyder/pull/3266) - Fix searching text in our Web widgets * [PR 3264](https://github.com/spyder-ide/spyder/pull/3264) - Support float16 values in array editor * [PR 3261](https://github.com/spyder-ide/spyder/pull/3261) - Fix timeouts in AppVeyor * [PR 3260](https://github.com/spyder-ide/spyder/pull/3260) - Fix handling of unmatched end-of-HTML-comment. * [PR 3253](https://github.com/spyder-ide/spyder/pull/3253) - Update minimal required version of several of our dependencies * [PR 3252](https://github.com/spyder-ide/spyder/pull/3252) - Change Replace shortcut from Ctrl/Cmd+H to Ctrl/Cmd+R * [PR 3251](https://github.com/spyder-ide/spyder/pull/3251) - Fix problems in AppVeyor because of update in conda-build * [PR 3248](https://github.com/spyder-ide/spyder/pull/3248) - Fix heartbeat in introspection client/server * [PR 3240](https://github.com/spyder-ide/spyder/pull/3240) - Improve sorting in dataframe editor * [PR 3235](https://github.com/spyder-ide/spyder/pull/3235) - Fix several problems with our shortcuts system * [PR 3234](https://github.com/spyder-ide/spyder/pull/3234) - Create only one instance of IntrospectionManager for the application * [PR 3233](https://github.com/spyder-ide/spyder/pull/3233) - Fixes for qtpy 1.1.0 * [PR 3228](https://github.com/spyder-ide/spyder/pull/3228) - Fix a bug preventing Spyder to open external file In Mac application * [PR 3227](https://github.com/spyder-ide/spyder/pull/3227) - Fix keyboard interrupt handling in plugin_server.py * [PR 3222](https://github.com/spyder-ide/spyder/pull/3222) - Variable explorer: Disregard list1 when sorting list1 against list2 * [PR 3218](https://github.com/spyder-ide/spyder/pull/3218) - PR: Allow empty wdir option to run_python_script_in_terminal * [PR 3217](https://github.com/spyder-ide/spyder/pull/3217) - Fix icon name in conda windows build script. * [PR 3210](https://github.com/spyder-ide/spyder/pull/3210) - PR: Follow the Flask plugin model instead of namespace packages * [PR 3209](https://github.com/spyder-ide/spyder/pull/3209) - Fix undefined `backends` when starting IPython kernel * [PR 3190](https://github.com/spyder-ide/spyder/pull/3190) - Fix small Explorer bugs about file operations * [PR 3177](https://github.com/spyder-ide/spyder/pull/3177) - PR: Fix automatic insertion of colon * [PR 3174](https://github.com/spyder-ide/spyder/pull/3174) - PR: Fix tutorial images on Windows * [PR 3095](https://github.com/spyder-ide/spyder/pull/3095) - Add some indentation tests * [PR 3024](https://github.com/spyder-ide/spyder/pull/3024) - Added QMutex protection to write_output in Python consoles to avoid crashes when writing long outputs In this release 25 pull requests were merged ---- ## Version 3.0beta3 (2016-06-06) ### Bugfixes **Issues** * [Issue 3145](https://github.com/spyder-ide/spyder/issues/3145) - Spyder doesn't work with Qt 5.6 * [Issue 3129](https://github.com/spyder-ide/spyder/issues/3129) - Is there a way to modify the main window title? * [Issue 3122](https://github.com/spyder-ide/spyder/issues/3122) - Test array builder widget * [Issue 3115](https://github.com/spyder-ide/spyder/issues/3115) - Automatically advance to the next line after pressing F9 * [Issue 3113](https://github.com/spyder-ide/spyder/issues/3113) - Cannot change font or font size * [Issue 3112](https://github.com/spyder-ide/spyder/issues/3112) - Cannot open preferences dialog because of missing PYQT5 constant * [Issue 3101](https://github.com/spyder-ide/spyder/issues/3101) - Migrate to qtpy * [Issue 3100](https://github.com/spyder-ide/spyder/issues/3100) - Migrate to qtpy: Remove internal Qt shim used by Spyder. * [Issue 3084](https://github.com/spyder-ide/spyder/issues/3084) - Variable Explorer generates an error while editing a DataFrame * [Issue 3078](https://github.com/spyder-ide/spyder/issues/3078) - (I)Python consoles are not setting PyQt API to #2 * [Issue 3073](https://github.com/spyder-ide/spyder/issues/3073) - Spyder doesn't work with QtWebEngine * [Issue 3061](https://github.com/spyder-ide/spyder/issues/3061) - Different output for internal and external console on Windows * [Issue 3053](https://github.com/spyder-ide/spyder/issues/3053) - Ctrl+I doesn't seem to work on the editor on current tree on Windows * [Issue 3041](https://github.com/spyder-ide/spyder/issues/3041) - Spyder crash with "too many files open" message * [Issue 3033](https://github.com/spyder-ide/spyder/issues/3033) - Create a Remote Procedure Call helper * [Issue 3022](https://github.com/spyder-ide/spyder/issues/3022) - Turn off module completion fallback * [Issue 3021](https://github.com/spyder-ide/spyder/issues/3021) - Ghost completions * [Issue 3013](https://github.com/spyder-ide/spyder/issues/3013) - "Goto definition" stopped working (3.0.0b2 Mac) * [Issue 3009](https://github.com/spyder-ide/spyder/issues/3009) - Spyder crashes with Python 3.5 and pyqt4 if there are no existing configuration files * [Issue 3000](https://github.com/spyder-ide/spyder/issues/3000) - Shortcuts: reset console / empty namespace * [Issue 2986](https://github.com/spyder-ide/spyder/issues/2986) - Add context menu option for %reset * [Issue 2968](https://github.com/spyder-ide/spyder/issues/2968) - Variable explorer gives an error when copying values * [Issue 2912](https://github.com/spyder-ide/spyder/issues/2912) - Change keybinding for re-running last script * [Issue 2910](https://github.com/spyder-ide/spyder/issues/2910) - Automatically set working directory in console * [Issue 2900](https://github.com/spyder-ide/spyder/issues/2900) - 'Commit' command in File explorer not working in Spyder 3.0.0b2 * [Issue 2877](https://github.com/spyder-ide/spyder/issues/2877) - path module not available in 3.0.0b2 * [Issue 2853](https://github.com/spyder-ide/spyder/issues/2853) - Set all fonts to be one and only one for all plugins in spyder * [Issue 2835](https://github.com/spyder-ide/spyder/issues/2835) - Control+C should not copy if it has nothing selected on the editor * [Issue 2724](https://github.com/spyder-ide/spyder/issues/2724) - Editor very slow on Mac Yosemite and El Capitan * [Issue 2703](https://github.com/spyder-ide/spyder/issues/2703) - File in Project Explorer is being executed(?) on dbl-click * [Issue 2619](https://github.com/spyder-ide/spyder/issues/2619) - Spyder fails to start on light mode because of check_updates code * [Issue 2438](https://github.com/spyder-ide/spyder/issues/2438) - Use a single font for all panes * [Issue 2407](https://github.com/spyder-ide/spyder/issues/2407) - very slow auto completion with pandas * [Issue 2376](https://github.com/spyder-ide/spyder/issues/2376) - Rename Object Inspector plug-in * [Issue 2354](https://github.com/spyder-ide/spyder/issues/2354) - Context menu for tabs in editor should allow "close all but this" and "close all to the right" * [Issue 2268](https://github.com/spyder-ide/spyder/issues/2268) - Start testing with pytest/pytest-qt and coverage for Spyder * [Issue 1996](https://github.com/spyder-ide/spyder/issues/1996) - Unable to change the interface colors despite saving them in the preferences. * [Issue 1750](https://github.com/spyder-ide/spyder/issues/1750) - Fail to do automatic indentation after comments * [Issue 1730](https://github.com/spyder-ide/spyder/issues/1730) - 2 or 4 spaces, not 3 * [Issue 820](https://github.com/spyder-ide/spyder/issues/820) - Move all color-related options into Preferences -> Color scheme In this release 40 issues were closed **Pull requests** * [PR 3204](https://github.com/spyder-ide/spyder/pull/3204) - Make "Spyder 3" the default icon theme * [PR 3201](https://github.com/spyder-ide/spyder/pull/3201) - Fix AppVeyor failures * [PR 3198](https://github.com/spyder-ide/spyder/pull/3198) - Support PyQt 5.6 * [PR 3151](https://github.com/spyder-ide/spyder/pull/3151) - More robust plugin initialization in layout * [PR 3146](https://github.com/spyder-ide/spyder/pull/3146) - Editor: Move to next line in run_selection() if nothing selected * [PR 3133](https://github.com/spyder-ide/spyder/pull/3133) - Add an option to set window title to the command line * [PR 3120](https://github.com/spyder-ide/spyder/pull/3120) - PR: Add pytests for array builder, code coverage and quantified code * [PR 3119](https://github.com/spyder-ide/spyder/pull/3119) - PR: fix Russian translation * [PR 3105](https://github.com/spyder-ide/spyder/pull/3105) - Remove our internal Qt shim in favor of QtPy * [PR 3098](https://github.com/spyder-ide/spyder/pull/3098) - PR: Migrate to qtpy * [PR 3086](https://github.com/spyder-ide/spyder/pull/3086) - Fix interrupt handling on Windows * [PR 3072](https://github.com/spyder-ide/spyder/pull/3072) - Added Russian translation. Updated POT file * [PR 3062](https://github.com/spyder-ide/spyder/pull/3062) - Fix consoles encoding in Python 3 * [PR 3060](https://github.com/spyder-ide/spyder/pull/3060) - Start testing with Qt5 on Windows * [PR 3049](https://github.com/spyder-ide/spyder/pull/3049) - Implement a new Async Server approach based on pyzmq to get completions on the Editor * [PR 3043](https://github.com/spyder-ide/spyder/pull/3043) - Copying when nothing is selected no longer affects the clipboard. * [PR 3036](https://github.com/spyder-ide/spyder/pull/3036) - PR: Improve Syntax Coloring preferences page and set color scheme for all plugins there * [PR 3035](https://github.com/spyder-ide/spyder/pull/3035) - PR: Remove font groups from plugins and move to general preferences * [PR 3034](https://github.com/spyder-ide/spyder/pull/3034) - Report missing hard dependencies after startup * [PR 3032](https://github.com/spyder-ide/spyder/pull/3032) - Fix errant completions * [PR 3029](https://github.com/spyder-ide/spyder/pull/3029) - Add shebang line to default template.py * [PR 3023](https://github.com/spyder-ide/spyder/pull/3023) - Fix bug in get encoding from "coding" comment line * [PR 3018](https://github.com/spyder-ide/spyder/pull/3018) - PR: Remove Jedi special code in tests and other minor fixes * [PR 3015](https://github.com/spyder-ide/spyder/pull/3015) - Editor: Fix code completions when working with bootstrap * [PR 2997](https://github.com/spyder-ide/spyder/pull/2997) - Added context menu option to reset IPython namespace * [PR 2974](https://github.com/spyder-ide/spyder/pull/2974) - Center cell icon * [PR 2973](https://github.com/spyder-ide/spyder/pull/2973) - PR: Show all supported text files when opening files with "File > Open" * [PR 2971](https://github.com/spyder-ide/spyder/pull/2971) - Make run-cell icons pixel-perfect * [PR 2957](https://github.com/spyder-ide/spyder/pull/2957) - PR: Select the word under cursor if nothing is selected in Find/Replace * [PR 2955](https://github.com/spyder-ide/spyder/pull/2955) - PR: Make backspace move to parent directory in file explorer * [PR 2952](https://github.com/spyder-ide/spyder/pull/2952) - PR: Enable 'Save All' if there are files to be saved * [PR 2939](https://github.com/spyder-ide/spyder/pull/2939) - PR: More accurate test for text-like files * [PR 2935](https://github.com/spyder-ide/spyder/pull/2935) - PR: Improving Spyder 3 icon theme * [PR 2932](https://github.com/spyder-ide/spyder/pull/2932) - PR: Asynchronous introspection for the Editor * [PR 2930](https://github.com/spyder-ide/spyder/pull/2930) - PR: fix not decorated slots connected to 'triggered' and 'clicked' signals * [PR 2929](https://github.com/spyder-ide/spyder/pull/2929) - Hide Help plugin if Sphinx is not installed * [PR 2919](https://github.com/spyder-ide/spyder/pull/2919) - PR: Synchronize entry in Working Directory toolbar with console's current working directory * [PR 2917](https://github.com/spyder-ide/spyder/pull/2917) - PR: Create a new module called app and move there all modules related to our application * [PR 2913](https://github.com/spyder-ide/spyder/pull/2913) - Move to use Jupyter imports and remove support for IPython 3 * [PR 2897](https://github.com/spyder-ide/spyder/pull/2897) - Fixed typos (thanks to Benjamin Weis) * [PR 2890](https://github.com/spyder-ide/spyder/pull/2890) - Added .idea folder to .gitignore for PyCharm users * [PR 2888](https://github.com/spyder-ide/spyder/pull/2888) - Add 3,5,6,7,8 spaces as options in indentation of the Editor * [PR 2886](https://github.com/spyder-ide/spyder/pull/2886) - Remove official support for PySide * [PR 2881](https://github.com/spyder-ide/spyder/pull/2881) - PR: Crashing on shortcut assignment with PyQt5 * [PR 2879](https://github.com/spyder-ide/spyder/pull/2879) - Use PyQt5 as default API * [PR 2874](https://github.com/spyder-ide/spyder/pull/2874) - Remove light mode * [PR 2873](https://github.com/spyder-ide/spyder/pull/2873) - Rename Object Inspector plugin to Help * [PR 2669](https://github.com/spyder-ide/spyder/pull/2669) - PR: Use pygments in introspection * [PR 2519](https://github.com/spyder-ide/spyder/pull/2519) - Add "close all but this" and "close all to the right" entries to the Editor context menu * [PR 2184](https://github.com/spyder-ide/spyder/pull/2184) - Prevent cmd.exe shell windows popping up in the background when calling subprocess In this release 50 pull requests were merged ---- ## Version 3.0beta1/beta2 (2015-12-11) ### Bugfixes **Issues** * [Issue 2852](https://github.com/spyder-ide/spyder/issues/2852) - Create conda.recipe folder at repo level * [Issue 2836](https://github.com/spyder-ide/spyder/issues/2836) - Dicom plugin error in bootstrap.py * [Issue 2795](https://github.com/spyder-ide/spyder/issues/2795) - Option 'Automatic insertion of parentheses, braces and brackets' has issues when un-checked * [Issue 2792](https://github.com/spyder-ide/spyder/issues/2792) - Changing IPython graphics backend to "Qt" will result in error when using Qt5 * [Issue 2788](https://github.com/spyder-ide/spyder/issues/2788) - Plots are requiring a Ctrl+C in the Python console when using the Qt4 backend on Windows * [Issue 2779](https://github.com/spyder-ide/spyder/issues/2779) - Bundled rope version is causing Spyder to crash * [Issue 2766](https://github.com/spyder-ide/spyder/issues/2766) - fix ArrayEditor under PyQt5 * [Issue 2763](https://github.com/spyder-ide/spyder/issues/2763) - Release 3.0 with PyQt5 as default * [Issue 2756](https://github.com/spyder-ide/spyder/issues/2756) - fallback_plugin tests are failing * [Issue 2748](https://github.com/spyder-ide/spyder/issues/2748) - Spyder freezes when large MaskedArrays are in memory * [Issue 2737](https://github.com/spyder-ide/spyder/issues/2737) - UI issues with collapse/expand in the profiler * [Issue 2736](https://github.com/spyder-ide/spyder/issues/2736) - Profiler config does not carry command line arguments correctly * [Issue 2685](https://github.com/spyder-ide/spyder/issues/2685) - "unable to connect to the internet" nag screen in 3.0.0b1 * [Issue 2677](https://github.com/spyder-ide/spyder/issues/2677) - Autocomplete for working directory widget * [Issue 2674](https://github.com/spyder-ide/spyder/issues/2674) - Add run cell (and run cell advance) to right click prompt * [Issue 2672](https://github.com/spyder-ide/spyder/issues/2672) - Autocomplete does not insert correct word when requested with Ctrl+Space * [Issue 2612](https://github.com/spyder-ide/spyder/issues/2612) - Fix version detection on the Dependencies dialog * [Issue 2598](https://github.com/spyder-ide/spyder/issues/2598) - Cannot change between UI tabs on OSX * [Issue 2597](https://github.com/spyder-ide/spyder/issues/2597) - new icon theme broken on OSX * [Issue 2581](https://github.com/spyder-ide/spyder/issues/2581) - Autoparens appear when autocompleting in the import section * [Issue 2574](https://github.com/spyder-ide/spyder/issues/2574) - Create wheels for Spyder * [Issue 2573](https://github.com/spyder-ide/spyder/issues/2573) - Spyder is crashing with PyQt5.5.0 on Windows / Python 3.4 * [Issue 2569](https://github.com/spyder-ide/spyder/issues/2569) - Spyper cannot read yahoo stock price * [Issue 2555](https://github.com/spyder-ide/spyder/issues/2555) - Main window is bigger than screen size, after a first start in Mac and KDE * [Issue 2527](https://github.com/spyder-ide/spyder/issues/2527) - More suggestions for the "Spyder 3" icon theme * [Issue 2481](https://github.com/spyder-ide/spyder/issues/2481) - Align boxes for different lines in preferences dialog * [Issue 2471](https://github.com/spyder-ide/spyder/issues/2471) - Matplotlib Gtk backend is broken in Python consoles * [Issue 2439](https://github.com/spyder-ide/spyder/issues/2439) - Rope not autocompleting when *args or **kwargs are present in function definition * [Issue 2436](https://github.com/spyder-ide/spyder/issues/2436) - Background coloring in array view (variable explorer) doesn't work if array contains nans * [Issue 2433](https://github.com/spyder-ide/spyder/issues/2433) - Argument cannot work in Spyder 2.3.4 * [Issue 2427](https://github.com/spyder-ide/spyder/issues/2427) - can't find pylint installed as python3-pylint * [Issue 2422](https://github.com/spyder-ide/spyder/issues/2422) - Selecting line numbers from the side areas with pointer potentially buggy? * [Issue 2420](https://github.com/spyder-ide/spyder/issues/2420) - Zoom should not be associated with a file * [Issue 2408](https://github.com/spyder-ide/spyder/issues/2408) - Exception on autocomplete in the internal console * [Issue 2404](https://github.com/spyder-ide/spyder/issues/2404) - Code completion raise exception when the editor widget is floating * [Issue 2401](https://github.com/spyder-ide/spyder/issues/2401) - Unable to reset settings from the Main Window * [Issue 2395](https://github.com/spyder-ide/spyder/issues/2395) - Can not show exception information correctly in IPython Console * [Issue 2390](https://github.com/spyder-ide/spyder/issues/2390) - Code completion is failing on Python consoles * [Issue 2389](https://github.com/spyder-ide/spyder/issues/2389) - Move helper widgets to helperwidgets.py * [Issue 2386](https://github.com/spyder-ide/spyder/issues/2386) - Error in Python console on startup * [Issue 2385](https://github.com/spyder-ide/spyder/issues/2385) - Can't report issue on master with PyQt5 * [Issue 2381](https://github.com/spyder-ide/spyder/issues/2381) - Disable post-crash popup in dev mode * [Issue 2379](https://github.com/spyder-ide/spyder/issues/2379) - Spyder can't switch lines of code when those two lines are the last two in the file * [Issue 2352](https://github.com/spyder-ide/spyder/issues/2352) - Some issues with code completion in the Editor * [Issue 2348](https://github.com/spyder-ide/spyder/issues/2348) - Combobox to choose Matplotlib backend * [Issue 2347](https://github.com/spyder-ide/spyder/issues/2347) - Add shortcuts to move to next/previous line in the Editor * [Issue 2340](https://github.com/spyder-ide/spyder/issues/2340) - SublimeText-like file switching widget * [Issue 2317](https://github.com/spyder-ide/spyder/issues/2317) - Object Inspector Text on Mac OS X is Misleading * [Issue 2313](https://github.com/spyder-ide/spyder/issues/2313) - 'NoneType' is not iterable in introspection/fallback_plugin.py * [Issue 2308](https://github.com/spyder-ide/spyder/issues/2308) - Python console stops running after first execution * [Issue 2307](https://github.com/spyder-ide/spyder/issues/2307) - Enhancement: Add check for updates and allow for autoupdating inside spyder * [Issue 2306](https://github.com/spyder-ide/spyder/issues/2306) - Enhancement: Add restart functionality to spyder. * [Issue 2305](https://github.com/spyder-ide/spyder/issues/2305) - Profiling error * [Issue 2300](https://github.com/spyder-ide/spyder/issues/2300) - Unable to start my Spyder * [Issue 2289](https://github.com/spyder-ide/spyder/issues/2289) - Disable icons in menus on Mac OS X * [Issue 2282](https://github.com/spyder-ide/spyder/issues/2282) - Incorrect setting of Qt API n°2 * [Issue 2277](https://github.com/spyder-ide/spyder/issues/2277) - "TypeError: decoding Unicode is not supported" when debugging * [Issue 2275](https://github.com/spyder-ide/spyder/issues/2275) - Can not report issue from dev version * [Issue 2274](https://github.com/spyder-ide/spyder/issues/2274) - Can not start spyder under python2 because guidata doesn't support PyQt5 * [Issue 2267](https://github.com/spyder-ide/spyder/issues/2267) - Move Conda Package Manager to its own repo * [Issue 2251](https://github.com/spyder-ide/spyder/issues/2251) - Spyder crashing on very long output * [Issue 2250](https://github.com/spyder-ide/spyder/issues/2250) - IPython 3.0 is showing a deprecation warning in the Internal Console * [Issue 2249](https://github.com/spyder-ide/spyder/issues/2249) - TypeError: 'method' object is not connected: self.timer.timeout.disconnect(self.show_time) * [Issue 2248](https://github.com/spyder-ide/spyder/issues/2248) - ImportError: No module named 'conda_api_q' * [Issue 2235](https://github.com/spyder-ide/spyder/issues/2235) - Error when running Spyder with Python 2 and PyQt5 * [Issue 2231](https://github.com/spyder-ide/spyder/issues/2231) - Master has issues when plotting graphs through matplotlib in Python consoles * [Issue 2213](https://github.com/spyder-ide/spyder/issues/2213) - Show absolute and relative (to the current file in Editor) images in Object inspector * [Issue 2210](https://github.com/spyder-ide/spyder/issues/2210) - Icons as vector graphics to support retina displays * [Issue 2204](https://github.com/spyder-ide/spyder/issues/2204) - Windows: something is preventing "File" and "Edit" menus being clicked * [Issue 2141](https://github.com/spyder-ide/spyder/issues/2141) - File list management broken in master * [Issue 2125](https://github.com/spyder-ide/spyder/issues/2125) - Removal of keyboard shortcut causes errors to be thrown * [Issue 2117](https://github.com/spyder-ide/spyder/issues/2117) - Add missing methods to SpyderPluginMixin * [Issue 2096](https://github.com/spyder-ide/spyder/issues/2096) - Feature Request: Add option to lock window/pane layout * [Issue 2083](https://github.com/spyder-ide/spyder/issues/2083) - Spyder stopped working with Qt4.6 * [Issue 2061](https://github.com/spyder-ide/spyder/issues/2061) - Spyder cannot load matplotlib if the latter tries to use PyQt5 * [Issue 2047](https://github.com/spyder-ide/spyder/issues/2047) - Provide Keyboard Shortcut for Save As * [Issue 2024](https://github.com/spyder-ide/spyder/issues/2024) - Add folders with subfolders with path manager * [Issue 2010](https://github.com/spyder-ide/spyder/issues/2010) - runfile arguments with spaces * [Issue 2001](https://github.com/spyder-ide/spyder/issues/2001) - inserting line break in code line does not align well on next line * [Issue 1966](https://github.com/spyder-ide/spyder/issues/1966) - Add fallback syntax highlighter using Pygments autodetection * [Issue 1940](https://github.com/spyder-ide/spyder/issues/1940) - Add search functionality for keyboard shortcuts * [Issue 1924](https://github.com/spyder-ide/spyder/issues/1924) - Add interactive tutorials * [Issue 1923](https://github.com/spyder-ide/spyder/issues/1923) - Bug when changing output and input prompts in the IPython console * [Issue 1876](https://github.com/spyder-ide/spyder/issues/1876) - Editor: Move suggested completion item to top of window * [Issue 1850](https://github.com/spyder-ide/spyder/issues/1850) - Calltip traceback while using Jedi * [Issue 1761](https://github.com/spyder-ide/spyder/issues/1761) - F5 (run) saves editor file, but F10 (profile) does not * [Issue 1749](https://github.com/spyder-ide/spyder/issues/1749) - Cycle tabs via Ctrl-PageUp/PageDown * [Issue 1394](https://github.com/spyder-ide/spyder/issues/1394) - Let the user select his/her own localization settings * [Issue 1387](https://github.com/spyder-ide/spyder/issues/1387) - Integrate post mortem debugging (like IEP) * [Issue 1335](https://github.com/spyder-ide/spyder/issues/1335) - Add option for naming the custom layouts * [Issue 1239](https://github.com/spyder-ide/spyder/issues/1239) - Include a package manager * [Issue 1221](https://github.com/spyder-ide/spyder/issues/1221) - Spyder doesn't use Native OS X fullscreen * [Issue 1212](https://github.com/spyder-ide/spyder/issues/1212) - Add keyboard shortcuts for beginning of line and end of line * [Issue 1001](https://github.com/spyder-ide/spyder/issues/1001) - How to change UI language * [Issue 729](https://github.com/spyder-ide/spyder/issues/729) - Enable assigning shortcuts for cursor navigation on the Editor * [Issue 494](https://github.com/spyder-ide/spyder/issues/494) - Need to hit Enter to change a keyboard shortcut (unintuitive) * [Issue 478](https://github.com/spyder-ide/spyder/issues/478) - Slash does not work as keyboard shortcut key * [Issue 404](https://github.com/spyder-ide/spyder/issues/404) - Spyder becomes unresponsive while loading a large source file * [Issue 195](https://github.com/spyder-ide/spyder/issues/195) - Backspace (\b) and carriage return (\r) characters are not printed correctly in the console In this release 99 issues were closed **Pull requests** * [PR 2847](https://github.com/spyder-ide/spyder/pull/2847) - Use High dpi pixmaps * [PR 2838](https://github.com/spyder-ide/spyder/pull/2838) - Import spyplugins only if there's a valid spec/module * [PR 2831](https://github.com/spyder-ide/spyder/pull/2831) - Remove external dependencies * [PR 2826](https://github.com/spyder-ide/spyder/pull/2826) - Remove imports from widgets/__init__ because they are making Spyder crash * [PR 2825](https://github.com/spyder-ide/spyder/pull/2825) - Fix tests in Travis after a recent update of conda-build * [PR 2813](https://github.com/spyder-ide/spyder/pull/2813) - Test spyplugins widgets on AppVeyor and other minor fixes * [PR 2810](https://github.com/spyder-ide/spyder/pull/2810) - Restore the insertion of the "(" character when parameter close_parentheses_enabled is False * [PR 2808](https://github.com/spyder-ide/spyder/pull/2808) - Make F10 (profile) save the current file before running * [PR 2800](https://github.com/spyder-ide/spyder/pull/2800) - Fix problems in AppVeyor and Travis * [PR 2786](https://github.com/spyder-ide/spyder/pull/2786) - Move the spyder script to the right place if it isn't present in the site Scripts directory * [PR 2784](https://github.com/spyder-ide/spyder/pull/2784) - Fix runfile argument parsing error by using shlex * [PR 2778](https://github.com/spyder-ide/spyder/pull/2778) - Use Appveyor to test on Windows * [PR 2777](https://github.com/spyder-ide/spyder/pull/2777) - Fix important errors in Travis * [PR 2776](https://github.com/spyder-ide/spyder/pull/2776) - Rename spyderlib.widgets.editors to spyderlib.widgets.variableexplorer * [PR 2774](https://github.com/spyder-ide/spyder/pull/2774) - Add dependencies to pip * [PR 2767](https://github.com/spyder-ide/spyder/pull/2767) - Fix arrayeditor import error in PyQt5 * [PR 2762](https://github.com/spyder-ide/spyder/pull/2762) - Start testing with PyQt5 * [PR 2761](https://github.com/spyder-ide/spyder/pull/2761) - Test Spyder with Python 3.5 * [PR 2758](https://github.com/spyder-ide/spyder/pull/2758) - Fix failing fallback_plugin tests and add to modules_test * [PR 2752](https://github.com/spyder-ide/spyder/pull/2752) - Test widgets in Travis * [PR 2750](https://github.com/spyder-ide/spyder/pull/2750) - Improved copying and selection behaviour of array editor * [PR 2747](https://github.com/spyder-ide/spyder/pull/2747) - Don't use bootstrap on Travis * [PR 2746](https://github.com/spyder-ide/spyder/pull/2746) - Move Variable Explorer widgets and utility libraries to its own namespace: widgets/varexp * [PR 2741](https://github.com/spyder-ide/spyder/pull/2741) - Get rid of the last shim warning with IPython/Jupyter 4 * [PR 2740](https://github.com/spyder-ide/spyder/pull/2740) - Read correctly the run config for profiling * [PR 2739](https://github.com/spyder-ide/spyder/pull/2739) - Fix collapse/expand buttons in profiler widget * [PR 2718](https://github.com/spyder-ide/spyder/pull/2718) - Fix issue with qtawesome fonts not rendering on OS X * [PR 2702](https://github.com/spyder-ide/spyder/pull/2702) - Fix tabbar issue in OSX * [PR 2692](https://github.com/spyder-ide/spyder/pull/2692) - Add tab completions for PathCombobox * [PR 2691](https://github.com/spyder-ide/spyder/pull/2691) - Fixed PyQt5 detection without QT_API env var * [PR 2687](https://github.com/spyder-ide/spyder/pull/2687) - Opt out of certificate verification on check for updates * [PR 2673](https://github.com/spyder-ide/spyder/pull/2673) - Fix single item completion * [PR 2671](https://github.com/spyder-ide/spyder/pull/2671) - Test module importing on Travis * [PR 2602](https://github.com/spyder-ide/spyder/pull/2602) - Revert auto open parens on completion * [PR 2594](https://github.com/spyder-ide/spyder/pull/2594) - Import HelperToolButton from helperwidgets.py in arraybuilder * [PR 2590](https://github.com/spyder-ide/spyder/pull/2590) - Redesign file switcher (a la Sublime Text) * [PR 2587](https://github.com/spyder-ide/spyder/pull/2587) - Homogenize History Pane UI * [PR 2585](https://github.com/spyder-ide/spyder/pull/2585) - Homogenize Object inspector UI * [PR 2584](https://github.com/spyder-ide/spyder/pull/2584) - Homogenize variable explorer UI * [PR 2583](https://github.com/spyder-ide/spyder/pull/2583) - Homogenize file explorer UI * [PR 2582](https://github.com/spyder-ide/spyder/pull/2582) - Move MessageCheckBox widget from workers to helperwidgets.py * [PR 2577](https://github.com/spyder-ide/spyder/pull/2577) - Make "copy" work better with numpy arrays * [PR 2576](https://github.com/spyder-ide/spyder/pull/2576) - Fix issues in Python3/PyQt5.5 * [PR 2575](https://github.com/spyder-ide/spyder/pull/2575) - Reorganize repo: grouped config files inside spyderlib/config * [PR 2565](https://github.com/spyder-ide/spyder/pull/2565) - Change plugins directory to spyplugins and make it a namespace package * [PR 2559](https://github.com/spyder-ide/spyder/pull/2559) - Fix default layout dockwidget on first Spyder start * [PR 2547](https://github.com/spyder-ide/spyder/pull/2547) - Fix resetting IPython custom exception hook * [PR 2537](https://github.com/spyder-ide/spyder/pull/2537) - fix misspelled extension * [PR 2533](https://github.com/spyder-ide/spyder/pull/2533) - Spyder 3 icon theme changes * [PR 2523](https://github.com/spyder-ide/spyder/pull/2523) - Keyboard shortcut editor enhancements * [PR 2511](https://github.com/spyder-ide/spyder/pull/2511) - New Spyder 3 icons for run-cell and run-cell inplace * [PR 2504](https://github.com/spyder-ide/spyder/pull/2504) - Update Spyder 3 icon theme: vertical alignment of maximize/unmaximize * [PR 2501](https://github.com/spyder-ide/spyder/pull/2501) - Make blank space less apparent. * [PR 2492](https://github.com/spyder-ide/spyder/pull/2492) - proof read tutorial.rst and removed several typos * [PR 2489](https://github.com/spyder-ide/spyder/pull/2489) - Remove warning message associated to language on Linux * [PR 2488](https://github.com/spyder-ide/spyder/pull/2488) - Improve appearance of options inside the preferences dialog * [PR 2480](https://github.com/spyder-ide/spyder/pull/2480) - Enable standard icons * [PR 2457](https://github.com/spyder-ide/spyder/pull/2457) - Return default language in case no locale is found * [PR 2445](https://github.com/spyder-ide/spyder/pull/2445) - Fix handling of jedi completions for jedi 0.9 * [PR 2426](https://github.com/spyder-ide/spyder/pull/2426) - Add option to toggle toolbars visibility * [PR 2425](https://github.com/spyder-ide/spyder/pull/2425) - Add option in preferences to show/hide status bar * [PR 2423](https://github.com/spyder-ide/spyder/pull/2423) - Reset spyder and restart from within running application * [PR 2412](https://github.com/spyder-ide/spyder/pull/2412) - Open preferences dialog even if a plugin raises errors * [PR 2410](https://github.com/spyder-ide/spyder/pull/2410) - Print git revision and branch in bootstrap.py instead of mercurial * [PR 2409](https://github.com/spyder-ide/spyder/pull/2409) - Fix error when trying an empty complete in internal console * [PR 2405](https://github.com/spyder-ide/spyder/pull/2405) - Avoid exception when the Editor is floating and users are trying to get completions * [PR 2391](https://github.com/spyder-ide/spyder/pull/2391) - Fix #2390, completions in python console * [PR 2382](https://github.com/spyder-ide/spyder/pull/2382) - Allow the last two lines in a file to be switched * [PR 2371](https://github.com/spyder-ide/spyder/pull/2371) - Automatically add parens for function completions * [PR 2369](https://github.com/spyder-ide/spyder/pull/2369) - Add drag support for dockwidgets sharing same position * [PR 2367](https://github.com/spyder-ide/spyder/pull/2367) - New KeySequence Editor for Keyboard Shortcut Preferences * [PR 2366](https://github.com/spyder-ide/spyder/pull/2366) - Update Path.py to version 7.3 * [PR 2357](https://github.com/spyder-ide/spyder/pull/2357) - Fix some completion issues on the Editor (issue #2352) * [PR 2349](https://github.com/spyder-ide/spyder/pull/2349) - Add support for language selection in preferences * [PR 2345](https://github.com/spyder-ide/spyder/pull/2345) - Add lock/unlock option for panes * [PR 2337](https://github.com/spyder-ide/spyder/pull/2337) - Add Icons to Completions * [PR 2331](https://github.com/spyder-ide/spyder/pull/2331) - Finish Introduction tour * [PR 2328](https://github.com/spyder-ide/spyder/pull/2328) - README.md running from source is a killer feature * [PR 2322](https://github.com/spyder-ide/spyder/pull/2322) - Make completions scroll to top of list * [PR 2321](https://github.com/spyder-ide/spyder/pull/2321) - Add a check for updates method * [PR 2319](https://github.com/spyder-ide/spyder/pull/2319) - Handle a connection abort error on shutdown * [PR 2318](https://github.com/spyder-ide/spyder/pull/2318) - Fix Object inspector message for OSX * [PR 2316](https://github.com/spyder-ide/spyder/pull/2316) - Use empty string instead of None for fallback. Fixes #2313. * [PR 2312](https://github.com/spyder-ide/spyder/pull/2312) - Fixes #2306: Add a restart method * [PR 2309](https://github.com/spyder-ide/spyder/pull/2309) - Replace obsolete setTextColor method by setForeground in qtreewidgetitem * [PR 2301](https://github.com/spyder-ide/spyder/pull/2301) - Run selection enabled even with empty selection * [PR 2295](https://github.com/spyder-ide/spyder/pull/2295) - Update CHANGELOG.md * [PR 2291](https://github.com/spyder-ide/spyder/pull/2291) - Add "func" to enaml highlighter * [PR 2286](https://github.com/spyder-ide/spyder/pull/2286) - Setting Qt API n°2 for all supported objects * [PR 2281](https://github.com/spyder-ide/spyder/pull/2281) - Add travis support for basic start of spyder * [PR 2260](https://github.com/spyder-ide/spyder/pull/2260) - New set of icons based on FontAwesome * [PR 2253](https://github.com/spyder-ide/spyder/pull/2253) - Try to avoid crashes on long output into Python console in a short time * [PR 2243](https://github.com/spyder-ide/spyder/pull/2243) - Don't add invalid paths to IMG_PATH * [PR 2237](https://github.com/spyder-ide/spyder/pull/2237) - Changed the IPython completion option from a checkbox to a combobox * [PR 2226](https://github.com/spyder-ide/spyder/pull/2226) - Add PyQt5 to Qt binding choices for Python consoles * [PR 2222](https://github.com/spyder-ide/spyder/pull/2222) - Update pep8 version shipped with spyder from 1.4.6 to 1.6.2 * [PR 2218](https://github.com/spyder-ide/spyder/pull/2218) - Update AUTHORS * [PR 2217](https://github.com/spyder-ide/spyder/pull/2217) - Keybinding Enhancements * [PR 2208](https://github.com/spyder-ide/spyder/pull/2208) - Fix issue 2204 in tour - blocking file and edit menu * [PR 2205](https://github.com/spyder-ide/spyder/pull/2205) - Added Brazilian Portuguese translation * [PR 2202](https://github.com/spyder-ide/spyder/pull/2202) - Allow tab cycling with ctrl+pageup/down * [PR 2198](https://github.com/spyder-ide/spyder/pull/2198) - Fill in missing global run config options * [PR 2189](https://github.com/spyder-ide/spyder/pull/2189) - Provide a base implementation for closing_plugin In this release 103 pull requests were merged ---- ## Version 2.3.9 ### New features * Preferences * Fix a crash when using certain versions of colorama (which is a Jedi dependency) * Python and IPython consoles * Filter a RuntimeWarning generated for DataFrames with nan values * Variable Explorer * Fix a freeze when binary strings can't be converted to unicode in Python 2 * Fix a freeze with Numpy arrays containing strings ### Bug fixes **Issues** * [Issue 3067](../../issues/3067) - File left open in sitecustomize when executing it in Python 3 * [Issue 3031](../../issues/3031) - Variable Explorer freezes when certain binary data is loaded * [Issue 2991](../../issues/2991) - RuntimeWarning with pandas.dataframes that contain np.nan values * [Issue 2984](../../issues/2984) - Can't access Preferences in spyder * [Issue 2983](../../issues/2983) - Freeze while assigning data from numpy array when the data is a string In this release 5 issues were closed ---- ## Version 2.3.8 ### New features * Python and IPython consoles * Fix a sitecustomize error when using Matplotlib 1.5 with Python 2 on Linux * Variable Explorer * Add support for Pandas Series when using Pandas 0.17+ * Fix a freeze when creating empty DataFrames in Python 2 * Fix a freeze when working with big Numpy recarray's * Under the hood * Avoid startup crashes when there are errors importing Numpy, SciPy or Pillow ### Bug fixes **Issues** * [Issue 2819](../../issues/2819) - Spyder fails to start because of an error with scipy * [Issue 2815](../../issues/2815) - Variable explorer is not recognizing Pandas Series objects * [Issue 2793](../../issues/2793) - Connecting to kernel fails because of update to Matplotlib 1.5 * [Issue 2791](../../issues/2791) - DataFrame with no rows gives error when trying to view it * [Issue 2783](../../issues/2783) - Spyder freezes on assigning a fits table data * [Issue 2744](../../issues/2744) - Spyder hangs when creating an empty DataFrame on Python 2 In this release 6 issues were closed ---- ## Version 2.3.7 ### New features * Editor * Remove support for Jedi 0.9 because it was causing crashes * Variable Explorer * Fix crashes and freezes when working with DataFrames on Python 2 * Under the hodd * Restore support for PySide ### Bug fixes **Issues** * [Issue 2709](../../issues/2709) - IPython console error when trying to use SymPy * [Issue 2693](../../issues/2693) - README should link to manual * [Issue 2689](../../issues/2689) - "Resize" button in variable explorer chops off the array * [Issue 2684](../../issues/2684) - Applications directory link is broken in Spyder 2.3.6 dmg's * [Issue 2680](../../issues/2680) - "Close all files" hangs Spyder * [Issue 2661](../../issues/2661) - Conda package manager is packed in 2.3.6 win32 distribution leading to errors * [Issue 2659](../../issues/2659) - Crash while getting completions of DataFrames on the Editor because of Jedi 0.9 * [Issue 2654](../../issues/2654) - Creating DataFrames in Python or IPython consoles make Spyder 2.3.6 to hang * [Issue 2649](../../issues/2649) - PySide can not be used on 2.3.6 * [Issue 2296](../../issues/2296) - Line numbers misaligned when zooming and scrolling in Mac * [Issue 2036](../../issues/2036) - Code analysis and tooltips are not displayed in Ubuntu In this release 11 issues were closed **Pull requests** * [PR 2650](../../pull/2650) - Failed sip import blocks fallback to PySide In this release 1 pull requests were merged ---- ## Version 2.3.6 ### New features * IPython Console * Make it fully compatible with IPython/Jupyter 4.0 * Variable Explorer * Don't refresh it when focused to avoid slow downs when working with big data * Add variable name to DataFrame editor * Fix several crashes and freezes when working with DataFrames * Under the hood * Use PyQt4 API #2 by default (API #1 is not supported anymore). This is necessary to support IPython/Jupyter 4.0 ### Bug fixes **Issues** * [Issue 2625](../../issues/2625) - Multiple untitled files generate at close * [Issue 2614](../../issues/2614) - Indenting at the first position in file fails/crashes * [Issue 2608](../../issues/2608) - Crash after update IPython to 4.0 * [Issue 2596](../../issues/2596) - Call tips and auto completion tips go out of screen on a second monitor * [Issue 2593](../../issues/2593) - Having a lof of data in the Variable explorer slows down Spyder considerably * [Issue 2566](../../issues/2566) - Spyder crash on launch with Babel 2.0/Python 3.4 * [Issue 2560](../../issues/2560) - List of pandas dataframes in variable explorer slows down Spyder * [Issue 2517](../../issues/2517) - Variable explorer auto-refreshes after kernel restarts * [Issue 2514](../../issues/2514) - DataFrames with headers that contain BOM utf-8 data are freezing/crashing Spyder (in Python 2) * [Issue 2491](../../issues/2491) - Spyder crashes when displaying DataFrames with duplicate column names in the Variable Explorer * [Issue 2413](../../issues/2413) - Don't ask to confirm exit on default untitled files * [Issue 2315](../../issues/2315) - Display object name in DataFrame editor In this release 12 issues were closed **Pull requests** * [PR 2639](../../pull/2639) - Fix missing exception on Windows when importing data on the Variable Explorer * [PR 2617](../../pull/2617) - Show call tips at right position when there are multiple screens * [PR 2615](../../pull/2615) - Fix error when indenting on the first line of a file In this release 3 pull requests were merged ---- ## Version 2.3.5.2 **Note**: Versions 2.3.5 and 2.3.5.1 have serious startup bugs on Windows and Mac respectively. Hence they are not listed here. ### New features * Editor * Add support for Jedi 0.9 * IPython Console * Add initial support for IPython/Jupyter 4.0 * Main Window * Improve how Spyder looks in MacOS X * Several fixes to prevent startup crashes ### Bug fixes **Issues** * [Issue 2468](../../issues/2468) - 'Connect to existing kernel' fails if json file not in PWD * [Issue 2466](../../issues/2466) - No Notification of Running Instance * [Issue 2463](../../issues/2463) - Failure to preserve Matplotlib backend when using symbolic math * [Issue 2456](../../issues/2456) - Launching IPython console fails because of errors importing Pandas or Matplotlib * [Issue 2452](../../issues/2452) - os.system causes TypeError in Python 3 * [Issue 2448](../../issues/2448) - Spyder crashes using Variable Explorer with BeautifulSoup * [Issue 2446](../../issues/2446) - When importing putting two periods in a row produces an error in a Python console * [Issue 2363](../../issues/2363) - Spyder fails to start because of problems with lockfile * [Issue 2356](../../issues/2356) - Block comment incorporating whitespace excludes last line * [Issue 2341](../../issues/2341) - IPython console: "sre_constants.error: unbalanced parenthesis" while typing * [Issue 2314](../../issues/2314) - Cell highlighting not updated after closing the FindReplace widget * [Issue 2302](../../issues/2302) - Closing all files in editor shouldn't leave it empty * [Issue 2299](../../issues/2299) - IPython preference "Automatically load Pylab and Numpy Modules" not followed * [Issue 2298](../../issues/2298) - Cannot stop executing when runing a flask app with debug=True * [Issue 2285](../../issues/2285) - Copying from Spyder and pasting into LibreOffice displays strange comments * [Issue 2228](../../issues/2228) - Shortcut to run cells on Mac is not working * [Issue 2188](../../issues/2188) - can't run win_post_install from pip * [Issue 2171](../../issues/2171) - Spyder Mac apps (for Python 2 and 3) hang on startup with OSX 10.9.5 * [Issue 2028](../../issues/2028) - Background color of theme is not set properly on Mac OSX * [Issue 1957](../../issues/1957) - Python 3 Mac app can't start Python or IPython consoles * [Issue 1844](../../issues/1844) - "Set as current console's working directory" button not working on Python 3 * [Issue 1615](../../issues/1615) - Mac app - Matplotlib does not work with Canopy In this release 22 issues were closed **Pull requests** * [PR 2486](../../pull/2486) - Stop using IPython.lib.kernel 0.13.2 shim and add initial support for Jupyter * [PR 2484](../../pull/2484) - Remove unnecessary changes to detected kernel json file when connecting to external kernels * [PR 2434](../../pull/2434) - Match for pylint when parsing pylint version * [PR 2411](../../pull/2411) - Improve github issue template * [PR 2377](../../pull/2377) - Fix the fact that spyder_win_post_install.py can't be run from pip * [PR 2293](../../pull/2293) - Hide menu icons on Mac OS X * [PR 2247](../../pull/2247) - Add support to run Python programs on xfce and xterm external terminals * [PR 2216](../../pull/2216) - Fix broken png files: libpng 1.6.2 and newer has stricter iCCP rules In this release 8 pull requests were merged ---- ## Version 2.3.4 ### New features * Debugging * After pressing the Debug button (or `Ctrl+F5`) move to the first breakpoint * IPython Console * Drop support for Sympy versions less than 0.7.3 * Python Console * Remove support to run system commands with ! (like `!diff`) * Editor * Accept drops from compressed files on Windows ### Bug fixes **Issues** * [Issue 2259](../../issues/2259) - spyder crashes if ipython installed but not pygments * [Issue 2257](../../issues/2257) - Cannot plot inline in IPython console on Linux * [Issue 2252](../../issues/2252) - Update French translations for 2.3.4 * [Issue 2245](../../issues/2245) - Importing a module with debugger causes "TypeError: decoding Unicode is not supported" * [Issue 2239](../../issues/2239) - SyntaxErrors with Python 3.2 * [Issue 2234](../../issues/2234) - Object Inspector is not showing "No documentation available" for objects without docstring * [Issue 2227](../../issues/2227) - IPython does not work with brewed or virtualenv Python(s) in MacOSX * [Issue 2223](../../issues/2223) - Spyder2.3.3 Code completion breaks * [Issue 2207](../../issues/2207) - Spyder's WM_CLASS is empty, resulting in unexpected behavior for task managers * [Issue 2203](../../issues/2203) - Code completion issue with Jedi * [Issue 2197](../../issues/2197) - IPython consoles are not named correctly when connecting to existing kernels and passing the full kernel path * [Issue 2158](../../issues/2158) - runfile with path containing apostrophes (quotes) will not work * [Issue 2151](../../issues/2151) - Long NumPy arrays throw off errors * [Issue 2146](../../issues/2146) - Special character "!" is not processed correctly when debugging in Python consoles * [Issue 2081](../../issues/2081) - Spyder crashes on Windows because of non-ascii chars in working directory * [Issue 2058](../../issues/2058) - Don't execute external commands (!) when running pdb in python consoles * [Issue 2034](../../issues/2034) - Execute until first breakpoint when pressing the Debug button * [Issue 2032](../../issues/2032) - Dragging (not dropping) file from 7zip over spyder window causes TypeError in dragEnterEvent * [Issue 1952](../../issues/1952) - spyderlib.utils.external overrides modules for script execution * [Issue 1948](../../issues/1948) - spyder 2.3 ipython console startup code or file not working * [Issue 1856](../../issues/1856) - Running in external system terminals is not working on Windows and Python 3 * [Issue 1845](../../issues/1845) - Spyder crashes on launch trying to load the project config file (.spyderproject) * [Issue 1568](../../issues/1568) - raw_input borks with '!' * [Issue 1529](../../issues/1529) - Plot A List Of Floats In Variable Explorer Not Possible * [Issue 1380](../../issues/1380) - Problems with sitecustomize because of pickleshare library * [Issue 1366](../../issues/1366) - "Highlight occurrences" setting is lost after IDE restart * [Issue 1359](../../issues/1359) - Mac app - Sometimes it's not possible to get the user env vars * [Issue 1321](../../issues/1321) - The PYTHONPATH manager on the Mac app does not work with the EPD64 interpreter * [Issue 1151](../../issues/1151) - Ctrl-C doesn't copy to clipboard in object inspector In this release 29 issues were closed **Pull requests** * [PR 2255](../../pull/2255) - Update French translations * [PR 2242](../../pull/2242) - Improve message for no docstring * [PR 2233](../../pull/2233) - catch a reason to crash on startup * [PR 2224](../../pull/2224) - Fix a bug in completion if callback value is not converted to string * [PR 2219](../../pull/2219) - Open configuration file with utf-8 encoding on Windows and Python 2 * [PR 2214](../../pull/2214) - Fix zlib segmentation fault in Anaconda 3.4 Linux In this release 6 pull requests were merged ---- ## Version 2.3.3 ### New features * Editor * Use the [Jedi](http://http://jedi.jedidjah.ch) library to do code completions * Add `Ctrl+=` as a shortcut to do Zoom in and `Ctrl+0` to reset zoom * Add an option to show blank spaces, under the Source menu. There is also an option to make this permanent under `Preferences > Editor`. * IPython Console * Don't print DataFrames as html tables because this won't be supported since IPython 3.0 * Drop support for IPython 0.13 * Support the upcoming 3.0 version * Add `Ctrl+T` as shortcut to open new consoles * Simplify how consoles are named * Variable Explorer * More optimizations to handle big DataFrames and NumPy arrays (i.e. with more than 1e6 elements). * Main Window * Add `Ctrl+W` and `Ctrl+F4` to close tabs in all platforms * Show shortcuts to move to each pane in `View > Panes` ### Bug fixes * [Issue 670](../../issues/670) - Visual help for indentation: draw spaces and tabs * [Issue 987](../../issues/987) - Allow the file explorer to open any file into the editor as text * [Issue 1213](../../issues/1213) - Augment or replace rope with Jedi * [Issue 1461](../../issues/1461) - Kill button 'clicked' signal is connected but never disconnected on the python shell * [Issue 1469](../../issues/1469) - Add support to get code completions for compiled modules (e.g. OpenCV) * [Issue 1484](../../issues/1484) - Debug ignores breakpoints, if there's no ASCII characters in a file path * [Issue 1574](../../issues/1574) - Creating file gives TypeError on Python 3 * [Issue 1718](../../issues/1718) - Keyboard shortcut to come back to normal zoom level * [Issue 1808](../../issues/1808) - Shortcuts to create and close IPython consoles * [Issue 1911](../../issues/1911) - Transition to git and github * [Issue 1930](../../issues/1930) - Evaluating cell or selection in Python consoles takes ages * [Issue 1946](../../issues/1946) - Spyder with GTK/GTKAgg backend on GNOME freezes * [Issue 1987](../../issues/1987) - Matplotlib backend in Mac can't be changed when using PySide * [Issue 1990](../../issues/1990) - exception in spyder internal console when typing 'exit(' in editor * [Issue 1993](../../issues/1993) - autocomplete in the middle of a word * [Issue 2006](../../issues/2006) - Your IPython frontend and kernel versions are incompatible * [Issue 2019](../../issues/2019) - Winpdb (F7) doesn't work in Python 3 * [Issue 2022](../../issues/2022) - TkAgg backend unresponsive window on Linux and OS X * [Issue 2040](../../issues/2040) - Improve inline backend options * [Issue 2049](../../issues/2049) - Pandas Dataframe not opening in Variable Explorer * [Issue 2064](../../issues/2064) - "About spyder" and "Report issue ..." output errors * [Issue 2072](../../issues/2072) - Unable to bring up tutorial * [Issue 2074](../../issues/2074) - Profiler - sorting by Total Time sorts by string order, not numeric order * [Issue 2080](../../issues/2080) - Bug on Variable Explorer while viewing DataFrames, with timestamp columns * [Issue 2082](../../issues/2082) - Missing py27 dmg download * [Issue 2092](../../issues/2092) - PYTHON pathmanager on windows 8 does not work properly * [Issue 2105](../../issues/2105) - Spyder 2.3.2 freezes when viewing big collections on the Variable Explorer * [Issue 2108](../../issues/2108) - UnicodeDecodeError in the Internal console when trying to run a file with non-ascii chars and synatx errors in it * [Issue 2109](../../issues/2109) - Go to definition menu item inactive with rope present. * [Issue 2126](../../issues/2126) - iPython console rendering of pandas.DataFrame._repr_html_() note in changelog * [Issue 2139](../../issues/2139) - Small typo in Help : Plotting examples * [Issue 2143](../../issues/2143) - Closing takes a long time with Python 3.4 * [Issue 2160](../../issues/2160) - UnicodeDecodeError when inspecting pandas DataFrame in ipython console * [Issue 2190](../../issues/2190) - Update French translations for 2.3.3 ---- ## Version 2.3.2 ### New features * Editor * Improve cells visualization * Add support for drag selection and improve look of line number area * Open on it any text file present in the File Explorer * View and edit IPython notebooks as Json files * Syntax highlighting for Json and Yaml files * Variable Explorer: * Import csv files as DataFrames (if Pandas is present) * Improve browsing speed for NumPy arrays and DataFrames with more than 1e5 rows * Debugging * Make it easier to set conditions through the Breakpoints pane * IPython Console * Add a stop button to easily stop computations * Python Console * Fixes various issues with unicode ### Bug fixes * [Issue 556](../../issues/556) - Deal with DOS/Windows encoding * [Issue 681](../../issues/681) - Allow printing Unicode characters * [Issue 875](../../issues/875) - Add indication that console is busy * [Issue 883](../../issues/883) - Open all text files in the Editor from the File Explorer * [Issue 1200](../../issues/1200) - Strings with accents and variable explorer * [Issue 1546](../../issues/1546) - Spyder issues with unicode under windows * [Issue 1767](../../issues/1767) - Some support for the ipynb format * [Issue 1774](../../issues/1774) - can't open preferences or interpreter after changing path to intepreter * [Issue 1789](../../issues/1789) - Getting warning "WARNING: Unexpected error discovering local network interfaces: 'SysOutput' object has no attribute 'flush" * [Issue 1809](../../issues/1809) - Shortcut to get to file explorer * [Issue 1812](../../issues/1812) - Erros when pressing Tab key in the Editor * [Issue 1830](../../issues/1830) - Don't modify python default system encoding in the console * [Issue 1832](../../issues/1832) - Select line via line numbers * [Issue 1847](../../issues/1847) - Preferences panel don't appear * [Issue 1849](../../issues/1849) - Support yaml files in editor * [Issue 1859](../../issues/1859) - Latest rope breaks the Object Inspector * [Issue 1874](../../issues/1874) - Wheel mouse scrolling not enabled in numberlinemarker or flag area * [Issue 1877](../../issues/1877) - Cell higlighting and scrollbar * [Issue 1878](../../issues/1878) - Cell highlighting on startup * [Issue 1891](../../issues/1891) - Sorting Variable explorer gives a traceback * [Issue 1892](../../issues/1892) - Spyder crashes because pyzmq is missing * [Issue 1949](../../issues/1949) - Spyder 'support for graphics' should not require pylab * [Issue 1953](../../issues/1953) - Please do not break API in minor releases * [Issue 1958](../../issues/1958) - Disable Variable Explorer auto-refresh feature by default * [Issue 1961](../../issues/1961) - opening bracket in editor or console: focus switches to internal console (which also display an error) * [Issue 1970](../../issues/1970) - Connecting to an IPython kernel through ssh hangs if you have never connected to hostname before * [Issue 1973](../../issues/1973) - Pandas DataFrame in variable explorer can crash the app if it gets out of memory * [Issue 1975](../../issues/1975) - Improve confusing "UMD has deleted" message * [Issue 1978](../../issues/1978) - 'Edit' context menu in Variable Explorer should work in all columns * [Issue 1979](../../issues/1979) - Spyder crashes or hangs when creating some pandas DataFrame's * [Issue 1982](../../issues/1982) - Middle mouse button *CUTS* text in editor in linux * [Issue 2004](../../issues/2004) - Open sys.stdin with the right encoding in the console for Python 2 * [Issue 2005](../../issues/2005) - Error when running files in folders with UTF-8 in path * [Issue 2008](../../issues/2008) - Wrong path to favicon.ico * [Issue 2015](../../issues/2015) - Printing large pandas DataFrame clears iPython terminal * [Issue 2033](../../issues/2033) - Link to new WinPython site * [Issue 2042](../../issues/2042) - IPython console doens't work with Pygments 2.0rc1 * [Issue 2044](../../issues/2044) - Autocomplete in the editor appends the completed variable onto the preceding expression if there's a token in between ---- ## Version 2.3.1 ### New features * Variable Explorer * Support for Pandas DataFrame's and TimeSerie's types * Support for Numpy 3D arrays * Drag and drop works for all its supported file types (e.g. images, mat files, json files, etc) * Editor * F9 runs the current line under the cursor if nothing is selected * Focus remains on it after evaluating cells and selections (an option was added to return to the old behavior) * IPython console * Connect to external kernels through ssh * Object Inspector * Add a tutorial for beginners * Main Window * Improve style on Mac ### Bug fixes * [Issue 93](../../issues/93) - Variable explorer: allow array editor to deal with arrays with more than 2 dimensions * [Issue 1160](../../issues/1160) - Variable Explorer: add support for pandas objects * [Issue 1305](../../issues/1305) - mayavi plot hangs when IPython graphics backend is inline (default) * [Issue 1319](../../issues/1319) - Spyder is not getting its taskbar icon right in Win 7/8 * [Issue 1445](../../issues/1445) - Linux style middle mouse button paste not executed in console * [Issue 1530](../../issues/1530) - Wrong encoding for date in pylint widget * [Issue 1590](../../issues/1590) - Add numpy matrices as a supported type to the Variable Explorer * [Issue 1604](../../issues/1604) - spyder 2.2.5 freezes with netCDF4-python * [Issue 1627](../../issues/1627) - Run selection (F9) changes focus to Python interpreter, but ex-Matlab users expect the focus to remain on the editor * [Issue 1670](../../issues/1670) - Provide a "Run current line" feature * [Issue 1690](../../issues/1690) - Feature request: connect to existing IPython kernel over ssh * [Issue 1699](../../issues/1699) - Option to disable middle button paste * [Issue 1783](../../issues/1783) - The new cell delimiter when converting a notebook to python file is # In[`*`] * [Issue 1863](../../issues/1863) - Ctrl-C doesn't work in a *restarted* IPython console * [Issue 1893](../../issues/1893) - Matplotlib plots do not display correctly in 2.3.0 (when running in dedicated python interpreter) ---- ## Version 2.3.0 ### New features * **Python 3 support** * Editor * Use the Tab key to do code completions * Highlight cells, i.e. portions of a file delimited by separators of the form `# %%` * First-class support for Enaml files * Syntax highlighting for Julia files * Use Shift+Tab to show the signature corresponding to a function/method while it's been called * Do code completions using the tokens (or words) found in a file * Token-based completions work for any file type supported by the Editor * Add a new tooltip widget (borrowed from the IPython project) to better handle how to show function signatures * IPython console * Assign the keyboard shortcut Ctrl+Shift+I to move to it * Open a console by default at startup * Give visual feedback when opening a console * Show kernel error messages in the client tab * Object Inspector * Add an intro message to explain how to use it * New style based on the Bootswatch Cerulean theme * Main Window * Reorganize several menus * Under the hood * Improve startup time * Develop a new way to update configuration defaults (that doesn't involve resetting user settings) ### Bug fixes * [Issue 696](../../issues/696) - Use Tab to do code completion in the Editor * [Issue 944](../../issues/944) - Add Python 3 support * [Issue 1068](../../issues/1068) - Shortcut key to switch to IPython console * [Issue 1082](../../issues/1082) - IPython console: multiprocessing print output goes to kernel not client * [Issue 1152](../../issues/1152) - Use the Editor/Console fonts for the code completion widget * [Issue 1243](../../issues/1243) - Bootstrap fails under Python 3.2 * [Issue 1356](../../issues/1356) - IPython ImportError by not using absolute_import * [Issue 1374](../../issues/1374) - IPython 1.0dev is giving "ImportError: No module named kernelmanager" * [Issue 1402](../../issues/1402) - Execute pyflakes, pep8, ... with the Python interpreter specified in Preferences>Console * [Issue 1420](../../issues/1420) - Deactivate pager by default in the iPython console (because it's perceived as a freeze) * [Issue 1424](../../issues/1424) - Object inspector is broken for external console * [Issue 1429](../../issues/1429) - Windows installer for Python 3.3 doesn't finish correctly * [Issue 1437](../../issues/1437) - Corrupted contents when saving non-unicode .py files with non-ASCII characters * [Issue 1441](../../issues/1441) - Spyder has several problems to start on Windows because pywin32 is not installed * [Issue 1465](../../issues/1465) - scientific_startup is defining print_function for Python 2.X interactive consoles * [Issue 1466](../../issues/1466) - unicode_literals breaks PySide * [Issue 1467](../../issues/1467) - pyflakes flags print "" on python2 systems * [Issue 1471](../../issues/1471) - IPython is not enabled in 2.3 (because of mismatched IPython version) * [Issue 1473](../../issues/1473) - IPython kernel can't be started, complaining that 'sys' doesn't have attribute 'argv' * [Issue 1475](../../issues/1475) - Plotting from the Variable Explorer is not working for IPython consoles * [Issue 1479](../../issues/1479) - Opening another file in a running Spyder from the terminal fails in Python 3 * [Issue 1496](../../issues/1496) - Ctrl+C don't interrupt computations in either the Console or IPython console * [Issue 1513](../../issues/1513) - "Replace all" crashes (not always, but regularly) * [Issue 1514](../../issues/1514) - Python 3 / Spyder 2.3 : impossible to run temporary script in current interpreter * [Issue 1517](../../issues/1517) - Console/IPython console reappear each time Spyder starts * [Issue 1519](../../issues/1519) - Old .spyder.ini is not copied to spyder.ini * [Issue 1528](../../issues/1528) - Error while shutting down Spyder * [Issue 1540](../../issues/1540) - Exception instead of dialog box * [Issue 1542](../../issues/1542) - Braces/Parentheses/Brackets Highlighting is broken with v2.3.0dev6 on Windows/Python 3 * [Issue 1545](../../issues/1545) - Win32 "Spyder Documentation" fails to open * [Issue 1556](../../issues/1556) - Show cells in the outline explorer * [Issue 1562](../../issues/1562) - Make Windows installers create a desktop shortcut for Spyder * [Issue 1567](../../issues/1567) - Accept newer versions of pyflakes * [Issue 1618](../../issues/1618) - Please provide a way to not compile the documentation during the build process * [Issue 1619](../../issues/1619) - Python3 invalid syntax in figureoptions.py * [Issue 1623](../../issues/1623) - Mac app: Editor slow on mac after os update to mavericks * [Issue 1628](../../issues/1628) - Profiler runs but doesn't show the results * [Issue 1631](../../issues/1631) - Documentation problem with numpy.concatenate * [Issue 1646](../../issues/1646) - Different numerical results from "runfile" and "execfile" * [Issue 1649](../../issues/1649) - Variable Explorer does not show complex number variables * [Issue 1653](../../issues/1653) - 2 popup windows during lauch * [Issue 1664](../../issues/1664) - Window gone transparent after splash screen * [Issue 1675](../../issues/1675) - Redifing any for numpy.any in the console * [Issue 1692](../../issues/1692) - Minor problem with the new Tab completion functionality * [Issue 1695](../../issues/1695) - Add "psutil" to the list of optional dependancies * [Issue 1696](../../issues/1696) - Check marks in display > windows menu are unchecked by moving plugins * [Issue 1697](../../issues/1697) - Variable explorer freezes spyder * [Issue 1701](../../issues/1701) - pip install spyder does not work any longer (pip version >=1.5) * [Issue 1715](../../issues/1715) - debian lintian4py check * [Issue 1716](../../issues/1716) - Add new icon and scripts for python3 in Linux * [Issue 1723](../../issues/1723) - .pyx Comment and syntax color error in editor * [Issue 1731](../../issues/1731) - Support Julia files (.jl) in editor * [Issue 1735](../../issues/1735) - Small correction in French translations * [Issue 1745](../../issues/1745) - Fix over-aggressive code completion on dot * [Issue 1746](../../issues/1746) - Errors when running empty cells * [Issue 1752](../../issues/1752) - Unable to read Spyder Documentation. F1 key does not work * [Issue 1753](../../issues/1753) - A fix for the behavior of spyderlib\utils\system.py on Windows * [Issue 1763](../../issues/1763) - Editor with auto-closing bracket enabled : unabled to type "0" before ")" * [Issue 1772](../../issues/1772) - Fix download links on the main page * [Issue 1786](../../issues/1786) - problem of icon with spyder 2.3.0 beta4 * [Issue 1793](../../issues/1793) - Highlight current cell slows down the Editor on big files * [Issue 1794](../../issues/1794) - Mouse pointer on vertical line * [Issue 1819](../../issues/1819) - Quick layout change unsuccessful * [Issue 1828](../../issues/1828) - QAction::eventFilter: Ambiguous shortcut overload: Ctrl+W * [Issue 1829](../../issues/1829) - Keyboard shortcuts, Reset to default values errors * [Issue 1836](../../issues/1836) - [CTRL]+F4 does not close tabs * [Issue 1879](../../issues/1879) - Can't start bootstrap.py with pyqt * [Issue 1881](../../issues/1881) - Bootstrap.py won't start with python3 ---- ## Version 2.2.5 ### Bug fixes * [Issue 1322](../../issues/1322) - Problems with scientific_startup in other interpreters from the one Spyder is running on * [Issue 1337](../../issues/1337) - Mac app - Update to Qt 4.8.4 for HDPI * [Issue 1450](../../issues/1450) - IPython kernel cpu usage increases with time * [Issue 1520](../../issues/1520) - LinuxColor for ipython plugin * [Issue 1551](../../issues/1551) - /doc/installation.rst: update Arch Linux package link * [Issue 1560](../../issues/1560) - spyder 2.2.3 incompatible with pylint 0.25.1 on Windows * [Issue 1564](../../issues/1564) - Fix several Editor cell problems * [Issue 1578](../../issues/1578) - Typo in your 'About Spyder...' dialog. * [Issue 1581](../../issues/1581) - Cannot launch Spyder 2.2.4 installed from DMG on Mac OS X. * [Issue 1589](../../issues/1589) - Mention what types of objects our Variable Explorer support in our docs * [Issue 1595](../../issues/1595) - Fail to start an ipython console when variable explorer autorefresh is turned off in Preferences * [Issue 1596](../../issues/1596) - Spelling mistake in dialog ('loose' --> 'lose') ### Other Changes * Update our Mac application to the latest versions of Python, Qt and PyQt (now it's based in Homebrew). * Several important compatibility fixes for PySide. * Improve our support for IPython 1.0+. ---- ## Version 2.2.4 ### Bug fixes * [Issue 347](../../issues/347) - Matplotlib hangs on Mac if using PySide * [Issue 1265](../../issues/1265) - Create a Debug menu to easily show how to set breakpoints * [Issue 1489](../../issues/1489) - Project Explorer does not load all projects in workspace. * [Issue 1516](../../issues/1516) - Make Spyder compatible with both IPython 0.13 and 1.0 * [Issue 1531](../../issues/1531) - Pyflakes version check is looking for 0.5.0 only * [Issue 1539](../../issues/1539) - /tmp/spyder is owned by the first user on the server to launch spyder ### Other Changes * Make Spyder compatible with SymPy 0.7.3+ * Add shortcuts to the tooltips of all toolbars * Make IPython Console work better if Matplotlib is not installed ---- ## Version 2.2.3 ### Bug fixes * [Issue 634](../../issues/634) - Debugging: Lingering break points * [Issue 639](../../issues/639) - Project Explorer: horizontal size issue (added an optional horizontal scrollbar. This option may be enabled/disabled in the widget context menu) * [Issue 749](../../issues/749) - Outline Explorer: Duplicate entries * [Issue 852](../../issues/852) - Implement matlab-like cell features * [Issue 1388](../../issues/1388) - Add an "About Spyder dependencies" dialog box * [Issue 1438](../../issues/1438) - "runfile" doesn't work correctly if unicode_literals has been imported (replaced backslashes by slashes in paths) * [Issue 1515](../../issues/1515) - Add an option to use the same interpreter Spyder is running on as "Python executable" for external consoles * [Issue 1522](../../issues/1522) - licenses of the images (especially the .png) * [Issue 1526](../../issues/1526) - Build script (setup.py) includes the wrong version of pyflakes/rope in Windows installer * [Issue 1527](../../issues/1527) - please include the LICENSE file in the source package ### Other Changes * New "Run selection" (F9), "Run cell" (Ctrl+Enter) and "Run cell and advance" (Shift+Enter) actions in "Run" menu entry, as a replacement to the old "Run selection or block" and "Run block and advance" actions. * Added "Optional Dependencies" dialog box in "?" menu. * Editor: added Monokai and Zenburn syntax coloring schemes. * Keyboard shortcuts: removing deprecated shortcuts at startup. Otherwise, when renaming the name of a registered shortcut (in the code), the old shortcut will stay in Spyder configuration file and opening the Preferences dialog will show a shortcut conflict dialog box. In other words, shortcuts were added to configuration file when registered but never removed if they were removed from the registered shortcuts in the code (or if their context or name was renamed). * External console tabs: fixed history browsing with Ctrl+Tab and added Shift+Ctrl+Tab support. * Preferences>Console>Advanced: new option to switch between the default Python executable (i.e. the one used to run Spyder itself) and the custom Python executable that the user may choose freely. This change avoid side-effects when switching from a Python distribution to another on the same OS (with the same Spyder configuration file): many users do not change the Python executable and because of the way it was written in externalconsole.py, changing from a distribution of Python to another with the same Spyder config file could lead to an unexpected configuration (Spyder is executed with the new interpreter but scripts inside Spyder are executed with the old interpreter). * Run Icons: removed deprecated images, updated other images to the new design * setup.py/Windows installers: now building CHM documentation for Windows * SPYDER_DEBUG environment variable now supports 3 levels of debug mode: * SPYDER_DEBUG=0 or False: debug mode is off * SPYDER_DEBUG=1 or True: debug level 1 is on (internal console is disconnected) * SPYDER_DEBUG=2: debug level 2 is on (+ logging coms with external Python processes) * SPYDER_DEBUG=3: debug level 3 is on (+ enabling -v option in external Python processes and debugging editor) ---- ## Version 2.2.2 ### Bug fixes * [Issue 1497](../../issues/1497) - Spyder 2.2.1 does not work with Python < 2.7 * [Issue 1498](../../issues/1498) - TypeError thrown by IPython Console when the pager is off * [Issue 1499](../../issues/1499) - Console (Terminal) throws NotImplementedError for Home/End keys * [Issue 1509](../../issues/1509) - Add support for javascript syntax highlighting * [Issue 1510](../../issues/1510) - Problems with zooming in/out ### Other Changes * Add new icons to the Run, Debug and Main toolbars * Update Pylint plugin to work with pylint 1.0 * Add Ctrl/Cmd+[+,-] to zoom in/out in the Editor * Disable Crtl+MouseWheel to zoom in/out in Mac (See Issue 1509) ---- ## Version 2.2.1 ### Bug fixes * [Issue 1231](../../issues/1231) - Some strange messages are printed in the terminal when Spyder is running * [Issue 1318](../../issues/1318) - Mac app - Unable to use the keyboard when completion widget is displayed and the app loses focus * [Issue 1331](../../issues/1331) - Git Bash: Spyder's script has wrong shebang * [Issue 1333](../../issues/1333) - Spyder is unable to detect git if installed with msysgit (Microsoft Windows PC's) * [Issue 1370](../../issues/1370) - Unit tests exceptions in IPython are displayed in its kernel tab * [Issue 1395](../../issues/1395) - Mac App - Importing matplotlib fails on Snow Leopard due to incompatible version of libpng * [Issue 1399](../../issues/1399) - Recommend to use pip instead of easy_install * [Issue 1426](../../issues/1426) - Background colour of Object Inspector (docstring) in Rich Text mode is same as the window's * [Issue 1439](../../issues/1439) - Update pil_patch to be compatible with Pillow * [Issue 1449](../../issues/1449) - Spyder --light is not functioning * [Issue 1470](../../issues/1470) - Preferences size is not saved when using PySide * [Issue 1472](../../issues/1472) - matplotlib plot's docstring is not rendered correctly in the Object Inspector ### Other Changes * All scientific libraries in our Mac application were updated to their latest releases. * The _Run Settings_ dialog has now its own icon. Before it was the same as the _Preferences_ pane one. * Update and improve our _Installation_ instructions for all platforms. * Add support for Google TODO comments: "TODO(username@domain.com): blabla" ---- ## Version 2.2.0 ### New features * **Better integration with IPython**. * A dedicated preferences page from which you can set its most important options * An easy way to manage IPython kernels inside Spyder (i.e. interrupts and restarts). * Each console can be configured separately (which is not possible in IPython-qtconsole) * Each console is now connected to the Object Inspector and the History log. * Learn how to use IPython reading its documentation on the Object Inspector. * Find text in the console and pager using our Find Widget. * A new **MacOS X Application** * We now provide a DMG for simple drag and drop installation. * The App comes with its own interpreter, which has the main Python scientific libraries preinstalled: Numpy, SciPy, Matplotlib, IPython, Pandas, Sympy, Scikit-learn and Scikit-image. * A much improved debugging experience * A new debugger toolbar, quite similar in spirit to the one present in Matlab. It works with both Python and IPython consoles. * A new breakpoints widget, which lists all active breakpoints set in open or closed files. * Breakpoints are updated in the Python and IPython consoles after being added or removed from the Editor. * Several Editor improvements * Faster and more accurate code completions for the most important scientific packages * Zoom in and out with Ctrl + the mouse wheel * A new dark theme * Automatic insertion of colons * Automatic insertion of quotes * New syntax highlighters for Matlab, batch, ini, NSIS and IDL files. * A better looking and faster Object Inspector * Several improvements to its style. * It can now show mathematical equations written in Latex, using the MathJax Sphinx plugin. * Rich text docs are now rendered in a thread to avoid UI lookup. * **Single instance mode** * Users can now open Python scripts from their file explorer on the currently available instance. * Linux users can also open their files from the terminal. * Spanish translation of the interface ### Bug fixes * [Issue 318](../../issues/318) - Create a widget to list all breakpoints * [Issue 349](../../issues/349) - Add "Run selection or current block" action to Editor's context menu * [Issue 448](../../issues/448) - Editor: disable code-related features inside comments (code completion, auto-indentation, ...) * [Issue 466](../../issues/466) - Can't use Spyder to open python scripts (.py files) from the terminal or the file explorer * [Issue 554](../../issues/554) - Improved debugger integration * [Issue 609](../../issues/609) - Debugging: Unsetting a breakpoint in the editor isn't reflected until you restart debugging entirely * [Issue 650](../../issues/650) - After deleting a directory set as working directory and changing to a new working directory the script won't run * [Issue 687](../../issues/687) - Indentation error when trying to "run selection" on simple indented code * [Issue 697](../../issues/697) - Create a DMG package for Spyder * [Issue 764](../../issues/764) - Jump to the next result when pressing Enter in search field * [Issue 836](../../issues/836) - Spyder is sometimes not detecting file changes from external editors * [Issue 849](../../issues/849) - Breakpoints are ignored sometimes * [Issue 853](../../issues/853) - Problems with code completion after adding submodules to ROPE_PREFS/extension_modules * [Issue 865](../../issues/865) - Run selection (F9) in IPython console 0.11+: problem with indented blank lines * [Issue 940](../../issues/940) - open_in_spyder not defined * [Issue 955](../../issues/955) - Breakpoints in debugger do not move correctly when editing code * [Issue 971](../../issues/971) - Add "Open with Spyder" entry to Windows File Explorer's context menu * [Issue 994](../../issues/994) - mathjax does not get installed properly * [Issue 997](../../issues/997) - Some docstrings are getting truncated in the object inspector * [Issue 1008](../../issues/1008) - Fail on context menu call in project explorer when project files are inside symlinked dir * [Issue 1018](../../issues/1018) - Menu locations, "Run Configurations" & "Preferences" * [Issue 1026](../../issues/1026) - Decide the best strategy to comment selections on the Editor * [Issue 1032](../../issues/1032) - Running a script from editor does not send runfile() correctly to IPython Qt plugin * [Issue 1050](../../issues/1050) - First implementation of the "IPython Console" plugin (single instance version) * [Issue 1051](../../issues/1051) - New IPython Console (Spyder 2.2+): add support for the %edit magic command * [Issue 1054](../../issues/1054) - New IPython Console (Spyder 2.2+): update variable explorer after new prompt * [Issue 1055](../../issues/1055) - New IPython Console (Spyder 2.2+): add support for history management * [Issue 1056](../../issues/1056) - New IPython Console (Spyder 2.2+): add an option to customize In/Out prompts * [Issue 1057](../../issues/1057) - New IPython Console (Spyder 2.2+): Add our FindReplace widget to every console * [Issue 1058](../../issues/1058) - New IPython Console (Spyder 2.2+): Add Ctrl+I keyboard shortcut to send an object the Object Inspector * [Issue 1059](../../issues/1059) - New IPython Console (Spyder 2.2+): drop support for IPython in external console * [Issue 1061](../../issues/1061) - New IPython Console (Spyder 2.2+): add support for "Find in files" plugin * [Issue 1062](../../issues/1062) - New IPython Console (Spyder 2.2+): add a dedicated section in documentation * [Issue 1064](../../issues/1064) - Editor performance issue since revision d98df4092e16 * [Issue 1069](../../issues/1069) - Focus goes to kernel not client with pdb in IPython client * [Issue 1078](../../issues/1078) - IPython Console: Cannot interrupt started processes * [Issue 1079](../../issues/1079) - Can't input Unicode in Internal Console * [Issue 1081](../../issues/1081) - ipython-qtconsole not listed as optional dependency in Ubuntu * [Issue 1083](../../issues/1083) - Make Ipython qtconsole widget more intuitive * [Issue 1085](../../issues/1085) - IPython console: sometimes files are executed in wrong IPython * [Issue 1094](../../issues/1094) - Error message when trying to save a file * [Issue 1095](../../issues/1095) - Preferences Dialog doesn't remember size * [Issue 1101](../../issues/1101) - Interrupt (Ctrl+C) in the console does not work in Spyder on Mac Os X * [Issue 1106](../../issues/1106) - Spyder console crashes when trying to type in console after running script * [Issue 1112](../../issues/1112) - Opening a file from the linux command line * [Issue 1128](../../issues/1128) - please remove pyflakes and rope from the .zip files * [Issue 1136](../../issues/1136) - IPython console: cannot connect to external kernels * [Issue 1138](../../issues/1138) - Rich text in object inspector mishandles some scipy docstrings * [Issue 1163](../../issues/1163) - Improve the spyder.desktop file fo easier integration into Linux * [Issue 1169](../../issues/1169) - Saving variables does not retain uppercase letters of variable names * [Issue 1179](../../issues/1179) - Pylint "go to line" does not work with the additional dot in filename * [Issue 1186](../../issues/1186) - scipy.weave doesn't work in the Mac app * [Issue 1191](../../issues/1191) - Inconsistent behaviour of the Editor on code completion and object introspection * [Issue 1199](../../issues/1199) - spyderlib/utils/windows.py has incorrect encoding * [Issue 1201](../../issues/1201) - Let the user set the default filter when opening file * [Issue 1210](../../issues/1210) - Enhancement: Create sphinx rich text docstrings in QThread * [Issue 1226](../../issues/1226) - MacOS X App - Can't import libraries from other Python interpreters * [Issue 1227](../../issues/1227) - Auto inserted colon causes pylint error * [Issue 1229](../../issues/1229) - Which version of ipython is needed for Spyder 2.2.0? * [Issue 1230](../../issues/1230) - Better handle for mathjax and jquery embeded libraries on linux systems * [Issue 1232](../../issues/1232) - Cmd-Space is not showing code-completion options * [Issue 1233](../../issues/1233) - ERROR and WARNING when compiling the documentation * [Issue 1234](../../issues/1234) - Edit .enaml files as text file * [Issue 1236](../../issues/1236) - Fix Qt Network Access warning messages that appear on the terminal * [Issue 1241](../../issues/1241) - 'Remove block comment' is not working * [Issue 1242](../../issues/1242) - Can't start spyder2.2 on Win 7, crashes upon saving .spyder.ini * [Issue 1249](../../issues/1249) - "Run block" and "Run File" are not working for external IPython kernels * [Issue 1250](../../issues/1250) - Spyder crashes on launch if the project explorer is used * [Issue 1252](../../issues/1252) - Expansion of nodes on tree view undoes itself * [Issue 1253](../../issues/1253) - Spyder is not detecting the presence of iPython 0.13.1rc2 nor IPython 1.0dev * [Issue 1258](../../issues/1258) - Focusing the "Replace with:" Text Box causes the editor to jump to the next instance of the item that's in the find box * [Issue 1261](../../issues/1261) - IPython kernel/clients: error when closing an IPython console * [Issue 1266](../../issues/1266) - Let the user eliminate breakpoints from the "Breakpoints widget" * [Issue 1269](../../issues/1269) - Dataloss when Spyder gets confused about which file goes with which editor tab * [Issue 1271](../../issues/1271) - Find and replace by empty string * [Issue 1272](../../issues/1272) - Fix code completion speed issues on the Editor * [Issue 1275](../../issues/1275) - Spyderlib fails to start new IPython consoles, raises socket exception * [Issue 1277](../../issues/1277) - Enthought Python Distribution and Spyder DMG are not working well on Mac OS X * [Issue 1281](../../issues/1281) - Mac App - Spyder swallows AssertionErrors while executing a file * [Issue 1285](../../issues/1285) - Object Inspector Crashes when Reloading Page * [Issue 1286](../../issues/1286) - Broken links in Help * [Issue 1287](../../issues/1287) - Saving file under different file name in split-window mode lets non-focused window jump to first file * [Issue 1288](../../issues/1288) - Some rope_patch improvements * [Issue 1296](../../issues/1296) - Clickable tracebacks in console are not working in PySide * [Issue 1298](../../issues/1298) - Mac App - matplotlib is not detecting ffmpeg to create animations * [Issue 1299](../../issues/1299) - pylint keeps opening same file at startup * [Issue 1309](../../issues/1309) - Clicking on filename in structure widget sets the cursor at the beginning of the file * [Issue 1314](../../issues/1314) - QPainter warnings when moving/undocking widgets in main window * [Issue 1315](../../issues/1315) - Project not closing files associated with after closing it * [Issue 1325](../../issues/1325) - Spyder cannot be re-opened on Windows if parent console is closed * [Issue 1327](../../issues/1327) - Allow global options for Run Configuration * [Issue 1344](../../issues/1344) - Mac App - Spyder crashed and can't be open again * [Issue 1345](../../issues/1345) - Code Review Request: Update breakpoints during pdb sessions * [Issue 1347](../../issues/1347) - The spyder.desktop has an wrong line * [Issue 1353](../../issues/1353) - Error messages in internal console when rope is not installed * [Issue 1363](../../issues/1363) - 2.2rc installation takes a long time because of sphinx dependency * [Issue 1364](../../issues/1364) - No spyder.ico after installation on Windows * [Issue 1369](../../issues/1369) - Using the subprocess.check_output function breaks compatibility with Python 2.5 and 2.6 * [Issue 1371](../../issues/1371) - Crash when adding text to multiline comment is CSS * [Issue 1372](../../issues/1372) - SphinxThread might return AttributeError ---- ## Version 2.1.13.1 ### Bug fixes * Spyder startup: fixed PyQt minimum version requirement test (the old poor comparison algorithm was considering that v4.10 was older than v4.4...) (See [Issue 1291](../../issues/1291)) * Console: Matplotlib was always imported even when the Matplotlib's Patch option was not available (i.e. the Matplotlib installed version was not compatible with the patch). As a consequence, even when disabling every console advanced option in preferences, the preloaded module list was huge * Editor: * When closing Spyder with unsaved modified files, Spyder was asking confirmation as many times as there were editor windows. Only one confirmation is necessary because, with current editor design, all editor windows are synced. * When creating two new files, saving one of them will lead to temporarily mask the leading '`*`' indicating the fact that the other untitled file was not already saved. This is simply a display issue: internally, it is clear that the file is in a non-saved state and Spyder will ask for it to be saved when trying to close the file * Multiple windows: when saving a new untitled file, other editor windows were getting confused on file list order -- eventually leading to data loss * Open file dialog: default file type filter now matches the current file (See [Issue 1201](../../issues/1201)) * Fixed "PyQt Reference Guide" link ### Other changes * Editor: Ctrl+MouseWheel is now zooming in/out the editor text size (see [Issue 1270](../../issues/1270)) * About dialog box: changed the "This project is part of Python(x,y)" part to more general words (which are also closer to the initial meaning of this sentence) including a citation of WinPython ---- ## Version 2.1.13 ### Bug fixes * Fixed [Issue 1158](../../issues/1158): "pip install spyder" fails on non-Windows platforms due to a bug in pip installation process (missing spyderlib_win_postinstall.py script) * File Explorer/Windows/Fixed "remove tree" feature: added an error handler in shutil.rmtree to be able to remove a non-empty folder with shutil.rmtree is not working on Windows when it contains read-only files * (See [Issue 1106](../../issues/1106)) Fixed "error: unpack requires a string argument of length 8" related to socket communication between Spyder and the remote Python process * Editor: * After splitting horizontally or vertically the editor window, filenames were not synchronized when saving a file as another name (see [Issue 1120](../../issues/1120)) * Fixed error when trying to "Save as..." a file with extension to a file without any extension (see [Issue 1183](../../issues/1183)) * pep8 code analysis: a new line character was abusively added by Spyder to source code before analyzing it because it's necessary for pyflakes but it's not for pep8! (see [Issue 1123](../../issues/1123)) * Fixed UnboundLocalError when clicking on "Search/Replace" button if both search pattern and replace pattern fields are empty (see [Issue 1188](../../issues/1188)) * Pylint plugin/tree widget: "go to line" was not working when filename contained additionnal dots (see [Issue 1179](../../issues/1179)) * Fixed critical bug when an invalid/unsupported version of pyflakes is installed (see [Issue 1181](../../issues/1181)) * Editor/block comments: fixed remaining PyQt API v2 compatibility issues (see [Issue 905](../../issues/905)) * Variable explorer: more flexible name fixing algorithm (even if it's not a good practice to use reference names with upper case letters, we do not remove them anymore) -- See [Issue 1169](../../issues/1169) ### Other changes * Spyder about dialog box: added Python build architecture (32 or 64 bits) * Find in files: fixed default 'exclude pattern' which was accidently excluding all files starting with 'build' instead of simply excluding 'build' folders as intended * For the sake of consistency, now using single-clicks for activating entries of all tree widgets in Spyder ("Find in files" and "Pylint" are now consistent with the "Outline" explorer) -- See [Issue 1180](../../issues/1180) ---- ## Version 2.1.12 ### Bug fixes * Spyder settings: sometimes (virus protection?) the .ini file can't be written, and removing the .ini file before writing seems to help, as suggested [here](https://groups.google.com/forum/#!msg/spyderlib/a_P9JBJEZeE/gOK_Pr2WbE8J) (see [Issue 1086](../../issues/1086)) * Fixed Home/End key behaviour inconsistency on MacOS X (See [Issue 495](../../issues/495)) * Internal console: new option "Pop up internal console when errors were intercepted" -- default: False, which avoids loosing focus when a traceback is shown in the internal console... but features may also fail silently! (bugs could stay hidden a while before being taken care of) -- See [Issue 1016](../../issues/1016) * Fixed "TypeError: file_saved(long,long).emit(): argument 1 has unexpected type 'long'" error occuring on some Linux 32-bit platforms -- See [Issue 1094](../../issues/1094) * Console: find/replace widget "Search next/previous occurrence" feature was broken ### Other changes * Portable version of Spyder (inside WinPython): * Spyder '?' menu: added documentation detection (.chm, .pdf) in sys.prefix\Doc (Windows-only) * Project explorer: * Handling errors when opening a workspace which has been moved * Workspace is now configured with relative paths, so it can be moved from a location to another and still be opened in Spyder * Windows: moved the functions hiding parent console to spyderlib/utils/windows.py ---- ### Version 2.1.11 ### Bug fixes * Critical bugs: * Editor ([Issue 960](../../issues/960)): cannot open/save files from GUI (QFileDialog issue with PyQt4 v4.6) * General: * Spyder menu bar: fixed menu ordering issue with Ubuntu/Unity * All console widgets: Shell widget: fixed "Clear terminal" (Ctrl+L) shortcut * Console: * Cleaned up widget interactions after Python script execution (before this changeset, it was possible to send data to console, which not only was not needed but was generating disturbing errors in the internal console...) * Editor: * If user accept to fix "mixed end-of-line characters", when opening file, the current editor was set as "modified" (the tab title had a `*` at the end) instead of the newly created editor * "occurrence highlighting" was highlighting previous word even if there was a whitespace between cursor and this word * Code analysis thread manager: handling errors while executing threads * "Replace all" was not regrouping changes into a single undo/redo step * "Find/Replace": replacements were not done for case unsensitive searches * Position of the 79-chars edge line is now more accurate on Linux, the older processed position was inaccurate with some font size of the classic "DejaVu Sans Mono" monospace font * IPython: * Version detection was broken so Preferences...Console...External Modules was incorreclty hiding the command line options line edit * Because the detection was not working correctly, it was not possible to start an IPython kernel with the just released IPython 0.13 * Project explorer was sometimes producing AttributeError when loading because of the workspace was not defined at the beginning of the class constructor * pyflakes code analysis function: * Handling files with invalid \x or null chars * This fixes a part of [Issue 1016](../../issues/1016) by handling the following pyflakes bugs: * http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=674796 * http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=674797 ### Other changes * Installer for Windows (bdist_wininst/bdist_msi): * added Start Menu shortcuts * added 'pyflakes' and 'rope' (if available in the repository) to the package list (this is not conventional but Spyder really need those tools and there is not decent package manager on Windows platforms, so...) * This change will make the Spyder building process simpler for Windows as the Python(x,y) won't be needed anymore to provide Start Menu shortcuts or to install 'rope' and 'pyflakes' at the same time. Now, there is no significative difference between the standard installers built with distutils (bdist_wininst or bdist_msi options) and the Python(x,y) plugin, except for the "package upgrade" ability (uninstall previous version) which is still not (and won't be) supported by distutils. ---- ## Version 2.1.10 ### Bug fixes * Critical bugs: * Spyder crashed at startup/TypeError: `_isdir()` takes exactly 1 argument (0 given). Affects only Windows platforms with Python 3.2.2+ or 2.7.3+) * Spyder was freezing when working with netCDF4 objects in the interactive console * Console: h5py was systematically imported to avoid crashes with the HDF5 plugin (Variable Explorer's I/O plugin). These ugly workarounds introduced with revision 3affc82ce081 were removed in this changeset to avoid side effects like DLL version conflict on Windows platforms. The main risk of this change is to break the HDF5 plugin on some configurations. But this is the best compromise. * General: * Fixed regression: when no Qt library is installed (PyQt/PySide), warning the user with a Tkinter dialog box (if possible) * Fixed Preferences Dialog flickering issue introduced with revision a4e1565e93c5 * Run configuration dialog: fixed Tab focus order behavior * Fixed "Run > Configure..." and "PYTHONPATH management" entry locations on MacOSX * Updated bootstrap script and Qt library selection logic to accomodate launch of Spyder using PySide while PyQt is also installed ([Issue 1013](../../issues/1013), see [Issue 975](../../issues/975) for additional background). * Fixed several encoding problems preventing Spyder from launching when the user's home directory contains non-ASCII characters ([Issue 812](../../issues/812), [Issue 1027](../../issues/2017)). * Debugging: [Issue 684](../../issues/684): Debug with winpdb will now use the command line options and working directory specified in the General Setting section of the Run Configuration dialog * Console: * Changed "Clear shell" shortcut to "Ctrl+L" to avoid conflict with the Windows Task Manager shortcut on Windows platforms * Preferences/Advanced options: added option to start an IPython kernel at startup * Editor: * When multiple files were open, close-clicking 1 file was closing 2 files on 64-bits OS * Conditional breakpoint could not be changed to regular breakpoint * Outline Explorer: removed obsolete decorated methods icon (a decorated method is now shown exactly as a regular method) * Top-left corner menu (file list): fixed common prefix removal feature * "Outline" item selection opened in incorrect split panel due to a lost signal when focus changed from an editor to another * when splitting window after changing a shortcut, old shortcut was still active * Internal console/fixed an old regression: re-added help(), raw_input() support * Profiler: tree was sometimes empty + fixed error when file path contained "&" * File/Project explorer: fixed [by shchelokovskyy] Git commit/browse support * Find in files: fixed crash due to a bug in the common prefix finder function ### Other changes * Checked Spyder's `rope` patch compatibility with rope v0.9.4 * IPython plugin (experimental): * added support for "Execute in current interpreter" * added support for "Execute selection or block (F9)" * imports from local directory did not work * when a new kernel is started in Console, tabifying the frontend to the Console (for the first created frontend) and the next frontends to the previously created frontend * clients (frontends) may now really be closed (see context menu). The associated kernel and related clients may be closed as well (a message box dialog ask the user about this) * added support for the "Object Inspector to/from IPython kernel" link * improved reliability of the "Editor to/from IPython kernel" link * fixed focus management issue (link with variable explorer and object inspector) ---- ## Version 2.1.9 ### Bug fixes * Run configuration/bugfix: command line options were not properly parsed * Preferences dialog was not showing up with PySide installed *and* without PyQt4 * Editor: * Closing additional editor window produced traceback and primary editor breakdown * File/Open: embedded editor popped up even if there is one in a separate window * Selecting a part of a word raises an IndexError exception * Revert option was prompting for user input even on an unmodified buffer * Added missing .f77 file extensions for Fortran files filter * Occurrence highlighting was not working when cursor was at the left side of a word and if the next character was ':', ',' or '(' (or any other character not matching the "word regexp") * Console: * Console was unusable (endless tracebacks) when monitor was disabled * File drag'n drop was not working (should execute dropped file) * (Experimental) IPython plugin: * Fixed compatibility issues with PyQt4 and IPython 0.12 * Fixed multiple instances issue (it was not possible to open more than one IPython frontend) and other issues * IPython kernel connections were unpredictable ([Issue 977](../../issues/977)) * Dictionary editor (Variable explorer): fixed UnboundLocalError when context menu is called on an empty table * Object inspector failed to show an error message due to unicode error * Project Explorer: * "Show all files" option was broken after restarting Spyder * It was impossible to create a project from an existing directory located outside the workspace ---- ## Version 2.1.8 ### Bug fixes * Editor/Source code toolbar: * "Show task list" and "Go to the next task" actions: the "Show TODO/FIXME/XXX/HINT/TIP comments list" button was not working * "Show warning/error list" and "Go to the next warning/error" actions: the "Show code analysis warnings/errors" button was not working ---- ## Version 2.1.7 ### Bug fixes * Main window: * Detached dockwidgets were not painted after restarting Spyder ([Issue 880](../../issues/880)) * Console: * Enhanced Python interpreter: %clear command was broken since v2.1.5 * Object inspector's rich text mode: fixed unexpected indent error * IPython plugin: fixed compatibility issue with latest v0.12dev (thanks to Boris Gorelik) ### Other changes * Variable explorer/Array editor: added support for masked arrays * Showing Spyder's internal console automatically when there is a traceback * Do not crash when a 3rd party plugin failed to import * Editor: * Automatic insertion of single, double and triple quotes * Automatically colons insertion when pressing Enter after 'if', 'def', etc * Don't trigger code completion on comments if text ends with a dot * Added keyboard shortcut (Ctrl+Shift+Escape) to clear the console * Added keyboard shortcut (Ctrl+P) to print current file (thanks to fheday at gmail dot com for the contribution) * Code introspection features (code completion, calltips, go-to-definition) are now working even if script has syntax errors ---- ## Version 2.1.6 ### Bug fixes * Critical bug on certain Windows platforms (not sure yet if it's related to a particular version of PyQt or something else): all plugins (dockwidgets) were shown detached (or hidden) from the mainwindow at startup (this is related to the attempt fixing [Issue 880](../../issues/880)) ---- ## Version 2.1.5 ### Bug fixes * Detached dockwidgets (Console, ...) were not painted after restarting Spyder * Editor/Outline-bugfix: duplicate entries were shown when the editor was synchronizing file contents with disk * File/Project explorer: * Fixed regression regarding [Issue 740](../../issues/740) (fixed in v2.1.0, re-introduced in v2.1.2): couldn't open files with non-ascii characters in their names * SCM support: commit/log actions were not working when right-clicking on a file instead of a folder * Console: * Monitor/Introspection: fixed socket communication issue due to a MemoryError -- This error was mixing communication messages, causing various problems described in [Issue 857](../../issues/847) and [Issue 858](../../issues/858). This bug was reported by ruoyu0088, who also tried (and succeeded) to fix it and suggested a workaround which is implemented in this release * Fix critical console hang on OS X when using the "Run selection or current block feature" (see [Issue 502](../../issues/502)) * Apply the right scheme color to the IPython console when there weren't any options provided by the user or when the only option was "-colors LightBG" * Windows platforms: * "Preferences" dialog was not shown if account username contained non-ASCII characters * Object Inspector: * Show signatures for docstrings sent from the Editor (see [Issue 690](../../issues/690)) ### Other changes * Debugging: when a non-empty SPYDER_DEBUG environment variable exists, Spyder switch to debug mode (log files are created in user's home directory and debug prints are available in the terminal) * Variable explorer/Dictionary editor: added option to plot histogram from a 1-D array * Console: * standard Python interpreter is now a real Python interactive session: the older implementation was running a startup script and tried to emulate a standard Python interactive session (changing attributes like __name__, running the PYTHONSTARTUP script, etc.). But this implementation was not close enough to the standard Python interactive session, i.e. when you execute `python` outside Spyder, without any argument. A recent bug report confirmed this: the PYTHONSTARTUP script was executed but not exactly the same way as it is outside Spyder: for example, doing `from __future__ import division` in the startup script had no effect whereas it did outside Spyder. * when running a standard Python interpreter, instead of running the startup script (spyderlib/widgets/externalshell/startup.py), the shell widget (ExternalPythonShell) simply runs the python executable with -u -i options, that's all. So now, the PYTHONSTARTUP script is executed as expected. * Scientific startup script (default PYTHONSTARTUP in Spyder): added floating point division (from __future__ import division) * PySide support: * Added new "Qt (PyQt/PySide)" settings group in "External modules" tab * It is now possible to select the Qt-Python bindings library: default (i.e. depends on the QT_API environment variable), PyQt or PySide * The PyQt input hook has been adapted for PySide, so it is now possible to do interactive (non-blocking) plotting with PySide * New options for standard Python interpreters (no effect on IPython): * "Merge process standard output/error channels": merging the output channels of the process means that the standard error won't be written in red anymore, but this has the effect of speeding up display * "Colorize standard error channel using ANSI escape codes": this method is the only way to have colorized standard error channel when the output channels have been merged * Internal console ([Issue 868](../../issues/868)): output is now immediately available * "Maximize current plugin" action: now automatically shows the "Outline" plugin when maximizing the "Editor" plugin * Editor/Outline comment separators: allow space betwee hash and dash, e.g "# --- Outline Separator" ---- ## Version 2.1.4 ### Bug fixes * Console: * *Critical bugfix* for IPython support: variable explorer link was broken (regression introduced with v2.1.3) ### Other changes * Console: * option "Open an IPython interperter at startup" is now *explicitely* disabled for IPython v0.11+ (these versions of IPython are not fully supported through Spyder's console plugin) ---- ## Version 2.1.3 ### Enhancements * Variable explorer performance were improved, especially when dealing with very long sequences -- See [this discussion](http://groups.google.com/group/spyderlib/browse_thread/thread/3a7ef892695e417a) * Variable explorer / dictionary editor: added support for unknown objects -- this allows browsing any object attributes -- This is still experimental. ### Bug fixes * General: * Spyder preferences/bugfix: comboboxes with keys other than strings (e.g. the PyQt API selection combo box) were not initialized properly * Fixed memory leaks (QThread objects) in the "Editor" and "Find in files" plugins. In those two plugins, QThread objects were created, then started but were never garbage-collected after they finished their execution * Editor: * Supported file types: added missing C++ file extensions (.cc, .hh, .hxx) * Variable explorer: * Debugging: added support for editing objects within functions * Debugging: when debugging, variable explorer link was broken after restarting program * handling errors when trying to enable/disable autorefresh (if one of the running console has no monitor enabled) * Project explorer: * when the workspace has not yet been defined, creating a new project not only warns the user but also proposes to set it right away ---- ## Version 2.1.2 ### Bug fixes * General: * Patched external path library to avoid a crash with a user HOME directory with non-ascii characters * Doc/README: warning the user about the fact that the 'python setup.py install' method does not uninstall a previous version * Console: * Fixed "AccessInit: hash collision: 3 for both 1 and 1" error (see [Issue 595](../../issues/595)) * Project explorer: * empty workspace/critical bugfix: impossible to create/import projects from context menu (this bug was introduced with a recent revision and stayed unnoticed until then because one has to test this from an empty workspace) * it is now possible to rename projects (safely) * now handling the I/O errors (e.g. read-only configuration files) occuring when loading/saving projects or the workspace: warning the user when an IOError exception was raised and mention the projects which could not be saved properly * File/Project explorer: * keyboard shortcut 'F2' (rename file/directory) was broken * the "Open" action (context menu) was failing silently for directories (expected behavior: open an external file explorer to browse the directory) * programs.start_file/bugfix: feature was not working on Windows 7 * Editor: * Fix empty username in new file template on OS X (patch by Christoph Gohle) * Object inspector: * Rich text mode was not showing headings when invoked from editor ([Issue 690](../../issues/690)) ### Enhancements * File/Project explorer: * Added "Delete" keyboard shortcut to remove selected file(s)/folder(s) * SCM integration: added support for TortoiseHg v2 (only v1 was supported) * Console/Matplotlib options: the backend may now be set separately from the Matplotlib patch ### Other changes * Console: * The Matplotlib patch is only applied for Matplotlib <=v1.0 * PyQt API version issues (error like "ValueError: API 'QString' has already been set to version 1"): the "ignore setapi errors" option is disabled by default, to avoid masking these errors and associated tracebacks ---- ## Version 2.1.1 _Note:_ v2.1.1 is a minor update of v2.1.0 (licence issues and minor bug fixes) Follow Spyder news on our official blog: http://spyder-ide.blogspot.com/ ### Compatibility/Requirements Since version 2.1: * Spyder is now compatible with: * PyQt's API v1 (i.e. compatible with PyQt 4.4 and 4.5), the default Python 2 API * *and* PyQt's API v2 (this is the future: default Python 3 API and PySide-compatible API) * *and* with PySide (PySide support is still experimental as this library is still young but its stability is evolving rapidly) * Editor/code analysis: Spyder now requires *pyflakes v0.5.0* (included in Windows installers). ### New features since v2.0.12 * New *Profiler* plugin (thanks to Santiago Jaramillo) * New experimental *IPython* plugin embedding IPython's Qt console: see [here](http://spyder-ide.blogspot.com/2011/08/preview-of-new-ipython-plugin-for.html) * General: * Main window: * added "Custom window layouts" management (see menu "View")/handling 3 custom layouts: default shortcuts Shift+Alt+FX to switch to/from layout #X and Ctrl+Shift+Alt+FX to set layout #X * "General" preferences page: added option to set the Qt windows style, depending on platform (Plastique, Cleanlooks, CDE, Windows...) * Menu "?": added menu entry to report Spyder issues, filling automatically informations on your configuration * Reorganized "Run"/"Source" menu, added "Interpreters" menu * Fixed application name for Gnome 3/Fedora 15 * Command line options: added option "--defaults" to reset settings (stored in .spyder.ini) to defaults (a lot of settings are preserved: shortcuts, window layouts, ...) -- this is less brutal than "--reset" which reset all settings by removing all configuration files related to Spyder * *Outline* (function/class browser) is now a plugin in itself, embedded in its own dockwidget: Spyder's window layout is even more customizable than before * *Code completion* * (Editor/Console): entries starting with an underscore character are now placed to the end of the suggested list * (Editor/Console): Import statements are now completed correctly * *Console*: * Major code cleaning: running Python applications in Spyder has never been cleaner and is very close to a simple Python interpreter * Added built-in function `open_in_spyder` to open a file in Spyder's source code editor from the console * Standard Python interpreter: * now refresh the variable explorer at each new prompt (even if auto-refresh is disabled -- actually, this is the typical use case) * added support for basic special commands (%pwd, %ls, %clear) and system commands (starting with '!', e.g. !dir or !ls) * added ["scientific" startup script](http://spyder-ide.blogspot.com/2011/09/new-enhanced-scientific-python.html) with support for numpy, scipy and matplotlib * Preferences (External modules tab): * added an option to set PyQt API to v1 or v2 -- this avoids issues with Enthought Tool Suite or any other library/program using PyQt API v2 which is *not* the default API for Python 2 * changed matplotlib patch to fix compatiblity issue with PyQt API v2 * Preferences (Advanced Settings tab): added option "Python executable" to customize path to Python interpreter executable binary * *Variable explorer*: * New HDF5 plugin by [DavidAnthonyPowell](http://code.google.com/u/DavidAnthonyPowell/): import/export HDF5 files to/from the variable explorer * Dictionary editor/Variable explorer: * Added support for more NumPy data types * Added action "Resize rows to contents" (partially implements feature requested with [Issue 807](../../issues/807)) * *Editor*: * find/replace: * added support for *multiline* regular expression search pattern * added support for *multiline* regular expression text replacement * added button "Highlight matches" to highlight all found results * syntax highlighting: added support for OpenCL, gettext files, patch/diff files, CSS and HTML files * support for "2 spaces" and "tabs" indentation characters * new code analysis feature: added support for the [pep8](http://pypi.python.org/pypi/pep8) style guide checker * "Comment" and "Uncomment" actions were replaced by a single "Comment/Uncommment" toggle action * (Fixes [Issue 811](../../issues/811) ) "Run configuration": added "Run in an external system terminal" option * *File explorer* and *Project explorer*: * great performance improvement (using a multithreaded file system model) * Added minimalist SCM support (Mercurial and git are currently supported) * *File explorer*: added an option to "Show current directory only" * *Project explorer*: this plugin was entirely rewritten to improve performances and usability * *Pylint plugin*: * added option to save file before analyzing it * Spyder's console embedded in your application (spyderlib.widgets.internalshell): * in traceback, a clickable link now opens the associated file in Spyder (if application was launched from Spyder with monitor enabled) * Application sample embedding Spyder's internal shell: upgraded to guidata v1.4+ (simplified build script a lot) * Windows platforms specific changes: * (requires pywin32) Hiding the attached console window: * allow running Spyder with 'python.exe' without visible console (this avoid using 'pythonw.exe' which does not attach a console to the process, hence preventing standard I/O to be redirected in a subprocess executed within Spyder, e.g. in your own program) * the attached console may be shown/hidden from menu entry "View > Attached console window (debugging)" * Major change for Windows/PyQt users: standard Python interpreter now supports interactive GUI manipulations thanks to a new Spyder-specific input hook (replacing PyQt's input hook which is not working within Spyder on Windows platforms) -- the input hook works even better than PyQt's builtin input hook (with a Python interpreter opened outside Spyder) * Spyder's stand-alone version building process was improved. This version is now available on project's download page. ### Bug fixes (since v2.0.12) * Spyder's main window: * QtDesigner and QtLinguist were not detected on Fedora * Console/Editor: code completion widget was partially hidden when working on two monitors and if Spyder's window was on the right screen * Fixed bugs due to too early/frequent calls to plugin refresh methods during startup * Console: * IPython Interpreter: Turn off autoindent magic to avoid indentation errors with code with inline comments * Editor: * Fortran syntax highlighter was made case insensitive * Fixed IndentationError when running first line of a file * Read only files allowed ".", "[", "(", etc. to be entered into the text editor * Fixed segmentation faults occuring after using the vertical-horizontal splitting feature * If a file name had non-ascii characters then code completion (and all other rope-based features) in the editor stopped working * Code analysis: fixed tasks pattern (for example, previous one was matching "TIP" in "MULTIPLICATION"... now it will match only single "TIP:" or "TIP ") * (Fixes [Issue 704](../../issues/704)) Outline was showing the delimiters of block comments ('#------...-'), causing nesting inconsistencies because block comments are not indented properly with respect to the code around * Fixed several bugs with the "Run selection or current block" feature. * Object inspector: * Rich text mode was failing for non-ascii docstrings * Find/Replace widget: * Combo box history was populated only when pressing Enter (now pressing F3 to find next occurrence will add the current entry to history) ---- ## Version 2.0.12 ### Bug fixes * (Fixes [Issue 476](../../issues/476)) Editor/bugfix: print preview was not working * Completion widget/bugfix (editor/console): combo box was truncated by main window depending on its size * widgets.sourcecode.base.TextEditBaseWidget/bugfix: parenting to None was not working * Console/Text wrap mode: character wrapping was not implemented since we switched from QTextEdit to QPlainTextEdit * (Fixes [Issue 649](../../issues/649)) Patch submitted by [DavidAnthonyPowell](http://code.google.com/u/DavidAnthonyPowell/) - Syntax highlighter does not recognise imaginary, binary or octal numbers * Spyder's layout: fixed window position/size issues when maximized/fullscreen mode was active * Object inspector: fixed minor bug (simple traceback in the internal console) when handling a sphinx error * (Fixes [Issue 667](../../issues/667)) Editor/bugfix: Shift+Enter inserted lines that did not get line numbers * (Fixes [Issue 672](../../issues/672)) Editor: TODO/FIXME were not detected if not followed by ':' (HINT/TIP were properly detected) ### Enhancements * (Fixes [Issue 655](../../issues/655)) Editor/pyflakes-powered code analysis: warnings are now ignored for lines containing "pyflakes:ignore" ### Other changes * Internal console (Spyder debugging only): turned off the multithreaded mode ---- ## Version 2.0.11 ### Bug fixes (since v2.0.9) * (Fixes [Issue 616](../../issues/616)) Pylint plugin: tree widget header text was not updated when analyizing a new script (the last analyzed script name was still shown) * Editor/completion widget/bugfix: pressing shift was hiding the completion combo box * (Fixes [Issue 630](../../issues/630)) Added missing default settings for "Spyder light" (only necessary when installing from scratch and without any remaining .spyder.ini file) * Editor/Console-bugfix: info tooltips (calltips) were hidden right after being shown (i.e. when typing any character after the left parenthesis) * (Fixes [Issue 631](../../issues/631)) Drag and drop of files into editor on Linux was pasting path instead of opening the file * (Fixes [Issue 640](../../issues/640)) Editor: block comment was not working correctly at end of file * Code completion widget (Editor/Console) - bugfix: parenting to the ancestor widget was necessary on Linux * (Fixes [Issue 546](../../issues/546)) (Contributor: [Alex Fargus](http://code.google.com/u/alex.fargus/)) C/Cpp syntax highlighting bugfix * (Fixes [Issue 646](../../issues/646)) IPython integration: fixed pyreadline monkey-patch for pyreadline v1.7 ### Enhancements (since v2.0.9) * File explorer widget/plugin: improved performances (widget is now populated in a separate thread) * Spyder crash dialog: warning the user about the '--reset' option (this will remove all configuration files) ---- ## Version 2.0.9 ### Bug fixes * Console: added option to ignore PyQt/sip errors when trying to set sip API (fixed Enthought Tool Suite 3.6.0 compatibility issue) * utils.dochelpers.getargtxt/bugfix: retrieving builtin function arguments was no longer working * (Fixes [Issue 499](../../issues/499)) Editor-related keyboard shortcuts were not applied after opening files * (Fixes [Issue 575](../../issues/575)) Tab scroll buttons were not shown on OS X resulting in clamped/changing window sizes * (Fixes [Issue 574](../../issues/574)) Debugging: Spyder only synced at debugger breakpoints * (Fixes [Issue 576](../../issues/576)) "Source / Remove trailing spaces" was removing newline at the end of file (+ added support for "undo") * (Fixes [Issue 582](../../issues/582)) Console: changing font preferences was requiring a restart to be fully taken into account * (Fixes [Issue 562](../../issues/562)) Spyder was unable to restore editor's outline explorer tree when mixed ' and " characters were found in tree entries * (Fixes [Issue 590](../../issues/590)) Shell/"Clear line" shortcut was not correct: this is actually "Shift+Escape" (not "Escape") * (Fixes [Issue 591](../../issues/591)) History log was systematically erased when updating Spyder version * Outline explorer/bugfix: when opening file, the 'show/hide all files' option was not applied (this was then applied when switching from a file to another) * (Fixes [Issue 602](../../issues/602)) Backported from v2.1 a couple of bugfixes related to Editor and multiple panels * Object inspector: when raised automatically above other dockwidgets, plugin refresh was unnecessarily triggered * Editor/code completion-bugfix: some key events (e.g. Ctrl+V) were lost during code completion-related hang-up * (Fixes [Issue 599](../../issues/599)) Multiline text pasting was not working in a newly opened console (i.e. first prompt) ### Enhancements * Major change/Translations: moved from 'QtLinguist' to 'gettext' (localizing Spyder should now be easier) * Console: increased default maximum line count (buffer depth) up to 10,000 lines (instead of only 300 lines) * Editor's rope-based introspection features (code completion, calltips, go to definition): new rope monkey-patch providing major performance improvements * File explorer/Project explorer - opening file with associated application: now supported on all platforms * Added action "Reset window layout" in "View" menu to reset main window layout to default * Documentation: added page on debugging * Editor: added syntax highlighters for diff/patch files (.diff, .patch, .rej) and gettext files (.po, .pot) * (Fixes [Issue 537](../../issues/537)) Global working directory toolbar: removed label considering the fact that the toolbar widgets are quite explicit on its role (and the combo box tooltip is explaining it in detail) * (Fixes [Issue 598](../../issues/598)) Added a .desktop file in source package * (Fixes [Issue 87](../../issues/87)) Editor plugin's title now show the current script filename ---- ## Version 2.0.8 ### Bug fixes (since v2.0.6) * Consoles/bugfix: saving history log (see context menu) was not working following a recent code cleaning/refactoring * On non-Windows platforms, the file selection dialog "All files (*.*)" filter was not matching files without extension * dochelpers.isdefined/bugfix: ignoring syntax errors while evaluating object * Preferences Dialog (dialog box + keyboard shortcut page): improved size/resize behavior * Editor: when cursor was on the very last line, Duplicate/Delete line features were getting stuck in an infinite loop * Editor/duplicate line feature - fixed unexpected behavior: when duplicating selected text, text selection was extended to duplicated part * Editor/bugfix with multiple editor windows: when opening file on one editor window, the top-left corner menu (file list) was not updated correctly in other editor windows * Editor/fixed unexpected behavior: when clicking on the main window's outline explorer while a separate editor window had focus, the latter was used to show the associated line of code * Project explorer: added new debugging options (profiling 'rope' calls) * Console/Advanced settings/UMD module list: removing all entries (empty module list) was not working * Editor/File list management dialog (Ctrl+E): double clicking/pressing Return on a listwidget item will switch to the associated file * Editor/Tab bar: fixed missing tooltips issue (and missing file switch menu entries) * Code completion/bugfix: list widget was not hiding as expected when pressing ':' * Editor/fixed unexpected behavior: when some text was selected, "Ctrl+Left mouse click" was trying to "go to definition" instead of doing the standard drag n'drop feature * Editor/bugfix: disabling code completion/calltips for non-Python source code (was not working -as expected- but was taking time to simply not work...) * Editor/go to line: fixed unicode error * Code editor/bugfix: cursor position was not restored when undoing an indent operation with "tab always indent" feature turned on *and* the cursor at the end of the line * Tab behavior when "tab always indents" is turned off: inserting 4-(len(leading_text) % 4) spaces (instead of 4) * Object inspector/bugfix: ignoring unknown objects when called automatically from editor/console, i.e. do not log, do not show 'no doc available' ### Other changes (since v2.0.6) * Code editor syntax highlighting: added more keywords to Cython syntax highlighter (cpdef, inline, cimport and DEF) * Added example of application using the Spyder's internal shell as a debugging console (demonstrates also the py2exe deployment procedure) * Object inspector: added "Source" combo box (Console/Editor) -> object inspected from editor are now analyzed only with rope (if available) and then shown in object inspector * Added keyboard shortcut to open Preferences Dialog (default: Ctrl+Alt+Shift+P) * Editor: added "Copy line" feature (Ctrl+Alt+Down), similar to "Duplicate line" (Ctrl+Alt+Up) but paste text before the current line/selected text (instead of after) * Array editor: added option to set row/col labels (resp. ylabels and xlabels) * Editor/rope: improved performance for calltips/doc feature ---- ## Version 2.0.6 ### Bug fixes * Console: menu entries "Environment variables", "Current working directory" and "Show sys.path" were not disabled when the Monitor was turned off * Preferences dialog box/Keyboard shortcuts: * conflicts are now ignored if shortcuts have different contexts *except* if one of this context is '`_`' (i.e. global context) * conflict warnings are now also shown when showing the preferences dialog box (not only when modifying shortcuts and applying changes) * Drag/drop Python script to console: fixed TypeError (TypeError: start() got an unexpected keyword argument 'ask_for_arguments') * Console base widget: added support for FF (Form Feed) ANSI sequence - Fixes bug in IPython console: 'cls' and 'clear' magic commands were inactive in IPython consoles * Editor: code completion was sometimes very slow when editing files within a Spyder project * Code editor: fixed "Delete line" feature (Ctrl+D) / was not working with multiline selection ### Other changes * Editor/80-column vertical edge line: added options to show/hide this line and change the column number * Editor: added "Comment"/"Uncomment" actions to context menu * Source code and shell editor widgets: code refactoring/cleaning (this should help people using these widgets outside Spyder) spyder-3.2.6/spyder/0000775000175000017500000000000013225025007015124 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/locale/0000775000175000017500000000000013225025007016363 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/locale/ru/0000775000175000017500000000000013225025006017010 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/locale/ru/LC_MESSAGES/0000775000175000017500000000000013225025007020576 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/locale/ru/LC_MESSAGES/spyder.mo0000664000175000017500000040507613224121062022452 0ustar carloscarlos000000000000007!CZY Zwc[\ \ ] ]#]>]G]N]R] q] {]]]]]]] ]] ]] ] ]^ ^^!^)^.^6^<^D^K^Q^Z^c^l^u^~^^W^b^<K_"_x_4$`Y`xaFbDVc9cAcBdDZdQd1d6#e;Ze7eceB2f7ufCf;f8-gtfg!ggh&j!j;jljr'Ɓ+aQQ߂"1)T(~'σ  + D N\ z3„ ҄ ׅ  ,:ZWȆ %DZ_*7@^} &̈ !,=L \}ى> 8 FT erz   .ˊ  < I S^eMkm'?F_!x Ō -> W e&q*ލ .@HMU= ( 6@Wn  ʐ א #&9` r}{Jƒ  ̔{ڔV ]~ ǖ ֖ %C0Y ї *<KP=&ژ1`3I9ޙd<} ؚ͚ *.3FOXk!4 <HY_f Ɯߜ &=Y;u ʝ ם>#*8cr w Ӟ!T7=u   ɠѠ ٠  4 = H S ] iw ǡgڡB"]  &  0B IUY ,/8h mz:ߤ & 0> O\ oB|ǥϥ ޥ "+JP$e&P+w  çΧMާ,2B%uRC237 k x+"ë!ʬ * ;H \i}խ  !.AP_n}  Үޮ116LUg{%ʯ+$94>s %ɰ5 %1D[ b mw *±   #D\n ²βֲ 5!Rt 'ճ# 7BV_t}75) 2 >L jw ,Dĵ  $$3 XcsE  1 ;HYm- ƷηԷ" E!Rg1ظ  $2P_ hs ù5ҹ'0NUl#º=|WԻ>42^gƼۼ6 ?M_8o½ ׽ \9xƾ"ؾLHdvDֿ =Og  4 O[`e lw} !%#7 M[4<N8M=_89&9N`ptSH P] ep u ,  !=Mbs+ C:#^ o{  =:.i  .fD1Nl(ChF+Lx;':c *iTl-Y[  Wp]n&>{P#/7Mg   &0LRW[X& &"[29 !%3Yq}7= DRds<G\*d#  }ap ns$;1ImxA   .>E`fk s~ )  # ,9B Y3g55 EQCW( ">Uez   - AMem~W :dlYSJ[XpvJsR5exg|m5t2v>(D >" -a  $JahR+3n*3' )/Eu ":RZ'> [*T@M6!-YOM::11l)^Q'fyqIR$  ,  7 E L ^ f  w   4 ' ! "! -! ;!I! _!l!!!l!m"}"!" "["##F2# y#M#0#i$=$k$3-%;a%*%0%%G&]&}&-&;&!'M''&u'.'')'1("C(&f(*(,("()')?)W).^))>)_)B*%Z*,**(**+*)+KF++++#+,,/,K,-;%-%a-!-----#.(.9.]N.).A.-/F/8[///6/O/YK0050&0$161O11l1K1,1Q2i21222 2 223'03X3g4XR5;556W6Ys66677+7:7V7h777V77>84U8688X99s:N;L];C;f;BU<%<<<<<?=BZ=)=-=H=>>X>ti>(>?!?@G@A/A&CAjAKAAB"B B8BaC@xC2CCRDmDlEIE;F9OF!F7FLF30G'dGG)G%GG<H2UH H2HAH'IFI`OI!I!I-I"J  S/V ځ %=RS4Յ gyt#9JXJ/#28>k(2Ӌ !#!E!g!I׌1!5S6ލ6"3Vvю  0Q eq#dڏ ?1J'|6:ې68MNCՑYs+WΒ'&7N*Fޓj%CŔ )$NHl%͕EW&n4ʖ@A$Af;C(3Fz#$ɘ4AQQL)2)\8" K>;"z,&ʛ9 G8d+7yb.' C%dJ!՞+#V?5H$fU C"4f6%\)|9..+1Z6cã' D Q!\V~ դ}z:MSѦ<& @L9d,ا|#g9ABP/CCĪbk[]vA;dZ-)7<!t&2:w+57ٰ!&38Z"sI-#Rpb?ӳ20FwQ/T'$.ѵ,I-Kw>ö4.71f0(ɷ:?-GmA &"5 Xcu@.J$*oF2,(ż~%C \&Z1*;Xv5  #<HW!2  ?M.l':)BG m'7d_". Ef!y #rl#!%+QQTT,2"U;"\TRG?/iHY~7!8Y5?= GfW)yb8yP ! #-%Qw: <987;"Wz^KP!m|, 9T3/1GByL5 :?6zF%7%Sy,JE,ry{yR C *N<yj!!C ] k-u4!'7MA' @M^e | 8 > JWl @  < V e  t " $  #   " E^Y Ti2f\!s"iL?'j&9CmH9S >1ln ;2+@r>g|XO'b}8T6l1qB <$Ed`FCge:#>or5 jkx"avEU{h 3oog a,aMMdX] $B[n-I[I!3-y`m5Oh \H'$~0x^D JR;y6Uf[t#P.jR0./ ~DcW4Q(Pp  -=7*H6G|9G%e!\{a ;2!z/ .b5P"17q<)w,D*J)4}4."+MnZw\_AG$F|%vR<&14Txs>'J(F Y)!SY#ww h0u3m}_S#&i I 0t-C4DVfyA3mN, QN6c[@(9Nt:qu=p(]LZ2`-,%u+l$3/V eQV+=xfpL7 5nKpIT1lbvRU*rz:*&Z0hugCrEvA8BO+jSe%{b|)^kM*"7?  z Adt%/^oB5K(Q~W']=cUJkW c&K?GK O]`kizVy?Z NPs6<:X@.Y~7,sX#}{ 28FW/;qH d8@L__) Numpy Array/Matrix Helper
Enter an array in the table.
Use Tab to move between cells.

Hit 'Enter' for array or 'Ctrl+Enter' for matrix.

Hint:
Use two tabs at the end of a row to move to the next row. Numpy Array/Matrix Helper
Type an array in Matlab : [1 2;3 4]
or Spyder simplified syntax : 1 2;3 4

Hit 'Enter' for array or 'Ctrl+Enter' for matrix.

Hint:
Use two spaces or two tabs to generate a ';'. Searching for files... Installed Required Scanning: {0} Searching for files in folder: {0} entries lines ms%s are currently not supported%s arrays%s editor&Close&Configuration per file...&Debug&Edit&File&Find in files&Find text&Help&New file...&Open...&Print...&Projects&Quit&Replace text&Restart&Revert&Run&Run...&Save&Search&Tools&View2 spaces3 spaces4 spaces5 spaces6 spaces7 spaces8 spaces%s contains mixed end-of-line characters.
Spyder will fix this automatically.%s has been modified outside Spyder.
Do you want to reload it and lose all your changes?%s has been modified.
Do you want to save changes?%s is not a Spyder project!%s is unavailable (this file may have been removed, moved or renamed outside Spyder).
Do you want to close it?-u is added to the other options you set hereSpyder %s is available!

Please use your package manager to update Spyder or go to our
Releases page to download this new version.

If you are not sure how to proceed to update Spyder please refer to our Installation instructions.Spyder has encountered a problem.
Sorry for the inconvenience.

You can automatically submit this error to our Github issues tracker.

Note: You need a Github account for that.Spyder is a powerful Interactive Development Environment (or IDE) for the Python programming language.

Here we are going to guide you through its most important features.

Please use the arrow keys or click on the buttons below to move along the tour.Spyder is an interactive development environment based on blaUnable to %s %s

Error message:
%sUnable to assign data to item.

Error message:
%sUnable to create file %s

Error message:
%sUnable to create folder %s

Error message:
%sUnable to delete {varpath}

The error message was:
{error}Unable to find external program.

%sUnable to load '%s'

Error message:
%sUnable to move %s

Error message:
%sUnable to plot data.

Error message:
%sUnable to proceed to next step

Please check your entries.

Error message:
%sUnable to rename file %s

Error message:
%sUnable to save array

Error message:
%sUnable to save current workspace

Error message:
%sUnable to save file '%s'

Error message:
%sUnable to show image.

Error message:
%sUnsupported file extension '%s'

Would you like to import it anyway (by selecting a known file format)?Unsupported file type '%s'Warning:
The Python module rope is not installed on this computer: calltips, code completion and go-to-definition features won't be available.You have missing dependencies!

%s

Please install them to avoid this message.

Note: Spyder could work without some of these dependencies, however to have a smooth experience when using Spyder we strongly recommend you to install all the listed missing dependencies.

Failing to install these dependencies might result in bugs. Please be sure that any found bugs are not the direct result of missing dependencies, prior to reporting a new issue.

Removing all variables...

Restarting kernel...


IMPORTANT NOTE: It seems that you are using Spyder with Anaconda/Miniconda. Please don't use pip to update it as that will probably break your installation.

Instead, please wait until new conda packages are available and use conda to perform the update.
(Refer to the {} page)

If enabled, Python source code will be analyzed using pycodestyle, lines that are not following PEP8 style guide will be highlighted.

Note: add analysis:ignore in a comment to ignore style analysis warnings.

If enabled, Python source code will be analyzed using pyflakes, lines containing errors or warnings will be highlighted.

Note: add analysis:ignore in a comment to ignore code analysis warnings.

Warning: changes are applied separatelyA compound sequence can have {break} a maximum of 4 subsequences.{break}About %sAbout %s...Activate supportAdd &block commentAdd block comment around current line or selectionAdd pathAdditional featuresAdditional optionsAddress:Advanced SettingsAdvanced settingsAll changes to %s will be lost.
Do you want to revert file from disk?All filesAll files (*)All files (*.*)All user-defined variables will be removed. Are you sure you want to proceed?Always show %s on a first file runAn error occurred while creating a socket needed by Spyder. Please, try to run as an Administrator from cmd.exe the following command and then restart your computer:

netsh winsock reset
An error ocurred while starting the kernelAnalysisAnimated toolbars and panesAppearanceAre you sure you want to delete this scheme?Are you sure you want to restart the kernel?ArgumentsArray dimensions not validArray editorArrays with more than 3 dimensions are not supportedAsk for confirmation before closingAsk for confirmation before removing all user-defined variablesAttached console window (debugging)AttributeAutocallAutocall makes IPython automatically call any callable object even if you didn't type explicit parentheses.
For example, if you type str 43 it becomes str(43) automatically.Autocall: AutomaticAutomatic code completionAutomatic connectionsAutomatic importAutomatic indentation after 'else', 'elif', etc.Automatic insertion of closing quotesAutomatic insertion of colons after 'for', 'if', 'def', etcAutomatic insertion of parentheses, braces and bracketsAutomatically load Pylab and NumPy modulesAutomatically remove trailing spaces when saving filesAxis:BackBackend:BackgroundBackground colorBackground:Batch filesBoldBreakpointBrowseBrowse a working directoryBrowse repositoryBrowse tabsBufferBuffer...Buffer: Builtin:C filesC&lose allC&onsolesC++ filesCPU and memory usage info in the status barCPU usage status: requires the `psutil` (>=v0.3) libraryCPU:CSV text filesCancelCannot restart a kernel not started by Spyder Carriage return (Mac)Carriage return and line feed (Windows)Case SensitiveCase sensitive code completionCell starts at line %sChange to lowercase current line or selectionChange to parent directoryChange to uppercase current line or selectionChanging backend to Qt for MayaviCheck for updates on startupCheck for updates...Class defined at line %sClear all ouputClear breakpoints in all filesClear consoleClear lineClear line or blockClear recent files listClear shellClear shell contents ('cls' command)Clear this listClipboard contentsClose ProjectClose all but thisClose all opened filesClose all to the rightClose current fileClose current paneClose current tabClose this panelClose this windowClose windowClosing SpyderCodeCode Introspection/AnalysisCode analysisCode analysis requires pyflakes %s+Code annotations (TODO, FIXME, XXX, HINT, TIP, @todo, HACK, BUG, OPTIMIZE, !!!, ???)Collapse allCollapse selectionColor scheme editorColumn min/maxColumn separator:Column:Command line options:CommentComment current line or selectionComment:Comments:CommitCompletion TypeCompletion:Condition:Configuration filesConfiguration for high DPI screens

Please see {0}<> for more information about these options (in English).ConflictsConnect to an existing kernelConnecting to kernel...Connection errorConnection info:ConsoleConsole directoryConsole helpContextContinueContinue execution until next breakpointConversion errorConvert end-of-line charactersConvert to Python scriptCopyCopy path to clipboardCopy to clipboardCopy without promptsCould not connect to remote hostCould not open ssh tunnel. The error was: CreateCreate a new editor windowCreate new projectCreate new schemeCurrent cell:Current line:Current shortcut:Current user environment variables...Current working directoryCurrently used to delete lines on editorCursor blinking:Custom margin for panes:CutCython/Pyrex filesDataDataFrameDebug fileDebug toolbarDebug with winpdbDecide how graphics are going to be displayed in the console. If unsure, please select %s to put graphics inside the console or %s to interact with them (through zooming and panning) in a separate window.Decide how to render the figures created by this backendDecide what type of completion to useDefault (i.e. the same as Spyder's)Default is 4Default is 6Default is
In [<span class="in-prompt-number">%i</span>]:Default is
Out[<span class="out-prompt-number">%i</span>]:Default working directory is:Definition:DeleteDelete LayoutDelete ProjectDelete...DependenciesDependencies...DictionaryDirectly enter debugging when errors appearDisplayDisplay balloon tipsDisplay initial bannerDo you really want to delete %s?Do you really want to delete {filename}?

Note: This action will only delete the project. Its files are going to be preserved on disk.Do you really want to remove selected path?Do you really want to rename %s and overwrite the existing file %s?Do you want to close all other consoles connected to the same kernel as this one?Do you want to close this console?Do you want to remove all selected items?Do you want to remove the selected item?Do you want to reset to default values?Do you wish to restart now?Don't show again.DoneDuplicateEOLEditEdit filename filtersEdit filename filters...Edit itemEdit selectedEdit template for new modulesEdit toolbarEditorEditor's code completion, go-to-definition and helpEmpty clipboardEmpty projectEnable Tab completion on elements of lists, results of function calls, etc, without assigning them to a variable.
For example, you can get completions on things like li[0].<Tab> or ins.meth().<Tab>Enable UMREnable auto high DPI scalingEnaml filesEncoding:End-of-line charactersEnd-of-lines:Enter key selects completionEnter values for different screens separated by semicolons ';', float values are supportedEnvironment variablesEnvironment variables...ErrorError restarting kernel: %s Exclude all-uppercase referencesExclude capitalized referencesExclude private referencesExclude references to unsupported data types (i.e. which won't be handled/saved correctly)Exclude references which name is uppercaseExclude references which name starts with an underscoreExclude references which name starts with an uppercase characterExclude unsupported data typesExclude:Excluded filenames patternExecutablesExecute in a dedicated consoleExecute in an external system terminalExecute in current consoleExisting directoryExpand allExpand selectionExternal ToolsExternal editorExternal editor executable path:External editor path...External editor:External system terminalFast switch between filesFast symbol search in fileFileFile %s already exists.
Do you want to overwrite it?File ExplorerFile explorerFile switcher...File toolbarFile...FilterFind &nextFind &previousFind in filesFind symbols in file...Find textFix automatically and show warning message boxFix indentationFloat formattingFolder %s already exists.Folder name:Folder...Font styleFont: FontsFor %s support, please install one of the
following tools:

%sFor performance reasons, changes applied to masked array won't be reflected in array's data (and vice-versa).Forbidden key sequence!FormatFormat (%s) is incorrectFormat ({}) is incorrectFormat ({}) should start with '%'Format:Fortran filesFullFullscreen modeFunction defined at line %sGIF imagesGUI-based editor:GeneralGeneral settingsGo to cursor positionGo to definitionGo to last edit locationGo to line...Go to line:Go to next code analysis warning/errorGo to next cursor positionGo to previous code analysis warning/errorGo to previous cursor positionGo to step: GraphicalGraphicsGraphics backendGreedy completionHeight:HelpHelp...Here you can get help of any object by pressing %s in front of it, either on the Editor or the Console.%sHelp can also be shown automatically after writing a left parenthesis next to an object. You can activate this behavior in %s.Here you can select the color scheme used in the Editor and all other Spyder plugins.

You can also edit the color schemes provided by Spyder or create your own ones by using the options provided below.
Hide advanced optionsHide toolbarsHighlightHighlight current cellHighlight current lineHighlight matchesHighlight occurrences afterHistogramHistoryHistory depth: History logHistory logsHistory...HomeHost nameIDL filesIPythonIPython ConsoleIPython consoleIPython documentationIPython interactive python environmentIPython notebooksIcon themeIf enabled, pressing Tab will always indent, even when the cursor is not at the beginning of a line (when this option is enabled, code completion may be triggered using the alternate shortcut: Ctrl+Space)If this option is enabled, clicking on an object name (left-click + Ctrl key) will go this object definition (if resolved).If you accept changes, this will modify the current user environment variables directly in Windows registry. Use it with precautions, at your own risks.

Note that for changes to take effect, you will need to restart the parent process of this application (simply restart Spyder if you have executed it from a Windows shortcut, otherwise restart any application from which you may have executed it, like Python(x,y) Home for example)ImportImport asImport dataImport errorImport from clipboardImport wizardIn this pane you can view and edit the variables generated during the execution of a program, or those entered directly in one of Spyder consoles.

As you can see, the Variable Explorer is showing the variables generated during the last step of this tour. By doing a double-click on any of them, a new window will be opened, where you can inspect and modify their contents.IndentIndent current line or selectionIndentation characters: IndexIndex:InformationInitializing...InlineInline backendInput prompt:InsertInspect current objectInstalled Python modulesInstance:Integrate the IPython consoleIntelligent backspaceInteract with the Python console after executionInteractive toursInterfaceInternal consoleInternal console settingsInternal editor:Intro to IPythonIntroduction tourIntrospectionInvalid directory pathInvalid file pathInvalid key enteredIt was not possible to close the previous Spyder instance. Restart aborted.It was not possible to convert this notebook. The error is: It was not possible to copy this arrayIt was not possible to copy values for this arrayIt was not possible to generate rich text help for this object.
Please see it in plain text.It was not possible to remove outputs from this notebook. The error is: It was not possible to restart Spyder. Operation aborted.It was not possible to restart the IPython console when switching to this project. The error was {0}It was not possible to run this file in an external terminalItalicJPEG imagesJSON filesJavascript filesJson filesJulia filesKernel died, restartingKernel restartingKeyKey:Keyboard shortcutsKeyword:LanguageLast edit locationLayout %s will be overwritten. Do you want to continue?Layout Display and OrderLayout preferencesLine %sLine count:Line feed (UNIX)Line:Lines:Link to object definitionLink:ListLoading %s...Loading IPython console...Loading editor...Loading file explorer...Loading help...Loading history plugin...Loading namespace browser...Loading online help...Loading outline explorer...Loading project explorer...Loading this kind of data while debugging is not supported.LocationLockLock panesMATLAB filesMain toolbarMaintain focus in the Editor after running cells or selectionsManage color schemesManipulate Jupyter notebooks on the EditorMarkdown filesMaskMasked dataMatched
parens:Matlab filesMatplotlib documentationMaximize current paneMaximum entriesMaximum line countMaximum number of recent filesMaximum number of recent files...Memory usage status: requires the `psutil` (>=v0.3) library on non-Windows platformsMemory:Method defined at line %sModify how Input and Output prompts are shown in the console.ModuleModule pywin32 was not found.
Please restart this Windows session (not the computer) for changes to take effect.Module or package:Module...Move DownMove UpMove downMove to bottomMove to topMove upMove...NSIS filesNameName filters:NewNew Project...New directoryNew features in version 3.0New fileNew folderNew moduleNew name:New packageNew shortcut:New to Spyder? Read ourNew variable name:New windowNextNext cursor positionNext warning/errorNo IPython console is currently available to run %s.

Please open a new one and try again.No documentation availableNo further documentation availableNo matchesNo source code available.NormalNormal text:Nothing to be imported from clipboard.NumPy arrayNumPy arraysNumPy zip arraysNumber:Numpy and Scipy documentationO&pen last closedObjectOccurrence:OffOn %s mode, Autocall is not applied if there are no arguments after the callable. On %s mode, all callable objects are automatically called (even if no arguments are present).Online documentationOnline helpOnly used when the format is PNG. Default is 72OpenOpen &recentOpen IPython console hereOpen Project...Open a new IPython console connected to an existing kernelOpen an &IPython consoleOpen command prompt hereOpen connection fileOpen fileOpen file as:Open last closedOpen projectOpen terminal hereOpenCL filesOpening this variable can be slow Do you want to continue anyway?OptionsOutlineOutput prompt:PNG imagesPYTHONPATH managerPackage name:Package...PanesParentPasswordPassword or ssh key passphrasePastePatch and diff filesPath to connection file or kernel idPath to ssh key filePerfom symbolic operations in the console (e.g. integrals, derivatives, vector calculus, etc) and get the outputs in a beautifully printed style (it requires the Sympy module).Perform analysis only when saving filePerform analysis when saving file and everyPermissions:Pickle filesPlainPlain TextPlain text fontPlease consider installing Sphinx to get documentation rendered in rich text.Please enter the connection info of the kernel you want to connect to. For that you can either select its JSON connection file using the Browse button, or write directly its id, in case it's a local kernel (for example kernel-3764.json or just 3764).Please install matplotlib or guiqwt.Please introduce a different shortcutPlease note that these changes will be applied only to new Python/IPython consolesPlease note that these changes will be applied only to new consolesPlotPop up internal console when internal errors appearPre&ferencesPreferencesPreferences > HelpPress Enter to switch files or Esc to cancel.

Type to filter filenames.

Use :number to go to a line, e.g. main:42
Use @symbol_text to go to a symbol, e.g. @init

Press Ctrl+W to close current tab.
Press enter to validate this entryPress enter to validate this pathPress the new shortcut and select 'Ok': (Press 'Tab' once to switch focus between the shortcut entry and the buttons below it)PreviewPreviousPrevious cursor positionPrevious warning/errorPrint current file...Print preview...Printing...ProjectProject ExplorerProject PreferencesProject explorerProject nameProject preferencesProject typePrompt when exitingPromptsProvided featuresPyQt4 API ReferencePyQt4 Reference GuidePyQt5 API ReferencePyQt5 Reference GuidePython Path ManagerPython documentationPython filesPython help:Python interpreterPython packagePython projectPython scriptsPython versionPython2 documentationPython3 documentationQt DesignerQt LinguistQt documentationQt examplesQt windows styleQuick referenceQuick switch layout #%s has not yet been defined.QuitR&emove block commentRaw textRe run last cell Re-run &last scriptRe-run last cellReal-time code analysisReal-time code analysis on the EditorReal-time code style analysisReal-time code style analysis on the EditorRecent ProjectsRecord array fields:RedoRefresh list of module names available in PYTHONPATHRegular expressionRegular expression errorRemoval errorRemoveRemove all variablesRemove all variables before executionRemove comment block around current line or selectionRemove pathRemove references:Remove trailing spacesRenameRename tabRename...Render mathematical equationsReplace allReplace selectionReplace stringReplace tab characters by space charactersReplace with:Replace/find nextReport issue...ResetReset Spyder to factory defaultsReset to default valuesReset to defaultsReset to spyder defaultResetting Spyder to defaultsResizeResize rows to contentsResolution:RestartRestart kernelRestart kernel?RestartingRestoreRestore current paneRestore data on startupRestore original tree layoutRestore pane to its original sizeRevert file from diskRich TextRich text fontRow separator:RunRun &selection or current lineRun Cython files in the IPython ConsoleRun Python scriptRun Settings dialogRun a Python scriptRun a fileRun again last fileRun cellRun cell and advanceRun codeRun configurationRun configuration per fileRun current cell (Ctrl+Enter) [Use #%% to create cells]Run current cell and go to the next one (Shift+Enter)Run current lineRun fileRun script:Run selectionRun selection or current lineRun settingsRun settings for %sRun toolbarRun until current function or method returnsRunning an external system terminal is not supported on platform %s.Sav&e allSaveSave &as...Save all filesSave all files before running scriptSave arraySave copy as...Save copy of current file as...Save current file as...Save current history log (i.e. all inputs and outputs) in a text fileSave current layoutSave dataSave data as...Save data on exitSave fileSave historySave history logSave history log...Save non project files openedSaving data while debugging is not supported.Scheme name:Scheme:ScoreScreen resolutionScroll automatically to last entrySearchSearch directorySearch in all files and directories present on thecurrent Spyder pathSearch in all files and directories present on thecurrent project path (If opened)Search in current opened fileSearch in other folder present on the file systemSearch in:Search patternSearch stringSearch text in multiple filesSearch toolbarSearch: Select AllSelect a run configuration:Select directorySelect fileSelect other directorySelect ssh keySelect the Python interpreter for all Spyder consolesSet UMR excluded (not reloaded) modulesSet a custom high DPI scalingSet console working directorySet current console (and file explorer) working directory to current script directorySet external editor executable pathSet history maximum entriesSet maximum line countSet the list of excluded modules as this: numpy, scipySet the maximum number of lines of text shown in the console before truncation. Specifying -1 disables it (not recommended!)Set this for high DPI displaysSet this for high DPI displays when auto scaling does not workSet this to detach any
menu from the main windowSet this to open external
Python files in an already running instance (Requires a restart)Set/Clear breakpointSet/Edit conditional breakpointSetting up main window...SettingsShell special commands:ShortcutShortcut: {0}Shortcuts SummaryShortcuts resetShortcuts that use Shift and another key are unsupportedShow (read-only) sys.pathShow CPU usage everyShow SourceShow absolute pathShow advanced optionsShow all filesShow and edit current user environment variables in Windows registry (i.e. for all sessions)Show and edit environment variables (for current session)Show arrays min/maxShow blank spacesShow code analysis warnings/errorsShow comments list (TODO/FIXME/XXX/HINT/TIP/@todo/HACK/BUG/OPTIMIZE/!!!/???)Show current directory onlyShow elapsed timeShow environment variablesShow help for objects in the Editor and Consoles in a dedicated paneShow horizontal scrollbarShow icons and textShow imageShow in FinderShow in external file explorerShow line numbersShow memory usage everyShow reloaded modules listShow special commentsShow status barShow sys.path contentsShow sys.path contents...Show tab barShow todo listShow toolbarsShow vertical line afterShow warning/error listShow/hide outline explorerSide areas:SiftSizeSize: Skip rows:SmartSour&ceSourceSource codeSource toolbarSphinx %s is currently installed.Split horizontallySplit horizontally this editor windowSplit verticallySplit vertically this editor windowSpyder Default LayoutSpyder EditorSpyder Internal Console This console is used to report application internal errors and to inspect Spyder internals with the following commands: spy.app, spy.window, dir(spy) Please don't use it to run your code Spyder Keyboard ShortCutsSpyder could not reset to factory defaults. Restart aborted.Spyder data filesSpyder depends on several Python modules to provide the right functionality for all its panes. The table below shows the required and installed versions (if any) of all of them.

Note: You can safely use Spyder without the following modules installed: %s and %s.

Please also note that new dependencies or changed ones will be correctly detected only after Spyder is restarted.Spyder documentationSpyder exit errorSpyder is an interactive development environment based on blaSpyder is up to date.Spyder needs to restart to change the following setting:Spyder needs to restart to change the following settings:Spyder reset errorSpyder restart errorSpyder support...Spyder tutorialSpyder updatesSpyder was unable to retrieve the value of this variable from the console.

The error mesage was:
%sSpyder will restart and reset to default settings:

Do you want to continue?Ssh keyStart searchStartupStatus barStepStep IntoStep ReturnStep into function or method of current lineStopStop debuggingStop searchStop the current commandString not foundString:Submit to GithubSupport for graphics (Matplotlib)Supported filesSupported text filesSymbol finder...Symbolic MathematicsSymbolic mathematics in the IPython ConsoleSynchronizeSynchronize Spyder's path list with PYTHONPATH environment variableSynchronize...Syntax coloringSyntax highlighting for Matlab, Julia and other file typesSystem commands:TIFF imagesTabTab always indentTab stop width:TabulationsTear off menusTemporary fileTerminalTextText editorText filesThe 'xlabels' argument length do no match array column numberThe 'ylabels' argument length do no match array row numberThe current working directory is the working directory for IPython consoles and the current directory for the File Explorer.The EditorThe File ExplorerThe History LogThe IPython consoleThe Variable ExplorerThe authenticity of host %s can't be established. Are you sure you want to continue connecting?The authenticity of the host can't be establishedThe current directory contains a project.

If you want to delete the project, please go to Projects » Delete ProjectThe current project directory or user home directory (if no project is active)The current working directoryThe directory of the file being executedThe directory when a new console is open will be the specified pathThe directory {} is not writable and it is required to create IPython consoles. Please make it writable.The following are the default options for running files.These options may be overriden using the Configuration per file entry of the Run menu.The following conflicts have been detected:The following directory:The following error occured when calling Sphinx %s.
Incompatible Sphinx version or doc string decoding failed.

Error message:
%sThe following modules are not installed on your machine: %sThe following working directory is not valid:
%sThe new shortcut conflicts with:The working directory for new consoles is:This directory is already included in Spyder path list.
Do you want to move it to the top of the list?This entry is incorrectThis error was most probably caused by installing Spyder in a directory with non-ascii characters (i.e. characters with tildes, apostrophes or non-latin symbols).

To fix it, please reinstall Spyder in a different location.This feature requires Sphinx 1.1 or superior.This feature requires the Rope or Jedi libraries. It seems you don't have either installed.This is a remote kernelThis is a temporary script file.This is one of panes where you can run or execute the code you wrote on the Editor. To do it you need to press the F5 key.

This console comes with several useful features that greatly improve your programming workflow (like syntax highlighting and inline plots). If you want to know more about them, please follow this link.

Please click on the button below to run some simple code in this console. This will be useful to show you other important features.This is the pane where you write Python code before evaluating it. You can get automatic suggestions and completions while writing, by pressing the Tab key next to a given text.

The Editor comes with a line number area (highlighted here in red), where Spyder shows warnings and syntax errors. They can help you to detect potential problems before running the code.

You can also set debug breakpoints in the line number area, by doing a double click next to a non-empty line.This is the working directory for newly opened consoles (Python/IPython consoles and terminals), for the file explorer, for the find in files plugin and for new files created in the editorThis lets you load graphics support without importing the commands to do plots. Useful to work with other plotting libraries different to Matplotlib or to develop GUIs with Spyder.This option lets you hide the message shown at the top of the console when it's opened.This option lets you hide the warning message shown when resetting the namespace from Spyder.This option loads the Sympy library to work with.
Please refer to its documentation to learn how to use it.This option will be applied the next time a console is opened.This option will enable the User Module Reloader (UMR) in Python/IPython consoles. UMR forces Python to reload deeply modules during import when running a Python script using the Spyder's builtin function runfile.

1. UMR may require to restart the console in which it will be called (otherwise only newly imported modules will be reloaded when executing files).

2. If errors occur when re-running a PyQt-based program, please check that the Qt objects are properly destroyed (e.g. you may have to use the attribute Qt.WA_DeleteOnClose on your main window, using the setAttribute method)This pane can automatically show an object's help information after a left parenthesis is written next to it. Below you can decide to which plugin you want to connect it to turn on this feature.This pane displays documentation of the functions, classes, methods or modules you are currently using in the Editor or the Consoles.

To use it, you need to press Ctrl+I in front of an object. If that object has some documentation associated with it, it will be displayed here.This pane lets you navigate through the directories and files present in your computer.

You can also open any of these files with its corresponding application, by doing a double click on it.

There is one exception to this rule: plain-text files will always be opened in the Spyder Editor.This pane records all commands introduced in the Python and IPython consoles.This will synchronize Spyder's path list with PYTHONPATH environment variable for current user, allowing you to run your Python modules outside Spyder without having to configure sys.path.
Do you want to clear contents of PYTHONPATH before adding Spyder's path list?To boolTo complexTo doTo floatTo intTo strToggle LowercaseToggle UppercaseToolbarsTransposeTunnel '%s' failed to startTupleTypeUMRUMR forces Python to reload modules which were imported when executing a file in a Python or IPython console with the runfile function.Unable to check for updates.Unable to connect to %sUnable to connect to the internet.

Make sure the connection is working properly.Unable to load pageUnable to retrieve information.UncommentUndoUnexpected error: see internal consoleUnindentUnindent current line or selectionUnlockUnmatched
parens:Update LANGUAGE_CODES (inside config/base.py) if a new translation has been added to SpyderUpdate module names listUsageUse a pager to display additional text inside the consoleUse a single instanceUse next layoutUse previous layoutUse symbolic mathUse the following Python interpreter:Use the following file:Use the greedy completerUse version controlUseful if you don't want to fill the console with long help or completion texts. Note: Use the Q key to get out of the pager.User Module Reloader (UMR)ValueValue:Variable NameVariable explorerVariable name:Version controlVersion control systemVertical tabs in panesVertical title bars in panesViTablesView and edit DataFrames and Series in the Variable ExplorerView and edit two and three dimensional arrays in the Variable ExplorerWarningWe cannot support this shortcut on WindowsWeb page filesWelcome to Spyder introduction tourWelcome to Spyder!Welcome to the Introduction tourWhen opening a text file containing mixed end-of-line characters (this may raise syntax errors in the consoles on Windows platforms), Spyder may fix the file automatically.WhitespaceWhole wordsWidth:WinPythonWinPython control panelWindow layout will be reset to default settings: this affects window position, size and dockwidgets. Do you want to continue?Window layoutsWorking Directory settingsWorkspaceWrap linesXML filesYaml filesYou are working with Python 2, this means that you can not import a module that contains non-ascii characters.You can also run a whole file at startup instead of just some lines (This is similar to have a PYTHONSTARTUP file).You can run several lines of code when a console is started. Please introduce each one separated by commas, for example:
import os, import sysYou don't have the right permissions to open this directoryYou selected a Python %d interpreter for the console but Spyder is running on Python %d!.

Although this is possible, we recommend you to install and run Spyder directly with your selected interpreter, to avoid seeing false warnings and errors due to the incompatible syntax between these two Python versions.You selected an invalid Python interpreter for the console so the previous interpreter will stay. Please make sure to select a valid one.Your Python environment or installation doesn't have the ipykernel and cloudpickle modules installed on it. Without these modules is not possible for Spyder to create a console for you.

You can install them by running in a system terminal:

pip install ipykernel cloudpickle

or

conda install ipykernel cloudpickleZoom inZoom outZoom resetarraycharacterscodecopydatadeletedpielementsfilegettext filesguidata examplesguiqwt examplesinchesinvalid regular expressionlineslistmatchesmatches inmovemsno matchesofotherpermission denied errors were encounteredpixelsreStructuredText filesread onlyspacestabletextthe following directory:this dialogtutorialunsaved fileuntitledusername@hostname:portvariable_nameProject-Id-Version: 3.0 Report-Msgid-Bugs-To: POT-Creation-Date: 2017-12-14 15:40+-05 PO-Revision-Date: 2017-12-16 15:10+0300 Last-Translator: Zgarbul Andrey Language-Team: русский Language: ru_RU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generated-By: pygettext.py 1.5 X-Generator: Poedit 1.8.7.1 Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2); X-Poedit-Basepath: ../../.. X-Poedit-SearchPath-0: . Помощник Массивов/Матриц Numpy
Введите массив в таблицу.
Используйте Tab для перемещения по ячейкам.

Нажмите 'Enter' для массива или 'Ctrl+Enter' для матрицы.

Трюк:
Две табуляции в конце строки перемещают на следующую строку. Помощник Массивов/Матриц Numpy
Введите массив в Matlab- : [1 2;3 4]
или Spyder-стиле : 1 2;3 4

Нажмите 'Enter' для массива или 'Ctrl+Enter' для матрицы.

Трюк:
Два пробели или две табуляции образуют ';'. Поиск файлов... установлен требуется Сканирование: {0} Поиск файлов в директории: {0} записей строк мс%s на данный момент не поддерживается%s массивы%s редактор&Закрыть&Настройки для файла...&Отладка&Правка&ФайлНайти в &файлах&Найти текстСпр&авка&Новый файл&Открыть&Печать&ПроектыВ&ыход&Заменить текстПе&резапускЗа&грузить заново&Запуск&Выполнить...&СохранитьП&оиск&Инструменты&Вид2 пробела3 пробела4 пробела5 пробелов6 пробелов7 пробелов8 пробелов%s содержит смешанные символы конца строки.
Spyder исправит это автоматически.%s был изменён вне Spyder.
Хотите перегрузить его и потерять все изменения?%s был изменён.
Хотите сохранить изменения?%s - не является проектом Spyder!%s недоступен (этот файл мог быть удален, перемещён или переименован вне Spyder).
Хотите его закрыть?-u добавлен к другим опциям, которые Вы здесь установилиДоступен Spyder %s!

Пожалйста, используйте свой пакетный менеджер или перейдите на нашу страницу Релизов для загрузки новой версии.

Если Вы не уверены, как произвести обновление Spyder, ознакомьтесь с нашими инструкциями по Установке.Spyder столкнулся с проблемой.
Извиняемся за неудобства.

Вы можете автоматически отправить сообщение об ошибке на Github.

Примечание:Вы должны иметь аккаунт на Github для этого.Spyder - мощная Интерактивная Среда Разработки (или IDE) для языка программирования Python.

Здесь мы ознакомим Вас с наиболее важными возможностями.

Пожалуйста, используйте клавиши со стрелками или кнопки внизу, чтобы двигаться вдоль тура.Spyder - интерактивная среда разработкиНевозможно %s %s

Сообщение об ошибке:
%sНевозможно назначить данные элементу.

Сообщение об ошибке:
%sНевозможно создать файл %s

Сообщение об ошибке:
%sНевозможно создать каталог %s

Сообщение об ошибке:
%sНевозможно удалить {varpath}

Сообщение об ошибке:
{error}Не удалось найти внешнюю программу.

%sНе удалось загрузить '%s'

Сообщение об ошибке:
%sНевозможно переместить файл %s

Сообщение об ошибке:
%sНе удалось построить график по данным.

Сообщение об ошибке:
%sНевозможно перейти к следующему шагу

Пожалуйста, проверьте введенные данные.

Сообщение об ошибке:
%sНевозможно переименовать файл %s

Сообщение об ошибке:
%sНе удалось сохранить массив

Сообщение об ошибке:
%sНевозможно сохранить текущую рабочую область

Сообщение об ошибке:
%sНевозможно сохранить файл %s

Сообщение об ошибке:
%sНе удалось показать изображение.

Сообщение об ошибке:
%sНеподдерживаемое расширение файла '%s'

Хотите его импортировать (выбрав известный формат файла)?Неподдерживаемый тип файла '%s'Предупреждение:
Модуль Python rope не установлен на этом компьютере: подсказки вызова функций, автодополнение кода и переход к определению будут недоступны.У Вас есть недостающие зависимости!

%s

Пожалуйста, установите их, чтобы это сообщение исчезло.

Примечание: Возможно, Spyder сможет работать без некоторых из них, однако для беспроблемного использования Spyder мы настоятельно рекомендуем установить все приведённые недостающие зависимости.

Неудачная установка этих зависимостей могла привести к ошибкам. Пожалуйста, прежде чем сообщать о новой проблеме, убедитесь, что любые найденные ошибки не являются прямым результатот отсутствия некоторых зависимостей.

Удаление всех переменных...

Перезапуск ядра...


ОЧЕНЬ ВАЖНО: Похоже, что вы используете Spyder вместе с Anaconda/Miniconda. Пожалуйста, не используйте pip для обновления, т.к. это может сломать вашу сборку.

Вместо этого, пожалуйста, дождитесь выхода новых пакетов и используйте conda для установки обновлений.
(смотреть стр. {})

Если активно, код Python будет проверяться с помощью pycodestyle, строки не соответсвующие стилю PEP8, будут подсвечены.

Примечание: добавьте analysis:ignore в комментарий, чтобы игнорировать предупреждения анализатора стиля.

Если активно, код Python будет анализироваться с помощью pyflakes, строки с ошибками или предупреждениями будут подсвечены.

Примечание: добавьте analysis:ignore в комментарий, чтобы игнорировать предупреждения анализатора кода.

Предупреждение: изменения применяются раздельноНе более 4 комбинаций клавиш {break} для одного действия.{break}О %sО %s...Активировать поддержкуДобавить &блок комментариевДобавить блок комментариев вокруг текущей строки/выделенияДобавить путьДополнительные возможностиДополнительные опцииАдрес:Расширенные настройкиДополнительные настройкиВсе изменения для %s были потеряны.
Хотите перегрузить файл с диска?Все файлыВсе файлы (*)Все файлы (*.*)Все пользовательские переменные будут удалены.
Вы уверены, что хотите продолжить?Всегда показывать %s при первом запуске файлаОшибка создания сокета, нужного Spyder. Пожалуйста, попробуйте запустить следующую команду из cmd.exe от имени администратора и перезапустите компьютер:

netsh winsock reset
При запуске ядра произошла ошибкаАнализАнимировать панели инструментов и плавающие окнаВнешний видВы уверены, что хотите удалить цветовую схему?Вы уверены, что хотите перезапустить ядро?АргументыНеверная размерность массиваРедактор массивовМассивы с размерностью более 3 не поддерживаютсяСпрашивать подтверждение перед закрытиемСпрашивать подтверждение перед удалением всех пользовательских переменныхПрикреплённая консоль (отладка)АтрибутАвтовызовАвтовызов позволяет IPython автоматически вызывать объекты без явного ввода скобок.
Например, если Вы введете str 43, будет выполнено str(43) автоматически.Автовызов: АвтоматическиАвтоматическое дополнение кодаАвтоматические соединенияАвтоматический импортАвтоматическая вставка отступа после 'else', 'elif' и т.п.Автоматическая вставка закрывающих кавычекАвтоматическая вставка двоеточия после 'for', 'if', 'def' и т.п.Автоматическая вставка круглых, фигурных и квадратных скобокАвтоматически загружать модули Pylab и NumPyАвтоматически удалять лишние пробелы в конце строк при сохранении файловОси:НазадБэкенд:ФонЦвет фонаФон:Файлы BatchЖирныйТочка остановаОбзорПросмотреть рабочий каталогПросмотр репозитарияОбзор вкладокБуферБуфер...Буфер: Встроенные:Файлы CЗакрыть вс&е&КонсолиФайлы C++Информация об использовании ЦП и памяти в строке состоянияСостояние использования ЦП: требуется библиотека `psutil` (>=v0.3)ЦП:Текстовые файлы CSVОтменаНе удается перезапусть ядро, запущенное не из Spyder Возврат каретки (Mac)Возврат каретки и перевод строки (Windows)С учетом регистраЧувствительное к регистру автодополнениеБлок начинается в строке %sПеревести текущую строчку или выделение в нижний регистрИзменить на родительский каталогПеревести текущую строчку или выделение в верхний регистрИзменить бэкенд для Mayavi на QtПроверять обновления при стартеПроверить обновления...Класс определён в строке %sОчистить выводОчистить точки останова во всех файлахОчистить консольОчистить строкуОчистить строку или блокОчистить список недавних файловОчистить оболочкуОчистить содержание оболочки (команда 'cls')Очистить этот списокСодержимое буфера обменаЗакрыть проектЗакрыть все кроме этойЗакрыть все открытые файлыЗакрыть все правееЗакрыть текущий файлЗакрыть текущую панельЗакрыть текущую вкладкуЗакрыть эту панельЗакрыть это окноЗакрыть окноЗакрытие SpyderКодИнтроспекция/анализ кодаАнализ кодаДля анализа кода требуется pyflakes %s+Аннотации кода (TODO, FIXME, XXX, HINT, TIP, @todo, HACK, BUG, OPTIMIZE, !!!, ???)Свернуть всёСвернуть выделенноеРедактор цветовой схемыMin/max столбцаРазделитель столбцов:Столбец:Опции командной строки:КомментироватьКомментировать текущую строку/выделениеКомментарий:Комментарии:ЗафиксироватьТип автодополненияАвтодополнение:Условие:Файлы настроекНастройки для экранов высокого разрешения

Больше о этих опциях можно прочесть на {0}<> (на англ.).КонфликтыПодключиться к работающему ядруПодключение к ядру...Ошибка соединенияИнформация о соединении:КонсольКаталог консолиКонсольная справкаКонтекстПродолжитьПродолжить выполнение до следующей точки остановаОшибка преобразованияПреобразовать символы конца строкиСохранить как скрипт PythonКопироватьКопировать путь в буфер обменаКопировать в буфер обменаКопировать без подтвержденияНе удалось подключиться к удалённому хостуНе удалось открыть ssh-туннель. Произошла ошибка: СоздатьСоздать новое окно редактораСоздать новый проектСоздать новую схемуТекущий блок:Текущая строка:Текущая комбинация клавиш:Переменные cреды текущего пользователя...Текущий рабочий каталогИспользуется для удаления строк в редактореМигание курсора:Настроить отступы панелей:ВырезатьФайлы Cython/PyrexДанныеDataFrameОтладка файлаПанель отладкиОтладка с помощью winpdbВыберите как графика будет отображаться в консоли. Если не уверены, пожалуйста выберите %s для вставки графики в консоль или %s для взаимодействия с ними (через масштабирование и панорамирование) в отдельном окне.Выберите как рендерить графики, созданные этим бэкендомВыберите какой тип автодополнения использоватьПо умолчанию (тот же, что для Spyder)4 по умолчанию6 по умолчаниюПо умолчанию:
In [<span class="in-prompt-number">%i</span>]:По умолчанию:
Out [<span class="out-prompt-number">%i</span>]:Рабочий каталог по умолчанию:Определение:УдалитьУдалитьУдалить проектУдалить...ЗависимостиЗависимости...СловарьЗапускать отладку, как только произошла ошибкаОтображениеПоказывать всплывающие подсказкиПоказывать стартовый баннерВы точно хотите удалить %s?Вы действительно хотите удалить проект {filename}?

Примечание:Файлы, входящие в проект, при этом останутся на диске.Вы действительно хотите удалить выбранный путь?Вы действительно хотите переименовать %s или перезаписать существующий файл %s?Хотите закрыть все другие консоли, подключённые к тому же ядру?Вы уверены, что хотите закрыть эту консоль?Вы хотите удалить все выбранные элементы?Вы хотите удалить выбранный элемент?Уверены, что хотите восстановить значения по умолчанию?Хотите выполнить перезапуск сейчас?Не показывать снова.СделаноСоздать копиюКонец строкиРедактироватьРедактировать фильтры имён файловРедактировать фильтры имён файлов...Редактировать элементРедактировать выбраннуюРедактировать шаблон для новых модулейПанель правкиРедакторАвтодополнение кода редактора, переход к определению и справкаОчистить буфер обменаПустой проектВключает автодополнение по Tab для элементов списков, результатов вызова функций, и т.п. без присвоения их переменной.
Например, Вы можете сделать автодополнение для таких вещей, как li[0].<Tab> или ins.meth().<Tab>Включить UMRВключить автомасштабирование для high DPIФайлы EnamlКодировка:Символы конца строкиКонец строки:Клавиша Ввод/Enter выбирает автодополнениеВведите значения для разных экранов, разденные точками с запятой ';', вещественные числа поддерживаютсяПеременные средыПеременные среды...ОшибкаОшибка при перезапуске ядра: %s Исключить ссылки со всеми буквами в верхнем регистреИсключить ссылки с прописной буквыИсключить приватные ссылкиИсключить ссылки на неподдерживаемые типы данных (т.е. которые не будут правильно обработаны/сохранены)Исключить ссылки с именем в верхнем регистреИсключить ссылки, имена которых начинаются с подчёркиванияИсключить ссылки, имена которых начинаются с символа в верхнем регистреИсключить неподдерживаемые типы данныхИсключить:Шаблон имён исключаемых файловИсполняемые файлыВыполнить в отдельной консолиВыполнить во внешнем системном терминалеВыполнить в текущей консолиСуществующий каталогРазвернуть всёРазвернуть выделенноеВнешние инструментыВнешний редакторПуть запуска внешнего редактора:Путь к внешнему редактору...Внешний редактор:Внешний системный терминалБыстрое переключение между файламиБыстрый поиск в файлеФайлФайл %s уже существует.
Хотите его перезаписать?Файловый менеджерФайловый менеджерПереключение по файлам...Панель файловФайл...ФильтрНайти &следующийНайти &предыдущийНайти в файлахНайти в файлe...Найти текстАвтоматически исправлять и показывать окно предупрежденийИсправить отступыФорматирование чиселКаталог %s уже существует.Имя каталога:Каталог...Стиль шрифтаШрифт: ШрифтыДля поддержки %s, установите, пожалуйста,
один из следующих инструментов:

%sПо соображениям производительности, изменения принятые для скрытых массивов не будут отражены в данных массивов (и наоборот).Запрещенная комбинация клавиш!ФорматироватьФормат (%s) неверныйФормат ({}) неверныйФормат ({}) должен начинаться с '%'Формат:Файлы FortranВсеПолноэкранный режимФункция определена в строке %sИзображения GIFВизуальный редактор:ОсновныеОсновные настройкиПерейти к позиции курсораПерейти к определениюПерейти к последнему месту редактированияПерейти к строке...Перейти к строке:Перейти к следующему предупреждению/ошибке анализа кодаПерейти к следующей позиции курсораПерейти к предыдущему предупреждению/ошибке анализа кодаПерейти к предыдущей позиции курсораПерейти к шагу:ГрафическийГрафикаГрафический бэкендСкупое автодополнениеВысота:СправкаСправка...Здесь Вы можете получить справку по любому объекту, наведя текстовый курсор на него и нажав %s, как в Редакторе, так и в Консоли.%sСправка также может автоматически показываться при вводе открывающей круглой скобки после объекта. Вы можете активировать эту возможность в %s.Здесь можно выбрать цветовую схему, используемую в Редакторе и всех других модулях Spyder.

Вы можете редактировать цветовые схемы, предлагаемые Spyder, или создать новую с помощью опций, приведённых ниже.Скрыть дополнительные опцииСкрыть панели инструментовПодсветкаПодсвечивать текущий блокПодсвечивать текущую строкуПодсвечивать найденныеПодсвечивать вхождения слова черезГистограммаИсторияГлубина истории: Журнал историиЖурналы историиИстория...ДомойИмя хостаФайлы IDLIPythonКонсоль IPythonКонсоль IPythonДокументация IPythonIPython, интерактивная оболочка для pythonБлокноты IPythonТема значковЕсли активно, нажатие Tab будет делать отступ всегда, даже когда курсор не в начале строки (когда эта опция включена, автодополнение кода можно будет включить альтернативной комбинацией: Ctrl+Space)Если эта опция активна, при нажатии на имя объекта (левая кнопка мыши + клавиша Ctrl) произойдёт переход в место его определения (если возможно).Если Вы примете изменения, это переопределит переменные среды для текущего пользователя непосредственно в реестре Windows. Используйте с осторожностью, на свой риск.

Имейте в виду, чтобы изменения вступили в силу, необходимо перезагрузить родительский процесс приложения (просто перезапустите Spyder, если запускали его ярлыком Windows, или перезапустите приложение из которого Вы его запускали, например Python(x,y) Home)ИмпортироватьИмпортировать какИмпортировать данныеОшибка импортаИмпортировать из буфера обменаМастер импортаВ этой панели можно изучать и редактировать переменные, созданные в ходе работы программы или введенные напрямую в консолях Spyder.

Как можно увидеть, Менеджер Переменных показывает переменные, созданные на предыдущем шаге тура. Двойным щелчком на любом из них открывается окно, где можно тщательно изучить и изменить содержимое.Добавить отступДобавить отступ к текущей строке или выделениюСимволы отступа: ИндексИндекс:ИнформацияИнициализация...ВстроенныйВстроенный бекэндСтрока ввода:ВставитьПроверить текущий объектУстановленные модули PythonЭкземпляр класса:Интегрирует консоли IPythonУмная клавиша backspaceПерейти в консоль Python после выполненияИнтерактивные турыИнтерфейсВстроенная консольНастройки встроенной консолиВстроенный редактор:Введение в IPythonОбучающий турИнтроспекцияНеверный путь каталогаНеверный путь файлаВведен неверный ключНе удалось закрыть предыдущий экземпляр Spyder. Перезапуск прерван.Не удалось сконвертировать этот блокнот. Ошибка: Не удалось скопировать этот массивНе удалось скопировать значения этого массиваНевозможно создать форматированную текстовую справку по объекту.
Пожалуйста, просмотрите в виде обычного текста.Невозможно удалить результаты из блокнота. Ошибка: Невозможно перезапустить Spyder. Операция прервана.Не удалось перезапустить консоль IPython при переключении в этот проект. Ошибка: {0}Невозможно запустить файл во внешнем терминалеКурсивИзображения JPEGФайлы JSONФайлы JavascriptФайлы JsonФайлы JuliaЯдро остановилось, перезапускПерезапуск ядраКлючКлюч:Комбинации клавишКлючевое слово:ЯзыкПоследнее место редактированияКомпоновка %s будет перезаписана. Хотите продолжить?Показывать и Выбирать компоновкуПараметры компоновкиСтрока %sКоличество строк:Перевод строки (UNIX)Строка:Строки:Ссылка на место определения объектаСсылка:СписокЗагрузка %s...Загрузка консоли IPython...Загрузка редактора...Загрузка менеджера файлов...Загрузка справки...Загрузка модуля истории...Загрузка менеджера пространств имён...Загрузка онлайн-помощи...Загузка менеджера структуры...Загрузка менеджера проектов...Загрузка этого типа данных во время отладки не поддерживается.РасположениеЗаблокироватьЗакрепить панелиФайлы MATLABГлавная панельСохранять фокус в Редакторе после запуска блоков или выделенийНастроить цветовые схемыРаботает с блокнотами Jupyter в РедактореФайлы MarkdownМаскаСкрытые данныеПарные
скобки:Файлы MatlabДокументация MatplotlibРазвернуть текущую панельМаксимум записейМаксимальное количество строкМаксимальное количество недавних файловМаксимальное количество недавних файлов...Состояние использования памяти: требуется библиотека `psutil` (>=v0.3) на не-Windows платформахПамять:Метод определён в строке %sОпределите как показывать приглашения Ввода и Вывода в консоли.МодульМодуль pywin32 не найден.
Пожалуйста, перезапустите сессию Windows (не компьютер), чтобы изменения вступили в силу.Модуль или пакет:Модуль...ВнизВверхПереместить нижеПереместить внизПереместить вверхПереместить вышеПереместить...Файлы NSISИмяФильтры имён:НовыйНовый проект...Новый каталогНовые возможности в версии 3.0Новый файлНовый каталогНовый модульНовое имя:Новый пакетНовая комбинация клавиш:Используете Spyder впервые? Прочитайте нашеНовое имя переменной:Новое окноДалееСледующая позиция курсораСледующее предупреждение/ошибкаСейчас нет доступных консолей IPython для запуска %s.

Пожалуйста, откройте новую и попытайтесь снова.Дополнительная документация отсутствуетДополнительная документация отсутствуетНет совпаденийИсходный код не доступен.НормальноеОбычный текст:Нечего импортировать из буфера обмена.Массив NumPyМассивы NumPyСжатые массивы NumPyЧисло:Документация Numpy и ScipyО&ткрыть последний закрытыйОбъектВхождения слова:ОтключёнВ режиме %s Автовызов не происходит если отсутствуют аргументы у вызываемого. В режиме %s все вызываемые объекты вызываются (даже если аргументы не переданы).Онлайн документацияОнлайн справкаИспользуется только для формата PNG. 72 по умолчаниюОткрытьОткрыть не&давниеОткрыть консоль IPython здесьОткрыть проект...Открыть новую консоль IPython, подключенную к существующему ядруОткрыть консоль &IPythonОткрыть командную строку здесьОткрыть файл соединения IPythonОткрыть файлОткрыть файл как:Открыть последний закрытыйОткрыть проектОткрыть терминал здесьФайлы OpenCLОткрытие этой переменной может занять время Желаете продолжить?ОпцииСтруктураСтрока вывода:Изображения PNGМенеджер PYTHONPATHИмя пакета:Пакет...Плавающие окнаРодительскаяПарольПароль или кодовая фраза ключа sshВставитьФайлы патчей и diffПуть к файлу соединения или id ядраПуть к ключу sshПроизводит символьные операции в консоли (напр. интегралы, производные, векторное исчисление и др.) и выводит результат в красивом виде (требуется модуль Sympy).Выполнять анализ только при сохранении файлаВыполнять анализ при сохранении файла и каждыеДоступ:Архивы PickleПростойПростой текстШрифт текстаПожалуйста, подумайте об установке Sphinx для просмотра документации в форматированном виде.Пожалуйста, введите информацию о соединении для ядра, к которому пытаетесь подключиться. Для этого либо выберите JSON-файл соединения кнопкой Обзор, либо, если ядро локальное, введите его id (напр. kernel-3764.json или просто 3764).Пожалуйста, установите matplotlib или guiqwt.Пожалуйста, введите другую комбинацию клавишОбратите внимание, что эти изменения будут применяться только к новым консолям Python/IPythonОбратите внимание, что эти изменения будут применяться только к новым консолямГрафикПереходить во встроенную консоль при появлении внутренних ошибок&ПараметрыПараметрыПараметры > СправкаНажмите Enter для перехода к файлу или Esc для отмены.

Введите текст для фильтрации имен файлов.

Используйте :номер для перехода к строке, напр. main:42
Используйте @имя для перехода к идентификатору, напр. @init

Нажмите Ctrl+W для закрытия текущей вкладки.Нажмите Enter для подтверждения этого поляНажмите Enter для подтверждения этого путиНажмите новую комбинацию клавиш и выберите 'Ok': (Нажатие 'Tab' один раз переключает фокус между полем ввода комбинации клавиш и кнопками под ним)Предварительный просмотрПредыдущаяПредыдущая позиция курсораПредыдущее предупреждение/ошибкаПечатать текущий файлПредварительный просмотр...Печать...ПроектМенеджер проектовПараметры проектаМенеджер проектовИмя проектаПараметры проектаТип проектаСпрашиваить подтверждение при закрытииПриглашения к вводу/выводуПредоставляемые возможностиСправка по API PyQt4Справочное руководство по PyQt4Справка по API PyQt5Справочное руководство по PyQt5Менеджер путей PythonДокументация PythonФайлы PythonСправка Python:Интепретатор PythonПакет PythonПроект PythonСкрипты PythonВерсия PythonДокументация Python2Документация Python3Qt дизайнерQt LinguistДокументация QtПримеры QtСтиль окон QtКраткий справочникБыстрое переключение компоновки #%s не было определено.ВыходУ&далить блок комментариевНеобработанный текстПерезапустить последний блокПерезапустить последний скриптПерезапустить последний блокАнализ кода в реальном времениАнализ кода в Редакторе в реальном времениАнализ стиля кода в реальном времениАнализ стиля кода в Редакторе в реальном времениНедавние проектыЗаполнить поля массива:ВернутьОбновить список имён модулей, доступных в PYTHONPATHРегулярное выражениеОшибка в регулярном выраженииОшибка удаленияУдалитьУдалить все переменныеУдалить все переменные перед запускомУбрать блок комментариев вокруг текущей строки/выделенияУдалить путьУдалить ссылки:Удалить лишние пробелы в конце строкПереименоватьПереименовать вкладкуПереименовать...Отрисовывать математические выраженияЗаменить всеЗаменить выделенноеЗаменить строкуЗаменить символы табуляции пробеламиЗаменить на:Заменить/найти далееОтправить отчёт о проблеме...ВосстановитьВернуть Spyder к заводским настройкамВосстановить значения по умолчаниюВосстановить значения по умолчаниюВернуть компоновку по умолчаниюВосстановить настройки по умолчаниюИзменить размерРазмер строк по содержимомуРазрешение:ПерезапускПерезапустить ядроПерезапустить ядро?ПерезапускВосстановитьВосстановить текущую панельВосстанавливать данные при запускеВосстановить оригинальную структуру дереваВернуть панель к первоначальному размеруЗагрузить файл с дискаФорматированный текстШрифт форматированного текстаРазделитель строк:ЗапускВыполнить в&ыделенное или текущую строкуЗапустить файлы Cython в консоли IPythonЗапуск скрипта Pythonдиалог Настроек ЗапускаВыполнить скрипт PythonВыполнить файлВыполнить снова последний файлВыполнить &блокВыполнить блок и перейти далееВыполнить кодЗапустить конфигурациюЗапустить настройки для файлаВыполнить текущий блок (Ctrl+Enter) [Используйте #%% для создания блоков]Выполнить текущий блок и перейти к следующему (Shift+Enter)Выполнить текущую строкуВыполнить файлВыполнить скрипт:Выполнить выделениеВыполнить выделенное или текущую строкуНастройки ЗапускаНастройки Запуска для %sПанель запускаВыполнять пока функция или метод не завершатсяЗапуск внешнего системного терминала не поддерживается на платформе %s.Сохранить &всеСохранитьСохранить &как...Сохранить все файлыСохранить все файлы перед выполнением скриптаСохранить массивСохранить копию...Сохранить копию текущего файла как...Сохранить текущий файл как...Сохранить текущий журнал истории (т.е. все вводы и выводы) в текстовом файлеСохранить текущую компоновкуСохранить данныеСохранить данные как...Сохранять данные перед выходомСохранить файлСохранять журнал историиСохранить журнал историиСохранить журнал истории...Сохранять файлы не из проектаСохранение данных во время отладки не поддерживается.Название схемы:Схема: МеткаРазрешение экранаАвтоматически пролистывать к последней записиНайтиКаталог поискаИскать во всех файлах и каталогах, присутствующих в текущем пути SpyderИскать во всех файлах и каталогах, присутствующих в текущем пути проекта (если открыт)Искать в текущем открытом файлеИскать в другом каталоге файловой системыИскать в:Найти по шаблонуНайти строкуИскать текст в нескольких файлахПанель поискаПоиск:Выделить всёВыберите конфигурацию запуска:Выберите каталогВыберите файлВыберите другой каталогВыберите ключ sshВыберите исполняемый файл интерпретатора Python для всех консолей SpyderУстановить модули-исключения для UMR (не перезагружаемые)Фиксированный масштаб для high DPIУстановить рабочий каталог консолиУстановить каталог текущего скрипта как рабочий для текущей консоли (и файлового менеджера) Установить путь запуска внешнего редактораУстановить максимум записей историиУстановить максимальное число строкЗадайте список модулей-исключений вот так: numpy, scipyУстановите максимальное количество линий, показываемых в консоли перед усечением. Значение -1 отключает функцию (не рекомендуется!)Используется для мониторов с высоким разрешениемУстановить для экранов с высоким DPI, если автомасштабирование не работаетОтметьте для возможности отделить
любое меню от главного окнаОтметьте для открытия внешних
файлов Python в уже запущенном окружении (требуется перезапуск)Поставить/Убрать точку остановаПоставить/Редактировать условную точку остановаСоздание главного окна...НастройкиСпециальные команды оболочки:Комбинация клавишКомбинация клавиш: {0}Перечень комбинаций клавишВосстановить комбинации клавишКомбинации, использующие Shift с другой клавишей не поддерживаютсяПоказать (только чтение) sys.pathПоказывать загрузку ЦП каждыеПоказать исходникПоказать полный путьПоказать дополнительные опцииПоказать все файлыПоказывать и редактировать переменные среды в реестре Windows (т.е. для всех сессий)Показать и редактировать переменные среды (для текущей сессии)Показывать min/max массивовПоказывать отступыПоказать предупреждения/ошибки анализа кодаПоказать список комментариев (TODO/FIXME/XXX/HINT/TIP/@todo/HACK/BUG/OPTIMIZE/!!!/???)Показывать только текущий каталогПоказывать прошедшее времяПоказать переменные средыПоказывать справку об объектах в Редакторе и Консолях в специальной панелиПоказывать горизонтальную полосу прокруткиПоказывать иконки и текстПоказать изображениеПоказывать в ПоискеПоказать менеджер файловПоказывать номера строкПоказывать использование памяти каждыеПоказать список перезагруженных модулейПоказать специальные комментарииПоказывать панель состоянияПоказать содержимое sys.pathПоказать содержимое sys.path...Показывать панель вкладокПоказать список задачПоказывать панели инструментовРисовать вертикальную линию послеПоказать список предупреждений/ошибокПоказать/скрыть менеджер структурыБоковые панели:SiftРазмерРазмер: Пропустить строки:Умный&ДокументИсходникИсходный кодПанель кодаSphinx %s на данный момент установлено.Разделить по горизонталиРазделить окна редактора по горизонталиРазделить по вертикалиРазделить окна редактора по вертикалиСтандартная компоновка SpyderРедактор SpyderВстроенная консоль Spyder Эта консоль предназначена для вывода внутренних ошибок приложени и изучения внутреннего состояния Spyder следующими командами: spy.app, spy.window, dir(spy) Пожалуйста, не используйте её для запуска своего кода Комбинации клавиш SpyderНевозможно сбросить настройки Spyder в значения по умолчанию. Операция прервана.Файлы данных SpyderSpyder зависит от нескольких модулей Python, обеспечивающих правильное функционирование всех панелей. В таблице ниже показаны требуемые и установленные версии (если таковые имеются) каждого из пакетов.

Примечание: Вы можете безопасно работать в Spyder без следующих модулей: %s и %s. Также, пожалуйста, учтите, что новые пакеты или изменения в них будут корректно учтены только после перезапуска Spyder.Документация SpyderОшибка выхода из SpyderSpyder - интерактивная среда разработкиSpyder обновлён.Необходим перезапуск Spyder для изменения параметра:Необходим перезапуск Spyder для изменения настроек:Ошибка сброса настроек SpyderОшибка перезапуска SpyderПоддержка Spyder...Руководство SpyderОбновления SpyderSpyder не смог извлечь значение этой переменной из консоли.

Сообщение об ошибке:
%sSpyder будет перезапущен, настройки возвращены по умолчанию:

Хотите продолжить?Ключ sshНачать поискЗапускПанель состоянияШагШаг в функциюШаг из функцииВойти в функцию или метод текущей линииСтопЗавершить отладкуОстановить поискОстановить текущую командуСтрока не найденаСтрока:Отправить на GithubПоддержка графики (Matplotlib)Поддерживаемые файлыПоддерживаемые текстовые файлыПоиск символов...Символьная математикаСимвольная математика в консоли PythonСинхронизироватьСинхронизировать список путей Spyder с переменной среды PYTHONPATHСинхронизация...Подсветка синтаксисаПодсветка синтаксиса для Matlab, Julia и других типов файловСистемные команды:Изображения TIFFтабуляцияКлавиша Tab - всегда отступШирина табуляции:ТабуляцияОткрепляемые менюВременный файлТерминалТекстТекстовый редакторТекстовые файлыДлина аргумента 'xlabels' не соответствует числу столбцов массиваДлина аргумента 'ylabels' не соответствует числу строк массиваТекущая рабочий каталог - рабочий каталог для консолей IPython и текущий каталог для Менеджера файлов.Текстовый редакторФайловый менеджерЖурнал историиКонсоль IPythonМенеджер ПеременныхПодлинность хоста %s не может быть установлена. Вы уверены, что хотите продолжить соединение?Подлинность хоста не может быть установленаВ текущий каталоге находится проект.

Если вы хотите удалить проект, пожалуйста, воспользуйтесь меню Проекты » Удалить проектТекущий каталог проекта или домашний каталог пользователя (если нет активного проекта)Текущий рабочий каталогКаталог исполняемого файлаПри создании консоли текущий рабочий каталог будет иметь указанный путьКаталог {} защищен от записи. Для запуска консоли IPython, пожалуйста, откройте доступ на запись.Далее - стандартные настройкия для запуска файлов. Эти опции можно перезаписать с помощью пункта Настройки для файла меню ЗапускSphinx %s.
Несовместимая версия Sphinx или ошибка декодирования строки документации.

Сообщение об ошибке:
%sСледующие модули не установлены на Вашей машине: %sСледующий рабочий каталог не применим:
%sНовая комбинация клавиш конфликтует с:Рабочий каталог для новой консоли:Этот каталог уже имеется в списке путей Spyder.
Хотите переместить его на вершину списка?Это поле неверноЭта ошибка скорее всего произошла из-за установки Spyder в каталог, содержащий non-ascii символы (тильды, апострофы, не латинские символы и т.п.).

Для исправления переустановите Spyder в другой каталог.Эта возможность требует Sphinx 1.1 или выше.Эта функция требует библиотеки Rope или Jedi. Похоже, Вы их не установили.Это удалённо-управляемое ядроЭто временный скриптовый файл.Это одна из панелей, где можно запустить или выполнить код, написанный в Редакторе. Чтобы это сделать нужно нажать клавишуF5.

В этой консоли есть несколько полезных функций, которые значительно улучшают Ваш процесс программирования (такие как подсветка синтаксиса и встроенные графики). Если вы хотите узнать о них больше, перейдите по этой ссылке.

Пожалуйста, нажмите на кнопку ниже, чтобы запустить простой код в этой консоли. Это будет полезно, чтобы показать Вам другие важные функции.Это панель, в которой Вы пишете код Python перед его выполнением. Вы можете получать предложения и автодополнение по ходу ввода, нажимая клавишу Tab после ввода текста.

В Редактор входит панель номеров строк (подсвечена здесь красным), на которой Spyder показывает предупреждения и синтаксические ошибки. Они могут помочь Вам найти потенциальные проблемы перед запуском кода.

Также Вы можете установить отладочные точки останова на панели номеров строк двойным щелчком рядом с непустой строкой.Это - рабочий каталог для новосозданных консолей (консолей и терминалов Python/IPython), для файлового менеджера, для модуля поиска в файлах и для новых файлов, созданных в редактореЭто позволит загружать поддержку графики без импорта команд построения графиков. Полезно для работы с графическими библиотеками, отличными от Matplotlib или разработки GUI в Spyder.Эта опция позволяет Вам спрятать сообщение, показываемое вверху консоли при открытии.Эта опция позволяет Вам спрятать сообщение, показываемое при перезапуске окружения Spyder.Эта опция подгружает для работы библиотеку Sympy.
Пожалуйста ознакомьтесь с документацией для её использования.Эта опция будет принята при следующем открытии консоли.Эта опция включает Перезагрузчик Модулей Пользователя (UMR) в консолях Python/IPython. UMR заставляет Python рекурсивно перезагружать все модули при запуске скрипта Python встроенной функцией Spyder runfile.

1. UMR может потребовать перезапустить консоль, в которой был вызван (в противном случае только вновь импортируемые модули будут перезагружены при выполнении скриптов).

2.Если при перезапуске программ на PyQt происходят ошибки, убедитесь, что Qt-объекты уничтожены должным образом (напр. можно установить атрибут Qt.WA_DeleteOnClose для Вашего главного окна с помощью метода setAttribute)Инспектор объектов может автоматически показывать справочную информацию по объекту после ввода открывающей круглой скобки вслед за ним. Ниже вы можете решить, в каком модуле использовать эту возможность.Эта панель показывает документацию по функциям, классам, методам и модулям, используемым сейчас в Редакторе или Консолях.

Чтобы воспользоваться ею, нажмите Ctrl+I напротив объекта. Если у объекта есть какая-либо документация, она будет показана здесь.Эта панель позволяет перемещаться по директориям и файлам на Вашем компьютере.

Вы также можете открыть любой из файлов соответствующим ему приложением двойным щелчком по нему.

Существует одно исключение из этого правила: простые текстовые файлы всегда будут открыты в редакторе Spyder.Эта панель записывает все команды, введённые в консолях Python и IPython.Будет синхронизирован список путей Spyder с переменной среды PYTHONPATH для текущего пользователя, позволяя Вам запускать Ваши модули Python вне Spyder без необходимости настраивать sys.path.
Хотите очистить содержимое PYTHONPATH перед добавлением списка путей Spyder?В булевоВ комплексноеСписок задачВ вещественноеВ целоеВ строкуСделать строчнымиСделать ПрописнымиПанели инструментовТранспонироватьТуннель '%s' не удалось запуститьКортежТипUMRUMR заставляет Python перезагружать модули, импортированные при выполнении скрипта во внешней консоли функцией runfile.Не удалось проверить обновления.Не удалось подключиться к %sНе удалось подключиться к интернету.

Убедитесь, что соединение работает должным образом.Не удалось загрузить страницуНевозможно получить информацию.РаскомментироватьОтменитьНеожиданная ошибка: смотрите во встроенной консолиУбрать отступУбрать отступ у текущей строки/выделенияРазблокироватьСкобки
без пары:Обновите LANGUAGE_CODES (в файле config/base.py) если добавили новый перевод в SpyderОбновить список модулейИспользованиеИспользовать постраничный вывод для показа дополнительного текста в консолиЗапускать только одну копиюИсп. следующую компоновкуИсп. предыдущую компоновкуИспользовать символьную математикуИспользовать следующий интепретатор Python:Использовать следующий файл:Включить скупое автодополнениеИспользовать контроль версийПолезно, если Вы не хотите захламлять консоль длинной справкой или сплошным текстом. Примечание: Используйте клавишу Q для выхода из постраничного вывода.Перезагрузка модулей пользователя (UMR)ЗначениеЗначение:Имя переменнойМенеджер переменныхИмя переменной:Контроль версийСистема контроля версийВертикальные вкладки на плавающих окнахНазвания плавающих окон - вертикальноViTablesПоказ и редактирование структур DataFrame и Serie в Менеджере ПеременныхПросмотр и редактирование 2-х и 3-мерных массивов в Менеджере ПеременныхПредупреждениеЭта комбинация клавиш не поддерживается WindowsФайлы Веб-страницДобро пожаловать в обучающий тур SpyderДобро пожаловать в Spyder!Добро пожаловать в обучающий турКогда открывается текстовый файл, содержащий смешанные символы конца строки (это может увеличить число синтаксических ошибок в консолях на платформах Windows), Spyder может исправить файл автоматически.пробельный символСлова целикомШирина:WinPythonконтрольная панель WinPythonКомпоновка окон будет восстановлена по умолчанию: это отразится на позиции, размере и объединении окон. Хотите продолжить?Компоновка оконНастройки Рабочего каталогаРабочая областьПереносить строкиФайлы XMLФайлы YamlВы работаете с Python 2, поэтому вы не можете ипортировать модули, содержащие не-ascii символы.При старте Вы также можете запустить весь файл вместо нескольких строк (Подобно использованию файла PYTHONSTARTUP).Вы можете выполнить несколько строк кода при запуске консоли. Пожалуйста, введите их через запятую, например:
import os, import sysУ Вас нет прав на открытие этой директорииВы выбрали интерпретатор Python %d для консоли, но Spyder запущен на Python %d!.

Мы рекомендуем, если возможно, установить и запустить Spyder непосредственно выбранным интерпретатором, чтобы избежать появления ложных предупреждений и ошибок, связанных с несовместимостями в синтаксисе между этими двумя версиями Python.Вы выбрали некорректный интерпретатор Python для консоли, поэтому был оставлен предыдущий интерпретатор. Пожалуйста, выберите правильный.В вашем Python окружении или инсталяции не установлены модули ipykernel и cloudpickle. Без этих модулей Spyder не может создать консоль для Вас.

Вы можете установить их, запустив в терминале команду:

pip install ipykernel cloudpickle

или

conda install ipykernel cloudpickleУвеличитьУменьшитьВосстановить масштабмассивсимволовкодскопироватьданныеудалитьdpiэлементовфайлФайлы gettextпримеры guidataпримеры guiqwtдюймовневерное регулярное выражение строксписоксовпаденийсовпадений впереместитьмснет совпаденийиздругойобнаружены ошибки отказа в доступепикселейФайлы reStructuredTextтолько чтениепробелытаблицатекстуказанный каталог:это диалоговое окноруководствонесохранённый файлuntitledusername@hostname:portимя_переменнойspyder-3.2.6/spyder/locale/ru/LC_MESSAGES/spyder.po0000664000175000017500000065103113224121062022447 0ustar carloscarlos00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR ORGANIZATION # FIRST AUTHOR , YEAR. # FULL NAME , 2014. # Zgarbul Andrey , 2014. # msgid "" msgstr "" "Project-Id-Version: 3.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-12-14 15:40+-05\n" "PO-Revision-Date: 2017-12-16 15:10+0300\n" "Last-Translator: Zgarbul Andrey \n" "Language-Team: русский \n" "Language: ru_RU\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "X-Generator: Poedit 1.8.7.1\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" "X-Poedit-Basepath: ../../..\n" "X-Poedit-SearchPath-0: .\n" #: spyder/app/mainwindow.py:134 msgid "Initializing..." msgstr "Инициализация..." #: spyder/app/mainwindow.py:237 msgid "Python2 documentation" msgstr "Документация Python2" #: spyder/app/mainwindow.py:239 msgid "Python3 documentation" msgstr "Документация Python3" #: spyder/app/mainwindow.py:241 msgid "Numpy and Scipy documentation" msgstr "Документация Numpy и Scipy" #: spyder/app/mainwindow.py:243 msgid "Matplotlib documentation" msgstr "Документация Matplotlib" #: spyder/app/mainwindow.py:246 msgid "PyQt4 Reference Guide" msgstr "Справочное руководство по PyQt4" #: spyder/app/mainwindow.py:249 msgid "PyQt4 API Reference" msgstr "Справка по API PyQt4" #: spyder/app/mainwindow.py:252 msgid "PyQt5 Reference Guide" msgstr "Справочное руководство по PyQt5" #: spyder/app/mainwindow.py:255 msgid "PyQt5 API Reference" msgstr "Справка по API PyQt5" #: spyder/app/mainwindow.py:257 msgid "WinPython" msgstr "WinPython" #: spyder/app/mainwindow.py:530 msgid "" "An error occurred while creating a socket needed by Spyder. Please, try to " "run as an Administrator from cmd.exe the following command and then restart " "your computer:

netsh winsock reset
" msgstr "" "Ошибка создания сокета, нужного Spyder. Пожалуйста, попробуйте запустить " "следующую команду из cmd.exe от имени администратора и перезапустите " "компьютер: \n" "

netsh winsock reset
" #: spyder/app/mainwindow.py:562 msgid "Close current pane" msgstr "Закрыть текущую панель" #: spyder/app/mainwindow.py:567 msgid "Lock panes" msgstr "Закрепить панели" #: spyder/app/mainwindow.py:574 msgid "Use next layout" msgstr "Исп. следующую компоновку" #: spyder/app/mainwindow.py:578 msgid "Use previous layout" msgstr "Исп. предыдущую компоновку" #: spyder/app/mainwindow.py:588 spyder/widgets/editor.py:497 msgid "File switcher..." msgstr "Переключение по файлам..." #: spyder/app/mainwindow.py:590 msgid "Fast switch between files" msgstr "Быстрое переключение между файлами" #: spyder/app/mainwindow.py:596 msgid "Symbol finder..." msgstr "Поиск символов..." #: spyder/app/mainwindow.py:598 msgid "Fast symbol search in file" msgstr "Быстрый поиск в файле" #: spyder/app/mainwindow.py:617 spyder/widgets/sourcecode/codeeditor.py:2661 msgid "Undo" msgstr "Отменить" #: spyder/app/mainwindow.py:619 spyder/widgets/sourcecode/codeeditor.py:2664 msgid "Redo" msgstr "Вернуть" #: spyder/app/mainwindow.py:621 spyder/widgets/shell.py:123 #: spyder/widgets/sourcecode/codeeditor.py:2670 #: spyder/widgets/variableexplorer/arrayeditor.py:467 #: spyder/widgets/variableexplorer/collectionseditor.py:671 #: spyder/widgets/variableexplorer/dataframeeditor.py:586 msgid "Copy" msgstr "Копировать" #: spyder/app/mainwindow.py:623 spyder/widgets/shell.py:119 #: spyder/widgets/sourcecode/codeeditor.py:2667 msgid "Cut" msgstr "Вырезать" #: spyder/app/mainwindow.py:625 spyder/widgets/shell.py:127 #: spyder/widgets/sourcecode/codeeditor.py:2673 #: spyder/widgets/variableexplorer/collectionseditor.py:668 msgid "Paste" msgstr "Вставить" #: spyder/app/mainwindow.py:628 spyder/widgets/shell.py:140 #: spyder/widgets/sourcecode/codeeditor.py:2676 msgid "Select All" msgstr "Выделить всё" #: spyder/app/mainwindow.py:638 spyder/plugins/editor.py:1423 msgid "&File" msgstr "&Файл" #: spyder/app/mainwindow.py:639 spyder/plugins/editor.py:1411 msgid "File toolbar" msgstr "Панель файлов" #: spyder/app/mainwindow.py:643 spyder/plugins/editor.py:1424 msgid "&Edit" msgstr "&Правка" #: spyder/app/mainwindow.py:644 spyder/plugins/editor.py:1421 msgid "Edit toolbar" msgstr "Панель правки" #: spyder/app/mainwindow.py:648 spyder/plugins/editor.py:1425 msgid "&Search" msgstr "П&оиск" #: spyder/app/mainwindow.py:649 spyder/plugins/editor.py:1413 msgid "Search toolbar" msgstr "Панель поиска" #: spyder/app/mainwindow.py:653 spyder/plugins/editor.py:1426 msgid "Sour&ce" msgstr "&Документ" #: spyder/app/mainwindow.py:654 spyder/plugins/editor.py:1415 msgid "Source toolbar" msgstr "Панель кода" #: spyder/app/mainwindow.py:658 spyder/plugins/editor.py:803 #: spyder/plugins/editor.py:1427 msgid "&Run" msgstr "&Запуск" #: spyder/app/mainwindow.py:659 spyder/plugins/editor.py:1417 msgid "Run toolbar" msgstr "Панель запуска" #: spyder/app/mainwindow.py:663 spyder/plugins/editor.py:762 msgid "&Debug" msgstr "&Отладка" #: spyder/app/mainwindow.py:664 spyder/plugins/editor.py:1419 msgid "Debug toolbar" msgstr "Панель отладки" #: spyder/app/mainwindow.py:668 msgid "C&onsoles" msgstr "&Консоли" #: spyder/app/mainwindow.py:671 msgid "&Projects" msgstr "&Проекты" #: spyder/app/mainwindow.py:674 spyder/plugins/editor.py:1428 msgid "&Tools" msgstr "&Инструменты" #: spyder/app/mainwindow.py:677 spyder/plugins/editor.py:1429 msgid "&View" msgstr "&Вид" #: spyder/app/mainwindow.py:680 spyder/plugins/editor.py:1430 msgid "&Help" msgstr "Спр&авка" #: spyder/app/mainwindow.py:685 msgid "Welcome to Spyder!" msgstr "Добро пожаловать в Spyder!" #: spyder/app/mainwindow.py:690 msgid "Pre&ferences" msgstr "&Параметры" #: spyder/app/mainwindow.py:697 spyder/widgets/pathmanager.py:53 msgid "PYTHONPATH manager" msgstr "Менеджер PYTHONPATH" #: spyder/app/mainwindow.py:700 msgid "Python Path Manager" msgstr "Менеджер путей Python" #: spyder/app/mainwindow.py:703 msgid "Update module names list" msgstr "Обновить список модулей" #: spyder/app/mainwindow.py:706 msgid "Refresh list of module names available in PYTHONPATH" msgstr "Обновить список имён модулей, доступных в PYTHONPATH" #: spyder/app/mainwindow.py:709 msgid "Reset Spyder to factory defaults" msgstr "Вернуть Spyder к заводским настройкам" #: spyder/app/mainwindow.py:714 msgid "Current user environment variables..." msgstr "Переменные cреды текущего пользователя..." #: spyder/app/mainwindow.py:716 msgid "" "Show and edit current user environment variables in Windows registry (i.e. " "for all sessions)" msgstr "" "Показывать и редактировать переменные среды в реестре Windows (т.е. для всех " "сессий)" #: spyder/app/mainwindow.py:725 spyder/app/mainwindow.py:1147 msgid "External Tools" msgstr "Внешние инструменты" #: spyder/app/mainwindow.py:728 msgid "WinPython control panel" msgstr "контрольная панель WinPython" #: spyder/app/mainwindow.py:737 msgid "Qt Designer" msgstr "Qt дизайнер" #: spyder/app/mainwindow.py:742 msgid "Qt Linguist" msgstr "Qt Linguist" #: spyder/app/mainwindow.py:748 msgid "Qt examples" msgstr "Примеры Qt" #: spyder/app/mainwindow.py:768 msgid "guidata examples" msgstr "примеры guidata" #: spyder/app/mainwindow.py:779 msgid "guiqwt examples" msgstr "примеры guiqwt" #: spyder/app/mainwindow.py:784 msgid "Sift" msgstr "Sift" #: spyder/app/mainwindow.py:794 msgid "ViTables" msgstr "ViTables" #: spyder/app/mainwindow.py:808 msgid "Fullscreen mode" msgstr "Полноэкранный режим" #: spyder/app/mainwindow.py:820 msgid "Main toolbar" msgstr "Главная панель" #: spyder/app/mainwindow.py:829 msgid "" "Spyder Internal Console\n" "\n" "This console is used to report application\n" "internal errors and to inspect Spyder\n" "internals with the following commands:\n" " spy.app, spy.window, dir(spy)\n" "\n" "Please don't use it to run your code\n" "\n" msgstr "" "Встроенная консоль Spyder\n" "\n" "Эта консоль предназначена для вывода внутренних\n" "ошибок приложени и изучения внутреннего\n" "состояния Spyder следующими командами:\n" " spy.app, spy.window, dir(spy)\n" "\n" "Пожалуйста, не используйте её для\n" "запуска своего кода\n" #: spyder/app/mainwindow.py:846 msgid "Loading help..." msgstr "Загрузка справки..." #: spyder/app/mainwindow.py:853 msgid "Loading outline explorer..." msgstr "Загузка менеджера структуры..." #: spyder/app/mainwindow.py:861 msgid "Loading editor..." msgstr "Загрузка редактора..." #: spyder/app/mainwindow.py:867 spyder/plugins/console.py:140 #: spyder/widgets/ipythonconsole/client.py:417 msgid "&Quit" msgstr "В&ыход" #: spyder/app/mainwindow.py:869 spyder/plugins/console.py:142 msgid "Quit" msgstr "Выход" #: spyder/app/mainwindow.py:873 msgid "&Restart" msgstr "Пе&резапуск" #: spyder/app/mainwindow.py:875 msgid "Restart" msgstr "Перезапуск" #: spyder/app/mainwindow.py:889 msgid "Loading file explorer..." msgstr "Загрузка менеджера файлов..." #: spyder/app/mainwindow.py:896 msgid "Loading history plugin..." msgstr "Загрузка модуля истории..." #: spyder/app/mainwindow.py:907 msgid "Loading online help..." msgstr "Загрузка онлайн-помощи..." #: spyder/app/mainwindow.py:912 msgid "Loading project explorer..." msgstr "Загрузка менеджера проектов..." #: spyder/app/mainwindow.py:925 msgid "Loading namespace browser..." msgstr "Загрузка менеджера пространств имён..." #: spyder/app/mainwindow.py:931 msgid "Loading IPython console..." msgstr "Загрузка консоли IPython..." #: spyder/app/mainwindow.py:936 msgid "Setting up main window..." msgstr "Создание главного окна..." #: spyder/app/mainwindow.py:939 msgid "Dependencies..." msgstr "Зависимости..." #: spyder/app/mainwindow.py:943 msgid "Report issue..." msgstr "Отправить отчёт о проблеме..." #: spyder/app/mainwindow.py:947 msgid "Spyder support..." msgstr "Поддержка Spyder..." #: spyder/app/mainwindow.py:950 msgid "Check for updates..." msgstr "Проверить обновления..." #: spyder/app/mainwindow.py:973 msgid "Spyder documentation" msgstr "Документация Spyder" #: spyder/app/mainwindow.py:981 msgid "Spyder tutorial" msgstr "Руководство Spyder" #: spyder/app/mainwindow.py:986 msgid "Shortcuts Summary" msgstr "Перечень комбинаций клавиш" #: spyder/app/mainwindow.py:992 msgid "Interactive tours" msgstr "Интерактивные туры" #: spyder/app/mainwindow.py:1018 msgid "Python documentation" msgstr "Документация Python" #: spyder/app/mainwindow.py:1024 msgid "IPython documentation" msgstr "Документация IPython" #: spyder/app/mainwindow.py:1025 msgid "Intro to IPython" msgstr "Введение в IPython" #: spyder/app/mainwindow.py:1027 msgid "Quick reference" msgstr "Краткий справочник" #: spyder/app/mainwindow.py:1029 msgid "Console help" msgstr "Консольная справка" #: spyder/app/mainwindow.py:1059 msgid "Installed Python modules" msgstr "Установленные модули Python" #: spyder/app/mainwindow.py:1063 msgid "Online documentation" msgstr "Онлайн документация" #: spyder/app/mainwindow.py:1076 msgid "Qt documentation" msgstr "Документация Qt" #: spyder/app/mainwindow.py:1082 msgid "About %s..." msgstr "О %s..." #: spyder/app/mainwindow.py:1113 msgid "Panes" msgstr "Плавающие окна" #: spyder/app/mainwindow.py:1115 msgid "Toolbars" msgstr "Панели инструментов" #: spyder/app/mainwindow.py:1116 msgid "Window layouts" msgstr "Компоновка окон" #: spyder/app/mainwindow.py:1125 spyder/app/mainwindow.py:1924 #: spyder/app/mainwindow.py:1925 msgid "Show toolbars" msgstr "Показывать панели инструментов" #: spyder/app/mainwindow.py:1140 msgid "Attached console window (debugging)" msgstr "Прикреплённая консоль (отладка)" #: spyder/app/mainwindow.py:1317 spyder/plugins/console.py:220 #: spyder/plugins/projects.py:248 spyder/widgets/explorer.py:708 #: spyder/widgets/explorer.py:813 #: spyder/widgets/variableexplorer/arrayeditor.py:587 #: spyder/widgets/variableexplorer/collectionseditor.py:427 #: spyder/widgets/variableexplorer/dataframeeditor.py:752 #: spyder/widgets/variableexplorer/dataframeeditor.py:756 #: spyder/widgets/variableexplorer/namespacebrowser.py:299 msgid "Error" msgstr "Ошибка" #: spyder/app/mainwindow.py:1318 msgid "" "You have missing dependencies!

%s

Please " "install them to avoid this message.

Note: Spyder could " "work without some of these dependencies, however to have a smooth experience " "when using Spyder we strongly recommend you to install all the listed " "missing dependencies.

Failing to install these dependencies might " "result in bugs. Please be sure that any found bugs are not the direct result " "of missing dependencies, prior to reporting a new issue." msgstr "" "У Вас есть недостающие зависимости!

%s

Пожалуйста, установите их, чтобы это сообщение исчезло.

Примечание: Возможно, Spyder сможет работать без некоторых " "из них, однако для беспроблемного использования Spyder мы настоятельно рекомендуем установить все приведённые недостающие зависимости." "

Неудачная установка этих зависимостей могла привести к ошибкам. " "Пожалуйста, прежде чем сообщать о новой проблеме, убедитесь, что любые " "найденные ошибки не являются прямым результатот отсутствия некоторых " "зависимостей." #: spyder/app/mainwindow.py:1771 msgid "Spyder Default Layout" msgstr "Стандартная компоновка Spyder" #: spyder/app/mainwindow.py:1789 msgid "Save current layout" msgstr "Сохранить текущую компоновку" #: spyder/app/mainwindow.py:1793 msgid "Layout preferences" msgstr "Параметры компоновки" #: spyder/app/mainwindow.py:1797 msgid "Reset to spyder default" msgstr "Вернуть компоновку по умолчанию" #: spyder/app/mainwindow.py:1817 spyder/app/mainwindow.py:1839 #: spyder/app/mainwindow.py:1902 spyder/app/mainwindow.py:2722 #: spyder/plugins/configdialog.py:1346 spyder/plugins/ipythonconsole.py:131 #: spyder/plugins/ipythonconsole.py:927 spyder/plugins/ipythonconsole.py:1365 #: spyder/plugins/maininterpreter.py:149 spyder/plugins/maininterpreter.py:174 #: spyder/plugins/maininterpreter.py:203 spyder/utils/environ.py:95 #: spyder/utils/environ.py:108 #: spyder/widgets/ipythonconsole/namespacebrowser.py:131 #: spyder/widgets/ipythonconsole/namespacebrowser.py:149 #: spyder/widgets/variableexplorer/arrayeditor.py:510 #: spyder/widgets/variableexplorer/collectionseditor.py:416 #: spyder/widgets/variableexplorer/collectionseditor.py:1092 msgid "Warning" msgstr "Предупреждение" #: spyder/app/mainwindow.py:1818 msgid "" "Window layout will be reset to default settings: this affects window " "position, size and dockwidgets.\n" "Do you want to continue?" msgstr "" "Компоновка окон будет восстановлена по умолчанию: это отразится на позиции, " "размере и объединении окон.\n" "Хотите продолжить?" #: spyder/app/mainwindow.py:1840 msgid "" "Layout %s will be " "overwritten. Do you want to " "continue?" msgstr "Компоновка %s будет перезаписана. Хотите продолжить?" #: spyder/app/mainwindow.py:1903 msgid "Quick switch layout #%s has not yet been defined." msgstr "Быстрое переключение компоновки #%s не было определено." #: spyder/app/mainwindow.py:1921 spyder/app/mainwindow.py:1922 msgid "Hide toolbars" msgstr "Скрыть панели инструментов" #: spyder/app/mainwindow.py:2237 spyder/app/mainwindow.py:2238 msgid "Maximize current pane" msgstr "Развернуть текущую панель" #: spyder/app/mainwindow.py:2241 msgid "Restore current pane" msgstr "Восстановить текущую панель" #: spyder/app/mainwindow.py:2242 msgid "Restore pane to its original size" msgstr "Вернуть панель к первоначальному размеру" #: spyder/app/mainwindow.py:2327 msgid "About %s" msgstr "О %s" #: spyder/app/mainwindow.py:2460 spyder/plugins/editor.py:168 #: spyder/plugins/runconfig.py:354 spyder/plugins/runconfig.py:476 #: spyder/utils/programs.py:286 spyder/widgets/explorer.py:335 msgid "Run" msgstr "Запуск" #: spyder/app/mainwindow.py:2461 msgid "Running an external system terminal is not supported on platform %s." msgstr "" "Запуск внешнего системного терминала не поддерживается на платформе %s." #: spyder/app/mainwindow.py:2723 msgid "" "Spyder will restart and reset to default settings:

Do you want to " "continue?" msgstr "" "Spyder будет перезапущен, настройки возвращены по умолчанию:

Хотите " "продолжить?" #: spyder/app/mainwindow.py:2851 spyder/widgets/helperwidgets.py:254 msgid "Spyder updates" msgstr "Обновления Spyder" #: spyder/app/mainwindow.py:2852 spyder/plugins/configdialog.py:836 msgid "Check for updates on startup" msgstr "Проверять обновления при старте" #: spyder/app/mainwindow.py:2871 msgid "" "
IMPORTANT NOTE: It seems that you are using Spyder with " "Anaconda/Miniconda. Please don't use pip to " "update it as that will probably break your installation.

Instead, " "please wait until new conda packages are available and use conda to perform the update.
" msgstr "" "
ОЧЕНЬ ВАЖНО: Похоже, что вы используете Spyder вместе с " "Anaconda/Miniconda. Пожалуйста, не используйте pip для обновления, т.к. это может сломать вашу сборку.

Вместо " "этого, пожалуйста, дождитесь выхода новых пакетов и используйте conda для установки обновлений.
" #: spyder/app/mainwindow.py:2881 msgid "" "Spyder %s is available!

Please use your package manager to " "update Spyder or go to our Releases page to download this " "new version.

If you are not sure how to proceed to update Spyder " "please refer to our Installation instructions." msgstr "" "Доступен Spyder %s!

Пожалйста, используйте свой пакетный " "менеджер или перейдите на нашу страницу Релизов для " "загрузки новой версии.

Если Вы не уверены, как произвести обновление " "Spyder, ознакомьтесь с нашими инструкциями по Установке." #: spyder/app/mainwindow.py:2894 msgid "Spyder is up to date." msgstr "Spyder обновлён." #: spyder/app/restart.py:134 msgid "" "It was not possible to close the previous Spyder instance.\n" "Restart aborted." msgstr "" "Не удалось закрыть предыдущий экземпляр Spyder.\n" "Перезапуск прерван." #: spyder/app/restart.py:136 msgid "" "Spyder could not reset to factory defaults.\n" "Restart aborted." msgstr "" "Невозможно сбросить настройки Spyder в значения по умолчанию.\n" "Операция прервана." #: spyder/app/restart.py:138 msgid "" "It was not possible to restart Spyder.\n" "Operation aborted." msgstr "" "Невозможно перезапустить Spyder.\n" "Операция прервана." #: spyder/app/restart.py:140 msgid "Spyder exit error" msgstr "Ошибка выхода из Spyder" #: spyder/app/restart.py:141 msgid "Spyder reset error" msgstr "Ошибка сброса настроек Spyder" #: spyder/app/restart.py:142 msgid "Spyder restart error" msgstr "Ошибка перезапуска Spyder" #: spyder/app/restart.py:183 msgid "Closing Spyder" msgstr "Закрытие Spyder" #: spyder/app/restart.py:257 msgid "Resetting Spyder to defaults" msgstr "Восстановить настройки по умолчанию" #: spyder/app/restart.py:289 msgid "Restarting" msgstr "Перезапуск" #: spyder/app/tour.py:123 msgid "Welcome to the Introduction tour" msgstr "Добро пожаловать в обучающий тур" #: spyder/app/tour.py:124 msgid "" "Spyder is a powerful Interactive Development Environment (or IDE) for " "the Python programming language.

Here we are going to guide you " "through its most important features.

Please use the arrow keys or " "click on the buttons below to move along the tour." msgstr "" "Spyder - мощная Интерактивная Среда Разработки (или IDE) для языка " "программирования Python.

Здесь мы ознакомим Вас с наиболее важными " "возможностями.

Пожалуйста, используйте клавиши со стрелками или " "кнопки внизу, чтобы двигаться вдоль тура." #: spyder/app/tour.py:133 msgid "The Editor" msgstr "Текстовый редактор" #: spyder/app/tour.py:134 msgid "" "This is the pane where you write Python code before evaluating it. You can " "get automatic suggestions and completions while writing, by pressing the " "Tab key next to a given text.

The Editor comes with a line " "number area (highlighted here in red), where Spyder shows warnings and " "syntax errors. They can help you to detect potential problems before running " "the code.

You can also set debug breakpoints in the line number area, " "by doing a double click next to a non-empty line." msgstr "" "Это панель, в которой Вы пишете код Python перед его выполнением. Вы можете " "получать предложения и автодополнение по ходу ввода, нажимая клавишу Tab после ввода текста.

В Редактор входит панель номеров строк " "(подсвечена здесь красным), на которой Spyder показывает предупреждения и " "синтаксические ошибки. Они могут помочь Вам найти потенциальные проблемы " "перед запуском кода.

Также Вы можете установить отладочные точки " "останова на панели номеров строк двойным щелчком рядом с непустой строкой." #: spyder/app/tour.py:149 msgid "The IPython console" msgstr "Консоль IPython" #: spyder/app/tour.py:150 msgid "" "This is one of panes where you can run or execute the code you wrote on the " "Editor. To do it you need to press the F5 key.

This console " "comes with several useful features that greatly improve your programming " "workflow (like syntax highlighting and inline plots). If you want to know " "more about them, please follow this link.

Please " "click on the button below to run some simple code in this console. This will " "be useful to show you other important features." msgstr "" "Это одна из панелей, где можно запустить или выполнить код, написанный в " "Редакторе. Чтобы это сделать нужно нажать клавишуF5.

В этой " "консоли есть несколько полезных функций, которые значительно улучшают Ваш " "процесс программирования (такие как подсветка синтаксиса и встроенные " "графики). Если вы хотите узнать о них больше, перейдите по этой ссылке.

Пожалуйста, нажмите на кнопку ниже, чтобы " "запустить простой код в этой консоли. Это будет полезно, чтобы показать Вам " "другие важные функции." #: spyder/app/tour.py:166 msgid "The Variable Explorer" msgstr "Менеджер Переменных" #: spyder/app/tour.py:167 msgid "" "In this pane you can view and edit the variables generated during the " "execution of a program, or those entered directly in one of Spyder consoles." "

As you can see, the Variable Explorer is showing the variables " "generated during the last step of this tour. By doing a double-click on any " "of them, a new window will be opened, where you can inspect and modify their " "contents." msgstr "" "В этой панели можно изучать и редактировать переменные, созданные в ходе " "работы программы или введенные напрямую в консолях Spyder.

Как можно " "увидеть, Менеджер Переменных показывает переменные, созданные на предыдущем " "шаге тура. Двойным щелчком на любом из них открывается окно, где можно " "тщательно изучить и изменить содержимое." #: spyder/app/tour.py:179 spyder/plugins/help.py:479 spyder/plugins/help.py:921 #: spyder/widgets/internalshell.py:270 msgid "Help" msgstr "Справка" #: spyder/app/tour.py:180 msgid "" "This pane displays documentation of the functions, classes, methods or " "modules you are currently using in the Editor or the Consoles.

To use " "it, you need to press Ctrl+I in front of an object. If that object " "has some documentation associated with it, it will be displayed here." msgstr "" "Эта панель показывает документацию по функциям, классам, методам и модулям, " "используемым сейчас в Редакторе или Консолях.

Чтобы воспользоваться " "ею, нажмите Ctrl+I напротив объекта. Если у объекта есть какая-либо " "документация, она будет показана здесь." #: spyder/app/tour.py:190 msgid "The File Explorer" msgstr "Файловый менеджер" #: spyder/app/tour.py:191 msgid "" "This pane lets you navigate through the directories and files present in " "your computer.

You can also open any of these files with its " "corresponding application, by doing a double click on it.

There is " "one exception to this rule: plain-text files will always be opened in the " "Spyder Editor." msgstr "" "Эта панель позволяет перемещаться по директориям и файлам на Вашем " "компьютере.

Вы также можете открыть любой из файлов соответствующим " "ему приложением двойным щелчком по нему.

Существует одно исключение " "из этого правила: простые текстовые файлы всегда будут открыты в редакторе " "Spyder." #: spyder/app/tour.py:201 msgid "The History Log" msgstr "Журнал истории" #: spyder/app/tour.py:202 msgid "" "This pane records all commands introduced in the Python and IPython consoles." msgstr "" "Эта панель записывает все команды, введённые в консолях Python и IPython." # Такое ощущение, что фраза не окончена и bla здесь (оно же bla-bla-bla) используется вместо '...' #: spyder/app/tour.py:250 msgid "Spyder is an interactive development environment based on bla" msgstr "Spyder - интерактивная среда разработки" #: spyder/app/tour.py:254 msgid "Welcome to Spyder introduction tour" msgstr "Добро пожаловать в обучающий тур Spyder" # Такое ощущение, что фраза не окончена и bla здесь (оно же bla-bla-bla) используется вместо '...' #: spyder/app/tour.py:255 msgid "Spyder is an interactive development environment based on bla" msgstr "Spyder - интерактивная среда разработки" #: spyder/app/tour.py:260 msgid "Introduction tour" msgstr "Обучающий тур" #: spyder/app/tour.py:261 msgid "New features in version 3.0" msgstr "Новые возможности в версии 3.0" #: spyder/app/tour.py:555 spyder/plugins/ipythonconsole.py:446 msgid "Run code" msgstr "Выполнить код" #: spyder/app/tour.py:830 msgid "Go to step: " msgstr "Перейти к шагу:" #: spyder/config/base.py:257 msgid "" "Update LANGUAGE_CODES (inside config/base.py) if a new translation has been " "added to Spyder" msgstr "" "Обновите LANGUAGE_CODES (в файле config/base.py) если добавили новый перевод " "в Spyder" #: spyder/config/utils.py:24 msgid "Python files" msgstr "Файлы Python" #: spyder/config/utils.py:25 msgid "Cython/Pyrex files" msgstr "Файлы Cython/Pyrex" #: spyder/config/utils.py:26 msgid "C files" msgstr "Файлы C" #: spyder/config/utils.py:27 msgid "C++ files" msgstr "Файлы C++" #: spyder/config/utils.py:28 msgid "OpenCL files" msgstr "Файлы OpenCL" #: spyder/config/utils.py:29 msgid "Fortran files" msgstr "Файлы Fortran" #: spyder/config/utils.py:30 msgid "IDL files" msgstr "Файлы IDL" #: spyder/config/utils.py:31 msgid "MATLAB files" msgstr "Файлы MATLAB" #: spyder/config/utils.py:32 msgid "Julia files" msgstr "Файлы Julia" #: spyder/config/utils.py:33 msgid "Yaml files" msgstr "Файлы Yaml" #: spyder/config/utils.py:34 msgid "Patch and diff files" msgstr "Файлы патчей и diff" #: spyder/config/utils.py:35 msgid "Batch files" msgstr "Файлы Batch" #: spyder/config/utils.py:36 spyder/utils/iofuncs.py:426 msgid "Text files" msgstr "Текстовые файлы" #: spyder/config/utils.py:37 msgid "reStructuredText files" msgstr "Файлы reStructuredText" #: spyder/config/utils.py:38 msgid "gettext files" msgstr "Файлы gettext" #: spyder/config/utils.py:39 msgid "NSIS files" msgstr "Файлы NSIS" #: spyder/config/utils.py:40 msgid "Web page files" msgstr "Файлы Веб-страниц" #: spyder/config/utils.py:41 msgid "XML files" msgstr "Файлы XML" #: spyder/config/utils.py:42 msgid "Javascript files" msgstr "Файлы Javascript" #: spyder/config/utils.py:43 msgid "Json files" msgstr "Файлы Json" #: spyder/config/utils.py:44 msgid "IPython notebooks" msgstr "Блокноты IPython" #: spyder/config/utils.py:45 msgid "Enaml files" msgstr "Файлы Enaml" #: spyder/config/utils.py:46 msgid "Configuration files" msgstr "Файлы настроек" #: spyder/config/utils.py:48 msgid "Markdown files" msgstr "Файлы Markdown" #: spyder/config/utils.py:52 spyder/widgets/explorer.py:781 msgid "All files" msgstr "Все файлы" #: spyder/config/utils.py:134 msgid "Supported text files" msgstr "Поддерживаемые текстовые файлы" #: spyder/plugins/__init__.py:508 spyder/plugins/editor.py:105 #: spyder/plugins/editor.py:568 spyder/plugins/editor.py:1819 #: spyder/plugins/help.py:117 spyder/plugins/help.py:380 #: spyder/widgets/editor.py:534 spyder/widgets/sourcecode/codeeditor.py:98 #: spyder/widgets/sourcecode/codeeditor.py:3193 msgid "Editor" msgstr "Редактор" #: spyder/plugins/configdialog.py:144 msgid "Reset to defaults" msgstr "Восстановить значения по умолчанию" #: spyder/plugins/configdialog.py:156 msgid "Preferences" msgstr "Параметры" #: spyder/plugins/configdialog.py:508 msgid "Invalid directory path" msgstr "Неверный путь каталога" #: spyder/plugins/configdialog.py:511 spyder/plugins/configdialog.py:526 #: spyder/plugins/runconfig.py:220 spyder/plugins/runconfig.py:268 #: spyder/plugins/workingdirectory.py:240 spyder/widgets/explorer.py:695 #: spyder/widgets/findinfiles.py:494 spyder/widgets/pathmanager.py:258 #: spyder/widgets/projects/projectdialog.py:155 msgid "Select directory" msgstr "Выберите каталог" #: spyder/plugins/configdialog.py:538 msgid "Invalid file path" msgstr "Неверный путь файла" #: spyder/plugins/configdialog.py:541 spyder/plugins/configdialog.py:558 msgid "Select file" msgstr "Выберите файл" #: spyder/plugins/configdialog.py:557 msgid "All files (*)" msgstr "Все файлы (*)" #: spyder/plugins/configdialog.py:630 msgid "Bold" msgstr "Жирный" #: spyder/plugins/configdialog.py:633 msgid "Italic" msgstr "Курсив" #: spyder/plugins/configdialog.py:687 msgid "Font: " msgstr "Шрифт: " #: spyder/plugins/configdialog.py:693 msgid "Size: " msgstr "Размер: " #: spyder/plugins/configdialog.py:712 msgid "Font style" msgstr "Стиль шрифта" #: spyder/plugins/configdialog.py:789 msgid "Spyder needs to restart to change the following setting:" msgstr "Необходим перезапуск Spyder для изменения параметра:" #: spyder/plugins/configdialog.py:792 msgid "Spyder needs to restart to change the following settings:" msgstr "Необходим перезапуск Spyder для изменения настроек:" #: spyder/plugins/configdialog.py:794 msgid "Do you wish to restart now?" msgstr "Хотите выполнить перезапуск сейчас?" #: spyder/plugins/configdialog.py:800 msgid "Information" msgstr "Информация" #: spyder/plugins/configdialog.py:814 spyder/plugins/configdialog.py:821 #: spyder/widgets/projects/configdialog.py:74 msgid "General" msgstr "Основные" #: spyder/plugins/configdialog.py:824 msgid "Language" msgstr "Язык" #: spyder/plugins/configdialog.py:827 msgid "Use a single instance" msgstr "Запускать только одну копию" #: spyder/plugins/configdialog.py:829 msgid "" "Set this to open external
Python files in an already running instance " "(Requires a restart)" msgstr "" "Отметьте для открытия внешних
файлов Python в уже запущенном окружении " "(требуется перезапуск)" #: spyder/plugins/configdialog.py:832 msgid "Prompt when exiting" msgstr "Спрашиваить подтверждение при закрытии" #: spyder/plugins/configdialog.py:833 msgid "Pop up internal console when internal errors appear" msgstr "Переходить во встроенную консоль при появлении внутренних ошибок" #: spyder/plugins/configdialog.py:853 spyder/plugins/editor.py:114 #: spyder/plugins/ipythonconsole.py:290 #: spyder/widgets/projects/configdialog.py:81 msgid "Interface" msgstr "Интерфейс" #: spyder/plugins/configdialog.py:861 msgid "Qt windows style" msgstr "Стиль окон Qt" #: spyder/plugins/configdialog.py:867 msgid "Icon theme" msgstr "Тема значков" #: spyder/plugins/configdialog.py:871 msgid "Vertical title bars in panes" msgstr "Названия плавающих окон - вертикально" #: spyder/plugins/configdialog.py:873 msgid "Vertical tabs in panes" msgstr "Вертикальные вкладки на плавающих окнах" #: spyder/plugins/configdialog.py:875 msgid "Animated toolbars and panes" msgstr "Анимировать панели инструментов и плавающие окна" #: spyder/plugins/configdialog.py:877 msgid "Tear off menus" msgstr "Открепляемые меню" #: spyder/plugins/configdialog.py:878 msgid "Set this to detach any
menu from the main window" msgstr "Отметьте для возможности отделить
любое меню от главного окна" #: spyder/plugins/configdialog.py:880 msgid "Custom margin for panes:" msgstr "Настроить отступы панелей:" #: spyder/plugins/configdialog.py:882 msgid "pixels" msgstr "пикселей" #: spyder/plugins/configdialog.py:889 msgid "Cursor blinking:" msgstr "Мигание курсора:" #: spyder/plugins/configdialog.py:891 msgid "ms" msgstr "мс" #: spyder/plugins/configdialog.py:930 msgid "Status bar" msgstr "Панель состояния" #: spyder/plugins/configdialog.py:931 msgid "Show status bar" msgstr "Показывать панель состояния" #: spyder/plugins/configdialog.py:933 msgid "Show memory usage every" msgstr "Показывать использование памяти каждые" #: spyder/plugins/configdialog.py:935 spyder/plugins/configdialog.py:944 #: spyder/plugins/editor.py:139 spyder/plugins/editor.py:283 msgid " ms" msgstr " мс" #: spyder/plugins/configdialog.py:942 msgid "Show CPU usage every" msgstr "Показывать загрузку ЦП каждые" #: spyder/plugins/configdialog.py:975 msgid "Screen resolution" msgstr "Разрешение экрана" #: spyder/plugins/configdialog.py:977 msgid "" "Configuration for high DPI screens

Please see {0}<> for more information about these options (in English)." msgstr "" "Настройки для экранов высокого разрешения

Больше о этих опциях можно " "прочесть на
{0}<> (на англ.)." #: spyder/plugins/configdialog.py:987 msgid "Normal" msgstr "Нормальное" #: spyder/plugins/configdialog.py:991 msgid "Enable auto high DPI scaling" msgstr "Включить автомасштабирование для high DPI" #: spyder/plugins/configdialog.py:994 msgid "Set this for high DPI displays" msgstr "Используется для мониторов с высоким разрешением" #: spyder/plugins/configdialog.py:998 msgid "Set a custom high DPI scaling" msgstr "Фиксированный масштаб для high DPI" #: spyder/plugins/configdialog.py:1001 msgid "Set this for high DPI displays when auto scaling does not work" msgstr "" "Установить для экранов с высоким DPI, если автомасштабирование не работает" #: spyder/plugins/configdialog.py:1007 msgid "" "Enter values for different screens separated by semicolons ';', float values " "are supported" msgstr "" "Введите значения для разных экранов, разденные точками с запятой ';', " "вещественные числа поддерживаются" #: spyder/plugins/configdialog.py:1034 msgid "Plain text font" msgstr "Шрифт текста" #: spyder/plugins/configdialog.py:1040 msgid "Rich text font" msgstr "Шрифт форматированного текста" #: spyder/plugins/configdialog.py:1043 msgid "Fonts" msgstr "Шрифты" #: spyder/plugins/configdialog.py:1057 msgid "Appearance" msgstr "Внешний вид" #: spyder/plugins/configdialog.py:1059 spyder/plugins/ipythonconsole.py:579 msgid "Advanced Settings" msgstr "Расширенные настройки" #: spyder/plugins/configdialog.py:1095 msgid "Syntax coloring" msgstr "Подсветка синтаксиса" #: spyder/plugins/configdialog.py:1108 msgid "" "Here you can select the color scheme used in the Editor and all other Spyder " "plugins.

You can also edit the color schemes provided by Spyder or " "create your own ones by using the options provided below.
" msgstr "" "Здесь можно выбрать цветовую схему, используемую в Редакторе и всех других " "модулях Spyder.

Вы можете редактировать цветовые схемы, предлагаемые " "Spyder, или создать новую с помощью опций, приведённых ниже." #: spyder/plugins/configdialog.py:1113 msgid "Edit selected" msgstr "Редактировать выбранную" #: spyder/plugins/configdialog.py:1114 msgid "Create new scheme" msgstr "Создать новую схему" #: spyder/plugins/configdialog.py:1115 spyder/widgets/explorer.py:574 #: spyder/widgets/projects/explorer.py:242 spyder/widgets/shell.py:136 msgid "Delete" msgstr "Удалить" #: spyder/plugins/configdialog.py:1118 msgid "Reset" msgstr "Восстановить" #: spyder/plugins/configdialog.py:1125 msgid "Scheme:" msgstr "Схема: " #: spyder/plugins/configdialog.py:1156 msgid "Manage color schemes" msgstr "Настроить цветовые схемы" #: spyder/plugins/configdialog.py:1347 msgid "Are you sure you want to delete this scheme?" msgstr "Вы уверены, что хотите удалить цветовую схему?" #: spyder/plugins/configdialog.py:1464 msgid "Text" msgstr "Текст" #: spyder/plugins/configdialog.py:1466 msgid "Highlight" msgstr "Подсветка" #: spyder/plugins/configdialog.py:1468 msgid "Background" msgstr "Фон" #: spyder/plugins/configdialog.py:1472 msgid "Scheme name:" msgstr "Название схемы:" #: spyder/plugins/configdialog.py:1479 msgid "Color scheme editor" msgstr "Редактор цветовой схемы" #: spyder/plugins/console.py:115 msgid "Internal console" msgstr "Встроенная консоль" #: spyder/plugins/console.py:145 msgid "&Run..." msgstr "&Выполнить..." #: spyder/plugins/console.py:147 msgid "Run a Python script" msgstr "Выполнить скрипт Python" #: spyder/plugins/console.py:150 msgid "Environment variables..." msgstr "Переменные среды..." #: spyder/plugins/console.py:152 msgid "Show and edit environment variables (for current session)" msgstr "Показать и редактировать переменные среды (для текущей сессии)" #: spyder/plugins/console.py:156 msgid "Show sys.path contents..." msgstr "Показать содержимое sys.path..." #: spyder/plugins/console.py:158 msgid "Show (read-only) sys.path" msgstr "Показать (только чтение) sys.path" #: spyder/plugins/console.py:161 msgid "Buffer..." msgstr "Буфер..." #: spyder/plugins/console.py:162 spyder/plugins/history.py:43 msgid "Set maximum line count" msgstr "Установить максимальное число строк" #: spyder/plugins/console.py:165 msgid "External editor path..." msgstr "Путь к внешнему редактору..." #: spyder/plugins/console.py:166 msgid "Set external editor executable path" msgstr "Установить путь запуска внешнего редактора" #: spyder/plugins/console.py:169 spyder/plugins/editor.py:149 #: spyder/plugins/help.py:152 spyder/plugins/help.py:355 #: spyder/plugins/history.py:46 spyder/plugins/history.py:157 msgid "Wrap lines" msgstr "Переносить строки" #: spyder/plugins/console.py:172 spyder/plugins/editor.py:185 #: spyder/plugins/ipythonconsole.py:300 msgid "Display balloon tips" msgstr "Показывать всплывающие подсказки" #: spyder/plugins/console.py:176 spyder/plugins/editor.py:179 msgid "Automatic code completion" msgstr "Автоматическое дополнение кода" #: spyder/plugins/console.py:180 spyder/plugins/editor.py:183 msgid "Enter key selects completion" msgstr "Клавиша Ввод/Enter выбирает автодополнение" #: spyder/plugins/console.py:185 msgid "Internal console settings" msgstr "Настройки встроенной консоли" #: spyder/plugins/console.py:221 msgid "" "Spyder has encountered a problem.
Sorry for the inconvenience." "

You can automatically submit this error to our Github issues tracker." "

Note: You need a Github account for that." msgstr "" "Spyder столкнулся с проблемой.
Извиняемся за неудобства.

Вы " "можете автоматически отправить сообщение об ошибке на Github." "

Примечание:Вы должны иметь аккаунт на Github для этого." #: spyder/plugins/console.py:231 msgid "Submit to Github" msgstr "Отправить на Github" #: spyder/plugins/console.py:283 msgid "Run Python script" msgstr "Запуск скрипта Python" #: spyder/plugins/console.py:284 spyder/widgets/explorer.py:796 msgid "Python scripts" msgstr "Скрипты Python" #: spyder/plugins/console.py:329 msgid "Buffer" msgstr "Буфер" #: spyder/plugins/console.py:330 msgid "Maximum line count" msgstr "Максимальное количество строк" #: spyder/plugins/console.py:340 msgid "External editor" msgstr "Внешний редактор" #: spyder/plugins/console.py:341 msgid "External editor executable path:" msgstr "Путь запуска внешнего редактора:" #: spyder/plugins/editor.py:59 msgid "Manipulate Jupyter notebooks on the Editor" msgstr "Работает с блокнотами Jupyter в Редакторе" #: spyder/plugins/editor.py:111 msgid "Edit template for new modules" msgstr "Редактировать шаблон для новых модулей" #: spyder/plugins/editor.py:116 msgid "Show tab bar" msgstr "Показывать панель вкладок" #: spyder/plugins/editor.py:122 spyder/plugins/editor.py:199 #: spyder/plugins/help.py:151 spyder/plugins/history.py:45 #: spyder/plugins/ipythonconsole.py:332 msgid "Source code" msgstr "Исходный код" #: spyder/plugins/editor.py:123 msgid "Show line numbers" msgstr "Показывать номера строк" #: spyder/plugins/editor.py:124 spyder/plugins/editor.py:985 msgid "Show blank spaces" msgstr "Показывать отступы" #: spyder/plugins/editor.py:125 msgid "Show vertical line after" msgstr "Рисовать вертикальную линию после" #: spyder/plugins/editor.py:126 msgid "characters" msgstr "символов" #: spyder/plugins/editor.py:133 msgid "Highlight current line" msgstr "Подсвечивать текущую строку" #: spyder/plugins/editor.py:135 msgid "Highlight current cell" msgstr "Подсвечивать текущий блок" #: spyder/plugins/editor.py:137 msgid "Highlight occurrences after" msgstr "Подсвечивать вхождения слова через" #: spyder/plugins/editor.py:169 msgid "Save all files before running script" msgstr "Сохранить все файлы перед выполнением скрипта" #: spyder/plugins/editor.py:172 msgid "Run selection" msgstr "Выполнить выделение" #: spyder/plugins/editor.py:173 msgid "Maintain focus in the Editor after running cells or selections" msgstr "Сохранять фокус в Редакторе после запуска блоков или выделений" #: spyder/plugins/editor.py:176 msgid "Introspection" msgstr "Интроспекция" #: spyder/plugins/editor.py:181 msgid "Case sensitive code completion" msgstr "Чувствительное к регистру автодополнение" #: spyder/plugins/editor.py:186 msgid "Link to object definition" msgstr "Ссылка на место определения объекта" #: spyder/plugins/editor.py:188 msgid "" "If this option is enabled, clicking on an object\n" "name (left-click + Ctrl key) will go this object\n" "definition (if resolved)." msgstr "" "Если эта опция активна, при нажатии на имя объекта\n" "(левая кнопка мыши + клавиша Ctrl) произойдёт\n" "переход в место его определения (если возможно)." #: spyder/plugins/editor.py:192 msgid "" "Warning:
The Python module rope is not installed on this " "computer: calltips, code completion and go-to-definition features won't be " "available." msgstr "" "Предупреждение:
Модуль Python rope не установлен на этом " "компьютере: подсказки вызова функций, автодополнение кода и переход к " "определению будут недоступны." #: spyder/plugins/editor.py:200 msgid "Automatic insertion of parentheses, braces and brackets" msgstr "Автоматическая вставка круглых, фигурных и квадратных скобок" #: spyder/plugins/editor.py:203 msgid "Automatic insertion of closing quotes" msgstr "Автоматическая вставка закрывающих кавычек" #: spyder/plugins/editor.py:205 msgid "Automatic insertion of colons after 'for', 'if', 'def', etc" msgstr "Автоматическая вставка двоеточия после 'for', 'if', 'def' и т.п." #: spyder/plugins/editor.py:208 msgid "Automatic indentation after 'else', 'elif', etc." msgstr "Автоматическая вставка отступа после 'else', 'elif' и т.п." #: spyder/plugins/editor.py:210 msgid "Indentation characters: " msgstr "Символы отступа: " #: spyder/plugins/editor.py:211 msgid "2 spaces" msgstr "2 пробела" #: spyder/plugins/editor.py:212 msgid "3 spaces" msgstr "3 пробела" #: spyder/plugins/editor.py:213 msgid "4 spaces" msgstr "4 пробела" #: spyder/plugins/editor.py:214 msgid "5 spaces" msgstr "5 пробелов" #: spyder/plugins/editor.py:215 msgid "6 spaces" msgstr "6 пробелов" #: spyder/plugins/editor.py:216 msgid "7 spaces" msgstr "7 пробелов" #: spyder/plugins/editor.py:217 msgid "8 spaces" msgstr "8 пробелов" #: spyder/plugins/editor.py:218 msgid "Tabulations" msgstr "Табуляция" #: spyder/plugins/editor.py:219 msgid "Tab stop width:" msgstr "Ширина табуляции:" #: spyder/plugins/editor.py:219 msgid "spaces" msgstr "пробелы" #: spyder/plugins/editor.py:231 msgid "Tab always indent" msgstr "Клавиша Tab - всегда отступ" #: spyder/plugins/editor.py:233 msgid "" "If enabled, pressing Tab will always indent,\n" "even when the cursor is not at the beginning\n" "of a line (when this option is enabled, code\n" "completion may be triggered using the alternate\n" "shortcut: Ctrl+Space)" msgstr "" "Если активно, нажатие Tab будет делать отступ\n" "всегда, даже когда курсор не в начале строки\n" "(когда эта опция включена, автодополнение\n" "кода можно будет включить альтернативной\n" "комбинацией: Ctrl+Space)" #: spyder/plugins/editor.py:238 msgid "Intelligent backspace" msgstr "Умная клавиша backspace" #: spyder/plugins/editor.py:240 msgid "Automatically remove trailing spaces when saving files" msgstr "" "Автоматически удалять лишние пробелы в конце строк при сохранении файлов" #: spyder/plugins/editor.py:244 msgid "Analysis" msgstr "Анализ" #: spyder/plugins/editor.py:246 msgid "(Refer to the {} page)" msgstr "(смотреть стр. {})" #: spyder/plugins/editor.py:251 msgid "Real-time code analysis" msgstr "Анализ кода в реальном времени" #: spyder/plugins/editor.py:253 msgid "" "

If enabled, Python source code will be analyzed using pyflakes, lines " "containing errors or warnings will be highlighted.

Note: add " "analysis:ignore in a comment to ignore code analysis warnings.

" msgstr "" "

Если активно, код Python будет анализироваться с помощью pyflakes, строки " "с ошибками или предупреждениями будут подсвечены.

Примечание: " "добавьте analysis:ignore в комментарий, чтобы игнорировать " "предупреждения анализатора кода.

" #: spyder/plugins/editor.py:261 msgid "Code analysis requires pyflakes %s+" msgstr "Для анализа кода требуется pyflakes %s+" #: spyder/plugins/editor.py:263 msgid "Real-time code style analysis" msgstr "Анализ стиля кода в реальном времени" #: spyder/plugins/editor.py:265 msgid "" "

If enabled, Python source code will be analyzed using pycodestyle, lines " "that are not following PEP8 style guide will be highlighted.

Note: add analysis:ignore in a comment to ignore style analysis " "warnings.

" msgstr "" "

Если активно, код Python будет проверяться с помощью pycodestyle, строки " "не соответсвующие стилю PEP8, будут подсвечены.

Примечание: " "добавьте analysis:ignore в комментарий, чтобы игнорировать " "предупреждения анализатора стиля.

" #: spyder/plugins/editor.py:272 msgid "" "Code annotations (TODO, FIXME, XXX, HINT, TIP, @todo, HACK, BUG, " "OPTIMIZE, !!!, ???)" msgstr "" "Аннотации кода (TODO, FIXME, XXX, HINT, TIP, @todo, HACK, BUG, " "OPTIMIZE, !!!, ???)" #: spyder/plugins/editor.py:276 msgid "Perform analysis when saving file and every" msgstr "Выполнять анализ при сохранении файла и каждые" #: spyder/plugins/editor.py:280 msgid "Perform analysis only when saving file" msgstr "Выполнять анализ только при сохранении файла" #: spyder/plugins/editor.py:339 msgid "End-of-line characters" msgstr "Символы конца строки" #: spyder/plugins/editor.py:340 msgid "" "When opening a text file containing mixed end-of-line characters (this may " "raise syntax errors in the consoles on Windows platforms), Spyder may fix " "the file automatically." msgstr "" "Когда открывается текстовый файл, содержащий смешанные символы конца строки " "(это может увеличить число синтаксических ошибок в консолях на платформах " "Windows), Spyder может исправить файл автоматически." #: spyder/plugins/editor.py:346 msgid "Fix automatically and show warning message box" msgstr "Автоматически исправлять и показывать окно предупреждений" #: spyder/plugins/editor.py:357 spyder/plugins/ipythonconsole.py:573 #: spyder/plugins/variableexplorer.py:35 msgid "Display" msgstr "Отображение" #: spyder/plugins/editor.py:359 msgid "Code Introspection/Analysis" msgstr "Интроспекция/анализ кода" #: spyder/plugins/editor.py:362 msgid "Advanced settings" msgstr "Дополнительные настройки" #: spyder/plugins/editor.py:644 msgid "&New file..." msgstr "&Новый файл" #: spyder/plugins/editor.py:645 spyder/widgets/explorer.py:773 #: spyder/widgets/explorer.py:780 msgid "New file" msgstr "Новый файл" #: spyder/plugins/editor.py:654 msgid "O&pen last closed" msgstr "О&ткрыть последний закрытый" #: spyder/plugins/editor.py:655 msgid "Open last closed" msgstr "Открыть последний закрытый" #: spyder/plugins/editor.py:661 msgid "&Open..." msgstr "&Открыть" #: spyder/plugins/editor.py:662 spyder/plugins/editor.py:1870 #: spyder/plugins/editor.py:1876 msgid "Open file" msgstr "Открыть файл" #: spyder/plugins/editor.py:668 msgid "&Revert" msgstr "За&грузить заново" #: spyder/plugins/editor.py:669 msgid "Revert file from disk" msgstr "Загрузить файл с диска" #: spyder/plugins/editor.py:672 msgid "&Save" msgstr "&Сохранить" #: spyder/plugins/editor.py:673 spyder/widgets/editor.py:1681 msgid "Save file" msgstr "Сохранить файл" #: spyder/plugins/editor.py:679 msgid "Sav&e all" msgstr "Сохранить &все" #: spyder/plugins/editor.py:680 msgid "Save all files" msgstr "Сохранить все файлы" #: spyder/plugins/editor.py:686 msgid "Save &as..." msgstr "Сохранить &как..." #: spyder/plugins/editor.py:687 msgid "Save current file as..." msgstr "Сохранить текущий файл как..." #: spyder/plugins/editor.py:692 msgid "Save copy as..." msgstr "Сохранить копию..." #: spyder/plugins/editor.py:693 msgid "Save copy of current file as..." msgstr "Сохранить копию текущего файла как..." #: spyder/plugins/editor.py:696 spyder/plugins/editor.py:697 msgid "Print preview..." msgstr "Предварительный просмотр..." #: spyder/plugins/editor.py:698 msgid "&Print..." msgstr "&Печать" #: spyder/plugins/editor.py:699 msgid "Print current file..." msgstr "Печатать текущий файл" #: spyder/plugins/editor.py:702 msgid "&Close" msgstr "&Закрыть" #: spyder/plugins/editor.py:703 msgid "Close current file" msgstr "Закрыть текущий файл" #: spyder/plugins/editor.py:706 msgid "C&lose all" msgstr "Закрыть вс&е" #: spyder/plugins/editor.py:707 msgid "Close all opened files" msgstr "Закрыть все открытые файлы" #: spyder/plugins/editor.py:714 msgid "&Find text" msgstr "&Найти текст" #: spyder/plugins/editor.py:720 msgid "Find &next" msgstr "Найти &следующий" #: spyder/plugins/editor.py:726 msgid "Find &previous" msgstr "Найти &предыдущий" #: spyder/plugins/editor.py:732 msgid "&Replace text" msgstr "&Заменить текст" #: spyder/plugins/editor.py:741 msgid "Set/Clear breakpoint" msgstr "Поставить/Убрать точку останова" #: spyder/plugins/editor.py:748 msgid "Set/Edit conditional breakpoint" msgstr "Поставить/Редактировать условную точку останова" #: spyder/plugins/editor.py:755 msgid "Clear breakpoints in all files" msgstr "Очистить точки останова во всех файлах" #: spyder/plugins/editor.py:757 msgid "Debug with winpdb" msgstr "Отладка с помощью winpdb" #: spyder/plugins/editor.py:764 msgid "Debug file" msgstr "Отладка файла" #: spyder/plugins/editor.py:769 msgid "Step" msgstr "Шаг" #: spyder/plugins/editor.py:770 msgid "Run current line" msgstr "Выполнить текущую строку" #: spyder/plugins/editor.py:775 msgid "Continue" msgstr "Продолжить" #: spyder/plugins/editor.py:777 msgid "Continue execution until next breakpoint" msgstr "Продолжить выполнение до следующей точки останова" #: spyder/plugins/editor.py:782 msgid "Step Into" msgstr "Шаг в функцию" #: spyder/plugins/editor.py:784 msgid "Step into function or method of current line" msgstr "Войти в функцию или метод текущей линии" #: spyder/plugins/editor.py:789 msgid "Step Return" msgstr "Шаг из функции" #: spyder/plugins/editor.py:791 msgid "Run until current function or method returns" msgstr "Выполнять пока функция или метод не завершатся" #: spyder/plugins/editor.py:796 spyder/widgets/findinfiles.py:281 #: spyder/widgets/ipythonconsole/client.py:357 msgid "Stop" msgstr "Стоп" #: spyder/plugins/editor.py:797 msgid "Stop debugging" msgstr "Завершить отладку" #: spyder/plugins/editor.py:804 msgid "Run file" msgstr "Выполнить файл" #: spyder/plugins/editor.py:809 msgid "&Configuration per file..." msgstr "&Настройки для файла..." #: spyder/plugins/editor.py:811 msgid "Run settings" msgstr "Настройки Запуска" #: spyder/plugins/editor.py:817 msgid "Re-run &last script" msgstr "Перезапустить последний скрипт" #: spyder/plugins/editor.py:819 msgid "Run again last file" msgstr "Выполнить снова последний файл" #: spyder/plugins/editor.py:825 spyder/widgets/sourcecode/codeeditor.py:2708 msgid "Run &selection or current line" msgstr "Выполнить в&ыделенное или текущую строку" #: spyder/plugins/editor.py:828 msgid "Run selection or current line" msgstr "Выполнить выделенное или текущую строку" #: spyder/plugins/editor.py:836 spyder/widgets/sourcecode/codeeditor.py:2696 msgid "Run cell" msgstr "Выполнить &блок" #: spyder/plugins/editor.py:839 msgid "" "Run current cell (Ctrl+Enter)\n" "[Use #%% to create cells]" msgstr "" "Выполнить текущий блок (Ctrl+Enter)\n" "[Используйте #%% для создания блоков]" #: spyder/plugins/editor.py:845 spyder/widgets/sourcecode/codeeditor.py:2700 msgid "Run cell and advance" msgstr "Выполнить блок и перейти далее" #: spyder/plugins/editor.py:848 msgid "Run current cell and go to the next one (Shift+Enter)" msgstr "Выполнить текущий блок и перейти к следующему (Shift+Enter)" #: spyder/plugins/editor.py:854 spyder/widgets/sourcecode/codeeditor.py:2704 msgid "Re-run last cell" msgstr "Перезапустить последний блок" #: spyder/plugins/editor.py:855 msgid "Re run last cell " msgstr "Перезапустить последний блок" #: spyder/plugins/editor.py:865 msgid "Show todo list" msgstr "Показать список задач" #: spyder/plugins/editor.py:866 msgid "" "Show comments list (TODO/FIXME/XXX/HINT/TIP/@todo/HACK/BUG/OPTIMIZE/!!!/???)" msgstr "" "Показать список комментариев (TODO/FIXME/XXX/HINT/TIP/@todo/HACK/BUG/" "OPTIMIZE/!!!/???)" #: spyder/plugins/editor.py:874 msgid "Show warning/error list" msgstr "Показать список предупреждений/ошибок" #: spyder/plugins/editor.py:875 msgid "Show code analysis warnings/errors" msgstr "Показать предупреждения/ошибки анализа кода" #: spyder/plugins/editor.py:881 msgid "Previous warning/error" msgstr "Предыдущее предупреждение/ошибка" #: spyder/plugins/editor.py:882 msgid "Go to previous code analysis warning/error" msgstr "Перейти к предыдущему предупреждению/ошибке анализа кода" #: spyder/plugins/editor.py:885 msgid "Next warning/error" msgstr "Следующее предупреждение/ошибка" #: spyder/plugins/editor.py:886 msgid "Go to next code analysis warning/error" msgstr "Перейти к следующему предупреждению/ошибке анализа кода" #: spyder/plugins/editor.py:890 msgid "Last edit location" msgstr "Последнее место редактирования" #: spyder/plugins/editor.py:891 msgid "Go to last edit location" msgstr "Перейти к последнему месту редактирования" #: spyder/plugins/editor.py:899 msgid "Previous cursor position" msgstr "Предыдущая позиция курсора" #: spyder/plugins/editor.py:900 msgid "Go to previous cursor position" msgstr "Перейти к предыдущей позиции курсора" #: spyder/plugins/editor.py:908 msgid "Next cursor position" msgstr "Следующая позиция курсора" #: spyder/plugins/editor.py:909 msgid "Go to next cursor position" msgstr "Перейти к следующей позиции курсора" #: spyder/plugins/editor.py:919 spyder/widgets/sourcecode/codeeditor.py:2680 msgid "Comment" msgstr "Комментировать" #: spyder/plugins/editor.py:919 spyder/widgets/sourcecode/codeeditor.py:2680 msgid "Uncomment" msgstr "Раскомментировать" #: spyder/plugins/editor.py:920 msgid "Comment current line or selection" msgstr "Комментировать текущую строку/выделение" #: spyder/plugins/editor.py:924 msgid "Add &block comment" msgstr "Добавить &блок комментариев" #: spyder/plugins/editor.py:925 msgid "Add block comment around current line or selection" msgstr "Добавить блок комментариев вокруг текущей строки/выделения" #: spyder/plugins/editor.py:931 msgid "R&emove block comment" msgstr "У&далить блок комментариев" #: spyder/plugins/editor.py:932 msgid "Remove comment block around current line or selection" msgstr "Убрать блок комментариев вокруг текущей строки/выделения" #: spyder/plugins/editor.py:943 msgid "Indent" msgstr "Добавить отступ" #: spyder/plugins/editor.py:944 msgid "Indent current line or selection" msgstr "Добавить отступ к текущей строке или выделению" #: spyder/plugins/editor.py:947 msgid "Unindent" msgstr "Убрать отступ" #: spyder/plugins/editor.py:948 msgid "Unindent current line or selection" msgstr "Убрать отступ у текущей строки/выделения" #: spyder/plugins/editor.py:952 msgid "Toggle Uppercase" msgstr "Сделать Прописными" #: spyder/plugins/editor.py:953 msgid "Change to uppercase current line or selection" msgstr "Перевести текущую строчку или выделение в верхний регистр" #: spyder/plugins/editor.py:959 msgid "Toggle Lowercase" msgstr "Сделать строчными" #: spyder/plugins/editor.py:960 msgid "Change to lowercase current line or selection" msgstr "Перевести текущую строчку или выделение в нижний регистр" #: spyder/plugins/editor.py:967 msgid "Carriage return and line feed (Windows)" msgstr "Возврат каретки и перевод строки (Windows)" #: spyder/plugins/editor.py:970 msgid "Line feed (UNIX)" msgstr "Перевод строки (UNIX)" #: spyder/plugins/editor.py:973 msgid "Carriage return (Mac)" msgstr "Возврат каретки (Mac)" #: spyder/plugins/editor.py:979 msgid "Convert end-of-line characters" msgstr "Преобразовать символы конца строки" #: spyder/plugins/editor.py:983 msgid "Remove trailing spaces" msgstr "Удалить лишние пробелы в конце строк" #: spyder/plugins/editor.py:987 msgid "Fix indentation" msgstr "Исправить отступы" #: spyder/plugins/editor.py:988 msgid "Replace tab characters by space characters" msgstr "Заменить символы табуляции пробелами" #: spyder/plugins/editor.py:991 msgid "Go to line..." msgstr "Перейти к строке..." #: spyder/plugins/editor.py:999 msgid "Set console working directory" msgstr "Установить рабочий каталог консоли" #: spyder/plugins/editor.py:1001 msgid "" "Set current console (and file explorer) working directory to current script " "directory" msgstr "" "Установить каталог текущего скрипта как рабочий для текущей консоли (и " "файлового менеджера) " #: spyder/plugins/editor.py:1006 msgid "Maximum number of recent files..." msgstr "Максимальное количество недавних файлов..." #: spyder/plugins/editor.py:1009 msgid "Clear recent files list" msgstr "Очистить список недавних файлов" #: spyder/plugins/editor.py:1009 spyder/plugins/projects.py:102 msgid "Clear this list" msgstr "Очистить этот список" #: spyder/plugins/editor.py:1013 msgid "Open &recent" msgstr "Открыть не&давние" #: spyder/plugins/editor.py:1678 msgid "Spyder Editor" msgstr "Редактор Spyder" #: spyder/plugins/editor.py:1679 msgid "This is a temporary script file." msgstr "Это временный скриптовый файл." #: spyder/plugins/editor.py:1748 msgid "untitled" msgstr "untitled" #: spyder/plugins/editor.py:1820 msgid "Maximum number of recent files" msgstr "Максимальное количество недавних файлов" #: spyder/plugins/editor.py:1966 msgid "Printing..." msgstr "Печать..." #: spyder/plugins/explorer.py:54 msgid "File explorer" msgstr "Файловый менеджер" #: spyder/plugins/findinfiles.py:119 spyder/widgets/findinfiles.py:829 msgid "Find in files" msgstr "Найти в файлах" #: spyder/plugins/findinfiles.py:143 msgid "&Find in files" msgstr "Найти в &файлах" #: spyder/plugins/findinfiles.py:146 msgid "Search text in multiple files" msgstr "Искать текст в нескольких файлах" #: spyder/plugins/help.py:43 msgid "Show help for objects in the Editor and Consoles in a dedicated pane" msgstr "" "Показывать справку об объектах в Редакторе и Консолях в специальной панели" #: spyder/plugins/help.py:109 msgid "Automatic connections" msgstr "Автоматические соединения" #: spyder/plugins/help.py:110 msgid "" "This pane can automatically show an object's help information after a left " "parenthesis is written next to it. Below you can decide to which plugin you " "want to connect it to turn on this feature." msgstr "" "Инспектор объектов может автоматически показывать справочную информацию по " "объекту после ввода открывающей круглой скобки вслед за ним. Ниже вы можете " "решить, в каком модуле использовать эту возможность." #: spyder/plugins/help.py:122 msgid "" "This feature requires the Rope or Jedi libraries.\n" "It seems you don't have either installed." msgstr "" "Эта функция требует библиотеки Rope или Jedi.\n" "Похоже, Вы их не установили." #: spyder/plugins/help.py:125 msgid "IPython Console" msgstr "Консоль IPython" #: spyder/plugins/help.py:135 msgid "Additional features" msgstr "Дополнительные возможности" #: spyder/plugins/help.py:136 msgid "Render mathematical equations" msgstr "Отрисовывать математические выражения" #: spyder/plugins/help.py:142 msgid "This feature requires Sphinx 1.1 or superior." msgstr "Эта возможность требует Sphinx 1.1 или выше." #: spyder/plugins/help.py:143 msgid "Sphinx %s is currently installed." msgstr "Sphinx %s на данный момент установлено." #: spyder/plugins/help.py:304 msgid "No further documentation available" msgstr "Дополнительная документация отсутствует" #: spyder/plugins/help.py:342 msgid "No documentation available" msgstr "Дополнительная документация отсутствует" #: spyder/plugins/help.py:373 msgid "Source" msgstr "Исходник" #: spyder/plugins/help.py:380 spyder/plugins/runconfig.py:170 #: spyder/plugins/runconfig.py:486 spyder/widgets/ipythonconsole/client.py:291 msgid "Console" msgstr "Консоль" #: spyder/plugins/help.py:388 msgid "Object" msgstr "Объект" #: spyder/plugins/help.py:402 msgid "Plain Text" msgstr "Простой текст" #: spyder/plugins/help.py:406 msgid "Show Source" msgstr "Показать исходник" #: spyder/plugins/help.py:410 msgid "Rich Text" msgstr "Форматированный текст" #: spyder/plugins/help.py:420 msgid "Automatic import" msgstr "Автоматический импорт" #: spyder/plugins/help.py:432 spyder/plugins/history.py:106 #: spyder/widgets/editor.py:720 spyder/widgets/explorer.py:1187 #: spyder/widgets/ipythonconsole/client.py:381 #: spyder/widgets/variableexplorer/namespacebrowser.py:148 msgid "Options" msgstr "Опции" #: spyder/plugins/help.py:687 msgid "" "Here you can get help of any object by pressing %s in front of it, either on " "the Editor or the Console.%sHelp can also be shown automatically after " "writing a left parenthesis next to an object. You can activate this behavior " "in %s." msgstr "" "Здесь Вы можете получить справку по любому объекту, наведя текстовый курсор " "на него и нажав %s, как в Редакторе, так и в Консоли.%sСправка также может " "автоматически показываться при вводе открывающей круглой скобки после " "объекта. Вы можете активировать эту возможность в %s." #: spyder/plugins/help.py:693 msgid "Preferences > Help" msgstr "Параметры > Справка" #: spyder/plugins/help.py:700 msgid "Usage" msgstr "Использование" #: spyder/plugins/help.py:701 msgid "New to Spyder? Read our" msgstr "Используете Spyder впервые? Прочитайте наше" #: spyder/plugins/help.py:702 msgid "tutorial" msgstr "руководство" #: spyder/plugins/help.py:709 msgid "" "Please consider installing Sphinx to get documentation rendered in rich text." msgstr "" "Пожалуйста, подумайте об установке Sphinx для просмотра документации в " "форматированном виде." #: spyder/plugins/help.py:878 msgid "Lock" msgstr "Заблокировать" #: spyder/plugins/help.py:878 msgid "Unlock" msgstr "Разблокировать" #: spyder/plugins/help.py:922 msgid "" "The following error occured when calling Sphinx %s.
Incompatible " "Sphinx version or doc string decoding failed.

Error message:
%s" msgstr "" "Следующая ошибка появляется при вызове Sphinx %s.
Несовместимая " "версия Sphinx или ошибка декодирования строки документации.

Сообщение " "об ошибке:
%s" #: spyder/plugins/help.py:966 msgid "No source code available." msgstr "Исходный код не доступен." #: spyder/plugins/history.py:39 msgid "Settings" msgstr "Настройки" #: spyder/plugins/history.py:41 msgid " entries" msgstr " записей" #: spyder/plugins/history.py:41 msgid "History depth: " msgstr "Глубина истории: " #: spyder/plugins/history.py:48 msgid "Scroll automatically to last entry" msgstr "Автоматически пролистывать к последней записи" #: spyder/plugins/history.py:126 msgid "History log" msgstr "Журнал истории" #: spyder/plugins/history.py:153 msgid "History..." msgstr "История..." #: spyder/plugins/history.py:155 msgid "Set history maximum entries" msgstr "Установить максимум записей истории" #: spyder/plugins/history.py:260 msgid "History" msgstr "История" #: spyder/plugins/history.py:261 msgid "Maximum entries" msgstr "Максимум записей" #: spyder/plugins/ipythonconsole.py:65 msgid "Symbolic mathematics in the IPython Console" msgstr "Символьная математика в консоли Python" #: spyder/plugins/ipythonconsole.py:69 msgid "Run Cython files in the IPython Console" msgstr "Запустить файлы Cython в консоли IPython" #: spyder/plugins/ipythonconsole.py:73 msgid "Integrate the IPython console" msgstr "Интегрирует консоли IPython" #: spyder/plugins/ipythonconsole.py:77 msgid "IPython interactive python environment" msgstr "IPython, интерактивная оболочка для python" #: spyder/plugins/ipythonconsole.py:128 msgid "" "The authenticity of host %s can't be established. Are you sure you " "want to continue connecting?" msgstr "" "Подлинность хоста %s не может быть установлена. Вы уверены, что " "хотите продолжить соединение?" #: spyder/plugins/ipythonconsole.py:140 msgid "The authenticity of the host can't be established" msgstr "Подлинность хоста не может быть установлена" #: spyder/plugins/ipythonconsole.py:147 msgid "Tunnel '%s' failed to start" msgstr "Туннель '%s' не удалось запустить" #: spyder/plugins/ipythonconsole.py:152 msgid "Could not connect to remote host" msgstr "Не удалось подключиться к удалённому хосту" #: spyder/plugins/ipythonconsole.py:169 spyder/plugins/ipythonconsole.py:799 msgid "Connect to an existing kernel" msgstr "Подключиться к работающему ядру" #: spyder/plugins/ipythonconsole.py:171 msgid "" "Please enter the connection info of the kernel you want to connect to. For " "that you can either select its JSON connection file using the Browse button, or write directly its id, in case it's a local kernel (for " "example kernel-3764.json or just 3764)." msgstr "" "Пожалуйста, введите информацию о соединении для ядра, к которому пытаетесь " "подключиться. Для этого либо выберите JSON-файл соединения кнопкой " "Обзор, либо, если ядро локальное, введите его id (напр. " "kernel-3764.json или просто 3764)." #: spyder/plugins/ipythonconsole.py:182 msgid "Connection info:" msgstr "Информация о соединении:" #: spyder/plugins/ipythonconsole.py:184 msgid "Path to connection file or kernel id" msgstr "Путь к файлу соединения или id ядра" #: spyder/plugins/ipythonconsole.py:186 spyder/plugins/ipythonconsole.py:203 msgid "Browse" msgstr "Обзор" #: spyder/plugins/ipythonconsole.py:195 msgid "This is a remote kernel" msgstr "Это удалённо-управляемое ядро" #: spyder/plugins/ipythonconsole.py:199 msgid "username@hostname:port" msgstr "username@hostname:port" #: spyder/plugins/ipythonconsole.py:202 msgid "Path to ssh key file" msgstr "Путь к ключу ssh" #: spyder/plugins/ipythonconsole.py:211 msgid "Password or ssh key passphrase" msgstr "Пароль или кодовая фраза ключа ssh" #: spyder/plugins/ipythonconsole.py:215 msgid "Host name" msgstr "Имя хоста" #: spyder/plugins/ipythonconsole.py:216 msgid "Ssh key" msgstr "Ключ ssh" #: spyder/plugins/ipythonconsole.py:217 msgid "Password" msgstr "Пароль" #: spyder/plugins/ipythonconsole.py:246 msgid "Open connection file" msgstr "Открыть файл соединения IPython" #: spyder/plugins/ipythonconsole.py:251 msgid "Select ssh key" msgstr "Выберите ключ ssh" #: spyder/plugins/ipythonconsole.py:284 spyder/plugins/ipythonconsole.py:734 msgid "IPython console" msgstr "Консоль IPython" #: spyder/plugins/ipythonconsole.py:291 msgid "Display initial banner" msgstr "Показывать стартовый баннер" #: spyder/plugins/ipythonconsole.py:292 msgid "" "This option lets you hide the message shown at\n" "the top of the console when it's opened." msgstr "" "Эта опция позволяет Вам спрятать сообщение,\n" "показываемое вверху консоли при открытии." #: spyder/plugins/ipythonconsole.py:294 msgid "Use a pager to display additional text inside the console" msgstr "" "Использовать постраничный вывод для показа дополнительного текста в консоли" #: spyder/plugins/ipythonconsole.py:296 msgid "" "Useful if you don't want to fill the console with long help or completion " "texts.\n" "Note: Use the Q key to get out of the pager." msgstr "" "Полезно, если Вы не хотите захламлять консоль длинной справкой или сплошным " "текстом.\n" "Примечание: Используйте клавишу Q для выхода из постраничного вывода." #: spyder/plugins/ipythonconsole.py:301 msgid "Ask for confirmation before closing" msgstr "Спрашивать подтверждение перед закрытием" #: spyder/plugins/ipythonconsole.py:304 msgid "Ask for confirmation before removing all user-defined variables" msgstr "" "Спрашивать подтверждение перед удалением всех пользовательских переменных" #: spyder/plugins/ipythonconsole.py:307 msgid "" "This option lets you hide the warning message shown\n" "when resetting the namespace from Spyder." msgstr "" "Эта опция позволяет Вам спрятать сообщение,\n" "показываемое при перезапуске окружения Spyder." #: spyder/plugins/ipythonconsole.py:309 #: spyder/widgets/ipythonconsole/client.py:320 msgid "Show elapsed time" msgstr "Показывать прошедшее время" #: spyder/plugins/ipythonconsole.py:320 msgid "Completion Type" msgstr "Тип автодополнения" #: spyder/plugins/ipythonconsole.py:321 msgid "Decide what type of completion to use" msgstr "Выберите какой тип автодополнения использовать" #: spyder/plugins/ipythonconsole.py:323 msgid "Graphical" msgstr "Графический" #: spyder/plugins/ipythonconsole.py:323 msgid "Plain" msgstr "Простой" #: spyder/plugins/ipythonconsole.py:323 msgid "Terminal" msgstr "Терминал" #: spyder/plugins/ipythonconsole.py:324 msgid "Completion:" msgstr "Автодополнение:" #: spyder/plugins/ipythonconsole.py:334 msgid " lines" msgstr " строк" #: spyder/plugins/ipythonconsole.py:334 msgid "Buffer: " msgstr "Буфер: " #: spyder/plugins/ipythonconsole.py:336 msgid "" "Set the maximum number of lines of text shown in the\n" "console before truncation. Specifying -1 disables it\n" "(not recommended!)" msgstr "" "Установите максимальное количество линий, показываемых\n" "в консоли перед усечением. Значение -1 отключает функцию\n" "(не рекомендуется!)" #: spyder/plugins/ipythonconsole.py:345 msgid "Support for graphics (Matplotlib)" msgstr "Поддержка графики (Matplotlib)" #: spyder/plugins/ipythonconsole.py:346 msgid "Activate support" msgstr "Активировать поддержку" #: spyder/plugins/ipythonconsole.py:347 msgid "Automatically load Pylab and NumPy modules" msgstr "Автоматически загружать модули Pylab и NumPy" #: spyder/plugins/ipythonconsole.py:350 msgid "" "This lets you load graphics support without importing \n" "the commands to do plots. Useful to work with other\n" "plotting libraries different to Matplotlib or to develop \n" "GUIs with Spyder." msgstr "" "Это позволит загружать поддержку графики без импорта\n" "команд построения графиков. Полезно для работы с\n" "графическими библиотеками, отличными от Matplotlib или\n" "разработки GUI в Spyder." #: spyder/plugins/ipythonconsole.py:365 msgid "Inline" msgstr "Встроенный" #: spyder/plugins/ipythonconsole.py:366 msgid "Automatic" msgstr "Автоматически" #: spyder/plugins/ipythonconsole.py:367 msgid "Graphics backend" msgstr "Графический бэкенд" #: spyder/plugins/ipythonconsole.py:368 msgid "" "Decide how graphics are going to be displayed in the console. If unsure, " "please select %s to put graphics inside the console or %s to " "interact with them (through zooming and panning) in a separate window." msgstr "" "Выберите как графика будет отображаться в консоли. Если не уверены, " "пожалуйста выберите %s для вставки графики в консоль или %s " "для взаимодействия с ними (через масштабирование и панорамирование) в " "отдельном окне." #: spyder/plugins/ipythonconsole.py:388 msgid "Backend:" msgstr "Бэкенд:" #: spyder/plugins/ipythonconsole.py:390 msgid "This option will be applied the next time a console is opened." msgstr "Эта опция будет принята при следующем открытии консоли." #: spyder/plugins/ipythonconsole.py:401 msgid "Inline backend" msgstr "Встроенный бекэнд" #: spyder/plugins/ipythonconsole.py:402 msgid "Decide how to render the figures created by this backend" msgstr "Выберите как рендерить графики, созданные этим бэкендом" #: spyder/plugins/ipythonconsole.py:406 msgid "Format:" msgstr "Формат:" #: spyder/plugins/ipythonconsole.py:409 msgid "Resolution:" msgstr "Разрешение:" #: spyder/plugins/ipythonconsole.py:409 msgid "dpi" msgstr "dpi" #: spyder/plugins/ipythonconsole.py:411 msgid "Only used when the format is PNG. Default is 72" msgstr "Используется только для формата PNG. 72 по умолчанию" #: spyder/plugins/ipythonconsole.py:414 msgid "Width:" msgstr "Ширина:" #: spyder/plugins/ipythonconsole.py:414 spyder/plugins/ipythonconsole.py:418 msgid "inches" msgstr "дюймов" #: spyder/plugins/ipythonconsole.py:416 msgid "Default is 6" msgstr "6 по умолчанию" #: spyder/plugins/ipythonconsole.py:418 msgid "Height:" msgstr "Высота:" #: spyder/plugins/ipythonconsole.py:420 msgid "Default is 4" msgstr "4 по умолчанию" #: spyder/plugins/ipythonconsole.py:447 msgid "" "You can run several lines of code when a console is started. Please " "introduce each one separated by commas, for example:
import os, import " "sys" msgstr "" "Вы можете выполнить несколько строк кода при запуске консоли. Пожалуйста, " "введите их через запятую, например:
import os, import sys" #: spyder/plugins/ipythonconsole.py:453 msgid "Lines:" msgstr "Строки:" #: spyder/plugins/ipythonconsole.py:462 msgid "Run a file" msgstr "Выполнить файл" #: spyder/plugins/ipythonconsole.py:463 msgid "" "You can also run a whole file at startup instead of just some lines (This is " "similar to have a PYTHONSTARTUP file)." msgstr "" "При старте Вы также можете запустить весь файл вместо нескольких строк " "(Подобно использованию файла PYTHONSTARTUP)." #: spyder/plugins/ipythonconsole.py:467 msgid "Use the following file:" msgstr "Использовать следующий файл:" #: spyder/plugins/ipythonconsole.py:481 msgid "Greedy completion" msgstr "Скупое автодополнение" #: spyder/plugins/ipythonconsole.py:482 msgid "" "Enable Tab completion on elements of lists, results of function " "calls, etc, without assigning them to a variable.
For example, you " "can get completions on things like li[0].<Tab> or ins." "meth().<Tab>" msgstr "" "Включает автодополнение по Tab для элементов списков, результатов " "вызова функций, и т.п. без присвоения их переменной.
Например, Вы " "можете сделать автодополнение для таких вещей, как li[0].<Tab> или ins.meth().<Tab>" #: spyder/plugins/ipythonconsole.py:490 msgid "Use the greedy completer" msgstr "Включить скупое автодополнение" #: spyder/plugins/ipythonconsole.py:501 msgid "Autocall" msgstr "Автовызов" #: spyder/plugins/ipythonconsole.py:502 msgid "" "Autocall makes IPython automatically call any callable object even if you " "didn't type explicit parentheses.
For example, if you type str 43 " "it becomes str(43) automatically." msgstr "" "Автовызов позволяет IPython автоматически вызывать объекты без явного ввода " "скобок.
Например, если Вы введете str 43, будет выполнено " "str(43) автоматически." #: spyder/plugins/ipythonconsole.py:509 msgid "Smart" msgstr "Умный" #: spyder/plugins/ipythonconsole.py:510 msgid "Full" msgstr "Все" #: spyder/plugins/ipythonconsole.py:511 msgid "Off" msgstr "Отключён" #: spyder/plugins/ipythonconsole.py:513 msgid "Autocall: " msgstr "Автовызов: " #: spyder/plugins/ipythonconsole.py:514 msgid "" "On %s mode, Autocall is not applied if there are no arguments after " "the callable. On %s mode, all callable objects are automatically " "called (even if no arguments are present)." msgstr "" "В режиме %s Автовызов не происходит если отсутствуют аргументы у " "вызываемого. В режиме %s все вызываемые объекты вызываются (даже если " "аргументы не переданы)." #: spyder/plugins/ipythonconsole.py:526 msgid "Symbolic Mathematics" msgstr "Символьная математика" #: spyder/plugins/ipythonconsole.py:527 msgid "" "Perfom symbolic operations in the console (e.g. integrals, derivatives, " "vector calculus, etc) and get the outputs in a beautifully printed style (it " "requires the Sympy module)." msgstr "" "Производит символьные операции в консоли (напр. интегралы, производные, " "векторное исчисление и др.) и выводит результат в красивом виде (требуется " "модуль Sympy)." #: spyder/plugins/ipythonconsole.py:532 msgid "Use symbolic math" msgstr "Использовать символьную математику" #: spyder/plugins/ipythonconsole.py:533 msgid "" "This option loads the Sympy library to work with.
Please refer to its " "documentation to learn how to use it." msgstr "" "Эта опция подгружает для работы библиотеку Sympy.
Пожалуйста ознакомьтесь " "с документацией для её использования." #: spyder/plugins/ipythonconsole.py:543 msgid "Prompts" msgstr "Приглашения к вводу/выводу" #: spyder/plugins/ipythonconsole.py:544 msgid "Modify how Input and Output prompts are shown in the console." msgstr "Определите как показывать приглашения Ввода и Вывода в консоли." #: spyder/plugins/ipythonconsole.py:547 msgid "Input prompt:" msgstr "Строка ввода:" #: spyder/plugins/ipythonconsole.py:549 msgid "" "Default is
In [<span class=\"in-prompt-number\">%i</span>]:" msgstr "" "По умолчанию:
In [<span class=\"in-prompt-number\">%i</" "span>]:" #: spyder/plugins/ipythonconsole.py:553 msgid "Output prompt:" msgstr "Строка вывода:" #: spyder/plugins/ipythonconsole.py:555 msgid "" "Default is
Out[<span class=\"out-prompt-number\">%i</span>]:" msgstr "" "По умолчанию:
Out [<span class=\"out-prompt-number\">%i</" "span>]:" #: spyder/plugins/ipythonconsole.py:575 msgid "Graphics" msgstr "Графика" #: spyder/plugins/ipythonconsole.py:577 msgid "Startup" msgstr "Запуск" #: spyder/plugins/ipythonconsole.py:604 msgid "" "The directory {} is not writable and it is required to create IPython " "consoles. Please make it writable." msgstr "" "Каталог {} защищен от записи. Для запуска консоли IPython, пожалуйста, " "откройте доступ на запись." #: spyder/plugins/ipythonconsole.py:784 msgid "Open an &IPython console" msgstr "Открыть консоль &IPython" #: spyder/plugins/ipythonconsole.py:791 msgid "Restart kernel" msgstr "Перезапустить ядро" #: spyder/plugins/ipythonconsole.py:800 msgid "Open a new IPython console connected to an existing kernel" msgstr "Открыть новую консоль IPython, подключенную к существующему ядру" #: spyder/plugins/ipythonconsole.py:803 msgid "Rename tab" msgstr "Переименовать вкладку" #: spyder/plugins/ipythonconsole.py:928 msgid "" "No IPython console is currently available to run %s.

Please " "open a new one and try again." msgstr "" "Сейчас нет доступных консолей IPython для запуска %s." "

Пожалуйста, откройте новую и попытайтесь снова." #: spyder/plugins/ipythonconsole.py:1018 msgid "" "Your Python environment or installation doesn't have the ipykernel " "and cloudpickle modules installed on it. Without these modules is " "not possible for Spyder to create a console for you.

You can install " "them by running in a system terminal:

pip install ipykernel " "cloudpickle

or

conda install ipykernel cloudpickle" msgstr "" "В вашем Python окружении или инсталяции не установлены модули ipykernel и cloudpickle. Без этих модулей Spyder не может создать консоль " "для Вас.

Вы можете установить их, запустив в терминале команду: " "

pip install ipykernel cloudpickle

или

conda install ipykernel cloudpickle" #: spyder/plugins/ipythonconsole.py:1295 msgid "Do you want to close this console?" msgstr "Вы уверены, что хотите закрыть эту консоль?" #: spyder/plugins/ipythonconsole.py:1301 msgid "" "Do you want to close all other consoles connected to the same kernel as this " "one?" msgstr "Хотите закрыть все другие консоли, подключённые к тому же ядру?" #: spyder/plugins/ipythonconsole.py:1366 msgid "" "It was not possible to restart the IPython console when switching to this " "project. The error was {0}" msgstr "" "Не удалось перезапустить консоль IPython при переключении в этот проект. " "Ошибка: {0}" #: spyder/plugins/ipythonconsole.py:1467 msgid "" "This error was most probably caused by installing Spyder in a directory with " "non-ascii characters (i.e. characters with tildes, apostrophes or non-latin " "symbols).

To fix it, please reinstall Spyder in a different " "location." msgstr "" "Эта ошибка скорее всего произошла из-за установки Spyder в каталог, " "содержащий non-ascii символы (тильды, апострофы, не латинские символы и т." "п.).

Для исправления переустановите Spyder в другой каталог." #: spyder/plugins/ipythonconsole.py:1659 msgid "IPython" msgstr "IPython" #: spyder/plugins/ipythonconsole.py:1660 msgid "Unable to connect to %s" msgstr "Не удалось подключиться к %s" #: spyder/plugins/ipythonconsole.py:1730 msgid "Connection error" msgstr "Ошибка соединения" #: spyder/plugins/ipythonconsole.py:1731 msgid "" "Could not open ssh tunnel. The error was:\n" "\n" msgstr "" "Не удалось открыть ssh-туннель. Произошла ошибка:\n" "\n" #: spyder/plugins/layoutdialog.py:177 msgid "Move Up" msgstr "Вверх" #: spyder/plugins/layoutdialog.py:178 msgid "Move Down" msgstr "Вниз" #: spyder/plugins/layoutdialog.py:179 msgid "Delete Layout" msgstr "Удалить" #: spyder/plugins/layoutdialog.py:183 msgid "Layout Display and Order" msgstr "Показывать и Выбирать компоновку" #: spyder/plugins/maininterpreter.py:31 spyder/plugins/maininterpreter.py:66 msgid "Python interpreter" msgstr "Интепретатор Python" #: spyder/plugins/maininterpreter.py:68 msgid "Select the Python interpreter for all Spyder consoles" msgstr "" "Выберите исполняемый файл интерпретатора Python\n" "для всех консолей Spyder" #: spyder/plugins/maininterpreter.py:71 msgid "Default (i.e. the same as Spyder's)" msgstr "По умолчанию (тот же, что для Spyder)" #: spyder/plugins/maininterpreter.py:74 msgid "Use the following Python interpreter:" msgstr "Использовать следующий интепретатор Python:" #: spyder/plugins/maininterpreter.py:77 msgid "Executables" msgstr "Исполняемые файлы" #: spyder/plugins/maininterpreter.py:94 msgid "User Module Reloader (UMR)" msgstr "Перезагрузка модулей пользователя (UMR)" #: spyder/plugins/maininterpreter.py:95 msgid "" "UMR forces Python to reload modules which were imported when executing a " "file in a Python or IPython console with the runfile function." msgstr "" "UMR заставляет Python перезагружать модули, импортированные при выполнении " "скрипта во внешней консоли функцией runfile." #: spyder/plugins/maininterpreter.py:100 msgid "Enable UMR" msgstr "Включить UMR" #: spyder/plugins/maininterpreter.py:101 msgid "" "This option will enable the User Module Reloader (UMR) in Python/IPython " "consoles. UMR forces Python to reload deeply modules during import when " "running a Python script using the Spyder's builtin function runfile." "

1. UMR may require to restart the console in which it will be " "called (otherwise only newly imported modules will be reloaded when " "executing files).

2. If errors occur when re-running a PyQt-" "based program, please check that the Qt objects are properly destroyed (e.g. " "you may have to use the attribute Qt.WA_DeleteOnClose on your main " "window, using the setAttribute method)" msgstr "" "Эта опция включает Перезагрузчик Модулей Пользователя (UMR) в консолях " "Python/IPython. UMR заставляет Python рекурсивно перезагружать все модули " "при запуске скрипта Python встроенной функцией Spyder runfile." "

1. UMR может потребовать перезапустить консоль, в которой был " "вызван (в противном случае только вновь импортируемые модули будут " "перезагружены при выполнении скриптов).

2.Если при перезапуске " "программ на PyQt происходят ошибки, убедитесь, что Qt-объекты уничтожены " "должным образом (напр. можно установить атрибут Qt.WA_DeleteOnClose " "для Вашего главного окна с помощью метода setAttribute)" #: spyder/plugins/maininterpreter.py:117 msgid "Show reloaded modules list" msgstr "Показать список перезагруженных модулей" #: spyder/plugins/maininterpreter.py:118 msgid "Please note that these changes will be applied only to new consoles" msgstr "" "Обратите внимание, что эти изменения будут применяться только к новым " "консолям" #: spyder/plugins/maininterpreter.py:122 msgid "Set UMR excluded (not reloaded) modules" msgstr "Установить модули-исключения для UMR (не перезагружаемые)" #: spyder/plugins/maininterpreter.py:150 msgid "" "You selected an invalid Python interpreter for the console so the previous " "interpreter will stay. Please make sure to select a valid one." msgstr "" "Вы выбрали некорректный интерпретатор Python для консоли, поэтому был " "оставлен предыдущий интерпретатор. Пожалуйста, выберите правильный." #: spyder/plugins/maininterpreter.py:175 msgid "" "You selected a Python %d interpreter for the console but Spyder is " "running on Python %d!.

Although this is possible, we recommend " "you to install and run Spyder directly with your selected interpreter, to " "avoid seeing false warnings and errors due to the incompatible syntax " "between these two Python versions." msgstr "" "Вы выбрали интерпретатор Python %d для консоли, но Spyder запущен на " "Python %d!.

Мы рекомендуем, если возможно, установить и " "запустить Spyder непосредственно выбранным интерпретатором, чтобы избежать " "появления ложных предупреждений и ошибок, связанных с несовместимостями в " "синтаксисе между этими двумя версиями Python." #: spyder/plugins/maininterpreter.py:186 spyder/plugins/maininterpreter.py:213 #: spyder/plugins/maininterpreter.py:217 msgid "UMR" msgstr "UMR" #: spyder/plugins/maininterpreter.py:187 msgid "Set the list of excluded modules as this: numpy, scipy" msgstr "Задайте список модулей-исключений вот так: numpy, scipy" #: spyder/plugins/maininterpreter.py:204 msgid "" "You are working with Python 2, this means that you can not import a module " "that contains non-ascii characters." msgstr "" "Вы работаете с Python 2, поэтому вы не можете ипортировать модули, " "содержащие не-ascii символы." #: spyder/plugins/maininterpreter.py:214 msgid "" "The following modules are not installed on your machine:\n" "%s" msgstr "" "Следующие модули не установлены на Вашей машине:\n" "%s" #: spyder/plugins/maininterpreter.py:218 msgid "" "Please note that these changes will be applied only to new Python/IPython " "consoles" msgstr "" "Обратите внимание, что эти изменения будут применяться только к новым " "консолям Python/IPython" #: spyder/plugins/onlinehelp.py:70 msgid "Online help" msgstr "Онлайн справка" #: spyder/plugins/outlineexplorer.py:49 spyder/widgets/editortools.py:195 msgid "Outline" msgstr "Структура" #: spyder/plugins/projects.py:78 spyder/widgets/projects/explorer.py:112 #: spyder/widgets/projects/explorer.py:126 msgid "Project explorer" msgstr "Менеджер проектов" #: spyder/plugins/projects.py:90 msgid "New Project..." msgstr "Новый проект..." #: spyder/plugins/projects.py:93 msgid "Open Project..." msgstr "Открыть проект..." #: spyder/plugins/projects.py:96 msgid "Close Project" msgstr "Закрыть проект" #: spyder/plugins/projects.py:99 msgid "Delete Project" msgstr "Удалить проект" #: spyder/plugins/projects.py:105 msgid "Project Preferences" msgstr "Параметры проекта" #: spyder/plugins/projects.py:107 msgid "Recent Projects" msgstr "Недавние проекты" #: spyder/plugins/projects.py:244 msgid "Open project" msgstr "Открыть проект" #: spyder/plugins/projects.py:249 msgid "%s is not a Spyder project!" msgstr "%s - не является проектом Spyder!" #: spyder/plugins/runconfig.py:29 msgid "Execute in current console" msgstr "Выполнить в текущей консоли" #: spyder/plugins/runconfig.py:30 msgid "Execute in a dedicated console" msgstr "Выполнить в отдельной консоли" #: spyder/plugins/runconfig.py:31 msgid "Execute in an external system terminal" msgstr "Выполнить во внешнем системном терминале" #: spyder/plugins/runconfig.py:42 msgid "Always show %s on a first file run" msgstr "Всегда показывать %s при первом запуске файла" #: spyder/plugins/runconfig.py:45 msgid "Remove all variables before execution" msgstr "Удалить все переменные перед запуском" #: spyder/plugins/runconfig.py:46 msgid "Directly enter debugging when errors appear" msgstr "Запускать отладку, как только произошла ошибка" #: spyder/plugins/runconfig.py:47 msgid "Interact with the Python console after execution" msgstr "Перейти в консоль Python после выполнения" #: spyder/plugins/runconfig.py:49 msgid "The directory of the file being executed" msgstr "Каталог исполняемого файла" #: spyder/plugins/runconfig.py:50 spyder/plugins/workingdirectory.py:56 msgid "The current working directory" msgstr "Текущий рабочий каталог" #: spyder/plugins/runconfig.py:51 msgid "The following directory:" msgstr "Следующий каталог:" #: spyder/plugins/runconfig.py:184 spyder/plugins/runconfig.py:504 msgid "General settings" msgstr "Основные настройки" #: spyder/plugins/runconfig.py:194 spyder/plugins/runconfig.py:236 msgid "Command line options:" msgstr "Опции командной строки:" #: spyder/plugins/runconfig.py:202 spyder/plugins/runconfig.py:514 msgid "Working Directory settings" msgstr "Настройки Рабочего каталога" #: spyder/plugins/runconfig.py:226 spyder/plugins/runconfig.py:548 msgid "External system terminal" msgstr "Внешний системный терминал" #: spyder/plugins/runconfig.py:241 msgid "-u is added to the other options you set here" msgstr "-u добавлен к другим опциям, которые Вы здесь установили" #: spyder/plugins/runconfig.py:250 msgid "this dialog" msgstr "это диалоговое окно" #: spyder/plugins/runconfig.py:315 msgid "Run configuration" msgstr "Запустить конфигурацию" #: spyder/plugins/runconfig.py:316 msgid "The following working directory is not valid:
%s" msgstr "Следующий рабочий каталог не применим:
%s" #: spyder/plugins/runconfig.py:394 msgid "Run settings for %s" msgstr "Настройки Запуска для %s" #: spyder/plugins/runconfig.py:426 msgid "Select a run configuration:" msgstr "Выберите конфигурацию запуска:" #: spyder/plugins/runconfig.py:455 msgid "Run configuration per file" msgstr "Запустить настройки для файла" #: spyder/plugins/runconfig.py:480 msgid "" "The following are the default options for running files.These options may be " "overriden using the Configuration per file entry of the Run " "menu." msgstr "" "Далее - стандартные настройкия для запуска файлов. Эти опции можно " "перезаписать с помощью пункта Настройки для файла меню Запускcurrent working directory is the working directory for IPython " "consoles and the current directory for the File Explorer." msgstr "" "Текущая рабочий каталог - рабочий каталог для консолей IPython и " "текущий каталог для Менеджера файлов." #: spyder/plugins/workingdirectory.py:44 msgid "Console directory" msgstr "Каталог консоли" #: spyder/plugins/workingdirectory.py:45 msgid "The working directory for new consoles is:" msgstr "Рабочий каталог для новой консоли:" #: spyder/plugins/workingdirectory.py:49 msgid "" "The current project directory or user home directory (if no project is " "active)" msgstr "" "Текущий каталог проекта или домашний каталог пользователя (если нет " "активного проекта)" #: spyder/plugins/workingdirectory.py:62 msgid "the following directory:" msgstr "указанный каталог:" #: spyder/plugins/workingdirectory.py:64 msgid "The directory when a new console is open will be the specified path" msgstr "" "При создании консоли текущий рабочий каталог будет иметь указанный путь" #: spyder/plugins/workingdirectory.py:124 msgid "Back" msgstr "Назад" #: spyder/plugins/workingdirectory.py:132 spyder/widgets/explorer.py:1181 #: spyder/widgets/variableexplorer/importwizard.py:539 msgid "Next" msgstr "Далее" #: spyder/plugins/workingdirectory.py:143 msgid "" "This is the working directory for newly\n" "opened consoles (Python/IPython consoles and\n" "terminals), for the file explorer, for the\n" "find in files plugin and for new files\n" "created in the editor" msgstr "" "Это - рабочий каталог для новосозданных\n" "консолей (консолей и терминалов Python/IPython),\n" "для файлового менеджера, для модуля\n" "поиска в файлах и для новых файлов,\n" "созданных в редакторе" #: spyder/plugins/workingdirectory.py:168 msgid "Browse a working directory" msgstr "Просмотреть рабочий каталог" #: spyder/plugins/workingdirectory.py:175 msgid "Change to parent directory" msgstr "Изменить на родительский каталог" #: spyder/plugins/workingdirectory.py:182 spyder/widgets/findinfiles.py:322 msgid "Current working directory" msgstr "Текущий рабочий каталог" #: spyder/utils/codeanalysis.py:92 msgid "Real-time code analysis on the Editor" msgstr "Анализ кода в Редакторе в реальном времени" #: spyder/utils/codeanalysis.py:96 msgid "Real-time code style analysis on the Editor" msgstr "Анализ стиля кода в Редакторе в реальном времени" #: spyder/utils/environ.py:46 msgid "Environment variables" msgstr "Переменные среды" #: spyder/utils/environ.py:96 msgid "" "Module pywin32 was not found.
Please restart this Windows " "session (not the computer) for changes to take effect." msgstr "" "Модуль pywin32 не найден.
Пожалуйста, перезапустите сессию " "Windows (не компьютер), чтобы изменения вступили в силу." #: spyder/utils/environ.py:109 msgid "" "If you accept changes, this will modify the current user environment " "variables directly in Windows registry. Use it with precautions, at " "your own risks.

Note that for changes to take effect, you will need " "to restart the parent process of this application (simply restart Spyder if " "you have executed it from a Windows shortcut, otherwise restart any " "application from which you may have executed it, like Python(x,y) Home for example)" msgstr "" "Если Вы примете изменения, это переопределит переменные среды для текущего " "пользователя непосредственно в реестре Windows. Используйте с " "осторожностью, на свой риск.

Имейте в виду, чтобы изменения вступили " "в силу, необходимо перезагрузить родительский процесс приложения (просто " "перезапустите Spyder, если запускали его ярлыком Windows, или перезапустите " "приложение из которого Вы его запускали, например Python(x,y) Home)" #: spyder/utils/help/sphinxify.py:217 spyder/utils/help/sphinxify.py:227 msgid "" "It was not possible to generate rich text help for this object.
Please " "see it in plain text." msgstr "" "Невозможно создать форматированную текстовую справку по объекту.Пожалуйста, просмотрите в виде обычного текста." #: spyder/utils/introspection/manager.py:34 #: spyder/utils/introspection/manager.py:39 msgid "Editor's code completion, go-to-definition and help" msgstr "Автодополнение кода редактора, переход к определению и справка" #: spyder/utils/iofuncs.py:408 msgid "Supported files" msgstr "Поддерживаемые файлы" #: spyder/utils/iofuncs.py:410 msgid "All files (*.*)" msgstr "Все файлы (*.*)" #: spyder/utils/iofuncs.py:420 msgid "Spyder data files" msgstr "Файлы данных Spyder" #: spyder/utils/iofuncs.py:422 #: spyder/widgets/variableexplorer/collectionseditor.py:1058 msgid "NumPy arrays" msgstr "Массивы NumPy" #: spyder/utils/iofuncs.py:423 msgid "NumPy zip arrays" msgstr "Сжатые массивы NumPy" #: spyder/utils/iofuncs.py:424 msgid "Matlab files" msgstr "Файлы Matlab" #: spyder/utils/iofuncs.py:425 msgid "CSV text files" msgstr "Текстовые файлы CSV" #: spyder/utils/iofuncs.py:427 msgid "JPEG images" msgstr "Изображения JPEG" #: spyder/utils/iofuncs.py:428 msgid "PNG images" msgstr "Изображения PNG" #: spyder/utils/iofuncs.py:429 msgid "GIF images" msgstr "Изображения GIF" #: spyder/utils/iofuncs.py:430 msgid "TIFF images" msgstr "Изображения TIFF" #: spyder/utils/iofuncs.py:431 spyder/utils/iofuncs.py:432 msgid "Pickle files" msgstr "Архивы Pickle" #: spyder/utils/iofuncs.py:433 msgid "JSON files" msgstr "Файлы JSON" #: spyder/utils/iofuncs.py:452 spyder/utils/iofuncs.py:459 msgid "Unsupported file type '%s'" msgstr "Неподдерживаемый тип файла '%s'" #: spyder/utils/programs.py:287 msgid "It was not possible to run this file in an external terminal" msgstr "Невозможно запустить файл во внешнем терминале" #: spyder/utils/syntaxhighlighters.py:34 msgid "Syntax highlighting for Matlab, Julia and other file types" msgstr "Подсветка синтаксиса для Matlab, Julia и других типов файлов" #: spyder/utils/syntaxhighlighters.py:43 msgid "Background:" msgstr "Фон:" #: spyder/utils/syntaxhighlighters.py:44 #: spyder/widgets/sourcecode/codeeditor.py:107 msgid "Current line:" msgstr "Текущая строка:" #: spyder/utils/syntaxhighlighters.py:45 msgid "Current cell:" msgstr "Текущий блок:" #: spyder/utils/syntaxhighlighters.py:46 msgid "Occurrence:" msgstr "Вхождения слова:" #: spyder/utils/syntaxhighlighters.py:47 msgid "Link:" msgstr "Ссылка:" #: spyder/utils/syntaxhighlighters.py:48 msgid "Side areas:" msgstr "Боковые панели:" #: spyder/utils/syntaxhighlighters.py:49 msgid "Matched
parens:" msgstr "Парные
скобки:" #: spyder/utils/syntaxhighlighters.py:50 msgid "Unmatched
parens:" msgstr "Скобки
без пары:" #: spyder/utils/syntaxhighlighters.py:51 msgid "Normal text:" msgstr "Обычный текст:" #: spyder/utils/syntaxhighlighters.py:52 msgid "Keyword:" msgstr "Ключевое слово:" #: spyder/utils/syntaxhighlighters.py:53 msgid "Builtin:" msgstr "Встроенные:" #: spyder/utils/syntaxhighlighters.py:54 msgid "Definition:" msgstr "Определение:" #: spyder/utils/syntaxhighlighters.py:55 msgid "Comment:" msgstr "Комментарий:" #: spyder/utils/syntaxhighlighters.py:56 msgid "String:" msgstr "Строка:" #: spyder/utils/syntaxhighlighters.py:57 msgid "Number:" msgstr "Число:" #: spyder/utils/syntaxhighlighters.py:58 msgid "Instance:" msgstr "Экземпляр класса:" #: spyder/widgets/arraybuilder.py:179 msgid "" "\n" " Numpy Array/Matrix Helper
\n" " Type an array in Matlab : [1 2;3 4]
\n" " or Spyder simplified syntax : 1 2;3 4\n" "

\n" " Hit 'Enter' for array or 'Ctrl+Enter' for matrix.\n" "

\n" " Hint:
\n" " Use two spaces or two tabs to generate a ';'.\n" " " msgstr "" "\n" " Помощник Массивов/Матриц Numpy
\n" " Введите массив в Matlab- : [1 2;3 4]
\n" " или Spyder-стиле : 1 2;3 4\n" "

\n" " Нажмите 'Enter' для массива или 'Ctrl+Enter' для матрицы.\n" "

\n" " Трюк:
\n" " Два пробели или две табуляции образуют ';'.\n" " " #: spyder/widgets/arraybuilder.py:190 msgid "" "\n" " Numpy Array/Matrix Helper
\n" " Enter an array in the table.
\n" " Use Tab to move between cells.\n" "

\n" " Hit 'Enter' for array or 'Ctrl+Enter' for matrix.\n" "

\n" " Hint:
\n" " Use two tabs at the end of a row to move to the next row.\n" " " msgstr "" "\n" " Помощник Массивов/Матриц Numpy
\n" " Введите массив в таблицу.
\n" " Используйте Tab для перемещения по ячейкам.\n" "

\n" "\n" " Нажмите 'Enter' для массива или 'Ctrl+Enter' для матрицы.\n" "

\n" " Трюк:
\n" " Две табуляции в конце строки перемещают на следующую строку.\n" " " #: spyder/widgets/arraybuilder.py:365 msgid "Array dimensions not valid" msgstr "Неверная размерность массива" #: spyder/widgets/browser.py:58 spyder/widgets/sourcecode/codeeditor.py:2719 msgid "Zoom out" msgstr "Уменьшить" #: spyder/widgets/browser.py:61 spyder/widgets/sourcecode/codeeditor.py:2715 msgid "Zoom in" msgstr "Увеличить" #: spyder/widgets/browser.py:213 msgid "Home" msgstr "Домой" #: spyder/widgets/browser.py:249 msgid "Find text" msgstr "Найти текст" #: spyder/widgets/browser.py:266 msgid "Address:" msgstr "Адрес:" #: spyder/widgets/browser.py:302 msgid "Unable to load page" msgstr "Не удалось загрузить страницу" #: spyder/widgets/comboboxes.py:164 msgid "Press enter to validate this entry" msgstr "Нажмите Enter для подтверждения этого поля" #: spyder/widgets/comboboxes.py:165 msgid "This entry is incorrect" msgstr "Это поле неверно" #: spyder/widgets/comboboxes.py:208 msgid "Press enter to validate this path" msgstr "Нажмите Enter для подтверждения этого пути" #: spyder/widgets/dependencies.py:63 msgid " Required " msgstr " требуется" #: spyder/widgets/dependencies.py:63 msgid "Module" msgstr "Модуль" #: spyder/widgets/dependencies.py:64 msgid " Installed " msgstr " установлен" #: spyder/widgets/dependencies.py:64 msgid "Provided features" msgstr "Предоставляемые возможности" #: spyder/widgets/dependencies.py:134 msgid "Dependencies" msgstr "Зависимости" #: spyder/widgets/dependencies.py:141 msgid "" "Spyder depends on several Python modules to provide the right functionality " "for all its panes. The table below shows the required and installed versions " "(if any) of all of them.

Note: You can safely use Spyder " "without the following modules installed: %s and %s." "

Please also note that new dependencies or changed ones will be " "correctly detected only after Spyder is restarted." msgstr "" "Spyder зависит от нескольких модулей Python, обеспечивающих правильное " "функционирование всех панелей. В таблице ниже показаны требуемые и " "установленные версии (если таковые имеются) каждого из пакетов." "

Примечание: Вы можете безопасно работать в Spyder без " "следующих модулей: %s и %s. Также, пожалуйста, учтите, что " "новые пакеты или изменения в них будут корректно учтены только после " "перезапуска Spyder." #: spyder/widgets/dependencies.py:157 msgid "Copy to clipboard" msgstr "Копировать в буфер обмена" #: spyder/widgets/editor.py:501 msgid "Find symbols in file..." msgstr "Найти в файлe..." #: spyder/widgets/editor.py:504 msgid "Copy path to clipboard" msgstr "Копировать путь в буфер обмена" #: spyder/widgets/editor.py:508 msgid "Close all to the right" msgstr "Закрыть все правее" #: spyder/widgets/editor.py:510 msgid "Close all but this" msgstr "Закрыть все кроме этой" #: spyder/widgets/editor.py:514 spyder/widgets/explorer.py:361 msgid "Show in Finder" msgstr "Показывать в Поиске" #: spyder/widgets/editor.py:516 spyder/widgets/explorer.py:363 msgid "Show in external file explorer" msgstr "Показать менеджер файлов" #: spyder/widgets/editor.py:1197 msgid "Temporary file" msgstr "Временный файл" #: spyder/widgets/editor.py:1289 msgid "New window" msgstr "Новое окно" #: spyder/widgets/editor.py:1290 msgid "Create a new editor window" msgstr "Создать новое окно редактора" #: spyder/widgets/editor.py:1293 msgid "Split vertically" msgstr "Разделить по вертикали" #: spyder/widgets/editor.py:1295 msgid "Split vertically this editor window" msgstr "Разделить окна редактора по вертикали" #: spyder/widgets/editor.py:1297 msgid "Split horizontally" msgstr "Разделить по горизонтали" #: spyder/widgets/editor.py:1299 msgid "Split horizontally this editor window" msgstr "Разделить окна редактора по горизонтали" #: spyder/widgets/editor.py:1301 msgid "Close this panel" msgstr "Закрыть эту панель" #: spyder/widgets/editor.py:1540 msgid "%s has been modified.
Do you want to save changes?" msgstr "%s был изменён.
Хотите сохранить изменения?" #: spyder/widgets/editor.py:1626 spyder/widgets/editor.py:1789 msgid "Save" msgstr "Сохранить" #: spyder/widgets/editor.py:1627 spyder/widgets/editor.py:1790 #: spyder/widgets/shell.py:267 msgid "Unable to save file '%s'

Error message:
%s" msgstr "" "Невозможно сохранить файл %s

Сообщение об ошибке:
%s" #: spyder/widgets/editor.py:1977 msgid "" "%s is unavailable (this file may have been removed, moved or renamed " "outside Spyder).
Do you want to close it?" msgstr "" "%s недоступен (этот файл мог быть удален, перемещён или переименован " "вне Spyder).
Хотите его закрыть?" #: spyder/widgets/editor.py:2000 msgid "" "%s has been modified outside Spyder.
Do you want to reload it and " "lose all your changes?" msgstr "" "%s был изменён вне Spyder.
Хотите перегрузить его и потерять все " "изменения?" #: spyder/widgets/editor.py:2110 msgid "" "All changes to %s will be lost.
Do you want to revert file from " "disk?" msgstr "" "Все изменения для %s были потеряны.
Хотите перегрузить файл с " "диска?" #: spyder/widgets/editor.py:2254 msgid "Loading %s..." msgstr "Загрузка %s..." #: spyder/widgets/editor.py:2266 msgid "" "%s contains mixed end-of-line characters.
Spyder will fix this " "automatically." msgstr "" "%s содержит смешанные символы конца строки.
Spyder исправит это " "автоматически." #: spyder/widgets/editor.py:2675 msgid "Close window" msgstr "Закрыть окно" #: spyder/widgets/editor.py:2677 msgid "Close this window" msgstr "Закрыть это окно" #: spyder/widgets/editortools.py:94 spyder/widgets/editortools.py:130 msgid "Line %s" msgstr "Строка %s" #: spyder/widgets/editortools.py:99 msgid "Class defined at line %s" msgstr "Класс определён в строке %s" #: spyder/widgets/editortools.py:107 msgid "Method defined at line %s" msgstr "Метод определён в строке %s" #: spyder/widgets/editortools.py:117 msgid "Function defined at line %s" msgstr "Функция определена в строке %s" #: spyder/widgets/editortools.py:149 msgid "Cell starts at line %s" msgstr "Блок начинается в строке %s" #: spyder/widgets/editortools.py:202 spyder/widgets/editortools.py:535 msgid "Go to cursor position" msgstr "Перейти к позиции курсора" #: spyder/widgets/editortools.py:205 msgid "Show absolute path" msgstr "Показать полный путь" #: spyder/widgets/editortools.py:208 spyder/widgets/explorer.py:274 msgid "Show all files" msgstr "Показать все файлы" #: spyder/widgets/editortools.py:211 msgid "Show special comments" msgstr "Показать специальные комментарии" #: spyder/widgets/editortools.py:509 msgid "Show/hide outline explorer" msgstr "Показать/скрыть менеджер структуры" #: spyder/widgets/explorer.py:270 msgid "Edit filename filters..." msgstr "Редактировать фильтры имён файлов..." #: spyder/widgets/explorer.py:284 msgid "Edit filename filters" msgstr "Редактировать фильтры имён файлов" #: spyder/widgets/explorer.py:285 msgid "Name filters:" msgstr "Фильтры имён:" #: spyder/widgets/explorer.py:304 msgid "File..." msgstr "Файл..." #: spyder/widgets/explorer.py:308 msgid "Module..." msgstr "Модуль..." #: spyder/widgets/explorer.py:312 msgid "Folder..." msgstr "Каталог..." #: spyder/widgets/explorer.py:316 msgid "Package..." msgstr "Пакет..." #: spyder/widgets/explorer.py:337 #: spyder/widgets/variableexplorer/collectionseditor.py:674 msgid "Edit" msgstr "Редактировать" #: spyder/widgets/explorer.py:339 msgid "Move..." msgstr "Переместить..." #: spyder/widgets/explorer.py:342 msgid "Delete..." msgstr "Удалить..." #: spyder/widgets/explorer.py:345 msgid "Rename..." msgstr "Переименовать..." #: spyder/widgets/explorer.py:348 msgid "Open" msgstr "Открыть" #: spyder/widgets/explorer.py:349 spyder/widgets/sourcecode/codeeditor.py:2687 msgid "Convert to Python script" msgstr "Сохранить как скрипт Python" # Варинаты: # - оставить без перевода # - использовать кальку: "коммитить" # - воспользоваться переводом из источников про Git (например, книга ProGit): "зафиксирвать изменения/индекс". #: spyder/widgets/explorer.py:390 msgid "Commit" msgstr "Зафиксировать" #: spyder/widgets/explorer.py:393 msgid "Browse repository" msgstr "Просмотр репозитария" #: spyder/widgets/explorer.py:404 msgid "Open command prompt here" msgstr "Открыть командную строку здесь" #: spyder/widgets/explorer.py:406 msgid "Open terminal here" msgstr "Открыть терминал здесь" #: spyder/widgets/explorer.py:407 msgid "Open IPython console here" msgstr "Открыть консоль IPython здесь" #: spyder/widgets/explorer.py:421 msgid "New" msgstr "Новый" #: spyder/widgets/explorer.py:429 msgid "Import" msgstr "Импортировать" #: spyder/widgets/explorer.py:575 msgid "Do you really want to delete %s?" msgstr "Вы точно хотите удалить %s?" #: spyder/widgets/explorer.py:593 msgid "delete" msgstr "удалить" #: spyder/widgets/explorer.py:594 spyder/widgets/projects/explorer.py:148 #: spyder/widgets/projects/explorer.py:255 msgid "Project Explorer" msgstr "Менеджер проектов" #: spyder/widgets/explorer.py:595 spyder/widgets/projects/explorer.py:149 msgid "Unable to %s %s

Error message:
%s" msgstr "Невозможно %s %s

Сообщение об ошибке:
%s" #: spyder/widgets/explorer.py:610 msgid "File Explorer" msgstr "Файловый менеджер" #: spyder/widgets/explorer.py:611 msgid "" "The current directory contains a project.

If you want to delete the " "project, please go to Projects » Delete Project" msgstr "" "В текущий каталоге находится проект.

Если вы хотите удалить проект, " "пожалуйста, воспользуйтесь меню Проекты » Удалить проект" #: spyder/widgets/explorer.py:628 spyder/widgets/sourcecode/codeeditor.py:2160 msgid "Conversion error" msgstr "Ошибка преобразования" #: spyder/widgets/explorer.py:629 spyder/widgets/sourcecode/codeeditor.py:2161 msgid "" "It was not possible to convert this notebook. The error is:\n" "\n" msgstr "" "Не удалось сконвертировать этот блокнот. Ошибка:\n" "\n" #: spyder/widgets/explorer.py:646 spyder/widgets/explorer.py:654 #: spyder/widgets/explorer.py:665 #: spyder/widgets/variableexplorer/collectionseditor.py:703 #: spyder/widgets/variableexplorer/collectionseditor.py:949 msgid "Rename" msgstr "Переименовать" #: spyder/widgets/explorer.py:647 msgid "New name:" msgstr "Новое имя:" #: spyder/widgets/explorer.py:655 msgid "" "Do you really want to rename %s and overwrite the existing file " "%s?" msgstr "" "Вы действительно хотите переименовать %s или перезаписать " "существующий файл %s?" #: spyder/widgets/explorer.py:666 msgid "Unable to rename file %s

Error message:
%s" msgstr "" "Невозможно переименовать файл %s

Сообщение об ошибке:" "
%s" #: spyder/widgets/explorer.py:709 msgid "Unable to move %s

Error message:
%s" msgstr "" "Невозможно переместить файл %s

Сообщение об ошибке:
" "%s" #: spyder/widgets/explorer.py:727 msgid "Unable to create folder %s

Error message:
%s" msgstr "" "Невозможно создать каталог %s

Сообщение об ошибке:
%s" #: spyder/widgets/explorer.py:740 spyder/widgets/explorer.py:774 msgid "Unable to create file %s

Error message:
%s" msgstr "" "Невозможно создать файл %s

Сообщение об ошибке:
%s" #: spyder/widgets/explorer.py:748 msgid "New folder" msgstr "Новый каталог" #: spyder/widgets/explorer.py:749 msgid "Folder name:" msgstr "Имя каталога:" #: spyder/widgets/explorer.py:754 msgid "New package" msgstr "Новый пакет" #: spyder/widgets/explorer.py:755 msgid "Package name:" msgstr "Имя пакета:" #: spyder/widgets/explorer.py:795 msgid "New module" msgstr "Новый модуль" #: spyder/widgets/explorer.py:810 msgid "" "For %s support, please install one of the
following tools:

%s" msgstr "" "Для поддержки %s, установите, пожалуйста,
один из следующих " "инструментов:

%s" #: spyder/widgets/explorer.py:814 msgid "Unable to find external program.

%s" msgstr "Не удалось найти внешнюю программу.

%s" #: spyder/widgets/explorer.py:1035 msgid "Show current directory only" msgstr "Показывать только текущий каталог" #: spyder/widgets/explorer.py:1145 msgid "You don't have the right permissions to open this directory" msgstr "У Вас нет прав на открытие этой директории" #: spyder/widgets/explorer.py:1176 msgid "Show icons and text" msgstr "Показывать иконки и текст" #: spyder/widgets/explorer.py:1178 #: spyder/widgets/variableexplorer/importwizard.py:535 msgid "Previous" msgstr "Предыдущая" #: spyder/widgets/explorer.py:1184 msgid "Parent" msgstr "Родительская" #: spyder/widgets/fileswitcher.py:110 msgid "unsaved file" msgstr "несохранённый файл" #: spyder/widgets/fileswitcher.py:249 msgid "" "Press Enter to switch files or Esc to cancel.

Type to " "filter filenames.

Use :number to go to a line, e.g. " "main:42
Use @symbol_text to go to a symbol, e." "g. @init

Press Ctrl+W to close current " "tab.
" msgstr "" "Нажмите Enter для перехода к файлу или Esc для отмены." "

Введите текст для фильтрации имен файлов.

Используйте :" "номер для перехода к строке, напр. main:42
Используйте @имя для перехода к идентификатору, напр. " "@init

Нажмите Ctrl+W для закрытия текущей " "вкладки." #: spyder/widgets/fileswitcher.py:663 msgid "lines" msgstr " строк" #: spyder/widgets/findinfiles.py:121 msgid "Unexpected error: see internal console" msgstr "Неожиданная ошибка: смотрите во встроенной консоли" #: spyder/widgets/findinfiles.py:149 msgid "invalid regular expression" msgstr "неверное регулярное выражение" #: spyder/widgets/findinfiles.py:199 msgid "permission denied errors were encountered" msgstr "обнаружены ошибки отказа в доступе" #: spyder/widgets/findinfiles.py:258 msgid "Search pattern" msgstr "Найти по шаблону" #: spyder/widgets/findinfiles.py:261 spyder/widgets/findinfiles.py:301 #: spyder/widgets/findreplace.py:99 msgid "Regular expression" msgstr "Регулярное выражение" #: spyder/widgets/findinfiles.py:264 spyder/widgets/findreplace.py:105 msgid "Case Sensitive" msgstr "С учетом регистра" #: spyder/widgets/findinfiles.py:275 msgid "Search" msgstr "Найти" #: spyder/widgets/findinfiles.py:278 msgid "Start search" msgstr "Начать поиск" #: spyder/widgets/findinfiles.py:285 msgid "Stop search" msgstr "Остановить поиск" #: spyder/widgets/findinfiles.py:295 msgid "Excluded filenames pattern" msgstr "Шаблон имён исключаемых файлов" #: spyder/widgets/findinfiles.py:304 msgid "Exclude:" msgstr "Исключить:" #: spyder/widgets/findinfiles.py:313 msgid "Search in:" msgstr "Искать в:" #: spyder/widgets/findinfiles.py:315 msgid "Search directory" msgstr "Каталог поиска" #: spyder/widgets/findinfiles.py:324 msgid "Search in all files and directories present on thecurrent Spyder path" msgstr "" "Искать во всех файлах и каталогах, присутствующих в текущем пути Spyder" #: spyder/widgets/findinfiles.py:328 msgid "Project" msgstr "Проект" #: spyder/widgets/findinfiles.py:330 msgid "" "Search in all files and directories present on thecurrent project path (If " "opened)" msgstr "" "Искать во всех файлах и каталогах, присутствующих в текущем пути проекта " "(если открыт)" #: spyder/widgets/findinfiles.py:336 msgid "File" msgstr "Файл" #: spyder/widgets/findinfiles.py:338 msgid "Search in current opened file" msgstr "Искать в текущем открытом файле" #: spyder/widgets/findinfiles.py:340 msgid "Select other directory" msgstr "Выберите другой каталог" #: spyder/widgets/findinfiles.py:342 msgid "Search in other folder present on the file system" msgstr "Искать в другом каталоге файловой системы" #: spyder/widgets/findinfiles.py:378 msgid "Hide advanced options" msgstr "Скрыть дополнительные опции" #: spyder/widgets/findinfiles.py:381 msgid "Show advanced options" msgstr "Показать дополнительные опции" #: spyder/widgets/findinfiles.py:675 spyder/widgets/findinfiles.py:759 msgid "String not found" msgstr "Строка не найдена" #: spyder/widgets/findinfiles.py:761 msgid "matches in" msgstr "совпадений в" #: spyder/widgets/findinfiles.py:762 msgid "file" msgstr "файл" #: spyder/widgets/findinfiles.py:794 msgid " Scanning: {0}" msgstr " Сканирование: {0}" #: spyder/widgets/findinfiles.py:796 msgid " Searching for files in folder: {0}" msgstr " Поиск файлов в директории: {0}" #: spyder/widgets/findinfiles.py:800 msgid " Searching for files..." msgstr " Поиск файлов..." #: spyder/widgets/findreplace.py:48 msgid "No matches" msgstr "Нет совпадений" #: spyder/widgets/findreplace.py:49 spyder/widgets/findreplace.py:50 #: spyder/widgets/findreplace.py:72 msgid "Search string" msgstr "Найти строку" #: spyder/widgets/findreplace.py:51 msgid "Regular expression error" msgstr "Ошибка в регулярном выражении" #: spyder/widgets/findreplace.py:111 msgid "Whole words" msgstr "Слова целиком" #: spyder/widgets/findreplace.py:117 msgid "Highlight matches" msgstr "Подсвечивать найденные" #: spyder/widgets/findreplace.py:131 msgid "Replace with:" msgstr "Заменить на:" #: spyder/widgets/findreplace.py:133 msgid "Replace string" msgstr "Заменить строку" #: spyder/widgets/findreplace.py:137 msgid "Replace/find next" msgstr "Заменить/найти далее" #: spyder/widgets/findreplace.py:142 msgid "Replace selection" msgstr "Заменить выделенное" #: spyder/widgets/findreplace.py:150 msgid "Replace all" msgstr "Заменить все" #: spyder/widgets/findreplace.py:572 msgid "of" msgstr "из" #: spyder/widgets/findreplace.py:576 msgid "matches" msgstr "совпадений" #: spyder/widgets/findreplace.py:579 msgid "no matches" msgstr "нет совпадений" #: spyder/widgets/internalshell.py:262 msgid "Help..." msgstr "Справка..." #: spyder/widgets/internalshell.py:279 msgid "Shell special commands:" msgstr "Специальные команды оболочки:" #: spyder/widgets/internalshell.py:280 msgid "Internal editor:" msgstr "Встроенный редактор:" #: spyder/widgets/internalshell.py:281 msgid "External editor:" msgstr "Внешний редактор:" #: spyder/widgets/internalshell.py:282 msgid "Run script:" msgstr "Выполнить скрипт:" #: spyder/widgets/internalshell.py:283 msgid "Remove references:" msgstr "Удалить ссылки:" #: spyder/widgets/internalshell.py:284 msgid "System commands:" msgstr "Системные команды:" #: spyder/widgets/internalshell.py:285 msgid "Python help:" msgstr "Справка Python:" #: spyder/widgets/internalshell.py:286 msgid "GUI-based editor:" msgstr "Визуальный редактор:" #: spyder/widgets/ipythonconsole/client.py:275 msgid "An error ocurred while starting the kernel" msgstr "При запуске ядра произошла ошибка" #: spyder/widgets/ipythonconsole/client.py:316 #: spyder/widgets/ipythonconsole/client.py:372 #: spyder/widgets/ipythonconsole/client.py:405 #: spyder/widgets/ipythonconsole/shell.py:232 #: spyder/widgets/variableexplorer/namespacebrowser.py:193 msgid "Remove all variables" msgstr "Удалить все переменные" #: spyder/widgets/ipythonconsole/client.py:325 msgid "Show environment variables" msgstr "Показать переменные среды" #: spyder/widgets/ipythonconsole/client.py:332 msgid "Show sys.path contents" msgstr "Показать содержимое sys.path" #: spyder/widgets/ipythonconsole/client.py:359 msgid "Stop the current command" msgstr "Остановить текущую команду" #: spyder/widgets/ipythonconsole/client.py:370 #: spyder/widgets/variableexplorer/collectionseditor.py:696 #: spyder/widgets/variableexplorer/collectionseditor.py:931 msgid "Remove" msgstr "Удалить" #: spyder/widgets/ipythonconsole/client.py:393 msgid "Inspect current object" msgstr "Проверить текущий объект" #: spyder/widgets/ipythonconsole/client.py:399 msgid "Clear line or block" msgstr "Очистить строку или блок" #: spyder/widgets/ipythonconsole/client.py:412 msgid "Clear console" msgstr "Очистить консоль" #: spyder/widgets/ipythonconsole/client.py:460 msgid "Are you sure you want to restart the kernel?" msgstr "Вы уверены, что хотите перезапустить ядро?" #: spyder/widgets/ipythonconsole/client.py:462 msgid "Restart kernel?" msgstr "Перезапустить ядро?" #: spyder/widgets/ipythonconsole/client.py:474 msgid "Error restarting kernel: %s\n" msgstr "Ошибка при перезапуске ядра: %s\n" #: spyder/widgets/ipythonconsole/client.py:479 msgid "" "
Restarting kernel...\n" "

" msgstr "" "
Перезапуск ядра...\n" "

" #: spyder/widgets/ipythonconsole/client.py:483 msgid "Cannot restart a kernel not started by Spyder\n" msgstr "Не удается перезапусть ядро, запущенное не из Spyder\n" #: spyder/widgets/ipythonconsole/client.py:592 msgid "Connecting to kernel..." msgstr "Подключение к ядру..." #: spyder/widgets/ipythonconsole/help.py:128 spyder/widgets/mixins.py:712 msgid "Arguments" msgstr "Аргументы" #: spyder/widgets/ipythonconsole/namespacebrowser.py:129 msgid "Loading this kind of data while debugging is not supported." msgstr "Загрузка этого типа данных во время отладки не поддерживается." #: spyder/widgets/ipythonconsole/namespacebrowser.py:148 msgid "Saving data while debugging is not supported." msgstr "Сохранение данных во время отладки не поддерживается." #: spyder/widgets/ipythonconsole/shell.py:233 msgid "" "All user-defined variables will be removed. Are you sure you want to proceed?" msgstr "" "Все пользовательские переменные будут удалены.
Вы уверены, что хотите " "продолжить?" #: spyder/widgets/ipythonconsole/shell.py:239 msgid "Don't show again." msgstr "Не показывать снова." #: spyder/widgets/ipythonconsole/shell.py:262 msgid "" "

Removing all variables...\n" "
" msgstr "" "

Удаление всех переменных...\n" "
" #: spyder/widgets/ipythonconsole/shell.py:426 msgid "Changing backend to Qt for Mayavi" msgstr "Изменить бэкенд для Mayavi на Qt" #: spyder/widgets/ipythonconsole/shell.py:471 msgid "Kernel died, restarting" msgstr "Ядро остановилось, перезапуск" #: spyder/widgets/ipythonconsole/shell.py:471 msgid "Kernel restarting" msgstr "Перезапуск ядра" #: spyder/widgets/onecolumntree.py:52 msgid "Collapse all" msgstr "Свернуть всё" #: spyder/widgets/onecolumntree.py:56 msgid "Expand all" msgstr "Развернуть всё" #: spyder/widgets/onecolumntree.py:60 msgid "Restore" msgstr "Восстановить" #: spyder/widgets/onecolumntree.py:61 msgid "Restore original tree layout" msgstr "Восстановить оригинальную структуру дерева" #: spyder/widgets/onecolumntree.py:65 msgid "Collapse selection" msgstr "Свернуть выделенное" #: spyder/widgets/onecolumntree.py:69 msgid "Expand selection" msgstr "Развернуть выделенное" #: spyder/widgets/pathmanager.py:97 msgid "Move to top" msgstr "Переместить вверх" #: spyder/widgets/pathmanager.py:103 msgid "Move up" msgstr "Переместить выше" #: spyder/widgets/pathmanager.py:109 msgid "Move down" msgstr "Переместить ниже" #: spyder/widgets/pathmanager.py:115 msgid "Move to bottom" msgstr "Переместить вниз" #: spyder/widgets/pathmanager.py:126 spyder/widgets/pathmanager.py:267 msgid "Add path" msgstr "Добавить путь" #: spyder/widgets/pathmanager.py:131 spyder/widgets/pathmanager.py:246 msgid "Remove path" msgstr "Удалить путь" #: spyder/widgets/pathmanager.py:141 msgid "Synchronize..." msgstr "Синхронизация..." #: spyder/widgets/pathmanager.py:143 msgid "Synchronize Spyder's path list with PYTHONPATH environment variable" msgstr "Синхронизировать список путей Spyder с переменной среды PYTHONPATH" #: spyder/widgets/pathmanager.py:155 msgid "Synchronize" msgstr "Синхронизировать" #: spyder/widgets/pathmanager.py:156 msgid "" "This will synchronize Spyder's path list with PYTHONPATH environment " "variable for current user, allowing you to run your Python modules outside " "Spyder without having to configure sys.path.
Do you want to clear " "contents of PYTHONPATH before adding Spyder's path list?" msgstr "" "Будет синхронизирован список путей Spyder с переменной среды PYTHONPATH для " "текущего пользователя, позволяя Вам запускать Ваши модули Python вне Spyder " "без необходимости настраивать sys.path.
Хотите очистить содержимое " "PYTHONPATH перед добавлением списка путей Spyder?" #: spyder/widgets/pathmanager.py:247 msgid "Do you really want to remove selected path?" msgstr "Вы действительно хотите удалить выбранный путь?" #: spyder/widgets/pathmanager.py:268 msgid "" "This directory is already included in Spyder path list.
Do you want to " "move it to the top of the list?" msgstr "" "Этот каталог уже имеется в списке путей Spyder.
Хотите переместить его на " "вершину списка?" #: spyder/widgets/projects/configdialog.py:30 msgid "Project preferences" msgstr "Параметры проекта" #: spyder/widgets/projects/configdialog.py:82 #: spyder/widgets/projects/configdialog.py:119 msgid "Restore data on startup" msgstr "Восстанавливать данные при запуске" #: spyder/widgets/projects/configdialog.py:84 #: spyder/widgets/projects/configdialog.py:121 msgid "Save data on exit" msgstr "Сохранять данные перед выходом" #: spyder/widgets/projects/configdialog.py:86 #: spyder/widgets/projects/configdialog.py:123 msgid "Save history" msgstr "Сохранять журнал истории" #: spyder/widgets/projects/configdialog.py:88 #: spyder/widgets/projects/configdialog.py:125 msgid "Save non project files opened" msgstr "Сохранять файлы не из проекта" #: spyder/widgets/projects/configdialog.py:111 msgid "Code" msgstr "Код" #: spyder/widgets/projects/configdialog.py:118 msgid "Workspace" msgstr "Рабочая область" #: spyder/widgets/projects/configdialog.py:148 #: spyder/widgets/projects/configdialog.py:155 msgid "Version control" msgstr "Контроль версий" #: spyder/widgets/projects/configdialog.py:156 msgid "Use version control" msgstr "Использовать контроль версий" #: spyder/widgets/projects/configdialog.py:161 msgid "Version control system" msgstr "Система контроля версий" #: spyder/widgets/projects/explorer.py:51 msgid "Show horizontal scrollbar" msgstr "Показывать горизонтальную полосу прокрутки" #: spyder/widgets/projects/explorer.py:113 msgid "File %s already exists.
Do you want to overwrite it?" msgstr "Файл %s уже существует.
Хотите его перезаписать?" #: spyder/widgets/projects/explorer.py:127 msgid "Folder %s already exists." msgstr "Каталог %s уже существует." #: spyder/widgets/projects/explorer.py:145 msgid "copy" msgstr "скопировать" #: spyder/widgets/projects/explorer.py:147 msgid "move" msgstr "переместить" #: spyder/widgets/projects/explorer.py:243 msgid "" "Do you really want to delete {filename}?

Note: This " "action will only delete the project. Its files are going to be preserved on " "disk." msgstr "" "Вы действительно хотите удалить проект {filename}?" "

Примечание:Файлы, входящие в проект, при этом останутся на " "диске." #: spyder/widgets/projects/explorer.py:256 msgid "" "Unable to delete {varpath}

The error message was:" "
{error}" msgstr "" "Невозможно удалить {varpath}

Сообщение об ошибке:" "
{error}" #: spyder/widgets/projects/projectdialog.py:69 msgid "New directory" msgstr "Новый каталог" #: spyder/widgets/projects/projectdialog.py:70 msgid "Existing directory" msgstr "Существующий каталог" #: spyder/widgets/projects/projectdialog.py:72 msgid "Project name" msgstr "Имя проекта" #: spyder/widgets/projects/projectdialog.py:73 msgid "Location" msgstr "Расположение" #: spyder/widgets/projects/projectdialog.py:74 msgid "Project type" msgstr "Тип проекта" #: spyder/widgets/projects/projectdialog.py:75 msgid "Python version" msgstr "Версия Python" #: spyder/widgets/projects/projectdialog.py:83 #: spyder/widgets/variableexplorer/importwizard.py:529 msgid "Cancel" msgstr "Отмена" #: spyder/widgets/projects/projectdialog.py:84 msgid "Create" msgstr "Создать" #: spyder/widgets/projects/projectdialog.py:102 msgid "Create new project" msgstr "Создать новый проект" #: spyder/widgets/projects/type/__init__.py:216 msgid "Empty project" msgstr "Пустой проект" #: spyder/widgets/projects/type/python.py:20 msgid "Python project" msgstr "Проект Python" #: spyder/widgets/projects/type/python.py:76 msgid "Python package" msgstr "Пакет Python" #: spyder/widgets/pydocgui.py:110 msgid "Module or package:" msgstr "Модуль или пакет:" #: spyder/widgets/shell.py:131 msgid "Save history log..." msgstr "Сохранить журнал истории..." #: spyder/widgets/shell.py:133 msgid "Save current history log (i.e. all inputs and outputs) in a text file" msgstr "" "Сохранить текущий журнал истории (т.е. все вводы и выводы) в текстовом файле" #: spyder/widgets/shell.py:253 msgid "Save history log" msgstr "Сохранить журнал истории" #: spyder/widgets/shell.py:256 msgid "History logs" msgstr "Журналы истории" #: spyder/widgets/shell.py:670 msgid "Copy without prompts" msgstr "Копировать без подтверждения" #: spyder/widgets/shell.py:673 spyder/widgets/shell.py:677 msgid "Clear line" msgstr "Очистить строку" #: spyder/widgets/shell.py:679 msgid "Clear shell" msgstr "Очистить оболочку" #: spyder/widgets/shell.py:683 msgid "Clear shell contents ('cls' command)" msgstr "Очистить содержание оболочки (команда 'cls')" #: spyder/widgets/shortcutssummary.py:42 msgid "Spyder Keyboard ShortCuts" msgstr "Комбинации клавиш Spyder" #: spyder/widgets/sourcecode/codeeditor.py:101 msgid "Go to line:" msgstr "Перейти к строке:" #: spyder/widgets/sourcecode/codeeditor.py:109 msgid "Line count:" msgstr "Количество строк:" #: spyder/widgets/sourcecode/codeeditor.py:1327 msgid "Breakpoint" msgstr "Точка останова" #: spyder/widgets/sourcecode/codeeditor.py:1328 msgid "Condition:" msgstr "Условие:" #: spyder/widgets/sourcecode/codeeditor.py:1733 msgid "Code analysis" msgstr "Анализ кода" #: spyder/widgets/sourcecode/codeeditor.py:1787 msgid "To do" msgstr "Список задач" #: spyder/widgets/sourcecode/codeeditor.py:2147 msgid "Removal error" msgstr "Ошибка удаления" #: spyder/widgets/sourcecode/codeeditor.py:2148 msgid "" "It was not possible to remove outputs from this notebook. The error is:\n" "\n" msgstr "" "Невозможно удалить результаты из блокнота. Ошибка:\n" "\n" #: spyder/widgets/sourcecode/codeeditor.py:2684 msgid "Clear all ouput" msgstr "Очистить вывод" #: spyder/widgets/sourcecode/codeeditor.py:2690 msgid "Go to definition" msgstr "Перейти к определению" #: spyder/widgets/sourcecode/codeeditor.py:2723 msgid "Zoom reset" msgstr "Восстановить масштаб" #: spyder/widgets/status.py:25 msgid "CPU and memory usage info in the status bar" msgstr "Информация об использовании ЦП и памяти в строке состояния" #: spyder/widgets/status.py:117 msgid "Memory:" msgstr "Память:" #: spyder/widgets/status.py:118 msgid "" "Memory usage status: requires the `psutil` (>=v0.3) library on non-Windows " "platforms" msgstr "" "Состояние использования памяти: требуется библиотека `psutil` (>=v0.3) на не-" "Windows платформах" #: spyder/widgets/status.py:134 msgid "CPU:" msgstr "ЦП:" #: spyder/widgets/status.py:135 msgid "CPU usage status: requires the `psutil` (>=v0.3) library" msgstr "Состояние использования ЦП: требуется библиотека `psutil` (>=v0.3)" #: spyder/widgets/status.py:162 msgid "Permissions:" msgstr "Доступ:" #: spyder/widgets/status.py:189 msgid "End-of-lines:" msgstr "Конец строки:" #: spyder/widgets/status.py:216 msgid "Encoding:" msgstr "Кодировка:" #: spyder/widgets/status.py:242 msgid "Line:" msgstr "Строка:" #: spyder/widgets/status.py:243 msgid "Column:" msgstr "Столбец:" #: spyder/widgets/tabs.py:274 msgid "Browse tabs" msgstr "Обзор вкладок" #: spyder/widgets/tabs.py:403 msgid "Close current tab" msgstr "Закрыть текущую вкладку" #: spyder/widgets/variableexplorer/arrayeditor.py:511 msgid "It was not possible to copy values for this array" msgstr "Не удалось скопировать значения этого массива" #: spyder/widgets/variableexplorer/arrayeditor.py:546 #: spyder/widgets/variableexplorer/arrayeditor.py:579 #: spyder/widgets/variableexplorer/dataframeeditor.py:697 #: spyder/widgets/variableexplorer/dataframeeditor.py:742 msgid "Format" msgstr "Форматировать" #: spyder/widgets/variableexplorer/arrayeditor.py:551 #: spyder/widgets/variableexplorer/dataframeeditor.py:701 msgid "Resize" msgstr "Изменить размер" #: spyder/widgets/variableexplorer/arrayeditor.py:554 #: spyder/widgets/variableexplorer/dataframeeditor.py:705 msgid "Background color" msgstr "Цвет фона" #: spyder/widgets/variableexplorer/arrayeditor.py:580 #: spyder/widgets/variableexplorer/dataframeeditor.py:743 msgid "Float formatting" msgstr "Форматирование чисел" #: spyder/widgets/variableexplorer/arrayeditor.py:588 msgid "Format (%s) is incorrect" msgstr "Формат (%s) неверный" #: spyder/widgets/variableexplorer/arrayeditor.py:624 msgid "Arrays with more than 3 dimensions are not supported" msgstr "Массивы с размерностью более 3 не поддерживаются" #: spyder/widgets/variableexplorer/arrayeditor.py:628 msgid "The 'xlabels' argument length do no match array column number" msgstr "Длина аргумента 'xlabels' не соответствует числу столбцов массива" #: spyder/widgets/variableexplorer/arrayeditor.py:632 msgid "The 'ylabels' argument length do no match array row number" msgstr "Длина аргумента 'ylabels' не соответствует числу строк массива" #: spyder/widgets/variableexplorer/arrayeditor.py:639 msgid "%s arrays" msgstr "%s массивы" #: spyder/widgets/variableexplorer/arrayeditor.py:640 msgid "%s are currently not supported" msgstr "%s на данный момент не поддерживается" #: spyder/widgets/variableexplorer/arrayeditor.py:647 msgid "NumPy array" msgstr "Массив NumPy" #: spyder/widgets/variableexplorer/arrayeditor.py:649 #: spyder/widgets/variableexplorer/arrayeditor.py:806 msgid "Array editor" msgstr "Редактор массивов" #: spyder/widgets/variableexplorer/arrayeditor.py:651 msgid "read only" msgstr "только чтение" #: spyder/widgets/variableexplorer/arrayeditor.py:681 msgid "Record array fields:" msgstr "Заполнить поля массива:" #: spyder/widgets/variableexplorer/arrayeditor.py:693 msgid "Data" msgstr "Данные" #: spyder/widgets/variableexplorer/arrayeditor.py:693 msgid "Mask" msgstr "Маска" #: spyder/widgets/variableexplorer/arrayeditor.py:693 msgid "Masked data" msgstr "Скрытые данные" #: spyder/widgets/variableexplorer/arrayeditor.py:704 msgid "Axis:" msgstr "Оси:" #: spyder/widgets/variableexplorer/arrayeditor.py:709 msgid "Index:" msgstr "Индекс:" #: spyder/widgets/variableexplorer/arrayeditor.py:722 msgid "Warning: changes are applied separately" msgstr "Предупреждение: изменения применяются раздельно" #: spyder/widgets/variableexplorer/arrayeditor.py:723 msgid "" "For performance reasons, changes applied to masked array won't be reflected " "in array's data (and vice-versa)." msgstr "" "По соображениям производительности, изменения принятые для скрытых массивов " "не будут отражены в данных массивов (и наоборот)." #: spyder/widgets/variableexplorer/collectionseditor.py:126 msgid "Index" msgstr "Индекс" #: spyder/widgets/variableexplorer/collectionseditor.py:131 msgid "Tuple" msgstr "Кортеж" #: spyder/widgets/variableexplorer/collectionseditor.py:134 msgid "List" msgstr "Список" #: spyder/widgets/variableexplorer/collectionseditor.py:137 msgid "Dictionary" msgstr "Словарь" #: spyder/widgets/variableexplorer/collectionseditor.py:139 msgid "Key" msgstr "Ключ" #: spyder/widgets/variableexplorer/collectionseditor.py:144 msgid "Attribute" msgstr "Атрибут" #: spyder/widgets/variableexplorer/collectionseditor.py:148 msgid "elements" msgstr "элементов" #: spyder/widgets/variableexplorer/collectionseditor.py:319 msgid "Size" msgstr "Размер" #: spyder/widgets/variableexplorer/collectionseditor.py:319 msgid "Type" msgstr "Тип" #: spyder/widgets/variableexplorer/collectionseditor.py:319 msgid "Value" msgstr "Значение" #: spyder/widgets/variableexplorer/collectionseditor.py:417 msgid "" "Opening this variable can be slow\n" "\n" "Do you want to continue anyway?" msgstr "" "Открытие этой переменной может занять время\n" "\n" "Желаете продолжить?" #: spyder/widgets/variableexplorer/collectionseditor.py:428 msgid "" "Spyder was unable to retrieve the value of this variable from the console." "

The error mesage was:
%s" msgstr "" "Spyder не смог извлечь значение этой переменной из консоли. " "

Сообщение об ошибке:
%s" #: spyder/widgets/variableexplorer/collectionseditor.py:605 msgid "Edit item" msgstr "Редактировать элемент" #: spyder/widgets/variableexplorer/collectionseditor.py:606 msgid "Unable to assign data to item.

Error message:
%s" msgstr "" "Невозможно назначить данные элементу.

Сообщение об ошибке:
" "%s" #: spyder/widgets/variableexplorer/collectionseditor.py:666 msgid "Resize rows to contents" msgstr "Размер строк по содержимому" #: spyder/widgets/variableexplorer/collectionseditor.py:677 #: spyder/widgets/variableexplorer/collectionseditor.py:1027 #: spyder/widgets/variableexplorer/collectionseditor.py:1044 msgid "Plot" msgstr "График" #: spyder/widgets/variableexplorer/collectionseditor.py:681 msgid "Histogram" msgstr "Гистограмма" #: spyder/widgets/variableexplorer/collectionseditor.py:685 msgid "Show image" msgstr "Показать изображение" #: spyder/widgets/variableexplorer/collectionseditor.py:689 #: spyder/widgets/variableexplorer/collectionseditor.py:1052 msgid "Save array" msgstr "Сохранить массив" #: spyder/widgets/variableexplorer/collectionseditor.py:693 #: spyder/widgets/variableexplorer/collectionseditor.py:991 #: spyder/widgets/variableexplorer/collectionseditor.py:999 msgid "Insert" msgstr "Вставить" #: spyder/widgets/variableexplorer/collectionseditor.py:706 #: spyder/widgets/variableexplorer/collectionseditor.py:952 msgid "Duplicate" msgstr "Создать копию" #: spyder/widgets/variableexplorer/collectionseditor.py:929 msgid "Do you want to remove the selected item?" msgstr "Вы хотите удалить выбранный элемент?" #: spyder/widgets/variableexplorer/collectionseditor.py:930 msgid "Do you want to remove all selected items?" msgstr "Вы хотите удалить все выбранные элементы?" #: spyder/widgets/variableexplorer/collectionseditor.py:950 msgid "New variable name:" msgstr "Новое имя переменной:" #: spyder/widgets/variableexplorer/collectionseditor.py:953 msgid "Variable name:" msgstr "Имя переменной:" #: spyder/widgets/variableexplorer/collectionseditor.py:991 msgid "Key:" msgstr "Ключ:" #: spyder/widgets/variableexplorer/collectionseditor.py:999 msgid "Value:" msgstr "Значение:" #: spyder/widgets/variableexplorer/collectionseditor.py:1015 msgid "Import error" msgstr "Ошибка импорта" #: spyder/widgets/variableexplorer/collectionseditor.py:1016 msgid "Please install matplotlib or guiqwt." msgstr "Пожалуйста, установите matplotlib или guiqwt." #: spyder/widgets/variableexplorer/collectionseditor.py:1028 msgid "Unable to plot data.

Error message:
%s" msgstr "" "Не удалось построить график по данным.

Сообщение об ошибке:
" "%s" #: spyder/widgets/variableexplorer/collectionseditor.py:1045 msgid "Unable to show image.

Error message:
%s" msgstr "" "Не удалось показать изображение.

Сообщение об ошибке:
%s" #: spyder/widgets/variableexplorer/collectionseditor.py:1068 msgid "Unable to save array

Error message:
%s" msgstr "Не удалось сохранить массив

Сообщение об ошибке:
%s" #: spyder/widgets/variableexplorer/collectionseditor.py:1093 msgid "It was not possible to copy this array" msgstr "Не удалось скопировать этот массив" #: spyder/widgets/variableexplorer/collectionseditor.py:1118 msgid "Clipboard contents" msgstr "Содержимое буфера обмена" #: spyder/widgets/variableexplorer/collectionseditor.py:1133 msgid "Import from clipboard" msgstr "Импортировать из буфера обмена" #: spyder/widgets/variableexplorer/collectionseditor.py:1135 msgid "Empty clipboard" msgstr "Очистить буфер обмена" #: spyder/widgets/variableexplorer/collectionseditor.py:1136 msgid "Nothing to be imported from clipboard." msgstr "Нечего импортировать из буфера обмена." #: spyder/widgets/variableexplorer/dataframeeditor.py:591 msgid "To bool" msgstr "В булево" #: spyder/widgets/variableexplorer/dataframeeditor.py:591 msgid "To complex" msgstr "В комплексное" #: spyder/widgets/variableexplorer/dataframeeditor.py:592 msgid "To float" msgstr "В вещественное" #: spyder/widgets/variableexplorer/dataframeeditor.py:592 msgid "To int" msgstr "В целое" #: spyder/widgets/variableexplorer/dataframeeditor.py:593 msgid "To str" msgstr "В строку" #: spyder/widgets/variableexplorer/dataframeeditor.py:677 msgid "%s editor" msgstr "%s редактор" #: spyder/widgets/variableexplorer/dataframeeditor.py:711 msgid "Column min/max" msgstr "Min/max столбца" #: spyder/widgets/variableexplorer/dataframeeditor.py:751 msgid "Format ({}) is incorrect" msgstr "Формат ({}) неверный" #: spyder/widgets/variableexplorer/dataframeeditor.py:755 msgid "Format ({}) should start with '%'" msgstr "Формат ({}) должен начинаться с '%'" #: spyder/widgets/variableexplorer/importwizard.py:118 #: spyder/widgets/variableexplorer/importwizard.py:438 msgid "Import as" msgstr "Импортировать как" #: spyder/widgets/variableexplorer/importwizard.py:120 msgid "data" msgstr "данные" #: spyder/widgets/variableexplorer/importwizard.py:124 msgid "code" msgstr "код" #: spyder/widgets/variableexplorer/importwizard.py:127 #: spyder/widgets/variableexplorer/importwizard.py:514 msgid "text" msgstr "текст" #: spyder/widgets/variableexplorer/importwizard.py:140 msgid "Column separator:" msgstr "Разделитель столбцов:" #: spyder/widgets/variableexplorer/importwizard.py:144 msgid "Tab" msgstr "табуляция" #: spyder/widgets/variableexplorer/importwizard.py:147 msgid "Whitespace" msgstr "пробельный символ" #: spyder/widgets/variableexplorer/importwizard.py:150 #: spyder/widgets/variableexplorer/importwizard.py:168 msgid "other" msgstr "другой" #: spyder/widgets/variableexplorer/importwizard.py:161 msgid "Row separator:" msgstr "Разделитель строк:" #: spyder/widgets/variableexplorer/importwizard.py:165 msgid "EOL" msgstr "Конец строки" #: spyder/widgets/variableexplorer/importwizard.py:180 msgid "Additional options" msgstr "Дополнительные опции" #: spyder/widgets/variableexplorer/importwizard.py:184 msgid "Skip rows:" msgstr "Пропустить строки:" #: spyder/widgets/variableexplorer/importwizard.py:195 msgid "Comments:" msgstr "Комментарии:" #: spyder/widgets/variableexplorer/importwizard.py:201 msgid "Transpose" msgstr "Транспонировать" #: spyder/widgets/variableexplorer/importwizard.py:441 msgid "array" msgstr "массив" #: spyder/widgets/variableexplorer/importwizard.py:446 msgid "list" msgstr "список" #: spyder/widgets/variableexplorer/importwizard.py:451 msgid "DataFrame" msgstr "DataFrame" #: spyder/widgets/variableexplorer/importwizard.py:497 #: spyder/widgets/variableexplorer/importwizard.py:581 msgid "Import wizard" msgstr "Мастер импорта" #: spyder/widgets/variableexplorer/importwizard.py:502 msgid "Raw text" msgstr "Необработанный текст" #: spyder/widgets/variableexplorer/importwizard.py:505 msgid "variable_name" msgstr "имя_переменной" #: spyder/widgets/variableexplorer/importwizard.py:516 msgid "table" msgstr "таблица" #: spyder/widgets/variableexplorer/importwizard.py:517 msgid "Preview" msgstr "Предварительный просмотр" #: spyder/widgets/variableexplorer/importwizard.py:521 msgid "Variable Name" msgstr "Имя переменной" #: spyder/widgets/variableexplorer/importwizard.py:544 msgid "Done" msgstr "Сделано" #: spyder/widgets/variableexplorer/importwizard.py:582 msgid "" "Unable to proceed to next step

Please check your entries." "

Error message:
%s" msgstr "" "Невозможно перейти к следующему шагу

Пожалуйста, проверьте " "введенные данные.

Сообщение об ошибке:
%s" #: spyder/widgets/variableexplorer/namespacebrowser.py:181 #: spyder/widgets/variableexplorer/namespacebrowser.py:385 msgid "Import data" msgstr "Импортировать данные" #: spyder/widgets/variableexplorer/namespacebrowser.py:184 #: spyder/widgets/variableexplorer/namespacebrowser.py:465 #: spyder/widgets/variableexplorer/namespacebrowser.py:479 msgid "Save data" msgstr "Сохранить данные" #: spyder/widgets/variableexplorer/namespacebrowser.py:189 msgid "Save data as..." msgstr "Сохранить данные как..." #: spyder/widgets/variableexplorer/namespacebrowser.py:201 msgid "Exclude references which name starts with an underscore" msgstr "Исключить ссылки, имена которых начинаются с подчёркивания" #: spyder/widgets/variableexplorer/namespacebrowser.py:209 msgid "Exclude references which name is uppercase" msgstr "Исключить ссылки с именем в верхнем регистре" #: spyder/widgets/variableexplorer/namespacebrowser.py:216 msgid "Exclude references which name starts with an uppercase character" msgstr "" "Исключить ссылки, имена которых начинаются с символа в верхнем регистре" #: spyder/widgets/variableexplorer/namespacebrowser.py:224 msgid "" "Exclude references to unsupported data types (i.e. which won't be handled/" "saved correctly)" msgstr "" "Исключить ссылки на неподдерживаемые типы данных (т.е. которые не будут " "правильно обработаны/сохранены)" #: spyder/widgets/variableexplorer/namespacebrowser.py:405 msgid "" "Unsupported file extension '%s'

Would you like to import it " "anyway (by selecting a known file format)?" msgstr "" "Неподдерживаемое расширение файла '%s'

Хотите его " "импортировать (выбрав известный формат файла)?" #: spyder/widgets/variableexplorer/namespacebrowser.py:413 msgid "Open file as:" msgstr "Открыть файл как:" #: spyder/widgets/variableexplorer/namespacebrowser.py:447 msgid "Unable to load '%s'

Error message:
%s" msgstr "Не удалось загрузить '%s'

Сообщение об ошибке:
%s" #: spyder/widgets/variableexplorer/namespacebrowser.py:480 msgid "Unable to save current workspace

Error message:
%s" msgstr "" "Невозможно сохранить текущую рабочую область

Сообщение об " "ошибке:
%s" #: spyder/widgets/variableexplorer/texteditor.py:74 msgid "Text editor" msgstr "Текстовый редактор" #: spyder/widgets/variableexplorer/utils.py:30 msgid "View and edit DataFrames and Series in the Variable Explorer" msgstr "" "Показ и редактирование структур DataFrame и Serie в Менеджере Переменных" #: spyder/widgets/variableexplorer/utils.py:35 msgid "View and edit two and three dimensional arrays in the Variable Explorer" msgstr "" "Просмотр и редактирование 2-х и 3-мерных массивов в Менеджере Переменных" #: spyder/workers/updates.py:90 spyder/workers/updates.py:92 msgid "Unable to retrieve information." msgstr "Невозможно получить информацию." #: spyder/workers/updates.py:94 msgid "" "Unable to connect to the internet.

Make sure the connection is " "working properly." msgstr "" "Не удалось подключиться к интернету.

Убедитесь, что соединение " "работает должным образом." #: spyder/workers/updates.py:97 msgid "Unable to check for updates." msgstr "Не удалось проверить обновления." #~ msgid "At startup, the current working directory is:" #~ msgstr "При запуске текущий рабочий каталог:" #, fuzzy #~ msgid "At startup," #~ msgstr "При запуске " #~ msgid "At startup, the current working directory will be the specified path" #~ msgstr "При запуске текущий рабочий каталог будет иметь указанный путь" #~ msgid "Reset namespace" #~ msgstr "Перезагрузить пространство имён" #~ msgid "Reset IPython namespace" #~ msgstr "Перезагрузить пространство имён IPython" #~ msgid "Loading external console..." #~ msgstr "Загрузка внешней консоли..." #~ msgid "The Python console" #~ msgstr "Консоль Python" #~ msgid "" #~ "You can also run your code on a Python console. These consoles are useful " #~ "because they let you run a file in a console dedicated only to it.To " #~ "select this behavior, please press the F6 key.

By pressing " #~ "the button below and then focusing the Variable Explorer, you will notice " #~ "that Python consoles are also connected to that pane, and that the " #~ "Variable Explorer only shows the variables of the currently focused " #~ "console." #~ msgstr "" #~ "Вы также можете запустить свой код в консоли Python. Эти консоли полезны, " #~ "поскольку они позволяют запускать файл в консоли, предназначенной только " #~ "для него. Чтобы выбрать такое поведение, нажмите клавишу F6." #~ "

Нажав на кнопку ниже и перейдя к Менеджеру Переменных, Вы " #~ "заметите, что консоли Python также подключены к этой панели, и что " #~ "Менеджер Переменных отображает только переменные текущей выбранной " #~ "консоли." #~ msgid "Sort files according to full path" #~ msgstr "Сортировать файлы по полному пути" #~ msgid "&Configure..." #~ msgstr "&Настроить" #~ msgid "Show TODO/FIXME/XXX/HINT/TIP/@todo comments list" #~ msgstr "Показать список комментариев TODO/FIXME/XXX/HINT/TIP/@todo" #~ msgid "Interactive data plotting in the consoles" #~ msgstr "Интерактивные графики в консолях" #~ msgid "Python console" #~ msgstr "Консоль Python" #~ msgid "One tab per script" #~ msgstr "Одна вкладка на скрипт" #~ msgid "Buffer: " #~ msgstr "Буфер: " #~ msgid "Merge process standard output/error channels" #~ msgstr "Объединить стандартные потоки вывода/ошибок" #~ msgid "" #~ "Merging the output channels of the process means that\n" #~ "the standard error won't be written in red anymore,\n" #~ "but this has the effect of speeding up display." #~ msgstr "" #~ "Объединение потоков вывода процесса означает, что\n" #~ "стандартные ошибки не будут более выделяться красным,\n" #~ "но это увеличит скорость отображения на дисплее." #~ msgid "Colorize standard error channel using ANSI escape codes" #~ msgstr "Выделить цветом стандартный поток ошибок управляющими кодами ANSI" #~ msgid "" #~ "This method is the only way to have colorized standard\n" #~ "error channel when the output channels have been merged." #~ msgstr "" #~ "Это единственный способ цветового выделения стандартного\n" #~ "потока ошибок, когда потоки вывода объединены." #~ msgid "" #~ "This option will be applied the next time a Python console or a terminal " #~ "is opened." #~ msgstr "" #~ "Эта опция будет применена при следующем открытии консоли Python
или " #~ "терминала." #~ msgid "Light background (white color)" #~ msgstr "Светлый фон (белый цвет)" #~ msgid "PYTHONSTARTUP replacement" #~ msgstr "Замена PYTHONSTARTUP" #~ msgid "" #~ "This option will override the PYTHONSTARTUP environment variable which\n" #~ "defines the script to be executed during the Python console startup." #~ msgstr "" #~ "Эта опция перезапишет переменную среды PYTHONSTARTUP, которая\n" #~ "определяет скрипт, запускаемый при старте консоли Python." #~ msgid "Default PYTHONSTARTUP script" #~ msgstr "Скрипт PYTHONSTARTUP по умолчанию" #~ msgid "Use the following startup script:" #~ msgstr "Использовать следующий скрипт запуска:" #~ msgid "Monitor" #~ msgstr "Монитор" #~ msgid "" #~ "The monitor provides introspection features to console: code completion, " #~ "calltips and variable explorer. Because it relies on several modules, " #~ "disabling the monitor may be useful to accelerate console startup." #~ msgstr "" #~ "Монитор обеспечивает возможность самоанализа в консоли: автодополнение, " #~ "подсказки вызова функций и менеджер переменных. Так как он зависит от " #~ "нескольких модулей, отключение монитора может быть полезно для ускорения " #~ "запуска консоли." #~ msgid "Enable monitor" #~ msgstr "Включить монитор" #~ msgid "Default library" #~ msgstr "Библиотека по умолчанию" #~ msgid "Qt-Python Bindings" #~ msgstr "Привязка Qt-Python" #~ msgid "Library:" #~ msgstr "Библиотека:" #~ msgid "" #~ "This option will act on
libraries such as Matplotlib, guidata or ETS" #~ msgstr "" #~ "Эта опция будет действовать на
\n" #~ "библиотеки, такие как Matplotlib, guidata или ETS" #~ msgid "" #~ "Decide which backend to use to display graphics. If unsure, please select " #~ "the Automatic backend.

Note: We support a very " #~ "limited number of backends in our Python consoles. If you prefer to work " #~ "with a different one, please use an IPython console." #~ msgstr "" #~ "Выберите какой бэкенд использовать для отображения графики. Если не " #~ "уверены, выберите Автоматически.

Примечание: Мы " #~ "поддерживаем очень ограниченный набор бэкендов в консолях Python. Если Вы " #~ "предпочитаете работать с другим, пожалуйста используйте консоль IPython." #~ msgid "None" #~ msgstr "Отсутствует" #~ msgid "Enthought Tool Suite" #~ msgstr "Набор инструментов Enthought" #~ msgid "" #~ "Enthought Tool Suite (ETS) supports PyQt4 (qt4) and wxPython (wx) " #~ "graphical user interfaces." #~ msgstr "" #~ "Enthought Tool Suite (ETS) поддерживает графические пользовательские " #~ "интерфейсы PyQt4 (qt4) и wxPython (wx)." #~ msgid "ETS_TOOLKIT:" #~ msgstr "ETS_TOOLKIT:" #~ msgid "External modules" #~ msgstr "Внешние модули" #~ msgid "" #~ "No Python console is currently selected to run %s.

Please " #~ "select or open a new Python console and try again." #~ msgstr "" #~ "Сейчас нет доступных консолей Python для запуска %s." #~ "

Пожалуйста, откройте новую и попытайтесь снова." #~ msgid "" #~ "%s is already running in a separate process.\n" #~ "Do you want to kill the process before starting a new one?" #~ msgstr "" #~ "%s всегда запускается в отдельном процессе.\n" #~ "Хотите убить процесс перед запуском нового?" #~ msgid "Command Window" #~ msgstr "Командное окно" #~ msgid "Open a &Python console" #~ msgstr "Открыть консоль &Python" #~ msgid "Open &command prompt" #~ msgstr "Открыть &командную строку" #~ msgid "Open a Windows command prompt" #~ msgstr "Открыть командную строку Windows" #~ msgid "Open a &terminal" #~ msgstr "Открыть &терминал" #~ msgid "Open a terminal window" #~ msgstr "Открыть окно терминала" #~ msgid "Python Console" #~ msgstr "Консоль Python" #~ msgid "Light background" #~ msgstr "Светлый фон" #~ msgid "Dark background" #~ msgstr "Тёмный фон" #~ msgid "Working directory:" #~ msgstr "Рабочий каталог:" #~ msgid "Dedicated Python console" #~ msgstr "Отдельная консоль Python" #~ msgid "Show warning when killing running process" #~ msgstr "Показывать предупреждение при завершении работающего процесса" #~ msgid "Run Settings" #~ msgstr "Настройки Запуска" #~ msgid "the script directory" #~ msgstr "каталог скриптов" #~ msgid "Show warning when killing running processes" #~ msgstr "Показывать предупреждение при завершении работающих процессов" #~ msgid "Autorefresh" #~ msgstr "Автообновление" #~ msgid "Enable autorefresh" #~ msgstr "Включить автообновление" #~ msgid "Refresh interval: " #~ msgstr "Интервал обновления: " #~ msgid "" #~ "The global working directory is the working directory for newly " #~ "opened consoles (Python/IPython consoles and terminals), for the " #~ "file explorer, for the find in files plugin and for new " #~ "files created in the editor." #~ msgstr "" #~ "Глобальный рабочий каталог - рабочий каталог для новых " #~ "консолей (консоли и терминалы Python/IPython), для файлового " #~ "менеджера, для модуля поиск по файлам и для новых файлов в " #~ "редакторе." #~ msgid "the same as in last session" #~ msgstr "такой же как в последней сессии" #~ msgid "" #~ "At startup, Spyder will restore the global directory from last session" #~ msgstr "" #~ "При загрузке Spyder восстановит глобальный каталог из прошлой сессии" #~ msgid "Files are opened from:" #~ msgstr "Файлы открываются из:" #~ msgid "the current file directory" #~ msgstr "текущий каталог" #~ msgid "the global working directory" #~ msgstr "глобальный рабочий каталог" #~ msgid "Files are created in:" #~ msgstr "Файлы создаются в:" #~ msgid "Change to file base directory" #~ msgstr "Изменить на каталог файла" #~ msgid "When opening a file" #~ msgstr "При открытии файла" #~ msgid "When saving a file" #~ msgstr "При сохранении файла" #~ msgid "Global working directory" #~ msgstr "Глобальный рабочий каталог" #~ msgid "Unable to save script '%s'

Error message:
%s" #~ msgstr "" #~ "Не удалось сохранить скрипт '%s'

Сообщение об ошибке:
%s" #~ msgid "Run again this program" #~ msgstr "Запустить эту программу снова" #~ msgid "Kill" #~ msgstr "Убить" #~ msgid "Kills the current process, causing it to exit immediately" #~ msgstr "Убивает текущий процесс, заставляя его немедленно завершиться" #~ msgid "Running..." #~ msgstr "Запуск..." #~ msgid "Terminated." #~ msgstr "Прекращено." #~ msgid "Command line arguments:" #~ msgstr "Аргументы командной строки:" #~ msgid "" #~ "NOTE: The Python console is going to be REMOVED in Spyder 3.2. Please " #~ "start to migrate your work to the IPython console instead.\n" #~ "\n" #~ msgstr "" #~ "ВНИМАНИЕ: Консоль Python будет УДАЛЕНА в Spyder 3.2. Пожалуйста, начните " #~ "переход на использование консоли IPython.\n" #~ "\n" #~ msgid "Variables" #~ msgstr "Значения" #~ msgid "Show/hide global variables explorer" #~ msgstr "Показать/скрыть менеджер глобальных переменных" #~ msgid "Terminate" #~ msgstr "Прекратить" #~ msgid "" #~ "Attempts to stop the process. The process\n" #~ "may not exit as a result of clicking this\n" #~ "button (it is given the chance to prompt\n" #~ "the user for any unsaved files, etc)." #~ msgstr "" #~ "Попытка остановить процесс. Процесс\n" #~ "имеет право не завершится после нажатия этой\n" #~ "кнопки (например, чтобы спросить у пользователя\n" #~ "о несохранённых файлах и т.п.)." #~ msgid "Interact" #~ msgstr "Интерактивный" #~ msgid "Debug" #~ msgstr "Отладка" #~ msgid "Arguments..." #~ msgstr "Аргументы..." #~ msgid "Post Mortem Debug" #~ msgstr "Отладка в случае падения" #~ msgid "Arguments: %s" #~ msgstr "Аргументы: %s" #~ msgid "No argument" #~ msgstr "Нет аргументов" #~ msgid "A Python console failed to start!" #~ msgstr "Консоль Python не удалось запустить!" #~ msgid "Process failed to start" #~ msgstr "Процесс не удалось запустить" #~ msgid "Included filenames pattern" #~ msgstr "Шаблон имён влючаемых файлов" #~ msgid "Include:" #~ msgstr "Включить:" #~ msgid "PYTHONPATH" #~ msgstr "PYTHONPATH" #~ msgid "" #~ "Search in all directories listed in sys.path which are outside the Python " #~ "installation directory" #~ msgstr "" #~ "Искать во всех каталогах, указанных в sys.path, которые отсутствуют в " #~ "установочном каталоге Python" #~ msgid "Hg repository" #~ msgstr "Hg-репозиторий" #~ msgid "Search in current directory hg repository" #~ msgstr "Поиск в текущем каталоге hg-репозитория" #~ msgid "Here:" #~ msgstr "Здесь:" #~ msgid "Search recursively in this directory" #~ msgstr "Искать рекурсивно в каталоге" #~ msgid "Browse a search directory" #~ msgstr "Выбрать каталог поиска" #~ msgid "Search canceled" #~ msgstr "Поиск отменён" #~ msgid "interrupted" #~ msgstr "прервано" #~ msgid "" #~ "
Restarting kernel because an error occurred while debugging\n" #~ "

" #~ msgstr "" #~ "
Перезапуск ядра из-за ошибки в процессе отладки\n" #~ "

" #~ msgid "" #~ "Inspecting and setting values while debugging in IPython consoles is not " #~ "supported yet by Spyder." #~ msgstr "" #~ "Spyder не поддерживет просмотр и установку значений во время отладки в " #~ "консоли IPython." #~ msgid "Refresh" #~ msgstr "Обновить" #~ msgid "Refresh periodically" #~ msgstr "Обновлять периодически" #~ msgid "Python(x,y)" #~ msgstr "Python(x,y)" #~ msgid "Python(x,y) launcher" #~ msgstr "Загрузчик Python(x,y)" #~ msgid "Python(x,y) documentation folder" #~ msgstr "Каталог с документацией Python(x,y)" #~ msgid "guidata documentation" #~ msgstr "Документация guidata" #~ msgid "guiqwt documentation" #~ msgstr "Документация guiqwt" #~ msgid "NumPy documentation" #~ msgstr "Документация NumPy" #~ msgid "NumPy reference guide" #~ msgstr "Справочное руководство NumPy" #~ msgid "NumPy user guide" #~ msgstr "Руководство пользователя NumPy" #~ msgid "SciPy documentation" #~ msgstr "Документация SciPy" #~ msgid "Show/hide project explorer" #~ msgstr "Показать/скрыть менеджер проектов" #~ msgid "?" #~ msgstr "?" #~ msgid "Use %s+T when the console is selected to open a new one" #~ msgstr "Используйте %s+T когда консоль выбрана, чтобы открыть новую" #~ msgid "Edit data in the remote process" #~ msgstr "Редактировать данные в удалённом процессе" #~ msgid "" #~ "Editors are opened in the remote process for NumPy arrays, PIL images, " #~ "lists, tuples and dictionaries.\n" #~ "This avoids transfering large amount of data between the remote process " #~ "and Spyder (through the socket)." #~ msgstr "" #~ "Редакторы открыты в удалённом процессе для массивов NumPy, изображений " #~ "PIL, списков, кортежей и словарей.\n" #~ "Это позволяет избежать передачи больших объёмов данных между удалённым " #~ "процессом и Spyder (через сокет)." #~ msgid "Array is empty" #~ msgstr "Массив пустой" #~ msgid "Object %s is not picklable" #~ msgstr "Объект %s не сериализуем" #~ msgid "Truncate values" #~ msgstr "Обрезать значения" #~ msgid "" #~ "\n" #~ "\n" #~ "{0}" #~ msgstr "" #~ "\n" #~ "\n" #~ "{0}" #~ msgid "Reload last session" #~ msgstr "Перезапустить последнюю сессию" #~ msgid "Load session..." #~ msgstr "Загрузить сессию..." #~ msgid "Load Spyder session" #~ msgstr "Загрузить сессию Spyder" #, fuzzy #~ msgid "Save session..." #~ msgstr "Сохранить сессию" #~ msgid "Save current session and quit application" #~ msgstr "Сохранить текущую сессию и закрыть приложение" #~ msgid "Open session" #~ msgstr "Открыть сессию" #~ msgid "Spyder sessions" #~ msgstr "Сессии Spyder" #~ msgid "Save session" #~ msgstr "Сохранить сессию" #~ msgid "Jupyter Qtconsole integration" #~ msgstr "Интеграция Qt-консоли Jupyter" #~ msgid "Python executable" #~ msgstr "Исполняемый файл Python" #~ msgid "Trying to kill a kernel?" #~ msgstr "Попытаться убить ядро?" #~ msgid "" #~ "You can't close this kernel because it has one or more consoles connected " #~ "to it.

You need to close them instead or you can kill the kernel " #~ "using the second button from right to left." #~ msgstr "" #~ "Вы не можете закрыть это ядро, т.к. к нему подключены одна или более " #~ "консолей

Сначала Вам нужно их закрыть или можете убить ядро второй " #~ "кнопкой справа." #~ msgid "Kernel" #~ msgstr "Ядро" #, fuzzy #~ msgid "" #~ "Either:
  1. Your IPython frontend and kernel versions are " #~ "incompatible or
  2. You don't have IPython installed in " #~ "your external interpreter.
In any case, we're sorry but we can't " #~ "create a console for you." #~ msgstr "" #~ "Либо:
  1. версии Ваших пользовательского и ядерного IPython " #~ "несовместимы, либо
  2. у Вас не установлен IPython в " #~ "Вашем внешнем интерпретаторе.
В любом случае, мы сожалеем, что " #~ "не можем создать консоль для Вас." #~ msgid "Kernel %s" #~ msgstr "Ядро %s" #~ msgid "Open an IPython console" #~ msgstr "Открыть консоль IPython" #~ msgid "" #~ "The console monitor was disabled: the IPython kernel will be started as " #~ "expected, but an IPython console will have to be connected manually to " #~ "the kernel." #~ msgstr "" #~ "Монитор консоли был отключен: ядро IPython будет запущено как ожидалось, " #~ "но консоль IPython нужно будет подключить к ядру вручную." #~ msgid "" #~ "UMR excluded modules:\n" #~ "(example: guidata, guiqwt)" #~ msgstr "" #~ "Модули-исключения для UMR:\n" #~ "(например: guidata, guiqwt)" #~ msgid "" #~ "This feature requires the Matplotlib library.\n" #~ "It seems you don't have it installed." #~ msgstr "" #~ "Эта функция требует библиотеку Matplotlib.\n" #~ "Похоже, Вы её не установили." #~ msgid "" #~ "This feature requires the Sympy library.\n" #~ "It seems you don't have it installed." #~ msgstr "" #~ "Эта функция требует библиотеку Sympy.\n" #~ "По-видимому, она не установлена." #~ msgid "&Font..." #~ msgstr "&Шрифт" #~ msgid "Set font style" #~ msgstr "Установить стиль шрифта" #~ msgid "Select a new font" #~ msgstr "Выбрать новый шрифт" #~ msgid "" #~ "The kernel failed to start!! That's all we know... Please close this " #~ "console and open a new one." #~ msgstr "" #~ "Ошибка запуска ядра!! Это всё, что известно... Пожалуйста, закройте " #~ "консоль и откройте новую." #~ msgid "" #~ "It seems the kernel died unexpectedly. Use 'Restart kernel' to continue " #~ "using this console." #~ msgstr "" #~ "По видимому ядро неожиданно умерло. Используйте 'Перезапустить ядро' для " #~ "продолжения работы в консоли." #~ msgid "Kernel process is either remote or unspecified. Cannot interrupt" #~ msgstr "" #~ "Процесс ядра либо подключён удалённо, либо неопределим. Невозможно " #~ "прервать" #~ msgid "Kernel process is either remote or unspecified. Cannot restart." #~ msgstr "" #~ "Процесс ядра либо подключён удалённо, либо неопределим. Невозможно " #~ "перезапустить." #~ msgid "its own configuration file" #~ msgstr "его собственный файл конфигурации" #~ msgid " and " #~ msgstr " и " #~ msgid "the following projects:
%s" #~ msgstr "следующие проекты:
%s" #~ msgid "Existing Pydev project" #~ msgstr "Существующий проект Pydev" #~ msgid "Close unrelated projects" #~ msgstr "Закрыть несвязанные проекты" #~ msgid "Edit related projects" #~ msgstr "Редактировать связанные проекты" #~ msgid "Add to PYTHONPATH" #~ msgstr "Добавить в PYTHONPATH" #~ msgid "Remove from PYTHONPATH" #~ msgstr "Удалить из PYTHONPATH" #~ msgid "Properties" #~ msgstr "Свойства" #~ msgid "" #~ "The workspace was unable to load or save %s

Please check if you " #~ "have the permission to write the associated configuration files." #~ msgstr "" #~ "Рабочую область не удалось загрузить или сохранить %s

Пожалуйста, " #~ "проверьте, достаточно ли у Вас прав для записи соответствующих файлов " #~ "конфигурации." #~ msgid "Import directory" #~ msgstr "Импортировать каталог" #~ msgid "" #~ "The following directory is not in workspace:
%s

Do you " #~ "want to continue (and copy the directory to workspace)?" #~ msgstr "" #~ "Выбранного каталога нет в рабочей области:
%s

Хотите " #~ "продолжить (и скопировать каталог в область)?" #~ msgid "The project %s is already opened!" #~ msgstr "Проект %s уже открыт!" #~ msgid "" #~ "The project root path directory is inside the workspace but not as the " #~ "expected tree level. It is not a directory of the workspace:
%s" #~ msgstr "" #~ "Корневой каталог проекта находится в рабочей области, но не в качестве " #~ "ожидаемого уровня дерева. Он не является каталогом рабочей области:
" #~ "%s" #~ msgid "A project named %s already exists" #~ msgstr "Проект с именем %s уже существует" #~ msgid "" #~ "Invalid project name.

Name must match the following regular " #~ "expression:
%s" #~ msgstr "" #~ "Неверное имя проекта.

Название должно соответствовать регулярному " #~ "выражению:
%s" #~ msgid "" #~ "The following directory is not empty:
%s

Do you want to " #~ "continue?" #~ msgstr "Выбранный каталог не пуст:
%s

Хотите продолжить?" #~ msgid "New project" #~ msgstr "Новый проект" #~ msgid "" #~ "The current workspace has not been configured yet.\n" #~ "Do you want to do this now?" #~ msgstr "" #~ "Текущая рабочая область ещё не сконфигурирована.\n" #~ "Сделать это сейчас?" #~ msgid "Import existing project" #~ msgstr "Импортировать существующий проект" #~ msgid "Select projects to import" #~ msgstr "Выбрать проекты для импорта" #~ msgid "The folder %s does not contain a valid %s project" #~ msgstr "Каталог %s не содержит подходящего проекта %s" #~ msgid "Import existing Pydev project" #~ msgstr "Импортировать существующий проект Pydev" #~ msgid "" #~ "Unable to read Pydev project %s

Error message:
%s" #~ msgstr "" #~ "Не удалось прочитать проект Pydev %s

Сообщение об " #~ "ошибке:
%s" #~ msgid "Select projects which are related to %s" #~ msgstr "Выбранные проекты связаны с %s" #~ msgid "" #~ "Statistics on source files only:
(Python, Cython, IPython, Enaml,C/C+" #~ "+, Fortran)

%s files.
%s lines of code." #~ msgstr "" #~ "Статистика по исходному коду только:
(Python, Cython, IPython, Enaml,C/" #~ "C++, Fortran)

%s файлов.
%s строк кода." #~ msgid "Select an existing workspace directory, or create a new one" #~ msgstr "Выберите каталог рабочей области или создайте новый" #~ msgid "" #~ "What is the workspace?

A Spyder workspace is " #~ "a directory on your filesystem that contains Spyder projects and ." #~ "spyderworkspace configuration file.

A Spyder project is " #~ "a directory with source code (and other related files) and a " #~ "configuration file (named .spyderproject) with project settings " #~ "(PYTHONPATH, linked projects, ...).
" #~ msgstr "" #~ "Что такое рабочая область?

A Рабочая область " #~ "Spyder - каталог в вашей файловой системе, содержащий проекты Spyder " #~ "и файл конфигурации .spyderworkspace.

A Проект Spyder - каталог с исходным кодом (и другими связанными файлами) и " #~ "конфигурационным файлом (с расширением .spyderproject), содержащим " #~ "настройки проекта (PYTHONPATH, взаимосвязанные проекты и т.п.)." #~ msgid "This is the current workspace directory" #~ msgstr "Это текущий каталог рабочей области" #~ msgid "" #~ "The following directory is not a Spyder workspace:
%s

Do you " #~ "want to create a new workspace in this directory?" #~ msgstr "" #~ "Выбранный каталог не является рабочей областью Spyder:
" #~ "%s

Хотите создать новую рабочую область в этом каталоге?" #~ msgid "Unable to retrieve data.

Error message:
%s" #~ msgstr "Не удалось вывести данные.

Сообщение об ошибке:
%s" #~ msgid "Save session and quit..." #~ msgstr "Сохранить сессию и выйти..." #~ msgid "Breakpoints" #~ msgstr "Точки останова" #~ msgid "Exit" #~ msgstr "Выход" #~ msgid "Exit Debug" #~ msgstr "Завершить отладку" #~ msgid "Updates" #~ msgstr "Обновления" #~ msgid "Set shell font style" #~ msgstr "Установить стиль шрифта среды" #~ msgid "Text and margin font style" #~ msgstr "Стиль шрифта текста и отступов" #~ msgid "tab" #~ msgstr "табуляция" #~ msgid "Rich text help on the Object Inspector" #~ msgstr "Форматированная справка в Инспекторе объектов" #~ msgid "Object inspector" #~ msgstr "Инспектор объектов" #~ msgid "Preferences > Object Inspector" #~ msgstr "Параметры > Инспектор объектов" #~ msgid "Set as current console's working directory" #~ msgstr "Установить рабочую папку для текущей консоли" #~ msgid "Loading object inspector..." #~ msgstr "Загрузка инспектора объектов..." #~ msgid "The Object Inspector" #~ msgstr "Инспектор объектов" #~ msgid "(Experimental) Editor's code completion, go-to-definition and help" #~ msgstr "" #~ "(Experimental) Автодополнение кода редактора, переход к определению и " #~ "справка" #~ msgid "" #~ "This path is incorrect.\n" #~ "Enter a correct directory path,\n" #~ "then press enter to validate" #~ msgstr "" #~ "Этот путь неверный.\n" #~ "Введите правильный путь к папке и\n" #~ "нажмите Enter для подтверждения." #~ msgid "Save Python script" #~ msgstr "Сохранить скрипт Python" #~ msgid "Vertical dockwidget tabs" #~ msgstr "Разместить вертикально вкладки плавающих окон" #~ msgid "Custom dockwidget margin:" #~ msgstr "Дополнительный отступ между плавающими окнами:" #~ msgid "" #~ "Note: add analysis:ignore in a comment to ignore code/style " #~ "analysis warnings. For more informations on style guide for Python code, " #~ "please refer to the %s page." #~ msgstr "" #~ "Примечание: добавлять analysis:ignore в комментарий для " #~ "игнорирования предупреждений анализа кода/стиля. Для дополнительной " #~ "информации по стилю кода Python, перейдите на страницу %s." #~ msgid "Run &selection" #~ msgstr "Выполнить в&ыделение" #~ msgid "(for example: kernel-3764.json, or simply 3764)" #~ msgstr "(например: kernel-3764.json, или просто 3764)" #~ msgid "Mismatch between kernel and frontend" #~ msgstr "Несовместимость ядра и интерфейса" #~ msgid "" #~ "Your IPython frontend and kernel versions are incompatible!!

We're sorry but we can't create an IPython console for you." #~ msgstr "" #~ "Версии Ваших интерфейса и ядра IPython несовместимы!!

Мы " #~ "извиняемся, но мы не можем создать консоль IPython." #~ msgid "" #~ "%s will be closed.\n" #~ "Do you want to kill the associated kernel and all of its clients?" #~ msgstr "" #~ "%s была закрыта.\n" #~ "Хотите убить связанное ядро и все его клиенты?" #~ msgid "Filter:" #~ msgstr "Фильтр:" #~ msgid "(press Enter to edit file)" #~ msgstr "(нажмите Enter для редактирования файла)" #~ msgid "&Edit file" #~ msgstr "&Редактировать файл" #~ msgid "&Close file" #~ msgstr "&Закрыть файл" #~ msgid "Hint: press Alt to show accelerators" #~ msgstr "Совет: нажмите Alt, чтобы увидеть акселераторы" #~ msgid "Import as array" #~ msgstr "Импортировать как массив" #~ msgid "Interrupt kernel" #~ msgstr "Прервать ядро" spyder-3.2.6/spyder/locale/pt_BR/0000775000175000017500000000000013225025006017370 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/locale/pt_BR/LC_MESSAGES/0000775000175000017500000000000013225025007021156 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/locale/pt_BR/LC_MESSAGES/spyder.mo0000664000175000017500000027036313224121062023031 0ustar carloscarlos00000000000000 )=RYRwS sU UUUUU U UUUUUU UV VV !V +V5V ;VIVRVZV_VgVmVuV|VVVVVVVVWVbW<|W"WxW4UXXY9ZAZB5[Dx[Q[1\6A\;x\7\c\BP]7]C];^8K^t^!^__!aaa.bHcLc Ucacrc2ccccccdOd ed od}d\d"d* e8eAe ]e,he,e ee e4e#)f#Mf qf{ff Cg OgYgsgg0g%g;g7-h*eh6hhhh hh h ii ii&iAi Si_i fi pizii i i i+i8ijj#j.*jYj'ojjjj-j k-%k!Skukkkkk k kll 4l$@lelul lllllllm m 2m?mNmSm om#}m mmmmmmmn!n>n GnQnXn hn tnn nnnnnn n oo(oDoUotooooo o+op$p?pRp dp rpp%ppppp p p qq"q8q%6r#\r r rHrIr-s KsWs ^sls {s ss ssss's t+tQtQ"u"tu)u(uuv vvvv4v Mv Wvev vv3vv vv w w wx x&xCxYxrxxx xxxZx*Ky7vy@yyzz 2z>z Qz\zmz|z zzzzz> { J{ X{f{ w{{{ {{ {{ {.{ || -| N| [| e|p|w|M}|m|9}@}Y}!r}} }}}} }}}~~'~8~ Q~ _~&k~~*~~ ~ (:BGO7 " 0:Qhz  ā с܁  3 EP{_ f p | {) 0Qjp w Շ 0,] oyƈ ؈K#=o&1ԉ`Ig9d<P  NjӋ"+>ی ,29SY ^l܍,HQ V a n>{*ώ  ,E[k~!T=6t{  $ ,6 EQY al q  ő Б ۑ  *5:Ogbʒ" "&/ V bo ˓ϓ /ޔ :;Tm   ˕Bؕ#+ :E X fqw~$&+ӗ  *M:2%љRCJ3 ǚ Ԛ+"!Bd&< MYj~  ѝٝ) > KXkz  Оܞ1/4JSg%+ß4N ao5v ˠ  *, Weu{ ġܡ#* BNVe u!Ң #26Ug{ ̣գ75Uf o {  Ȥ,ԤD FP Ua$p E , > HUfz "֦ݦ ' 0;W ht5'U#Uy=|g4^/Oir  Ъܪ\9q"ѫDUo Ӭ *7 FTm  ȭέ֭ ݭ!%-S#d <¯ԯo892GYitxSA IV ^i n x, ųѳ!%5J[+p C: F Wcgy  ͵=ص: Q\n~f1Ahз+9e;:7irܹ-["~ TW nc>{#P/tM !*18IZ cm'DXc &&"/RY[o9$:J^%p}Ytz  <GQ#   }h w ns;IYK-y   % *5:)@jq     v:   +3<DM cmt     + 6 A LiWi8+'dw388QEPP!NrVAFZHJ|5SF[MLLrC*/! 8O+ {  C5 IToar,(2 2* ] ~$6/'(PYb ? J"Vy7?9B8|= &-<D[$c  ( ;6rwH*& ?G..+!/M}3 "!8 Z)g% *?Sdw $) "4Qcy!   9"Cf~ =$&Kk+r!.5;!Acy +&. 4>NcvJS'JLK$   (7Jc1 X;R+1(En %(  #5G(Nw #  /I`z!. @45&9`$i  ) ;)K(u: .9@Sf { 76EN^eVlF N m $          5 T &d   ' & ' !$ F Y  b l |    !      3 S ^i   +@Pb k y$}#   %8 V"b*, " ,<TixQ8!%Z1gB;]]?7 @ M[ o} !4:@Qo$&%$> cqyA-5>Oex$'V/ ?   # 2 7 I N ^ n          !!!6!mM!"!,!& " 2"<@" }""""""# # #!#$ $4%$Z$`$o$A$$$$ %"%6% T%b%v%N%%%% &&'& 7&A&J&S&Y&_&e&0{&&&-p'5' ''' ' (U(:j(5)%)d*Of**.** * +P!+&r,&,,K-_-h---- ---.+.;.T.)d.....!./*/:/K/ `/n/}// / /// //4/.030Q0$h0!0+0+0+131E1e1Bm1111A12/2E2`2 i2"u2221222 33(53^3p33'3)3 3&4 .4 ;4E4V4 h4 t4~4!4!4(455,5<5P5"Y5|5555"556,6=6DT6966667!#7E7^7}767@7 888.8'G8 o8}8K88 899.9=9O9a9=v9999)99::,:G: Y:d:$t::::A:-;G;lf;!;2;!(<FJ<<4=HP=u=->9=>w>>>> >0>>?.?I?f?l?A?&/@V@-q@"@D@#A+ACARAlA0AAAA B2BHBaB$~BB(BBBC C C !C-C6C =CKC%\CC/CC-CD 'D5D[:EE>EFGGD:GFGGGGHHr-H_H I II(I8IGIeI/~III IIII0J8JLJiJJ)J JPJ$K3KCDKK K KKK KK L!L*L0L@LXRLWLM M%M9MKMtfM6MNN(0OYOB.P?qPmPQ29QdlQQ)QR TVVmW~/XFXX\9\M^Pf_4_ ` `aa a *a6aKa`aua$~aaaaa0Cb'tbhb%c*+c Vcbc'kcc1c ccSc'Odwd7{ddddde4eLefeye*e'f-f4fFf_frfffff<fK(gtgzg+gg!gghh hhhiii i itiTjj4knk+m<m o o $o1o 8oCoKoRoXo`o donovooo ooooooo*p/p6pVpfpopvp|p ppp pppR} Z/7!6e+g-JFpU#hF/:5@ fbx L za)/\:bNy~P[8;VGn1ESeuclmFZ#KslNP &YOgOzmx 2{;.Mk 1 Ad+JkV'AM jPaZUk,+QOvS SNBl(E^2Df[<s#O@yy%rWr{9i&9KZt6@0`K _?KIivFmT8w<nH:]>}0i,]GR;Cx r;v{Q)<3WU|h|~uftph juW[r=LzT.I*l$HkA}gC W>IX6  .fzg58\C}X.w4(JVsqV([i%pPn)"?qx2ejM3,w!SQ ~7m7 G%]BX9w"^|M`3~-0c>Q_]<j?-oY"t,_Yt0n4 \E`cB$eJ8T_TqU$a4H&(Evd1+5/^b 91quRI%da\LD&*o|c'y-NdXDH =!R'o=B"#{>A $!')?oD `@pC3L47=Y25:*b*hG6s^  Numpy Array/Matrix Helper
Enter an array in the table.
Use Tab to move between cells.

Hit 'Enter' for array or 'Ctrl+Enter' for matrix.

Hint:
Use two tabs at the end of a row to move to the next row. Numpy Array/Matrix Helper
Type an array in Matlab : [1 2;3 4]
or Spyder simplified syntax : 1 2;3 4

Hit 'Enter' for array or 'Ctrl+Enter' for matrix.

Hint:
Use two spaces or two tabs to generate a ';'. Installed Required entries lines ms%s are currently not supported%s arrays%s editor&Close&Debug&Edit&File&Find in files&Find text&Help&New file...&Open...&Print...&Projects&Quit&Replace text&Restart&Revert&Run&Run...&Save&Search&Tools&View2 spaces3 spaces4 spaces5 spaces6 spaces7 spaces8 spaces%s contains mixed end-of-line characters.
Spyder will fix this automatically.%s has been modified outside Spyder.
Do you want to reload it and lose all your changes?%s has been modified.
Do you want to save changes?%s is not a Spyder project!%s is unavailable (this file may have been removed, moved or renamed outside Spyder).
Do you want to close it?-u is added to the other options you set hereSpyder %s is available!

Please use your package manager to update Spyder or go to our Releases page to download this new version.

If you are not sure how to proceed to update Spyder please refer to our Installation instructions.Spyder is a powerful Interactive Development Environment (or IDE) for the Python programming language.

Here we are going to guide you through its most important features.

Please use the arrow keys or click on the buttons below to move along the tour.Unable to %s %s

Error message:
%sUnable to assign data to item.

Error message:
%sUnable to create file %s

Error message:
%sUnable to create folder %s

Error message:
%sUnable to delete {varpath}

The error message was:
{error}Unable to find external program.

%sUnable to load '%s'

Error message:
%sUnable to move %s

Error message:
%sUnable to plot data.

Error message:
%sUnable to proceed to next step

Please check your entries.

Error message:
%sUnable to rename file %s

Error message:
%sUnable to save array

Error message:
%sUnable to save current workspace

Error message:
%sUnable to save file '%s'

Error message:
%sUnable to show image.

Error message:
%sUnsupported file extension '%s'

Would you like to import it anyway (by selecting a known file format)?Unsupported file type '%s'Warning:
The Python module rope is not installed on this computer: calltips, code completion and go-to-definition features won't be available.You have missing dependencies!

%s

Please install them to avoid this message.

Note: Spyder could work without some of these dependencies, however to have a smooth experience when using Spyder we strongly recommend you to install all the listed missing dependencies.

Failing to install these dependencies might result in bugs. Please be sure that any found bugs are not the direct result of missing dependencies, prior to reporting a new issue.
Restarting kernel...

(Refer to the {} page)

If enabled, Python source code will be analyzed using pyflakes, lines containing errors or warnings will be highlighted.

Note: add analysis:ignore in a comment to ignore code analysis warnings.

Warning: changes are applied separatelyA compound sequence can have {break} a maximum of 4 subsequences.{break}About %sAbout %s...Activate supportAdd &block commentAdd block comment around current line or selectionAdd pathAdditional featuresAdditional optionsAddress:Advanced SettingsAdvanced settingsAll changes to %s will be lost.
Do you want to revert file from disk?All filesAll files (*)All files (*.*)All user-defined variables will be removed.
Are you sure you want to reset the namespace?Always show %s on a first file runAn error ocurred while starting the kernelAnalysisAnimated toolbars and panesAppearanceAre you sure you want to delete this scheme?Are you sure you want to restart the kernel?ArgumentsArray dimensions not validArray editorArrays with more than 3 dimensions are not supportedAsk for confirmation before closingAttached console window (debugging)AttributeAutocallAutocall makes IPython automatically call any callable object even if you didn't type explicit parentheses.
For example, if you type str 43 it becomes str(43) automatically.Autocall: AutomaticAutomatic code completionAutomatic connectionsAutomatic importAutomatic indentation after 'else', 'elif', etc.Automatic insertion of closing quotesAutomatic insertion of colons after 'for', 'if', 'def', etcAutomatic insertion of parentheses, braces and bracketsAutomatically load Pylab and NumPy modulesAutomatically remove trailing spaces when saving filesAxis:BackBackend:BackgroundBackground colorBackground:Batch filesBoldBreakpointBrowseBrowse a working directoryBrowse repositoryBrowse tabsBufferBuffer...Buffer: Builtin:C filesC&lose allC&onsolesC++ filesCPU and memory usage info in the status barCPU usage status: requires the `psutil` (>=v0.3) libraryCPU:CSV text filesCancelCannot restart a kernel not started by Spyder Carriage return (Mac)Carriage return and line feed (Windows)Case SensitiveCase sensitive code completionCell starts at line %sChange to lowercase current line or selectionChange to parent directoryChange to uppercase current line or selectionChanging backend to Qt for MayaviCheck for updates on startupCheck for updates...Class defined at line %sClear all ouputClear breakpoints in all filesClear consoleClear lineClear line or blockClear recent files listClear shellClear shell contents ('cls' command)Clear this listClipboard contentsClose ProjectClose all but thisClose all opened filesClose all to the rightClose current fileClose current paneClose current tabClose this panelClose this windowClose windowClosing SpyderCodeCode Introspection/AnalysisCode analysisCode analysis requires pyflakes %s+Collapse allCollapse selectionColor scheme editorColumn min/maxColumn separator:Column:Command line options:CommentComment current line or selectionComment:Comments:CommitCompletion TypeCompletion:Condition:Configuration filesConflictsConnect to an existing kernelConnecting to kernel...Connection errorConnection info:ConsoleConsole helpContextContinueContinue execution until next breakpointConversion errorConvert end-of-line charactersConvert to Python scriptCopyCopy path to clipboardCopy to clipboardCopy without promptsCould not connect to remote hostCould not open ssh tunnel. The error was: CreateCreate a new editor windowCreate new projectCreate new schemeCurrent cell:Current line:Current shortcut:Current user environment variables...Custom margin for panes:CutCython/Pyrex filesDataDataFrameDebug fileDebug toolbarDebug with winpdbDecide how graphics are going to be displayed in the console. If unsure, please select %s to put graphics inside the console or %s to interact with them (through zooming and panning) in a separate window.Decide how to render the figures created by this backendDecide what type of completion to useDefault (i.e. the same as Spyder's)Default is 4Default is 6Default is
In [<span class="in-prompt-number">%i</span>]:Default is
Out[<span class="out-prompt-number">%i</span>]:Default working directory is:Definition:DeleteDelete LayoutDelete ProjectDelete...DependenciesDependencies...DictionaryDisplayDisplay balloon tipsDisplay initial bannerDo you really want to delete %s?Do you really want to delete {filename}?

Note: This action will only delete the project. Its files are going to be preserved on disk.Do you really want to remove selected path?Do you really want to rename %s and overwrite the existing file %s?Do you want to close all other consoles connected to the same kernel as this one?Do you want to close this console?Do you want to remove all selected items?Do you want to remove the selected item?Do you wish to restart now?DoneDuplicateEOLEditEdit filename filtersEdit filename filters...Edit itemEdit selectedEdit template for new modulesEdit toolbarEditorEditor's code completion, go-to-definition and helpEmpty clipboardEmpty projectEnable Tab completion on elements of lists, results of function calls, etc, without assigning them to a variable.
For example, you can get completions on things like li[0].<Tab> or ins.meth().<Tab>Enable UMREnaml filesEncoding:End-of-line charactersEnd-of-lines:Enter key selects completionEnvironment variablesEnvironment variables...ErrorError restarting kernel: %s Exclude all-uppercase referencesExclude capitalized referencesExclude private referencesExclude references to unsupported data types (i.e. which won't be handled/saved correctly)Exclude references which name is uppercaseExclude references which name starts with an underscoreExclude references which name starts with an uppercase characterExclude unsupported data typesExclude:Excluded filenames patternExecutablesExisting directoryExpand allExpand selectionExternal ToolsExternal editorExternal editor executable path:External editor path...External editor:Fast switch between filesFast symbol search in fileFile %s already exists.
Do you want to overwrite it?File ExplorerFile explorerFile switcher...File toolbarFile...FilterFind &nextFind &previousFind in filesFind symbols in file...Find textFix automatically and show warning message boxFix indentationFloat formattingFolder %s already exists.Folder name:Folder...Font styleFont: FontsFor %s support, please install one of the
following tools:

%sFor performance reasons, changes applied to masked array won't be reflected in array's data (and vice-versa).FormatFormat (%s) is incorrectFormat ({}) is incorrectFormat ({}) should start with '%'Format:Fortran filesFullFullscreen modeFunction defined at line %sGIF imagesGUI-based editor:GeneralGeneral settingsGo to cursor positionGo to definitionGo to last edit locationGo to line...Go to line:Go to next code analysis warning/errorGo to next cursor positionGo to previous code analysis warning/errorGo to previous cursor positionGo to step: GraphicalGraphicsGraphics backendGreedy completionHeight:HelpHelp...Here you can get help of any object by pressing %s in front of it, either on the Editor or the Console.%sHelp can also be shown automatically after writing a left parenthesis next to an object. You can activate this behavior in %s.Here you can select the color scheme used in the Editor and all other Spyder plugins.

You can also edit the color schemes provided by Spyder or create your own ones by using the options provided below.
Hide advanced optionsHide toolbarsHighlightHighlight current cellHighlight current lineHighlight matchesHighlight occurrences afterHistogramHistoryHistory depth: History logHistory logsHistory...HomeHost nameIDL filesIPythonIPython ConsoleIPython consoleIPython documentationIPython notebooksIcon themeIf enabled, pressing Tab will always indent, even when the cursor is not at the beginning of a line (when this option is enabled, code completion may be triggered using the alternate shortcut: Ctrl+Space)If this option is enabled, clicking on an object name (left-click + Ctrl key) will go this object definition (if resolved).If you accept changes, this will modify the current user environment variables directly in Windows registry. Use it with precautions, at your own risks.

Note that for changes to take effect, you will need to restart the parent process of this application (simply restart Spyder if you have executed it from a Windows shortcut, otherwise restart any application from which you may have executed it, like Python(x,y) Home for example)ImportImport asImport dataImport errorImport from clipboardImport wizardIn this pane you can view and edit the variables generated during the execution of a program, or those entered directly in one of Spyder consoles.

As you can see, the Variable Explorer is showing the variables generated during the last step of this tour. By doing a double-click on any of them, a new window will be opened, where you can inspect and modify their contents.IndentIndent current line or selectionIndentation characters: IndexIndex:InformationInitializing...InlineInline backendInput prompt:InsertInspect current objectInstalled Python modulesInstance:Integrate the IPython consoleIntelligent backspaceInteract with the Python console after executionInteractive toursInterfaceInternal consoleInternal console settingsInternal editor:Intro to IPythonIntroduction tourIntrospectionInvalid directory pathInvalid file pathInvalid key enteredIt was not possible to close the previous Spyder instance. Restart aborted.It was not possible to convert this notebook. The error is: It was not possible to copy this arrayIt was not possible to copy values for this arrayIt was not possible to generate rich text help for this object.
Please see it in plain text.It was not possible to remove outputs from this notebook. The error is: It was not possible to restart Spyder. Operation aborted.It was not possible to restart the IPython console when switching to this project. The error was {0}It was not possible to run this file in an external terminalItalicJPEG imagesJSON filesJavascript filesJson filesJulia filesKernel died, restartingKernel restartingKeyKey:Keyboard shortcutsKeyword:LanguageLast edit locationLayout %s will be overwritten. Do you want to continue?Layout Display and OrderLayout preferencesLine %sLine count:Line feed (UNIX)Line:Lines:Link to object definitionLink:ListLoading %s...Loading IPython console...Loading editor...Loading file explorer...Loading help...Loading history plugin...Loading namespace browser...Loading online help...Loading outline explorer...Loading project explorer...LocationLockLock panesMATLAB filesMain toolbarMaintain focus in the Editor after running cells or selectionsManage color schemesManipulate Jupyter notebooks on the EditorMaskMasked dataMatched
parens:Matlab filesMatplotlib documentationMaximize current paneMaximum entriesMaximum line countMaximum number of recent filesMaximum number of recent files...Memory usage status: requires the `psutil` (>=v0.3) library on non-Windows platformsMemory:Method defined at line %sModify how Input and Output prompts are shown in the console.ModuleModule pywin32 was not found.
Please restart this Windows session (not the computer) for changes to take effect.Module or package:Module...Move DownMove UpMove downMove to bottomMove to topMove upMove...NSIS filesNameName filters:NewNew Project...New directoryNew features in version 3.0New fileNew folderNew moduleNew name:New packageNew shortcut:New to Spyder? Read ourNew variable name:New windowNextNext cursor positionNext warning/errorNo IPython console is currently available to run %s.

Please open a new one and try again.No documentation availableNo further documentation availableNo source code available.Normal text:Nothing to be imported from clipboard.NumPy arrayNumPy arraysNumPy zip arraysNumber:Numpy and Scipy documentationO&pen last closedObjectOccurrence:OffOn %s mode, Autocall is not applied if there are no arguments after the callable. On %s mode, all callable objects are automatically called (even if no arguments are present).Online documentationOnline helpOnly used when the format is PNG. Default is 72OpenOpen &recentOpen Project...Open a new IPython console connected to an existing kernelOpen an &IPython consoleOpen command prompt hereOpen connection fileOpen fileOpen file as:Open last closedOpen projectOpen terminal hereOpenCL filesOpening this variable can be slow Do you want to continue anyway?OptionsOutlineOutput prompt:PNG imagesPYTHONPATH managerPackage name:Package...PanesParentPasswordPassword or ssh key passphrasePastePatch and diff filesPath to connection file or kernel idPath to ssh key filePerfom symbolic operations in the console (e.g. integrals, derivatives, vector calculus, etc) and get the outputs in a beautifully printed style (it requires the Sympy module).Perform analysis only when saving filePerform analysis when saving file and everyPermissions:Pickle filesPlainPlain TextPlain text fontPlease consider installing Sphinx to get documentation rendered in rich text.Please enter the connection info of the kernel you want to connect to. For that you can either select its JSON connection file using the Browse button, or write directly its id, in case it's a local kernel (for example kernel-3764.json or just 3764).Please install matplotlib or guiqwt.Please introduce a different shortcutPlease note that these changes will be applied only to new Python/IPython consolesPlease note that these changes will be applied only to new consolesPlotPop up internal console when internal errors appearPre&ferencesPreferencesPreferences > HelpPress Enter to switch files or Esc to cancel.

Type to filter filenames.

Use :number to go to a line, e.g. main:42
Use @symbol_text to go to a symbol, e.g. @init

Press Ctrl+W to close current tab.
Press enter to validate this entryPress enter to validate this pathPress the new shortcut and select 'Ok': (Press 'Tab' once to switch focus between the shortcut entry and the buttons below it)PreviewPreviousPrevious cursor positionPrevious warning/errorPrint current file...Print preview...Printing...Project ExplorerProject PreferencesProject explorerProject nameProject preferencesProject typePrompt when exitingPromptsProvided featuresPyQt4 API ReferencePyQt4 Reference GuidePython Path ManagerPython documentationPython filesPython help:Python interpreterPython packagePython projectPython scriptsPython versionQt DesignerQt LinguistQt documentationQt examplesQt windows styleQuick referenceQuick switch layout #%s has not yet been defined.QuitR&emove block commentRaw textRe-run &last scriptReal-time code analysisReal-time code analysis on the EditorReal-time code style analysisReal-time code style analysis on the EditorRecent ProjectsRecord array fields:RedoRefresh list of module names available in PYTHONPATHRegular expressionRemoval errorRemoveRemove comment block around current line or selectionRemove pathRemove references:Remove trailing spacesRenameRename...Render mathematical equationsReplace allReplace stringReplace tab characters by space charactersReplace with:Report issue...ResetReset IPython namespaceReset Spyder to factory defaultsReset namespaceReset to default valuesReset to defaultsReset to spyder defaultResetting Spyder to defaultsResizeResize rows to contentsResolution:RestartRestart kernelRestart kernel?RestartingRestoreRestore current paneRestore data on startupRestore original tree layoutRestore pane to its original sizeRevert file from diskRich TextRich text fontRow separator:RunRun &selection or current lineRun Python scriptRun Settings dialogRun a Python scriptRun a fileRun again last fileRun cellRun cell and advanceRun codeRun configurationRun current cell (Ctrl+Enter) [Use #%% to create cells]Run current cell and go to the next one (Shift+Enter)Run current lineRun fileRun script:Run selectionRun selection or current lineRun settingsRun settings for %sRun toolbarRun until current function or method returnsRunning an external system terminal is not supported on platform %s.Sav&e allSaveSave &as...Save all filesSave all files before running scriptSave arraySave current file as...Save current history log (i.e. all inputs and outputs) in a text fileSave current layoutSave dataSave data as...Save data on exitSave fileSave historySave history logSave history log...Save non project files openedScheme name:Scheme:ScoreScroll automatically to last entrySearchSearch patternSearch stringSearch text in multiple filesSearch toolbarSearch: Select AllSelect a run configuration:Select directorySelect fileSelect ssh keySelect the Python interpreter for all Spyder consolesSet UMR excluded (not reloaded) modulesSet console working directorySet current console (and file explorer) working directory to current script directorySet external editor executable pathSet history maximum entriesSet maximum line countSet the list of excluded modules as this: numpy, scipySet the maximum number of lines of text shown in the console before truncation. Specifying -1 disables it (not recommended!)Set this for high DPI displaysSet this to detach any
menu from the main windowSet this to open external
Python files in an already running instance (Requires a restart)Set/Clear breakpointSet/Edit conditional breakpointSetting up main window...SettingsShell special commands:ShortcutShortcut: {0}Show (read-only) sys.pathShow CPU usage everyShow SourceShow absolute pathShow advanced optionsShow all filesShow and edit current user environment variables in Windows registry (i.e. for all sessions)Show and edit environment variables (for current session)Show arrays min/maxShow blank spacesShow code analysis warnings/errorsShow current directory onlyShow help for objects in the Editor and Consoles in a dedicated paneShow horizontal scrollbarShow icons and textShow imageShow line numbersShow memory usage everyShow reloaded modules listShow special commentsShow status barShow sys.path contentsShow sys.path contents...Show tab barShow todo listShow toolbarsShow vertical line afterShow warning/error listShow/hide outline explorerSide areas:SiftSizeSize: Skip rows:SmartSour&ceSourceSource codeSource toolbarSphinx %s is currently installed.Split horizontallySplit horizontally this editor windowSplit verticallySplit vertically this editor windowSpyder Default LayoutSpyder EditorSpyder Internal Console This console is used to report application internal errors and to inspect Spyder internals with the following commands: spy.app, spy.window, dir(spy) Please don't use it to run your code Spyder could not reset to factory defaults. Restart aborted.Spyder data filesSpyder depends on several Python modules to provide the right functionality for all its panes. The table below shows the required and installed versions (if any) of all of them.

Note: You can safely use Spyder without the following modules installed: %s and %s.

Please also note that new dependencies or changed ones will be correctly detected only after Spyder is restarted.Spyder documentationSpyder exit errorSpyder is up to date.Spyder needs to restart to change the following setting:Spyder needs to restart to change the following settings:Spyder reset errorSpyder restart errorSpyder support...Spyder tutorialSpyder updatesSpyder was unable to retrieve the value of this variable from the console.

The error mesage was:
%sSpyder will restart and reset to default settings:

Do you want to continue?Ssh keyStart searchStartupStatus barStepStep IntoStep ReturnStep into function or method of current lineStopStop debuggingStop searchStop the current commandString not foundString:Support for graphics (Matplotlib)Supported filesSupported text filesSymbol finder...Symbolic MathematicsSymbolic mathematics in the IPython ConsoleSynchronizeSynchronize Spyder's path list with PYTHONPATH environment variableSynchronize...Syntax coloringSyntax highlighting for Matlab, Julia and other file typesSystem commands:TIFF imagesTabTab always indentTab stop width:TabulationsTear off menusTemporary fileTerminalTextText editorText filesThe 'xlabels' argument length do no match array column numberThe 'ylabels' argument length do no match array row numberThe EditorThe File ExplorerThe History LogThe IPython consoleThe Variable ExplorerThe authenticity of host %s can't be established. Are you sure you want to continue connecting?The authenticity of the host can't be establishedThe current directory contains a project.

If you want to delete the project, please go to Projects » Delete ProjectThe directory {} is not writable and it is required to create IPython consoles. Please make it writable.The following conflicts have been detected:The following error occured when calling Sphinx %s.
Incompatible Sphinx version or doc string decoding failed.

Error message:
%sThe following modules are not installed on your machine: %sThe following working directory is not valid:
%sThis directory is already included in Spyder path list.
Do you want to move it to the top of the list?This entry is incorrectThis feature requires Sphinx 1.1 or superior.This feature requires the Rope or Jedi libraries. It seems you don't have either installed.This is a remote kernelThis is a temporary script file.This is one of panes where you can run or execute the code you wrote on the Editor. To do it you need to press the F5 key.

This console comes with several useful features that greatly improve your programming workflow (like syntax highlighting and inline plots). If you want to know more about them, please follow this link.

Please click on the button below to run some simple code in this console. This will be useful to show you other important features.This is the pane where you write Python code before evaluating it. You can get automatic suggestions and completions while writing, by pressing the Tab key next to a given text.

The Editor comes with a line number area (highlighted here in red), where Spyder shows warnings and syntax errors. They can help you to detect potential problems before running the code.

You can also set debug breakpoints in the line number area, by doing a double click next to a non-empty line.This is the working directory for newly opened consoles (Python/IPython consoles and terminals), for the file explorer, for the find in files plugin and for new files created in the editorThis lets you load graphics support without importing the commands to do plots. Useful to work with other plotting libraries different to Matplotlib or to develop GUIs with Spyder.This option lets you hide the message shown at the top of the console when it's opened.This option loads the Sympy library to work with.
Please refer to its documentation to learn how to use it.This option will be applied the next time a console is opened.This option will enable the User Module Reloader (UMR) in Python/IPython consoles. UMR forces Python to reload deeply modules during import when running a Python script using the Spyder's builtin function runfile.

1. UMR may require to restart the console in which it will be called (otherwise only newly imported modules will be reloaded when executing files).

2. If errors occur when re-running a PyQt-based program, please check that the Qt objects are properly destroyed (e.g. you may have to use the attribute Qt.WA_DeleteOnClose on your main window, using the setAttribute method)This pane can automatically show an object's help information after a left parenthesis is written next to it. Below you can decide to which plugin you want to connect it to turn on this feature.This pane displays documentation of the functions, classes, methods or modules you are currently using in the Editor or the Consoles.

To use it, you need to press Ctrl+I in front of an object. If that object has some documentation associated with it, it will be displayed here.This pane lets you navigate through the directories and files present in your computer.

You can also open any of these files with its corresponding application, by doing a double click on it.

There is one exception to this rule: plain-text files will always be opened in the Spyder Editor.This pane records all commands introduced in the Python and IPython consoles.This will synchronize Spyder's path list with PYTHONPATH environment variable for current user, allowing you to run your Python modules outside Spyder without having to configure sys.path.
Do you want to clear contents of PYTHONPATH before adding Spyder's path list?To boolTo complexTo doTo floatTo intTo strToggle LowercaseToggle UppercaseToolbarsTransposeTunnel '%s' failed to startTupleTypeUMRUMR forces Python to reload modules which were imported when executing a file in a Python or IPython console with the runfile function.Unable to check for updates.Unable to connect to %sUnable to connect to the internet.

Make sure the connection is working properly.Unable to load pageUnable to retrieve information.UncommentUndoUnexpected error: see internal consoleUnindentUnindent current line or selectionUnlockUnmatched
parens:Update LANGUAGE_CODES (inside config/base.py) if a new translation has been added to SpyderUpdate module names listUsageUse a pager to display additional text inside the consoleUse a single instanceUse next layoutUse previous layoutUse symbolic mathUse the following Python interpreter:Use the following file:Use the greedy completerUse version controlUseful if you don't want to fill the console with long help or completion texts. Note: Use the Q key to get out of the pager.User Module Reloader (UMR)ValueValue:Variable NameVariable explorerVariable name:Version controlVersion control systemVertical tabs in panesVertical title bars in panesViTablesView and edit DataFrames and Series in the Variable ExplorerView and edit two and three dimensional arrays in the Variable ExplorerWarningWeb page filesWelcome to Spyder introduction tourWelcome to Spyder!Welcome to the Introduction tourWhen opening a text file containing mixed end-of-line characters (this may raise syntax errors in the consoles on Windows platforms), Spyder may fix the file automatically.Whole wordsWidth:WinPythonWinPython control panelWindow layout will be reset to default settings: this affects window position, size and dockwidgets. Do you want to continue?Window layoutsWorkspaceWrap linesXML filesYaml filesYou are working with Python 2, this means that you can not import a module that contains non-ascii characters.You can also run a whole file at startup instead of just some lines (This is similar to have a PYTHONSTARTUP file).You can run several lines of code when a console is started. Please introduce each one separated by commas, for example:
import os, import sysYou don't have the right permissions to open this directoryYou selected a Python %d interpreter for the console but Spyder is running on Python %d!.

Although this is possible, we recommend you to install and run Spyder directly with your selected interpreter, to avoid seeing false warnings and errors due to the incompatible syntax between these two Python versions.You selected an invalid Python interpreter for the console so the previous interpreter will stay. Please make sure to select a valid one.Your Python environment or installation doesn't have the ipykernel module installed on it. Without this module is not possible for Spyder to create a console for you.

You can install ipykernel by running in a terminal:

pip install ipykernel

or

conda install ipykernelZoom inZoom outZoom resetarraycharacterscodecopydatadeletedpielementsfilegettext filesguidata examplesguiqwt examplesinchesinvalid regular expressionlineslistmatches inmoveotherpermission denied errors were encounteredpixelsreStructuredText filesread onlyspacestabletextthe following directory:this dialogtutorialunsaved fileuntitledusername@hostname:portvariable_nameProject-Id-Version: 3.8POT-Creation-Date: 2017-01-17 12:57-0300 POT-Creation-Date: 2017-07-11 13:28+COT PO-Revision-Date: 2017-01-17 14:38-0300 Last-Translator: Valter Nazianzeno Language-Team: pt_BR Language: pt_BR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generated-By: pygettext.py 1.5 X-Generator: Poedit 1.8.11 Plural-Forms: nplurals=2; plural=(n > 1); Ajuda no Numpy Array/Matriz
Digite um array na tabela.
Use Tab para se mover entre as células.

Aperte 'Enter' para array ou 'Ctrl+Enter' para matriz.

Dica:
Use dois Tabs no fim de uma coluna para se mover até a próxima coluna. Ajuda no Numpy Array/Matriz
Definir uma matriz no Matlab : [1 2;3 4]
ou na sintaxe simplificada do Spyder : 1 2;3 4

Aperte 'Enter' para array ou 'Ctrl+Enter' para matriz.

Dica:
Use dois espaços ou dois tabs para gerar um ';'. InstaladoRequeridoentradaslinhasms%s não é suportado no momento%s matrizesEditor de %s&Fechar&Depurar&Editar&ArquivoProcurar em arqui&vos&ProcurarA&juda&Novo arquivo...&Abrir...&Imprimir...&Projetos&Sair&Substituir&ReiniciarResta&urar&Executar&Executar...&Salvar&Pesquisar&Ferramentas&Ver2 espaços3 espaços4 espaços5 espaços6 espaços7 espaços8 espaços%s contém vários tipos de caracteres de fim de linha.
O Spyder irá corrigir automaticamente.%s foi modificado fora do Spyder.
Você deseja recarregar ele e perder todas as modificações?%s foi modificado.
Deseja salvar as mudanças?%s não é um projeto do Spyder!%s está indisponível (o arquivo pode ter sido removido, movido ou renomeado fora do Spyder).
Deseja fechar?A opção -u foi adicionada a essas opçõesSpyder %s está disponível!

Por favor utilize o seu gerenciador de pacotes ou visite a página Releases para baixar a nova versão.

Se você não sabe como atualizar o Spyder visite a página de instruções Installation.Spyder é um poderoso Ambiente de Desenvolvimento Integrado (ou IDE) para a linguagem de programação Python.

Aqui vamos guiar você nas mais importantes características e funcionalidades do Spyder.

Por favor use as teclas de seta ou clique nos botões abaixo para se mover durante a tour.Não foi possível %s %s

Mensagem de erro:
%sNão foi possível atribuir dados ao item.

Mensagem de erro:
%sNão foi possível criar arquivo %s

Mensagem de erro:
%sNão foi possível criar pasta %s

Mensagem de erro:
%sNão foi possível deletar {varpath}

Mensagem de erro:
{error}Não foi possível encontrar o programa externo.

%sNão foi possível carregar '%s'

Mensagem de erro:
%sNão foi possível mover %s

Mensagem de erro:
%sNão foi possível mostrar os dados.

Mensagem de erro:
%sNão foi possível prosseguir para o próximo passo

Por favor revise seus dados

Mensagem de erro:
%sNão foi possível renomear arquivo %s

Mensagem de erro:
%sNão foi possível salvar matriz

Mensagem de erro:
%sNão foi possível salvar o espaço de trabalho atual

Mensagem de erro:
%sNão foi possível salvar arquivo '%s'

Mensagem de erro:
%sNão foi possível mostrar o gráfico.

Mensagem de erro:
%sTipo de arquivo não suportado '%s'

Deseja importar mesmo assim (selecionando um formato conhecido)?Tipo de arquivo não suportado '%s'Aviso:
O módulo rope não está instalado neste computador: Por tanto a completação de código, balões de dicas e o método ir para função não estão disponíveis.Você tem dependências faltando!

%s

Por favor instale elas para evitar esta mensagem.

Nota: O Spyder pode funcionar sem algumas dependências, porém para ter uma experiência melhor ao utilizar o software recomendamos fortemente a instalação das dependências listadas que estão faltando.

A não instalação destas dependências pode gerar bugs. Antes de relatar um novo problema certifique-se de que quaisquer bugs encontrados não são o resultado das dependências que estão faltando.
Reiniciando kernel..

(Guia de estilo {})

Se ativado, o código fonte será analisado utilizando o pyflakes, linhas contendo erros ou avisos serão destacadas.

Nota: add analysis:ignore em um comentário para ignorar avisos da analise de estilo.

Aviso: mudanças são aplicadas de forma separadaUma sequência composta pode ter {break} um máximo de 4 subsequências.{break}Sobre o %sSobre o %s...Ativar suporteAdicionar &bloco de comentário Adicionar bloco de comentário ao redor da linha ou seleção atualAdicionar caminhoFuncionalidades adicionaisOpções adicionaisEndereço:Configurações avançadasConfigurações avançadasTodas as modificações do %s foram perdidas.
Você deseja reverter o arquivo do disco?Todos os arquivosTodos os arquivos (*)Todos os arquivos (*.*)Todas as variáveis definidas pelo usuário serão removidas.
Você tem certeza que deseja resetar o namespace?Sempre mostrar %s na primeira execuçãoUm erro ocorreu enquanto o kernel era inicializadoAnáliseBarras e painéis animadosAparênciaVocê tem certeza que deseja deletar esse esquema?Deseja mesmo reiniciar o kernel?ArgumentosDimensões da matriz não é válidaEditor de matrizesMatrizes com mais de 3 dimensões não são suportadasMostrar janela de confirmação antes de fecharJanela do console anexada (depuração)AtributoAutocallEsta opção faz com que o Python chame automaticamente qualquer objeto mesmo se você não tenha digitado os parenteses ao seu redor.
Por exemplo, ao escrever str 43, irá virar automaticamente str(43).Autocall: AutomáticoCompletar código automáticamenteConexões automáticas Importar automaticamenteIndentação automática depois do 'else', 'elif', etc.Inserção automática de aspasInserção automática de ":" depois de 'for', 'if', 'def', etcInserção automática de parênteses, chaves e colchetesCarregar automaticamente os módulos do Pylab e do NumPyRemover automaticamente espaços em branco ao salvar arquivosEixo:AnteriorSaída:Plano de fundoCor de fundoFundo:Arquivos BatchNegritoPonto de interrupçãoNavegarSelecionar um diretório de trabalhoExplorar repositório Navegar pelas abasBufferBuffer...Buffer: Objeto integrado:Arquivos CFechar &tudoC&onsolesArquivos C++Uso de CPU e memória na barra de statusStatus de uso da CPU: requer a biblioteca `psutil` (>=v0.3)CPU:Arquivos de texto CSVCancelarNão é possível reiniciar um kernel que não foi iniciado pelo Spyder Carriage return (Mac)Carriage return e salto de linha (Windows)Diferenciar maiúsculas de minúsculasDiferenciar entre maiúsculas e minusculas ao completar códigoA célula inicia na linha %sMudar linha ou seleção atual para minúsculoMudar para diretório superiorMudar linha ou seleção atual para maiúsculoMudando a saída gráfica do Qt para MayaviVerificar por atualizações na inicializaçãoVerificar por atualizações...Classe definida na linha %sLimpar todas as saídas Limpar pontos de interrupção em todos os arquivosLimpar consoleLimpar linhaLimpar linha ou blocoLimpar lista de arquivos recentesLimpar shellLimpar conteúdo do shell (comando 'cls')Limpar esta listaConteúdo da área de transferência Fechar ProjetoFechar todos, menos esteFechar todos os arquivos abertosFechar todos à direitaFechar arquivo atualFechar painel atualFechar aba atualFechar este painelFechar esta janelaFechar janelaFechando o SpyderCódigoAnálise e introspecção de códigoAnálise de códigoA análise de código requer pyflakes %s+Reduzir tudoReduzir seleçãoEdição do esquema de coresMin/max de colunaSeparador de colunas:Coluna:Opções de linha de comando: ComentarComentar linha ou seleção atualComentário:Comentários:EnviarTipo de completaçãoCompletação:Condição:Arquivos de ConfiguraçãoConflitosConectar a um kernel já existenteConectando ao kernel...Erro de conexãoInformação da conexão:ConsoleAjuda do consoleContextoContinuarContinuar a execução até o próximo ponto de interrupçãoErro de conversãoConverter caracteres de fim de linhaConverter para um script PythonCopiarCopiar caminho para área de transferênciaCopiar para área transferência Copiar sem os promptsNão foi possível conectar ao servidor remotoNão foi possível criar um túnel ssh. O erro foi: CriarCriar uma nova janela de ediçãoCriar um novo projetoCriar novo esquemaCélula selecionada:Linha atual:Atalho atual:Variáveis de ambiente do usuário atual...Margem personalizada para os painéis:RecortarArquivos Cython/PyrexDadosDataFrameDepurar arquivoBarra de depuraçãoDepurar com winpdbDecidir como serão mostrados os gráficos no console. Se está inseguro, por favor selecione %s para colocar os gráficos no console ou %s para interagir com eles (através de zoom) em uma janela separada.Decida como renderizar as imagens criados por este tipo de saída gráficaDecidir qual tipo de completação usarPadrão (o mesmo do Spyder)O padrão é 4O padrão é 6O Padrão é
In [<span class="in-prompt-number">%i</span>]:O Padrão é
Out[<span class="out-prompt-number">%i</span>]: O diretório de trabalho padrão é:Definição:DeletarDeletar LayoutDeletar ProjetoDeletar...DependênciasDependências...Dicionário VisualizaçãoMostrar sugestõesMostrar o banner inicialDeseja mesmo deletar %s?Você deseja mesmo deletar {filename}?

Nota: Isso deletará apenas o projeto. Os arquivos continuarão no disco.Você deseja mesmo remover o caminho selecionado?Você deseja mesmo renomear %s e sobrescrever o arquivo já existente %s? Você deseja fechar todos os outros consoles conectados ao mesmo kernel como esse?Tem certeza que deseja fechar esse console?Você deseja remover todos os itens selecionados?Você deseja remover o item selecionado?Você deseja reiniciar agora?FeitoDuplicarFim de linhaEditarEditar filtros para nomes de arquivosEditar filtros para nomes de arquivos...Editar itemEditarEditar template para novos módulosBarra de ediçãoEditorCompletador de código e ajuda no EditorÁrea de transferência vaziaProjeto vazioHabilita o completador usando a tecla Tab em elementos de listas, resultados de chamadas de funções, etc, sem atribuí-los a uma variável.
Dessa forma pode-se obter sugestões de completação em coisas como li[0].<Tab> ou ins.meth().<Tab>Ativar RMUArquivos EnamlCodificação:Caracteres de fim de linhaFim de linha:A tecla Enter seleciona o resultado a completarVariáveis de ambienteVariáveis de ambiente...ErroErro ao reiniciar kernel: %s Excluir variáveis em maiúscula Excluir variáveis que começam em maiúsculasExcluir variáveis privadasExcluir variáveis que guardam tipos de dados não suportados (aqueles que não podem ser manipulados e armazenados corretamente)Excluir variáveis cujo nome esteja completamente em maiúsculasExcluir variáveis cujo nomes comecem com sublinhadoExcluir variáveis cujo nome comece com maiúsculas. Excluir tipos de dados não suportadosExcluir:Excluir padrões de nomes do arquivoExecutáveis Diretório existenteExpandir tudoExpandir seleçãoFerramentas externasEditor externoCaminho do executável do editor externo:Caminho de editor externo:Editor externo:Troca rápida de seleção entre arquivosPesquisa rápida de símbolos no arquivoO arquivo %s já existe
Deseja sobrescrever ele?Explorador de arquivosExplorador de arquivosSeletor de arquivo...Barra de arquivoArquivo...FiltroP&rocurar próximoProcurar &anteriorProcurar em arquivosProcurar símbolos no arquivo...Buscar textoCorrigir automaticamente e exibir uma mensagem de avisoConsertar indentaçãoFormatação de ponto flutuanteA Pasta %s já existe.Nome da pasta:Pasta...Estilo de fonteFonte:FontesPara ter suporte ao %s, por favor instale as
seguintes ferramentas:

%sPor motivos de desempenho, as mudanças aplicadas a matrizes mascaradas não serão refletidas nos dados da matriz (e vice-versa).FormatoO formato (%s) está incorretoO formato ({}) éincorretoO formato ({}) deve começar com '%'Formato:Arquivos FortranTotalModo tela cheiaFunção definida na linha %sImagens GIFEditor gráfico:GeralConfigurações geraisIr para a posição do cursor Ver definiçãoIr para posição anterior da ediçãoIr para linha...Ir para a linha:Ir para próxima linha de aviso ou erroIr para a próxima posição do cursorIr para linha anterior de aviso ou erroIr a posição anterior do cursorVá para a etapa: GráficoGráficosSaída gráficaCompletação gulosaAltura:AjudaAjuda...Neste painel é possível obter a ajuda de qualquer objeto ao pressionar %s estando na frente do mesmo, tanto no Editor quanto no Console.%sEssa ajuda também pode ser mostrada automaticamente depois de escrever um parênteses junto a um objeto. Você pode ativar este comportamento em %s.Aqui você pode escolher o esquema de cor usado no Editor e em todos outros plugins do Spyder.

Você pode também editar os esquemas padrões do Spyder ou criar os seus próprios utilizando as opções abaixo.
Esconder opções avançadasEsconder barra de ferramentasDestaqueRealçar célula atualRealçar linha atualDestacar correspondências Realçar ocorrências depois deHistogramaHistóricoProfundidade do histórico: Log do histórico Histórico de comandosHistórico...Página inicialNome do host Arquivos IDLIPythonConsole IPythonConsole IPythonDocumentação do IPythonNotebooks do IPythonTema dos iconesSe ativada, pressionando Tab o código será indentado, mesmo se o cursor não estiver no inicio da linha (se essa opção for ativada a completação de código poderá ser usada pressionando Ctrl+Espaço)Se esta opção estiver ativada, clicando no nome de um objeto (clique-esquerdo + Ctrl) o editor irá mostrar a definição do mesmo.Se você aceitar, as variáveis de ambiente atuais serão modificadas no registro do Windows. Use com precaução, em seu próprio risco.

Tenha em mente que para que as mudanças tenham efeito, você deverá reiniciar o processo pai deste aplicativo (simplesmente reinicie o Spyder se você executou ele de um atalho, caso contrário reinicie qualquer aplicativo pelo qual você você executou ele, como o Python(x,y) Home)ImportarImportar comoImportar dataErro de importaçãoImportar da área de transferência Assistente de importaçãoNeste painel você pode ver e editar as variáveis geradas durante a execução de um programa ou quando digitadas diretamente em um dos consoles do Spyder.

Como você pode ver, o Explorador de Variáveis está mostrando as variáveis geradas durante o passo anterior desta tour. Clicando duas vezes em qualquer uma delas uma nova janela será aberta, aonde você poderá inspecionar e modificar seus valores.IndentarIndentar a linha ou seleção atualCaracteres de indentação:ÍndiceÍndice:InformaçãoIniciando...Em linhaSaída em linhaPrompt de entrada:InserirInspecionar objetoMódulos instalados do PythonInstância:Integração com o console IPythonTecla de retorno ("backspace") inteligenteInteragir com o console depois da execuçãoTours interativasInterfaceConsole internoConfigurações do console internoEditor interno:Introdução ao IPythonTour de introduçãoIntrospecçãoCaminho de diretório inválidoCaminho de arquivo inválido Chave inválida inseridaNão foi possível fechar a última instância do Spyder. Reiniciamento abortado.Não foi possível converter esse notebook. O erro é: Não foi possível copiar essa matrizNão foi possível copiar os valores dessa matrizNão foi possível gerar ajuda em texto formatado para este objeto.
Por favor veja em texto normal.Não foi possível remover as saídas deste notebook. O erro é: Não foi possível reiniciar o Spyder. Operação abortada.Não foi possível reiniciar o console IPython enquanto trocava-se de projeto. O erro foi {0}Não foi possível executar este arquivo em um terminal externoItálicoImagens JPEGArquivos JSONArquivos JavascriptArquivos JsonArquivos JuliaO Kernel morreu, reiniciandoReiniciando KernelChaveChave:Teclas de atalhoPalavra chave:IdiomaÚltima posição da ediçãoLayout %s será sobrescrito. Você deseja Continuar?Ordem dos layoutsPreferências do LayoutLinha %sNúmero de linhas:Salto de linha (UNIX)Linha:Linhas:Link para a definição do objetoLink:ListaCarregando %s...Carregando console IPython...Carregando editor...Carregando explorador de arquivos...Carregando ajuda...Carregando histórico...Carregando explorador de variáveis...Carregando ajuda online...Carregando o explorador de código...Carregando explorador de projetos...LocalizaçãoTrancarTravar painéisArquivos MATLABBarra principalManter o foco no editor depois de executar células ou seleçõesGerenciar esquemas de coresPermite manipular Jupyter notebooks no EditorMáscaraDados mascaradosParênteses fechados:Arquivos do MatlabDocumentação do MatplotlibMaximizar painel atualNúmero máximo de entradasNúmero máximo de linhasNúmero máximo de arquivos recentesNúmero máximo de arquivos recentes...Status de uso da memória: requer a biblioteca `psutil` (>=v0.3) em outras plataformasMemória:Método definido na linha %sModifique como são mostradas as saídas e entradas no console.Módulo O módulo pywin32 não foi encontrado.
Por favor reinicie esta sessão do Windows (não do computador) para que as mudanças tenham efeito.Módulo ou pacote:Módulo...Mover para baixoMover para CimaMover para baixoMover para o finalMover para o inicioMover para cimaMover...Arquivos NSIS NomeNome dos filtros:NovoNovo Projeto...Novo diretórioNovidades na versão 3.0Novo arquivoNova pastaNovo módulo Novo nome:Novo pacoteNovo atalho:Novo no Spyder? Leia nossoNovo nome da variável:Nova janelaPróximoPróxima posição do cursorPróximo aviso ou erroNão existe um console IPython para ser executado %s.

Por favor abra um novo e tente novamente.Nenhuma documentação disponívelNenhuma documentação adicional disponívelO código fonte não está disponívelTexto normal:Não há nada para ser importado da área de transferência.Matriz NumPyMatrizes do NumPyMatrizes comprimidas do NumPyNúmero:Documentação do Numpy e ScipyAb&rir último arquivo fechadoObjetoOcorrência:DesativadoNo modo %s, Auto-chamada não é aplicada se não houver argumentos depois do objeto clamável. No modo %s, todos os objetos chamáveis são chamados automaticamente (mesmo se não houver argumentos presentes).Documentação onlineAjuda onlineSó se usa quando o formato for PNG. O padrão é 72AbrirAbrir &recenteAbrir Projeto...Abrir um novo console do IPython conectado a um kernel existente.Abrir um console &IPython Abrir prompt de comando aquiAbrir arquivo de conexãoAbrir arquivoAbrir arquivo como:Abrir último arquivo fechadoAbrir projetoAbrir terminal aquiArquivos OpenCLAbrir essa variável pode ser um processo lento Deseja continuar mesmo assim?OpçõesExplorador de códigoPrompt de saída:Imagens PNGGerenciar PYTHONPATHNome do pacote:Pacote...PainéisSuperiorSenhaSenhaColarArquivos Patch e diffCaminho para arquivo de conexão ou id do kernelCaminho do arquivo de chave sshRealiza operações simbólicas no console (integrais, derivadas, cálculo vetoria e etcl) tendo os resultados em um belo estilo impresso (requer o módulo Sympy).Fazer análise só quando o arquivo for salvoFazer análise de código ao guardar arquivo e a cadaPermissões:Arquivos PickleSimplesTexto NormalTexto simplesPor favor considere instalar o Sphinx para obter a documentação em texto formatado.Por favor introduza a informação de conexão do kernel ao qual deseja se conectar. Para isso você pode selecionar seu arquivo de conexão JSON, usando o botão Selecionar, ou escrever diretamente seu id, em caso de que seja um kernel local (por exemplo, kernel-3764.json ou só 3764).Por favor instale matplotlib ou guiqwt.Por favor escolha um atalho diferentePor favor, note que estas mudanças só serão aplicadas apenas aos novos consoles do Python/IPythonPor favor tenha em nota que as mudanças só serão aplicadas em novos consolesGráficoMostrar o terminal interno quando houver errosPre&ferênciasPreferênciasPreferências > AjudaPressione Enter para trocar de arquivo ou Esc para cancelar.

Type to filter filenames.

Utilize :número para ir numa linha, ex: main:42
Use @texto_do_simbolo para ir em um simbolo, ex: @init

Pressione Ctrl+W para fechar a aba atual.
Aperte enter para validar esta entradaAperte enter para validar esse caminhoPressione o novo atalho e selecione 'Ok': (Pressione 'Tab' uma vez para mudar o foco entre a entrada do atalho e os botões abaixo dele)Pré-VisualizaçãoAnteriorPosição anterior do cursorAviso ou erro anteriorImprimir o arquivo atual...Pré-visualizar impressão...Imprimindo...Explorador de projetosPreferências do ProjetoExplorador de projetosNome do projetoPreferências do projetoTipo do projetoMostrar mensagem de confirmação ao sairPromptsCaracterísticas proporcionadasReferência da API do PyQt4Guia de referência do PyQt4Gerenciador de caminhos do PythonDocumentação do PythonArquivos PythonAjuda do Python:Interpretador PythonPacote PythonProjeto PythonScripts PythonVersão do PythonQt DesignerQt LinguistDocumentação do QtExemplos do QtTema do QtReferência rápidaTroca rápida do layout #%s ainda não foi definida.SairR&emover bloco de comentárioTexto sem formataçãoExecutar &novamente o último scriptAnálise de código em tempo realAnálise de código em tempo real no editorAnálise do estilo de código em tempo realAnálise de estilo em tempo real no editor.Projetos RecentesCampos de matrizes registradas:RefazerAtualizar a lista de nomes dos módulos disponíveis no PYTHONPATHExpressão regularErro de remoçãoRemoverRemover bloco de comentário ao redor da linha ou seleção atualRemover caminhoRemover referências:Remover espaços em brancoRenomearRenomear...Renderizar equações matemáticasSubstituir tudoSubstituir stringSubstituir caracteres de tabulação por espaçosSubstituir com:Reportar problema...RestaurarResetar IPython namespaceResetar configuração padrão do SpyderResetar namespaceRestaurar os valores padrões.Redefinir PreferênciasResetar para o layout padrão do SpyderResetando definições padrões do SpyderRedimensionarRedimensionar linhas para o conteúdo Resolução:ReiniciarReiniciar kernelReiniciar kernel?ReiniciandoRestaurarRestaurar painel atualRestaurar data na inicializaçãoRestaurar a disposição originalRestaurar painel ao seu tamanho originalReverter arquivo do discoTexto FormatadoTexto formatadoSeparador de linha:ExecutarExecutar &seleção ou linha atualExecutar script PythonConfigurações de execuçãoExecutar um script PythonExecutar arquivoExecutar novamente o mesmo arquivoExecutar célulaExecutar célula e avançarExecutar códigoOpções de execuçãoExecutar a célula atual (Ctrl+Enter) [Usar #%% para criar células]Executar célula atual e ir para a próxima (Shift+Enter)Executar linha selecionadaExecutar arquivoExecutar script:Executar seleçãoExecutar seleção ou linha atualExecutar configuraçõesAjustar configuração para %sBarra de execução Executar até que a função ou método atual terminemExecutar um terminal externo não é suportado na plataforma %s.Sal&var tudoSalvarSalvar c&omo...Salvar todos os arquivosSalvar tudo antes de executar um scriptSalvar matrizSalvar arquivo atual como...Salvar o histórico atual (todas entradas e saídas) em um arquivo de textoSalvar layout atualSalvar dataSalvar data como...Salvar data ao sairSalvar arquivoSalvar históricoSalvar históricoSalvar histórico...Salvar arquivos que não são de projetos, atualmente abertosNome do esquema:Esquema:ValorIr automaticamente para a última entradaProcurarPadrão de pesquisa Procurar stringBuscar em vários arquivosBarra de pesquisaProcurar: Selecionar tudoSelecionar um arquivo de execução:Selecionar diretórioSelecionar arquivoSelecionar chave sshSelecione o interpretador Python para todos os consoles do SpyderDefinir lista de módulos excluídos pelo RMUDefinir diretório de trabalhoDefinir o diretório de trabalho do console (e do explorador de arquivos) para o diretório do script atual.Definir caminho de editor externoDefinir número máximo de entradas para armazenarDefinir número máximo de linhasDefina a lista de módulos excluídos desta forma: numpy, scipyDefine o número máximo de linhas que serão mostradas no console em qualquer momento. Especificando -1 serão mostradas todas as linhas (não é recomendável!)Ativar em telas de alto DPIHabilite esta opção
se deseja separar os menus da janela principalSelecione esta opção
para abrir arquivos externos de Python nessa instância atual (Requer que seja reiniciado)Adicionar ou limpar um ponto de interrupçãoAdicionar ou editar um ponto de interrupção condicionalConfigurando tela principal...ConfiguraçõesComando especiais: AtalhoAtalho: {0}Mostrar conteúdo da sys.path em modo de leituraMostrar uso da CPU a cadaMostrar código fonteMostrar o caminho completoMostrar opções avançadas Mostrar todos os arquivosMostrar e editar as variáveis de ambiente do usuário atual no registro do Windows (para todas as sessões)Mostrar e editar as variáveis de ambiente (para a sessão atual)Mostrar o minimo e máximo de matrizesMostrar espaços em brancoMostrar erros e avisos da análise de códigoMostrar somente o diretório atualMostra ajuda para objetos do Editor e Consoles em um painel dedicadoMostrar barra de rolagem horizontalMostrar ícones e textoMostrar imagemMostrar número de linhasMostrar uso da memória a cadaMostrar lista de módulos que foram recarregadosMostrar comentários especiaisMostrar barra de statusMostrar conteúdo do sys.pathMostrar conteúdo da sys.path...Mostrar barra de abasMostrar lista de tarefasMostrar barra de ferramentasMostrar uma linha vertical depois deMostrar lista de erros e avisosMostrar/esconder o explorador de códigoÁreas laterais:SiftTamanhoTamanho:Pular linhas:InteligenteCódi&goOrigemCódigo fonteBarra de códigoSphinx %s está instalado atualmente.Dividir horizontalmenteDividir horizontalmente esta janela de ediçãoDividir verticalmenteDividir verticalmente esta janela de ediçãoLayout padrão do SpyderSpyder EditorConsole interno do Spyder! Este console é usado para reportar erros internos do aplicativo e para inspecionar as características internas do Spyder com os seguintes comandos: spy.app, spy.window, dir(spy) Por favor não execute seu código neste console Não é possível resetar o Spyder para suas definições padrões. Reiniciamento abortado.Arquivos data do SpyderO Spyder depende de vários módulos do Python para fornecer suas funcionalidades corretamente em todos os painéis. A tabela abaixo mostra as versões requeridas e instaladas (se houver) de todos eles.

Nota: Você pode usar o Spyder normalmente sem os seguintes módulos instalados: %se %sDocumentação do SpyderErro de saída do SpyderO Spyder está atualizado.O Spyder precisa ser reiniciado para mudança de tal configuração:O Spyder precisa ser reiniciado para mudança de tais configurações:Erro ao resetarErro de reiniciamentoSuporte do Spyder...Tutorial do SpyderAtualizações do SpyderO Spyder não foi capaz de receber o valor desta variável do console.

A mensagem de erro foi:
%sO Spyder será reiniciado e resetado para suas definições padrões:

Deseja continuar?Chave sshIniciar buscaInicializaçãoBarra de statusExecutar linhaIngressar na função/métodoSair da função/métodoIngressar na função ou método da linha atualPararParar depuraçãoParar buscaParar o comando atualString não encontradaString:Suporte para criação de gráficos (Matplotlib)Arquivos suportadosArquivos de texto suportadosPesquisador de símbolos....Matemática simbólicaMatemática simbólica no console IPythonSincronizarSincronizar a lista de caminhos do Spyder com a variável de ambiente PYTHONPATHSincronizar...Sintaxe coloridaSintaxe colorida para arquivos do tipo Matlab, Julia e outros tiposComandos do sistema:Imagens TIFFTabulaçãoSempre indentar com a tecla TabLargura da tabulação:TabulaçõesSeparar os menusArquivo temporário TerminalTextoEditor de textoArquivos de textoO argumento de comprimento 'xlabels' não corresponde com o número de colunas da matrizO argumento de comprimento 'ylabels' não corresponde com o número de linhas da matrizO EditorO Explorador de ArquivosO Log do HistóricoO console IPythonO Explorador de VariáveisA autenticidade do servidor %s não pode ser estabelecida. Você tem certeza que deseja continuar conectando?A autenticidade do servidor não pode ser estabelecidaO diretório atual contém um projeto.

Se você deseja mesmo deletar o projeto, por favor vá em Projetos » Deletar ProjetoO diretório {} não está em modo de escrita e isto é necessário para criar consoles IPython. Por favor deixe-o em modo de escrita.Os seguintes conflitos foram detectados:Ocorreu o seguinte erro quando o Sphinx %s tentou ser utilizado.
Isso se deve a uma versão incompatível do Sphinx ou não foi possível ler a documentação solicitada.

Mensagem de erro:
%sOs seguintes módulos não estão instalados no seu computador: %sO seguinte diretório de trabalho não é válido:
%sEste diretório já está incluído na lista de caminhos do Spyder.
Deseja mover ele para o topo da lista?Esta entrada é incorretaEsta funcionalidade requer Sphinx 1.1 ou superior.Esta funcionalidade requer as bibliotecas Rope ou Jedi. Parece que você não possui elas instalada.Este é um kernel remotoEste é um arquivo de script temporário.Este é um dos painéis aonde você consegue executar o código que você escreveu no Editor. Para fazer isso pressione a tecla F5.

Este console possui diversas funcionalidades úteis que podem improvisar sua experiência programando (como sintaxe colorida). Se você quiser saber mais sobre isso, visite link.

Por favor clique no botão abaixo para executar um simples código neste console. Isso será útil para mostrar para você outras funcionalidades importantes.Este é o painel aonde você escreve seu código Python antes de testa-lo. Enquanto digita você pode receber sugestões automáticas e completação apertando a tecla Tab depois do texto inserido.

O Editor possui uma área com uma linha numérica (destacada aqui em vermelho), nesta mesma área o Spyder mostra avisos e erros de sintaxe. Isso pode ajudar você a detectar potencial problemas antes de executar o código.

Você também pode definir pontos de interrupção para debugação nesta área.Este é o diretório de trabalho para os consoles recém abertos (do IPython/Python e terminais), para o Explorador de arquivos, Buscar em arquivos e para os novos arquivos criados no EditorIsso lhe permite carregar o suporte gráfico sem importar os comandos para criar imagens. É útil para trabalhar com outras bibliotecas gráficas diferentes da Matplotlib ou para desenvolver interfaces gráficas com o Spyder.Esta opção permite ocultar a mensagem que aparece no topo do console quando se abre ele pela primeira vez.Esta opção carrega a biblioteca Sympy para trabalhar
com ela. Por favor leia sua documentação para aprender a usá-la. Esta opção será aplicada na próxima vez que um console for aberto.Esta opção ativará o Recarregador de Módulos do Usuário (RMU) nos consoles Python/IPython. O RMU força o Python a recarregar profundamente os módulos que foram importados ao executar um arquivo do Python, usando a função incorporada do Spyder chamada runfile.

1. O RMU pode necessitar que se reinicie o console em o qual será utilizado (de outra forma, só os módulos que foram importados em último lugar serão recarregados ao executar um arquivo).

2. Se ocorrer algum erro ao re-executar um programa baseado no PyQt, por favor verifique se os objetos do Qt foram destruídos apropriadamente (por exemplo, você pode ter que utilizar o atributo Qt.WA_DeleteOnClose em sua janela principal, utilizando o método setAttribute)Este painel pode mostrar automaticamente a ajuda de um objeto depois de escrever um parênteses no mesmo. A seguir você pode decidir a que painel/componente você deseja conectar para ativar esta característica.Este painel mostra a documentação de funções, classes, métodos ou módulos que você está usando no Editor ou nos Consoles.

Para usar esta funcionalidade você deve pressionar Ctrl+I na frente de um objeto. Se este objeto possuir alguma documentação associada a ele, ela será mostrada aqui.Este painel permite você navegar entre os diretórios e arquivos presentes no seu computador.

Você também pode abrir qualquer arquivo com a aplicação correspondente ao mesmo clicando duas vezes nele.

Existe apenas uma exceção para isso: arquivos de texto simples, esses sempre serão abertos no editor do Spyder.Este painel grava todos os comandos executados nos consoles do Python e IPython.Isso irá sincronizar a lista de caminhos do Spyder com a variável de ambiente PYTHONPATHpara o usuário atual, permitindo executar seus módulos de Python fora do Spyder sem precisar configurar o sys.path.
Deseja limpar o conteúdo da PYTHONPATH antes de adicionar a lista de caminhos do Spyder?Para booleanoPara complexoTo doPara flutuantePara inteiroPara stringAlternar MinúsculasAlternar MaiúsculasBarra de ferramentasTransporO túnel '%s' falhou ao ser iniciadoTuplaTipoRMUO RMU força o Python a recarregar os módulos que foram importados durante a execução de um arquivo no console com a função runfile.Não foi possível verificar por atualizações.Não foi possível conectar a %sNão foi possível conectar a internet.

Tenha certeza se a conexão está realmente funcionando.Não foi possível carregar a páginaNão foi possível receber a informação.DescomentarDesfazerErro inesperado: veja o console internoDesfazer indentaçãoDesfazer indentação da linha ou seleção atualDestrancarParênteses abertos:Atualize LANGUAGE_CODES (config/base.py) se um novo idioma for adicionado ao SpyderAtualizar a lista de nomes dos módulosUsoUsar um paginador para mostrar textos dentro do consoleUsar uma única instância Usar próximo layoutUsar layout anteriorUsar matemática simbólicaUsar o seguinte interpretador:Use o seguinte arquivo:Usar o completador gulosoUsar controlador de versãoIsso é útil se não deseja preencher o console com grandes textos de ajuda. Nota: Use a tecla Q para sair do paginador.Recarregador de Módulos do Usuário (RMU)ValorValor:Nome da variávelExplorador de variáveisNome da variável:Controlador de versãoSistema de Controle de VersãoAbas dos painéis na verticalBarra de titulo em verticalViTablesVer e editar DataFrames e Series no Explorador de VariáveisVer e editar duas e três matrizes dimensionais no Explorador de VariáveisAvisoArquivos de Páginas webBem-vindo ao tour de introdução ao SpyderBem-vindo ao Spyder!Bem-vindo ao tour de introduçãoQuando for aberto um arquivo de texto que contenha vários tipos de caracteres de fim de linha (o qual pode dar erros no Windows). O Spyder pode consertar o arquivo automaticamente.Palavras inteirasLargura:WinPythonPainel de controle WinPythonO esquema das janelas será reiniciado para as configurações padrões: isso afeta a posição, tamanho e componentes da janela. Deseja continuar?Layouts da janelaEspaço de trabalhoAjuste de linha automáticoArquivos XMLArquivos YamlVocê está utilizando Python 2, não é possível importar um módulo que contenha não contenha caracteres ascii.Você também pode executar um arquivo por inteiro ao inicializar, em vez de poucas linhas (Isso é similar a ter um arquivo PYTHONSTARTUP).Você pode executar várias linhas de código ao abrir um terminal. Por favor introduza cada uma separada por vírgulas, por exemplo:
import os, import sysVocê não tem permissão para abrir esse diretórioVocê selecionou um interpretador Python %d para o console, mas o Spyder está sendo executado em Python %d!.

Embora isso seja possível, nós recomendamos instalar e executar o Spyder diretamente com o interpretador selecionado, para evitar ver falsos erros e avisos no Editor devido a sintaxe incompatível entre estas duas versões do Python.Você selecionou um interpretador inválido do Python para o console, o interpretador anterior irá continuar. Por favor tenha certeza se você selecionou um válido.Sua instalação do Python não possui o módulo ipykernel instalado. Sem esse módulo não é possível que o Spyder crie um console.

Você pode instalar o ipykernel executando no terminal tal comando:

pip install ipykernel

ou

conda install ipykernelMais zoomMenos zoomResetar ZoommatrizcaracterescódigocopiardadosdeletardpielementosarquivoArquivos gettext Exemplos do guidataExemplos do guiqwtpolegadasexpressão regular inválidalinhaslistacorrespondências emmoveroutropermissão negada, foram encontrados errospixelsArquivos de texto reeStruturadosomente leituraespaçostabelatextoO seguinte diretório:este dialogo tutorialarquivo não salvoSem títulousuário@servidor:portanome_da_variávelspyder-3.2.6/spyder/locale/pt_BR/LC_MESSAGES/spyder.po0000664000175000017500000050557113224121062023036 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # Spyder's brazilian portuguese translation file # Valter Nazianzeno , 2014. # msgid "" msgstr "" "Project-Id-Version: 3.8POT-Creation-Date: 2017-01-17 12:57-0300\n" "POT-Creation-Date: 2017-12-14 15:40+-05\n" "PO-Revision-Date: 2017-01-17 14:38-0300\n" "Last-Translator: Valter Nazianzeno \n" "Language-Team: pt_BR\n" "Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "X-Generator: Poedit 1.8.11\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #: spyder/app/mainwindow.py:134 msgid "Initializing..." msgstr "Iniciando..." #: spyder/app/mainwindow.py:237 #, fuzzy msgid "Python2 documentation" msgstr "Documentação do Python" #: spyder/app/mainwindow.py:239 #, fuzzy msgid "Python3 documentation" msgstr "Documentação do Python" #: spyder/app/mainwindow.py:241 msgid "Numpy and Scipy documentation" msgstr "Documentação do Numpy e Scipy" #: spyder/app/mainwindow.py:243 msgid "Matplotlib documentation" msgstr "Documentação do Matplotlib" #: spyder/app/mainwindow.py:246 msgid "PyQt4 Reference Guide" msgstr "Guia de referência do PyQt4" #: spyder/app/mainwindow.py:249 msgid "PyQt4 API Reference" msgstr "Referência da API do PyQt4" #: spyder/app/mainwindow.py:252 #, fuzzy msgid "PyQt5 Reference Guide" msgstr "Guia de referência do PyQt4" #: spyder/app/mainwindow.py:255 #, fuzzy msgid "PyQt5 API Reference" msgstr "Referência da API do PyQt4" #: spyder/app/mainwindow.py:257 msgid "WinPython" msgstr "WinPython" #: spyder/app/mainwindow.py:530 msgid "" "An error occurred while creating a socket needed by Spyder. Please, try to " "run as an Administrator from cmd.exe the following command and then restart " "your computer:

netsh winsock reset
" msgstr "" #: spyder/app/mainwindow.py:562 msgid "Close current pane" msgstr "Fechar painel atual" #: spyder/app/mainwindow.py:567 msgid "Lock panes" msgstr "Travar painéis" #: spyder/app/mainwindow.py:574 msgid "Use next layout" msgstr "Usar próximo layout" #: spyder/app/mainwindow.py:578 msgid "Use previous layout" msgstr "Usar layout anterior" #: spyder/app/mainwindow.py:588 spyder/widgets/editor.py:497 msgid "File switcher..." msgstr "Seletor de arquivo..." #: spyder/app/mainwindow.py:590 msgid "Fast switch between files" msgstr "Troca rápida de seleção entre arquivos" #: spyder/app/mainwindow.py:596 msgid "Symbol finder..." msgstr "Pesquisador de símbolos...." #: spyder/app/mainwindow.py:598 msgid "Fast symbol search in file" msgstr "Pesquisa rápida de símbolos no arquivo" #: spyder/app/mainwindow.py:617 spyder/widgets/sourcecode/codeeditor.py:2661 msgid "Undo" msgstr "Desfazer" #: spyder/app/mainwindow.py:619 spyder/widgets/sourcecode/codeeditor.py:2664 msgid "Redo" msgstr "Refazer" #: spyder/app/mainwindow.py:621 spyder/widgets/shell.py:123 #: spyder/widgets/sourcecode/codeeditor.py:2670 #: spyder/widgets/variableexplorer/arrayeditor.py:467 #: spyder/widgets/variableexplorer/collectionseditor.py:671 #: spyder/widgets/variableexplorer/dataframeeditor.py:586 msgid "Copy" msgstr "Copiar" #: spyder/app/mainwindow.py:623 spyder/widgets/shell.py:119 #: spyder/widgets/sourcecode/codeeditor.py:2667 msgid "Cut" msgstr "Recortar" #: spyder/app/mainwindow.py:625 spyder/widgets/shell.py:127 #: spyder/widgets/sourcecode/codeeditor.py:2673 #: spyder/widgets/variableexplorer/collectionseditor.py:668 msgid "Paste" msgstr "Colar" #: spyder/app/mainwindow.py:628 spyder/widgets/shell.py:140 #: spyder/widgets/sourcecode/codeeditor.py:2676 msgid "Select All" msgstr "Selecionar tudo" #: spyder/app/mainwindow.py:638 spyder/plugins/editor.py:1423 msgid "&File" msgstr "&Arquivo" #: spyder/app/mainwindow.py:639 spyder/plugins/editor.py:1411 msgid "File toolbar" msgstr "Barra de arquivo" #: spyder/app/mainwindow.py:643 spyder/plugins/editor.py:1424 msgid "&Edit" msgstr "&Editar" #: spyder/app/mainwindow.py:644 spyder/plugins/editor.py:1421 msgid "Edit toolbar" msgstr "Barra de edição" #: spyder/app/mainwindow.py:648 spyder/plugins/editor.py:1425 msgid "&Search" msgstr "&Pesquisar" #: spyder/app/mainwindow.py:649 spyder/plugins/editor.py:1413 msgid "Search toolbar" msgstr "Barra de pesquisa" #: spyder/app/mainwindow.py:653 spyder/plugins/editor.py:1426 msgid "Sour&ce" msgstr "Códi&go" #: spyder/app/mainwindow.py:654 spyder/plugins/editor.py:1415 msgid "Source toolbar" msgstr "Barra de código" #: spyder/app/mainwindow.py:658 spyder/plugins/editor.py:803 #: spyder/plugins/editor.py:1427 msgid "&Run" msgstr "&Executar" #: spyder/app/mainwindow.py:659 spyder/plugins/editor.py:1417 msgid "Run toolbar" msgstr "Barra de execução " #: spyder/app/mainwindow.py:663 spyder/plugins/editor.py:762 msgid "&Debug" msgstr "&Depurar" #: spyder/app/mainwindow.py:664 spyder/plugins/editor.py:1419 msgid "Debug toolbar" msgstr "Barra de depuração" #: spyder/app/mainwindow.py:668 msgid "C&onsoles" msgstr "C&onsoles" #: spyder/app/mainwindow.py:671 msgid "&Projects" msgstr "&Projetos" #: spyder/app/mainwindow.py:674 spyder/plugins/editor.py:1428 msgid "&Tools" msgstr "&Ferramentas" #: spyder/app/mainwindow.py:677 spyder/plugins/editor.py:1429 msgid "&View" msgstr "&Ver" #: spyder/app/mainwindow.py:680 spyder/plugins/editor.py:1430 msgid "&Help" msgstr "A&juda" #: spyder/app/mainwindow.py:685 msgid "Welcome to Spyder!" msgstr "Bem-vindo ao Spyder!" #: spyder/app/mainwindow.py:690 msgid "Pre&ferences" msgstr "Pre&ferências" #: spyder/app/mainwindow.py:697 spyder/widgets/pathmanager.py:53 msgid "PYTHONPATH manager" msgstr "Gerenciar PYTHONPATH" #: spyder/app/mainwindow.py:700 msgid "Python Path Manager" msgstr "Gerenciador de caminhos do Python" #: spyder/app/mainwindow.py:703 msgid "Update module names list" msgstr "Atualizar a lista de nomes dos módulos" #: spyder/app/mainwindow.py:706 msgid "Refresh list of module names available in PYTHONPATH" msgstr "Atualizar a lista de nomes dos módulos disponíveis no PYTHONPATH" #: spyder/app/mainwindow.py:709 msgid "Reset Spyder to factory defaults" msgstr "Resetar configuração padrão do Spyder" #: spyder/app/mainwindow.py:714 msgid "Current user environment variables..." msgstr "Variáveis de ambiente do usuário atual..." #: spyder/app/mainwindow.py:716 msgid "" "Show and edit current user environment variables in Windows registry (i.e. " "for all sessions)" msgstr "" "Mostrar e editar as variáveis de\n" "ambiente do usuário atual no\n" "registro do Windows (para todas\n" "as sessões)" #: spyder/app/mainwindow.py:725 spyder/app/mainwindow.py:1147 msgid "External Tools" msgstr "Ferramentas externas" #: spyder/app/mainwindow.py:728 msgid "WinPython control panel" msgstr "Painel de controle WinPython" #: spyder/app/mainwindow.py:737 msgid "Qt Designer" msgstr "Qt Designer" #: spyder/app/mainwindow.py:742 msgid "Qt Linguist" msgstr "Qt Linguist" #: spyder/app/mainwindow.py:748 msgid "Qt examples" msgstr "Exemplos do Qt" #: spyder/app/mainwindow.py:768 msgid "guidata examples" msgstr "Exemplos do guidata" #: spyder/app/mainwindow.py:779 msgid "guiqwt examples" msgstr "Exemplos do guiqwt" #: spyder/app/mainwindow.py:784 msgid "Sift" msgstr "Sift" #: spyder/app/mainwindow.py:794 msgid "ViTables" msgstr "ViTables" #: spyder/app/mainwindow.py:808 msgid "Fullscreen mode" msgstr "Modo tela cheia" #: spyder/app/mainwindow.py:820 msgid "Main toolbar" msgstr "Barra principal" #: spyder/app/mainwindow.py:829 msgid "" "Spyder Internal Console\n" "\n" "This console is used to report application\n" "internal errors and to inspect Spyder\n" "internals with the following commands:\n" " spy.app, spy.window, dir(spy)\n" "\n" "Please don't use it to run your code\n" "\n" msgstr "" "Console interno do Spyder!\n" "\n" "Este console é usado para reportar erros\n" "internos do aplicativo e para inspecionar\n" "as características internas do Spyder com\n" "os seguintes comandos:\n" " spy.app, spy.window, dir(spy)\n" "\n" "Por favor não execute seu código neste console\n" #: spyder/app/mainwindow.py:846 msgid "Loading help..." msgstr "Carregando ajuda..." #: spyder/app/mainwindow.py:853 msgid "Loading outline explorer..." msgstr "Carregando o explorador de código..." #: spyder/app/mainwindow.py:861 msgid "Loading editor..." msgstr "Carregando editor..." #: spyder/app/mainwindow.py:867 spyder/plugins/console.py:140 #: spyder/widgets/ipythonconsole/client.py:417 msgid "&Quit" msgstr "&Sair" #: spyder/app/mainwindow.py:869 spyder/plugins/console.py:142 msgid "Quit" msgstr "Sair" #: spyder/app/mainwindow.py:873 msgid "&Restart" msgstr "&Reiniciar" #: spyder/app/mainwindow.py:875 msgid "Restart" msgstr "Reiniciar" #: spyder/app/mainwindow.py:889 msgid "Loading file explorer..." msgstr "Carregando explorador de arquivos..." #: spyder/app/mainwindow.py:896 msgid "Loading history plugin..." msgstr "Carregando histórico..." #: spyder/app/mainwindow.py:907 msgid "Loading online help..." msgstr "Carregando ajuda online..." #: spyder/app/mainwindow.py:912 msgid "Loading project explorer..." msgstr "Carregando explorador de projetos..." #: spyder/app/mainwindow.py:925 msgid "Loading namespace browser..." msgstr "Carregando explorador de variáveis..." #: spyder/app/mainwindow.py:931 msgid "Loading IPython console..." msgstr "Carregando console IPython..." #: spyder/app/mainwindow.py:936 msgid "Setting up main window..." msgstr "Configurando tela principal..." #: spyder/app/mainwindow.py:939 msgid "Dependencies..." msgstr "Dependências..." #: spyder/app/mainwindow.py:943 msgid "Report issue..." msgstr "Reportar problema..." #: spyder/app/mainwindow.py:947 msgid "Spyder support..." msgstr "Suporte do Spyder..." #: spyder/app/mainwindow.py:950 msgid "Check for updates..." msgstr "Verificar por atualizações..." #: spyder/app/mainwindow.py:973 msgid "Spyder documentation" msgstr "Documentação do Spyder" #: spyder/app/mainwindow.py:981 msgid "Spyder tutorial" msgstr "Tutorial do Spyder" #: spyder/app/mainwindow.py:986 #, fuzzy msgid "Shortcuts Summary" msgstr "Atalho" #: spyder/app/mainwindow.py:992 msgid "Interactive tours" msgstr "Tours interativas" #: spyder/app/mainwindow.py:1018 msgid "Python documentation" msgstr "Documentação do Python" #: spyder/app/mainwindow.py:1024 msgid "IPython documentation" msgstr "Documentação do IPython" #: spyder/app/mainwindow.py:1025 msgid "Intro to IPython" msgstr "Introdução ao IPython" #: spyder/app/mainwindow.py:1027 msgid "Quick reference" msgstr "Referência rápida" #: spyder/app/mainwindow.py:1029 msgid "Console help" msgstr "Ajuda do console" #: spyder/app/mainwindow.py:1059 msgid "Installed Python modules" msgstr "Módulos instalados do Python" #: spyder/app/mainwindow.py:1063 msgid "Online documentation" msgstr "Documentação online" #: spyder/app/mainwindow.py:1076 msgid "Qt documentation" msgstr "Documentação do Qt" #: spyder/app/mainwindow.py:1082 msgid "About %s..." msgstr "Sobre o %s..." #: spyder/app/mainwindow.py:1113 msgid "Panes" msgstr "Painéis" #: spyder/app/mainwindow.py:1115 msgid "Toolbars" msgstr "Barra de ferramentas" #: spyder/app/mainwindow.py:1116 msgid "Window layouts" msgstr "Layouts da janela" #: spyder/app/mainwindow.py:1125 spyder/app/mainwindow.py:1924 #: spyder/app/mainwindow.py:1925 msgid "Show toolbars" msgstr "Mostrar barra de ferramentas" #: spyder/app/mainwindow.py:1140 msgid "Attached console window (debugging)" msgstr "Janela do console anexada (depuração)" #: spyder/app/mainwindow.py:1317 spyder/plugins/console.py:220 #: spyder/plugins/projects.py:248 spyder/widgets/explorer.py:708 #: spyder/widgets/explorer.py:813 #: spyder/widgets/variableexplorer/arrayeditor.py:587 #: spyder/widgets/variableexplorer/collectionseditor.py:427 #: spyder/widgets/variableexplorer/dataframeeditor.py:752 #: spyder/widgets/variableexplorer/dataframeeditor.py:756 #: spyder/widgets/variableexplorer/namespacebrowser.py:299 msgid "Error" msgstr "Erro" #: spyder/app/mainwindow.py:1318 msgid "" "You have missing dependencies!

%s

Please " "install them to avoid this message.

Note: Spyder could " "work without some of these dependencies, however to have a smooth experience " "when using Spyder we strongly recommend you to install all the listed " "missing dependencies.

Failing to install these dependencies might " "result in bugs. Please be sure that any found bugs are not the direct result " "of missing dependencies, prior to reporting a new issue." msgstr "" "Você tem dependências faltando!

%s

Por " "favor instale elas para evitar esta mensagem.

Nota: O " "Spyder pode funcionar sem algumas dependências, porém para ter uma " "experiência melhor ao utilizar o software recomendamos fortemente a " "instalação das dependências listadas que estão faltando.

A não " "instalação destas dependências pode gerar bugs. Antes de relatar um novo " "problema certifique-se de que quaisquer bugs encontrados não são o resultado " "das dependências que estão faltando." #: spyder/app/mainwindow.py:1771 msgid "Spyder Default Layout" msgstr "Layout padrão do Spyder" #: spyder/app/mainwindow.py:1789 msgid "Save current layout" msgstr "Salvar layout atual" #: spyder/app/mainwindow.py:1793 msgid "Layout preferences" msgstr "Preferências do Layout" #: spyder/app/mainwindow.py:1797 msgid "Reset to spyder default" msgstr "Resetar para o layout padrão do Spyder" #: spyder/app/mainwindow.py:1817 spyder/app/mainwindow.py:1839 #: spyder/app/mainwindow.py:1902 spyder/app/mainwindow.py:2722 #: spyder/plugins/configdialog.py:1346 spyder/plugins/ipythonconsole.py:131 #: spyder/plugins/ipythonconsole.py:927 spyder/plugins/ipythonconsole.py:1365 #: spyder/plugins/maininterpreter.py:149 spyder/plugins/maininterpreter.py:174 #: spyder/plugins/maininterpreter.py:203 spyder/utils/environ.py:95 #: spyder/utils/environ.py:108 #: spyder/widgets/ipythonconsole/namespacebrowser.py:131 #: spyder/widgets/ipythonconsole/namespacebrowser.py:149 #: spyder/widgets/variableexplorer/arrayeditor.py:510 #: spyder/widgets/variableexplorer/collectionseditor.py:416 #: spyder/widgets/variableexplorer/collectionseditor.py:1092 msgid "Warning" msgstr "Aviso" #: spyder/app/mainwindow.py:1818 msgid "" "Window layout will be reset to default settings: this affects window " "position, size and dockwidgets.\n" "Do you want to continue?" msgstr "" "O esquema das janelas será reiniciado para as configurações padrões: isso " "afeta a posição, tamanho e componentes da janela.\n" "Deseja continuar?" #: spyder/app/mainwindow.py:1840 msgid "" "Layout %s will be " "overwritten. Do you want to " "continue?" msgstr "" "Layout %s será " "sobrescrito. Você deseja " "Continuar?" #: spyder/app/mainwindow.py:1903 msgid "Quick switch layout #%s has not yet been defined." msgstr "Troca rápida do layout #%s ainda não foi definida." #: spyder/app/mainwindow.py:1921 spyder/app/mainwindow.py:1922 msgid "Hide toolbars" msgstr "Esconder barra de ferramentas" #: spyder/app/mainwindow.py:2237 spyder/app/mainwindow.py:2238 msgid "Maximize current pane" msgstr "Maximizar painel atual" #: spyder/app/mainwindow.py:2241 msgid "Restore current pane" msgstr "Restaurar painel atual" #: spyder/app/mainwindow.py:2242 msgid "Restore pane to its original size" msgstr "Restaurar painel ao seu tamanho original" #: spyder/app/mainwindow.py:2327 msgid "About %s" msgstr "Sobre o %s" #: spyder/app/mainwindow.py:2460 spyder/plugins/editor.py:168 #: spyder/plugins/runconfig.py:354 spyder/plugins/runconfig.py:476 #: spyder/utils/programs.py:286 spyder/widgets/explorer.py:335 msgid "Run" msgstr "Executar" #: spyder/app/mainwindow.py:2461 msgid "Running an external system terminal is not supported on platform %s." msgstr "Executar um terminal externo não é suportado na plataforma %s." #: spyder/app/mainwindow.py:2723 msgid "" "Spyder will restart and reset to default settings:

Do you want to " "continue?" msgstr "" "O Spyder será reiniciado e resetado para suas definições padrões: " "

Deseja continuar?" #: spyder/app/mainwindow.py:2851 spyder/widgets/helperwidgets.py:254 msgid "Spyder updates" msgstr "Atualizações do Spyder" #: spyder/app/mainwindow.py:2852 spyder/plugins/configdialog.py:836 msgid "Check for updates on startup" msgstr "Verificar por atualizações na inicialização" #: spyder/app/mainwindow.py:2871 msgid "" "
IMPORTANT NOTE: It seems that you are using Spyder with " "Anaconda/Miniconda. Please don't use pip to " "update it as that will probably break your installation.

Instead, " "please wait until new conda packages are available and use conda to perform the update.
" msgstr "" #: spyder/app/mainwindow.py:2881 msgid "" "Spyder %s is available!

Please use your package manager to " "update Spyder or go to our Releases page to download this " "new version.

If you are not sure how to proceed to update Spyder " "please refer to our Installation instructions." msgstr "" "Spyder %s está disponível!

Por favor utilize o seu " "gerenciador de pacotes ou visite a página Releases para " "baixar a nova versão.

Se você não sabe como atualizar o Spyder " "visite a página de instruções Installation." #: spyder/app/mainwindow.py:2894 msgid "Spyder is up to date." msgstr "O Spyder está atualizado." #: spyder/app/restart.py:134 msgid "" "It was not possible to close the previous Spyder instance.\n" "Restart aborted." msgstr "" "Não foi possível fechar a última instância do Spyder.\n" "Reiniciamento abortado." #: spyder/app/restart.py:136 msgid "" "Spyder could not reset to factory defaults.\n" "Restart aborted." msgstr "" "Não é possível resetar o Spyder para suas definições padrões.\n" "Reiniciamento abortado." #: spyder/app/restart.py:138 msgid "" "It was not possible to restart Spyder.\n" "Operation aborted." msgstr "" "Não foi possível reiniciar o Spyder.\n" "Operação abortada." #: spyder/app/restart.py:140 msgid "Spyder exit error" msgstr "Erro de saída do Spyder" #: spyder/app/restart.py:141 msgid "Spyder reset error" msgstr "Erro ao resetar" #: spyder/app/restart.py:142 msgid "Spyder restart error" msgstr "Erro de reiniciamento" #: spyder/app/restart.py:183 msgid "Closing Spyder" msgstr "Fechando o Spyder" #: spyder/app/restart.py:257 msgid "Resetting Spyder to defaults" msgstr "Resetando definições padrões do Spyder" #: spyder/app/restart.py:289 msgid "Restarting" msgstr "Reiniciando" #: spyder/app/tour.py:123 msgid "Welcome to the Introduction tour" msgstr "Bem-vindo ao tour de introdução" #: spyder/app/tour.py:124 msgid "" "Spyder is a powerful Interactive Development Environment (or IDE) for " "the Python programming language.

Here we are going to guide you " "through its most important features.

Please use the arrow keys or " "click on the buttons below to move along the tour." msgstr "" "Spyder é um poderoso Ambiente de Desenvolvimento Integrado (ou IDE) " "para a linguagem de programação Python.

Aqui vamos guiar você nas " "mais importantes características e funcionalidades do Spyder.

Por " "favor use as teclas de seta ou clique nos botões abaixo para se mover " "durante a tour." #: spyder/app/tour.py:133 msgid "The Editor" msgstr "O Editor" #: spyder/app/tour.py:134 msgid "" "This is the pane where you write Python code before evaluating it. You can " "get automatic suggestions and completions while writing, by pressing the " "Tab key next to a given text.

The Editor comes with a line " "number area (highlighted here in red), where Spyder shows warnings and " "syntax errors. They can help you to detect potential problems before running " "the code.

You can also set debug breakpoints in the line number area, " "by doing a double click next to a non-empty line." msgstr "" "Este é o painel aonde você escreve seu código Python antes de testa-lo. " "Enquanto digita você pode receber sugestões automáticas e completação " "apertando a tecla Tab depois do texto inserido.

O Editor " "possui uma área com uma linha numérica (destacada aqui em vermelho), nesta " "mesma área o Spyder mostra avisos e erros de sintaxe. Isso pode ajudar você " "a detectar potencial problemas antes de executar o código.

Você " "também pode definir pontos de interrupção para debugação nesta área." #: spyder/app/tour.py:149 msgid "The IPython console" msgstr "O console IPython" #: spyder/app/tour.py:150 msgid "" "This is one of panes where you can run or execute the code you wrote on the " "Editor. To do it you need to press the F5 key.

This console " "comes with several useful features that greatly improve your programming " "workflow (like syntax highlighting and inline plots). If you want to know " "more about them, please follow this link.

Please " "click on the button below to run some simple code in this console. This will " "be useful to show you other important features." msgstr "" "Este é um dos painéis aonde você consegue executar o código que você " "escreveu no Editor. Para fazer isso pressione a tecla F5.

Este " "console possui diversas funcionalidades úteis que podem improvisar sua " "experiência programando (como sintaxe colorida). Se você quiser saber mais " "sobre isso, visite link.

Por favor clique no " "botão abaixo para executar um simples código neste console. Isso será útil " "para mostrar para você outras funcionalidades importantes." #: spyder/app/tour.py:166 msgid "The Variable Explorer" msgstr "O Explorador de Variáveis" #: spyder/app/tour.py:167 msgid "" "In this pane you can view and edit the variables generated during the " "execution of a program, or those entered directly in one of Spyder consoles." "

As you can see, the Variable Explorer is showing the variables " "generated during the last step of this tour. By doing a double-click on any " "of them, a new window will be opened, where you can inspect and modify their " "contents." msgstr "" "Neste painel você pode ver e editar as variáveis geradas durante a execução " "de um programa ou quando digitadas diretamente em um dos consoles do Spyder." "

Como você pode ver, o Explorador de Variáveis está mostrando as " "variáveis geradas durante o passo anterior desta tour. Clicando duas vezes " "em qualquer uma delas uma nova janela será aberta, aonde você poderá " "inspecionar e modificar seus valores." #: spyder/app/tour.py:179 spyder/plugins/help.py:479 spyder/plugins/help.py:921 #: spyder/widgets/internalshell.py:270 msgid "Help" msgstr "Ajuda" #: spyder/app/tour.py:180 msgid "" "This pane displays documentation of the functions, classes, methods or " "modules you are currently using in the Editor or the Consoles.

To use " "it, you need to press Ctrl+I in front of an object. If that object " "has some documentation associated with it, it will be displayed here." msgstr "" "Este painel mostra a documentação de funções, classes, métodos ou módulos " "que você está usando no Editor ou nos Consoles.

Para usar esta " "funcionalidade você deve pressionar Ctrl+I na frente de um objeto. Se " "este objeto possuir alguma documentação associada a ele, ela será mostrada " "aqui." #: spyder/app/tour.py:190 msgid "The File Explorer" msgstr "O Explorador de Arquivos" #: spyder/app/tour.py:191 msgid "" "This pane lets you navigate through the directories and files present in " "your computer.

You can also open any of these files with its " "corresponding application, by doing a double click on it.

There is " "one exception to this rule: plain-text files will always be opened in the " "Spyder Editor." msgstr "" "Este painel permite você navegar entre os diretórios e arquivos presentes no " "seu computador.

Você também pode abrir qualquer arquivo com a " "aplicação correspondente ao mesmo clicando duas vezes nele.

Existe " "apenas uma exceção para isso: arquivos de texto simples, esses sempre serão " "abertos no editor do Spyder." #: spyder/app/tour.py:201 msgid "The History Log" msgstr "O Log do Histórico" #: spyder/app/tour.py:202 msgid "" "This pane records all commands introduced in the Python and IPython consoles." msgstr "" "Este painel grava todos os comandos executados nos consoles do Python e " "IPython." #: spyder/app/tour.py:250 msgid "Spyder is an interactive development environment based on bla" msgstr "" #: spyder/app/tour.py:254 msgid "Welcome to Spyder introduction tour" msgstr "Bem-vindo ao tour de introdução ao Spyder" #: spyder/app/tour.py:255 msgid "Spyder is an interactive development environment based on bla" msgstr "" #: spyder/app/tour.py:260 msgid "Introduction tour" msgstr "Tour de introdução" #: spyder/app/tour.py:261 msgid "New features in version 3.0" msgstr "Novidades na versão 3.0" #: spyder/app/tour.py:555 spyder/plugins/ipythonconsole.py:446 msgid "Run code" msgstr "Executar código" #: spyder/app/tour.py:830 msgid "Go to step: " msgstr "Vá para a etapa: " #: spyder/config/base.py:257 msgid "" "Update LANGUAGE_CODES (inside config/base.py) if a new translation has been " "added to Spyder" msgstr "" "Atualize LANGUAGE_CODES (config/base.py) se um novo idioma for adicionado ao " "Spyder" #: spyder/config/utils.py:24 msgid "Python files" msgstr "Arquivos Python" #: spyder/config/utils.py:25 msgid "Cython/Pyrex files" msgstr "Arquivos Cython/Pyrex" #: spyder/config/utils.py:26 msgid "C files" msgstr "Arquivos C" #: spyder/config/utils.py:27 msgid "C++ files" msgstr "Arquivos C++" #: spyder/config/utils.py:28 msgid "OpenCL files" msgstr "Arquivos OpenCL" #: spyder/config/utils.py:29 msgid "Fortran files" msgstr "Arquivos Fortran" #: spyder/config/utils.py:30 msgid "IDL files" msgstr "Arquivos IDL" #: spyder/config/utils.py:31 msgid "MATLAB files" msgstr "Arquivos MATLAB" #: spyder/config/utils.py:32 msgid "Julia files" msgstr "Arquivos Julia" #: spyder/config/utils.py:33 msgid "Yaml files" msgstr "Arquivos Yaml" #: spyder/config/utils.py:34 msgid "Patch and diff files" msgstr "Arquivos Patch e diff" #: spyder/config/utils.py:35 msgid "Batch files" msgstr "Arquivos Batch" #: spyder/config/utils.py:36 spyder/utils/iofuncs.py:426 msgid "Text files" msgstr "Arquivos de texto" #: spyder/config/utils.py:37 msgid "reStructuredText files" msgstr "Arquivos de texto reeStruturado" #: spyder/config/utils.py:38 msgid "gettext files" msgstr "Arquivos gettext " #: spyder/config/utils.py:39 msgid "NSIS files" msgstr "Arquivos NSIS " #: spyder/config/utils.py:40 msgid "Web page files" msgstr "Arquivos de Páginas web" #: spyder/config/utils.py:41 msgid "XML files" msgstr "Arquivos XML" #: spyder/config/utils.py:42 msgid "Javascript files" msgstr "Arquivos Javascript" #: spyder/config/utils.py:43 msgid "Json files" msgstr "Arquivos Json" #: spyder/config/utils.py:44 msgid "IPython notebooks" msgstr "Notebooks do IPython" #: spyder/config/utils.py:45 msgid "Enaml files" msgstr "Arquivos Enaml" #: spyder/config/utils.py:46 msgid "Configuration files" msgstr "Arquivos de Configuração" #: spyder/config/utils.py:48 #, fuzzy msgid "Markdown files" msgstr "Arquivos Json" #: spyder/config/utils.py:52 spyder/widgets/explorer.py:781 msgid "All files" msgstr "Todos os arquivos" #: spyder/config/utils.py:134 msgid "Supported text files" msgstr "Arquivos de texto suportados" #: spyder/plugins/__init__.py:508 spyder/plugins/editor.py:105 #: spyder/plugins/editor.py:568 spyder/plugins/editor.py:1819 #: spyder/plugins/help.py:117 spyder/plugins/help.py:380 #: spyder/widgets/editor.py:534 spyder/widgets/sourcecode/codeeditor.py:98 #: spyder/widgets/sourcecode/codeeditor.py:3193 msgid "Editor" msgstr "Editor" #: spyder/plugins/configdialog.py:144 msgid "Reset to defaults" msgstr "Redefinir Preferências" #: spyder/plugins/configdialog.py:156 msgid "Preferences" msgstr "Preferências" #: spyder/plugins/configdialog.py:508 msgid "Invalid directory path" msgstr "Caminho de diretório inválido" #: spyder/plugins/configdialog.py:511 spyder/plugins/configdialog.py:526 #: spyder/plugins/runconfig.py:220 spyder/plugins/runconfig.py:268 #: spyder/plugins/workingdirectory.py:240 spyder/widgets/explorer.py:695 #: spyder/widgets/findinfiles.py:494 spyder/widgets/pathmanager.py:258 #: spyder/widgets/projects/projectdialog.py:155 msgid "Select directory" msgstr "Selecionar diretório" #: spyder/plugins/configdialog.py:538 msgid "Invalid file path" msgstr "Caminho de arquivo inválido " #: spyder/plugins/configdialog.py:541 spyder/plugins/configdialog.py:558 msgid "Select file" msgstr "Selecionar arquivo" #: spyder/plugins/configdialog.py:557 msgid "All files (*)" msgstr "Todos os arquivos (*)" #: spyder/plugins/configdialog.py:630 msgid "Bold" msgstr "Negrito" #: spyder/plugins/configdialog.py:633 msgid "Italic" msgstr "Itálico" #: spyder/plugins/configdialog.py:687 msgid "Font: " msgstr "Fonte:" #: spyder/plugins/configdialog.py:693 msgid "Size: " msgstr "Tamanho:" #: spyder/plugins/configdialog.py:712 msgid "Font style" msgstr "Estilo de fonte" #: spyder/plugins/configdialog.py:789 msgid "Spyder needs to restart to change the following setting:" msgstr "O Spyder precisa ser reiniciado para mudança de tal configuração:" #: spyder/plugins/configdialog.py:792 msgid "Spyder needs to restart to change the following settings:" msgstr "O Spyder precisa ser reiniciado para mudança de tais configurações:" #: spyder/plugins/configdialog.py:794 msgid "Do you wish to restart now?" msgstr "Você deseja reiniciar agora?" #: spyder/plugins/configdialog.py:800 msgid "Information" msgstr "Informação" #: spyder/plugins/configdialog.py:814 spyder/plugins/configdialog.py:821 #: spyder/widgets/projects/configdialog.py:74 msgid "General" msgstr "Geral" #: spyder/plugins/configdialog.py:824 msgid "Language" msgstr "Idioma" #: spyder/plugins/configdialog.py:827 msgid "Use a single instance" msgstr "Usar uma única instância " #: spyder/plugins/configdialog.py:829 msgid "" "Set this to open external
Python files in an already running instance " "(Requires a restart)" msgstr "" "Selecione esta opção
para abrir arquivos externos de Python nessa " "instância atual (Requer que seja reiniciado)" #: spyder/plugins/configdialog.py:832 msgid "Prompt when exiting" msgstr "Mostrar mensagem de confirmação ao sair" #: spyder/plugins/configdialog.py:833 msgid "Pop up internal console when internal errors appear" msgstr "Mostrar o terminal interno quando houver erros" #: spyder/plugins/configdialog.py:853 spyder/plugins/editor.py:114 #: spyder/plugins/ipythonconsole.py:290 #: spyder/widgets/projects/configdialog.py:81 msgid "Interface" msgstr "Interface" #: spyder/plugins/configdialog.py:861 msgid "Qt windows style" msgstr "Tema do Qt" #: spyder/plugins/configdialog.py:867 msgid "Icon theme" msgstr "Tema dos icones" #: spyder/plugins/configdialog.py:871 msgid "Vertical title bars in panes" msgstr "Barra de titulo em vertical" #: spyder/plugins/configdialog.py:873 msgid "Vertical tabs in panes" msgstr "Abas dos painéis na vertical" #: spyder/plugins/configdialog.py:875 msgid "Animated toolbars and panes" msgstr "Barras e painéis animados" #: spyder/plugins/configdialog.py:877 msgid "Tear off menus" msgstr "Separar os menus" #: spyder/plugins/configdialog.py:878 msgid "Set this to detach any
menu from the main window" msgstr "Habilite esta opção
se deseja separar os menus da janela principal" #: spyder/plugins/configdialog.py:880 msgid "Custom margin for panes:" msgstr "Margem personalizada para os painéis:" #: spyder/plugins/configdialog.py:882 msgid "pixels" msgstr "pixels" #: spyder/plugins/configdialog.py:889 msgid "Cursor blinking:" msgstr "" #: spyder/plugins/configdialog.py:891 #, fuzzy msgid "ms" msgstr "ms" #: spyder/plugins/configdialog.py:930 msgid "Status bar" msgstr "Barra de status" #: spyder/plugins/configdialog.py:931 msgid "Show status bar" msgstr "Mostrar barra de status" #: spyder/plugins/configdialog.py:933 msgid "Show memory usage every" msgstr "Mostrar uso da memória a cada" #: spyder/plugins/configdialog.py:935 spyder/plugins/configdialog.py:944 #: spyder/plugins/editor.py:139 spyder/plugins/editor.py:283 msgid " ms" msgstr "ms" #: spyder/plugins/configdialog.py:942 msgid "Show CPU usage every" msgstr "Mostrar uso da CPU a cada" #: spyder/plugins/configdialog.py:975 #, fuzzy msgid "Screen resolution" msgstr "Resolução:" #: spyder/plugins/configdialog.py:977 msgid "" "Configuration for high DPI screens

Please see {0}<> for more information about these options (in English)." msgstr "" #: spyder/plugins/configdialog.py:987 #, fuzzy msgid "Normal" msgstr "Texto normal:" #: spyder/plugins/configdialog.py:991 #, fuzzy msgid "Enable auto high DPI scaling" msgstr "Ativar escala alta de DPI" #: spyder/plugins/configdialog.py:994 msgid "Set this for high DPI displays" msgstr "Ativar em telas de alto DPI" #: spyder/plugins/configdialog.py:998 #, fuzzy msgid "Set a custom high DPI scaling" msgstr "Ativar escala alta de DPI" #: spyder/plugins/configdialog.py:1001 #, fuzzy msgid "Set this for high DPI displays when auto scaling does not work" msgstr "Ativar em telas de alto DPI" #: spyder/plugins/configdialog.py:1007 msgid "" "Enter values for different screens separated by semicolons ';', float values " "are supported" msgstr "" #: spyder/plugins/configdialog.py:1034 msgid "Plain text font" msgstr "Texto simples" #: spyder/plugins/configdialog.py:1040 msgid "Rich text font" msgstr "Texto formatado" #: spyder/plugins/configdialog.py:1043 msgid "Fonts" msgstr "Fontes" #: spyder/plugins/configdialog.py:1057 msgid "Appearance" msgstr "Aparência" #: spyder/plugins/configdialog.py:1059 spyder/plugins/ipythonconsole.py:579 msgid "Advanced Settings" msgstr "Configurações avançadas" #: spyder/plugins/configdialog.py:1095 msgid "Syntax coloring" msgstr "Sintaxe colorida" #: spyder/plugins/configdialog.py:1108 msgid "" "Here you can select the color scheme used in the Editor and all other Spyder " "plugins.

You can also edit the color schemes provided by Spyder or " "create your own ones by using the options provided below.
" msgstr "" "Aqui você pode escolher o esquema de cor usado no Editor e em todos outros " "plugins do Spyder.

Você pode também editar os esquemas padrões do " "Spyder ou criar os seus próprios utilizando as opções abaixo.
" #: spyder/plugins/configdialog.py:1113 msgid "Edit selected" msgstr "Editar" #: spyder/plugins/configdialog.py:1114 msgid "Create new scheme" msgstr "Criar novo esquema" #: spyder/plugins/configdialog.py:1115 spyder/widgets/explorer.py:574 #: spyder/widgets/projects/explorer.py:242 spyder/widgets/shell.py:136 msgid "Delete" msgstr "Deletar" #: spyder/plugins/configdialog.py:1118 msgid "Reset" msgstr "Restaurar" #: spyder/plugins/configdialog.py:1125 msgid "Scheme:" msgstr "Esquema:" #: spyder/plugins/configdialog.py:1156 msgid "Manage color schemes" msgstr "Gerenciar esquemas de cores" #: spyder/plugins/configdialog.py:1347 msgid "Are you sure you want to delete this scheme?" msgstr "Você tem certeza que deseja deletar esse esquema?" #: spyder/plugins/configdialog.py:1464 msgid "Text" msgstr "Texto" #: spyder/plugins/configdialog.py:1466 msgid "Highlight" msgstr "Destaque" #: spyder/plugins/configdialog.py:1468 msgid "Background" msgstr "Plano de fundo" #: spyder/plugins/configdialog.py:1472 msgid "Scheme name:" msgstr "Nome do esquema:" #: spyder/plugins/configdialog.py:1479 msgid "Color scheme editor" msgstr "Edição do esquema de cores" #: spyder/plugins/console.py:115 msgid "Internal console" msgstr "Console interno" #: spyder/plugins/console.py:145 msgid "&Run..." msgstr "&Executar..." #: spyder/plugins/console.py:147 msgid "Run a Python script" msgstr "Executar um script Python" #: spyder/plugins/console.py:150 msgid "Environment variables..." msgstr "Variáveis de ambiente..." #: spyder/plugins/console.py:152 msgid "Show and edit environment variables (for current session)" msgstr "Mostrar e editar as variáveis de ambiente (para a sessão atual)" #: spyder/plugins/console.py:156 msgid "Show sys.path contents..." msgstr "Mostrar conteúdo da sys.path..." #: spyder/plugins/console.py:158 msgid "Show (read-only) sys.path" msgstr "Mostrar conteúdo da sys.path em modo de leitura" #: spyder/plugins/console.py:161 msgid "Buffer..." msgstr "Buffer..." #: spyder/plugins/console.py:162 spyder/plugins/history.py:43 msgid "Set maximum line count" msgstr "Definir número máximo de linhas" #: spyder/plugins/console.py:165 msgid "External editor path..." msgstr "Caminho de editor externo:" #: spyder/plugins/console.py:166 msgid "Set external editor executable path" msgstr "Definir caminho de editor externo" #: spyder/plugins/console.py:169 spyder/plugins/editor.py:149 #: spyder/plugins/help.py:152 spyder/plugins/help.py:355 #: spyder/plugins/history.py:46 spyder/plugins/history.py:157 msgid "Wrap lines" msgstr "Ajuste de linha automático" #: spyder/plugins/console.py:172 spyder/plugins/editor.py:185 #: spyder/plugins/ipythonconsole.py:300 msgid "Display balloon tips" msgstr "Mostrar sugestões" #: spyder/plugins/console.py:176 spyder/plugins/editor.py:179 msgid "Automatic code completion" msgstr "Completar código automáticamente" #: spyder/plugins/console.py:180 spyder/plugins/editor.py:183 msgid "Enter key selects completion" msgstr "A tecla Enter seleciona o resultado a completar" #: spyder/plugins/console.py:185 msgid "Internal console settings" msgstr "Configurações do console interno" #: spyder/plugins/console.py:221 msgid "" "Spyder has encountered a problem.
Sorry for the inconvenience." "

You can automatically submit this error to our Github issues tracker." "

Note: You need a Github account for that." msgstr "" #: spyder/plugins/console.py:231 msgid "Submit to Github" msgstr "" #: spyder/plugins/console.py:283 msgid "Run Python script" msgstr "Executar script Python" #: spyder/plugins/console.py:284 spyder/widgets/explorer.py:796 msgid "Python scripts" msgstr "Scripts Python" #: spyder/plugins/console.py:329 msgid "Buffer" msgstr "Buffer" #: spyder/plugins/console.py:330 msgid "Maximum line count" msgstr "Número máximo de linhas" #: spyder/plugins/console.py:340 msgid "External editor" msgstr "Editor externo" #: spyder/plugins/console.py:341 msgid "External editor executable path:" msgstr "Caminho do executável do editor externo:" #: spyder/plugins/editor.py:59 msgid "Manipulate Jupyter notebooks on the Editor" msgstr "Permite manipular Jupyter notebooks no Editor" #: spyder/plugins/editor.py:111 msgid "Edit template for new modules" msgstr "Editar template para novos módulos" #: spyder/plugins/editor.py:116 msgid "Show tab bar" msgstr "Mostrar barra de abas" #: spyder/plugins/editor.py:122 spyder/plugins/editor.py:199 #: spyder/plugins/help.py:151 spyder/plugins/history.py:45 #: spyder/plugins/ipythonconsole.py:332 msgid "Source code" msgstr "Código fonte" #: spyder/plugins/editor.py:123 msgid "Show line numbers" msgstr "Mostrar número de linhas" #: spyder/plugins/editor.py:124 spyder/plugins/editor.py:985 msgid "Show blank spaces" msgstr "Mostrar espaços em branco" #: spyder/plugins/editor.py:125 msgid "Show vertical line after" msgstr "Mostrar uma linha vertical depois de" #: spyder/plugins/editor.py:126 msgid "characters" msgstr "caracteres" #: spyder/plugins/editor.py:133 msgid "Highlight current line" msgstr "Realçar linha atual" #: spyder/plugins/editor.py:135 msgid "Highlight current cell" msgstr "Realçar célula atual" #: spyder/plugins/editor.py:137 msgid "Highlight occurrences after" msgstr "Realçar ocorrências depois de" #: spyder/plugins/editor.py:169 msgid "Save all files before running script" msgstr "Salvar tudo antes de executar um script" #: spyder/plugins/editor.py:172 msgid "Run selection" msgstr "Executar seleção" #: spyder/plugins/editor.py:173 msgid "Maintain focus in the Editor after running cells or selections" msgstr "Manter o foco no editor depois de executar células ou seleções" #: spyder/plugins/editor.py:176 msgid "Introspection" msgstr "Introspecção" #: spyder/plugins/editor.py:181 msgid "Case sensitive code completion" msgstr "Diferenciar entre maiúsculas e minusculas ao completar código" #: spyder/plugins/editor.py:186 msgid "Link to object definition" msgstr "Link para a definição do objeto" #: spyder/plugins/editor.py:188 msgid "" "If this option is enabled, clicking on an object\n" "name (left-click + Ctrl key) will go this object\n" "definition (if resolved)." msgstr "" "Se esta opção estiver ativada, clicando no nome\n" "de um objeto (clique-esquerdo + Ctrl) o editor irá\n" "mostrar a definição do mesmo." #: spyder/plugins/editor.py:192 msgid "" "Warning:
The Python module rope is not installed on this " "computer: calltips, code completion and go-to-definition features won't be " "available." msgstr "" "Aviso:
O módulo rope não está instalado neste computador: " "Por tanto a completação de código, balões de dicas e o método ir para função " "não estão disponíveis." #: spyder/plugins/editor.py:200 msgid "Automatic insertion of parentheses, braces and brackets" msgstr "Inserção automática de parênteses, chaves e colchetes" #: spyder/plugins/editor.py:203 msgid "Automatic insertion of closing quotes" msgstr "Inserção automática de aspas" #: spyder/plugins/editor.py:205 msgid "Automatic insertion of colons after 'for', 'if', 'def', etc" msgstr "Inserção automática de \":\" depois de 'for', 'if', 'def', etc" #: spyder/plugins/editor.py:208 msgid "Automatic indentation after 'else', 'elif', etc." msgstr "Indentação automática depois do 'else', 'elif', etc." #: spyder/plugins/editor.py:210 msgid "Indentation characters: " msgstr "Caracteres de indentação:" #: spyder/plugins/editor.py:211 msgid "2 spaces" msgstr "2 espaços" #: spyder/plugins/editor.py:212 msgid "3 spaces" msgstr "3 espaços" #: spyder/plugins/editor.py:213 msgid "4 spaces" msgstr "4 espaços" #: spyder/plugins/editor.py:214 msgid "5 spaces" msgstr "5 espaços" #: spyder/plugins/editor.py:215 msgid "6 spaces" msgstr "6 espaços" #: spyder/plugins/editor.py:216 msgid "7 spaces" msgstr "7 espaços" #: spyder/plugins/editor.py:217 msgid "8 spaces" msgstr "8 espaços" #: spyder/plugins/editor.py:218 msgid "Tabulations" msgstr "Tabulações" #: spyder/plugins/editor.py:219 msgid "Tab stop width:" msgstr "Largura da tabulação:" #: spyder/plugins/editor.py:219 msgid "spaces" msgstr "espaços" #: spyder/plugins/editor.py:231 msgid "Tab always indent" msgstr "Sempre indentar com a tecla Tab" #: spyder/plugins/editor.py:233 msgid "" "If enabled, pressing Tab will always indent,\n" "even when the cursor is not at the beginning\n" "of a line (when this option is enabled, code\n" "completion may be triggered using the alternate\n" "shortcut: Ctrl+Space)" msgstr "" "Se ativada, pressionando Tab o código\n" "será indentado, mesmo se o cursor não estiver\n" "no inicio da linha (se essa opção for ativada a\n" "completação de código poderá ser usada\n" "pressionando Ctrl+Espaço)" #: spyder/plugins/editor.py:238 msgid "Intelligent backspace" msgstr "Tecla de retorno (\"backspace\") inteligente" #: spyder/plugins/editor.py:240 msgid "Automatically remove trailing spaces when saving files" msgstr "Remover automaticamente espaços em branco ao salvar arquivos" #: spyder/plugins/editor.py:244 msgid "Analysis" msgstr "Análise" #: spyder/plugins/editor.py:246 msgid "(Refer to the {} page)" msgstr "(Guia de estilo {})" #: spyder/plugins/editor.py:251 msgid "Real-time code analysis" msgstr "Análise de código em tempo real" #: spyder/plugins/editor.py:253 msgid "" "

If enabled, Python source code will be analyzed using pyflakes, lines " "containing errors or warnings will be highlighted.

Note: add " "analysis:ignore in a comment to ignore code analysis warnings.

" msgstr "" "

Se ativado, o código fonte será analisado utilizando o pyflakes, linhas " "contendo erros ou avisos serão destacadas.

Nota: add " "analysis:ignore em um comentário para ignorar avisos da analise de " "estilo.

" #: spyder/plugins/editor.py:261 msgid "Code analysis requires pyflakes %s+" msgstr "A análise de código requer pyflakes %s+" #: spyder/plugins/editor.py:263 msgid "Real-time code style analysis" msgstr "Análise do estilo de código em tempo real" #: spyder/plugins/editor.py:265 #, fuzzy msgid "" "

If enabled, Python source code will be analyzed using pycodestyle, lines " "that are not following PEP8 style guide will be highlighted.

Note: add analysis:ignore in a comment to ignore style analysis " "warnings.

" msgstr "" "

Se ativado, o código fonte será analisado utilizando o pep8, linhas que " "não seguem o guia de estilo PEP8 serão destacadas.

Nota: add " "analysis:ignore em um comentário para ignorar avisos da analise de " "estilo.

" #: spyder/plugins/editor.py:272 #, fuzzy msgid "" "Code annotations (TODO, FIXME, XXX, HINT, TIP, @todo, HACK, BUG, " "OPTIMIZE, !!!, ???)" msgstr "Anotações (TODO, FIXME, XXX, HINT, TIP, @todo)" #: spyder/plugins/editor.py:276 msgid "Perform analysis when saving file and every" msgstr "Fazer análise de código ao guardar arquivo e a cada" #: spyder/plugins/editor.py:280 msgid "Perform analysis only when saving file" msgstr "Fazer análise só quando o arquivo for salvo" #: spyder/plugins/editor.py:339 msgid "End-of-line characters" msgstr "Caracteres de fim de linha" #: spyder/plugins/editor.py:340 msgid "" "When opening a text file containing mixed end-of-line characters (this may " "raise syntax errors in the consoles on Windows platforms), Spyder may fix " "the file automatically." msgstr "" "Quando for aberto um arquivo de texto que contenha vários tipos de " "caracteres de fim de linha (o qual pode dar erros no Windows). O Spyder pode " "consertar o arquivo automaticamente." #: spyder/plugins/editor.py:346 msgid "Fix automatically and show warning message box" msgstr "Corrigir automaticamente e exibir uma mensagem de aviso" #: spyder/plugins/editor.py:357 spyder/plugins/ipythonconsole.py:573 #: spyder/plugins/variableexplorer.py:35 msgid "Display" msgstr "Visualização" #: spyder/plugins/editor.py:359 msgid "Code Introspection/Analysis" msgstr "Análise e introspecção de código" #: spyder/plugins/editor.py:362 msgid "Advanced settings" msgstr "Configurações avançadas" #: spyder/plugins/editor.py:644 msgid "&New file..." msgstr "&Novo arquivo..." #: spyder/plugins/editor.py:645 spyder/widgets/explorer.py:773 #: spyder/widgets/explorer.py:780 msgid "New file" msgstr "Novo arquivo" #: spyder/plugins/editor.py:654 msgid "O&pen last closed" msgstr "Ab&rir último arquivo fechado" #: spyder/plugins/editor.py:655 msgid "Open last closed" msgstr "Abrir último arquivo fechado" #: spyder/plugins/editor.py:661 msgid "&Open..." msgstr "&Abrir..." #: spyder/plugins/editor.py:662 spyder/plugins/editor.py:1870 #: spyder/plugins/editor.py:1876 msgid "Open file" msgstr "Abrir arquivo" #: spyder/plugins/editor.py:668 msgid "&Revert" msgstr "Resta&urar" #: spyder/plugins/editor.py:669 msgid "Revert file from disk" msgstr "Reverter arquivo do disco" #: spyder/plugins/editor.py:672 msgid "&Save" msgstr "&Salvar" #: spyder/plugins/editor.py:673 spyder/widgets/editor.py:1681 msgid "Save file" msgstr "Salvar arquivo" #: spyder/plugins/editor.py:679 msgid "Sav&e all" msgstr "Sal&var tudo" #: spyder/plugins/editor.py:680 msgid "Save all files" msgstr "Salvar todos os arquivos" #: spyder/plugins/editor.py:686 msgid "Save &as..." msgstr "Salvar c&omo..." #: spyder/plugins/editor.py:687 msgid "Save current file as..." msgstr "Salvar arquivo atual como..." #: spyder/plugins/editor.py:692 #, fuzzy msgid "Save copy as..." msgstr "Salvar c&omo..." #: spyder/plugins/editor.py:693 #, fuzzy msgid "Save copy of current file as..." msgstr "Salvar arquivo atual como..." #: spyder/plugins/editor.py:696 spyder/plugins/editor.py:697 msgid "Print preview..." msgstr "Pré-visualizar impressão..." #: spyder/plugins/editor.py:698 msgid "&Print..." msgstr "&Imprimir..." #: spyder/plugins/editor.py:699 msgid "Print current file..." msgstr "Imprimir o arquivo atual..." #: spyder/plugins/editor.py:702 msgid "&Close" msgstr "&Fechar" #: spyder/plugins/editor.py:703 msgid "Close current file" msgstr "Fechar arquivo atual" #: spyder/plugins/editor.py:706 msgid "C&lose all" msgstr "Fechar &tudo" #: spyder/plugins/editor.py:707 msgid "Close all opened files" msgstr "Fechar todos os arquivos abertos" #: spyder/plugins/editor.py:714 msgid "&Find text" msgstr "&Procurar" #: spyder/plugins/editor.py:720 msgid "Find &next" msgstr "P&rocurar próximo" #: spyder/plugins/editor.py:726 msgid "Find &previous" msgstr "Procurar &anterior" #: spyder/plugins/editor.py:732 msgid "&Replace text" msgstr "&Substituir" #: spyder/plugins/editor.py:741 msgid "Set/Clear breakpoint" msgstr "Adicionar ou limpar um ponto de interrupção" #: spyder/plugins/editor.py:748 msgid "Set/Edit conditional breakpoint" msgstr "Adicionar ou editar um ponto de interrupção condicional" #: spyder/plugins/editor.py:755 msgid "Clear breakpoints in all files" msgstr "Limpar pontos de interrupção em todos os arquivos" #: spyder/plugins/editor.py:757 msgid "Debug with winpdb" msgstr "Depurar com winpdb" #: spyder/plugins/editor.py:764 msgid "Debug file" msgstr "Depurar arquivo" #: spyder/plugins/editor.py:769 msgid "Step" msgstr "Executar linha" #: spyder/plugins/editor.py:770 msgid "Run current line" msgstr "Executar linha selecionada" #: spyder/plugins/editor.py:775 msgid "Continue" msgstr "Continuar" #: spyder/plugins/editor.py:777 msgid "Continue execution until next breakpoint" msgstr "Continuar a execução até o próximo ponto de interrupção" #: spyder/plugins/editor.py:782 msgid "Step Into" msgstr "Ingressar na função/método" #: spyder/plugins/editor.py:784 msgid "Step into function or method of current line" msgstr "Ingressar na função ou método da linha atual" #: spyder/plugins/editor.py:789 msgid "Step Return" msgstr "Sair da função/método" #: spyder/plugins/editor.py:791 msgid "Run until current function or method returns" msgstr "Executar até que a função ou método atual terminem" #: spyder/plugins/editor.py:796 spyder/widgets/findinfiles.py:281 #: spyder/widgets/ipythonconsole/client.py:357 msgid "Stop" msgstr "Parar" #: spyder/plugins/editor.py:797 msgid "Stop debugging" msgstr "Parar depuração" #: spyder/plugins/editor.py:804 msgid "Run file" msgstr "Executar arquivo" #: spyder/plugins/editor.py:809 #, fuzzy msgid "&Configuration per file..." msgstr "Arquivos de Configuração" #: spyder/plugins/editor.py:811 msgid "Run settings" msgstr "Executar configurações" #: spyder/plugins/editor.py:817 msgid "Re-run &last script" msgstr "Executar &novamente o último script" #: spyder/plugins/editor.py:819 msgid "Run again last file" msgstr "Executar novamente o mesmo arquivo" #: spyder/plugins/editor.py:825 spyder/widgets/sourcecode/codeeditor.py:2708 msgid "Run &selection or current line" msgstr "Executar &seleção ou linha atual" #: spyder/plugins/editor.py:828 msgid "Run selection or current line" msgstr "Executar seleção ou linha atual" #: spyder/plugins/editor.py:836 spyder/widgets/sourcecode/codeeditor.py:2696 msgid "Run cell" msgstr "Executar célula" #: spyder/plugins/editor.py:839 msgid "" "Run current cell (Ctrl+Enter)\n" "[Use #%% to create cells]" msgstr "" "Executar a célula atual (Ctrl+Enter)\n" "[Usar #%% para criar células]" #: spyder/plugins/editor.py:845 spyder/widgets/sourcecode/codeeditor.py:2700 msgid "Run cell and advance" msgstr "Executar célula e avançar" #: spyder/plugins/editor.py:848 msgid "Run current cell and go to the next one (Shift+Enter)" msgstr "Executar célula atual e ir para a próxima (Shift+Enter)" #: spyder/plugins/editor.py:854 spyder/widgets/sourcecode/codeeditor.py:2704 #, fuzzy msgid "Re-run last cell" msgstr "Executar &novamente o último script" #: spyder/plugins/editor.py:855 #, fuzzy msgid "Re run last cell " msgstr "Executar &novamente o último script" #: spyder/plugins/editor.py:865 msgid "Show todo list" msgstr "Mostrar lista de tarefas" #: spyder/plugins/editor.py:866 msgid "" "Show comments list (TODO/FIXME/XXX/HINT/TIP/@todo/HACK/BUG/OPTIMIZE/!!!/???)" msgstr "" #: spyder/plugins/editor.py:874 msgid "Show warning/error list" msgstr "Mostrar lista de erros e avisos" #: spyder/plugins/editor.py:875 msgid "Show code analysis warnings/errors" msgstr "Mostrar erros e avisos da análise de código" #: spyder/plugins/editor.py:881 msgid "Previous warning/error" msgstr "Aviso ou erro anterior" #: spyder/plugins/editor.py:882 msgid "Go to previous code analysis warning/error" msgstr "Ir para linha anterior de aviso ou erro" #: spyder/plugins/editor.py:885 msgid "Next warning/error" msgstr "Próximo aviso ou erro" #: spyder/plugins/editor.py:886 msgid "Go to next code analysis warning/error" msgstr "Ir para próxima linha de aviso ou erro" #: spyder/plugins/editor.py:890 msgid "Last edit location" msgstr "Última posição da edição" #: spyder/plugins/editor.py:891 msgid "Go to last edit location" msgstr "Ir para posição anterior da edição" #: spyder/plugins/editor.py:899 msgid "Previous cursor position" msgstr "Posição anterior do cursor" #: spyder/plugins/editor.py:900 msgid "Go to previous cursor position" msgstr "Ir a posição anterior do cursor" #: spyder/plugins/editor.py:908 msgid "Next cursor position" msgstr "Próxima posição do cursor" #: spyder/plugins/editor.py:909 msgid "Go to next cursor position" msgstr "Ir para a próxima posição do cursor" #: spyder/plugins/editor.py:919 spyder/widgets/sourcecode/codeeditor.py:2680 msgid "Comment" msgstr "Comentar" #: spyder/plugins/editor.py:919 spyder/widgets/sourcecode/codeeditor.py:2680 msgid "Uncomment" msgstr "Descomentar" #: spyder/plugins/editor.py:920 msgid "Comment current line or selection" msgstr "Comentar linha ou seleção atual" #: spyder/plugins/editor.py:924 msgid "Add &block comment" msgstr "Adicionar &bloco de comentário " #: spyder/plugins/editor.py:925 msgid "Add block comment around current line or selection" msgstr "Adicionar bloco de comentário ao redor da linha ou seleção atual" #: spyder/plugins/editor.py:931 msgid "R&emove block comment" msgstr "R&emover bloco de comentário" #: spyder/plugins/editor.py:932 msgid "Remove comment block around current line or selection" msgstr "Remover bloco de comentário ao redor da linha ou seleção atual" #: spyder/plugins/editor.py:943 msgid "Indent" msgstr "Indentar" #: spyder/plugins/editor.py:944 msgid "Indent current line or selection" msgstr "Indentar a linha ou seleção atual" #: spyder/plugins/editor.py:947 msgid "Unindent" msgstr "Desfazer indentação" #: spyder/plugins/editor.py:948 msgid "Unindent current line or selection" msgstr "Desfazer indentação da linha ou seleção atual" #: spyder/plugins/editor.py:952 msgid "Toggle Uppercase" msgstr "Alternar Maiúsculas" #: spyder/plugins/editor.py:953 msgid "Change to uppercase current line or selection" msgstr "Mudar linha ou seleção atual para maiúsculo" #: spyder/plugins/editor.py:959 msgid "Toggle Lowercase" msgstr "Alternar Minúsculas" #: spyder/plugins/editor.py:960 msgid "Change to lowercase current line or selection" msgstr "Mudar linha ou seleção atual para minúsculo" #: spyder/plugins/editor.py:967 msgid "Carriage return and line feed (Windows)" msgstr "Carriage return e salto de linha (Windows)" #: spyder/plugins/editor.py:970 msgid "Line feed (UNIX)" msgstr "Salto de linha (UNIX)" #: spyder/plugins/editor.py:973 msgid "Carriage return (Mac)" msgstr "Carriage return (Mac)" #: spyder/plugins/editor.py:979 msgid "Convert end-of-line characters" msgstr "Converter caracteres de fim de linha" #: spyder/plugins/editor.py:983 msgid "Remove trailing spaces" msgstr "Remover espaços em branco" #: spyder/plugins/editor.py:987 msgid "Fix indentation" msgstr "Consertar indentação" #: spyder/plugins/editor.py:988 msgid "Replace tab characters by space characters" msgstr "Substituir caracteres de tabulação por espaços" #: spyder/plugins/editor.py:991 msgid "Go to line..." msgstr "Ir para linha..." #: spyder/plugins/editor.py:999 msgid "Set console working directory" msgstr "Definir diretório de trabalho" #: spyder/plugins/editor.py:1001 msgid "" "Set current console (and file explorer) working directory to current script " "directory" msgstr "" "Definir o diretório de trabalho do console (e do explorador de arquivos) " "para o diretório do script atual." #: spyder/plugins/editor.py:1006 msgid "Maximum number of recent files..." msgstr "Número máximo de arquivos recentes..." #: spyder/plugins/editor.py:1009 msgid "Clear recent files list" msgstr "Limpar lista de arquivos recentes" #: spyder/plugins/editor.py:1009 spyder/plugins/projects.py:102 msgid "Clear this list" msgstr "Limpar esta lista" #: spyder/plugins/editor.py:1013 msgid "Open &recent" msgstr "Abrir &recente" #: spyder/plugins/editor.py:1678 msgid "Spyder Editor" msgstr "Spyder Editor" #: spyder/plugins/editor.py:1679 msgid "This is a temporary script file." msgstr "Este é um arquivo de script temporário." #: spyder/plugins/editor.py:1748 msgid "untitled" msgstr "Sem título" #: spyder/plugins/editor.py:1820 msgid "Maximum number of recent files" msgstr "Número máximo de arquivos recentes" #: spyder/plugins/editor.py:1966 msgid "Printing..." msgstr "Imprimindo..." #: spyder/plugins/explorer.py:54 msgid "File explorer" msgstr "Explorador de arquivos" #: spyder/plugins/findinfiles.py:119 spyder/widgets/findinfiles.py:829 msgid "Find in files" msgstr "Procurar em arquivos" #: spyder/plugins/findinfiles.py:143 msgid "&Find in files" msgstr "Procurar em arqui&vos" #: spyder/plugins/findinfiles.py:146 msgid "Search text in multiple files" msgstr "Buscar em vários arquivos" #: spyder/plugins/help.py:43 msgid "Show help for objects in the Editor and Consoles in a dedicated pane" msgstr "Mostra ajuda para objetos do Editor e Consoles em um painel dedicado" #: spyder/plugins/help.py:109 msgid "Automatic connections" msgstr "Conexões automáticas " #: spyder/plugins/help.py:110 msgid "" "This pane can automatically show an object's help information after a left " "parenthesis is written next to it. Below you can decide to which plugin you " "want to connect it to turn on this feature." msgstr "" "Este painel pode mostrar automaticamente a ajuda de um objeto depois de " "escrever um parênteses no mesmo. A seguir você pode decidir a que painel/" "componente você deseja conectar para ativar esta característica." #: spyder/plugins/help.py:122 msgid "" "This feature requires the Rope or Jedi libraries.\n" "It seems you don't have either installed." msgstr "" "Esta funcionalidade requer as bibliotecas Rope ou Jedi.\n" "Parece que você não possui elas instalada." #: spyder/plugins/help.py:125 msgid "IPython Console" msgstr "Console IPython" #: spyder/plugins/help.py:135 msgid "Additional features" msgstr "Funcionalidades adicionais" #: spyder/plugins/help.py:136 msgid "Render mathematical equations" msgstr "Renderizar equações matemáticas" #: spyder/plugins/help.py:142 msgid "This feature requires Sphinx 1.1 or superior." msgstr "Esta funcionalidade requer Sphinx 1.1 ou superior." #: spyder/plugins/help.py:143 msgid "Sphinx %s is currently installed." msgstr "Sphinx %s está instalado atualmente." #: spyder/plugins/help.py:304 msgid "No further documentation available" msgstr "Nenhuma documentação adicional disponível" #: spyder/plugins/help.py:342 msgid "No documentation available" msgstr "Nenhuma documentação disponível" #: spyder/plugins/help.py:373 msgid "Source" msgstr "Origem" #: spyder/plugins/help.py:380 spyder/plugins/runconfig.py:170 #: spyder/plugins/runconfig.py:486 spyder/widgets/ipythonconsole/client.py:291 msgid "Console" msgstr "Console" #: spyder/plugins/help.py:388 msgid "Object" msgstr "Objeto" #: spyder/plugins/help.py:402 msgid "Plain Text" msgstr "Texto Normal" #: spyder/plugins/help.py:406 msgid "Show Source" msgstr "Mostrar código fonte" #: spyder/plugins/help.py:410 msgid "Rich Text" msgstr "Texto Formatado" #: spyder/plugins/help.py:420 msgid "Automatic import" msgstr "Importar automaticamente" #: spyder/plugins/help.py:432 spyder/plugins/history.py:106 #: spyder/widgets/editor.py:720 spyder/widgets/explorer.py:1187 #: spyder/widgets/ipythonconsole/client.py:381 #: spyder/widgets/variableexplorer/namespacebrowser.py:148 msgid "Options" msgstr "Opções" #: spyder/plugins/help.py:687 msgid "" "Here you can get help of any object by pressing %s in front of it, either on " "the Editor or the Console.%sHelp can also be shown automatically after " "writing a left parenthesis next to an object. You can activate this behavior " "in %s." msgstr "" "Neste painel é possível obter a ajuda de qualquer objeto ao pressionar %s " "estando na frente do mesmo, tanto no Editor quanto no Console.%sEssa ajuda " "também pode ser mostrada automaticamente depois de escrever um parênteses " "junto a um objeto. Você pode ativar este comportamento em %s." #: spyder/plugins/help.py:693 msgid "Preferences > Help" msgstr "Preferências > Ajuda" #: spyder/plugins/help.py:700 msgid "Usage" msgstr "Uso" #: spyder/plugins/help.py:701 msgid "New to Spyder? Read our" msgstr "Novo no Spyder? Leia nosso" #: spyder/plugins/help.py:702 msgid "tutorial" msgstr "tutorial" #: spyder/plugins/help.py:709 msgid "" "Please consider installing Sphinx to get documentation rendered in rich text." msgstr "" "Por favor considere instalar o Sphinx para obter a documentação em texto " "formatado." #: spyder/plugins/help.py:878 msgid "Lock" msgstr "Trancar" #: spyder/plugins/help.py:878 msgid "Unlock" msgstr "Destrancar" #: spyder/plugins/help.py:922 msgid "" "The following error occured when calling Sphinx %s.
Incompatible " "Sphinx version or doc string decoding failed.

Error message:
%s" msgstr "" "Ocorreu o seguinte erro quando o Sphinx %s tentou ser utilizado. " "
Isso se deve a uma versão incompatível do Sphinx ou não foi possível ler " "a documentação solicitada.

Mensagem de erro:
%s" #: spyder/plugins/help.py:966 msgid "No source code available." msgstr "O código fonte não está disponível" #: spyder/plugins/history.py:39 msgid "Settings" msgstr "Configurações" #: spyder/plugins/history.py:41 msgid " entries" msgstr "entradas" #: spyder/plugins/history.py:41 msgid "History depth: " msgstr "Profundidade do histórico: " #: spyder/plugins/history.py:48 msgid "Scroll automatically to last entry" msgstr "Ir automaticamente para a última entrada" #: spyder/plugins/history.py:126 msgid "History log" msgstr "Log do histórico " #: spyder/plugins/history.py:153 msgid "History..." msgstr "Histórico..." #: spyder/plugins/history.py:155 msgid "Set history maximum entries" msgstr "Definir número máximo de entradas para armazenar" #: spyder/plugins/history.py:260 msgid "History" msgstr "Histórico" #: spyder/plugins/history.py:261 msgid "Maximum entries" msgstr "Número máximo de entradas" #: spyder/plugins/ipythonconsole.py:65 msgid "Symbolic mathematics in the IPython Console" msgstr "Matemática simbólica no console IPython" #: spyder/plugins/ipythonconsole.py:69 #, fuzzy msgid "Run Cython files in the IPython Console" msgstr "Matemática simbólica no console IPython" #: spyder/plugins/ipythonconsole.py:73 msgid "Integrate the IPython console" msgstr "Integração com o console IPython" #: spyder/plugins/ipythonconsole.py:77 msgid "IPython interactive python environment" msgstr "" #: spyder/plugins/ipythonconsole.py:128 msgid "" "The authenticity of host %s can't be established. Are you sure you " "want to continue connecting?" msgstr "" "A autenticidade do servidor %s não pode ser estabelecida. Você tem " "certeza que deseja continuar conectando?" #: spyder/plugins/ipythonconsole.py:140 msgid "The authenticity of the host can't be established" msgstr "A autenticidade do servidor não pode ser estabelecida" #: spyder/plugins/ipythonconsole.py:147 msgid "Tunnel '%s' failed to start" msgstr "O túnel '%s' falhou ao ser iniciado" #: spyder/plugins/ipythonconsole.py:152 msgid "Could not connect to remote host" msgstr "Não foi possível conectar ao servidor remoto" #: spyder/plugins/ipythonconsole.py:169 spyder/plugins/ipythonconsole.py:799 msgid "Connect to an existing kernel" msgstr "Conectar a um kernel já existente" #: spyder/plugins/ipythonconsole.py:171 msgid "" "Please enter the connection info of the kernel you want to connect to. For " "that you can either select its JSON connection file using the Browse button, or write directly its id, in case it's a local kernel (for " "example kernel-3764.json or just 3764)." msgstr "" "Por favor introduza a informação de conexão do kernel ao qual deseja se " "conectar. Para isso você pode selecionar seu arquivo de conexão JSON, usando " "o botão Selecionar, ou escrever diretamente seu id, em caso de que " "seja um kernel local (por exemplo, kernel-3764.json ou só 3764)." #: spyder/plugins/ipythonconsole.py:182 msgid "Connection info:" msgstr "Informação da conexão:" #: spyder/plugins/ipythonconsole.py:184 msgid "Path to connection file or kernel id" msgstr "Caminho para arquivo de conexão ou id do kernel" #: spyder/plugins/ipythonconsole.py:186 spyder/plugins/ipythonconsole.py:203 msgid "Browse" msgstr "Navegar" #: spyder/plugins/ipythonconsole.py:195 msgid "This is a remote kernel" msgstr "Este é um kernel remoto" #: spyder/plugins/ipythonconsole.py:199 msgid "username@hostname:port" msgstr "usuário@servidor:porta" #: spyder/plugins/ipythonconsole.py:202 msgid "Path to ssh key file" msgstr "Caminho do arquivo de chave ssh" #: spyder/plugins/ipythonconsole.py:211 msgid "Password or ssh key passphrase" msgstr "Senha" #: spyder/plugins/ipythonconsole.py:215 msgid "Host name" msgstr "Nome do host " #: spyder/plugins/ipythonconsole.py:216 msgid "Ssh key" msgstr "Chave ssh" #: spyder/plugins/ipythonconsole.py:217 msgid "Password" msgstr "Senha" #: spyder/plugins/ipythonconsole.py:246 msgid "Open connection file" msgstr "Abrir arquivo de conexão" #: spyder/plugins/ipythonconsole.py:251 msgid "Select ssh key" msgstr "Selecionar chave ssh" #: spyder/plugins/ipythonconsole.py:284 spyder/plugins/ipythonconsole.py:734 msgid "IPython console" msgstr "Console IPython" #: spyder/plugins/ipythonconsole.py:291 msgid "Display initial banner" msgstr "Mostrar o banner inicial" #: spyder/plugins/ipythonconsole.py:292 msgid "" "This option lets you hide the message shown at\n" "the top of the console when it's opened." msgstr "" "Esta opção permite ocultar a mensagem que \n" "aparece no topo do console quando se abre\n" "ele pela primeira vez." #: spyder/plugins/ipythonconsole.py:294 msgid "Use a pager to display additional text inside the console" msgstr "Usar um paginador para mostrar textos dentro do console" #: spyder/plugins/ipythonconsole.py:296 msgid "" "Useful if you don't want to fill the console with long help or completion " "texts.\n" "Note: Use the Q key to get out of the pager." msgstr "" "Isso é útil se não deseja preencher o console com grandes textos de ajuda.\n" "Nota: Use a tecla Q para sair do paginador." #: spyder/plugins/ipythonconsole.py:301 msgid "Ask for confirmation before closing" msgstr "Mostrar janela de confirmação antes de fechar" #: spyder/plugins/ipythonconsole.py:304 #, fuzzy msgid "Ask for confirmation before removing all user-defined variables" msgstr "Mostrar janela de confirmação antes de fechar" #: spyder/plugins/ipythonconsole.py:307 #, fuzzy msgid "" "This option lets you hide the warning message shown\n" "when resetting the namespace from Spyder." msgstr "" "Esta opção permite ocultar a mensagem que \n" "aparece no topo do console quando se abre\n" "ele pela primeira vez." #: spyder/plugins/ipythonconsole.py:309 #: spyder/widgets/ipythonconsole/client.py:320 msgid "Show elapsed time" msgstr "Mostrar tempo de execução" #: spyder/plugins/ipythonconsole.py:320 msgid "Completion Type" msgstr "Tipo de completação" #: spyder/plugins/ipythonconsole.py:321 msgid "Decide what type of completion to use" msgstr "Decidir qual tipo de completação usar" #: spyder/plugins/ipythonconsole.py:323 msgid "Graphical" msgstr "Gráfico" #: spyder/plugins/ipythonconsole.py:323 msgid "Plain" msgstr "Simples" #: spyder/plugins/ipythonconsole.py:323 msgid "Terminal" msgstr "Terminal" #: spyder/plugins/ipythonconsole.py:324 msgid "Completion:" msgstr "Completação:" #: spyder/plugins/ipythonconsole.py:334 msgid " lines" msgstr "linhas" #: spyder/plugins/ipythonconsole.py:334 msgid "Buffer: " msgstr "Buffer: " #: spyder/plugins/ipythonconsole.py:336 msgid "" "Set the maximum number of lines of text shown in the\n" "console before truncation. Specifying -1 disables it\n" "(not recommended!)" msgstr "" "Define o número máximo de linhas que serão mostradas\n" "no console em qualquer momento. Especificando -1 serão\n" "mostradas todas as linhas (não é recomendável!)" #: spyder/plugins/ipythonconsole.py:345 msgid "Support for graphics (Matplotlib)" msgstr "Suporte para criação de gráficos (Matplotlib)" #: spyder/plugins/ipythonconsole.py:346 msgid "Activate support" msgstr "Ativar suporte" #: spyder/plugins/ipythonconsole.py:347 msgid "Automatically load Pylab and NumPy modules" msgstr "Carregar automaticamente os módulos do Pylab e do NumPy" #: spyder/plugins/ipythonconsole.py:350 msgid "" "This lets you load graphics support without importing \n" "the commands to do plots. Useful to work with other\n" "plotting libraries different to Matplotlib or to develop \n" "GUIs with Spyder." msgstr "" "Isso lhe permite carregar o suporte gráfico sem importar\n" "os comandos para criar imagens. É útil para trabalhar com\n" "outras bibliotecas gráficas diferentes da Matplotlib ou para\n" "desenvolver interfaces gráficas com o Spyder." #: spyder/plugins/ipythonconsole.py:365 msgid "Inline" msgstr "Em linha" #: spyder/plugins/ipythonconsole.py:366 msgid "Automatic" msgstr "Automático" #: spyder/plugins/ipythonconsole.py:367 msgid "Graphics backend" msgstr "Saída gráfica" #: spyder/plugins/ipythonconsole.py:368 msgid "" "Decide how graphics are going to be displayed in the console. If unsure, " "please select %s to put graphics inside the console or %s to " "interact with them (through zooming and panning) in a separate window." msgstr "" "Decidir como serão mostrados os gráficos no console. Se está inseguro, por " "favor selecione %s para colocar os gráficos no console ou %s " "para interagir com eles (através de zoom) em uma janela separada." #: spyder/plugins/ipythonconsole.py:388 msgid "Backend:" msgstr "Saída:" #: spyder/plugins/ipythonconsole.py:390 msgid "This option will be applied the next time a console is opened." msgstr "Esta opção será aplicada na próxima vez que um console for aberto." #: spyder/plugins/ipythonconsole.py:401 msgid "Inline backend" msgstr "Saída em linha" #: spyder/plugins/ipythonconsole.py:402 msgid "Decide how to render the figures created by this backend" msgstr "" "Decida como renderizar as imagens criados por este tipo de saída gráfica" #: spyder/plugins/ipythonconsole.py:406 msgid "Format:" msgstr "Formato:" #: spyder/plugins/ipythonconsole.py:409 msgid "Resolution:" msgstr "Resolução:" #: spyder/plugins/ipythonconsole.py:409 msgid "dpi" msgstr "dpi" #: spyder/plugins/ipythonconsole.py:411 msgid "Only used when the format is PNG. Default is 72" msgstr "Só se usa quando o formato for PNG. O padrão é 72" #: spyder/plugins/ipythonconsole.py:414 msgid "Width:" msgstr "Largura:" #: spyder/plugins/ipythonconsole.py:414 spyder/plugins/ipythonconsole.py:418 msgid "inches" msgstr "polegadas" #: spyder/plugins/ipythonconsole.py:416 msgid "Default is 6" msgstr "O padrão é 6" #: spyder/plugins/ipythonconsole.py:418 msgid "Height:" msgstr "Altura:" #: spyder/plugins/ipythonconsole.py:420 msgid "Default is 4" msgstr "O padrão é 4" #: spyder/plugins/ipythonconsole.py:447 msgid "" "You can run several lines of code when a console is started. Please " "introduce each one separated by commas, for example:
import os, import " "sys" msgstr "" "Você pode executar várias linhas de código ao abrir um terminal. Por favor " "introduza cada uma separada por vírgulas, por exemplo:
import os, " "import sys" #: spyder/plugins/ipythonconsole.py:453 msgid "Lines:" msgstr "Linhas:" #: spyder/plugins/ipythonconsole.py:462 msgid "Run a file" msgstr "Executar arquivo" #: spyder/plugins/ipythonconsole.py:463 msgid "" "You can also run a whole file at startup instead of just some lines (This is " "similar to have a PYTHONSTARTUP file)." msgstr "" "Você também pode executar um arquivo por inteiro ao inicializar, em vez de " "poucas linhas (Isso é similar a ter um arquivo PYTHONSTARTUP)." #: spyder/plugins/ipythonconsole.py:467 msgid "Use the following file:" msgstr "Use o seguinte arquivo:" #: spyder/plugins/ipythonconsole.py:481 msgid "Greedy completion" msgstr "Completação gulosa" #: spyder/plugins/ipythonconsole.py:482 msgid "" "Enable Tab completion on elements of lists, results of function " "calls, etc, without assigning them to a variable.
For example, you " "can get completions on things like li[0].<Tab> or ins." "meth().<Tab>" msgstr "" "Habilita o completador usando a tecla Tab em elementos de listas, " "resultados de chamadas de funções, etc, sem atribuí-los a uma " "variável.
Dessa forma pode-se obter sugestões de completação em coisas " "como li[0].<Tab> ou ins.meth().<Tab>" #: spyder/plugins/ipythonconsole.py:490 msgid "Use the greedy completer" msgstr "Usar o completador guloso" #: spyder/plugins/ipythonconsole.py:501 msgid "Autocall" msgstr "Autocall" #: spyder/plugins/ipythonconsole.py:502 msgid "" "Autocall makes IPython automatically call any callable object even if you " "didn't type explicit parentheses.
For example, if you type str 43 " "it becomes str(43) automatically." msgstr "" "Esta opção faz com que o Python chame automaticamente qualquer objeto mesmo " "se você não tenha digitado os parenteses ao seu redor.
Por exemplo, ao " "escrever str 43, irá virar automaticamente str(43)." #: spyder/plugins/ipythonconsole.py:509 msgid "Smart" msgstr "Inteligente" #: spyder/plugins/ipythonconsole.py:510 msgid "Full" msgstr "Total" #: spyder/plugins/ipythonconsole.py:511 msgid "Off" msgstr "Desativado" #: spyder/plugins/ipythonconsole.py:513 msgid "Autocall: " msgstr "Autocall: " #: spyder/plugins/ipythonconsole.py:514 msgid "" "On %s mode, Autocall is not applied if there are no arguments after " "the callable. On %s mode, all callable objects are automatically " "called (even if no arguments are present)." msgstr "" "No modo %s, Auto-chamada não é aplicada se não houver argumentos " "depois do objeto clamável. No modo %s, todos os objetos chamáveis são " "chamados automaticamente (mesmo se não houver argumentos presentes)." #: spyder/plugins/ipythonconsole.py:526 msgid "Symbolic Mathematics" msgstr "Matemática simbólica" #: spyder/plugins/ipythonconsole.py:527 msgid "" "Perfom symbolic operations in the console (e.g. integrals, derivatives, " "vector calculus, etc) and get the outputs in a beautifully printed style (it " "requires the Sympy module)." msgstr "" "Realiza operações simbólicas no console (integrais, derivadas, cálculo " "vetoria e etcl) tendo os resultados em um belo estilo impresso (requer o " "módulo Sympy)." #: spyder/plugins/ipythonconsole.py:532 msgid "Use symbolic math" msgstr "Usar matemática simbólica" #: spyder/plugins/ipythonconsole.py:533 msgid "" "This option loads the Sympy library to work with.
Please refer to its " "documentation to learn how to use it." msgstr "" "Esta opção carrega a biblioteca Sympy para trabalhar
com ela. Por favor " "leia sua documentação para aprender a usá-la. " #: spyder/plugins/ipythonconsole.py:543 msgid "Prompts" msgstr "Prompts" #: spyder/plugins/ipythonconsole.py:544 msgid "Modify how Input and Output prompts are shown in the console." msgstr "Modifique como são mostradas as saídas e entradas no console." #: spyder/plugins/ipythonconsole.py:547 msgid "Input prompt:" msgstr "Prompt de entrada:" #: spyder/plugins/ipythonconsole.py:549 msgid "" "Default is
In [<span class=\"in-prompt-number\">%i</span>]:" msgstr "" "O Padrão é
In [<span class=\"in-prompt-number\">%i</span>]:" #: spyder/plugins/ipythonconsole.py:553 msgid "Output prompt:" msgstr "Prompt de saída:" #: spyder/plugins/ipythonconsole.py:555 msgid "" "Default is
Out[<span class=\"out-prompt-number\">%i</span>]:" msgstr "" "O Padrão é
Out[<span class=\"out-prompt-number\">%i</span>]: " #: spyder/plugins/ipythonconsole.py:575 msgid "Graphics" msgstr "Gráficos" #: spyder/plugins/ipythonconsole.py:577 msgid "Startup" msgstr "Inicialização" #: spyder/plugins/ipythonconsole.py:604 msgid "" "The directory {} is not writable and it is required to create IPython " "consoles. Please make it writable." msgstr "" "O diretório {} não está em modo de escrita e isto é necessário para criar " "consoles IPython. Por favor deixe-o em modo de escrita." #: spyder/plugins/ipythonconsole.py:784 msgid "Open an &IPython console" msgstr "Abrir um console &IPython " #: spyder/plugins/ipythonconsole.py:791 msgid "Restart kernel" msgstr "Reiniciar kernel" #: spyder/plugins/ipythonconsole.py:800 msgid "Open a new IPython console connected to an existing kernel" msgstr "Abrir um novo console do IPython conectado a um kernel existente." #: spyder/plugins/ipythonconsole.py:803 #, fuzzy msgid "Rename tab" msgstr "Renomear" #: spyder/plugins/ipythonconsole.py:928 msgid "" "No IPython console is currently available to run %s.

Please " "open a new one and try again." msgstr "" "Não existe um console IPython para ser executado %s.

Por favor " "abra um novo e tente novamente." #: spyder/plugins/ipythonconsole.py:1018 #, fuzzy msgid "" "Your Python environment or installation doesn't have the ipykernel " "and cloudpickle modules installed on it. Without these modules is " "not possible for Spyder to create a console for you.

You can install " "them by running in a system terminal:

pip install ipykernel " "cloudpickle

or

conda install ipykernel cloudpickle" msgstr "" "Sua instalação do Python não possui o módulo ipykernel instalado. " "Sem esse módulo não é possível que o Spyder crie um console.

Você " "pode instalar o ipykernel executando no terminal tal comando:" "

pip install ipykernel

ou

conda install " "ipykernel" #: spyder/plugins/ipythonconsole.py:1295 msgid "Do you want to close this console?" msgstr "Tem certeza que deseja fechar esse console?" #: spyder/plugins/ipythonconsole.py:1301 msgid "" "Do you want to close all other consoles connected to the same kernel as this " "one?" msgstr "" "Você deseja fechar todos os outros consoles conectados ao mesmo kernel como " "esse?" #: spyder/plugins/ipythonconsole.py:1366 msgid "" "It was not possible to restart the IPython console when switching to this " "project. The error was {0}" msgstr "" "Não foi possível reiniciar o console IPython enquanto trocava-se de projeto. " "O erro foi {0}" #: spyder/plugins/ipythonconsole.py:1467 msgid "" "This error was most probably caused by installing Spyder in a directory with " "non-ascii characters (i.e. characters with tildes, apostrophes or non-latin " "symbols).

To fix it, please reinstall Spyder in a different " "location." msgstr "" #: spyder/plugins/ipythonconsole.py:1659 msgid "IPython" msgstr "IPython" #: spyder/plugins/ipythonconsole.py:1660 msgid "Unable to connect to %s" msgstr "Não foi possível conectar a %s" #: spyder/plugins/ipythonconsole.py:1730 msgid "Connection error" msgstr "Erro de conexão" #: spyder/plugins/ipythonconsole.py:1731 msgid "" "Could not open ssh tunnel. The error was:\n" "\n" msgstr "" "Não foi possível criar um túnel ssh. O erro foi:\n" "\n" #: spyder/plugins/layoutdialog.py:177 msgid "Move Up" msgstr "Mover para Cima" #: spyder/plugins/layoutdialog.py:178 msgid "Move Down" msgstr "Mover para baixo" #: spyder/plugins/layoutdialog.py:179 msgid "Delete Layout" msgstr "Deletar Layout" #: spyder/plugins/layoutdialog.py:183 msgid "Layout Display and Order" msgstr "Ordem dos layouts" #: spyder/plugins/maininterpreter.py:31 spyder/plugins/maininterpreter.py:66 msgid "Python interpreter" msgstr "Interpretador Python" #: spyder/plugins/maininterpreter.py:68 msgid "Select the Python interpreter for all Spyder consoles" msgstr "Selecione o interpretador Python para todos os consoles do Spyder" #: spyder/plugins/maininterpreter.py:71 msgid "Default (i.e. the same as Spyder's)" msgstr "Padrão (o mesmo do Spyder)" #: spyder/plugins/maininterpreter.py:74 msgid "Use the following Python interpreter:" msgstr "Usar o seguinte interpretador:" #: spyder/plugins/maininterpreter.py:77 msgid "Executables" msgstr "Executáveis " #: spyder/plugins/maininterpreter.py:94 msgid "User Module Reloader (UMR)" msgstr "Recarregador de Módulos do Usuário (RMU)" #: spyder/plugins/maininterpreter.py:95 msgid "" "UMR forces Python to reload modules which were imported when executing a " "file in a Python or IPython console with the runfile function." msgstr "" "O RMU força o Python a recarregar os módulos que foram importados durante a " "execução de um arquivo no console com a função runfile." #: spyder/plugins/maininterpreter.py:100 msgid "Enable UMR" msgstr "Ativar RMU" #: spyder/plugins/maininterpreter.py:101 msgid "" "This option will enable the User Module Reloader (UMR) in Python/IPython " "consoles. UMR forces Python to reload deeply modules during import when " "running a Python script using the Spyder's builtin function runfile." "

1. UMR may require to restart the console in which it will be " "called (otherwise only newly imported modules will be reloaded when " "executing files).

2. If errors occur when re-running a PyQt-" "based program, please check that the Qt objects are properly destroyed (e.g. " "you may have to use the attribute Qt.WA_DeleteOnClose on your main " "window, using the setAttribute method)" msgstr "" "Esta opção ativará o Recarregador de Módulos do Usuário (RMU) nos consoles " "Python/IPython. O RMU força o Python a recarregar profundamente os módulos " "que foram importados ao executar um arquivo do Python, usando a função " "incorporada do Spyder chamada runfile.

1. O RMU pode " "necessitar que se reinicie o console em o qual será utilizado (de outra " "forma, só os módulos que foram importados em último lugar serão recarregados " "ao executar um arquivo).

2. Se ocorrer algum erro ao re-" "executar um programa baseado no PyQt, por favor verifique se os objetos do " "Qt foram destruídos apropriadamente (por exemplo, você pode ter que utilizar " "o atributo Qt.WA_DeleteOnClose em sua janela principal, utilizando o " "método setAttribute)" #: spyder/plugins/maininterpreter.py:117 msgid "Show reloaded modules list" msgstr "Mostrar lista de módulos que foram recarregados" #: spyder/plugins/maininterpreter.py:118 msgid "Please note that these changes will be applied only to new consoles" msgstr "" "Por favor tenha em nota que as mudanças só serão aplicadas em novos consoles" #: spyder/plugins/maininterpreter.py:122 msgid "Set UMR excluded (not reloaded) modules" msgstr "Definir lista de módulos excluídos pelo RMU" #: spyder/plugins/maininterpreter.py:150 msgid "" "You selected an invalid Python interpreter for the console so the previous " "interpreter will stay. Please make sure to select a valid one." msgstr "" "Você selecionou um interpretador inválido do Python para o console, o " "interpretador anterior irá continuar. Por favor tenha certeza se você " "selecionou um válido." #: spyder/plugins/maininterpreter.py:175 msgid "" "You selected a Python %d interpreter for the console but Spyder is " "running on Python %d!.

Although this is possible, we recommend " "you to install and run Spyder directly with your selected interpreter, to " "avoid seeing false warnings and errors due to the incompatible syntax " "between these two Python versions." msgstr "" "Você selecionou um interpretador Python %d para o console, mas o " "Spyder está sendo executado em Python %d!.

Embora isso seja " "possível, nós recomendamos instalar e executar o Spyder diretamente com o " "interpretador selecionado, para evitar ver falsos erros e avisos no Editor " "devido a sintaxe incompatível entre estas duas versões do Python." #: spyder/plugins/maininterpreter.py:186 spyder/plugins/maininterpreter.py:213 #: spyder/plugins/maininterpreter.py:217 msgid "UMR" msgstr "RMU" #: spyder/plugins/maininterpreter.py:187 msgid "Set the list of excluded modules as this: numpy, scipy" msgstr "Defina a lista de módulos excluídos desta forma: numpy, scipy" #: spyder/plugins/maininterpreter.py:204 msgid "" "You are working with Python 2, this means that you can not import a module " "that contains non-ascii characters." msgstr "" "Você está utilizando Python 2, não é possível importar um módulo que " "contenha não contenha caracteres ascii." #: spyder/plugins/maininterpreter.py:214 msgid "" "The following modules are not installed on your machine:\n" "%s" msgstr "" "Os seguintes módulos não estão instalados no seu computador:\n" "%s" #: spyder/plugins/maininterpreter.py:218 msgid "" "Please note that these changes will be applied only to new Python/IPython " "consoles" msgstr "" "Por favor, note que estas mudanças só serão aplicadas apenas aos novos " "consoles do Python/IPython" #: spyder/plugins/onlinehelp.py:70 msgid "Online help" msgstr "Ajuda online" #: spyder/plugins/outlineexplorer.py:49 spyder/widgets/editortools.py:195 msgid "Outline" msgstr "Explorador de código" #: spyder/plugins/projects.py:78 spyder/widgets/projects/explorer.py:112 #: spyder/widgets/projects/explorer.py:126 msgid "Project explorer" msgstr "Explorador de projetos" #: spyder/plugins/projects.py:90 msgid "New Project..." msgstr "Novo Projeto..." #: spyder/plugins/projects.py:93 msgid "Open Project..." msgstr "Abrir Projeto..." #: spyder/plugins/projects.py:96 msgid "Close Project" msgstr "Fechar Projeto" #: spyder/plugins/projects.py:99 msgid "Delete Project" msgstr "Deletar Projeto" #: spyder/plugins/projects.py:105 msgid "Project Preferences" msgstr "Preferências do Projeto" #: spyder/plugins/projects.py:107 msgid "Recent Projects" msgstr "Projetos Recentes" #: spyder/plugins/projects.py:244 msgid "Open project" msgstr "Abrir projeto" #: spyder/plugins/projects.py:249 msgid "%s is not a Spyder project!" msgstr "%s não é um projeto do Spyder!" #: spyder/plugins/runconfig.py:29 #, fuzzy msgid "Execute in current console" msgstr "Executar no console atual do Python ou IPython" #: spyder/plugins/runconfig.py:30 #, fuzzy msgid "Execute in a dedicated console" msgstr "Executar em um novo console dedicado do Python" #: spyder/plugins/runconfig.py:31 #, fuzzy msgid "Execute in an external system terminal" msgstr "Executar em um terminal externo do Sistema" #: spyder/plugins/runconfig.py:42 msgid "Always show %s on a first file run" msgstr "Sempre mostrar %s na primeira execução" #: spyder/plugins/runconfig.py:45 #, fuzzy msgid "Remove all variables before execution" msgstr "Limpar todas variáveis antes da execução (Consoles IPython)" #: spyder/plugins/runconfig.py:46 #, fuzzy msgid "Directly enter debugging when errors appear" msgstr "Entrar no modo de depuração quando erros aparecerem durante a execução" #: spyder/plugins/runconfig.py:47 msgid "Interact with the Python console after execution" msgstr "Interagir com o console depois da execução" #: spyder/plugins/runconfig.py:49 msgid "The directory of the file being executed" msgstr "" #: spyder/plugins/runconfig.py:50 spyder/plugins/workingdirectory.py:56 #, fuzzy msgid "The current working directory" msgstr "Definir diretório de trabalho" #: spyder/plugins/runconfig.py:51 #, fuzzy msgid "The following directory:" msgstr "O seguinte diretório:" #: spyder/plugins/runconfig.py:184 spyder/plugins/runconfig.py:504 msgid "General settings" msgstr "Configurações gerais" #: spyder/plugins/runconfig.py:194 spyder/plugins/runconfig.py:236 msgid "Command line options:" msgstr "Opções de linha de comando: " #: spyder/plugins/runconfig.py:202 spyder/plugins/runconfig.py:514 #, fuzzy msgid "Working Directory settings" msgstr "Diretório de trabalho" #: spyder/plugins/runconfig.py:226 spyder/plugins/runconfig.py:548 #, fuzzy msgid "External system terminal" msgstr "Executar em um terminal externo do Sistema" #: spyder/plugins/runconfig.py:241 msgid "-u is added to the other options you set here" msgstr "A opção -u foi adicionada a essas opções" #: spyder/plugins/runconfig.py:250 msgid "this dialog" msgstr "este dialogo " #: spyder/plugins/runconfig.py:315 msgid "Run configuration" msgstr "Opções de execução" #: spyder/plugins/runconfig.py:316 msgid "The following working directory is not valid:
%s" msgstr "O seguinte diretório de trabalho não é válido:
%s" #: spyder/plugins/runconfig.py:394 msgid "Run settings for %s" msgstr "Ajustar configuração para %s" #: spyder/plugins/runconfig.py:426 msgid "Select a run configuration:" msgstr "Selecionar um arquivo de execução:" #: spyder/plugins/runconfig.py:455 #, fuzzy msgid "Run configuration per file" msgstr "Opções de execução" #: spyder/plugins/runconfig.py:480 #, fuzzy msgid "" "The following are the default options for running files.These options may be " "overriden using the Configuration per file entry of the Run " "menu." msgstr "" "As seguintes %s são padrões. Estas opções podem ser modificadas " "usando o diálogo %s (ver o menu %s)" #: spyder/plugins/runconfig.py:516 msgid "Default working directory is:" msgstr "O diretório de trabalho padrão é:" #: spyder/plugins/runconfig.py:556 msgid "Run Settings dialog" msgstr "Configurações de execução" #: spyder/plugins/shortcuts.py:65 msgid "Currently used to delete lines on editor" msgstr "" #: spyder/plugins/shortcuts.py:69 msgid "We cannot support this shortcut on Windows" msgstr "" #: spyder/plugins/shortcuts.py:72 msgid "Shortcuts that use Shift and another key are unsupported" msgstr "" #: spyder/plugins/shortcuts.py:149 msgid "" "Press the new shortcut and select 'Ok': \n" "(Press 'Tab' once to switch focus between the shortcut entry \n" "and the buttons below it)" msgstr "" "Pressione o novo atalho e selecione 'Ok': \n" "(Pressione 'Tab' uma vez para mudar o foco entre a entrada do atalho \n" "e os botões abaixo dele)" #: spyder/plugins/shortcuts.py:152 msgid "Current shortcut:" msgstr "Atalho atual:" #: spyder/plugins/shortcuts.py:154 msgid "New shortcut:" msgstr "Novo atalho:" #: spyder/plugins/shortcuts.py:167 msgid "Shortcut: {0}" msgstr "Atalho: {0}" #: spyder/plugins/shortcuts.py:288 msgid "Please introduce a different shortcut" msgstr "Por favor escolha um atalho diferente" #: spyder/plugins/shortcuts.py:325 #, fuzzy msgid "The new shortcut conflicts with:" msgstr "O novo atalho conflita com:" #: spyder/plugins/shortcuts.py:334 spyder/plugins/shortcuts.py:343 msgid "Forbidden key sequence!" msgstr "" #: spyder/plugins/shortcuts.py:354 msgid "" "A compound sequence can have {break} a maximum of 4 subsequences.{break}" msgstr "" "Uma sequência composta pode ter {break} um máximo de 4 subsequências.{break}" #: spyder/plugins/shortcuts.py:359 msgid "Invalid key entered" msgstr "Chave inválida inserida" #: spyder/plugins/shortcuts.py:567 msgid "Context" msgstr "Contexto" #: spyder/plugins/shortcuts.py:569 #: spyder/widgets/variableexplorer/collectionseditor.py:128 msgid "Name" msgstr "Nome" #: spyder/plugins/shortcuts.py:571 msgid "Shortcut" msgstr "Atalho" #: spyder/plugins/shortcuts.py:573 msgid "Score" msgstr "Valor" #: spyder/plugins/shortcuts.py:734 msgid "Conflicts" msgstr "Conflitos" #: spyder/plugins/shortcuts.py:735 msgid "The following conflicts have been detected:" msgstr "Os seguintes conflitos foram detectados:" #: spyder/plugins/shortcuts.py:820 msgid "Keyboard shortcuts" msgstr "Teclas de atalho" #: spyder/plugins/shortcuts.py:828 msgid "Search: " msgstr "Procurar: " #: spyder/plugins/shortcuts.py:829 msgid "Reset to default values" msgstr "Restaurar os valores padrões." #: spyder/plugins/shortcuts.py:859 #, fuzzy msgid "Shortcuts reset" msgstr "Atalho" #: spyder/plugins/shortcuts.py:860 #, fuzzy msgid "Do you want to reset to default values?" msgstr "Restaurar os valores padrões." #: spyder/plugins/variableexplorer.py:25 msgid "Filter" msgstr "Filtro" #: spyder/plugins/variableexplorer.py:27 #: spyder/widgets/variableexplorer/namespacebrowser.py:200 msgid "Exclude private references" msgstr "Excluir variáveis privadas" #: spyder/plugins/variableexplorer.py:28 #: spyder/widgets/variableexplorer/namespacebrowser.py:215 msgid "Exclude capitalized references" msgstr "Excluir variáveis que começam em maiúsculas" #: spyder/plugins/variableexplorer.py:29 #: spyder/widgets/variableexplorer/namespacebrowser.py:208 msgid "Exclude all-uppercase references" msgstr "Excluir variáveis em maiúscula " #: spyder/plugins/variableexplorer.py:30 #: spyder/widgets/variableexplorer/namespacebrowser.py:223 msgid "Exclude unsupported data types" msgstr "Excluir tipos de dados não suportados" #: spyder/plugins/variableexplorer.py:36 #: spyder/widgets/variableexplorer/collectionseditor.py:699 msgid "Show arrays min/max" msgstr "Mostrar o minimo e máximo de matrizes" #: spyder/plugins/variableexplorer.py:178 msgid "Variable explorer" msgstr "Explorador de variáveis" #: spyder/plugins/workingdirectory.py:39 msgid "" "The current working directory is the working directory for IPython " "consoles and the current directory for the File Explorer." msgstr "" #: spyder/plugins/workingdirectory.py:44 #, fuzzy msgid "Console directory" msgstr "Novo diretório" #: spyder/plugins/workingdirectory.py:45 #, fuzzy msgid "The working directory for new consoles is:" msgstr "O diretório de trabalho padrão é:" #: spyder/plugins/workingdirectory.py:49 msgid "" "The current project directory or user home directory (if no project is " "active)" msgstr "" #: spyder/plugins/workingdirectory.py:62 msgid "the following directory:" msgstr "O seguinte diretório:" #: spyder/plugins/workingdirectory.py:64 #, fuzzy msgid "The directory when a new console is open will be the specified path" msgstr "Ao iniciar o diretório de trabalho será o seguinte" #: spyder/plugins/workingdirectory.py:124 msgid "Back" msgstr "Anterior" #: spyder/plugins/workingdirectory.py:132 spyder/widgets/explorer.py:1181 #: spyder/widgets/variableexplorer/importwizard.py:539 msgid "Next" msgstr "Próximo" #: spyder/plugins/workingdirectory.py:143 msgid "" "This is the working directory for newly\n" "opened consoles (Python/IPython consoles and\n" "terminals), for the file explorer, for the\n" "find in files plugin and for new files\n" "created in the editor" msgstr "" "Este é o diretório de trabalho para os\n" "consoles recém abertos \n" "(do IPython/Python e terminais), \n" "para o Explorador de arquivos,\n" "Buscar em arquivos e para os novos\n" "arquivos criados no Editor" #: spyder/plugins/workingdirectory.py:168 msgid "Browse a working directory" msgstr "Selecionar um diretório de trabalho" #: spyder/plugins/workingdirectory.py:175 msgid "Change to parent directory" msgstr "Mudar para diretório superior" #: spyder/plugins/workingdirectory.py:182 spyder/widgets/findinfiles.py:322 #, fuzzy msgid "Current working directory" msgstr "Definir diretório de trabalho" #: spyder/utils/codeanalysis.py:92 msgid "Real-time code analysis on the Editor" msgstr "Análise de código em tempo real no editor" #: spyder/utils/codeanalysis.py:96 msgid "Real-time code style analysis on the Editor" msgstr "Análise de estilo em tempo real no editor." #: spyder/utils/environ.py:46 msgid "Environment variables" msgstr "Variáveis de ambiente" #: spyder/utils/environ.py:96 msgid "" "Module pywin32 was not found.
Please restart this Windows " "session (not the computer) for changes to take effect." msgstr "" "O módulo pywin32 não foi encontrado.
Por favor reinicie esta " "sessão do Windows (não do computador) para que as mudanças tenham " "efeito." #: spyder/utils/environ.py:109 msgid "" "If you accept changes, this will modify the current user environment " "variables directly in Windows registry. Use it with precautions, at " "your own risks.

Note that for changes to take effect, you will need " "to restart the parent process of this application (simply restart Spyder if " "you have executed it from a Windows shortcut, otherwise restart any " "application from which you may have executed it, like Python(x,y) Home for example)" msgstr "" "Se você aceitar, as variáveis de ambiente atuais serão modificadas no " "registro do Windows. Use com precaução, em seu próprio risco." "

Tenha em mente que para que as mudanças tenham efeito, você deverá " "reiniciar o processo pai deste aplicativo (simplesmente reinicie o Spyder se " "você executou ele de um atalho, caso contrário reinicie qualquer aplicativo " "pelo qual você você executou ele, como o Python(x,y) Home)" #: spyder/utils/help/sphinxify.py:217 spyder/utils/help/sphinxify.py:227 msgid "" "It was not possible to generate rich text help for this object.
Please " "see it in plain text." msgstr "" "Não foi possível gerar ajuda em texto formatado para este objeto.
Por " "favor veja em texto normal." #: spyder/utils/introspection/manager.py:34 #: spyder/utils/introspection/manager.py:39 msgid "Editor's code completion, go-to-definition and help" msgstr "Completador de código e ajuda no Editor" #: spyder/utils/iofuncs.py:408 msgid "Supported files" msgstr "Arquivos suportados" #: spyder/utils/iofuncs.py:410 msgid "All files (*.*)" msgstr "Todos os arquivos (*.*)" #: spyder/utils/iofuncs.py:420 msgid "Spyder data files" msgstr "Arquivos data do Spyder" #: spyder/utils/iofuncs.py:422 #: spyder/widgets/variableexplorer/collectionseditor.py:1058 msgid "NumPy arrays" msgstr "Matrizes do NumPy" #: spyder/utils/iofuncs.py:423 msgid "NumPy zip arrays" msgstr "Matrizes comprimidas do NumPy" #: spyder/utils/iofuncs.py:424 msgid "Matlab files" msgstr "Arquivos do Matlab" #: spyder/utils/iofuncs.py:425 msgid "CSV text files" msgstr "Arquivos de texto CSV" #: spyder/utils/iofuncs.py:427 msgid "JPEG images" msgstr "Imagens JPEG" #: spyder/utils/iofuncs.py:428 msgid "PNG images" msgstr "Imagens PNG" #: spyder/utils/iofuncs.py:429 msgid "GIF images" msgstr "Imagens GIF" #: spyder/utils/iofuncs.py:430 msgid "TIFF images" msgstr "Imagens TIFF" #: spyder/utils/iofuncs.py:431 spyder/utils/iofuncs.py:432 msgid "Pickle files" msgstr "Arquivos Pickle" #: spyder/utils/iofuncs.py:433 msgid "JSON files" msgstr "Arquivos JSON" #: spyder/utils/iofuncs.py:452 spyder/utils/iofuncs.py:459 msgid "Unsupported file type '%s'" msgstr "Tipo de arquivo não suportado '%s'" #: spyder/utils/programs.py:287 msgid "It was not possible to run this file in an external terminal" msgstr "Não foi possível executar este arquivo em um terminal externo" #: spyder/utils/syntaxhighlighters.py:34 msgid "Syntax highlighting for Matlab, Julia and other file types" msgstr "Sintaxe colorida para arquivos do tipo Matlab, Julia e outros tipos" #: spyder/utils/syntaxhighlighters.py:43 msgid "Background:" msgstr "Fundo:" #: spyder/utils/syntaxhighlighters.py:44 #: spyder/widgets/sourcecode/codeeditor.py:107 msgid "Current line:" msgstr "Linha atual:" #: spyder/utils/syntaxhighlighters.py:45 msgid "Current cell:" msgstr "Célula selecionada:" #: spyder/utils/syntaxhighlighters.py:46 msgid "Occurrence:" msgstr "Ocorrência:" #: spyder/utils/syntaxhighlighters.py:47 msgid "Link:" msgstr "Link:" #: spyder/utils/syntaxhighlighters.py:48 msgid "Side areas:" msgstr "Áreas laterais:" #: spyder/utils/syntaxhighlighters.py:49 msgid "Matched
parens:" msgstr "Parênteses fechados:" #: spyder/utils/syntaxhighlighters.py:50 msgid "Unmatched
parens:" msgstr "Parênteses abertos:" #: spyder/utils/syntaxhighlighters.py:51 msgid "Normal text:" msgstr "Texto normal:" #: spyder/utils/syntaxhighlighters.py:52 msgid "Keyword:" msgstr "Palavra chave:" #: spyder/utils/syntaxhighlighters.py:53 msgid "Builtin:" msgstr "Objeto integrado:" #: spyder/utils/syntaxhighlighters.py:54 msgid "Definition:" msgstr "Definição:" #: spyder/utils/syntaxhighlighters.py:55 msgid "Comment:" msgstr "Comentário:" #: spyder/utils/syntaxhighlighters.py:56 msgid "String:" msgstr "String:" #: spyder/utils/syntaxhighlighters.py:57 msgid "Number:" msgstr "Número:" #: spyder/utils/syntaxhighlighters.py:58 msgid "Instance:" msgstr "Instância:" #: spyder/widgets/arraybuilder.py:179 msgid "" "\n" " Numpy Array/Matrix Helper
\n" " Type an array in Matlab : [1 2;3 4]
\n" " or Spyder simplified syntax : 1 2;3 4\n" "

\n" " Hit 'Enter' for array or 'Ctrl+Enter' for matrix.\n" "

\n" " Hint:
\n" " Use two spaces or two tabs to generate a ';'.\n" " " msgstr "" "\n" " Ajuda no Numpy Array/Matriz
\n" " Definir uma matriz no Matlab : [1 2;3 4]
\n" " ou na sintaxe simplificada do Spyder : 1 2;3 4\n" "

\n" " Aperte 'Enter' para array ou 'Ctrl+Enter' para matriz.\n" "

\n" " Dica:
\n" " Use dois espaços ou dois tabs para gerar um ';'.\n" " " #: spyder/widgets/arraybuilder.py:190 msgid "" "\n" " Numpy Array/Matrix Helper
\n" " Enter an array in the table.
\n" " Use Tab to move between cells.\n" "

\n" " Hit 'Enter' for array or 'Ctrl+Enter' for matrix.\n" "

\n" " Hint:
\n" " Use two tabs at the end of a row to move to the next row.\n" " " msgstr "" "\n" " Ajuda no Numpy Array/Matriz
\n" " Digite um array na tabela.
\n" " Use Tab para se mover entre as células.\n" "

\n" " Aperte 'Enter' para array ou 'Ctrl+Enter' para matriz.\n" "

\n" " Dica:
\n" " Use dois Tabs no fim de uma coluna para se mover até a próxima " "coluna.\n" " " #: spyder/widgets/arraybuilder.py:365 msgid "Array dimensions not valid" msgstr "Dimensões da matriz não é válida" #: spyder/widgets/browser.py:58 spyder/widgets/sourcecode/codeeditor.py:2719 msgid "Zoom out" msgstr "Menos zoom" #: spyder/widgets/browser.py:61 spyder/widgets/sourcecode/codeeditor.py:2715 msgid "Zoom in" msgstr "Mais zoom" #: spyder/widgets/browser.py:213 msgid "Home" msgstr "Página inicial" #: spyder/widgets/browser.py:249 msgid "Find text" msgstr "Buscar texto" #: spyder/widgets/browser.py:266 msgid "Address:" msgstr "Endereço:" #: spyder/widgets/browser.py:302 msgid "Unable to load page" msgstr "Não foi possível carregar a página" #: spyder/widgets/comboboxes.py:164 msgid "Press enter to validate this entry" msgstr "Aperte enter para validar esta entrada" #: spyder/widgets/comboboxes.py:165 msgid "This entry is incorrect" msgstr "Esta entrada é incorreta" #: spyder/widgets/comboboxes.py:208 msgid "Press enter to validate this path" msgstr "Aperte enter para validar esse caminho" #: spyder/widgets/dependencies.py:63 msgid " Required " msgstr "Requerido" #: spyder/widgets/dependencies.py:63 msgid "Module" msgstr "Módulo " #: spyder/widgets/dependencies.py:64 msgid " Installed " msgstr "Instalado" #: spyder/widgets/dependencies.py:64 msgid "Provided features" msgstr "Características proporcionadas" #: spyder/widgets/dependencies.py:134 msgid "Dependencies" msgstr "Dependências" #: spyder/widgets/dependencies.py:141 msgid "" "Spyder depends on several Python modules to provide the right functionality " "for all its panes. The table below shows the required and installed versions " "(if any) of all of them.

Note: You can safely use Spyder " "without the following modules installed: %s and %s." "

Please also note that new dependencies or changed ones will be " "correctly detected only after Spyder is restarted." msgstr "" "O Spyder depende de vários módulos do Python para fornecer suas " "funcionalidades corretamente em todos os painéis. A tabela abaixo mostra as " "versões requeridas e instaladas (se houver) de todos eles.

Nota: Você pode usar o Spyder normalmente sem os seguintes módulos instalados: " "%se %s" #: spyder/widgets/dependencies.py:157 msgid "Copy to clipboard" msgstr "Copiar para área transferência " #: spyder/widgets/editor.py:501 msgid "Find symbols in file..." msgstr "Procurar símbolos no arquivo..." #: spyder/widgets/editor.py:504 msgid "Copy path to clipboard" msgstr "Copiar caminho para área de transferência" #: spyder/widgets/editor.py:508 msgid "Close all to the right" msgstr "Fechar todos à direita" #: spyder/widgets/editor.py:510 msgid "Close all but this" msgstr "Fechar todos, menos este" #: spyder/widgets/editor.py:514 spyder/widgets/explorer.py:361 #, fuzzy msgid "Show in Finder" msgstr "Mostrar número de linhas" #: spyder/widgets/editor.py:516 spyder/widgets/explorer.py:363 #, fuzzy msgid "Show in external file explorer" msgstr "Mostrar/esconder o explorador de código" #: spyder/widgets/editor.py:1197 msgid "Temporary file" msgstr "Arquivo temporário " #: spyder/widgets/editor.py:1289 msgid "New window" msgstr "Nova janela" #: spyder/widgets/editor.py:1290 msgid "Create a new editor window" msgstr "Criar uma nova janela de edição" #: spyder/widgets/editor.py:1293 msgid "Split vertically" msgstr "Dividir verticalmente" #: spyder/widgets/editor.py:1295 msgid "Split vertically this editor window" msgstr "Dividir verticalmente esta janela de edição" #: spyder/widgets/editor.py:1297 msgid "Split horizontally" msgstr "Dividir horizontalmente" #: spyder/widgets/editor.py:1299 msgid "Split horizontally this editor window" msgstr "Dividir horizontalmente esta janela de edição" #: spyder/widgets/editor.py:1301 msgid "Close this panel" msgstr "Fechar este painel" #: spyder/widgets/editor.py:1540 msgid "%s has been modified.
Do you want to save changes?" msgstr "%s foi modificado.
Deseja salvar as mudanças?" #: spyder/widgets/editor.py:1626 spyder/widgets/editor.py:1789 msgid "Save" msgstr "Salvar" #: spyder/widgets/editor.py:1627 spyder/widgets/editor.py:1790 #: spyder/widgets/shell.py:267 msgid "Unable to save file '%s'

Error message:
%s" msgstr "" "Não foi possível salvar arquivo '%s'

Mensagem de erro:
%s" #: spyder/widgets/editor.py:1977 msgid "" "%s is unavailable (this file may have been removed, moved or renamed " "outside Spyder).
Do you want to close it?" msgstr "" "%s está indisponível (o arquivo pode ter sido removido, movido ou " "renomeado fora do Spyder).
Deseja fechar?" #: spyder/widgets/editor.py:2000 msgid "" "%s has been modified outside Spyder.
Do you want to reload it and " "lose all your changes?" msgstr "" "%s foi modificado fora do Spyder.
Você deseja recarregar ele e " "perder todas as modificações?" #: spyder/widgets/editor.py:2110 msgid "" "All changes to %s will be lost.
Do you want to revert file from " "disk?" msgstr "" "Todas as modificações do %s foram perdidas.
Você deseja reverter o " "arquivo do disco?" #: spyder/widgets/editor.py:2254 msgid "Loading %s..." msgstr "Carregando %s..." #: spyder/widgets/editor.py:2266 msgid "" "%s contains mixed end-of-line characters.
Spyder will fix this " "automatically." msgstr "" "%s contém vários tipos de caracteres de fim de linha.
O Spyder irá " "corrigir automaticamente." #: spyder/widgets/editor.py:2675 msgid "Close window" msgstr "Fechar janela" #: spyder/widgets/editor.py:2677 msgid "Close this window" msgstr "Fechar esta janela" #: spyder/widgets/editortools.py:94 spyder/widgets/editortools.py:130 msgid "Line %s" msgstr "Linha %s" #: spyder/widgets/editortools.py:99 msgid "Class defined at line %s" msgstr "Classe definida na linha %s" #: spyder/widgets/editortools.py:107 msgid "Method defined at line %s" msgstr "Método definido na linha %s" #: spyder/widgets/editortools.py:117 msgid "Function defined at line %s" msgstr "Função definida na linha %s" #: spyder/widgets/editortools.py:149 msgid "Cell starts at line %s" msgstr "A célula inicia na linha %s" #: spyder/widgets/editortools.py:202 spyder/widgets/editortools.py:535 msgid "Go to cursor position" msgstr "Ir para a posição do cursor " #: spyder/widgets/editortools.py:205 msgid "Show absolute path" msgstr "Mostrar o caminho completo" #: spyder/widgets/editortools.py:208 spyder/widgets/explorer.py:274 msgid "Show all files" msgstr "Mostrar todos os arquivos" #: spyder/widgets/editortools.py:211 msgid "Show special comments" msgstr "Mostrar comentários especiais" #: spyder/widgets/editortools.py:509 msgid "Show/hide outline explorer" msgstr "Mostrar/esconder o explorador de código" #: spyder/widgets/explorer.py:270 msgid "Edit filename filters..." msgstr "Editar filtros para nomes de arquivos..." #: spyder/widgets/explorer.py:284 msgid "Edit filename filters" msgstr "Editar filtros para nomes de arquivos" #: spyder/widgets/explorer.py:285 msgid "Name filters:" msgstr "Nome dos filtros:" #: spyder/widgets/explorer.py:304 msgid "File..." msgstr "Arquivo..." #: spyder/widgets/explorer.py:308 msgid "Module..." msgstr "Módulo..." #: spyder/widgets/explorer.py:312 msgid "Folder..." msgstr "Pasta..." #: spyder/widgets/explorer.py:316 msgid "Package..." msgstr "Pacote..." #: spyder/widgets/explorer.py:337 #: spyder/widgets/variableexplorer/collectionseditor.py:674 msgid "Edit" msgstr "Editar" #: spyder/widgets/explorer.py:339 msgid "Move..." msgstr "Mover..." #: spyder/widgets/explorer.py:342 msgid "Delete..." msgstr "Deletar..." #: spyder/widgets/explorer.py:345 msgid "Rename..." msgstr "Renomear..." #: spyder/widgets/explorer.py:348 msgid "Open" msgstr "Abrir" #: spyder/widgets/explorer.py:349 spyder/widgets/sourcecode/codeeditor.py:2687 msgid "Convert to Python script" msgstr "Converter para um script Python" #: spyder/widgets/explorer.py:390 msgid "Commit" msgstr "Enviar" #: spyder/widgets/explorer.py:393 msgid "Browse repository" msgstr "Explorar repositório " #: spyder/widgets/explorer.py:404 msgid "Open command prompt here" msgstr "Abrir prompt de comando aqui" #: spyder/widgets/explorer.py:406 msgid "Open terminal here" msgstr "Abrir terminal aqui" #: spyder/widgets/explorer.py:407 #, fuzzy msgid "Open IPython console here" msgstr "Abrir console Python aqui" #: spyder/widgets/explorer.py:421 msgid "New" msgstr "Novo" #: spyder/widgets/explorer.py:429 msgid "Import" msgstr "Importar" #: spyder/widgets/explorer.py:575 msgid "Do you really want to delete %s?" msgstr "Deseja mesmo deletar %s?" #: spyder/widgets/explorer.py:593 msgid "delete" msgstr "deletar" #: spyder/widgets/explorer.py:594 spyder/widgets/projects/explorer.py:148 #: spyder/widgets/projects/explorer.py:255 msgid "Project Explorer" msgstr "Explorador de projetos" #: spyder/widgets/explorer.py:595 spyder/widgets/projects/explorer.py:149 msgid "Unable to %s %s

Error message:
%s" msgstr "Não foi possível %s %s

Mensagem de erro:
%s" #: spyder/widgets/explorer.py:610 msgid "File Explorer" msgstr "Explorador de arquivos" #: spyder/widgets/explorer.py:611 msgid "" "The current directory contains a project.

If you want to delete the " "project, please go to Projects » Delete Project" msgstr "" "O diretório atual contém um projeto.

Se você deseja mesmo deletar o " "projeto, por favor vá em Projetos » Deletar Projeto" #: spyder/widgets/explorer.py:628 spyder/widgets/sourcecode/codeeditor.py:2160 msgid "Conversion error" msgstr "Erro de conversão" #: spyder/widgets/explorer.py:629 spyder/widgets/sourcecode/codeeditor.py:2161 msgid "" "It was not possible to convert this notebook. The error is:\n" "\n" msgstr "" "Não foi possível converter esse notebook. O erro é:\n" "\n" #: spyder/widgets/explorer.py:646 spyder/widgets/explorer.py:654 #: spyder/widgets/explorer.py:665 #: spyder/widgets/variableexplorer/collectionseditor.py:703 #: spyder/widgets/variableexplorer/collectionseditor.py:949 msgid "Rename" msgstr "Renomear" #: spyder/widgets/explorer.py:647 msgid "New name:" msgstr "Novo nome:" #: spyder/widgets/explorer.py:655 msgid "" "Do you really want to rename %s and overwrite the existing file " "%s?" msgstr "" "Você deseja mesmo renomear %s e sobrescrever o arquivo já existente " "%s? " #: spyder/widgets/explorer.py:666 msgid "Unable to rename file %s

Error message:
%s" msgstr "" "Não foi possível renomear arquivo %s

Mensagem de erro:" "
%s" #: spyder/widgets/explorer.py:709 msgid "Unable to move %s

Error message:
%s" msgstr "Não foi possível mover %s

Mensagem de erro:
%s" #: spyder/widgets/explorer.py:727 msgid "Unable to create folder %s

Error message:
%s" msgstr "" "Não foi possível criar pasta %s

Mensagem de erro:
%s" #: spyder/widgets/explorer.py:740 spyder/widgets/explorer.py:774 msgid "Unable to create file %s

Error message:
%s" msgstr "" "Não foi possível criar arquivo %s

Mensagem de erro:
" "%s" #: spyder/widgets/explorer.py:748 msgid "New folder" msgstr "Nova pasta" #: spyder/widgets/explorer.py:749 msgid "Folder name:" msgstr "Nome da pasta:" #: spyder/widgets/explorer.py:754 msgid "New package" msgstr "Novo pacote" #: spyder/widgets/explorer.py:755 msgid "Package name:" msgstr "Nome do pacote:" #: spyder/widgets/explorer.py:795 msgid "New module" msgstr "Novo módulo " #: spyder/widgets/explorer.py:810 msgid "" "For %s support, please install one of the
following tools:

%s" msgstr "" "Para ter suporte ao %s, por favor instale as
seguintes ferramentas:

%s" #: spyder/widgets/explorer.py:814 msgid "Unable to find external program.

%s" msgstr "Não foi possível encontrar o programa externo.

%s" #: spyder/widgets/explorer.py:1035 msgid "Show current directory only" msgstr "Mostrar somente o diretório atual" #: spyder/widgets/explorer.py:1145 msgid "You don't have the right permissions to open this directory" msgstr "Você não tem permissão para abrir esse diretório" #: spyder/widgets/explorer.py:1176 msgid "Show icons and text" msgstr "Mostrar ícones e texto" #: spyder/widgets/explorer.py:1178 #: spyder/widgets/variableexplorer/importwizard.py:535 msgid "Previous" msgstr "Anterior" #: spyder/widgets/explorer.py:1184 msgid "Parent" msgstr "Superior" #: spyder/widgets/fileswitcher.py:110 msgid "unsaved file" msgstr "arquivo não salvo" #: spyder/widgets/fileswitcher.py:249 msgid "" "Press Enter to switch files or Esc to cancel.

Type to " "filter filenames.

Use :number to go to a line, e.g. " "main:42
Use @symbol_text to go to a symbol, e." "g. @init

Press Ctrl+W to close current " "tab.
" msgstr "" "Pressione Enter para trocar de arquivo ou Esc para cancelar." "

Type to filter filenames.

Utilize :número para ir numa " "linha, ex: main:42
Use @texto_do_simbolo para " "ir em um simbolo, ex: @init

Pressione Ctrl+W para fechar a aba atual.
" #: spyder/widgets/fileswitcher.py:663 msgid "lines" msgstr "linhas" #: spyder/widgets/findinfiles.py:121 msgid "Unexpected error: see internal console" msgstr "Erro inesperado: veja o console interno" #: spyder/widgets/findinfiles.py:149 msgid "invalid regular expression" msgstr "expressão regular inválida" #: spyder/widgets/findinfiles.py:199 msgid "permission denied errors were encountered" msgstr "permissão negada, foram encontrados erros" #: spyder/widgets/findinfiles.py:258 msgid "Search pattern" msgstr "Padrão de pesquisa " #: spyder/widgets/findinfiles.py:261 spyder/widgets/findinfiles.py:301 #: spyder/widgets/findreplace.py:99 msgid "Regular expression" msgstr "Expressão regular" #: spyder/widgets/findinfiles.py:264 spyder/widgets/findreplace.py:105 msgid "Case Sensitive" msgstr "" "Diferenciar maiúsculas\n" "de minúsculas" #: spyder/widgets/findinfiles.py:275 msgid "Search" msgstr "Procurar" #: spyder/widgets/findinfiles.py:278 msgid "Start search" msgstr "Iniciar busca" #: spyder/widgets/findinfiles.py:285 msgid "Stop search" msgstr "Parar busca" #: spyder/widgets/findinfiles.py:295 msgid "Excluded filenames pattern" msgstr "" "Excluir padrões de nomes\n" "do arquivo" #: spyder/widgets/findinfiles.py:304 msgid "Exclude:" msgstr "Excluir:" #: spyder/widgets/findinfiles.py:313 #, fuzzy msgid "Search in:" msgstr "Procurar string" #: spyder/widgets/findinfiles.py:315 #, fuzzy msgid "Search directory" msgstr "Selecionar diretório" #: spyder/widgets/findinfiles.py:324 msgid "Search in all files and directories present on thecurrent Spyder path" msgstr "" #: spyder/widgets/findinfiles.py:328 #, fuzzy msgid "Project" msgstr "&Projetos" #: spyder/widgets/findinfiles.py:330 msgid "" "Search in all files and directories present on thecurrent project path (If " "opened)" msgstr "" #: spyder/widgets/findinfiles.py:336 #, fuzzy msgid "File" msgstr "&Arquivo" #: spyder/widgets/findinfiles.py:338 #, fuzzy msgid "Search in current opened file" msgstr "Buscar em vários arquivos" #: spyder/widgets/findinfiles.py:340 #, fuzzy msgid "Select other directory" msgstr "Selecionar diretório" #: spyder/widgets/findinfiles.py:342 #, fuzzy msgid "Search in other folder present on the file system" msgstr "Buscar em vários arquivos" #: spyder/widgets/findinfiles.py:378 msgid "Hide advanced options" msgstr "Esconder opções avançadas" #: spyder/widgets/findinfiles.py:381 msgid "Show advanced options" msgstr "Mostrar opções avançadas " #: spyder/widgets/findinfiles.py:675 spyder/widgets/findinfiles.py:759 msgid "String not found" msgstr "String não encontrada" #: spyder/widgets/findinfiles.py:761 msgid "matches in" msgstr "correspondências em" #: spyder/widgets/findinfiles.py:762 msgid "file" msgstr "arquivo" #: spyder/widgets/findinfiles.py:794 msgid " Scanning: {0}" msgstr "" #: spyder/widgets/findinfiles.py:796 msgid " Searching for files in folder: {0}" msgstr "" #: spyder/widgets/findinfiles.py:800 msgid " Searching for files..." msgstr "" #: spyder/widgets/findreplace.py:48 #, fuzzy msgid "No matches" msgstr "correspondências em" #: spyder/widgets/findreplace.py:49 spyder/widgets/findreplace.py:50 #: spyder/widgets/findreplace.py:72 msgid "Search string" msgstr "Procurar string" #: spyder/widgets/findreplace.py:51 #, fuzzy msgid "Regular expression error" msgstr "Expressão regular" #: spyder/widgets/findreplace.py:111 msgid "Whole words" msgstr "Palavras inteiras" #: spyder/widgets/findreplace.py:117 msgid "Highlight matches" msgstr "Destacar correspondências " #: spyder/widgets/findreplace.py:131 msgid "Replace with:" msgstr "Substituir com:" #: spyder/widgets/findreplace.py:133 msgid "Replace string" msgstr "Substituir string" #: spyder/widgets/findreplace.py:137 #, fuzzy msgid "Replace/find next" msgstr "Substituir/buscar" #: spyder/widgets/findreplace.py:142 #, fuzzy msgid "Replace selection" msgstr "Substituir string" #: spyder/widgets/findreplace.py:150 msgid "Replace all" msgstr "Substituir tudo" #: spyder/widgets/findreplace.py:572 msgid "of" msgstr "" #: spyder/widgets/findreplace.py:576 #, fuzzy msgid "matches" msgstr "correspondências em" #: spyder/widgets/findreplace.py:579 #, fuzzy msgid "no matches" msgstr "correspondências em" #: spyder/widgets/internalshell.py:262 msgid "Help..." msgstr "Ajuda..." #: spyder/widgets/internalshell.py:279 msgid "Shell special commands:" msgstr "Comando especiais: " #: spyder/widgets/internalshell.py:280 msgid "Internal editor:" msgstr "Editor interno:" #: spyder/widgets/internalshell.py:281 msgid "External editor:" msgstr "Editor externo:" #: spyder/widgets/internalshell.py:282 msgid "Run script:" msgstr "Executar script:" #: spyder/widgets/internalshell.py:283 msgid "Remove references:" msgstr "Remover referências:" #: spyder/widgets/internalshell.py:284 msgid "System commands:" msgstr "Comandos do sistema:" #: spyder/widgets/internalshell.py:285 msgid "Python help:" msgstr "Ajuda do Python:" #: spyder/widgets/internalshell.py:286 msgid "GUI-based editor:" msgstr "Editor gráfico:" #: spyder/widgets/ipythonconsole/client.py:275 msgid "An error ocurred while starting the kernel" msgstr "Um erro ocorreu enquanto o kernel era inicializado" #: spyder/widgets/ipythonconsole/client.py:316 #: spyder/widgets/ipythonconsole/client.py:372 #: spyder/widgets/ipythonconsole/client.py:405 #: spyder/widgets/ipythonconsole/shell.py:232 #: spyder/widgets/variableexplorer/namespacebrowser.py:193 #, fuzzy msgid "Remove all variables" msgstr "Salvar todos os arquivos" #: spyder/widgets/ipythonconsole/client.py:325 #, fuzzy msgid "Show environment variables" msgstr "Variáveis de ambiente" #: spyder/widgets/ipythonconsole/client.py:332 msgid "Show sys.path contents" msgstr "Mostrar conteúdo do sys.path" #: spyder/widgets/ipythonconsole/client.py:359 msgid "Stop the current command" msgstr "Parar o comando atual" #: spyder/widgets/ipythonconsole/client.py:370 #: spyder/widgets/variableexplorer/collectionseditor.py:696 #: spyder/widgets/variableexplorer/collectionseditor.py:931 msgid "Remove" msgstr "Remover" #: spyder/widgets/ipythonconsole/client.py:393 msgid "Inspect current object" msgstr "Inspecionar objeto" #: spyder/widgets/ipythonconsole/client.py:399 msgid "Clear line or block" msgstr "Limpar linha ou bloco" #: spyder/widgets/ipythonconsole/client.py:412 msgid "Clear console" msgstr "Limpar console" #: spyder/widgets/ipythonconsole/client.py:460 msgid "Are you sure you want to restart the kernel?" msgstr "Deseja mesmo reiniciar o kernel?" #: spyder/widgets/ipythonconsole/client.py:462 msgid "Restart kernel?" msgstr "Reiniciar kernel?" #: spyder/widgets/ipythonconsole/client.py:474 msgid "Error restarting kernel: %s\n" msgstr "Erro ao reiniciar kernel: %s\n" #: spyder/widgets/ipythonconsole/client.py:479 msgid "" "
Restarting kernel...\n" "

" msgstr "" "
Reiniciando kernel..\n" "

" #: spyder/widgets/ipythonconsole/client.py:483 msgid "Cannot restart a kernel not started by Spyder\n" msgstr "Não é possível reiniciar um kernel que não foi iniciado pelo Spyder\n" #: spyder/widgets/ipythonconsole/client.py:592 msgid "Connecting to kernel..." msgstr "Conectando ao kernel..." #: spyder/widgets/ipythonconsole/help.py:128 spyder/widgets/mixins.py:712 msgid "Arguments" msgstr "Argumentos" #: spyder/widgets/ipythonconsole/namespacebrowser.py:129 msgid "Loading this kind of data while debugging is not supported." msgstr "" #: spyder/widgets/ipythonconsole/namespacebrowser.py:148 msgid "Saving data while debugging is not supported." msgstr "" #: spyder/widgets/ipythonconsole/shell.py:233 #, fuzzy msgid "" "All user-defined variables will be removed. Are you sure you want to proceed?" msgstr "" "Todas as variáveis definidas pelo usuário serão removidas.
Você tem " "certeza que deseja resetar o namespace?" #: spyder/widgets/ipythonconsole/shell.py:239 msgid "Don't show again." msgstr "" #: spyder/widgets/ipythonconsole/shell.py:262 msgid "" "

Removing all variables...\n" "
" msgstr "" #: spyder/widgets/ipythonconsole/shell.py:426 msgid "Changing backend to Qt for Mayavi" msgstr "Mudando a saída gráfica do Qt para Mayavi" #: spyder/widgets/ipythonconsole/shell.py:471 msgid "Kernel died, restarting" msgstr "O Kernel morreu, reiniciando" #: spyder/widgets/ipythonconsole/shell.py:471 msgid "Kernel restarting" msgstr "Reiniciando Kernel" #: spyder/widgets/onecolumntree.py:52 msgid "Collapse all" msgstr "Reduzir tudo" #: spyder/widgets/onecolumntree.py:56 msgid "Expand all" msgstr "Expandir tudo" #: spyder/widgets/onecolumntree.py:60 msgid "Restore" msgstr "Restaurar" #: spyder/widgets/onecolumntree.py:61 msgid "Restore original tree layout" msgstr "Restaurar a disposição original" #: spyder/widgets/onecolumntree.py:65 msgid "Collapse selection" msgstr "Reduzir seleção" #: spyder/widgets/onecolumntree.py:69 msgid "Expand selection" msgstr "Expandir seleção" #: spyder/widgets/pathmanager.py:97 msgid "Move to top" msgstr "Mover para o inicio" #: spyder/widgets/pathmanager.py:103 msgid "Move up" msgstr "Mover para cima" #: spyder/widgets/pathmanager.py:109 msgid "Move down" msgstr "Mover para baixo" #: spyder/widgets/pathmanager.py:115 msgid "Move to bottom" msgstr "Mover para o final" #: spyder/widgets/pathmanager.py:126 spyder/widgets/pathmanager.py:267 msgid "Add path" msgstr "Adicionar caminho" #: spyder/widgets/pathmanager.py:131 spyder/widgets/pathmanager.py:246 msgid "Remove path" msgstr "Remover caminho" #: spyder/widgets/pathmanager.py:141 msgid "Synchronize..." msgstr "Sincronizar..." #: spyder/widgets/pathmanager.py:143 msgid "Synchronize Spyder's path list with PYTHONPATH environment variable" msgstr "" "Sincronizar a lista de caminhos do Spyder com a variável\n" "de ambiente PYTHONPATH" #: spyder/widgets/pathmanager.py:155 msgid "Synchronize" msgstr "Sincronizar" #: spyder/widgets/pathmanager.py:156 msgid "" "This will synchronize Spyder's path list with PYTHONPATH environment " "variable for current user, allowing you to run your Python modules outside " "Spyder without having to configure sys.path.
Do you want to clear " "contents of PYTHONPATH before adding Spyder's path list?" msgstr "" "Isso irá sincronizar a lista de caminhos do Spyder com a variável de " "ambiente PYTHONPATHpara o usuário atual, permitindo executar seus " "módulos de Python fora do Spyder sem precisar configurar o sys.path. " "
Deseja limpar o conteúdo da PYTHONPATH antes de adicionar a lista de " "caminhos do Spyder?" #: spyder/widgets/pathmanager.py:247 msgid "Do you really want to remove selected path?" msgstr "Você deseja mesmo remover o caminho selecionado?" #: spyder/widgets/pathmanager.py:268 msgid "" "This directory is already included in Spyder path list.
Do you want to " "move it to the top of the list?" msgstr "" "Este diretório já está incluído na lista de caminhos do Spyder.
Deseja " "mover ele para o topo da lista?" #: spyder/widgets/projects/configdialog.py:30 msgid "Project preferences" msgstr "Preferências do projeto" #: spyder/widgets/projects/configdialog.py:82 #: spyder/widgets/projects/configdialog.py:119 msgid "Restore data on startup" msgstr "Restaurar data na inicialização" #: spyder/widgets/projects/configdialog.py:84 #: spyder/widgets/projects/configdialog.py:121 msgid "Save data on exit" msgstr "Salvar data ao sair" #: spyder/widgets/projects/configdialog.py:86 #: spyder/widgets/projects/configdialog.py:123 msgid "Save history" msgstr "Salvar histórico" #: spyder/widgets/projects/configdialog.py:88 #: spyder/widgets/projects/configdialog.py:125 msgid "Save non project files opened" msgstr "Salvar arquivos que não são de projetos, atualmente abertos" #: spyder/widgets/projects/configdialog.py:111 msgid "Code" msgstr "Código" #: spyder/widgets/projects/configdialog.py:118 msgid "Workspace" msgstr "Espaço de trabalho" #: spyder/widgets/projects/configdialog.py:148 #: spyder/widgets/projects/configdialog.py:155 msgid "Version control" msgstr "Controlador de versão" #: spyder/widgets/projects/configdialog.py:156 msgid "Use version control" msgstr "Usar controlador de versão" #: spyder/widgets/projects/configdialog.py:161 msgid "Version control system" msgstr "Sistema de Controle de Versão" #: spyder/widgets/projects/explorer.py:51 msgid "Show horizontal scrollbar" msgstr "Mostrar barra de rolagem horizontal" #: spyder/widgets/projects/explorer.py:113 msgid "File %s already exists.
Do you want to overwrite it?" msgstr "O arquivo %s já existe
Deseja sobrescrever ele?" #: spyder/widgets/projects/explorer.py:127 msgid "Folder %s already exists." msgstr "A Pasta %s já existe." #: spyder/widgets/projects/explorer.py:145 msgid "copy" msgstr "copiar" #: spyder/widgets/projects/explorer.py:147 msgid "move" msgstr "mover" #: spyder/widgets/projects/explorer.py:243 msgid "" "Do you really want to delete {filename}?

Note: This " "action will only delete the project. Its files are going to be preserved on " "disk." msgstr "" "Você deseja mesmo deletar {filename}?

Nota: Isso " "deletará apenas o projeto. Os arquivos continuarão no disco." #: spyder/widgets/projects/explorer.py:256 msgid "" "Unable to delete {varpath}

The error message was:" "
{error}" msgstr "" "Não foi possível deletar {varpath}

Mensagem de erro:" "
{error}" #: spyder/widgets/projects/projectdialog.py:69 msgid "New directory" msgstr "Novo diretório" #: spyder/widgets/projects/projectdialog.py:70 msgid "Existing directory" msgstr "Diretório existente" #: spyder/widgets/projects/projectdialog.py:72 msgid "Project name" msgstr "Nome do projeto" #: spyder/widgets/projects/projectdialog.py:73 msgid "Location" msgstr "Localização" #: spyder/widgets/projects/projectdialog.py:74 msgid "Project type" msgstr "Tipo do projeto" #: spyder/widgets/projects/projectdialog.py:75 msgid "Python version" msgstr "Versão do Python" #: spyder/widgets/projects/projectdialog.py:83 #: spyder/widgets/variableexplorer/importwizard.py:529 msgid "Cancel" msgstr "Cancelar" #: spyder/widgets/projects/projectdialog.py:84 msgid "Create" msgstr "Criar" #: spyder/widgets/projects/projectdialog.py:102 msgid "Create new project" msgstr "Criar um novo projeto" #: spyder/widgets/projects/type/__init__.py:216 msgid "Empty project" msgstr "Projeto vazio" #: spyder/widgets/projects/type/python.py:20 msgid "Python project" msgstr "Projeto Python" #: spyder/widgets/projects/type/python.py:76 msgid "Python package" msgstr "Pacote Python" #: spyder/widgets/pydocgui.py:110 msgid "Module or package:" msgstr "Módulo ou pacote:" #: spyder/widgets/shell.py:131 msgid "Save history log..." msgstr "Salvar histórico..." #: spyder/widgets/shell.py:133 msgid "Save current history log (i.e. all inputs and outputs) in a text file" msgstr "" "Salvar o histórico atual (todas entradas e saídas) em um arquivo de texto" #: spyder/widgets/shell.py:253 msgid "Save history log" msgstr "Salvar histórico" #: spyder/widgets/shell.py:256 msgid "History logs" msgstr "Histórico de comandos" #: spyder/widgets/shell.py:670 msgid "Copy without prompts" msgstr "Copiar sem os prompts" #: spyder/widgets/shell.py:673 spyder/widgets/shell.py:677 msgid "Clear line" msgstr "Limpar linha" #: spyder/widgets/shell.py:679 msgid "Clear shell" msgstr "Limpar shell" #: spyder/widgets/shell.py:683 msgid "Clear shell contents ('cls' command)" msgstr "Limpar conteúdo do shell (comando 'cls')" #: spyder/widgets/shortcutssummary.py:42 #, fuzzy msgid "Spyder Keyboard ShortCuts" msgstr "Teclas de atalho" #: spyder/widgets/sourcecode/codeeditor.py:101 msgid "Go to line:" msgstr "Ir para a linha:" #: spyder/widgets/sourcecode/codeeditor.py:109 msgid "Line count:" msgstr "Número de linhas:" #: spyder/widgets/sourcecode/codeeditor.py:1327 msgid "Breakpoint" msgstr "Ponto de interrupção" #: spyder/widgets/sourcecode/codeeditor.py:1328 msgid "Condition:" msgstr "Condição:" #: spyder/widgets/sourcecode/codeeditor.py:1733 msgid "Code analysis" msgstr "Análise de código" #: spyder/widgets/sourcecode/codeeditor.py:1787 msgid "To do" msgstr "To do" #: spyder/widgets/sourcecode/codeeditor.py:2147 msgid "Removal error" msgstr "Erro de remoção" #: spyder/widgets/sourcecode/codeeditor.py:2148 msgid "" "It was not possible to remove outputs from this notebook. The error is:\n" "\n" msgstr "" "Não foi possível remover as saídas deste notebook. O erro é:\n" "\n" #: spyder/widgets/sourcecode/codeeditor.py:2684 msgid "Clear all ouput" msgstr "Limpar todas as saídas " #: spyder/widgets/sourcecode/codeeditor.py:2690 msgid "Go to definition" msgstr "Ver definição" #: spyder/widgets/sourcecode/codeeditor.py:2723 msgid "Zoom reset" msgstr "Resetar Zoom" #: spyder/widgets/status.py:25 msgid "CPU and memory usage info in the status bar" msgstr "Uso de CPU e memória na barra de status" #: spyder/widgets/status.py:117 msgid "Memory:" msgstr "Memória:" #: spyder/widgets/status.py:118 msgid "" "Memory usage status: requires the `psutil` (>=v0.3) library on non-Windows " "platforms" msgstr "" "Status de uso da memória: requer a biblioteca `psutil` (>=v0.3) em outras " "plataformas" #: spyder/widgets/status.py:134 msgid "CPU:" msgstr "CPU:" #: spyder/widgets/status.py:135 msgid "CPU usage status: requires the `psutil` (>=v0.3) library" msgstr "Status de uso da CPU: requer a biblioteca `psutil` (>=v0.3)" #: spyder/widgets/status.py:162 msgid "Permissions:" msgstr "Permissões:" #: spyder/widgets/status.py:189 msgid "End-of-lines:" msgstr "Fim de linha:" #: spyder/widgets/status.py:216 msgid "Encoding:" msgstr "Codificação:" #: spyder/widgets/status.py:242 msgid "Line:" msgstr "Linha:" #: spyder/widgets/status.py:243 msgid "Column:" msgstr "Coluna:" #: spyder/widgets/tabs.py:274 msgid "Browse tabs" msgstr "Navegar pelas abas" #: spyder/widgets/tabs.py:403 msgid "Close current tab" msgstr "Fechar aba atual" #: spyder/widgets/variableexplorer/arrayeditor.py:511 msgid "It was not possible to copy values for this array" msgstr "Não foi possível copiar os valores dessa matriz" #: spyder/widgets/variableexplorer/arrayeditor.py:546 #: spyder/widgets/variableexplorer/arrayeditor.py:579 #: spyder/widgets/variableexplorer/dataframeeditor.py:697 #: spyder/widgets/variableexplorer/dataframeeditor.py:742 msgid "Format" msgstr "Formato" #: spyder/widgets/variableexplorer/arrayeditor.py:551 #: spyder/widgets/variableexplorer/dataframeeditor.py:701 msgid "Resize" msgstr "Redimensionar" #: spyder/widgets/variableexplorer/arrayeditor.py:554 #: spyder/widgets/variableexplorer/dataframeeditor.py:705 msgid "Background color" msgstr "Cor de fundo" #: spyder/widgets/variableexplorer/arrayeditor.py:580 #: spyder/widgets/variableexplorer/dataframeeditor.py:743 msgid "Float formatting" msgstr "Formatação de ponto flutuante" #: spyder/widgets/variableexplorer/arrayeditor.py:588 msgid "Format (%s) is incorrect" msgstr "O formato (%s) está incorreto" #: spyder/widgets/variableexplorer/arrayeditor.py:624 msgid "Arrays with more than 3 dimensions are not supported" msgstr "Matrizes com mais de 3 dimensões não são suportadas" #: spyder/widgets/variableexplorer/arrayeditor.py:628 msgid "The 'xlabels' argument length do no match array column number" msgstr "" "O argumento de comprimento 'xlabels' não corresponde com o número de colunas " "da matriz" #: spyder/widgets/variableexplorer/arrayeditor.py:632 msgid "The 'ylabels' argument length do no match array row number" msgstr "" "O argumento de comprimento 'ylabels' não corresponde com o número de linhas " "da matriz" #: spyder/widgets/variableexplorer/arrayeditor.py:639 msgid "%s arrays" msgstr "%s matrizes" #: spyder/widgets/variableexplorer/arrayeditor.py:640 msgid "%s are currently not supported" msgstr "%s não é suportado no momento" #: spyder/widgets/variableexplorer/arrayeditor.py:647 msgid "NumPy array" msgstr "Matriz NumPy" #: spyder/widgets/variableexplorer/arrayeditor.py:649 #: spyder/widgets/variableexplorer/arrayeditor.py:806 msgid "Array editor" msgstr "Editor de matrizes" #: spyder/widgets/variableexplorer/arrayeditor.py:651 msgid "read only" msgstr "somente leitura" #: spyder/widgets/variableexplorer/arrayeditor.py:681 msgid "Record array fields:" msgstr "Campos de matrizes registradas:" #: spyder/widgets/variableexplorer/arrayeditor.py:693 msgid "Data" msgstr "Dados" #: spyder/widgets/variableexplorer/arrayeditor.py:693 msgid "Mask" msgstr "Máscara" #: spyder/widgets/variableexplorer/arrayeditor.py:693 msgid "Masked data" msgstr "Dados mascarados" #: spyder/widgets/variableexplorer/arrayeditor.py:704 msgid "Axis:" msgstr "Eixo:" #: spyder/widgets/variableexplorer/arrayeditor.py:709 msgid "Index:" msgstr "Índice:" #: spyder/widgets/variableexplorer/arrayeditor.py:722 msgid "Warning: changes are applied separately" msgstr "Aviso: mudanças são aplicadas de forma separada" #: spyder/widgets/variableexplorer/arrayeditor.py:723 msgid "" "For performance reasons, changes applied to masked array won't be reflected " "in array's data (and vice-versa)." msgstr "" "Por motivos de desempenho, as mudanças\n" "aplicadas a matrizes mascaradas não serão\n" "refletidas nos dados da matriz\n" "(e vice-versa)." #: spyder/widgets/variableexplorer/collectionseditor.py:126 msgid "Index" msgstr "Índice" #: spyder/widgets/variableexplorer/collectionseditor.py:131 msgid "Tuple" msgstr "Tupla" #: spyder/widgets/variableexplorer/collectionseditor.py:134 msgid "List" msgstr "Lista" #: spyder/widgets/variableexplorer/collectionseditor.py:137 msgid "Dictionary" msgstr "Dicionário " #: spyder/widgets/variableexplorer/collectionseditor.py:139 msgid "Key" msgstr "Chave" #: spyder/widgets/variableexplorer/collectionseditor.py:144 msgid "Attribute" msgstr "Atributo" #: spyder/widgets/variableexplorer/collectionseditor.py:148 msgid "elements" msgstr "elementos" #: spyder/widgets/variableexplorer/collectionseditor.py:319 msgid "Size" msgstr "Tamanho" #: spyder/widgets/variableexplorer/collectionseditor.py:319 msgid "Type" msgstr "Tipo" #: spyder/widgets/variableexplorer/collectionseditor.py:319 msgid "Value" msgstr "Valor" #: spyder/widgets/variableexplorer/collectionseditor.py:417 msgid "" "Opening this variable can be slow\n" "\n" "Do you want to continue anyway?" msgstr "" "Abrir essa variável pode ser um processo lento\n" "\n" "Deseja continuar mesmo assim?" #: spyder/widgets/variableexplorer/collectionseditor.py:428 msgid "" "Spyder was unable to retrieve the value of this variable from the console." "

The error mesage was:
%s" msgstr "" "O Spyder não foi capaz de receber o valor desta variável do console." "

A mensagem de erro foi:
%s" #: spyder/widgets/variableexplorer/collectionseditor.py:605 msgid "Edit item" msgstr "Editar item" #: spyder/widgets/variableexplorer/collectionseditor.py:606 msgid "Unable to assign data to item.

Error message:
%s" msgstr "" "Não foi possível atribuir dados ao item.

Mensagem de erro:
" "%s" #: spyder/widgets/variableexplorer/collectionseditor.py:666 msgid "Resize rows to contents" msgstr "Redimensionar linhas para o conteúdo " #: spyder/widgets/variableexplorer/collectionseditor.py:677 #: spyder/widgets/variableexplorer/collectionseditor.py:1027 #: spyder/widgets/variableexplorer/collectionseditor.py:1044 msgid "Plot" msgstr "Gráfico" #: spyder/widgets/variableexplorer/collectionseditor.py:681 msgid "Histogram" msgstr "Histograma" #: spyder/widgets/variableexplorer/collectionseditor.py:685 msgid "Show image" msgstr "Mostrar imagem" #: spyder/widgets/variableexplorer/collectionseditor.py:689 #: spyder/widgets/variableexplorer/collectionseditor.py:1052 msgid "Save array" msgstr "Salvar matriz" #: spyder/widgets/variableexplorer/collectionseditor.py:693 #: spyder/widgets/variableexplorer/collectionseditor.py:991 #: spyder/widgets/variableexplorer/collectionseditor.py:999 msgid "Insert" msgstr "Inserir" #: spyder/widgets/variableexplorer/collectionseditor.py:706 #: spyder/widgets/variableexplorer/collectionseditor.py:952 msgid "Duplicate" msgstr "Duplicar" #: spyder/widgets/variableexplorer/collectionseditor.py:929 msgid "Do you want to remove the selected item?" msgstr "Você deseja remover o item selecionado?" #: spyder/widgets/variableexplorer/collectionseditor.py:930 msgid "Do you want to remove all selected items?" msgstr "Você deseja remover todos os itens selecionados?" #: spyder/widgets/variableexplorer/collectionseditor.py:950 msgid "New variable name:" msgstr "Novo nome da variável:" #: spyder/widgets/variableexplorer/collectionseditor.py:953 msgid "Variable name:" msgstr "Nome da variável:" #: spyder/widgets/variableexplorer/collectionseditor.py:991 msgid "Key:" msgstr "Chave:" #: spyder/widgets/variableexplorer/collectionseditor.py:999 msgid "Value:" msgstr "Valor:" #: spyder/widgets/variableexplorer/collectionseditor.py:1015 msgid "Import error" msgstr "Erro de importação" #: spyder/widgets/variableexplorer/collectionseditor.py:1016 msgid "Please install matplotlib or guiqwt." msgstr "Por favor instale matplotlib ou guiqwt." #: spyder/widgets/variableexplorer/collectionseditor.py:1028 msgid "Unable to plot data.

Error message:
%s" msgstr "" "Não foi possível mostrar os dados.

Mensagem de erro:
%s" #: spyder/widgets/variableexplorer/collectionseditor.py:1045 msgid "Unable to show image.

Error message:
%s" msgstr "" "Não foi possível mostrar o gráfico.

Mensagem de erro:
%s" #: spyder/widgets/variableexplorer/collectionseditor.py:1068 msgid "Unable to save array

Error message:
%s" msgstr "Não foi possível salvar matriz

Mensagem de erro:
%s" #: spyder/widgets/variableexplorer/collectionseditor.py:1093 msgid "It was not possible to copy this array" msgstr "Não foi possível copiar essa matriz" #: spyder/widgets/variableexplorer/collectionseditor.py:1118 msgid "Clipboard contents" msgstr "Conteúdo da área de transferência " #: spyder/widgets/variableexplorer/collectionseditor.py:1133 msgid "Import from clipboard" msgstr "Importar da área de transferência " #: spyder/widgets/variableexplorer/collectionseditor.py:1135 msgid "Empty clipboard" msgstr "Área de transferência vazia" #: spyder/widgets/variableexplorer/collectionseditor.py:1136 msgid "Nothing to be imported from clipboard." msgstr "Não há nada para ser importado da área de transferência." #: spyder/widgets/variableexplorer/dataframeeditor.py:591 msgid "To bool" msgstr "Para booleano" #: spyder/widgets/variableexplorer/dataframeeditor.py:591 msgid "To complex" msgstr "Para complexo" #: spyder/widgets/variableexplorer/dataframeeditor.py:592 msgid "To float" msgstr "Para flutuante" #: spyder/widgets/variableexplorer/dataframeeditor.py:592 msgid "To int" msgstr "Para inteiro" #: spyder/widgets/variableexplorer/dataframeeditor.py:593 msgid "To str" msgstr "Para string" #: spyder/widgets/variableexplorer/dataframeeditor.py:677 msgid "%s editor" msgstr "Editor de %s" #: spyder/widgets/variableexplorer/dataframeeditor.py:711 msgid "Column min/max" msgstr "Min/max de coluna" #: spyder/widgets/variableexplorer/dataframeeditor.py:751 msgid "Format ({}) is incorrect" msgstr "O formato ({}) éincorreto" #: spyder/widgets/variableexplorer/dataframeeditor.py:755 msgid "Format ({}) should start with '%'" msgstr "O formato ({}) deve começar com '%'" #: spyder/widgets/variableexplorer/importwizard.py:118 #: spyder/widgets/variableexplorer/importwizard.py:438 msgid "Import as" msgstr "Importar como" #: spyder/widgets/variableexplorer/importwizard.py:120 msgid "data" msgstr "dados" #: spyder/widgets/variableexplorer/importwizard.py:124 msgid "code" msgstr "código" #: spyder/widgets/variableexplorer/importwizard.py:127 #: spyder/widgets/variableexplorer/importwizard.py:514 msgid "text" msgstr "texto" #: spyder/widgets/variableexplorer/importwizard.py:140 msgid "Column separator:" msgstr "Separador de colunas:" #: spyder/widgets/variableexplorer/importwizard.py:144 msgid "Tab" msgstr "Tabulação" #: spyder/widgets/variableexplorer/importwizard.py:147 #, fuzzy msgid "Whitespace" msgstr "Espaço de trabalho" #: spyder/widgets/variableexplorer/importwizard.py:150 #: spyder/widgets/variableexplorer/importwizard.py:168 msgid "other" msgstr "outro" #: spyder/widgets/variableexplorer/importwizard.py:161 msgid "Row separator:" msgstr "Separador de linha:" #: spyder/widgets/variableexplorer/importwizard.py:165 msgid "EOL" msgstr "Fim de linha" #: spyder/widgets/variableexplorer/importwizard.py:180 msgid "Additional options" msgstr "Opções adicionais" #: spyder/widgets/variableexplorer/importwizard.py:184 msgid "Skip rows:" msgstr "Pular linhas:" #: spyder/widgets/variableexplorer/importwizard.py:195 msgid "Comments:" msgstr "Comentários:" #: spyder/widgets/variableexplorer/importwizard.py:201 msgid "Transpose" msgstr "Transpor" #: spyder/widgets/variableexplorer/importwizard.py:441 msgid "array" msgstr "matriz" #: spyder/widgets/variableexplorer/importwizard.py:446 msgid "list" msgstr "lista" #: spyder/widgets/variableexplorer/importwizard.py:451 msgid "DataFrame" msgstr "DataFrame" #: spyder/widgets/variableexplorer/importwizard.py:497 #: spyder/widgets/variableexplorer/importwizard.py:581 msgid "Import wizard" msgstr "Assistente de importação" #: spyder/widgets/variableexplorer/importwizard.py:502 msgid "Raw text" msgstr "Texto sem formatação" #: spyder/widgets/variableexplorer/importwizard.py:505 msgid "variable_name" msgstr "nome_da_variável" #: spyder/widgets/variableexplorer/importwizard.py:516 msgid "table" msgstr "tabela" #: spyder/widgets/variableexplorer/importwizard.py:517 msgid "Preview" msgstr "Pré-Visualização" #: spyder/widgets/variableexplorer/importwizard.py:521 msgid "Variable Name" msgstr "Nome da variável" #: spyder/widgets/variableexplorer/importwizard.py:544 msgid "Done" msgstr "Feito" #: spyder/widgets/variableexplorer/importwizard.py:582 msgid "" "Unable to proceed to next step

Please check your entries." "

Error message:
%s" msgstr "" "Não foi possível prosseguir para o próximo passo

Por favor " "revise seus dados

Mensagem de erro:
%s" #: spyder/widgets/variableexplorer/namespacebrowser.py:181 #: spyder/widgets/variableexplorer/namespacebrowser.py:385 msgid "Import data" msgstr "Importar data" #: spyder/widgets/variableexplorer/namespacebrowser.py:184 #: spyder/widgets/variableexplorer/namespacebrowser.py:465 #: spyder/widgets/variableexplorer/namespacebrowser.py:479 msgid "Save data" msgstr "Salvar data" #: spyder/widgets/variableexplorer/namespacebrowser.py:189 msgid "Save data as..." msgstr "Salvar data como..." #: spyder/widgets/variableexplorer/namespacebrowser.py:201 msgid "Exclude references which name starts with an underscore" msgstr "Excluir variáveis cujo nomes comecem com sublinhado" #: spyder/widgets/variableexplorer/namespacebrowser.py:209 msgid "Exclude references which name is uppercase" msgstr "" "Excluir variáveis cujo nome esteja\n" "completamente em maiúsculas" #: spyder/widgets/variableexplorer/namespacebrowser.py:216 msgid "Exclude references which name starts with an uppercase character" msgstr "Excluir variáveis cujo nome comece com maiúsculas. " #: spyder/widgets/variableexplorer/namespacebrowser.py:224 msgid "" "Exclude references to unsupported data types (i.e. which won't be handled/" "saved correctly)" msgstr "" "Excluir variáveis que guardam tipos de dados não suportados\n" "(aqueles que não podem ser manipulados e armazenados\n" " corretamente)" #: spyder/widgets/variableexplorer/namespacebrowser.py:405 msgid "" "Unsupported file extension '%s'

Would you like to import it " "anyway (by selecting a known file format)?" msgstr "" "Tipo de arquivo não suportado '%s'

Deseja importar mesmo assim " "(selecionando um formato conhecido)?" #: spyder/widgets/variableexplorer/namespacebrowser.py:413 msgid "Open file as:" msgstr "Abrir arquivo como:" #: spyder/widgets/variableexplorer/namespacebrowser.py:447 msgid "Unable to load '%s'

Error message:
%s" msgstr "Não foi possível carregar '%s'

Mensagem de erro:
%s" #: spyder/widgets/variableexplorer/namespacebrowser.py:480 msgid "Unable to save current workspace

Error message:
%s" msgstr "" "Não foi possível salvar o espaço de trabalho atual

Mensagem de " "erro:
%s" #: spyder/widgets/variableexplorer/texteditor.py:74 msgid "Text editor" msgstr "Editor de texto" #: spyder/widgets/variableexplorer/utils.py:30 msgid "View and edit DataFrames and Series in the Variable Explorer" msgstr "Ver e editar DataFrames e Series no Explorador de Variáveis" #: spyder/widgets/variableexplorer/utils.py:35 msgid "View and edit two and three dimensional arrays in the Variable Explorer" msgstr "" "Ver e editar duas e três matrizes dimensionais no Explorador de Variáveis" #: spyder/workers/updates.py:90 spyder/workers/updates.py:92 msgid "Unable to retrieve information." msgstr "Não foi possível receber a informação." #: spyder/workers/updates.py:94 msgid "" "Unable to connect to the internet.

Make sure the connection is " "working properly." msgstr "" "Não foi possível conectar a internet.

Tenha certeza se a conexão " "está realmente funcionando." #: spyder/workers/updates.py:97 msgid "Unable to check for updates." msgstr "Não foi possível verificar por atualizações." #, fuzzy #~ msgid "At startup, the current working directory is:" #~ msgstr "Ao iniciar, o diretório de trabalho global é:" #, fuzzy #~ msgid "At startup," #~ msgstr "Inicialização" #, fuzzy #~ msgid "At startup, the current working directory will be the specified path" #~ msgstr "Ao iniciar o diretório de trabalho será o seguinte" #~ msgid "Reset namespace" #~ msgstr "Resetar namespace" #~ msgid "Reset IPython namespace" #~ msgstr "Resetar IPython namespace" #~ msgid "Loading external console..." #~ msgstr "Carregando console externo..." #~ msgid "The Python console" #~ msgstr "O Console Python" #~ msgid "" #~ "You can also run your code on a Python console. These consoles are useful " #~ "because they let you run a file in a console dedicated only to it.To " #~ "select this behavior, please press the F6 key.

By pressing " #~ "the button below and then focusing the Variable Explorer, you will notice " #~ "that Python consoles are also connected to that pane, and that the " #~ "Variable Explorer only shows the variables of the currently focused " #~ "console." #~ msgstr "" #~ "Você também pode executar seu código em um console Python. Estes consoles " #~ "são úteis porque permitem que você execute um arquivo em um console " #~ "dedicado apenas para ele. Para selecionar este comportamento por favor " #~ "pressione a tecla F6.

Apertando o botão abaixo e indo no " #~ "Explorador de Variáveis você irá notar que os consoles Python também " #~ "estão conectados a este painel e que o Explorador de Variáveis só mostra " #~ "as variáveis do console atual." #~ msgid "Sort files according to full path" #~ msgstr "Ordenar arquivos seguindo seu caminho completo" #~ msgid "&Configure..." #~ msgstr "&Configurar..." #~ msgid "Show TODO/FIXME/XXX/HINT/TIP/@todo comments list" #~ msgstr "" #~ "Mostrar a lista de comentários dos\n" #~ "TODO/FIXME/XXX/HINT/TIP/@todo" #~ msgid "Interactive data plotting in the consoles" #~ msgstr "Mostra dados interativos no console" #~ msgid "Python console" #~ msgstr "Console Python" #~ msgid "One tab per script" #~ msgstr "Uma aba por script" #~ msgid "Buffer: " #~ msgstr "Buffer:" #~ msgid "Merge process standard output/error channels" #~ msgstr "Combinar os canais de saída/erro do processo" #~ msgid "" #~ "Merging the output channels of the process means that\n" #~ "the standard error won't be written in red anymore,\n" #~ "but this has the effect of speeding up display." #~ msgstr "" #~ "Combinar os canais de saída do processo significa que\n" #~ "o erro padrão não será escrito em vermelho, mas isso ajuda a\n" #~ "melhorar a velocidade em que aparece o texto no console." #~ msgid "Colorize standard error channel using ANSI escape codes" #~ msgstr "Colorir o canal de error padrão utilizando códigos de escape ANSI " #~ msgid "" #~ "This method is the only way to have colorized standard\n" #~ "error channel when the output channels have been merged." #~ msgstr "" #~ "Este método é a única forma de ter cor no canal de erro\n" #~ "padrão quando os canais de saída forem combinados." #~ msgid "" #~ "This option will be applied the next time a Python console or a terminal " #~ "is opened." #~ msgstr "" #~ "Esta opção será ativada na próxima vez que um console Python ou um " #~ "terminal for aberto." #~ msgid "Light background (white color)" #~ msgstr "Fundo claro (cor branca)" #~ msgid "PYTHONSTARTUP replacement" #~ msgstr "Substituto do PYTHONSTARTUP" #~ msgid "" #~ "This option will override the PYTHONSTARTUP environment variable which\n" #~ "defines the script to be executed during the Python console startup." #~ msgstr "" #~ "Esta opção modificará a variável de ambiente PYTHONSTARTUP, a qual\n" #~ "define o script que é executado durante a inicialização do console\n" #~ "Python." #~ msgid "Default PYTHONSTARTUP script" #~ msgstr "Script PYTHONSTARTUP padrão" #~ msgid "Use the following startup script:" #~ msgstr "Usar o seguinte script de inicialização:" #~ msgid "Monitor" #~ msgstr "Monitor" #~ msgid "" #~ "The monitor provides introspection features to console: code completion, " #~ "calltips and variable explorer. Because it relies on several modules, " #~ "disabling the monitor may be useful to accelerate console startup." #~ msgstr "" #~ "O monitor fornece características de introspecção para o console: " #~ "completador de código, sugestões e o explorador de variáveis. Porque ele " #~ "depende de vários módulos adicionais, desativando o monitor é possível " #~ "acelerar a inicialização do console." #~ msgid "Enable monitor" #~ msgstr "Ativar monitor" #~ msgid "Default library" #~ msgstr "Biblioteca padrão" #~ msgid "Qt-Python Bindings" #~ msgstr "Integração Qt-Python" #~ msgid "Library:" #~ msgstr "Biblioteca:" #~ msgid "" #~ "This option will act on
libraries such as Matplotlib, guidata or ETS" #~ msgstr "" #~ "Esta opção trará efeitos
em bibliotecas como Matplotlib, guidata ou " #~ "ETS" #~ msgid "" #~ "Decide which backend to use to display graphics. If unsure, please select " #~ "the Automatic backend.

Note: We support a very " #~ "limited number of backends in our Python consoles. If you prefer to work " #~ "with a different one, please use an IPython console." #~ msgstr "" #~ "Decidir qual saída usar para mostrar gráficos. Se não possui certeza, por " #~ "favor selecione a saída Automática.

Nota: Suportamos " #~ "um número muito limitado de saídas nos consoles Python. Se você preferir " #~ "preferir trabalhar com uma diferente utilize um console IPython." #~ msgid "None" #~ msgstr "Nenhum" #~ msgid "Enthought Tool Suite" #~ msgstr "Enthought Tool Suite" #~ msgid "" #~ "Enthought Tool Suite (ETS) supports PyQt4 (qt4) and wxPython (wx) " #~ "graphical user interfaces." #~ msgstr "" #~ "Enthought Tool Suite (ETS) suporta as bibliotecas gráficas PyQt4 (qt4) " #~ "e \n" #~ "wxPython (wx)." #~ msgid "ETS_TOOLKIT:" #~ msgstr "ETS_TOOLKIT:" #~ msgid "External modules" #~ msgstr "Módulos externos" #~ msgid "" #~ "No Python console is currently selected to run %s.

Please " #~ "select or open a new Python console and try again." #~ msgstr "" #~ "Nenhum console Python foi selecionado para executar %s.

Por " #~ "favor selecione ou abra um novo console Python e tente novamente." #~ msgid "" #~ "%s is already running in a separate process.\n" #~ "Do you want to kill the process before starting a new one?" #~ msgstr "" #~ "%s já está sendo executado em um processo separado.\n" #~ "Você deseja matar o processo antes de iniciar um novo?" #~ msgid "Command Window" #~ msgstr "Janela de comando" #~ msgid "Open a &Python console" #~ msgstr "Abrir um console &Python" #~ msgid "Open &command prompt" #~ msgstr "Abrir &prompt de comando" #~ msgid "Open a Windows command prompt" #~ msgstr "Abrir o prompt de comando do Windows" #~ msgid "Open a &terminal" #~ msgstr "Abrir um &terminal" #~ msgid "Open a terminal window" #~ msgstr "Abrir uma janela de terminal" #~ msgid "Python Console" #~ msgstr "Console Python" #~ msgid "Light background" #~ msgstr "Fundo claro" #~ msgid "Dark background" #~ msgstr "Fundo escuro" #~ msgid "Working directory:" #~ msgstr "Diretório de trabalho:" #~ msgid "Dedicated Python console" #~ msgstr "Console do Python dedicado" #~ msgid "Show warning when killing running process" #~ msgstr "Mostrar um aviso quando matar o processo" #~ msgid "Run Settings" #~ msgstr "Opções de execução" #~ msgid "the script directory" #~ msgstr "Diretório do script atual" #~ msgid "Show warning when killing running processes" #~ msgstr "Mostrar aviso quando um processo em execução for morto" #~ msgid "Autorefresh" #~ msgstr "Atualizar automaticamente" #~ msgid "Enable autorefresh" #~ msgstr "Ativar atualização automatica" #~ msgid "Refresh interval: " #~ msgstr "Intervalo de atualização" #~ msgid "" #~ "The global working directory is the working directory for newly " #~ "opened consoles (Python/IPython consoles and terminals), for the " #~ "file explorer, for the find in files plugin and for new " #~ "files created in the editor." #~ msgstr "" #~ "O diretório de trabalho global é o diretório de trabalho para os " #~ "consoles recém abertos (do IPython/Python e dos terminais), para o " #~ "Explorador de arquivos, Buscar em arquivos e para os novos " #~ "arquivos criados no Editor." #~ msgid "the same as in last session" #~ msgstr "O mesmo da última sessão" #~ msgid "" #~ "At startup, Spyder will restore the global directory from last session" #~ msgstr "" #~ "Ao iniciar o Spyder irá restaurar o diretório global da última sessão" #~ msgid "Files are opened from:" #~ msgstr "Os arquivos são abertos de:" #~ msgid "the current file directory" #~ msgstr "O diretório do arquivo atual" #~ msgid "the global working directory" #~ msgstr "O diretório de trabalho global" #~ msgid "Files are created in:" #~ msgstr "Os arquivos são criados em:" #~ msgid "Change to file base directory" #~ msgstr "Mudar para diretório base do arquivo" #~ msgid "When opening a file" #~ msgstr "Ao abrir um arquivo" #~ msgid "When saving a file" #~ msgstr "Ao salvar um arquivo" #~ msgid "Global working directory" #~ msgstr "Diretório de trabalho global" #~ msgid "Unable to save script '%s'

Error message:
%s" #~ msgstr "" #~ "Não foi possível salvar o script '%s'

Mensagem de erro:
" #~ "%s" #~ msgid "Run again this program" #~ msgstr "Executar novamente este programa" #~ msgid "Kill" #~ msgstr "Matar" #~ msgid "Kills the current process, causing it to exit immediately" #~ msgstr "Matar o processo atual, fazendo ele fechar imediatamente" #~ msgid "Running..." #~ msgstr "Executando..." #~ msgid "Terminated." #~ msgstr "Finalizado." #~ msgid "Command line arguments:" #~ msgstr "Argumentos da linha de comando:" #~ msgid "Variables" #~ msgstr "Variáveis" #~ msgid "Show/hide global variables explorer" #~ msgstr "Mostrar/esconder o explorador de variáveis " #~ msgid "Terminate" #~ msgstr "Finalizar" #~ msgid "" #~ "Attempts to stop the process. The process\n" #~ "may not exit as a result of clicking this\n" #~ "button (it is given the chance to prompt\n" #~ "the user for any unsaved files, etc)." #~ msgstr "" #~ "Tentativa de parar este processo, mas este\n" #~ "pode não ser concluído se esse botão for pressionado\n" #~ "(pode ser possível que se peça ao usuário\n" #~ "para guardar arquivos ainda não salvos, etc)." #~ msgid "Interact" #~ msgstr "Interagir" #~ msgid "Debug" #~ msgstr "Depurar" #~ msgid "Arguments..." #~ msgstr "Argumentos..." #~ msgid "Post Mortem Debug" #~ msgstr "Post Mortem Debug" #~ msgid "Arguments: %s" #~ msgstr "Argumentos: %s" #~ msgid "No argument" #~ msgstr "Sem argumento" #~ msgid "A Python console failed to start!" #~ msgstr "Não foi possível iniciar um console Python!" #~ msgid "Process failed to start" #~ msgstr "O processo falhou ao iniciar." #~ msgid "Included filenames pattern" #~ msgstr "" #~ "Incluir padrões de nomes\n" #~ "do arquivo" #~ msgid "Include:" #~ msgstr "Incluir:" #~ msgid "PYTHONPATH" #~ msgstr "PYTHONPATH" #~ msgid "" #~ "Search in all directories listed in sys.path which are outside the Python " #~ "installation directory" #~ msgstr "" #~ "Procurar em todos diretórios listados na sys.path\n" #~ "que estão fora do diretório de instalação do Python" #~ msgid "Hg repository" #~ msgstr "Repositório Hg" #~ msgid "Search in current directory hg repository" #~ msgstr "Buscar no repositório" #~ msgid "Here:" #~ msgstr "Aqui:" #~ msgid "Search recursively in this directory" #~ msgstr "Buscar recursivamente neste diretório" #~ msgid "Browse a search directory" #~ msgstr "Selecionar um diretório de busca" #~ msgid "Search canceled" #~ msgstr "Busca cancelada" #~ msgid "interrupted" #~ msgstr "interrompido" #~ msgid "" #~ "Inspecting and setting values while debugging in IPython consoles is not " #~ "supported yet by Spyder." #~ msgstr "" #~ "Inspecionar e introduzir valores enquanto se estar debugando em consoles " #~ "IPython ainda não é suportado pelo Spyder." #~ msgid "Refresh" #~ msgstr "Atualizar" #~ msgid "Refresh periodically" #~ msgstr "Atualizar periodicamente" #~ msgid "Python(x,y)" #~ msgstr "Python(x,y)" #~ msgid "Python(x,y) launcher" #~ msgstr "Lançador do Python(x,y)" #~ msgid "Python(x,y) documentation folder" #~ msgstr "Pasta de documentação do Python(x,y)" #~ msgid "guidata documentation" #~ msgstr "Documentação do guidata " #~ msgid "guiqwt documentation" #~ msgstr "Documentação do guiqwt" #~ msgid "NumPy documentation" #~ msgstr "Documentação do NumPy" #~ msgid "NumPy reference guide" #~ msgstr "Guia de referência do NumPy" #~ msgid "NumPy user guide" #~ msgstr "Guia do usuário do NumPy" #~ msgid "SciPy documentation" #~ msgstr "Documentação do SciPy" #~ msgid "Show/hide project explorer" #~ msgstr "Mostrar/esconder o explorador de projetos" #~ msgid "?" #~ msgstr "?" #~ msgid "Use %s+T when the console is selected to open a new one" #~ msgstr "" #~ "Utilize %s+T quando o console estiver selecionado para abrir um novo" #~ msgid "Edit data in the remote process" #~ msgstr "Editar dados em um processo remoto" #~ msgid "" #~ "Editors are opened in the remote process for NumPy arrays, PIL images, " #~ "lists, tuples and dictionaries.\n" #~ "This avoids transfering large amount of data between the remote process " #~ "and Spyder (through the socket)." #~ msgstr "" #~ "Esta opção permite modificar matrizes do NumPY, imagens do PIL, listas, " #~ "tuplas e\n" #~ "dicionários em um processo remoto. Isto impede a transferência de grandes " #~ "quantidades de dados\n" #~ "entre o processo remoto e o Spyder." #~ msgid "Array is empty" #~ msgstr "A matriz está vazia" #~ msgid "Object %s is not picklable" #~ msgstr "O objeto %s não é picklable" #~ msgid "" #~ "\n" #~ "\n" #~ "{0}" #~ msgstr "" #~ "\n" #~ "\n" #~ "{0}" #~ msgid "Truncate values" #~ msgstr "Abreviar valores" spyder-3.2.6/spyder/locale/ja/0000775000175000017500000000000013225025006016754 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/locale/ja/LC_MESSAGES/0000775000175000017500000000000013225025007020542 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/locale/ja/LC_MESSAGES/spyder.mo0000664000175000017500000033455613224121062022422 0ustar carloscarlos000000000000007!CZY Zwc[\ \ ] ]#]>]G]N]R] q] {]]]]]]] ]] ]] ] ]^ ^^!^)^.^6^<^D^K^Q^Z^c^l^u^~^^W^b^<K_"_x_4$`Y`xaFbDVc9cAcBdDZdQd1d6#e;Ze7eceB2f7ufCf;f8-gtfg!ggh&j!j;jljr'Ɓ+aQQ߂"1)T(~'σ  + D N\ z3„ ҄ ׅ  ,:ZWȆ %DZ_*7@^} &̈ !,=L \}ى> 8 FT erz   .ˊ  < I S^eMkm'?F_!x Ō -> W e&q*ލ .@HMU= ( 6@Wn  ʐ א #&9` r}{Jƒ  ̔{ڔV ]~ ǖ ֖ %C0Y ї *<KP=&ژ1`3I9ޙd<} ؚ͚ *.3FOXk!4 <HY_f Ɯߜ &=Y;u ʝ ם>#*8cr w Ӟ!T7=u   ɠѠ ٠  4 = H S ] iw ǡgڡB"]  &  0B IUY ,/8h mz:ߤ & 0> O\ oB|ǥϥ ޥ "+JP$e&P+w  çΧMާ,2B%uRC237 k x+"ë!ʬ * ;H \i}խ  !.AP_n}  Үޮ116LUg{%ʯ+$94>s %ɰ5 %1D[ b mw *±   #D\n ²βֲ 5!Rt 'ճ# 7BV_t}75) 2 >L jw ,Dĵ  $$3 XcsE  1 ;HYm- ƷηԷ" E!Rg1ظ  $2P_ hs ù5ҹ'0NUl#º=|WԻ>42^gƼۼ6 ?M_8o½ ׽ \9xƾ"ؾLHdvDֿ =Og  4 O[`e lw} !%#7 M[4<N8M=_89&9N`ptSH P] ep u ,  !=Mbs+ C:#^ o{  =:.i  .fD1Nl(ChF+Lx;':c *iTl-Y[  Wp]n&>{P#/7Mg   &0LRW[X& &"[29 !%3Yq}7= DRds<G\*d#  }ap ns$;1ImxA   .>E`fk s~ )  # ,9B Yg)x0 - KU es    -8 OZ t kh?=4rX c2Cqckg]7]^ARORX7cLdX1O07;7sJ*g 3 [  ) < %U N{        t%    W +D p 9[<30ELe:x*<;W^g T^e {9!<673n9  ' 9F_!f   )?9^yO Ybr.0 0*,[!'<!Df*v6/:!Y{-!2!Np /1So!% 9# ] k yQXw !6O_~ *!!69M3  $9!^?     & !0 R n & W!*"!."P"j"P"Q"+'#S#[#b#!{# # # ##B#$$=$*V$$3&%_Z%Z%3&<I&3&'&!&'#'*'1'5''<'*d'''3'' '@ ($M(r((q)0)))))#)n* ** *=***$+3+bM+$+0+$,'+,S,*[,,',*,!,-3-C-b-r----!-!-*. F.NS.$.$../$/4/D/U/f/'|//K/0!02>0q000 0 00I1*1 2' 2'H2Ap22222$2 #3-3>3 E3R3n3$~33 303!304!E4g4}44*444 4 4#5)6 7?7X7_7u7777 77788 $8 .8;8K8S8j88+888 89':<$=*=F=*_===?3????@@@$/@T@k@*r@0@@@0A33A!gAAAAAAAB!'BIBeB[{B8B*C0;ClCDDOVDeDK EXE hEsEEEE-EEF F'F`*Q`|`*```` a$a4aJa faa aaaa bbl ňЈ'׈  0C S`yEE؉ $Ŋ _--'":Ju(d[>@ 6a*F7K'66rmieZrQeZyxv  )6< R \i- $*{ܧ$X} J9Wg[$ W!iɪ0ߪ00P,2_c hr !-!->HMFݭF+$Diz  $ίѰ {9>(;QX _ i s}  ѷ۷   $ '81 jw  ȸ$6I `E^Y Ti2f\!s"iL?'j&9CmH9S >1ln ;2+@r>g|XO'b}8T6l1qB <$Ed`FCge:#>or5 jkx"avEU{h 3oog a,aMMdX] $B[n-I[I!3-y`m5Oh \H'$~0x^D JR;y6Uf[t#P.jR0./ ~DcW4Q(Pp  -=7*H6G|9G%e!\{a ;2!z/ .b5P"17q<)w,D*J)4}4."+MnZw\_AG$F|%vR<&14Txs>'J(F Y)!SY#ww h0u3m}_S#&i I 0t-C4DVfyA3mN, QN6c[@(9Nt:qu=p(]LZ2`-,%u+l$3/V eQV+=xfpL7 5nKpIT1lbvRU*rz:*&Z0hugCrEvA8BO+jSe%{b|)^kM*"7?  z Adt%/^oB5K(Q~W']=cUJkW c&K?GK O]`kizVy?Z NPs6<:X@.Y~7,sX#}{ 28FW/;qH d8@L__) Numpy Array/Matrix Helper
Enter an array in the table.
Use Tab to move between cells.

Hit 'Enter' for array or 'Ctrl+Enter' for matrix.

Hint:
Use two tabs at the end of a row to move to the next row. Numpy Array/Matrix Helper
Type an array in Matlab : [1 2;3 4]
or Spyder simplified syntax : 1 2;3 4

Hit 'Enter' for array or 'Ctrl+Enter' for matrix.

Hint:
Use two spaces or two tabs to generate a ';'. Searching for files... Installed Required Scanning: {0} Searching for files in folder: {0} entries lines ms%s are currently not supported%s arrays%s editor&Close&Configuration per file...&Debug&Edit&File&Find in files&Find text&Help&New file...&Open...&Print...&Projects&Quit&Replace text&Restart&Revert&Run&Run...&Save&Search&Tools&View2 spaces3 spaces4 spaces5 spaces6 spaces7 spaces8 spaces%s contains mixed end-of-line characters.
Spyder will fix this automatically.%s has been modified outside Spyder.
Do you want to reload it and lose all your changes?%s has been modified.
Do you want to save changes?%s is not a Spyder project!%s is unavailable (this file may have been removed, moved or renamed outside Spyder).
Do you want to close it?-u is added to the other options you set hereSpyder %s is available!

Please use your package manager to update Spyder or go to our
Releases page to download this new version.

If you are not sure how to proceed to update Spyder please refer to our Installation instructions.Spyder has encountered a problem.
Sorry for the inconvenience.

You can automatically submit this error to our Github issues tracker.

Note: You need a Github account for that.Spyder is a powerful Interactive Development Environment (or IDE) for the Python programming language.

Here we are going to guide you through its most important features.

Please use the arrow keys or click on the buttons below to move along the tour.Spyder is an interactive development environment based on blaUnable to %s %s

Error message:
%sUnable to assign data to item.

Error message:
%sUnable to create file %s

Error message:
%sUnable to create folder %s

Error message:
%sUnable to delete {varpath}

The error message was:
{error}Unable to find external program.

%sUnable to load '%s'

Error message:
%sUnable to move %s

Error message:
%sUnable to plot data.

Error message:
%sUnable to proceed to next step

Please check your entries.

Error message:
%sUnable to rename file %s

Error message:
%sUnable to save array

Error message:
%sUnable to save current workspace

Error message:
%sUnable to save file '%s'

Error message:
%sUnable to show image.

Error message:
%sUnsupported file extension '%s'

Would you like to import it anyway (by selecting a known file format)?Unsupported file type '%s'Warning:
The Python module rope is not installed on this computer: calltips, code completion and go-to-definition features won't be available.You have missing dependencies!

%s

Please install them to avoid this message.

Note: Spyder could work without some of these dependencies, however to have a smooth experience when using Spyder we strongly recommend you to install all the listed missing dependencies.

Failing to install these dependencies might result in bugs. Please be sure that any found bugs are not the direct result of missing dependencies, prior to reporting a new issue.

Removing all variables...

Restarting kernel...


IMPORTANT NOTE: It seems that you are using Spyder with Anaconda/Miniconda. Please don't use pip to update it as that will probably break your installation.

Instead, please wait until new conda packages are available and use conda to perform the update.
(Refer to the {} page)

If enabled, Python source code will be analyzed using pycodestyle, lines that are not following PEP8 style guide will be highlighted.

Note: add analysis:ignore in a comment to ignore style analysis warnings.

If enabled, Python source code will be analyzed using pyflakes, lines containing errors or warnings will be highlighted.

Note: add analysis:ignore in a comment to ignore code analysis warnings.

Warning: changes are applied separatelyA compound sequence can have {break} a maximum of 4 subsequences.{break}About %sAbout %s...Activate supportAdd &block commentAdd block comment around current line or selectionAdd pathAdditional featuresAdditional optionsAddress:Advanced SettingsAdvanced settingsAll changes to %s will be lost.
Do you want to revert file from disk?All filesAll files (*)All files (*.*)All user-defined variables will be removed. Are you sure you want to proceed?Always show %s on a first file runAn error occurred while creating a socket needed by Spyder. Please, try to run as an Administrator from cmd.exe the following command and then restart your computer:

netsh winsock reset
An error ocurred while starting the kernelAnalysisAnimated toolbars and panesAppearanceAre you sure you want to delete this scheme?Are you sure you want to restart the kernel?ArgumentsArray dimensions not validArray editorArrays with more than 3 dimensions are not supportedAsk for confirmation before closingAsk for confirmation before removing all user-defined variablesAttached console window (debugging)AttributeAutocallAutocall makes IPython automatically call any callable object even if you didn't type explicit parentheses.
For example, if you type str 43 it becomes str(43) automatically.Autocall: AutomaticAutomatic code completionAutomatic connectionsAutomatic importAutomatic indentation after 'else', 'elif', etc.Automatic insertion of closing quotesAutomatic insertion of colons after 'for', 'if', 'def', etcAutomatic insertion of parentheses, braces and bracketsAutomatically load Pylab and NumPy modulesAutomatically remove trailing spaces when saving filesAxis:BackBackend:BackgroundBackground colorBackground:Batch filesBoldBreakpointBrowseBrowse a working directoryBrowse repositoryBrowse tabsBufferBuffer...Buffer: Builtin:C filesC&lose allC&onsolesC++ filesCPU and memory usage info in the status barCPU usage status: requires the `psutil` (>=v0.3) libraryCPU:CSV text filesCancelCannot restart a kernel not started by Spyder Carriage return (Mac)Carriage return and line feed (Windows)Case SensitiveCase sensitive code completionCell starts at line %sChange to lowercase current line or selectionChange to parent directoryChange to uppercase current line or selectionChanging backend to Qt for MayaviCheck for updates on startupCheck for updates...Class defined at line %sClear all ouputClear breakpoints in all filesClear consoleClear lineClear line or blockClear recent files listClear shellClear shell contents ('cls' command)Clear this listClipboard contentsClose ProjectClose all but thisClose all opened filesClose all to the rightClose current fileClose current paneClose current tabClose this panelClose this windowClose windowClosing SpyderCodeCode Introspection/AnalysisCode analysisCode analysis requires pyflakes %s+Code annotations (TODO, FIXME, XXX, HINT, TIP, @todo, HACK, BUG, OPTIMIZE, !!!, ???)Collapse allCollapse selectionColor scheme editorColumn min/maxColumn separator:Column:Command line options:CommentComment current line or selectionComment:Comments:CommitCompletion TypeCompletion:Condition:Configuration filesConfiguration for high DPI screens

Please see {0}<> for more information about these options (in English).ConflictsConnect to an existing kernelConnecting to kernel...Connection errorConnection info:ConsoleConsole directoryConsole helpContextContinueContinue execution until next breakpointConversion errorConvert end-of-line charactersConvert to Python scriptCopyCopy path to clipboardCopy to clipboardCopy without promptsCould not connect to remote hostCould not open ssh tunnel. The error was: CreateCreate a new editor windowCreate new projectCreate new schemeCurrent cell:Current line:Current shortcut:Current user environment variables...Current working directoryCurrently used to delete lines on editorCursor blinking:Custom margin for panes:CutCython/Pyrex filesDataDataFrameDebug fileDebug toolbarDebug with winpdbDecide how graphics are going to be displayed in the console. If unsure, please select %s to put graphics inside the console or %s to interact with them (through zooming and panning) in a separate window.Decide how to render the figures created by this backendDecide what type of completion to useDefault (i.e. the same as Spyder's)Default is 4Default is 6Default is
In [<span class="in-prompt-number">%i</span>]:Default is
Out[<span class="out-prompt-number">%i</span>]:Default working directory is:Definition:DeleteDelete LayoutDelete ProjectDelete...DependenciesDependencies...DictionaryDirectly enter debugging when errors appearDisplayDisplay balloon tipsDisplay initial bannerDo you really want to delete %s?Do you really want to delete {filename}?

Note: This action will only delete the project. Its files are going to be preserved on disk.Do you really want to remove selected path?Do you really want to rename %s and overwrite the existing file %s?Do you want to close all other consoles connected to the same kernel as this one?Do you want to close this console?Do you want to remove all selected items?Do you want to remove the selected item?Do you want to reset to default values?Do you wish to restart now?Don't show again.DoneDuplicateEOLEditEdit filename filtersEdit filename filters...Edit itemEdit selectedEdit template for new modulesEdit toolbarEditorEditor's code completion, go-to-definition and helpEmpty clipboardEmpty projectEnable Tab completion on elements of lists, results of function calls, etc, without assigning them to a variable.
For example, you can get completions on things like li[0].<Tab> or ins.meth().<Tab>Enable UMREnable auto high DPI scalingEnaml filesEncoding:End-of-line charactersEnd-of-lines:Enter key selects completionEnter values for different screens separated by semicolons ';', float values are supportedEnvironment variablesEnvironment variables...ErrorError restarting kernel: %s Exclude all-uppercase referencesExclude capitalized referencesExclude private referencesExclude references to unsupported data types (i.e. which won't be handled/saved correctly)Exclude references which name is uppercaseExclude references which name starts with an underscoreExclude references which name starts with an uppercase characterExclude unsupported data typesExclude:Excluded filenames patternExecutablesExecute in a dedicated consoleExecute in an external system terminalExecute in current consoleExisting directoryExpand allExpand selectionExternal ToolsExternal editorExternal editor executable path:External editor path...External editor:External system terminalFast switch between filesFast symbol search in fileFileFile %s already exists.
Do you want to overwrite it?File ExplorerFile explorerFile switcher...File toolbarFile...FilterFind &nextFind &previousFind in filesFind symbols in file...Find textFix automatically and show warning message boxFix indentationFloat formattingFolder %s already exists.Folder name:Folder...Font styleFont: FontsFor %s support, please install one of the
following tools:

%sFor performance reasons, changes applied to masked array won't be reflected in array's data (and vice-versa).Forbidden key sequence!FormatFormat (%s) is incorrectFormat ({}) is incorrectFormat ({}) should start with '%'Format:Fortran filesFullFullscreen modeFunction defined at line %sGIF imagesGUI-based editor:GeneralGeneral settingsGo to cursor positionGo to definitionGo to last edit locationGo to line...Go to line:Go to next code analysis warning/errorGo to next cursor positionGo to previous code analysis warning/errorGo to previous cursor positionGo to step: GraphicalGraphicsGraphics backendGreedy completionHeight:HelpHelp...Here you can get help of any object by pressing %s in front of it, either on the Editor or the Console.%sHelp can also be shown automatically after writing a left parenthesis next to an object. You can activate this behavior in %s.Here you can select the color scheme used in the Editor and all other Spyder plugins.

You can also edit the color schemes provided by Spyder or create your own ones by using the options provided below.
Hide advanced optionsHide toolbarsHighlightHighlight current cellHighlight current lineHighlight matchesHighlight occurrences afterHistogramHistoryHistory depth: History logHistory logsHistory...HomeHost nameIDL filesIPythonIPython ConsoleIPython consoleIPython documentationIPython interactive python environmentIPython notebooksIcon themeIf enabled, pressing Tab will always indent, even when the cursor is not at the beginning of a line (when this option is enabled, code completion may be triggered using the alternate shortcut: Ctrl+Space)If this option is enabled, clicking on an object name (left-click + Ctrl key) will go this object definition (if resolved).If you accept changes, this will modify the current user environment variables directly in Windows registry. Use it with precautions, at your own risks.

Note that for changes to take effect, you will need to restart the parent process of this application (simply restart Spyder if you have executed it from a Windows shortcut, otherwise restart any application from which you may have executed it, like Python(x,y) Home for example)ImportImport asImport dataImport errorImport from clipboardImport wizardIn this pane you can view and edit the variables generated during the execution of a program, or those entered directly in one of Spyder consoles.

As you can see, the Variable Explorer is showing the variables generated during the last step of this tour. By doing a double-click on any of them, a new window will be opened, where you can inspect and modify their contents.IndentIndent current line or selectionIndentation characters: IndexIndex:InformationInitializing...InlineInline backendInput prompt:InsertInspect current objectInstalled Python modulesInstance:Integrate the IPython consoleIntelligent backspaceInteract with the Python console after executionInteractive toursInterfaceInternal consoleInternal console settingsInternal editor:Intro to IPythonIntroduction tourIntrospectionInvalid directory pathInvalid file pathInvalid key enteredIt was not possible to close the previous Spyder instance. Restart aborted.It was not possible to convert this notebook. The error is: It was not possible to copy this arrayIt was not possible to copy values for this arrayIt was not possible to generate rich text help for this object.
Please see it in plain text.It was not possible to remove outputs from this notebook. The error is: It was not possible to restart Spyder. Operation aborted.It was not possible to restart the IPython console when switching to this project. The error was {0}It was not possible to run this file in an external terminalItalicJPEG imagesJSON filesJavascript filesJson filesJulia filesKernel died, restartingKernel restartingKeyKey:Keyboard shortcutsKeyword:LanguageLast edit locationLayout %s will be overwritten. Do you want to continue?Layout Display and OrderLayout preferencesLine %sLine count:Line feed (UNIX)Line:Lines:Link to object definitionLink:ListLoading %s...Loading IPython console...Loading editor...Loading file explorer...Loading help...Loading history plugin...Loading namespace browser...Loading online help...Loading outline explorer...Loading project explorer...Loading this kind of data while debugging is not supported.LocationLockLock panesMATLAB filesMain toolbarMaintain focus in the Editor after running cells or selectionsManage color schemesManipulate Jupyter notebooks on the EditorMarkdown filesMaskMasked dataMatched
parens:Matlab filesMatplotlib documentationMaximize current paneMaximum entriesMaximum line countMaximum number of recent filesMaximum number of recent files...Memory usage status: requires the `psutil` (>=v0.3) library on non-Windows platformsMemory:Method defined at line %sModify how Input and Output prompts are shown in the console.ModuleModule pywin32 was not found.
Please restart this Windows session (not the computer) for changes to take effect.Module or package:Module...Move DownMove UpMove downMove to bottomMove to topMove upMove...NSIS filesNameName filters:NewNew Project...New directoryNew features in version 3.0New fileNew folderNew moduleNew name:New packageNew shortcut:New to Spyder? Read ourNew variable name:New windowNextNext cursor positionNext warning/errorNo IPython console is currently available to run %s.

Please open a new one and try again.No documentation availableNo further documentation availableNo matchesNo source code available.NormalNormal text:Nothing to be imported from clipboard.NumPy arrayNumPy arraysNumPy zip arraysNumber:Numpy and Scipy documentationO&pen last closedObjectOccurrence:OffOn %s mode, Autocall is not applied if there are no arguments after the callable. On %s mode, all callable objects are automatically called (even if no arguments are present).Online documentationOnline helpOnly used when the format is PNG. Default is 72OpenOpen &recentOpen IPython console hereOpen Project...Open a new IPython console connected to an existing kernelOpen an &IPython consoleOpen command prompt hereOpen connection fileOpen fileOpen file as:Open last closedOpen projectOpen terminal hereOpenCL filesOpening this variable can be slow Do you want to continue anyway?OptionsOutlineOutput prompt:PNG imagesPYTHONPATH managerPackage name:Package...PanesParentPasswordPassword or ssh key passphrasePastePatch and diff filesPath to connection file or kernel idPath to ssh key filePerfom symbolic operations in the console (e.g. integrals, derivatives, vector calculus, etc) and get the outputs in a beautifully printed style (it requires the Sympy module).Perform analysis only when saving filePerform analysis when saving file and everyPermissions:Pickle filesPlainPlain TextPlain text fontPlease consider installing Sphinx to get documentation rendered in rich text.Please enter the connection info of the kernel you want to connect to. For that you can either select its JSON connection file using the Browse button, or write directly its id, in case it's a local kernel (for example kernel-3764.json or just 3764).Please install matplotlib or guiqwt.Please introduce a different shortcutPlease note that these changes will be applied only to new Python/IPython consolesPlease note that these changes will be applied only to new consolesPlotPop up internal console when internal errors appearPre&ferencesPreferencesPreferences > HelpPress Enter to switch files or Esc to cancel.

Type to filter filenames.

Use :number to go to a line, e.g. main:42
Use @symbol_text to go to a symbol, e.g. @init

Press Ctrl+W to close current tab.
Press enter to validate this entryPress enter to validate this pathPress the new shortcut and select 'Ok': (Press 'Tab' once to switch focus between the shortcut entry and the buttons below it)PreviewPreviousPrevious cursor positionPrevious warning/errorPrint current file...Print preview...Printing...ProjectProject ExplorerProject PreferencesProject explorerProject nameProject preferencesProject typePrompt when exitingPromptsProvided featuresPyQt4 API ReferencePyQt4 Reference GuidePyQt5 API ReferencePyQt5 Reference GuidePython Path ManagerPython documentationPython filesPython help:Python interpreterPython packagePython projectPython scriptsPython versionPython2 documentationPython3 documentationQt DesignerQt LinguistQt documentationQt examplesQt windows styleQuick referenceQuick switch layout #%s has not yet been defined.QuitR&emove block commentRaw textRe run last cell Re-run &last scriptRe-run last cellReal-time code analysisReal-time code analysis on the EditorReal-time code style analysisReal-time code style analysis on the EditorRecent ProjectsRecord array fields:RedoRefresh list of module names available in PYTHONPATHRegular expressionRegular expression errorRemoval errorRemoveRemove all variablesRemove all variables before executionRemove comment block around current line or selectionRemove pathRemove references:Remove trailing spacesRenameRename tabRename...Render mathematical equationsReplace allReplace selectionReplace stringReplace tab characters by space charactersReplace with:Replace/find nextReport issue...ResetReset Spyder to factory defaultsReset to default valuesReset to defaultsReset to spyder defaultResetting Spyder to defaultsResizeResize rows to contentsResolution:RestartRestart kernelRestart kernel?RestartingRestoreRestore current paneRestore data on startupRestore original tree layoutRestore pane to its original sizeRevert file from diskRich TextRich text fontRow separator:RunRun &selection or current lineRun Cython files in the IPython ConsoleRun Python scriptRun Settings dialogRun a Python scriptRun a fileRun again last fileRun cellRun cell and advanceRun codeRun configurationRun configuration per fileRun current cell (Ctrl+Enter) [Use #%% to create cells]Run current cell and go to the next one (Shift+Enter)Run current lineRun fileRun script:Run selectionRun selection or current lineRun settingsRun settings for %sRun toolbarRun until current function or method returnsRunning an external system terminal is not supported on platform %s.Sav&e allSaveSave &as...Save all filesSave all files before running scriptSave arraySave copy as...Save copy of current file as...Save current file as...Save current history log (i.e. all inputs and outputs) in a text fileSave current layoutSave dataSave data as...Save data on exitSave fileSave historySave history logSave history log...Save non project files openedSaving data while debugging is not supported.Scheme name:Scheme:ScoreScreen resolutionScroll automatically to last entrySearchSearch directorySearch in all files and directories present on thecurrent Spyder pathSearch in all files and directories present on thecurrent project path (If opened)Search in current opened fileSearch in other folder present on the file systemSearch in:Search patternSearch stringSearch text in multiple filesSearch toolbarSearch: Select AllSelect a run configuration:Select directorySelect fileSelect other directorySelect ssh keySelect the Python interpreter for all Spyder consolesSet UMR excluded (not reloaded) modulesSet a custom high DPI scalingSet console working directorySet current console (and file explorer) working directory to current script directorySet external editor executable pathSet history maximum entriesSet maximum line countSet the list of excluded modules as this: numpy, scipySet the maximum number of lines of text shown in the console before truncation. Specifying -1 disables it (not recommended!)Set this for high DPI displaysSet this for high DPI displays when auto scaling does not workSet this to detach any
menu from the main windowSet this to open external
Python files in an already running instance (Requires a restart)Set/Clear breakpointSet/Edit conditional breakpointSetting up main window...SettingsShell special commands:ShortcutShortcut: {0}Shortcuts SummaryShortcuts resetShortcuts that use Shift and another key are unsupportedShow (read-only) sys.pathShow CPU usage everyShow SourceShow absolute pathShow advanced optionsShow all filesShow and edit current user environment variables in Windows registry (i.e. for all sessions)Show and edit environment variables (for current session)Show arrays min/maxShow blank spacesShow code analysis warnings/errorsShow comments list (TODO/FIXME/XXX/HINT/TIP/@todo/HACK/BUG/OPTIMIZE/!!!/???)Show current directory onlyShow elapsed timeShow environment variablesShow help for objects in the Editor and Consoles in a dedicated paneShow horizontal scrollbarShow icons and textShow imageShow in FinderShow in external file explorerShow line numbersShow memory usage everyShow reloaded modules listShow special commentsShow status barShow sys.path contentsShow sys.path contents...Show tab barShow todo listShow toolbarsShow vertical line afterShow warning/error listShow/hide outline explorerSide areas:SiftSizeSize: Skip rows:SmartSour&ceSourceSource codeSource toolbarSphinx %s is currently installed.Split horizontallySplit horizontally this editor windowSplit verticallySplit vertically this editor windowSpyder Default LayoutSpyder EditorSpyder Internal Console This console is used to report application internal errors and to inspect Spyder internals with the following commands: spy.app, spy.window, dir(spy) Please don't use it to run your code Spyder Keyboard ShortCutsSpyder could not reset to factory defaults. Restart aborted.Spyder data filesSpyder depends on several Python modules to provide the right functionality for all its panes. The table below shows the required and installed versions (if any) of all of them.

Note: You can safely use Spyder without the following modules installed: %s and %s.

Please also note that new dependencies or changed ones will be correctly detected only after Spyder is restarted.Spyder documentationSpyder exit errorSpyder is an interactive development environment based on blaSpyder is up to date.Spyder needs to restart to change the following setting:Spyder needs to restart to change the following settings:Spyder reset errorSpyder restart errorSpyder support...Spyder tutorialSpyder updatesSpyder was unable to retrieve the value of this variable from the console.

The error mesage was:
%sSpyder will restart and reset to default settings:

Do you want to continue?Ssh keyStart searchStartupStatus barStepStep IntoStep ReturnStep into function or method of current lineStopStop debuggingStop searchStop the current commandString not foundString:Submit to GithubSupport for graphics (Matplotlib)Supported filesSupported text filesSymbol finder...Symbolic MathematicsSymbolic mathematics in the IPython ConsoleSynchronizeSynchronize Spyder's path list with PYTHONPATH environment variableSynchronize...Syntax coloringSyntax highlighting for Matlab, Julia and other file typesSystem commands:TIFF imagesTabTab always indentTab stop width:TabulationsTear off menusTemporary fileTerminalTextText editorText filesThe 'xlabels' argument length do no match array column numberThe 'ylabels' argument length do no match array row numberThe current working directory is the working directory for IPython consoles and the current directory for the File Explorer.The EditorThe File ExplorerThe History LogThe IPython consoleThe Variable ExplorerThe authenticity of host %s can't be established. Are you sure you want to continue connecting?The authenticity of the host can't be establishedThe current directory contains a project.

If you want to delete the project, please go to Projects » Delete ProjectThe current project directory or user home directory (if no project is active)The current working directoryThe directory of the file being executedThe directory when a new console is open will be the specified pathThe directory {} is not writable and it is required to create IPython consoles. Please make it writable.The following are the default options for running files.These options may be overriden using the Configuration per file entry of the Run menu.The following conflicts have been detected:The following directory:The following error occured when calling Sphinx %s.
Incompatible Sphinx version or doc string decoding failed.

Error message:
%sThe following modules are not installed on your machine: %sThe following working directory is not valid:
%sThe new shortcut conflicts with:The working directory for new consoles is:This directory is already included in Spyder path list.
Do you want to move it to the top of the list?This entry is incorrectThis error was most probably caused by installing Spyder in a directory with non-ascii characters (i.e. characters with tildes, apostrophes or non-latin symbols).

To fix it, please reinstall Spyder in a different location.This feature requires Sphinx 1.1 or superior.This feature requires the Rope or Jedi libraries. It seems you don't have either installed.This is a remote kernelThis is a temporary script file.This is one of panes where you can run or execute the code you wrote on the Editor. To do it you need to press the F5 key.

This console comes with several useful features that greatly improve your programming workflow (like syntax highlighting and inline plots). If you want to know more about them, please follow this link.

Please click on the button below to run some simple code in this console. This will be useful to show you other important features.This is the pane where you write Python code before evaluating it. You can get automatic suggestions and completions while writing, by pressing the Tab key next to a given text.

The Editor comes with a line number area (highlighted here in red), where Spyder shows warnings and syntax errors. They can help you to detect potential problems before running the code.

You can also set debug breakpoints in the line number area, by doing a double click next to a non-empty line.This is the working directory for newly opened consoles (Python/IPython consoles and terminals), for the file explorer, for the find in files plugin and for new files created in the editorThis lets you load graphics support without importing the commands to do plots. Useful to work with other plotting libraries different to Matplotlib or to develop GUIs with Spyder.This option lets you hide the message shown at the top of the console when it's opened.This option lets you hide the warning message shown when resetting the namespace from Spyder.This option loads the Sympy library to work with.
Please refer to its documentation to learn how to use it.This option will be applied the next time a console is opened.This option will enable the User Module Reloader (UMR) in Python/IPython consoles. UMR forces Python to reload deeply modules during import when running a Python script using the Spyder's builtin function runfile.

1. UMR may require to restart the console in which it will be called (otherwise only newly imported modules will be reloaded when executing files).

2. If errors occur when re-running a PyQt-based program, please check that the Qt objects are properly destroyed (e.g. you may have to use the attribute Qt.WA_DeleteOnClose on your main window, using the setAttribute method)This pane can automatically show an object's help information after a left parenthesis is written next to it. Below you can decide to which plugin you want to connect it to turn on this feature.This pane displays documentation of the functions, classes, methods or modules you are currently using in the Editor or the Consoles.

To use it, you need to press Ctrl+I in front of an object. If that object has some documentation associated with it, it will be displayed here.This pane lets you navigate through the directories and files present in your computer.

You can also open any of these files with its corresponding application, by doing a double click on it.

There is one exception to this rule: plain-text files will always be opened in the Spyder Editor.This pane records all commands introduced in the Python and IPython consoles.This will synchronize Spyder's path list with PYTHONPATH environment variable for current user, allowing you to run your Python modules outside Spyder without having to configure sys.path.
Do you want to clear contents of PYTHONPATH before adding Spyder's path list?To boolTo complexTo doTo floatTo intTo strToggle LowercaseToggle UppercaseToolbarsTransposeTunnel '%s' failed to startTupleTypeUMRUMR forces Python to reload modules which were imported when executing a file in a Python or IPython console with the runfile function.Unable to check for updates.Unable to connect to %sUnable to connect to the internet.

Make sure the connection is working properly.Unable to load pageUnable to retrieve information.UncommentUndoUnexpected error: see internal consoleUnindentUnindent current line or selectionUnlockUnmatched
parens:Update LANGUAGE_CODES (inside config/base.py) if a new translation has been added to SpyderUpdate module names listUsageUse a pager to display additional text inside the consoleUse a single instanceUse next layoutUse previous layoutUse symbolic mathUse the following Python interpreter:Use the following file:Use the greedy completerUse version controlUseful if you don't want to fill the console with long help or completion texts. Note: Use the Q key to get out of the pager.User Module Reloader (UMR)ValueValue:Variable NameVariable explorerVariable name:Version controlVersion control systemVertical tabs in panesVertical title bars in panesViTablesView and edit DataFrames and Series in the Variable ExplorerView and edit two and three dimensional arrays in the Variable ExplorerWarningWe cannot support this shortcut on WindowsWeb page filesWelcome to Spyder introduction tourWelcome to Spyder!Welcome to the Introduction tourWhen opening a text file containing mixed end-of-line characters (this may raise syntax errors in the consoles on Windows platforms), Spyder may fix the file automatically.WhitespaceWhole wordsWidth:WinPythonWinPython control panelWindow layout will be reset to default settings: this affects window position, size and dockwidgets. Do you want to continue?Window layoutsWorking Directory settingsWorkspaceWrap linesXML filesYaml filesYou are working with Python 2, this means that you can not import a module that contains non-ascii characters.You can also run a whole file at startup instead of just some lines (This is similar to have a PYTHONSTARTUP file).You can run several lines of code when a console is started. Please introduce each one separated by commas, for example:
import os, import sysYou don't have the right permissions to open this directoryYou selected a Python %d interpreter for the console but Spyder is running on Python %d!.

Although this is possible, we recommend you to install and run Spyder directly with your selected interpreter, to avoid seeing false warnings and errors due to the incompatible syntax between these two Python versions.You selected an invalid Python interpreter for the console so the previous interpreter will stay. Please make sure to select a valid one.Your Python environment or installation doesn't have the ipykernel and cloudpickle modules installed on it. Without these modules is not possible for Spyder to create a console for you.

You can install them by running in a system terminal:

pip install ipykernel cloudpickle

or

conda install ipykernel cloudpickleZoom inZoom outZoom resetarraycharacterscodecopydatadeletedpielementsfilegettext filesguidata examplesguiqwt examplesinchesinvalid regular expressionlineslistmatchesmatches inmovemsno matchesofotherpermission denied errors were encounteredpixelsreStructuredText filesread onlyspacestabletextthe following directory:this dialogtutorialunsaved fileuntitledusername@hostname:portvariable_nameProject-Id-Version: Spyder3 Report-Msgid-Bugs-To: POT-Creation-Date: 2017-12-14 15:40+-05 PO-Revision-Date: 2017-12-18 19:05+0900 Last-Translator: Language-Team: Japanese Language: ja MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=1; plural=0; X-Generator: Poedit 1.8.11 X-Poedit-SourceCharset: UTF-8 Numpy 配列/行列 ヘルパー
テーブルに配列を入力してください。
セル間の移動にはタブを使います。

配列入力には'Enter'を、行列入力には 'Ctrl+Enter'を。

ヒント:
行末で次の行へ移動するにはタブを2回入力すれば良い。 Numpy 配列/行列 ヘルパー
以下の形式で入力 Matlab形式 : [1 2;3 4]
あるいはSpyder構文 : 1 2;3 4

配列入力には'Enter'を、行列入力には 'Ctrl+Enter'を使う。

ヒント:
空白2つあるいはタブ2つは';'入力になる。 ファイルを検索しています...インストール済み必須スキャン中: {0} フォルダ内のファイルを検索中: {0} エントリ行ms%s は現在サポートされていません%s 配列%s エディタ閉じる(&C)ファイルごとの設定(&C)デバッグ(&D)編集(&E)ファイル(&A)ファイル内を検索(&F)テキストを検索(&F)ヘルプ(&H)新規ファイル(&N)...開く(&O)...印刷(&P)プロジェクト(&P)終了(&Q)テキストを置換(&R)再起動(&R)復帰(&R)実行(&R)実行(&R)保存(&S)検索(&S)ツール(&T)表示(&V)空白2個空白3個空白4個空白5個空白6個空白7個空白8個%s は複数種の改行コードを含んでいます。
Spyderは自動的に修正します。%s はSpyderの外で変更されています。
変更を破棄して再読込しますか?%s は変更されています。
保存しますか?%s はSpyderプロジェクトではありません!%s は利用できません (このファイルはSpypder外で削除、移動あるいは名前変更されています)。
閉じますか?ここで設定した以外に、-u がオプションに追加されました。Spyder %s is available!

Please use your package manager to update Spyder or go to our Releases page to download this new version.

If you are not sure how to proceed to update Spyder please refer to our Installation instructions.spyderで問題が発生しました。
ご不便をおかけします。

エラーの情報を自動的にspyderのGithubバグトラックシステムへ送信することができます。

注: これを実行するにはあなたのGithubアカウントが必要です。Spyder はPythonプログラミングのためのパワフルな対話型開発環境(Interactive Development Environment, IDE) です。

これはもっとも重要な機能の紹介です。

ツアーにそって進むには矢印キーを押すか下のボタンをクリックしてください。Spyder はなにか(bla)に基づいた対話型開発環境(Interactive development environment)です。%s が %s に実行できませんでした。

エラーメッセージ:
%sアイテムにデータを割り当てられません。

エラーメッセージ:
%sファイル %s を作成できません

エラーメッセージ:
%sフォルダ %s を作成できません

エラーメッセージ:
%s{varpath}を削除できません。

エラーメッセージ:
{error}外部プログラムが見つかりません。

%s '%s' をロードできません

エラーメッセージ:
%s %s を移動できません

エラーメッセージ:
%sデータをプロットできません。

エラーメッセージ:
%s次のステップを実行できません

入力をチェックしてください。

エラーメッセージ:
%sファイル %s をリネームできません

エラーメッセージ:
%s配列を保存できません

エラーメッセージ:
%s現在のワークスペースを保存できません

エラーメッセージ:
%sファイル '%s' を保存できません

エラーメッセージ:
%s画像を表示できません。

エラーメッセージ:
%sサポートされていないファイル拡張 '%s'

(既知のファイルフォーマットを選択して)とにかくインポートしますか ?非サポートファイルタイプ '%s'警告:
パイソンモジュール rope がこのコンピューターにインストールされていません: 呼び出し情報の表示、コード補完及びgo-to-definition機能は利用できません。依存パッケージが見つかりません!

%s

このメッセージ表示を避けるにはこれらのパッケージをインストールしてください。

: Spyderは依存関係を満足させなくても動作しますが、円滑な動作のためには依存関係を解決することが 強く 推奨されます。
これらの依存パッケージがインストールされていない場合不具合が発生する可能性があります。新しい問題を報告する前には、発生した不具合が依存性の欠如によるものではないことを確認してください。

全ての変数を削除しています…

カーネルを再起動しています...


重要: SpyderはAnaconda/Minicondaと使われているようです。Spyderをアップデートするためにpipを使うことは避けてで下さい。現在インストールされた環境が壊れる可能性があります。

新しいcondaパッケージが利用できるまで待ち、condaを使ってアップデートして下さい。
( {} ページ参照)

有効にした場合、Pythonソースコードはpycodestyleを使って分析され、PEP8スタイルガイドに適合していない行は強調表示されます。

: 警告を抑制するには、analysis:ignore をコメント内に追加してください。

有効にした場合Pythonソースコードはpyflakesで分析され、エラーや警告のある行は強調表示されます。

: analysis:ignore をコメントで追加すると警告は無視されます。

警告: 変更は別々に適用されます複合シーケンスは{break} 最大4個のサブシーケンス{break}を持てます。%s について%s について...サポートを有効化ブロックコメントを追加(&B)ブロックコメントを現在行あるいは選択範囲の周りに追加パスを追加追加機能追加オプションアドレス:詳細設定詳細設定%s へのすべての変更は失われます。
ファイルをディスクから復帰させますか?すべてのファイル全てのファイル (*)すべてのファイル (*.*)全てのユーザー定義変数は削除されます。本当に実行しますか?ファイルの先頭に %s を常に表示通信ソケット作成中にエラーが発生しました。cmd.exeから以下のコマンドを管理者権限で実行し、PCを再起動して下さい:

netsh winsock reset
カーネルを開始中にエラーが発生しました分析ツールバーとペインをアニメーションさせる外見本当にこのスキームを削除しますか?本当にカーネルを再起動しますか?引数配列の次元が不正配列エディタ3次元以上の配列はサポートされていません閉じる前に確認するようにする全ユーザー定義変数を削除する前に確認する接続されたコンソールウインドウ(デバッグ)属性Autocall明示的に括弧を省略している場合でも、IPythonで呼び出し可能なオブジェクトをAutocallによって自動的に呼ぶ。
例えば、str 43 と入力すると自動的に str(43) となる。Autocall:自動自動コード補完自動接続自動インポート'else'や'elif'の後を自動的にインデントする引用符を自動的に閉じる'for', 'if', 'def'等の後にコロンを自動挿入する括弧、中括弧、大かっこを自動的に挿入Pylab, NumPyモジュールを自動的にロードファイル保存時に後続スペースを削除する軸:戻るバックエンド:背景背景色バックグラウンド:Batchファイルボールドブレークポイント表示作業ディレクトリを表示レポジトリを表示tabを表示バッファーバッファー...バッファー:組み込み:Cファイルすべて閉じる(&C)コンソール(&O)C++ファイルCPUとメモリの使用状況をステータスバーに表示CPU使用状況の表示には非Windows環境では`psutil` (>=v0.3) が必要になりますCPU:CSVテキストファイルキャンセルSpyder以外によって起動されたカーネルは再起動できません CR (Mac)CR+LF (Windows)大文字/小文字を区別コード補完で大文字/小文字を区別%s 行から始まるセル選択範囲あるいは現在行を小文字化親ディレクトリへ移動選択範囲あるいは現在行を大文字化MayaviのバックエンドをQtに変更中起動時に更新をチェック更新をチェック...%s 行で定義されているクラス全ての出力をクリア全てのファイルのブレークポイントをクリアコンソールをクリアする行をクリアラインやブロックをクリアする最近使用したファイルのリストをクリアシェルをクリアシェルの中身をクリア(clsコマンド)このリストをクリアクリップボードの内容プロジェクトを閉じる...他を閉じる開いているファイルを全て閉じる全体を右側へ閉じる現在のファイルを閉じる現在のペインを閉じる現在のタブを閉じるこのパネルを閉じるこのウインドウを閉じるウインドウを閉じるSpyderを閉じるコードコード イントロスペクション/分析コード分析コード分析にはpyflakes %s+ が必要ですコード注釈 (TODO, FIXME, XXX, HINT, TIP, @todo, HACK, BUG, OPTIMIZE, !!!, ???)全て折りたたむ現在の選択を折りたたむ色スキームエディタ列の 最小/最大列セパレータ列:コマンドラインオプション:コメント現在行あるいは選択範囲をコメントアウトコメント:コメント:コミット補完タイプ補完:条件:Configurationファイル高DPIスクリーン設定

これらのオプションのより詳細な情報は以下を参照して下さい {0}<>.競合既存のカーネルに接続カーネルへ接続中...接続エラー接続情報:コンソールコンソールディレクトリコンソールヘルプコンテキストContinue次のブレークポイントまで実行を続ける変換エラー改行コードを変換するPythonスクリプトへ変換コピーパスをクリップボードにコピークリップボードにコピープロンプトなしでコピーリモートホストへ接続できませんでしたsshトンネルを開けませんでした。エラー: 作成新しいエディタウインドウを作成する新規プロジェクト作成新しいスキームを作成現在セル:現在行:現在のショートカット:現在のユーザー環境変数...現在の作業ディレクトリエディタで行削除をするために使われていますカーソルの点滅:ペインのマージン調整切り取りCython/PyrexファイルデータDataFrameファイルをデバッグ開始デバッグツールバーwinpdbでデバッグコンソール内でどのように画像を表示するか選んでください。よくわからなければ、コンソール内で画像を表示したい場合 %s を選び、別ウィンドウで(ズーム、パン等)操作したい場合は %s を選んでください。このバックエンドで生成された画像をどのように描画するか選択どのタイプの補完を使うか選択デフォルト(=Spyderと同じ)デフォルトは4ですデフォルトは6ですデフォルトは
In [<span class="in-prompt-number">%i</span>]:デフォルトは
Out[<span class="out-prompt-number">%i</span>]:デフォルト作業ディレクトリは:定義:削除レイアウトの削除プロジェクトを削除する削除...依存性依存性...ディクショナリエラーが発生した場合直接デバッグモードに入る表示バルーンチップを表示初期バナーの表示本当に %s を削除しますか?本当に{filename}を削除しますか?

注: プロジェクトファイルはディスク上からは削除されません。

注: 本当に選択したパスを削除しますか?本当に %s をリネームし、既存ファイル %s を上書きしますか?同じカーネルに接続している他の全てのコンソールを閉じますか?本当にこのコンソールを閉じますか?選択された全てのアイテムを除去しますか?選択されたアイテムを除去しますか?デフォルト値に戻しますか?直ちに再起動しますか?次回以降表示しない。完了複製EOL編集ファイル名フィルターを編集ファイル名フィルターを編集...アイテムを編集選択を編集新規モジュール用テンプレートの編集編集ツールバーエディタエディタのコード補完、go-to-definition及びヘルプクリップボードを空にする空のプロジェクトリスト要素、関数呼び出し結果等を変数に割り当てずにTab 補完を有効にする。
例えば li[0].<Tab>ins.meth().<Tab> のように補完できるUMRを有効化高DPIスケーリング自動設定を有効化Enamlファイルエンコード改行コード改行:Enterキーで補完候補を選択他のスクリーンの値(小数点表記も可)をセミコロン';'で区切って入力して下さい。環境変数環境変数..エラーカーネルを開始中にエラーが発生しました:%s 名前が全て大文字の参照を除外大文字で始まる参照を除外privateな参照を除外非サポートデータ型(例:正しくhandle/saveがができない型)への参照を除外 名前が大文字の参照を除外アンダースコアで始まる参照を除外大文字で始まる参照を除外非サポートのデータ型を除外除外:除外されるファイル名パターン実行可能ファイル専用の新規コンソールで実行外部システムターミナルで実行現在のコンソールで実行存在するディレクトリすべて展開現在の選択を展開する外部ツール外部エディタ外部エディタ実行パス:外部エディタのパス...外部エディタ外部システムターミナルフィルを高速で切り替えファイル内の高速シンボル検索ファイルファイル %s は既に存在します。
上書きしますか?ファイルエクスプローラーファイルエクスプローラーファイル切り替え...ファイルツールバーファイル...フィルター次を検索(&N)前を検索(&F)ファイルの検索ファイル中のシンボル検索...テキスト検索自動的に修正し、警告をメッセージボックスで表示するインデントを修正浮動小数点フォーマットフォルダ %s は既に存在します。フォルダ名:フォルダー...フォントスタイルフォント:フォント %s をサポートするためには以下のツールをインストールしてください。
ツール:

%s実行性能に関する理由により、masked配列に適用された変更は配列内のデータには反映されません(逆もまた同様)。禁止されたキーシーケンスですフォーマットフォーマット (%s) が不正ですフォーマット ({}) が不正ですフォーマット({}) は'%'で開始する必要がありますフォーマット:FortranファイルFullフルスクリーンモード%s 行で定義されている関数GIF画像GUIエディタ:一般一般設定カーソル位置へ移動定義へ移動最後に編集した箇所へ移動行へ移動...行へ移動:次のコード分析 警告/エラー へ移動次のカーソル位置へ移動前のコード分析 警告/エラー へ移動前のカーソル位置へ移動ステップへ移動グラフィックスグラフィックスグラフィックスのバックエンドGreedy completion高さ:ヘルプヘルプ...エディタあるいはコンソールでは %s を直前で押すことで直後のオブジェクトのヘルプが得られます。%s ヘルプはオブジェクトの隣で左括弧を入力することでも自動的に表示されます。%sでこの機能を有効化できます。エディタ及びその他全Spyderプラグインで利用する色スキームを選択できます。

以下のオプションにより定義済みの色スキームの編集及び独自色スキーム作成が実行できます。
詳細オプションを隠すツールバーを隠す強調現在セルを強調現在行を強調一致箇所を強調以下の事象を強調ヒストグラムヒストリヒストリー階層:ヒストリログヒストリログヒストリ...ホームホスト名IDLファイルIPythonIPythonコンソールIPythonコンソールIPythonドキュメントIPythonインタラクティブpython環境IPython notebooksアイコンテーマこれを有効にすると、タブキーを押すとカーソルが 行頭になくても常にインデントされる。 (このオプションを有効化した場合、コード補完 のトリガーは別のショートカット Ctrl+Spaceに変更される)このオプションを有効にした場合、オブジェクト名の上で クリック(left-click + Ctrl key) するとオブジェクトの定義へ (定義位置が解決できていれば)移動する。変更を受諾すると Windowsレジストリ内の現在のユーザー環境変数が直接修正されます。 各自のリスクで注意深く使用すること。

変更が効果を及ぼすにはこのアプリケーションの親プロセスを再起動する必要があります。(Windowsショートカットから実行している場合単にspyderを再起動すれば良い。そうでなければ例えばPython(x,y) HomeのようにSpyderを実行しているアプリケーションを全て再起動する)インポート形式を指定してインポートデータをインポートインポートエラークリップボードからインポートインポートウィザードこのペインではプログラム実行中に生成されたり、Spyderコンソールで直接入力されたりした変数の表示・編集ができます。

見ての通り変数エクスプローラーはこのツアー最後のステップで生成された変数を表示しています。表示された変数をダブルクリックすると新しいウィンドウが開き、変数の中身を調査したり変更したりすることができます。インデント現在行あるいは選択範囲をインデントインデント文字:インデックスインデックス:情報初期化中...インラインインラインのバックエンド入力プロンプト:挿入現在のオブジェクトを調査するインストールされたPythonモジュールインスタンス:IPythonコンソールを統合インテリジェントなバックスペース実行後Pythonコンソールと相互作用するインタラクティブツアーインターフェイス内部コンソール内部コンソール設定内部エディタIPythonの紹介紹介ツアーイントロスペクション不正なディレクトリパス不正なファイルパス不正なキー入力前回実行したSpyderを終了できませんでした。 再起動を終了します。notebookが変換できませんでした。エラー: 配列をコピーできませんでした配列の値をコピーできませんでしたこのオブジェクトに対してリッチテキストのヘルプを生成できませんでした。
プレーンテキストを参照してください。notebookからoutputを削除できませんでした。エラー: 再起動できませんでした。 オペレーションを終了します。プロジェクト切替時にIPythonコンソールの再起動に失敗しました。エラー {0}このファイルを外部ターミナルで実行できませんでしたイタリックJPEG画像JSONファイルJavascriptファイルJsonファイルJuliaファイルカーネル停止しました。再起動中カーネル再起動中キーキー:キーボード・ショートカットキーワード:言語最後に編集した箇所レイアウト %sは 上書きされます。 続行しますか?レイアウトの表示と順序レイアウト設定 %s 行行数:LF (UNIX)行:行:オブジェクトの定義にリンクリンク:リスト%s をロードしています...IPythonコンソールをロード中...エディタをロードしています...ファイルエクスプローラーをロードしています...ヘルプをロードしています...ヒストリプラグインをロードしています...名前空間ブラウザをロード中...オンラインヘルプをロードしています...アウトラインエクスプローラーをロードしています...プロジェクトエクスプローラーをロード中...この種のデータのデバッグ中の読み込みはサポートされていません。位置ロックペインをロックMATLABファイルメインツールバーエディタ内で実行後、選択後もセルのフォーカスを維持する色スキームのマネージエディタ上でJupyter notebookを操作MarkdownファイルマスクMaskedデータ閉じた
括弧:MatlabファイルMatplotlibドキュメント現在のペインを最大化最大エントリ数最大行数「最近使用したファイル」の最大履歴数「最近使用したファイル」の最大履歴数...メモリ使用状況の表示には非Windows環境では`psutil` (>=v0.3) が必要になりますメモリ:%s 行で定義されているメソッドプロンプトの入力と出力のコンソール内での表示を変更する。モジュールモジュール pywin32 は見つかりませんでした
変更を反映させるには(コンピュータではなく)このWindowsセッション を再起動して。モジュールあるいはパッケージ:モジュール...下へ移動上へ移動下へ移動一番下へ移動一番上へ移動上へ移動移動...NSISファイル名前フィルター:新規新規プロジェクト...新規ディクショナリバージョン3.0の新機能新規ファイル新規フォルダー新規モジュール新しい名前:新規パッケージ新規ショートカット:Spypderは初めてですか? 読んでください。新しい変数名:新しいウインドウ次次のカーソル位置次の 警告/エラー現在%s実行可能なIPythonコンソールがありません。.

新規に開いて再試行してください。利用可能なドキュメントはありませんこれ以上のドキュメントはありません一致なしソースコードが利用できません通常通常テキスト:クリップボードからインポートするものはありません。NumPy配列NumPy配列NumPy zip配列数字:NumpyとScipyのドキュメント最後に閉じたファイルを開く(&O)オブジェクト事象:オフ%s モードでは、 呼び出し可能オブジェクトに引数がない場合Autocallは適用されません。 %s モードでは、(引数がない場合でも)全ての呼び出し可能オブジェクトが自動的に呼ばれます。オンラインドキュメントオンラインヘルプPNGフォーマットの場合のみ使われます。デフォルトは72開く最近使用したファイル(&R)IPythonコンソールをここで開くプロジェクトを開く...既存カーネルに接続された新規IPythonコンソールを開くIPythonコンソールを開く(&I)コマンドプロンプトをここで開くIPython接続ファイルを開くファイルを開く形式を指定して開く:最後に閉じたファイルを開くプロジェクトを開くターミナルをここで開くOpenCLファイルこの変数を開くには時間がかかる場合があります 続行しますか?オプションアウトライン出力プロンプト:PNG画像PYTHONPATHマネージャパッケージ名:パッケージ...ペイン親パスワードパスワードあるいはsshキーのパスフレーズ貼り付けPatch and diffファイル接続ファイルへのパスあるいはカーネルIDsshキーファイルへのパス記号演算をコンソール内で実行し(例:積分、微分、ベクトル演算等)、整えられた印刷可能スタイルで出力する(要Sympyモジュール)。コード分析をファイル保存時のみ実施コード分析をファイル保存時と以下の間隔で実施権限:Pickleファイルプレーンテキストプレーンテキストプレーンテキストドキュメントをリッチテキストで表示するためにSphinxをインストールした方が良いでしょう。接続したいカーネルの接続情報を入力してください。 表示 ボタンを押し、JSON接続ファイルを選ぶか、ローカルカーネルの場合IDを入力してください (例: kernel-3764.json あるいは 3764)。matplotlibguiqwt をインストールしてください。異なるショートカットを設定してくださいこれらの変更は新規Python/IPythonコンソールにのみ適用されることに注意してくださいこれらの変更は新規コンソールのみに適用されることに注意してくださいプロット内部エラー発生時に内部コンソールをポップアップさせる設定(&F)設定設定 > ヘルプファイルを切り替えるために Enter を押すか Esc でキャンセルしてください。.

ファイルをフィルターするために入力してください。

行移動には:数字 を使ってください。例: main:42
シンボルへの移動は@symbol_text を使ってください。例: @init

現在のタブを閉じるには Ctrl+W を押してください。
入力を検証するにはエンターキーを押してくださいパスを検証するにはエンターキーを押してください新しショートカットを押し、 'Ok'を選択してください: (ショートカットエントリ間やボタン間のフォーカス移動には 'Tab'を押してください)プレビュー前前のカーソル位置前の 警告/表示現在のファイルを印刷...プレビューを表示...印刷中...プロジェクトプロジェクトエクスプローラープロジェクト設定プロジェクトエクスプローラープロジェクト名プロジェクト設定プロジェクトタイプ終了時に確認するプロンプト利用できる機能PyQt4 APIリファレンスPyQt4リファレンスガイドPyQt5 APIリファレンスPyQt5リファレンスガイドPythonパスマネージャPythonドキュメントPythonファイルPythonヘルプ:PythonインタープリターPythonパッケージPythonプロジェクトPythonスクリプトPythonバージョンPython2ドキュメントPython3ドキュメントQt DesignerQt LinguistQtドキュメントQt examplesQt windowスタイルクイックリファレンスクイックスイッチレイアウト #%s は未定義です。終了ブロックコメントを削除(&R)Rawテキスト最後のcellを再度実行する最後のスクリプトを再度実行する(&L)最後のcellを再度実行する(リアルタイムコード分析エディタ上でのリアルタイムコード分析リアルタイムコードスタイル分析エディタ上でのリアルタイムコードスタイル分析最近開いたプロジェクト配列のフィールドを記録:やり直すPYTHONPATH上で利用可能なモジュールリストの更新正規表現正規表現エラー削除エラー除去全ての変数を削除実行前に全ての変数を削除現在行あるいは選択範囲の周りのブロックコメントを削除パスを削除参照を削除無駄な後続スペースを削除リネームタブをリネームリネーム...数式を描画全て置換選択部分を置換置換文字列タブ文字を空白に置換以下で置換:次へ置換/検索問題をレポート...リセットSpyderをデフォルト設定へ戻すデフォルト値に戻すデフォルト設定へ戻すSpyderのデフォルト値に戻すSpyderをデフォルト状態に戻していますリサイズ行数を中身に応じて変更解像度:再起動カーネルの再起動カーネルを再起動しますか?再起動中。復元現在のペインを復元起動時にデータを復元元のツリーレイアウトを復元ペインをオリジナルサイズに復元ディスクからファイルを復帰リッチテキストリッチテキスト行セパレーター実行選択範囲あるいは現在のカーソル行を実行(&S)CythonファイルをIPythonコンソールで実行Pythonスクリプトを実行設定ダイアログを実行Pythonスクリプトを実行ファイルを実行最後のファイルを再度実行するcellを実行cellを実行し進むコードを実行実行設定ファイルごとの実行設定現在のセルを実行する (Ctrl+Enter) [Use #%% to create cells]現在のセルを実行し次のセルへ(Shift+Enter)現在行を実行ファイルを実行スクリプトを実行:選択を実行選択範囲あるいは現在行を実行設定の実行%s の実行設定実行ツールバー現在行のメソッド/関数までRunするプラットフォーム %s では外部システムターミナルの実行はサポートされていません。全て保存(&E)保存形式を指定して保存(&A)すべてのファイルを保存スクリプトを実行前に保存配列を保存形式を指定して保存現在のファイルを形式を指定して保存...現在のファイルを形式を指定して保存...現在のヒストリログ(全ての入出力)をテキストファイルに保存現在のレイアウトを保存データを保存形式を指定してデータ保存データを保存して終了ファイルを保存ヒストリログを保存ヒストリログを保存ヒストリログを保存...開いているプロジェクト外のファイルを保存するデバッグ中のデータ保存はサポートされていません。スキーム名:スキーム:スコアスクリーン解像度:最後のエントリーまで自動的にスクロール検索ディレクトリを検索現在のSpyderパス内に存在している全てのファイルとディレクトリを検索現在のプロジェクトパス内に存在している全てのファイルとディレクトリを検索現在開いているファイルを検索ファイルシステム上の他フォルダを検索検索:パターンを検索検索文字列複数のファイルからテキストを検索検索ツールバー検索:全て選択実行する設定を選択ディレクトリを選択ファイル選択他のディレクトリを選択sshキーを選択Spyderコンソールで使用するPythonインタープリターの選択UMRから排除される(=再読込されない)モジュールを設定カスタム高DPIスケーリングを設定コンソールの作業ディレクトリをセットコンソール(とファイルエクスプローラー)の作業ディレクトリを現在のスクリプトのディレクトリにセット外部エディタ実行パスを設定ヒストリの最大エントリ数最大行数を設定除外モジュールのリストを以下の例のように入力して下さい: numpy, scipyコンソール内で表示するテキストの最大行数を設定。 -1 を設定すると無効になります (非推奨です!)高DPIディスプレイ用にセットする自動スケーリングが動作しない場合、高DPIディスプレイ用にこの設定を適用する。メインウインドウから
メニューを切り離すために設定する外部Pythonファイルを実行中の
インスタンスで開くためにこれをセット (再起動が必要)ブレークポイントのセット/クリア条件付きブレークポイントをセット/編集メインウインドウを設定中...設定特別なシェルコマンド:ショートカットショートカット: {0}ショートカットサマリーショートカットのリセットシフトキーを組み合わせたショートカットはサポートされていませんsys.pathを読み取り専用で表示CPU使用状況を以下の間隔で更新ソースを表示絶対パスを表示詳細オプションを表示全てのファイルを表示レジストリ内のユーザー環境変数を表示・編集する(現在のセッションのため)環境変数を表示・編集する配列の最小/最大を表示空白スペースを表示コード分析の 警告/エラー を表示コメントリスト(TODO/FIXME/XXX/HINT/TIP/@todo/HACK/BUG/OPTIMIZE/!!!/???)の表示現在のディレクトリのみを表示実行時間を表示環境変数を表示専用ペインでエディタ・コンソール中のオブジェクトのヘルプを表示する水平スクロールバーを表示アイコンとテキストを表示画像を表示Finderで表示外部ファイルエクスプローラーで表示行番号を表示メモリ使用状況を以下の間隔で更新再読込されたモジュールのリストを表示特別なコメントを表示ステータスバーを表示sys.pathの中身を表示sys.pathの中身を表示...タブバーを表示TODOリストを表示ツールバーを表示縦線を以下の後に表示警告/エラー リストを表示アウトラインエクスプローラーの表示/隠すサイドエリア:選別するサイズサイズ:行を飛ばす:Smartソース(&C)ソースソースコードソースツールバーSphinx %s が現在インストールされています。横に分割このエディタウインドウを横に分割縦に分割するこのエディタウインドウを縦に分割するSpyderデフォルトレイアウトSpyderエディタSpyder 内部コンソール このコンソールは下記コマンド spy.app, spy.window, dir(spy) により、アプリケーション内部エラーの報告と Spyder内部検査のために使われます。 ユーザーのpythonコードを実行するために使わないでください。 Spyderキーボード・ショートカットデフォルト設定を適用できませんでした。 再起動を終了します。Spyderデータファイル全てのペインが正しく機能するために、Spyderは複数のPythonモジュールに依存しています。 下記のテーブルには必要なモジュールとインストール済みモジュールのバージョンを示します。

: 以下のモジュールはインストールしなくてもSpyderを安全に使用できます。:%s%s.

新たに発生した依存関係及び解決された依存関係はSpyderを再起動するまで正しく認識されませんspyderドキュメントSpyder実行エラーSpyderはなにか(bla)に基づいた対話型開発環境(Interactive development environment)です。Spyderは最新の状態です。Spyderは以下の設定を適用するために再起動が必要となります:Spyderは以下の設定を適用するために再起動が必要となります:SpyderリセットエラーSpyder再起動エラーSpyderサポート...SpyderチュートリアルSpyderアップデートSpyderはコンソールから変数の値を読み取ることができませんでした。

エラーメッセージ:
%sSpyderを再起動して設定をデフォルトに戻します:

続行しますか?sshキー検索開始スタートアップステータスバーStepStep IntoStep Return現在行のメソッド/関数までStep inする停止デバッグを停止検索終了現在のコマンドを停止する文字列が見つかりませんでした文字列:Githubへ送信する画像のサポート(Matplotlib)サポートされているファイルサポートされたテキストファイルシンボルファインダー...記号数学IPythonコンソールでの記号数学同期SpyderのパスリストをPYTHONPATH環境変数に同期させる同期...構文強調の配色Matbal、Julia及びたのファイルタイプの構文強調システムコマンド:TIFF画像タブ常にインデントにタブを使うタブ幅:一覧表メニューを切り離す一時ファイルターミナルテキストテキストエディタテキストファイル'xlabels'引数の長さが配列の列数に一致していません'ylabels'引数の長さが配列の行数に一致していません現在の作業ディレクトリ はIPythonコンソールとファイルエクスプローラーのための作業でディレクトリです。エディタファイルエクスプローラー履歴ログIPythonコンソール変数エクスプローラーホスト %s の信頼性が確立できません。本当に接続を続けますか?ホストの信頼性が確立できません現在のディクショナリはプロジェクトを含んでいます。

プロジェクトを削除したい場合はプロジェクト » プロジェクトの削除を選択して下さい現在のプロジェクトディレクトリあるいは(アクティブなプロジェクトが無い場合)ホームディレクトリ現在の作業ディレクトリ設定現在実行しているファイルのディレクトリ 新規コンソールを開いた時の作業ディレクトリは設定されたパスによって決定されますIPythonコンソール作成に必要なディクショナリ{}が書き込み不可になっています。書き込み可能に変更して下さい以下はファイル実行時のデフォルトオプション設定です。これらのオプションは実行メニューのファイルごとの設定エントリで上書きされます。以下の競合が検知されました:以下のディレクトリ:以下のエラーは Sphinx %s を呼んだ時に発生しました。
Sphinxのバージョンが合っていないか文字列のデコードに失敗しました。

エラーメッセージ:
%s以下のモジュールがコンピュータにインストールされていません: %s以下の作業ディレクトリは不正です:
%s新しいショートカットは以下と競合しています:新規コンソール用の作業ディレクトリ:このディレクトリは既にSpyderのパスリストに含まれています。
リストの一番上にパスを移動させますか?この入力は不正ですこのエラーはおそらくSpyderを非ASCII文字を名前に含むディレクトリにインストールしていることによって発生しています。br>
解決するにはSpyderを他の場所に再インストール して下さい。この機能はSphinx 1.1以上を必要とします。この機能はRopeあるいはJediライブラリを必要とします。 どちらもインストールされていないようです。これはリモートカーネルですこれは一時的なスクリプトファイルですこれはエディタで入力したコードを実行できるペインの一つです。 コードを実行するには F5 キーを押す必要があります。

このコンソールにはプログラミングを改善するいくつかの有用な機能(構文の強調や行内プロット等)があります。これらについてもっと知りたい場合はリンク先を参照してください。

このコンソール内の単純なコードを動かすために下のボタンをクリックしてください。 他の重要な機能を見るために役立ちます。これは評価(evaluate)前にPythonコードを書くためのペインです。 入力したテキストの横でタブキーを押すことにより、自動サジェスト及び補完機能を使うことができます。

エディタには行番号エリア(ここでは赤で強調)があり、 警告や文法エラーが表示されます。 これらはコード実行前に潜在的な問題を発見する助けとなります。

また行番号エリアの空行以外の場所でダブルクリックすることにより、デバッグのためのブレークポイントを設置することができます。これは、ファイルエクスプローラー、 ファイル検索プラグイン、新規コンソール (Python/IPythonコンソール及びターミナル) 及びエディタで作成した新規ファイルの 作業ディレクトリです。プロットコマンドをインポートすることなしに画像サポートを 有効にします。Matplotlib以外のプロットライブラリを利用 している場合や、SpyderでGUIを開発している場合、 有用です。このオプションによりコンソールを開いた時に表示される 一番上のメッセージを隠すことができます。このオプションによりSpyderから名前空間をリセットするときの 警告メッセージを隠すことができます。このオプションはSympyライブラリをロードします。
Sympyドキュメントを参照し、使用方法を学んでください。このオプションは次にコンソールを開いた時に適用されますこのオプションはPython/IPython コンソールでのユーザーモジュールリローダー (UMR)を有効化します。UMRはSpyderの組み込み関数runfileを使うPythonスクリプトを実行する場合、インポート時にモジュールの再読み込みを強制します。

1. UMRは実行するコンソールの再起動を必要とする場合が有ります(あるいはスクリプト実行時に新しくインポートされたモジュールのみが再読み込みされます)。

2. PyQtを使ったプログラムの再実行時にエラーが発生した場合、Qtオブジェクトが適切に破棄されているか確認してください。(例: setAttributeメソッドを使ってアトリビュートQt.WA_DeleteOnClose をメインウインドウに適用するなど)このペインは括弧の左側が入力されるとそのオブジェクトのヘルプ情報を自動的に表示します。この機能を有効にするために接続したいプラグインを選べます。このペインは現在エディタやコンソルーで使っている関数、クラス、メソッドあるいはモジュールを表示します。

このペインを使うにはオブジェクトの前で Ctrl+I を押す必要があります。もしオブジェクトに関連付けられたドキュメントがある場合ここに表示されます。このペインはコンピュータ内のディレクトリとファイルをナビゲートします。

ペイン上でダブルクリックすることにより、任意のファイルを対応したアプリケーションで開くことができます。

但しプレーンテキストは常にSpyder Editorで開かれるという例外はあります。このペインはPython及びIPythonコンソール内で入力された全てののコマンドを記録します。sys.pathを変更することなくSpypder外でPythonモジュールを実行できるように、Spyderのパスはユーザーの PYTHONPATH 環境変数に同期されます。
Spyderのパスリストを追加する前にPYTHONPATHの値をクリアしますか?真偽値へ複素数へTo do浮動小数点数へ整数へ文字列へ小文字に変更する大文字に変更するツールバー転置Tunnel '%s' は開始できませんでしたタプル型UMRPythonあるいはIPythonでrunfileを使うスクリプトをインポートする時、UMRはモジュール再読み込みを強制します。更新をチェックできません%sに接続できませんでしたインターネットに接続できません。

接続が正しく動作しているか確認してください。ページをロードできません情報が取得できませんコメント解除元に戻す予期しないエラー: 内部コンソールを参照してくださいインデント解除現在行あるいは選択範囲をインデント解除アンロック閉じていない
括弧:新しい翻訳がSpyderに追加された場合LANGUAGE_CODES (config/base.py内)を更新モジュール名リストの更新使用法コンソール内で追加テキストを表示するためにページャーを使用単一インスタンスを使用次のレイアウトを使用前のレイアウトを使用記号演算を使う以下のPythonインタープリターを使う以下のファイルを使う:greedy completerを利用するバージョンコントロールを使用する補完テキストや長いヘルプでコンソールを埋めたくない場合有効です。 注: このページャーから出るには Qキーを押してください。モジュールリローダーを使用(UMR)値値:変数名変数エクスプローラー変数名:バージョンコントロールバージョンコントロールシステムペインのタブを縦にするペインのタイトルバーを縦にするViテーブル変数エクスプローラーでのDataFrameとSeriesの表示・編集変数エクスプローラーでの2, 3次元配列の表示・編集警告WindowsではこのショートカットはサポートできませんWebページファイルSpyder紹介ツアーへようこそSpyderへようこそ!紹介ツアーへようこそ複数種の改行コードを含むテキストファイル(Windows環境ではコンソールで文法エラーを起こす可能性があります)を開く場合、Spyderは自動的にこれを修正します。空白スペース単語全体幅:WinPythonWinPythonコントロールパネルウインドウレイアウトはデフォルト状態にリセットされます:ウインドウ位置、サイズ及びドックウィジェットが影響されます。 続行しますか?ウインドウレイアウト作業ディレクトリ設定ワークスペース行の折り返しXMLファイルYamlファイルPython2で動作しています。この環境では非アスキー文字を含むモジュールをインポートできません。行の一部だけではなくファイル全体をスタート時に実行できます(PYTHONSTARTUPファイルと類似)コンソールを開始した時にコードを実行できます。それぞれをコンマで区切ってください。例:
import os, import sysこのディレクトリを開く権限がありませんコンソール用にPython %dインタープリターが選択されましたがSpyder上ではPython %dが実行されています!

この選択は可能ですが、Pythonバージョン間での構文非互換性による偽の警告/エラーを避けるため、Spyder上でも選択したバージョンのインタープリターをインストール・実行することが推奨されます。無効なPythonインタープリターが選択されたためインタープリターは変更されません。有効なものを選択して下さい。Python環境にipykernelcloudpickle モジュールがインストールされていません。これらのモジュールがない場合Spyderでコンソールを開くことができない場合があります。

システムのターミナルで以下のコマンドでインストールすることが可能です。:

pip install ipykernel cloudpickle

あるいは

conda install ipykernel cloudpickleズームインズームアウトズームリセット配列文字コードコピーデータ削除dpi要素ファイルgettextファイルguidata examplesguiqwt examplesインチ無効な正規表現行リスト一致一致移動ms一致なしofその他エラーが発生しました(権限がありません)ピクセルreStructuredTextファイル読み取り専用空白テーブルテキスト以下のディレクトリ:このダイアログチュートリアル保存されていないファイルタイトル無しusername@hostname:portvariable_namespyder-3.2.6/spyder/locale/ja/LC_MESSAGES/spyder.po0000664000175000017500000056026413224121062022422 0ustar carloscarlos00000000000000# Japanese translations for PACKAGE package # PACKAGE パッケージに対する英訳. # Copyright (C) 2016 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Ohnishi Seiki , 2016. # msgid "" msgstr "" "Project-Id-Version: Spyder3\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-12-14 15:40+-05\n" "PO-Revision-Date: 2017-12-18 19:05+0900\n" "Last-Translator: \n" "Language-Team: Japanese \n" "Language: ja\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Poedit 1.8.11\n" "X-Poedit-SourceCharset: UTF-8\n" #: spyder/app/mainwindow.py:134 msgid "Initializing..." msgstr "初期化中..." #: spyder/app/mainwindow.py:237 msgid "Python2 documentation" msgstr "Python2ドキュメント" #: spyder/app/mainwindow.py:239 msgid "Python3 documentation" msgstr "Python3ドキュメント" #: spyder/app/mainwindow.py:241 msgid "Numpy and Scipy documentation" msgstr "NumpyとScipyのドキュメント" #: spyder/app/mainwindow.py:243 msgid "Matplotlib documentation" msgstr "Matplotlibドキュメント" #: spyder/app/mainwindow.py:246 msgid "PyQt4 Reference Guide" msgstr "PyQt4リファレンスガイド" #: spyder/app/mainwindow.py:249 msgid "PyQt4 API Reference" msgstr "PyQt4 APIリファレンス" #: spyder/app/mainwindow.py:252 msgid "PyQt5 Reference Guide" msgstr "PyQt5リファレンスガイド" #: spyder/app/mainwindow.py:255 msgid "PyQt5 API Reference" msgstr "PyQt5 APIリファレンス" #: spyder/app/mainwindow.py:257 msgid "WinPython" msgstr "WinPython" #: spyder/app/mainwindow.py:530 msgid "" "An error occurred while creating a socket needed by Spyder. Please, try to " "run as an Administrator from cmd.exe the following command and then restart " "your computer:

netsh winsock reset
" msgstr "" "通信ソケット作成中にエラーが発生しました。cmd.exeから以下のコマンドを管理者権" "限で実行し、PCを再起動して下さい:

netsh winsock reset
" #: spyder/app/mainwindow.py:562 msgid "Close current pane" msgstr "現在のペインを閉じる" #: spyder/app/mainwindow.py:567 msgid "Lock panes" msgstr "ペインをロック" #: spyder/app/mainwindow.py:574 msgid "Use next layout" msgstr "次のレイアウトを使用" #: spyder/app/mainwindow.py:578 msgid "Use previous layout" msgstr "前のレイアウトを使用" #: spyder/app/mainwindow.py:588 spyder/widgets/editor.py:497 msgid "File switcher..." msgstr "ファイル切り替え..." #: spyder/app/mainwindow.py:590 msgid "Fast switch between files" msgstr "フィルを高速で切り替え" #: spyder/app/mainwindow.py:596 msgid "Symbol finder..." msgstr "シンボルファインダー..." #: spyder/app/mainwindow.py:598 msgid "Fast symbol search in file" msgstr "ファイル内の高速シンボル検索" #: spyder/app/mainwindow.py:617 spyder/widgets/sourcecode/codeeditor.py:2661 msgid "Undo" msgstr "元に戻す" #: spyder/app/mainwindow.py:619 spyder/widgets/sourcecode/codeeditor.py:2664 msgid "Redo" msgstr "やり直す" #: spyder/app/mainwindow.py:621 spyder/widgets/shell.py:123 #: spyder/widgets/sourcecode/codeeditor.py:2670 #: spyder/widgets/variableexplorer/arrayeditor.py:467 #: spyder/widgets/variableexplorer/collectionseditor.py:671 #: spyder/widgets/variableexplorer/dataframeeditor.py:586 msgid "Copy" msgstr "コピー" #: spyder/app/mainwindow.py:623 spyder/widgets/shell.py:119 #: spyder/widgets/sourcecode/codeeditor.py:2667 msgid "Cut" msgstr "切り取り" #: spyder/app/mainwindow.py:625 spyder/widgets/shell.py:127 #: spyder/widgets/sourcecode/codeeditor.py:2673 #: spyder/widgets/variableexplorer/collectionseditor.py:668 msgid "Paste" msgstr "貼り付け" #: spyder/app/mainwindow.py:628 spyder/widgets/shell.py:140 #: spyder/widgets/sourcecode/codeeditor.py:2676 msgid "Select All" msgstr "全て選択" #: spyder/app/mainwindow.py:638 spyder/plugins/editor.py:1423 msgid "&File" msgstr "ファイル(&A)" #: spyder/app/mainwindow.py:639 spyder/plugins/editor.py:1411 msgid "File toolbar" msgstr "ファイルツールバー" #: spyder/app/mainwindow.py:643 spyder/plugins/editor.py:1424 msgid "&Edit" msgstr "編集(&E)" #: spyder/app/mainwindow.py:644 spyder/plugins/editor.py:1421 msgid "Edit toolbar" msgstr "編集ツールバー" #: spyder/app/mainwindow.py:648 spyder/plugins/editor.py:1425 msgid "&Search" msgstr "検索(&S)" #: spyder/app/mainwindow.py:649 spyder/plugins/editor.py:1413 msgid "Search toolbar" msgstr "検索ツールバー" #: spyder/app/mainwindow.py:653 spyder/plugins/editor.py:1426 msgid "Sour&ce" msgstr "ソース(&C)" #: spyder/app/mainwindow.py:654 spyder/plugins/editor.py:1415 msgid "Source toolbar" msgstr "ソースツールバー" #: spyder/app/mainwindow.py:658 spyder/plugins/editor.py:803 #: spyder/plugins/editor.py:1427 msgid "&Run" msgstr "実行(&R)" #: spyder/app/mainwindow.py:659 spyder/plugins/editor.py:1417 msgid "Run toolbar" msgstr "実行ツールバー" #: spyder/app/mainwindow.py:663 spyder/plugins/editor.py:762 msgid "&Debug" msgstr "デバッグ(&D)" #: spyder/app/mainwindow.py:664 spyder/plugins/editor.py:1419 msgid "Debug toolbar" msgstr "デバッグツールバー" #: spyder/app/mainwindow.py:668 msgid "C&onsoles" msgstr "コンソール(&O)" #: spyder/app/mainwindow.py:671 msgid "&Projects" msgstr "プロジェクト(&P)" #: spyder/app/mainwindow.py:674 spyder/plugins/editor.py:1428 msgid "&Tools" msgstr "ツール(&T)" #: spyder/app/mainwindow.py:677 spyder/plugins/editor.py:1429 msgid "&View" msgstr "表示(&V)" #: spyder/app/mainwindow.py:680 spyder/plugins/editor.py:1430 msgid "&Help" msgstr "ヘルプ(&H)" #: spyder/app/mainwindow.py:685 msgid "Welcome to Spyder!" msgstr "Spyderへようこそ!" #: spyder/app/mainwindow.py:690 msgid "Pre&ferences" msgstr "設定(&F)" #: spyder/app/mainwindow.py:697 spyder/widgets/pathmanager.py:53 msgid "PYTHONPATH manager" msgstr "PYTHONPATHマネージャ" #: spyder/app/mainwindow.py:700 msgid "Python Path Manager" msgstr "Pythonパスマネージャ" #: spyder/app/mainwindow.py:703 msgid "Update module names list" msgstr "モジュール名リストの更新" #: spyder/app/mainwindow.py:706 msgid "Refresh list of module names available in PYTHONPATH" msgstr "PYTHONPATH上で利用可能なモジュールリストの更新" #: spyder/app/mainwindow.py:709 msgid "Reset Spyder to factory defaults" msgstr "Spyderをデフォルト設定へ戻す" #: spyder/app/mainwindow.py:714 msgid "Current user environment variables..." msgstr "現在のユーザー環境変数..." #: spyder/app/mainwindow.py:716 msgid "" "Show and edit current user environment variables in Windows registry (i.e. " "for all sessions)" msgstr "レジストリ内のユーザー環境変数を表示・編集する" #: spyder/app/mainwindow.py:725 spyder/app/mainwindow.py:1147 msgid "External Tools" msgstr "外部ツール" #: spyder/app/mainwindow.py:728 msgid "WinPython control panel" msgstr "WinPythonコントロールパネル" #: spyder/app/mainwindow.py:737 msgid "Qt Designer" msgstr "Qt Designer" #: spyder/app/mainwindow.py:742 msgid "Qt Linguist" msgstr "Qt Linguist" #: spyder/app/mainwindow.py:748 msgid "Qt examples" msgstr "Qt examples" #: spyder/app/mainwindow.py:768 msgid "guidata examples" msgstr "guidata examples" #: spyder/app/mainwindow.py:779 msgid "guiqwt examples" msgstr "guiqwt examples" #: spyder/app/mainwindow.py:784 msgid "Sift" msgstr "選別する" #: spyder/app/mainwindow.py:794 msgid "ViTables" msgstr "Viテーブル" #: spyder/app/mainwindow.py:808 msgid "Fullscreen mode" msgstr "フルスクリーンモード" #: spyder/app/mainwindow.py:820 msgid "Main toolbar" msgstr "メインツールバー" #: spyder/app/mainwindow.py:829 msgid "" "Spyder Internal Console\n" "\n" "This console is used to report application\n" "internal errors and to inspect Spyder\n" "internals with the following commands:\n" " spy.app, spy.window, dir(spy)\n" "\n" "Please don't use it to run your code\n" "\n" msgstr "" "Spyder 内部コンソール\n" "\n" "このコンソールは下記コマンド\n" " spy.app, spy.window, dir(spy)\n" "により、アプリケーション内部エラーの報告と\n" "Spyder内部検査のために使われます。\n" "\n" "ユーザーのpythonコードを実行するために使わないでください。\n" "\n" #: spyder/app/mainwindow.py:846 msgid "Loading help..." msgstr "ヘルプをロードしています..." #: spyder/app/mainwindow.py:853 msgid "Loading outline explorer..." msgstr "アウトラインエクスプローラーをロードしています..." #: spyder/app/mainwindow.py:861 msgid "Loading editor..." msgstr "エディタをロードしています..." #: spyder/app/mainwindow.py:867 spyder/plugins/console.py:140 #: spyder/widgets/ipythonconsole/client.py:417 msgid "&Quit" msgstr "終了(&Q)" #: spyder/app/mainwindow.py:869 spyder/plugins/console.py:142 msgid "Quit" msgstr "終了" #: spyder/app/mainwindow.py:873 msgid "&Restart" msgstr "再起動(&R)" #: spyder/app/mainwindow.py:875 msgid "Restart" msgstr "再起動" #: spyder/app/mainwindow.py:889 msgid "Loading file explorer..." msgstr "ファイルエクスプローラーをロードしています..." #: spyder/app/mainwindow.py:896 msgid "Loading history plugin..." msgstr "ヒストリプラグインをロードしています..." #: spyder/app/mainwindow.py:907 msgid "Loading online help..." msgstr "オンラインヘルプをロードしています..." #: spyder/app/mainwindow.py:912 msgid "Loading project explorer..." msgstr "プロジェクトエクスプローラーをロード中..." #: spyder/app/mainwindow.py:925 msgid "Loading namespace browser..." msgstr "名前空間ブラウザをロード中..." #: spyder/app/mainwindow.py:931 msgid "Loading IPython console..." msgstr "IPythonコンソールをロード中..." #: spyder/app/mainwindow.py:936 msgid "Setting up main window..." msgstr "メインウインドウを設定中..." #: spyder/app/mainwindow.py:939 msgid "Dependencies..." msgstr "依存性..." #: spyder/app/mainwindow.py:943 msgid "Report issue..." msgstr "問題をレポート..." #: spyder/app/mainwindow.py:947 msgid "Spyder support..." msgstr "Spyderサポート..." #: spyder/app/mainwindow.py:950 msgid "Check for updates..." msgstr "更新をチェック..." #: spyder/app/mainwindow.py:973 msgid "Spyder documentation" msgstr "spyderドキュメント" #: spyder/app/mainwindow.py:981 msgid "Spyder tutorial" msgstr "Spyderチュートリアル" #: spyder/app/mainwindow.py:986 msgid "Shortcuts Summary" msgstr "ショートカットサマリー" #: spyder/app/mainwindow.py:992 msgid "Interactive tours" msgstr "インタラクティブツアー" #: spyder/app/mainwindow.py:1018 msgid "Python documentation" msgstr "Pythonドキュメント" #: spyder/app/mainwindow.py:1024 msgid "IPython documentation" msgstr "IPythonドキュメント" #: spyder/app/mainwindow.py:1025 msgid "Intro to IPython" msgstr "IPythonの紹介" #: spyder/app/mainwindow.py:1027 msgid "Quick reference" msgstr "クイックリファレンス" #: spyder/app/mainwindow.py:1029 msgid "Console help" msgstr "コンソールヘルプ" #: spyder/app/mainwindow.py:1059 msgid "Installed Python modules" msgstr "インストールされたPythonモジュール" #: spyder/app/mainwindow.py:1063 msgid "Online documentation" msgstr "オンラインドキュメント" #: spyder/app/mainwindow.py:1076 msgid "Qt documentation" msgstr "Qtドキュメント" #: spyder/app/mainwindow.py:1082 msgid "About %s..." msgstr "%s について..." #: spyder/app/mainwindow.py:1113 msgid "Panes" msgstr "ペイン" #: spyder/app/mainwindow.py:1115 msgid "Toolbars" msgstr "ツールバー" #: spyder/app/mainwindow.py:1116 msgid "Window layouts" msgstr "ウインドウレイアウト" #: spyder/app/mainwindow.py:1125 spyder/app/mainwindow.py:1924 #: spyder/app/mainwindow.py:1925 msgid "Show toolbars" msgstr "ツールバーを表示" #: spyder/app/mainwindow.py:1140 msgid "Attached console window (debugging)" msgstr "接続されたコンソールウインドウ(デバッグ)" #: spyder/app/mainwindow.py:1317 spyder/plugins/console.py:220 #: spyder/plugins/projects.py:248 spyder/widgets/explorer.py:708 #: spyder/widgets/explorer.py:813 #: spyder/widgets/variableexplorer/arrayeditor.py:587 #: spyder/widgets/variableexplorer/collectionseditor.py:427 #: spyder/widgets/variableexplorer/dataframeeditor.py:752 #: spyder/widgets/variableexplorer/dataframeeditor.py:756 #: spyder/widgets/variableexplorer/namespacebrowser.py:299 msgid "Error" msgstr "エラー" #: spyder/app/mainwindow.py:1318 msgid "" "You have missing dependencies!

%s

Please " "install them to avoid this message.

Note: Spyder could " "work without some of these dependencies, however to have a smooth experience " "when using Spyder we strongly recommend you to install all the listed " "missing dependencies.

Failing to install these dependencies might " "result in bugs. Please be sure that any found bugs are not the direct result " "of missing dependencies, prior to reporting a new issue." msgstr "" "依存パッケージが見つかりません!

%s

このメッ" "セージ表示を避けるにはこれらのパッケージをインストールしてください。

: Spyderは依存関係を満足させなくても動作しますが、円滑な動" "作のためには依存関係を解決することが 強く 推奨されます。
これらの依" "存パッケージがインストールされていない場合不具合が発生する可能性があります。" "新しい問題を報告する前には、発生した不具合が依存性の欠如によるものではないこ" "とを確認してください。" #: spyder/app/mainwindow.py:1771 msgid "Spyder Default Layout" msgstr "Spyderデフォルトレイアウト" #: spyder/app/mainwindow.py:1789 msgid "Save current layout" msgstr "現在のレイアウトを保存" #: spyder/app/mainwindow.py:1793 msgid "Layout preferences" msgstr "レイアウト設定" #: spyder/app/mainwindow.py:1797 msgid "Reset to spyder default" msgstr "Spyderのデフォルト値に戻す" #: spyder/app/mainwindow.py:1817 spyder/app/mainwindow.py:1839 #: spyder/app/mainwindow.py:1902 spyder/app/mainwindow.py:2722 #: spyder/plugins/configdialog.py:1346 spyder/plugins/ipythonconsole.py:131 #: spyder/plugins/ipythonconsole.py:927 spyder/plugins/ipythonconsole.py:1365 #: spyder/plugins/maininterpreter.py:149 spyder/plugins/maininterpreter.py:174 #: spyder/plugins/maininterpreter.py:203 spyder/utils/environ.py:95 #: spyder/utils/environ.py:108 #: spyder/widgets/ipythonconsole/namespacebrowser.py:131 #: spyder/widgets/ipythonconsole/namespacebrowser.py:149 #: spyder/widgets/variableexplorer/arrayeditor.py:510 #: spyder/widgets/variableexplorer/collectionseditor.py:416 #: spyder/widgets/variableexplorer/collectionseditor.py:1092 msgid "Warning" msgstr "警告" #: spyder/app/mainwindow.py:1818 msgid "" "Window layout will be reset to default settings: this affects window " "position, size and dockwidgets.\n" "Do you want to continue?" msgstr "" "ウインドウレイアウトはデフォルト状態にリセットされます:ウインドウ位置、サイ" "ズ及びドックウィジェットが影響されます。\n" "続行しますか?" #: spyder/app/mainwindow.py:1840 msgid "" "Layout %s will be " "overwritten. Do you want to " "continue?" msgstr "" "レイアウト %sは 上書き" "されます。 続行しますか?" #: spyder/app/mainwindow.py:1903 msgid "Quick switch layout #%s has not yet been defined." msgstr "クイックスイッチレイアウト #%s は未定義です。" #: spyder/app/mainwindow.py:1921 spyder/app/mainwindow.py:1922 msgid "Hide toolbars" msgstr "ツールバーを隠す" #: spyder/app/mainwindow.py:2237 spyder/app/mainwindow.py:2238 msgid "Maximize current pane" msgstr "現在のペインを最大化" #: spyder/app/mainwindow.py:2241 msgid "Restore current pane" msgstr "現在のペインを復元" #: spyder/app/mainwindow.py:2242 msgid "Restore pane to its original size" msgstr "ペインをオリジナルサイズに復元" #: spyder/app/mainwindow.py:2327 msgid "About %s" msgstr "%s について" #: spyder/app/mainwindow.py:2460 spyder/plugins/editor.py:168 #: spyder/plugins/runconfig.py:354 spyder/plugins/runconfig.py:476 #: spyder/utils/programs.py:286 spyder/widgets/explorer.py:335 msgid "Run" msgstr "実行" #: spyder/app/mainwindow.py:2461 msgid "Running an external system terminal is not supported on platform %s." msgstr "" "プラットフォーム %s では外部システムターミナルの実行はサポートされていませ" "ん。" #: spyder/app/mainwindow.py:2723 msgid "" "Spyder will restart and reset to default settings:

Do you want to " "continue?" msgstr "Spyderを再起動して設定をデフォルトに戻します:

続行しますか?" #: spyder/app/mainwindow.py:2851 spyder/widgets/helperwidgets.py:254 msgid "Spyder updates" msgstr "Spyderアップデート" #: spyder/app/mainwindow.py:2852 spyder/plugins/configdialog.py:836 msgid "Check for updates on startup" msgstr "起動時に更新をチェック" #: spyder/app/mainwindow.py:2871 msgid "" "
IMPORTANT NOTE: It seems that you are using Spyder with " "Anaconda/Miniconda. Please don't use pip to " "update it as that will probably break your installation.

Instead, " "please wait until new conda packages are available and use conda to perform the update.
" msgstr "" "
重要: SpyderはAnaconda/Minicondaと使われているようです。" "Spyderをアップデートするためにpipを使うことは避けてで下さ" "い。現在インストールされた環境が壊れる可能性があります。

新しいconda" "パッケージが利用できるまで待ち、condaを使ってアップデートして下" "さい。
" #: spyder/app/mainwindow.py:2881 msgid "" "Spyder %s is available!

Please use your package manager to " "update Spyder or go to our Releases page to download this " "new version.

If you are not sure how to proceed to update Spyder " "please refer to our Installation instructions." msgstr "" "Spyder %s is available!

Please use your package manager to " "update Spyder or go to our Releases page to download this " "new version.

If you are not sure how to proceed to update Spyder " "please refer to our Installation instructions." #: spyder/app/mainwindow.py:2894 msgid "Spyder is up to date." msgstr "Spyderは最新の状態です。" #: spyder/app/restart.py:134 msgid "" "It was not possible to close the previous Spyder instance.\n" "Restart aborted." msgstr "" "前回実行したSpyderを終了できませんでした。\n" "再起動を終了します。" #: spyder/app/restart.py:136 msgid "" "Spyder could not reset to factory defaults.\n" "Restart aborted." msgstr "" "デフォルト設定を適用できませんでした。\n" "再起動を終了します。" #: spyder/app/restart.py:138 msgid "" "It was not possible to restart Spyder.\n" "Operation aborted." msgstr "" "再起動できませんでした。\n" "オペレーションを終了します。" #: spyder/app/restart.py:140 msgid "Spyder exit error" msgstr "Spyder実行エラー" #: spyder/app/restart.py:141 msgid "Spyder reset error" msgstr "Spyderリセットエラー" #: spyder/app/restart.py:142 msgid "Spyder restart error" msgstr "Spyder再起動エラー" #: spyder/app/restart.py:183 msgid "Closing Spyder" msgstr "Spyderを閉じる" #: spyder/app/restart.py:257 msgid "Resetting Spyder to defaults" msgstr "Spyderをデフォルト状態に戻しています" #: spyder/app/restart.py:289 msgid "Restarting" msgstr "再起動中。" #: spyder/app/tour.py:123 msgid "Welcome to the Introduction tour" msgstr "紹介ツアーへようこそ" #: spyder/app/tour.py:124 msgid "" "Spyder is a powerful Interactive Development Environment (or IDE) for " "the Python programming language.

Here we are going to guide you " "through its most important features.

Please use the arrow keys or " "click on the buttons below to move along the tour." msgstr "" "Spyder はPythonプログラミングのためのパワフルな対話型開発環境" "(Interactive Development Environment, IDE) です。

これはもっとも重要" "な機能の紹介です。

ツアーにそって進むには矢印キーを押すか下のボタンを" "クリックしてください。" #: spyder/app/tour.py:133 msgid "The Editor" msgstr "エディタ" #: spyder/app/tour.py:134 msgid "" "This is the pane where you write Python code before evaluating it. You can " "get automatic suggestions and completions while writing, by pressing the " "Tab key next to a given text.

The Editor comes with a line " "number area (highlighted here in red), where Spyder shows warnings and " "syntax errors. They can help you to detect potential problems before running " "the code.

You can also set debug breakpoints in the line number area, " "by doing a double click next to a non-empty line." msgstr "" "これは評価(evaluate)前にPythonコードを書くためのペインです。 入力したテキスト" "の横でタブキーを押すことにより、自動サジェスト及び補完機能を使うことが" "できます。

エディタには行番号エリア(ここでは赤で強調)があり、 警告や文" "法エラーが表示されます。 これらはコード実行前に潜在的な問題を発見する助けとな" "ります。

また行番号エリアの空行以外の場所でダブルクリックすることによ" "り、デバッグのためのブレークポイントを設置することができます。" #: spyder/app/tour.py:149 msgid "The IPython console" msgstr "IPythonコンソール" #: spyder/app/tour.py:150 msgid "" "This is one of panes where you can run or execute the code you wrote on the " "Editor. To do it you need to press the F5 key.

This console " "comes with several useful features that greatly improve your programming " "workflow (like syntax highlighting and inline plots). If you want to know " "more about them, please follow this link.

Please " "click on the button below to run some simple code in this console. This will " "be useful to show you other important features." msgstr "" "これはエディタで入力したコードを実行できるペインの一つです。 コードを実行する" "には F5 キーを押す必要があります。

このコンソールにはプログラミ" "ングを改善するいくつかの有用な機能(構文の強調や行内プロット等)があります。こ" "れらについてもっと知りたい場合はリンク先を参照してくださ" "い。

このコンソール内の単純なコードを動かすために下のボタンをクリック" "してください。 他の重要な機能を見るために役立ちます。" #: spyder/app/tour.py:166 msgid "The Variable Explorer" msgstr "変数エクスプローラー" #: spyder/app/tour.py:167 msgid "" "In this pane you can view and edit the variables generated during the " "execution of a program, or those entered directly in one of Spyder consoles." "

As you can see, the Variable Explorer is showing the variables " "generated during the last step of this tour. By doing a double-click on any " "of them, a new window will be opened, where you can inspect and modify their " "contents." msgstr "" "このペインではプログラム実行中に生成されたり、Spyderコンソールで直接入力され" "たりした変数の表示・編集ができます。

見ての通り変数エクスプローラーは" "このツアー最後のステップで生成された変数を表示しています。表示された変数をダ" "ブルクリックすると新しいウィンドウが開き、変数の中身を調査したり変更したりす" "ることができます。" #: spyder/app/tour.py:179 spyder/plugins/help.py:479 spyder/plugins/help.py:921 #: spyder/widgets/internalshell.py:270 msgid "Help" msgstr "ヘルプ" #: spyder/app/tour.py:180 msgid "" "This pane displays documentation of the functions, classes, methods or " "modules you are currently using in the Editor or the Consoles.

To use " "it, you need to press Ctrl+I in front of an object. If that object " "has some documentation associated with it, it will be displayed here." msgstr "" "このペインは現在エディタやコンソルーで使っている関数、クラス、メソッドあるい" "はモジュールを表示します。

このペインを使うにはオブジェクトの前で " "Ctrl+I を押す必要があります。もしオブジェクトに関連付けられたドキュメ" "ントがある場合ここに表示されます。" #: spyder/app/tour.py:190 msgid "The File Explorer" msgstr "ファイルエクスプローラー" #: spyder/app/tour.py:191 msgid "" "This pane lets you navigate through the directories and files present in " "your computer.

You can also open any of these files with its " "corresponding application, by doing a double click on it.

There is " "one exception to this rule: plain-text files will always be opened in the " "Spyder Editor." msgstr "" "このペインはコンピュータ内のディレクトリとファイルをナビゲートします。" "

ペイン上でダブルクリックすることにより、任意のファイルを対応したアプ" "リケーションで開くことができます。

但しプレーンテキストは常にSpyder " "Editorで開かれるという例外はあります。" #: spyder/app/tour.py:201 msgid "The History Log" msgstr "履歴ログ" #: spyder/app/tour.py:202 msgid "" "This pane records all commands introduced in the Python and IPython consoles." msgstr "" "このペインはPython及びIPythonコンソール内で入力された全てののコマンドを記録し" "ます。" #: spyder/app/tour.py:250 msgid "Spyder is an interactive development environment based on bla" msgstr "" "Spyder はなにか(bla)に基づいた対話型開発環境(Interactive development " "environment)です。" #: spyder/app/tour.py:254 msgid "Welcome to Spyder introduction tour" msgstr "Spyder紹介ツアーへようこそ" #: spyder/app/tour.py:255 msgid "Spyder is an interactive development environment based on bla" msgstr "" "Spyderはなにか(bla)に基づいた対話型開発環境(Interactive development " "environment)です。" #: spyder/app/tour.py:260 msgid "Introduction tour" msgstr "紹介ツアー" #: spyder/app/tour.py:261 msgid "New features in version 3.0" msgstr "バージョン3.0の新機能" #: spyder/app/tour.py:555 spyder/plugins/ipythonconsole.py:446 msgid "Run code" msgstr "コードを実行" #: spyder/app/tour.py:830 msgid "Go to step: " msgstr "ステップへ移動" #: spyder/config/base.py:257 msgid "" "Update LANGUAGE_CODES (inside config/base.py) if a new translation has been " "added to Spyder" msgstr "" "新しい翻訳がSpyderに追加された場合LANGUAGE_CODES (config/base.py内)を更新" #: spyder/config/utils.py:24 msgid "Python files" msgstr "Pythonファイル" #: spyder/config/utils.py:25 msgid "Cython/Pyrex files" msgstr "Cython/Pyrexファイル" #: spyder/config/utils.py:26 msgid "C files" msgstr "Cファイル" #: spyder/config/utils.py:27 msgid "C++ files" msgstr "C++ファイル" #: spyder/config/utils.py:28 msgid "OpenCL files" msgstr "OpenCLファイル" #: spyder/config/utils.py:29 msgid "Fortran files" msgstr "Fortranファイル" #: spyder/config/utils.py:30 msgid "IDL files" msgstr "IDLファイル" #: spyder/config/utils.py:31 msgid "MATLAB files" msgstr "MATLABファイル" #: spyder/config/utils.py:32 msgid "Julia files" msgstr "Juliaファイル" #: spyder/config/utils.py:33 msgid "Yaml files" msgstr "Yamlファイル" #: spyder/config/utils.py:34 msgid "Patch and diff files" msgstr "Patch and diffファイル" #: spyder/config/utils.py:35 msgid "Batch files" msgstr "Batchファイル" #: spyder/config/utils.py:36 spyder/utils/iofuncs.py:426 msgid "Text files" msgstr "テキストファイル" #: spyder/config/utils.py:37 msgid "reStructuredText files" msgstr "reStructuredTextファイル" #: spyder/config/utils.py:38 msgid "gettext files" msgstr "gettextファイル" #: spyder/config/utils.py:39 msgid "NSIS files" msgstr "NSISファイル" #: spyder/config/utils.py:40 msgid "Web page files" msgstr "Webページファイル" #: spyder/config/utils.py:41 msgid "XML files" msgstr "XMLファイル" #: spyder/config/utils.py:42 msgid "Javascript files" msgstr "Javascriptファイル" #: spyder/config/utils.py:43 msgid "Json files" msgstr "Jsonファイル" #: spyder/config/utils.py:44 msgid "IPython notebooks" msgstr "IPython notebooks" #: spyder/config/utils.py:45 msgid "Enaml files" msgstr "Enamlファイル" #: spyder/config/utils.py:46 msgid "Configuration files" msgstr "Configurationファイル" #: spyder/config/utils.py:48 msgid "Markdown files" msgstr "Markdownファイル" #: spyder/config/utils.py:52 spyder/widgets/explorer.py:781 msgid "All files" msgstr "すべてのファイル" #: spyder/config/utils.py:134 msgid "Supported text files" msgstr "サポートされたテキストファイル" #: spyder/plugins/__init__.py:508 spyder/plugins/editor.py:105 #: spyder/plugins/editor.py:568 spyder/plugins/editor.py:1819 #: spyder/plugins/help.py:117 spyder/plugins/help.py:380 #: spyder/widgets/editor.py:534 spyder/widgets/sourcecode/codeeditor.py:98 #: spyder/widgets/sourcecode/codeeditor.py:3193 msgid "Editor" msgstr "エディタ" #: spyder/plugins/configdialog.py:144 msgid "Reset to defaults" msgstr "デフォルト設定へ戻す" #: spyder/plugins/configdialog.py:156 msgid "Preferences" msgstr "設定" #: spyder/plugins/configdialog.py:508 msgid "Invalid directory path" msgstr "不正なディレクトリパス" #: spyder/plugins/configdialog.py:511 spyder/plugins/configdialog.py:526 #: spyder/plugins/runconfig.py:220 spyder/plugins/runconfig.py:268 #: spyder/plugins/workingdirectory.py:240 spyder/widgets/explorer.py:695 #: spyder/widgets/findinfiles.py:494 spyder/widgets/pathmanager.py:258 #: spyder/widgets/projects/projectdialog.py:155 msgid "Select directory" msgstr "ディレクトリを選択" #: spyder/plugins/configdialog.py:538 msgid "Invalid file path" msgstr "不正なファイルパス" #: spyder/plugins/configdialog.py:541 spyder/plugins/configdialog.py:558 msgid "Select file" msgstr "ファイル選択" #: spyder/plugins/configdialog.py:557 msgid "All files (*)" msgstr "全てのファイル (*)" #: spyder/plugins/configdialog.py:630 msgid "Bold" msgstr "ボールド" #: spyder/plugins/configdialog.py:633 msgid "Italic" msgstr "イタリック" #: spyder/plugins/configdialog.py:687 msgid "Font: " msgstr "フォント:" #: spyder/plugins/configdialog.py:693 msgid "Size: " msgstr "サイズ:" #: spyder/plugins/configdialog.py:712 msgid "Font style" msgstr "フォントスタイル" #: spyder/plugins/configdialog.py:789 msgid "Spyder needs to restart to change the following setting:" msgstr "Spyderは以下の設定を適用するために再起動が必要となります:" #: spyder/plugins/configdialog.py:792 msgid "Spyder needs to restart to change the following settings:" msgstr "Spyderは以下の設定を適用するために再起動が必要となります:" #: spyder/plugins/configdialog.py:794 msgid "Do you wish to restart now?" msgstr "直ちに再起動しますか?" #: spyder/plugins/configdialog.py:800 msgid "Information" msgstr "情報" #: spyder/plugins/configdialog.py:814 spyder/plugins/configdialog.py:821 #: spyder/widgets/projects/configdialog.py:74 msgid "General" msgstr "一般" #: spyder/plugins/configdialog.py:824 msgid "Language" msgstr "言語" #: spyder/plugins/configdialog.py:827 msgid "Use a single instance" msgstr "単一インスタンスを使用" #: spyder/plugins/configdialog.py:829 msgid "" "Set this to open external
Python files in an already running instance " "(Requires a restart)" msgstr "" "外部Pythonファイルを実行中の
インスタンスで開くためにこれをセット (再起動" "が必要)" #: spyder/plugins/configdialog.py:832 msgid "Prompt when exiting" msgstr "終了時に確認する" #: spyder/plugins/configdialog.py:833 msgid "Pop up internal console when internal errors appear" msgstr "内部エラー発生時に内部コンソールをポップアップさせる" #: spyder/plugins/configdialog.py:853 spyder/plugins/editor.py:114 #: spyder/plugins/ipythonconsole.py:290 #: spyder/widgets/projects/configdialog.py:81 msgid "Interface" msgstr "インターフェイス" #: spyder/plugins/configdialog.py:861 msgid "Qt windows style" msgstr "Qt windowスタイル" #: spyder/plugins/configdialog.py:867 msgid "Icon theme" msgstr "アイコンテーマ" #: spyder/plugins/configdialog.py:871 msgid "Vertical title bars in panes" msgstr "ペインのタイトルバーを縦にする" #: spyder/plugins/configdialog.py:873 msgid "Vertical tabs in panes" msgstr "ペインのタブを縦にする" #: spyder/plugins/configdialog.py:875 msgid "Animated toolbars and panes" msgstr "ツールバーとペインをアニメーションさせる" #: spyder/plugins/configdialog.py:877 msgid "Tear off menus" msgstr "メニューを切り離す" #: spyder/plugins/configdialog.py:878 msgid "Set this to detach any
menu from the main window" msgstr "メインウインドウから
メニューを切り離すために設定する" #: spyder/plugins/configdialog.py:880 msgid "Custom margin for panes:" msgstr "ペインのマージン調整" #: spyder/plugins/configdialog.py:882 msgid "pixels" msgstr "ピクセル" #: spyder/plugins/configdialog.py:889 msgid "Cursor blinking:" msgstr "カーソルの点滅:" #: spyder/plugins/configdialog.py:891 msgid "ms" msgstr "ms" #: spyder/plugins/configdialog.py:930 msgid "Status bar" msgstr "ステータスバー" #: spyder/plugins/configdialog.py:931 msgid "Show status bar" msgstr "ステータスバーを表示" #: spyder/plugins/configdialog.py:933 msgid "Show memory usage every" msgstr "メモリ使用状況を以下の間隔で更新" #: spyder/plugins/configdialog.py:935 spyder/plugins/configdialog.py:944 #: spyder/plugins/editor.py:139 spyder/plugins/editor.py:283 msgid " ms" msgstr "ms" #: spyder/plugins/configdialog.py:942 msgid "Show CPU usage every" msgstr "CPU使用状況を以下の間隔で更新" #: spyder/plugins/configdialog.py:975 msgid "Screen resolution" msgstr "スクリーン解像度:" #: spyder/plugins/configdialog.py:977 msgid "" "Configuration for high DPI screens

Please see {0}<> for more information about these options (in English)." msgstr "" "高DPIスクリーン設定

これらのオプションのより詳細な情報は以下を参照して" "下さい
{0}<>." #: spyder/plugins/configdialog.py:987 msgid "Normal" msgstr "通常" #: spyder/plugins/configdialog.py:991 msgid "Enable auto high DPI scaling" msgstr "高DPIスケーリング自動設定を有効化" #: spyder/plugins/configdialog.py:994 msgid "Set this for high DPI displays" msgstr "高DPIディスプレイ用にセットする" #: spyder/plugins/configdialog.py:998 msgid "Set a custom high DPI scaling" msgstr "カスタム高DPIスケーリングを設定" #: spyder/plugins/configdialog.py:1001 msgid "Set this for high DPI displays when auto scaling does not work" msgstr "" "自動スケーリングが動作しない場合、高DPIディスプレイ用にこの設定を適用する。" #: spyder/plugins/configdialog.py:1007 msgid "" "Enter values for different screens separated by semicolons ';', float values " "are supported" msgstr "" "他のスクリーンの値(小数点表記も可)をセミコロン';'で区切って入力して下さい。" #: spyder/plugins/configdialog.py:1034 msgid "Plain text font" msgstr "プレーンテキスト" #: spyder/plugins/configdialog.py:1040 msgid "Rich text font" msgstr "リッチテキスト" #: spyder/plugins/configdialog.py:1043 msgid "Fonts" msgstr "フォント" #: spyder/plugins/configdialog.py:1057 msgid "Appearance" msgstr "外見" #: spyder/plugins/configdialog.py:1059 spyder/plugins/ipythonconsole.py:579 msgid "Advanced Settings" msgstr "詳細設定" #: spyder/plugins/configdialog.py:1095 msgid "Syntax coloring" msgstr "構文強調の配色" #: spyder/plugins/configdialog.py:1108 msgid "" "Here you can select the color scheme used in the Editor and all other Spyder " "plugins.

You can also edit the color schemes provided by Spyder or " "create your own ones by using the options provided below.
" msgstr "" "エディタ及びその他全Spyderプラグインで利用する色スキームを選択できます。" "

以下のオプションにより定義済みの色スキームの編集及び独自色スキーム作" "成が実行できます。
" #: spyder/plugins/configdialog.py:1113 msgid "Edit selected" msgstr "選択を編集" #: spyder/plugins/configdialog.py:1114 msgid "Create new scheme" msgstr "新しいスキームを作成" #: spyder/plugins/configdialog.py:1115 spyder/widgets/explorer.py:574 #: spyder/widgets/projects/explorer.py:242 spyder/widgets/shell.py:136 msgid "Delete" msgstr "削除" #: spyder/plugins/configdialog.py:1118 msgid "Reset" msgstr "リセット" #: spyder/plugins/configdialog.py:1125 msgid "Scheme:" msgstr "スキーム:" #: spyder/plugins/configdialog.py:1156 msgid "Manage color schemes" msgstr "色スキームのマネージ" #: spyder/plugins/configdialog.py:1347 msgid "Are you sure you want to delete this scheme?" msgstr "本当にこのスキームを削除しますか?" #: spyder/plugins/configdialog.py:1464 msgid "Text" msgstr "テキスト" #: spyder/plugins/configdialog.py:1466 msgid "Highlight" msgstr "強調" #: spyder/plugins/configdialog.py:1468 msgid "Background" msgstr "背景" #: spyder/plugins/configdialog.py:1472 msgid "Scheme name:" msgstr "スキーム名:" #: spyder/plugins/configdialog.py:1479 msgid "Color scheme editor" msgstr "色スキームエディタ" #: spyder/plugins/console.py:115 msgid "Internal console" msgstr "内部コンソール" #: spyder/plugins/console.py:145 msgid "&Run..." msgstr "実行(&R)" #: spyder/plugins/console.py:147 msgid "Run a Python script" msgstr "Pythonスクリプトを実行" #: spyder/plugins/console.py:150 msgid "Environment variables..." msgstr "環境変数.." #: spyder/plugins/console.py:152 msgid "Show and edit environment variables (for current session)" msgstr "(現在のセッションのため)環境変数を表示・編集する" #: spyder/plugins/console.py:156 msgid "Show sys.path contents..." msgstr "sys.pathの中身を表示..." #: spyder/plugins/console.py:158 msgid "Show (read-only) sys.path" msgstr "sys.pathを読み取り専用で表示" #: spyder/plugins/console.py:161 msgid "Buffer..." msgstr "バッファー..." #: spyder/plugins/console.py:162 spyder/plugins/history.py:43 msgid "Set maximum line count" msgstr "最大行数を設定" #: spyder/plugins/console.py:165 msgid "External editor path..." msgstr "外部エディタのパス..." #: spyder/plugins/console.py:166 msgid "Set external editor executable path" msgstr "外部エディタ実行パスを設定" #: spyder/plugins/console.py:169 spyder/plugins/editor.py:149 #: spyder/plugins/help.py:152 spyder/plugins/help.py:355 #: spyder/plugins/history.py:46 spyder/plugins/history.py:157 msgid "Wrap lines" msgstr "行の折り返し" #: spyder/plugins/console.py:172 spyder/plugins/editor.py:185 #: spyder/plugins/ipythonconsole.py:300 msgid "Display balloon tips" msgstr "バルーンチップを表示" #: spyder/plugins/console.py:176 spyder/plugins/editor.py:179 msgid "Automatic code completion" msgstr "自動コード補完" #: spyder/plugins/console.py:180 spyder/plugins/editor.py:183 msgid "Enter key selects completion" msgstr "Enterキーで補完候補を選択" #: spyder/plugins/console.py:185 msgid "Internal console settings" msgstr "内部コンソール設定" #: spyder/plugins/console.py:221 msgid "" "Spyder has encountered a problem.
Sorry for the inconvenience." "

You can automatically submit this error to our Github issues tracker." "

Note: You need a Github account for that." msgstr "" "spyderで問題が発生しました。
ご不便をおかけします。

エラーの" "情報を自動的にspyderのGithubバグトラックシステムへ送信することができます。" "

注: これを実行するにはあなたのGithubアカウントが必要です。" #: spyder/plugins/console.py:231 msgid "Submit to Github" msgstr "Githubへ送信する" #: spyder/plugins/console.py:283 msgid "Run Python script" msgstr "Pythonスクリプトを実行" #: spyder/plugins/console.py:284 spyder/widgets/explorer.py:796 msgid "Python scripts" msgstr "Pythonスクリプト" #: spyder/plugins/console.py:329 msgid "Buffer" msgstr "バッファー" #: spyder/plugins/console.py:330 msgid "Maximum line count" msgstr "最大行数" #: spyder/plugins/console.py:340 msgid "External editor" msgstr "外部エディタ" #: spyder/plugins/console.py:341 msgid "External editor executable path:" msgstr "外部エディタ実行パス:" #: spyder/plugins/editor.py:59 msgid "Manipulate Jupyter notebooks on the Editor" msgstr "エディタ上でJupyter notebookを操作" #: spyder/plugins/editor.py:111 msgid "Edit template for new modules" msgstr "新規モジュール用テンプレートの編集" #: spyder/plugins/editor.py:116 msgid "Show tab bar" msgstr "タブバーを表示" #: spyder/plugins/editor.py:122 spyder/plugins/editor.py:199 #: spyder/plugins/help.py:151 spyder/plugins/history.py:45 #: spyder/plugins/ipythonconsole.py:332 msgid "Source code" msgstr "ソースコード" #: spyder/plugins/editor.py:123 msgid "Show line numbers" msgstr "行番号を表示" #: spyder/plugins/editor.py:124 spyder/plugins/editor.py:985 msgid "Show blank spaces" msgstr "空白スペースを表示" #: spyder/plugins/editor.py:125 msgid "Show vertical line after" msgstr "縦線を以下の後に表示" #: spyder/plugins/editor.py:126 msgid "characters" msgstr "文字" #: spyder/plugins/editor.py:133 msgid "Highlight current line" msgstr "現在行を強調" #: spyder/plugins/editor.py:135 msgid "Highlight current cell" msgstr "現在セルを強調" #: spyder/plugins/editor.py:137 msgid "Highlight occurrences after" msgstr "以下の事象を強調" #: spyder/plugins/editor.py:169 msgid "Save all files before running script" msgstr "スクリプトを実行前に保存" #: spyder/plugins/editor.py:172 msgid "Run selection" msgstr "選択を実行" #: spyder/plugins/editor.py:173 msgid "Maintain focus in the Editor after running cells or selections" msgstr "エディタ内で実行後、選択後もセルのフォーカスを維持する" #: spyder/plugins/editor.py:176 msgid "Introspection" msgstr "イントロスペクション" #: spyder/plugins/editor.py:181 msgid "Case sensitive code completion" msgstr "コード補完で大文字/小文字を区別" #: spyder/plugins/editor.py:186 msgid "Link to object definition" msgstr "オブジェクトの定義にリンク" #: spyder/plugins/editor.py:188 msgid "" "If this option is enabled, clicking on an object\n" "name (left-click + Ctrl key) will go this object\n" "definition (if resolved)." msgstr "" "このオプションを有効にした場合、オブジェクト名の上で\n" "クリック(left-click + Ctrl key) するとオブジェクトの定義へ\n" "(定義位置が解決できていれば)移動する。" #: spyder/plugins/editor.py:192 msgid "" "Warning:
The Python module rope is not installed on this " "computer: calltips, code completion and go-to-definition features won't be " "available." msgstr "" "警告:
パイソンモジュール rope がこのコンピューターにインス" "トールされていません: 呼び出し情報の表示、コード補完及びgo-to-definition機能" "は利用できません。" #: spyder/plugins/editor.py:200 msgid "Automatic insertion of parentheses, braces and brackets" msgstr "括弧、中括弧、大かっこを自動的に挿入" #: spyder/plugins/editor.py:203 msgid "Automatic insertion of closing quotes" msgstr "引用符を自動的に閉じる" #: spyder/plugins/editor.py:205 msgid "Automatic insertion of colons after 'for', 'if', 'def', etc" msgstr "'for', 'if', 'def'等の後にコロンを自動挿入する" #: spyder/plugins/editor.py:208 msgid "Automatic indentation after 'else', 'elif', etc." msgstr "'else'や'elif'の後を自動的にインデントする" #: spyder/plugins/editor.py:210 msgid "Indentation characters: " msgstr "インデント文字:" #: spyder/plugins/editor.py:211 msgid "2 spaces" msgstr "空白2個" #: spyder/plugins/editor.py:212 msgid "3 spaces" msgstr "空白3個" #: spyder/plugins/editor.py:213 msgid "4 spaces" msgstr "空白4個" #: spyder/plugins/editor.py:214 msgid "5 spaces" msgstr "空白5個" #: spyder/plugins/editor.py:215 msgid "6 spaces" msgstr "空白6個" #: spyder/plugins/editor.py:216 msgid "7 spaces" msgstr "空白7個" #: spyder/plugins/editor.py:217 msgid "8 spaces" msgstr "空白8個" #: spyder/plugins/editor.py:218 msgid "Tabulations" msgstr "一覧表" #: spyder/plugins/editor.py:219 msgid "Tab stop width:" msgstr "タブ幅:" #: spyder/plugins/editor.py:219 msgid "spaces" msgstr "空白" #: spyder/plugins/editor.py:231 msgid "Tab always indent" msgstr "常にインデントにタブを使う" #: spyder/plugins/editor.py:233 msgid "" "If enabled, pressing Tab will always indent,\n" "even when the cursor is not at the beginning\n" "of a line (when this option is enabled, code\n" "completion may be triggered using the alternate\n" "shortcut: Ctrl+Space)" msgstr "" "これを有効にすると、タブキーを押すとカーソルが\n" "行頭になくても常にインデントされる。\n" "(このオプションを有効化した場合、コード補完\n" "のトリガーは別のショートカット\n" "Ctrl+Spaceに変更される)" #: spyder/plugins/editor.py:238 msgid "Intelligent backspace" msgstr "インテリジェントなバックスペース" #: spyder/plugins/editor.py:240 msgid "Automatically remove trailing spaces when saving files" msgstr "ファイル保存時に後続スペースを削除する" #: spyder/plugins/editor.py:244 msgid "Analysis" msgstr "分析" #: spyder/plugins/editor.py:246 msgid "(Refer to the {} page)" msgstr "( {} ページ参照)" #: spyder/plugins/editor.py:251 msgid "Real-time code analysis" msgstr "リアルタイムコード分析" #: spyder/plugins/editor.py:253 msgid "" "

If enabled, Python source code will be analyzed using pyflakes, lines " "containing errors or warnings will be highlighted.

Note: add " "analysis:ignore in a comment to ignore code analysis warnings.

" msgstr "" "

有効にした場合Pythonソースコードはpyflakesで分析され、エラーや警告のある行" "は強調表示されます。

: analysis:ignore をコメントで追加" "すると警告は無視されます。

" #: spyder/plugins/editor.py:261 msgid "Code analysis requires pyflakes %s+" msgstr "コード分析にはpyflakes %s+ が必要です" #: spyder/plugins/editor.py:263 msgid "Real-time code style analysis" msgstr "リアルタイムコードスタイル分析" #: spyder/plugins/editor.py:265 msgid "" "

If enabled, Python source code will be analyzed using pycodestyle, lines " "that are not following PEP8 style guide will be highlighted.

Note: add analysis:ignore in a comment to ignore style analysis " "warnings.

" msgstr "" "

有効にした場合、Pythonソースコードはpycodestyleを使って分析され、PEP8スタ" "イルガイドに適合していない行は強調表示されます。

: 警告を抑制" "するには、analysis:ignore をコメント内に追加してください。

" #: spyder/plugins/editor.py:272 msgid "" "Code annotations (TODO, FIXME, XXX, HINT, TIP, @todo, HACK, BUG, " "OPTIMIZE, !!!, ???)" msgstr "" "コード注釈 (TODO, FIXME, XXX, HINT, TIP, @todo, HACK, BUG, " "OPTIMIZE, !!!, ???)" #: spyder/plugins/editor.py:276 msgid "Perform analysis when saving file and every" msgstr "コード分析をファイル保存時と以下の間隔で実施" #: spyder/plugins/editor.py:280 msgid "Perform analysis only when saving file" msgstr "コード分析をファイル保存時のみ実施" #: spyder/plugins/editor.py:339 msgid "End-of-line characters" msgstr "改行コード" #: spyder/plugins/editor.py:340 msgid "" "When opening a text file containing mixed end-of-line characters (this may " "raise syntax errors in the consoles on Windows platforms), Spyder may fix " "the file automatically." msgstr "" "複数種の改行コードを含むテキストファイル(Windows環境ではコンソールで文法エ" "ラーを起こす可能性があります)を開く場合、Spyderは自動的にこれを修正します。" #: spyder/plugins/editor.py:346 msgid "Fix automatically and show warning message box" msgstr "自動的に修正し、警告をメッセージボックスで表示する" #: spyder/plugins/editor.py:357 spyder/plugins/ipythonconsole.py:573 #: spyder/plugins/variableexplorer.py:35 msgid "Display" msgstr "表示" #: spyder/plugins/editor.py:359 msgid "Code Introspection/Analysis" msgstr "コード イントロスペクション/分析" #: spyder/plugins/editor.py:362 msgid "Advanced settings" msgstr "詳細設定" #: spyder/plugins/editor.py:644 msgid "&New file..." msgstr "新規ファイル(&N)..." #: spyder/plugins/editor.py:645 spyder/widgets/explorer.py:773 #: spyder/widgets/explorer.py:780 msgid "New file" msgstr "新規ファイル" #: spyder/plugins/editor.py:654 msgid "O&pen last closed" msgstr "最後に閉じたファイルを開く(&O)" #: spyder/plugins/editor.py:655 msgid "Open last closed" msgstr "最後に閉じたファイルを開く" #: spyder/plugins/editor.py:661 msgid "&Open..." msgstr "開く(&O)..." #: spyder/plugins/editor.py:662 spyder/plugins/editor.py:1870 #: spyder/plugins/editor.py:1876 msgid "Open file" msgstr "ファイルを開く" #: spyder/plugins/editor.py:668 msgid "&Revert" msgstr "復帰(&R)" #: spyder/plugins/editor.py:669 msgid "Revert file from disk" msgstr "ディスクからファイルを復帰" #: spyder/plugins/editor.py:672 msgid "&Save" msgstr "保存(&S)" #: spyder/plugins/editor.py:673 spyder/widgets/editor.py:1681 msgid "Save file" msgstr "ファイルを保存" #: spyder/plugins/editor.py:679 msgid "Sav&e all" msgstr "全て保存(&E)" #: spyder/plugins/editor.py:680 msgid "Save all files" msgstr "すべてのファイルを保存" #: spyder/plugins/editor.py:686 msgid "Save &as..." msgstr "形式を指定して保存(&A)" #: spyder/plugins/editor.py:687 msgid "Save current file as..." msgstr "現在のファイルを形式を指定して保存..." #: spyder/plugins/editor.py:692 msgid "Save copy as..." msgstr "形式を指定して保存" #: spyder/plugins/editor.py:693 msgid "Save copy of current file as..." msgstr "現在のファイルを形式を指定して保存..." #: spyder/plugins/editor.py:696 spyder/plugins/editor.py:697 msgid "Print preview..." msgstr "プレビューを表示..." #: spyder/plugins/editor.py:698 msgid "&Print..." msgstr "印刷(&P)" #: spyder/plugins/editor.py:699 msgid "Print current file..." msgstr "現在のファイルを印刷..." #: spyder/plugins/editor.py:702 msgid "&Close" msgstr "閉じる(&C)" #: spyder/plugins/editor.py:703 msgid "Close current file" msgstr "現在のファイルを閉じる" #: spyder/plugins/editor.py:706 msgid "C&lose all" msgstr "すべて閉じる(&C)" #: spyder/plugins/editor.py:707 msgid "Close all opened files" msgstr "開いているファイルを全て閉じる" #: spyder/plugins/editor.py:714 msgid "&Find text" msgstr "テキストを検索(&F)" #: spyder/plugins/editor.py:720 msgid "Find &next" msgstr "次を検索(&N)" #: spyder/plugins/editor.py:726 msgid "Find &previous" msgstr "前を検索(&F)" #: spyder/plugins/editor.py:732 msgid "&Replace text" msgstr "テキストを置換(&R)" #: spyder/plugins/editor.py:741 msgid "Set/Clear breakpoint" msgstr "ブレークポイントのセット/クリア" #: spyder/plugins/editor.py:748 msgid "Set/Edit conditional breakpoint" msgstr "条件付きブレークポイントをセット/編集" #: spyder/plugins/editor.py:755 msgid "Clear breakpoints in all files" msgstr "全てのファイルのブレークポイントをクリア" #: spyder/plugins/editor.py:757 msgid "Debug with winpdb" msgstr "winpdbでデバッグ" #: spyder/plugins/editor.py:764 msgid "Debug file" msgstr "ファイルをデバッグ開始" #: spyder/plugins/editor.py:769 msgid "Step" msgstr "Step" #: spyder/plugins/editor.py:770 msgid "Run current line" msgstr "現在行を実行" #: spyder/plugins/editor.py:775 msgid "Continue" msgstr "Continue" #: spyder/plugins/editor.py:777 msgid "Continue execution until next breakpoint" msgstr "次のブレークポイントまで実行を続ける" #: spyder/plugins/editor.py:782 msgid "Step Into" msgstr "Step Into" #: spyder/plugins/editor.py:784 msgid "Step into function or method of current line" msgstr "現在行のメソッド/関数までStep inする" #: spyder/plugins/editor.py:789 msgid "Step Return" msgstr "Step Return" #: spyder/plugins/editor.py:791 msgid "Run until current function or method returns" msgstr "現在行のメソッド/関数までRunする" #: spyder/plugins/editor.py:796 spyder/widgets/findinfiles.py:281 #: spyder/widgets/ipythonconsole/client.py:357 msgid "Stop" msgstr "停止" #: spyder/plugins/editor.py:797 msgid "Stop debugging" msgstr "デバッグを停止" #: spyder/plugins/editor.py:804 msgid "Run file" msgstr "ファイルを実行" #: spyder/plugins/editor.py:809 msgid "&Configuration per file..." msgstr "ファイルごとの設定(&C)" #: spyder/plugins/editor.py:811 msgid "Run settings" msgstr "設定の実行" #: spyder/plugins/editor.py:817 msgid "Re-run &last script" msgstr "最後のスクリプトを再度実行する(&L)" #: spyder/plugins/editor.py:819 msgid "Run again last file" msgstr "最後のファイルを再度実行する" #: spyder/plugins/editor.py:825 spyder/widgets/sourcecode/codeeditor.py:2708 msgid "Run &selection or current line" msgstr "選択範囲あるいは現在のカーソル行を実行(&S)" #: spyder/plugins/editor.py:828 msgid "Run selection or current line" msgstr "選択範囲あるいは現在行を実行" #: spyder/plugins/editor.py:836 spyder/widgets/sourcecode/codeeditor.py:2696 msgid "Run cell" msgstr "cellを実行" #: spyder/plugins/editor.py:839 msgid "" "Run current cell (Ctrl+Enter)\n" "[Use #%% to create cells]" msgstr "" "現在のセルを実行する (Ctrl+Enter)\n" "[Use #%% to create cells]" #: spyder/plugins/editor.py:845 spyder/widgets/sourcecode/codeeditor.py:2700 msgid "Run cell and advance" msgstr "cellを実行し進む" #: spyder/plugins/editor.py:848 msgid "Run current cell and go to the next one (Shift+Enter)" msgstr "現在のセルを実行し次のセルへ(Shift+Enter)" #: spyder/plugins/editor.py:854 spyder/widgets/sourcecode/codeeditor.py:2704 msgid "Re-run last cell" msgstr "最後のcellを再度実行する(" #: spyder/plugins/editor.py:855 msgid "Re run last cell " msgstr "最後のcellを再度実行する" #: spyder/plugins/editor.py:865 msgid "Show todo list" msgstr "TODOリストを表示" #: spyder/plugins/editor.py:866 msgid "" "Show comments list (TODO/FIXME/XXX/HINT/TIP/@todo/HACK/BUG/OPTIMIZE/!!!/???)" msgstr "" "コメントリスト(TODO/FIXME/XXX/HINT/TIP/@todo/HACK/BUG/OPTIMIZE/!!!/???)の表示" #: spyder/plugins/editor.py:874 msgid "Show warning/error list" msgstr "警告/エラー リストを表示" #: spyder/plugins/editor.py:875 msgid "Show code analysis warnings/errors" msgstr "コード分析の 警告/エラー を表示" #: spyder/plugins/editor.py:881 msgid "Previous warning/error" msgstr "前の 警告/表示" #: spyder/plugins/editor.py:882 msgid "Go to previous code analysis warning/error" msgstr "前のコード分析 警告/エラー へ移動" #: spyder/plugins/editor.py:885 msgid "Next warning/error" msgstr "次の 警告/エラー" #: spyder/plugins/editor.py:886 msgid "Go to next code analysis warning/error" msgstr "次のコード分析 警告/エラー へ移動" #: spyder/plugins/editor.py:890 msgid "Last edit location" msgstr "最後に編集した箇所" #: spyder/plugins/editor.py:891 msgid "Go to last edit location" msgstr "最後に編集した箇所へ移動" #: spyder/plugins/editor.py:899 msgid "Previous cursor position" msgstr "前のカーソル位置" #: spyder/plugins/editor.py:900 msgid "Go to previous cursor position" msgstr "前のカーソル位置へ移動" #: spyder/plugins/editor.py:908 msgid "Next cursor position" msgstr "次のカーソル位置" #: spyder/plugins/editor.py:909 msgid "Go to next cursor position" msgstr "次のカーソル位置へ移動" #: spyder/plugins/editor.py:919 spyder/widgets/sourcecode/codeeditor.py:2680 msgid "Comment" msgstr "コメント" #: spyder/plugins/editor.py:919 spyder/widgets/sourcecode/codeeditor.py:2680 msgid "Uncomment" msgstr "コメント解除" #: spyder/plugins/editor.py:920 msgid "Comment current line or selection" msgstr "現在行あるいは選択範囲をコメントアウト" #: spyder/plugins/editor.py:924 msgid "Add &block comment" msgstr "ブロックコメントを追加(&B)" #: spyder/plugins/editor.py:925 msgid "Add block comment around current line or selection" msgstr "ブロックコメントを現在行あるいは選択範囲の周りに追加" #: spyder/plugins/editor.py:931 msgid "R&emove block comment" msgstr "ブロックコメントを削除(&R)" #: spyder/plugins/editor.py:932 msgid "Remove comment block around current line or selection" msgstr "現在行あるいは選択範囲の周りのブロックコメントを削除" #: spyder/plugins/editor.py:943 msgid "Indent" msgstr "インデント" #: spyder/plugins/editor.py:944 msgid "Indent current line or selection" msgstr "現在行あるいは選択範囲をインデント" #: spyder/plugins/editor.py:947 msgid "Unindent" msgstr "インデント解除" #: spyder/plugins/editor.py:948 msgid "Unindent current line or selection" msgstr "現在行あるいは選択範囲をインデント解除" #: spyder/plugins/editor.py:952 msgid "Toggle Uppercase" msgstr "大文字に変更する" #: spyder/plugins/editor.py:953 msgid "Change to uppercase current line or selection" msgstr "選択範囲あるいは現在行を大文字化" #: spyder/plugins/editor.py:959 msgid "Toggle Lowercase" msgstr "小文字に変更する" #: spyder/plugins/editor.py:960 msgid "Change to lowercase current line or selection" msgstr "選択範囲あるいは現在行を小文字化" #: spyder/plugins/editor.py:967 msgid "Carriage return and line feed (Windows)" msgstr "CR+LF (Windows)" #: spyder/plugins/editor.py:970 msgid "Line feed (UNIX)" msgstr "LF (UNIX)" #: spyder/plugins/editor.py:973 msgid "Carriage return (Mac)" msgstr "CR (Mac)" #: spyder/plugins/editor.py:979 msgid "Convert end-of-line characters" msgstr "改行コードを変換する" #: spyder/plugins/editor.py:983 msgid "Remove trailing spaces" msgstr "無駄な後続スペースを削除" #: spyder/plugins/editor.py:987 msgid "Fix indentation" msgstr "インデントを修正" #: spyder/plugins/editor.py:988 msgid "Replace tab characters by space characters" msgstr "タブ文字を空白に置換" #: spyder/plugins/editor.py:991 msgid "Go to line..." msgstr "行へ移動..." #: spyder/plugins/editor.py:999 msgid "Set console working directory" msgstr "コンソールの作業ディレクトリをセット" #: spyder/plugins/editor.py:1001 msgid "" "Set current console (and file explorer) working directory to current script " "directory" msgstr "" "コンソール(とファイルエクスプローラー)の作業ディレクトリを現在のスクリプトの" "ディレクトリにセット" #: spyder/plugins/editor.py:1006 msgid "Maximum number of recent files..." msgstr "「最近使用したファイル」の最大履歴数..." #: spyder/plugins/editor.py:1009 msgid "Clear recent files list" msgstr "最近使用したファイルのリストをクリア" #: spyder/plugins/editor.py:1009 spyder/plugins/projects.py:102 msgid "Clear this list" msgstr "このリストをクリア" #: spyder/plugins/editor.py:1013 msgid "Open &recent" msgstr "最近使用したファイル(&R)" #: spyder/plugins/editor.py:1678 msgid "Spyder Editor" msgstr "Spyderエディタ" #: spyder/plugins/editor.py:1679 msgid "This is a temporary script file." msgstr "これは一時的なスクリプトファイルです" #: spyder/plugins/editor.py:1748 msgid "untitled" msgstr "タイトル無し" #: spyder/plugins/editor.py:1820 msgid "Maximum number of recent files" msgstr "「最近使用したファイル」の最大履歴数" #: spyder/plugins/editor.py:1966 msgid "Printing..." msgstr "印刷中..." #: spyder/plugins/explorer.py:54 msgid "File explorer" msgstr "ファイルエクスプローラー" #: spyder/plugins/findinfiles.py:119 spyder/widgets/findinfiles.py:829 msgid "Find in files" msgstr "ファイルの検索" #: spyder/plugins/findinfiles.py:143 msgid "&Find in files" msgstr "ファイル内を検索(&F)" #: spyder/plugins/findinfiles.py:146 msgid "Search text in multiple files" msgstr "複数のファイルからテキストを検索" #: spyder/plugins/help.py:43 msgid "Show help for objects in the Editor and Consoles in a dedicated pane" msgstr "専用ペインでエディタ・コンソール中のオブジェクトのヘルプを表示する" #: spyder/plugins/help.py:109 msgid "Automatic connections" msgstr "自動接続" #: spyder/plugins/help.py:110 msgid "" "This pane can automatically show an object's help information after a left " "parenthesis is written next to it. Below you can decide to which plugin you " "want to connect it to turn on this feature." msgstr "" "このペインは括弧の左側が入力されるとそのオブジェクトのヘルプ情報を自動的に表" "示します。この機能を有効にするために接続したいプラグインを選べます。" #: spyder/plugins/help.py:122 msgid "" "This feature requires the Rope or Jedi libraries.\n" "It seems you don't have either installed." msgstr "" "この機能はRopeあるいはJediライブラリを必要とします。\n" "どちらもインストールされていないようです。" #: spyder/plugins/help.py:125 msgid "IPython Console" msgstr "IPythonコンソール" #: spyder/plugins/help.py:135 msgid "Additional features" msgstr "追加機能" #: spyder/plugins/help.py:136 msgid "Render mathematical equations" msgstr "数式を描画" #: spyder/plugins/help.py:142 msgid "This feature requires Sphinx 1.1 or superior." msgstr "この機能はSphinx 1.1以上を必要とします。" #: spyder/plugins/help.py:143 msgid "Sphinx %s is currently installed." msgstr "Sphinx %s が現在インストールされています。" #: spyder/plugins/help.py:304 msgid "No further documentation available" msgstr "これ以上のドキュメントはありません" #: spyder/plugins/help.py:342 msgid "No documentation available" msgstr "利用可能なドキュメントはありません" #: spyder/plugins/help.py:373 msgid "Source" msgstr "ソース" #: spyder/plugins/help.py:380 spyder/plugins/runconfig.py:170 #: spyder/plugins/runconfig.py:486 spyder/widgets/ipythonconsole/client.py:291 msgid "Console" msgstr "コンソール" #: spyder/plugins/help.py:388 msgid "Object" msgstr "オブジェクト" #: spyder/plugins/help.py:402 msgid "Plain Text" msgstr "プレーンテキスト" #: spyder/plugins/help.py:406 msgid "Show Source" msgstr "ソースを表示" #: spyder/plugins/help.py:410 msgid "Rich Text" msgstr "リッチテキスト" #: spyder/plugins/help.py:420 msgid "Automatic import" msgstr "自動インポート" #: spyder/plugins/help.py:432 spyder/plugins/history.py:106 #: spyder/widgets/editor.py:720 spyder/widgets/explorer.py:1187 #: spyder/widgets/ipythonconsole/client.py:381 #: spyder/widgets/variableexplorer/namespacebrowser.py:148 msgid "Options" msgstr "オプション" #: spyder/plugins/help.py:687 msgid "" "Here you can get help of any object by pressing %s in front of it, either on " "the Editor or the Console.%sHelp can also be shown automatically after " "writing a left parenthesis next to an object. You can activate this behavior " "in %s." msgstr "" "エディタあるいはコンソールでは %s を直前で押すことで直後のオブジェクトのヘル" "プが得られます。%s ヘルプはオブジェクトの隣で左括弧を入力することでも自動的に" "表示されます。%sでこの機能を有効化できます。" #: spyder/plugins/help.py:693 msgid "Preferences > Help" msgstr "設定 > ヘルプ" #: spyder/plugins/help.py:700 msgid "Usage" msgstr "使用法" #: spyder/plugins/help.py:701 msgid "New to Spyder? Read our" msgstr "Spypderは初めてですか? 読んでください。" #: spyder/plugins/help.py:702 msgid "tutorial" msgstr "チュートリアル" #: spyder/plugins/help.py:709 msgid "" "Please consider installing Sphinx to get documentation rendered in rich text." msgstr "" "ドキュメントをリッチテキストで表示するためにSphinxをインストールした方が良い" "でしょう。" #: spyder/plugins/help.py:878 msgid "Lock" msgstr "ロック" #: spyder/plugins/help.py:878 msgid "Unlock" msgstr "アンロック" #: spyder/plugins/help.py:922 msgid "" "The following error occured when calling Sphinx %s.
Incompatible " "Sphinx version or doc string decoding failed.

Error message:
%s" msgstr "" "以下のエラーは Sphinx %s を呼んだ時に発生しました。
Sphinxのバー" "ジョンが合っていないか文字列のデコードに失敗しました。

エラーメッセー" "ジ:
%s" #: spyder/plugins/help.py:966 msgid "No source code available." msgstr "ソースコードが利用できません" #: spyder/plugins/history.py:39 msgid "Settings" msgstr "設定" #: spyder/plugins/history.py:41 msgid " entries" msgstr " エントリ" #: spyder/plugins/history.py:41 msgid "History depth: " msgstr "ヒストリー階層:" #: spyder/plugins/history.py:48 msgid "Scroll automatically to last entry" msgstr "最後のエントリーまで自動的にスクロール" #: spyder/plugins/history.py:126 msgid "History log" msgstr "ヒストリログ" #: spyder/plugins/history.py:153 msgid "History..." msgstr "ヒストリ..." #: spyder/plugins/history.py:155 msgid "Set history maximum entries" msgstr "ヒストリの最大エントリ数" #: spyder/plugins/history.py:260 msgid "History" msgstr "ヒストリ" #: spyder/plugins/history.py:261 msgid "Maximum entries" msgstr "最大エントリ数" #: spyder/plugins/ipythonconsole.py:65 msgid "Symbolic mathematics in the IPython Console" msgstr "IPythonコンソールでの記号数学" #: spyder/plugins/ipythonconsole.py:69 msgid "Run Cython files in the IPython Console" msgstr "CythonファイルをIPythonコンソールで実行" #: spyder/plugins/ipythonconsole.py:73 msgid "Integrate the IPython console" msgstr "IPythonコンソールを統合" #: spyder/plugins/ipythonconsole.py:77 msgid "IPython interactive python environment" msgstr "IPythonインタラクティブpython環境" #: spyder/plugins/ipythonconsole.py:128 msgid "" "The authenticity of host %s can't be established. Are you sure you " "want to continue connecting?" msgstr "ホスト %s の信頼性が確立できません。本当に接続を続けますか?" #: spyder/plugins/ipythonconsole.py:140 msgid "The authenticity of the host can't be established" msgstr "ホストの信頼性が確立できません" #: spyder/plugins/ipythonconsole.py:147 msgid "Tunnel '%s' failed to start" msgstr "Tunnel '%s' は開始できませんでした" #: spyder/plugins/ipythonconsole.py:152 msgid "Could not connect to remote host" msgstr "リモートホストへ接続できませんでした" #: spyder/plugins/ipythonconsole.py:169 spyder/plugins/ipythonconsole.py:799 msgid "Connect to an existing kernel" msgstr "既存のカーネルに接続" #: spyder/plugins/ipythonconsole.py:171 msgid "" "Please enter the connection info of the kernel you want to connect to. For " "that you can either select its JSON connection file using the Browse button, or write directly its id, in case it's a local kernel (for " "example kernel-3764.json or just 3764)." msgstr "" "接続したいカーネルの接続情報を入力してください。 表示 ボタンを押し、" "JSON接続ファイルを選ぶか、ローカルカーネルの場合IDを入力してください (例: " "kernel-3764.json あるいは 3764)。" #: spyder/plugins/ipythonconsole.py:182 msgid "Connection info:" msgstr "接続情報:" #: spyder/plugins/ipythonconsole.py:184 msgid "Path to connection file or kernel id" msgstr "接続ファイルへのパスあるいはカーネルID" #: spyder/plugins/ipythonconsole.py:186 spyder/plugins/ipythonconsole.py:203 msgid "Browse" msgstr "表示" #: spyder/plugins/ipythonconsole.py:195 msgid "This is a remote kernel" msgstr "これはリモートカーネルです" #: spyder/plugins/ipythonconsole.py:199 msgid "username@hostname:port" msgstr "username@hostname:port" #: spyder/plugins/ipythonconsole.py:202 msgid "Path to ssh key file" msgstr "sshキーファイルへのパス" #: spyder/plugins/ipythonconsole.py:211 msgid "Password or ssh key passphrase" msgstr "パスワードあるいはsshキーのパスフレーズ" #: spyder/plugins/ipythonconsole.py:215 msgid "Host name" msgstr "ホスト名" #: spyder/plugins/ipythonconsole.py:216 msgid "Ssh key" msgstr "sshキー" #: spyder/plugins/ipythonconsole.py:217 msgid "Password" msgstr "パスワード" #: spyder/plugins/ipythonconsole.py:246 msgid "Open connection file" msgstr "IPython接続ファイルを開く" #: spyder/plugins/ipythonconsole.py:251 msgid "Select ssh key" msgstr "sshキーを選択" #: spyder/plugins/ipythonconsole.py:284 spyder/plugins/ipythonconsole.py:734 msgid "IPython console" msgstr "IPythonコンソール" #: spyder/plugins/ipythonconsole.py:291 msgid "Display initial banner" msgstr "初期バナーの表示" #: spyder/plugins/ipythonconsole.py:292 msgid "" "This option lets you hide the message shown at\n" "the top of the console when it's opened." msgstr "" "このオプションによりコンソールを開いた時に表示される\n" "一番上のメッセージを隠すことができます。" #: spyder/plugins/ipythonconsole.py:294 msgid "Use a pager to display additional text inside the console" msgstr "コンソール内で追加テキストを表示するためにページャーを使用" #: spyder/plugins/ipythonconsole.py:296 msgid "" "Useful if you don't want to fill the console with long help or completion " "texts.\n" "Note: Use the Q key to get out of the pager." msgstr "" "補完テキストや長いヘルプでコンソールを埋めたくない場合有効です。\n" "注: このページャーから出るには Qキーを押してください。" #: spyder/plugins/ipythonconsole.py:301 msgid "Ask for confirmation before closing" msgstr "閉じる前に確認するようにする" #: spyder/plugins/ipythonconsole.py:304 msgid "Ask for confirmation before removing all user-defined variables" msgstr "全ユーザー定義変数を削除する前に確認する" #: spyder/plugins/ipythonconsole.py:307 msgid "" "This option lets you hide the warning message shown\n" "when resetting the namespace from Spyder." msgstr "" "このオプションによりSpyderから名前空間をリセットするときの\n" "警告メッセージを隠すことができます。" #: spyder/plugins/ipythonconsole.py:309 #: spyder/widgets/ipythonconsole/client.py:320 msgid "Show elapsed time" msgstr "実行時間を表示" #: spyder/plugins/ipythonconsole.py:320 msgid "Completion Type" msgstr "補完タイプ" #: spyder/plugins/ipythonconsole.py:321 msgid "Decide what type of completion to use" msgstr "どのタイプの補完を使うか選択" #: spyder/plugins/ipythonconsole.py:323 msgid "Graphical" msgstr "グラフィックス" #: spyder/plugins/ipythonconsole.py:323 msgid "Plain" msgstr "プレーンテキスト" #: spyder/plugins/ipythonconsole.py:323 msgid "Terminal" msgstr "ターミナル" #: spyder/plugins/ipythonconsole.py:324 msgid "Completion:" msgstr "補完:" #: spyder/plugins/ipythonconsole.py:334 msgid " lines" msgstr "行" #: spyder/plugins/ipythonconsole.py:334 msgid "Buffer: " msgstr "バッファー:" #: spyder/plugins/ipythonconsole.py:336 msgid "" "Set the maximum number of lines of text shown in the\n" "console before truncation. Specifying -1 disables it\n" "(not recommended!)" msgstr "" "コンソール内で表示するテキストの最大行数を設定。\n" "-1 を設定すると無効になります\n" "(非推奨です!)" #: spyder/plugins/ipythonconsole.py:345 msgid "Support for graphics (Matplotlib)" msgstr "画像のサポート(Matplotlib)" #: spyder/plugins/ipythonconsole.py:346 msgid "Activate support" msgstr "サポートを有効化" #: spyder/plugins/ipythonconsole.py:347 msgid "Automatically load Pylab and NumPy modules" msgstr "Pylab, NumPyモジュールを自動的にロード" #: spyder/plugins/ipythonconsole.py:350 msgid "" "This lets you load graphics support without importing \n" "the commands to do plots. Useful to work with other\n" "plotting libraries different to Matplotlib or to develop \n" "GUIs with Spyder." msgstr "" "プロットコマンドをインポートすることなしに画像サポートを\n" "有効にします。Matplotlib以外のプロットライブラリを利用\n" "している場合や、SpyderでGUIを開発している場合、\n" "有用です。" #: spyder/plugins/ipythonconsole.py:365 msgid "Inline" msgstr "インライン" #: spyder/plugins/ipythonconsole.py:366 msgid "Automatic" msgstr "自動" #: spyder/plugins/ipythonconsole.py:367 msgid "Graphics backend" msgstr "グラフィックスのバックエンド" #: spyder/plugins/ipythonconsole.py:368 msgid "" "Decide how graphics are going to be displayed in the console. If unsure, " "please select %s to put graphics inside the console or %s to " "interact with them (through zooming and panning) in a separate window." msgstr "" "コンソール内でどのように画像を表示するか選んでください。よくわからなければ、" "コンソール内で画像を表示したい場合 %s を選び、別ウィンドウで(ズーム、" "パン等)操作したい場合は %s を選んでください。" #: spyder/plugins/ipythonconsole.py:388 msgid "Backend:" msgstr "バックエンド:" #: spyder/plugins/ipythonconsole.py:390 msgid "This option will be applied the next time a console is opened." msgstr "このオプションは次にコンソールを開いた時に適用されます" #: spyder/plugins/ipythonconsole.py:401 msgid "Inline backend" msgstr "インラインのバックエンド" #: spyder/plugins/ipythonconsole.py:402 msgid "Decide how to render the figures created by this backend" msgstr "このバックエンドで生成された画像をどのように描画するか選択" #: spyder/plugins/ipythonconsole.py:406 msgid "Format:" msgstr "フォーマット:" #: spyder/plugins/ipythonconsole.py:409 msgid "Resolution:" msgstr "解像度:" #: spyder/plugins/ipythonconsole.py:409 msgid "dpi" msgstr "dpi" #: spyder/plugins/ipythonconsole.py:411 msgid "Only used when the format is PNG. Default is 72" msgstr "PNGフォーマットの場合のみ使われます。デフォルトは72" #: spyder/plugins/ipythonconsole.py:414 msgid "Width:" msgstr "幅:" #: spyder/plugins/ipythonconsole.py:414 spyder/plugins/ipythonconsole.py:418 msgid "inches" msgstr "インチ" #: spyder/plugins/ipythonconsole.py:416 msgid "Default is 6" msgstr "デフォルトは6です" #: spyder/plugins/ipythonconsole.py:418 msgid "Height:" msgstr "高さ:" #: spyder/plugins/ipythonconsole.py:420 msgid "Default is 4" msgstr "デフォルトは4です" #: spyder/plugins/ipythonconsole.py:447 msgid "" "You can run several lines of code when a console is started. Please " "introduce each one separated by commas, for example:
import os, import " "sys" msgstr "" "コンソールを開始した時にコードを実行できます。それぞれをコンマで区切ってくだ" "さい。例:
import os, import sys" #: spyder/plugins/ipythonconsole.py:453 msgid "Lines:" msgstr "行:" #: spyder/plugins/ipythonconsole.py:462 msgid "Run a file" msgstr "ファイルを実行" #: spyder/plugins/ipythonconsole.py:463 msgid "" "You can also run a whole file at startup instead of just some lines (This is " "similar to have a PYTHONSTARTUP file)." msgstr "" "行の一部だけではなくファイル全体をスタート時に実行できます(PYTHONSTARTUPファ" "イルと類似)" #: spyder/plugins/ipythonconsole.py:467 msgid "Use the following file:" msgstr "以下のファイルを使う:" #: spyder/plugins/ipythonconsole.py:481 msgid "Greedy completion" msgstr "Greedy completion" #: spyder/plugins/ipythonconsole.py:482 msgid "" "Enable Tab completion on elements of lists, results of function " "calls, etc, without assigning them to a variable.
For example, you " "can get completions on things like li[0].<Tab> or ins." "meth().<Tab>" msgstr "" "リスト要素、関数呼び出し結果等を変数に割り当てずにTab 補完" "を有効にする。
例えば li[0].<Tab>ins.meth().<" "Tab> のように補完できる" #: spyder/plugins/ipythonconsole.py:490 msgid "Use the greedy completer" msgstr "greedy completerを利用する" #: spyder/plugins/ipythonconsole.py:501 msgid "Autocall" msgstr "Autocall" #: spyder/plugins/ipythonconsole.py:502 msgid "" "Autocall makes IPython automatically call any callable object even if you " "didn't type explicit parentheses.
For example, if you type str 43 " "it becomes str(43) automatically." msgstr "" "明示的に括弧を省略している場合でも、IPythonで呼び出し可能なオブジェクトを" "Autocallによって自動的に呼ぶ。
例えば、str 43 と入力すると自動的" "に str(43) となる。" #: spyder/plugins/ipythonconsole.py:509 msgid "Smart" msgstr "Smart" #: spyder/plugins/ipythonconsole.py:510 msgid "Full" msgstr "Full" #: spyder/plugins/ipythonconsole.py:511 msgid "Off" msgstr "オフ" #: spyder/plugins/ipythonconsole.py:513 msgid "Autocall: " msgstr "Autocall:" #: spyder/plugins/ipythonconsole.py:514 msgid "" "On %s mode, Autocall is not applied if there are no arguments after " "the callable. On %s mode, all callable objects are automatically " "called (even if no arguments are present)." msgstr "" "%s モードでは、 呼び出し可能オブジェクトに引数がない場合Autocallは適用" "されません。 %s モードでは、(引数がない場合でも)全ての呼び出し可能オブ" "ジェクトが自動的に呼ばれます。" #: spyder/plugins/ipythonconsole.py:526 msgid "Symbolic Mathematics" msgstr "記号数学" #: spyder/plugins/ipythonconsole.py:527 msgid "" "Perfom symbolic operations in the console (e.g. integrals, derivatives, " "vector calculus, etc) and get the outputs in a beautifully printed style (it " "requires the Sympy module)." msgstr "" "記号演算をコンソール内で実行し(例:積分、微分、ベクトル演算等)、整えられた印刷" "可能スタイルで出力する(要Sympyモジュール)。" #: spyder/plugins/ipythonconsole.py:532 msgid "Use symbolic math" msgstr "記号演算を使う" #: spyder/plugins/ipythonconsole.py:533 msgid "" "This option loads the Sympy library to work with.
Please refer to its " "documentation to learn how to use it." msgstr "" "このオプションはSympyライブラリをロードします。
Sympyドキュメントを参照" "し、使用方法を学んでください。" #: spyder/plugins/ipythonconsole.py:543 msgid "Prompts" msgstr "プロンプト" #: spyder/plugins/ipythonconsole.py:544 msgid "Modify how Input and Output prompts are shown in the console." msgstr "プロンプトの入力と出力のコンソール内での表示を変更する。" #: spyder/plugins/ipythonconsole.py:547 msgid "Input prompt:" msgstr "入力プロンプト:" #: spyder/plugins/ipythonconsole.py:549 msgid "" "Default is
In [<span class=\"in-prompt-number\">%i</span>]:" msgstr "" "デフォルトは
In [<span class=\"in-prompt-number\">%i</span>]:" #: spyder/plugins/ipythonconsole.py:553 msgid "Output prompt:" msgstr "出力プロンプト:" #: spyder/plugins/ipythonconsole.py:555 msgid "" "Default is
Out[<span class=\"out-prompt-number\">%i</span>]:" msgstr "" "デフォルトは
Out[<span class=\"out-prompt-number\">%i</span>]:" #: spyder/plugins/ipythonconsole.py:575 msgid "Graphics" msgstr "グラフィックス" #: spyder/plugins/ipythonconsole.py:577 msgid "Startup" msgstr "スタートアップ" #: spyder/plugins/ipythonconsole.py:604 msgid "" "The directory {} is not writable and it is required to create IPython " "consoles. Please make it writable." msgstr "" "IPythonコンソール作成に必要なディクショナリ{}が書き込み不可になっています。書" "き込み可能に変更して下さい" #: spyder/plugins/ipythonconsole.py:784 msgid "Open an &IPython console" msgstr "IPythonコンソールを開く(&I)" #: spyder/plugins/ipythonconsole.py:791 msgid "Restart kernel" msgstr "カーネルの再起動" #: spyder/plugins/ipythonconsole.py:800 msgid "Open a new IPython console connected to an existing kernel" msgstr "既存カーネルに接続された新規IPythonコンソールを開く" #: spyder/plugins/ipythonconsole.py:803 msgid "Rename tab" msgstr "タブをリネーム" #: spyder/plugins/ipythonconsole.py:928 msgid "" "No IPython console is currently available to run %s.

Please " "open a new one and try again." msgstr "" "現在%s実行可能なIPythonコンソールがありません。.

新規に開いて再" "試行してください。" #: spyder/plugins/ipythonconsole.py:1018 msgid "" "Your Python environment or installation doesn't have the ipykernel " "and cloudpickle modules installed on it. Without these modules is " "not possible for Spyder to create a console for you.

You can install " "them by running in a system terminal:

pip install ipykernel " "cloudpickle

or

conda install ipykernel cloudpickle" msgstr "" "Python環境にipykernelcloudpickle モジュールがインストール" "されていません。これらのモジュールがない場合Spyderでコンソールを開くことがで" "きない場合があります。

システムのターミナルで以下のコマンドでインス" "トールすることが可能です。:

pip install ipykernel cloudpickle

あるいは

conda install ipykernel cloudpickle" #: spyder/plugins/ipythonconsole.py:1295 msgid "Do you want to close this console?" msgstr "本当にこのコンソールを閉じますか?" #: spyder/plugins/ipythonconsole.py:1301 msgid "" "Do you want to close all other consoles connected to the same kernel as this " "one?" msgstr "同じカーネルに接続している他の全てのコンソールを閉じますか?" #: spyder/plugins/ipythonconsole.py:1366 msgid "" "It was not possible to restart the IPython console when switching to this " "project. The error was {0}" msgstr "" "プロジェクト切替時にIPythonコンソールの再起動に失敗しました。エラー {0}" #: spyder/plugins/ipythonconsole.py:1467 msgid "" "This error was most probably caused by installing Spyder in a directory with " "non-ascii characters (i.e. characters with tildes, apostrophes or non-latin " "symbols).

To fix it, please reinstall Spyder in a different " "location." msgstr "" "このエラーはおそらくSpyderを非ASCII文字を名前に含むディレクトリにインストール" "していることによって発生しています。br>
解決するにはSpyderを他の場所に" "再インストール して下さい。" #: spyder/plugins/ipythonconsole.py:1659 msgid "IPython" msgstr "IPython" #: spyder/plugins/ipythonconsole.py:1660 msgid "Unable to connect to %s" msgstr "%sに接続できませんでした" #: spyder/plugins/ipythonconsole.py:1730 msgid "Connection error" msgstr "接続エラー" #: spyder/plugins/ipythonconsole.py:1731 msgid "" "Could not open ssh tunnel. The error was:\n" "\n" msgstr "" "sshトンネルを開けませんでした。エラー:\n" "\n" #: spyder/plugins/layoutdialog.py:177 msgid "Move Up" msgstr "上へ移動" #: spyder/plugins/layoutdialog.py:178 msgid "Move Down" msgstr "下へ移動" #: spyder/plugins/layoutdialog.py:179 msgid "Delete Layout" msgstr "レイアウトの削除" #: spyder/plugins/layoutdialog.py:183 msgid "Layout Display and Order" msgstr "レイアウトの表示と順序" #: spyder/plugins/maininterpreter.py:31 spyder/plugins/maininterpreter.py:66 msgid "Python interpreter" msgstr "Pythonインタープリター" #: spyder/plugins/maininterpreter.py:68 msgid "Select the Python interpreter for all Spyder consoles" msgstr "Spyderコンソールで使用するPythonインタープリターの選択" #: spyder/plugins/maininterpreter.py:71 msgid "Default (i.e. the same as Spyder's)" msgstr "デフォルト(=Spyderと同じ)" #: spyder/plugins/maininterpreter.py:74 msgid "Use the following Python interpreter:" msgstr "以下のPythonインタープリターを使う" #: spyder/plugins/maininterpreter.py:77 msgid "Executables" msgstr "実行可能ファイル" #: spyder/plugins/maininterpreter.py:94 msgid "User Module Reloader (UMR)" msgstr "モジュールリローダーを使用(UMR)" #: spyder/plugins/maininterpreter.py:95 msgid "" "UMR forces Python to reload modules which were imported when executing a " "file in a Python or IPython console with the runfile function." msgstr "" "PythonあるいはIPythonでrunfileを使うスクリプトをインポートする時、UMR" "はモジュール再読み込みを強制します。" #: spyder/plugins/maininterpreter.py:100 msgid "Enable UMR" msgstr "UMRを有効化" #: spyder/plugins/maininterpreter.py:101 msgid "" "This option will enable the User Module Reloader (UMR) in Python/IPython " "consoles. UMR forces Python to reload deeply modules during import when " "running a Python script using the Spyder's builtin function runfile." "

1. UMR may require to restart the console in which it will be " "called (otherwise only newly imported modules will be reloaded when " "executing files).

2. If errors occur when re-running a PyQt-" "based program, please check that the Qt objects are properly destroyed (e.g. " "you may have to use the attribute Qt.WA_DeleteOnClose on your main " "window, using the setAttribute method)" msgstr "" "このオプションはPython/IPython コンソールでのユーザーモジュールリローダー " "(UMR)を有効化します。UMRはSpyderの組み込み関数runfileを使うPythonスク" "リプトを実行する場合、インポート時にモジュールの再読み込みを強制します。" "

1. UMRは実行するコンソールの再起動を必要とする場合が有ります" "(あるいはスクリプト実行時に新しくインポートされたモジュールのみが再読み込みさ" "れます)。

2. PyQtを使ったプログラムの再実行時にエラーが発生した" "場合、Qtオブジェクトが適切に破棄されているか確認してください。(例: " "setAttributeメソッドを使ってアトリビュートQt.WA_DeleteOnClose " "をメインウインドウに適用するなど)" #: spyder/plugins/maininterpreter.py:117 msgid "Show reloaded modules list" msgstr "再読込されたモジュールのリストを表示" #: spyder/plugins/maininterpreter.py:118 msgid "Please note that these changes will be applied only to new consoles" msgstr "これらの変更は新規コンソールのみに適用されることに注意してください" #: spyder/plugins/maininterpreter.py:122 msgid "Set UMR excluded (not reloaded) modules" msgstr "UMRから排除される(=再読込されない)モジュールを設定" #: spyder/plugins/maininterpreter.py:150 msgid "" "You selected an invalid Python interpreter for the console so the previous " "interpreter will stay. Please make sure to select a valid one." msgstr "" "無効なPythonインタープリターが選択されたためインタープリターは変更されませ" "ん。有効なものを選択して下さい。" #: spyder/plugins/maininterpreter.py:175 msgid "" "You selected a Python %d interpreter for the console but Spyder is " "running on Python %d!.

Although this is possible, we recommend " "you to install and run Spyder directly with your selected interpreter, to " "avoid seeing false warnings and errors due to the incompatible syntax " "between these two Python versions." msgstr "" "コンソール用にPython %dインタープリターが選択されましたがSpyder上では" "Python %dが実行されています!

この選択は可能ですが、Pythonバー" "ジョン間での構文非互換性による偽の警告/エラーを避けるため、Spyder上でも選択し" "たバージョンのインタープリターをインストール・実行することが推奨されます。" #: spyder/plugins/maininterpreter.py:186 spyder/plugins/maininterpreter.py:213 #: spyder/plugins/maininterpreter.py:217 msgid "UMR" msgstr "UMR" #: spyder/plugins/maininterpreter.py:187 msgid "Set the list of excluded modules as this: numpy, scipy" msgstr "" "除外モジュールのリストを以下の例のように入力して下さい: numpy, scipy" #: spyder/plugins/maininterpreter.py:204 msgid "" "You are working with Python 2, this means that you can not import a module " "that contains non-ascii characters." msgstr "" "Python2で動作しています。この環境では非アスキー文字を含むモジュールをインポー" "トできません。" #: spyder/plugins/maininterpreter.py:214 msgid "" "The following modules are not installed on your machine:\n" "%s" msgstr "" "以下のモジュールがコンピュータにインストールされていません:\n" "%s" #: spyder/plugins/maininterpreter.py:218 msgid "" "Please note that these changes will be applied only to new Python/IPython " "consoles" msgstr "" "これらの変更は新規Python/IPythonコンソールにのみ適用されることに注意してくだ" "さい" #: spyder/plugins/onlinehelp.py:70 msgid "Online help" msgstr "オンラインヘルプ" #: spyder/plugins/outlineexplorer.py:49 spyder/widgets/editortools.py:195 msgid "Outline" msgstr "アウトライン" #: spyder/plugins/projects.py:78 spyder/widgets/projects/explorer.py:112 #: spyder/widgets/projects/explorer.py:126 msgid "Project explorer" msgstr "プロジェクトエクスプローラー" #: spyder/plugins/projects.py:90 msgid "New Project..." msgstr "新規プロジェクト..." #: spyder/plugins/projects.py:93 msgid "Open Project..." msgstr "プロジェクトを開く..." #: spyder/plugins/projects.py:96 msgid "Close Project" msgstr "プロジェクトを閉じる..." #: spyder/plugins/projects.py:99 msgid "Delete Project" msgstr "プロジェクトを削除する" #: spyder/plugins/projects.py:105 msgid "Project Preferences" msgstr "プロジェクト設定" #: spyder/plugins/projects.py:107 msgid "Recent Projects" msgstr "最近開いたプロジェクト" #: spyder/plugins/projects.py:244 msgid "Open project" msgstr "プロジェクトを開く" #: spyder/plugins/projects.py:249 msgid "%s is not a Spyder project!" msgstr "%s はSpyderプロジェクトではありません!" #: spyder/plugins/runconfig.py:29 msgid "Execute in current console" msgstr "現在のコンソールで実行" #: spyder/plugins/runconfig.py:30 msgid "Execute in a dedicated console" msgstr "専用の新規コンソールで実行" #: spyder/plugins/runconfig.py:31 msgid "Execute in an external system terminal" msgstr "外部システムターミナルで実行" #: spyder/plugins/runconfig.py:42 msgid "Always show %s on a first file run" msgstr "ファイルの先頭に %s を常に表示" #: spyder/plugins/runconfig.py:45 msgid "Remove all variables before execution" msgstr "実行前に全ての変数を削除" #: spyder/plugins/runconfig.py:46 msgid "Directly enter debugging when errors appear" msgstr "エラーが発生した場合直接デバッグモードに入る" #: spyder/plugins/runconfig.py:47 msgid "Interact with the Python console after execution" msgstr "実行後Pythonコンソールと相互作用する" #: spyder/plugins/runconfig.py:49 msgid "The directory of the file being executed" msgstr "現在実行しているファイルのディレクトリ\t" #: spyder/plugins/runconfig.py:50 spyder/plugins/workingdirectory.py:56 msgid "The current working directory" msgstr "現在の作業ディレクトリ設定" #: spyder/plugins/runconfig.py:51 msgid "The following directory:" msgstr "以下のディレクトリ:" #: spyder/plugins/runconfig.py:184 spyder/plugins/runconfig.py:504 msgid "General settings" msgstr "一般設定" #: spyder/plugins/runconfig.py:194 spyder/plugins/runconfig.py:236 msgid "Command line options:" msgstr "コマンドラインオプション:" #: spyder/plugins/runconfig.py:202 spyder/plugins/runconfig.py:514 msgid "Working Directory settings" msgstr "作業ディレクトリ設定" #: spyder/plugins/runconfig.py:226 spyder/plugins/runconfig.py:548 msgid "External system terminal" msgstr "外部システムターミナル" #: spyder/plugins/runconfig.py:241 msgid "-u is added to the other options you set here" msgstr "ここで設定した以外に、-u がオプションに追加されました。" #: spyder/plugins/runconfig.py:250 msgid "this dialog" msgstr "このダイアログ" #: spyder/plugins/runconfig.py:315 msgid "Run configuration" msgstr "実行設定" #: spyder/plugins/runconfig.py:316 msgid "The following working directory is not valid:
%s" msgstr "以下の作業ディレクトリは不正です:
%s" #: spyder/plugins/runconfig.py:394 msgid "Run settings for %s" msgstr "%s の実行設定" #: spyder/plugins/runconfig.py:426 msgid "Select a run configuration:" msgstr "実行する設定を選択" #: spyder/plugins/runconfig.py:455 msgid "Run configuration per file" msgstr "ファイルごとの実行設定" #: spyder/plugins/runconfig.py:480 msgid "" "The following are the default options for running files.These options may be " "overriden using the Configuration per file entry of the Run " "menu." msgstr "" "以下はファイル実行時のデフォルトオプション設定です。これらのオプションは実" "行メニューのファイルごとの設定エントリで上書きされます。" #: spyder/plugins/runconfig.py:516 msgid "Default working directory is:" msgstr "デフォルト作業ディレクトリは:" #: spyder/plugins/runconfig.py:556 msgid "Run Settings dialog" msgstr "設定ダイアログを実行" #: spyder/plugins/shortcuts.py:65 msgid "Currently used to delete lines on editor" msgstr "エディタで行削除をするために使われています" #: spyder/plugins/shortcuts.py:69 msgid "We cannot support this shortcut on Windows" msgstr "Windowsではこのショートカットはサポートできません" #: spyder/plugins/shortcuts.py:72 msgid "Shortcuts that use Shift and another key are unsupported" msgstr "シフトキーを組み合わせたショートカットはサポートされていません" #: spyder/plugins/shortcuts.py:149 msgid "" "Press the new shortcut and select 'Ok': \n" "(Press 'Tab' once to switch focus between the shortcut entry \n" "and the buttons below it)" msgstr "" "新しショートカットを押し、 'Ok'を選択してください: \n" "(ショートカットエントリ間やボタン間のフォーカス移動には\n" "'Tab'を押してください)" #: spyder/plugins/shortcuts.py:152 msgid "Current shortcut:" msgstr "現在のショートカット:" #: spyder/plugins/shortcuts.py:154 msgid "New shortcut:" msgstr "新規ショートカット:" #: spyder/plugins/shortcuts.py:167 msgid "Shortcut: {0}" msgstr "ショートカット: {0}" #: spyder/plugins/shortcuts.py:288 msgid "Please introduce a different shortcut" msgstr "異なるショートカットを設定してください" #: spyder/plugins/shortcuts.py:325 msgid "The new shortcut conflicts with:" msgstr "新しいショートカットは以下と競合しています:" #: spyder/plugins/shortcuts.py:334 spyder/plugins/shortcuts.py:343 msgid "Forbidden key sequence!" msgstr "禁止されたキーシーケンスです" #: spyder/plugins/shortcuts.py:354 msgid "" "A compound sequence can have {break} a maximum of 4 subsequences.{break}" msgstr "複合シーケンスは{break} 最大4個のサブシーケンス{break}を持てます。" #: spyder/plugins/shortcuts.py:359 msgid "Invalid key entered" msgstr "不正なキー入力" #: spyder/plugins/shortcuts.py:567 msgid "Context" msgstr "コンテキスト" #: spyder/plugins/shortcuts.py:569 #: spyder/widgets/variableexplorer/collectionseditor.py:128 msgid "Name" msgstr "名前" #: spyder/plugins/shortcuts.py:571 msgid "Shortcut" msgstr "ショートカット" #: spyder/plugins/shortcuts.py:573 msgid "Score" msgstr "スコア" #: spyder/plugins/shortcuts.py:734 msgid "Conflicts" msgstr "競合" #: spyder/plugins/shortcuts.py:735 msgid "The following conflicts have been detected:" msgstr "以下の競合が検知されました:" #: spyder/plugins/shortcuts.py:820 msgid "Keyboard shortcuts" msgstr "キーボード・ショートカット" #: spyder/plugins/shortcuts.py:828 msgid "Search: " msgstr "検索:" #: spyder/plugins/shortcuts.py:829 msgid "Reset to default values" msgstr "デフォルト値に戻す" #: spyder/plugins/shortcuts.py:859 msgid "Shortcuts reset" msgstr "ショートカットのリセット" #: spyder/plugins/shortcuts.py:860 msgid "Do you want to reset to default values?" msgstr "デフォルト値に戻しますか?" #: spyder/plugins/variableexplorer.py:25 msgid "Filter" msgstr "フィルター" #: spyder/plugins/variableexplorer.py:27 #: spyder/widgets/variableexplorer/namespacebrowser.py:200 msgid "Exclude private references" msgstr "privateな参照を除外" #: spyder/plugins/variableexplorer.py:28 #: spyder/widgets/variableexplorer/namespacebrowser.py:215 msgid "Exclude capitalized references" msgstr "大文字で始まる参照を除外" #: spyder/plugins/variableexplorer.py:29 #: spyder/widgets/variableexplorer/namespacebrowser.py:208 msgid "Exclude all-uppercase references" msgstr "名前が全て大文字の参照を除外" #: spyder/plugins/variableexplorer.py:30 #: spyder/widgets/variableexplorer/namespacebrowser.py:223 msgid "Exclude unsupported data types" msgstr "非サポートのデータ型を除外" #: spyder/plugins/variableexplorer.py:36 #: spyder/widgets/variableexplorer/collectionseditor.py:699 msgid "Show arrays min/max" msgstr "配列の最小/最大を表示" #: spyder/plugins/variableexplorer.py:178 msgid "Variable explorer" msgstr "変数エクスプローラー" #: spyder/plugins/workingdirectory.py:39 msgid "" "The current working directory is the working directory for IPython " "consoles and the current directory for the File Explorer." msgstr "" "現在の作業ディレクトリ はIPythonコンソールとファイルエクスプローラーの" "ための作業でディレクトリです。" #: spyder/plugins/workingdirectory.py:44 msgid "Console directory" msgstr "コンソールディレクトリ" #: spyder/plugins/workingdirectory.py:45 msgid "The working directory for new consoles is:" msgstr "新規コンソール用の作業ディレクトリ:" #: spyder/plugins/workingdirectory.py:49 msgid "" "The current project directory or user home directory (if no project is " "active)" msgstr "" "現在のプロジェクトディレクトリあるいは(アクティブなプロジェクトが無い場合)" "ホームディレクトリ" #: spyder/plugins/workingdirectory.py:62 msgid "the following directory:" msgstr "以下のディレクトリ:" #: spyder/plugins/workingdirectory.py:64 msgid "The directory when a new console is open will be the specified path" msgstr "" "新規コンソールを開いた時の作業ディレクトリは設定されたパスによって決定されま" "す" #: spyder/plugins/workingdirectory.py:124 msgid "Back" msgstr "戻る" #: spyder/plugins/workingdirectory.py:132 spyder/widgets/explorer.py:1181 #: spyder/widgets/variableexplorer/importwizard.py:539 msgid "Next" msgstr "次" #: spyder/plugins/workingdirectory.py:143 msgid "" "This is the working directory for newly\n" "opened consoles (Python/IPython consoles and\n" "terminals), for the file explorer, for the\n" "find in files plugin and for new files\n" "created in the editor" msgstr "" "これは、ファイルエクスプローラー、\n" "ファイル検索プラグイン、新規コンソール\n" "(Python/IPythonコンソール及びターミナル)\n" "及びエディタで作成した新規ファイルの\n" "作業ディレクトリです。" #: spyder/plugins/workingdirectory.py:168 msgid "Browse a working directory" msgstr "作業ディレクトリを表示" #: spyder/plugins/workingdirectory.py:175 msgid "Change to parent directory" msgstr "親ディレクトリへ移動" #: spyder/plugins/workingdirectory.py:182 spyder/widgets/findinfiles.py:322 msgid "Current working directory" msgstr "現在の作業ディレクトリ" #: spyder/utils/codeanalysis.py:92 msgid "Real-time code analysis on the Editor" msgstr "エディタ上でのリアルタイムコード分析" #: spyder/utils/codeanalysis.py:96 msgid "Real-time code style analysis on the Editor" msgstr "エディタ上でのリアルタイムコードスタイル分析" #: spyder/utils/environ.py:46 msgid "Environment variables" msgstr "環境変数" #: spyder/utils/environ.py:96 msgid "" "Module pywin32 was not found.
Please restart this Windows " "session (not the computer) for changes to take effect." msgstr "" "モジュール pywin32 は見つかりませんでした
変更を反映させるには(コ" "ンピュータではなく)このWindowsセッション を再起動して。" #: spyder/utils/environ.py:109 msgid "" "If you accept changes, this will modify the current user environment " "variables directly in Windows registry. Use it with precautions, at " "your own risks.

Note that for changes to take effect, you will need " "to restart the parent process of this application (simply restart Spyder if " "you have executed it from a Windows shortcut, otherwise restart any " "application from which you may have executed it, like Python(x,y) Home for example)" msgstr "" "変更を受諾すると Windowsレジストリ内の現在のユーザー環境変数が直接修正" "されます。 各自のリスクで注意深く使用すること。

変更が効果を及ぼすには" "このアプリケーションの親プロセスを再起動する必要があります。(Windowsショート" "カットから実行している場合単にspyderを再起動すれば良い。そうでなければ例えば" "Python(x,y) HomeのようにSpyderを実行しているアプリケーションを全て再起" "動する)" #: spyder/utils/help/sphinxify.py:217 spyder/utils/help/sphinxify.py:227 msgid "" "It was not possible to generate rich text help for this object.
Please " "see it in plain text." msgstr "" "このオブジェクトに対してリッチテキストのヘルプを生成できませんでした。
プ" "レーンテキストを参照してください。" #: spyder/utils/introspection/manager.py:34 #: spyder/utils/introspection/manager.py:39 msgid "Editor's code completion, go-to-definition and help" msgstr "エディタのコード補完、go-to-definition及びヘルプ" #: spyder/utils/iofuncs.py:408 msgid "Supported files" msgstr "サポートされているファイル" #: spyder/utils/iofuncs.py:410 msgid "All files (*.*)" msgstr "すべてのファイル (*.*)" #: spyder/utils/iofuncs.py:420 msgid "Spyder data files" msgstr "Spyderデータファイル" #: spyder/utils/iofuncs.py:422 #: spyder/widgets/variableexplorer/collectionseditor.py:1058 msgid "NumPy arrays" msgstr "NumPy配列" #: spyder/utils/iofuncs.py:423 msgid "NumPy zip arrays" msgstr "NumPy zip配列" #: spyder/utils/iofuncs.py:424 msgid "Matlab files" msgstr "Matlabファイル" #: spyder/utils/iofuncs.py:425 msgid "CSV text files" msgstr "CSVテキストファイル" #: spyder/utils/iofuncs.py:427 msgid "JPEG images" msgstr "JPEG画像" #: spyder/utils/iofuncs.py:428 msgid "PNG images" msgstr "PNG画像" #: spyder/utils/iofuncs.py:429 msgid "GIF images" msgstr "GIF画像" #: spyder/utils/iofuncs.py:430 msgid "TIFF images" msgstr "TIFF画像" #: spyder/utils/iofuncs.py:431 spyder/utils/iofuncs.py:432 msgid "Pickle files" msgstr "Pickleファイル" #: spyder/utils/iofuncs.py:433 msgid "JSON files" msgstr "JSONファイル" #: spyder/utils/iofuncs.py:452 spyder/utils/iofuncs.py:459 msgid "Unsupported file type '%s'" msgstr "非サポートファイルタイプ '%s'" #: spyder/utils/programs.py:287 msgid "It was not possible to run this file in an external terminal" msgstr "このファイルを外部ターミナルで実行できませんでした" #: spyder/utils/syntaxhighlighters.py:34 msgid "Syntax highlighting for Matlab, Julia and other file types" msgstr "Matbal、Julia及びたのファイルタイプの構文強調" #: spyder/utils/syntaxhighlighters.py:43 msgid "Background:" msgstr "バックグラウンド:" #: spyder/utils/syntaxhighlighters.py:44 #: spyder/widgets/sourcecode/codeeditor.py:107 msgid "Current line:" msgstr "現在行:" #: spyder/utils/syntaxhighlighters.py:45 msgid "Current cell:" msgstr "現在セル:" #: spyder/utils/syntaxhighlighters.py:46 msgid "Occurrence:" msgstr "事象:" #: spyder/utils/syntaxhighlighters.py:47 msgid "Link:" msgstr "リンク:" #: spyder/utils/syntaxhighlighters.py:48 msgid "Side areas:" msgstr "サイドエリア:" #: spyder/utils/syntaxhighlighters.py:49 msgid "Matched
parens:" msgstr "閉じた
括弧:" #: spyder/utils/syntaxhighlighters.py:50 msgid "Unmatched
parens:" msgstr "閉じていない
括弧:" #: spyder/utils/syntaxhighlighters.py:51 msgid "Normal text:" msgstr "通常テキスト:" #: spyder/utils/syntaxhighlighters.py:52 msgid "Keyword:" msgstr "キーワード:" #: spyder/utils/syntaxhighlighters.py:53 msgid "Builtin:" msgstr "組み込み:" #: spyder/utils/syntaxhighlighters.py:54 msgid "Definition:" msgstr "定義:" #: spyder/utils/syntaxhighlighters.py:55 msgid "Comment:" msgstr "コメント:" #: spyder/utils/syntaxhighlighters.py:56 msgid "String:" msgstr "文字列:" #: spyder/utils/syntaxhighlighters.py:57 msgid "Number:" msgstr "数字:" #: spyder/utils/syntaxhighlighters.py:58 msgid "Instance:" msgstr "インスタンス:" #: spyder/widgets/arraybuilder.py:179 msgid "" "\n" " Numpy Array/Matrix Helper
\n" " Type an array in Matlab : [1 2;3 4]
\n" " or Spyder simplified syntax : 1 2;3 4\n" "

\n" " Hit 'Enter' for array or 'Ctrl+Enter' for matrix.\n" "

\n" " Hint:
\n" " Use two spaces or two tabs to generate a ';'.\n" " " msgstr "" "\n" " Numpy 配列/行列 ヘルパー
\n" " 以下の形式で入力 Matlab形式 : [1 2;3 4]
\n" " あるいはSpyder構文 : 1 2;3 4\n" "

\n" " 配列入力には'Enter'を、行列入力には 'Ctrl+Enter'を使う。\n" "

\n" " ヒント:
\n" " 空白2つあるいはタブ2つは';'入力になる。\n" " " #: spyder/widgets/arraybuilder.py:190 msgid "" "\n" " Numpy Array/Matrix Helper
\n" " Enter an array in the table.
\n" " Use Tab to move between cells.\n" "

\n" " Hit 'Enter' for array or 'Ctrl+Enter' for matrix.\n" "

\n" " Hint:
\n" " Use two tabs at the end of a row to move to the next row.\n" " " msgstr "" "\n" " Numpy 配列/行列 ヘルパー
\n" " テーブルに配列を入力してください。
\n" " セル間の移動にはタブを使います。\n" "

\n" " 配列入力には'Enter'を、行列入力には 'Ctrl+Enter'を。\n" "

\n" " ヒント:
\n" " 行末で次の行へ移動するにはタブを2回入力すれば良い。\n" " " #: spyder/widgets/arraybuilder.py:365 msgid "Array dimensions not valid" msgstr "配列の次元が不正" #: spyder/widgets/browser.py:58 spyder/widgets/sourcecode/codeeditor.py:2719 msgid "Zoom out" msgstr "ズームアウト" #: spyder/widgets/browser.py:61 spyder/widgets/sourcecode/codeeditor.py:2715 msgid "Zoom in" msgstr "ズームイン" #: spyder/widgets/browser.py:213 msgid "Home" msgstr "ホーム" #: spyder/widgets/browser.py:249 msgid "Find text" msgstr "テキスト検索" #: spyder/widgets/browser.py:266 msgid "Address:" msgstr "アドレス:" #: spyder/widgets/browser.py:302 msgid "Unable to load page" msgstr "ページをロードできません" #: spyder/widgets/comboboxes.py:164 msgid "Press enter to validate this entry" msgstr "入力を検証するにはエンターキーを押してください" #: spyder/widgets/comboboxes.py:165 msgid "This entry is incorrect" msgstr "この入力は不正です" #: spyder/widgets/comboboxes.py:208 msgid "Press enter to validate this path" msgstr "パスを検証するにはエンターキーを押してください" #: spyder/widgets/dependencies.py:63 msgid " Required " msgstr "必須" #: spyder/widgets/dependencies.py:63 msgid "Module" msgstr "モジュール" #: spyder/widgets/dependencies.py:64 msgid " Installed " msgstr "インストール済み" #: spyder/widgets/dependencies.py:64 msgid "Provided features" msgstr "利用できる機能" #: spyder/widgets/dependencies.py:134 msgid "Dependencies" msgstr "依存性" #: spyder/widgets/dependencies.py:141 msgid "" "Spyder depends on several Python modules to provide the right functionality " "for all its panes. The table below shows the required and installed versions " "(if any) of all of them.

Note: You can safely use Spyder " "without the following modules installed: %s and %s." "

Please also note that new dependencies or changed ones will be " "correctly detected only after Spyder is restarted." msgstr "" "全てのペインが正しく機能するために、Spyderは複数のPythonモジュールに依存して" "います。 下記のテーブルには必要なモジュールとインストール済みモジュールのバー" "ジョンを示します。

: 以下のモジュールはインストールしなくても" "Spyderを安全に使用できます。:%s%s.

新たに発生した依存" "関係及び解決された依存関係はSpyderを再起動するまで正しく認識されません" #: spyder/widgets/dependencies.py:157 msgid "Copy to clipboard" msgstr "クリップボードにコピー" #: spyder/widgets/editor.py:501 msgid "Find symbols in file..." msgstr "ファイル中のシンボル検索..." #: spyder/widgets/editor.py:504 msgid "Copy path to clipboard" msgstr "パスをクリップボードにコピー" #: spyder/widgets/editor.py:508 msgid "Close all to the right" msgstr "全体を右側へ閉じる" #: spyder/widgets/editor.py:510 msgid "Close all but this" msgstr "他を閉じる" #: spyder/widgets/editor.py:514 spyder/widgets/explorer.py:361 msgid "Show in Finder" msgstr "Finderで表示" #: spyder/widgets/editor.py:516 spyder/widgets/explorer.py:363 msgid "Show in external file explorer" msgstr "外部ファイルエクスプローラーで表示" #: spyder/widgets/editor.py:1197 msgid "Temporary file" msgstr "一時ファイル" #: spyder/widgets/editor.py:1289 msgid "New window" msgstr "新しいウインドウ" #: spyder/widgets/editor.py:1290 msgid "Create a new editor window" msgstr "新しいエディタウインドウを作成する" #: spyder/widgets/editor.py:1293 msgid "Split vertically" msgstr "縦に分割する" #: spyder/widgets/editor.py:1295 msgid "Split vertically this editor window" msgstr "このエディタウインドウを縦に分割する" #: spyder/widgets/editor.py:1297 msgid "Split horizontally" msgstr "横に分割" #: spyder/widgets/editor.py:1299 msgid "Split horizontally this editor window" msgstr "このエディタウインドウを横に分割" #: spyder/widgets/editor.py:1301 msgid "Close this panel" msgstr "このパネルを閉じる" #: spyder/widgets/editor.py:1540 msgid "%s has been modified.
Do you want to save changes?" msgstr "%s は変更されています。
保存しますか?" #: spyder/widgets/editor.py:1626 spyder/widgets/editor.py:1789 msgid "Save" msgstr "保存" #: spyder/widgets/editor.py:1627 spyder/widgets/editor.py:1790 #: spyder/widgets/shell.py:267 msgid "Unable to save file '%s'

Error message:
%s" msgstr "ファイル '%s' を保存できません

エラーメッセージ:
%s" #: spyder/widgets/editor.py:1977 msgid "" "%s is unavailable (this file may have been removed, moved or renamed " "outside Spyder).
Do you want to close it?" msgstr "" "%s は利用できません (このファイルはSpypder外で削除、移動あるいは名前変" "更されています)。
閉じますか?" #: spyder/widgets/editor.py:2000 msgid "" "%s has been modified outside Spyder.
Do you want to reload it and " "lose all your changes?" msgstr "" "%s はSpyderの外で変更されています。
変更を破棄して再読込しますか?" #: spyder/widgets/editor.py:2110 msgid "" "All changes to %s will be lost.
Do you want to revert file from " "disk?" msgstr "" "%s へのすべての変更は失われます。
ファイルをディスクから復帰させま" "すか?" #: spyder/widgets/editor.py:2254 msgid "Loading %s..." msgstr "%s をロードしています..." #: spyder/widgets/editor.py:2266 msgid "" "%s contains mixed end-of-line characters.
Spyder will fix this " "automatically." msgstr "" "%s は複数種の改行コードを含んでいます。
Spyderは自動的に修正しま" "す。" #: spyder/widgets/editor.py:2675 msgid "Close window" msgstr "ウインドウを閉じる" #: spyder/widgets/editor.py:2677 msgid "Close this window" msgstr "このウインドウを閉じる" #: spyder/widgets/editortools.py:94 spyder/widgets/editortools.py:130 msgid "Line %s" msgstr " %s 行" #: spyder/widgets/editortools.py:99 msgid "Class defined at line %s" msgstr "%s 行で定義されているクラス" #: spyder/widgets/editortools.py:107 msgid "Method defined at line %s" msgstr "%s 行で定義されているメソッド" #: spyder/widgets/editortools.py:117 msgid "Function defined at line %s" msgstr "%s 行で定義されている関数" #: spyder/widgets/editortools.py:149 msgid "Cell starts at line %s" msgstr "%s 行から始まるセル" #: spyder/widgets/editortools.py:202 spyder/widgets/editortools.py:535 msgid "Go to cursor position" msgstr "カーソル位置へ移動" #: spyder/widgets/editortools.py:205 msgid "Show absolute path" msgstr "絶対パスを表示" #: spyder/widgets/editortools.py:208 spyder/widgets/explorer.py:274 msgid "Show all files" msgstr "全てのファイルを表示" #: spyder/widgets/editortools.py:211 msgid "Show special comments" msgstr "特別なコメントを表示" #: spyder/widgets/editortools.py:509 msgid "Show/hide outline explorer" msgstr "アウトラインエクスプローラーの表示/隠す" #: spyder/widgets/explorer.py:270 msgid "Edit filename filters..." msgstr "ファイル名フィルターを編集..." #: spyder/widgets/explorer.py:284 msgid "Edit filename filters" msgstr "ファイル名フィルターを編集" #: spyder/widgets/explorer.py:285 msgid "Name filters:" msgstr "フィルター:" #: spyder/widgets/explorer.py:304 msgid "File..." msgstr "ファイル..." #: spyder/widgets/explorer.py:308 msgid "Module..." msgstr "モジュール..." #: spyder/widgets/explorer.py:312 msgid "Folder..." msgstr "フォルダー..." #: spyder/widgets/explorer.py:316 msgid "Package..." msgstr "パッケージ..." #: spyder/widgets/explorer.py:337 #: spyder/widgets/variableexplorer/collectionseditor.py:674 msgid "Edit" msgstr "編集" #: spyder/widgets/explorer.py:339 msgid "Move..." msgstr "移動..." #: spyder/widgets/explorer.py:342 msgid "Delete..." msgstr "削除..." #: spyder/widgets/explorer.py:345 msgid "Rename..." msgstr "リネーム..." #: spyder/widgets/explorer.py:348 msgid "Open" msgstr "開く" #: spyder/widgets/explorer.py:349 spyder/widgets/sourcecode/codeeditor.py:2687 msgid "Convert to Python script" msgstr "Pythonスクリプトへ変換" #: spyder/widgets/explorer.py:390 msgid "Commit" msgstr "コミット" #: spyder/widgets/explorer.py:393 msgid "Browse repository" msgstr "レポジトリを表示" #: spyder/widgets/explorer.py:404 msgid "Open command prompt here" msgstr "コマンドプロンプトをここで開く" #: spyder/widgets/explorer.py:406 msgid "Open terminal here" msgstr "ターミナルをここで開く" #: spyder/widgets/explorer.py:407 msgid "Open IPython console here" msgstr "IPythonコンソールをここで開く" #: spyder/widgets/explorer.py:421 msgid "New" msgstr "新規" #: spyder/widgets/explorer.py:429 msgid "Import" msgstr "インポート" #: spyder/widgets/explorer.py:575 msgid "Do you really want to delete %s?" msgstr "本当に %s を削除しますか?" #: spyder/widgets/explorer.py:593 msgid "delete" msgstr "削除" #: spyder/widgets/explorer.py:594 spyder/widgets/projects/explorer.py:148 #: spyder/widgets/projects/explorer.py:255 msgid "Project Explorer" msgstr "プロジェクトエクスプローラー" #: spyder/widgets/explorer.py:595 spyder/widgets/projects/explorer.py:149 msgid "Unable to %s %s

Error message:
%s" msgstr "" "%s が %s に実行できませんでした。

エラーメッセージ:
" "%s" #: spyder/widgets/explorer.py:610 msgid "File Explorer" msgstr "ファイルエクスプローラー" #: spyder/widgets/explorer.py:611 msgid "" "The current directory contains a project.

If you want to delete the " "project, please go to Projects » Delete Project" msgstr "" "現在のディクショナリはプロジェクトを含んでいます。

プロジェクトを削除" "したい場合はプロジェクト » プロジェクトの削除を選択して下" "さい" #: spyder/widgets/explorer.py:628 spyder/widgets/sourcecode/codeeditor.py:2160 msgid "Conversion error" msgstr "変換エラー" #: spyder/widgets/explorer.py:629 spyder/widgets/sourcecode/codeeditor.py:2161 msgid "" "It was not possible to convert this notebook. The error is:\n" "\n" msgstr "" "notebookが変換できませんでした。エラー:\n" "\n" #: spyder/widgets/explorer.py:646 spyder/widgets/explorer.py:654 #: spyder/widgets/explorer.py:665 #: spyder/widgets/variableexplorer/collectionseditor.py:703 #: spyder/widgets/variableexplorer/collectionseditor.py:949 msgid "Rename" msgstr "リネーム" #: spyder/widgets/explorer.py:647 msgid "New name:" msgstr "新しい名前:" #: spyder/widgets/explorer.py:655 msgid "" "Do you really want to rename %s and overwrite the existing file " "%s?" msgstr "" "本当に %s をリネームし、既存ファイル %s を上書きしますか?" #: spyder/widgets/explorer.py:666 msgid "Unable to rename file %s

Error message:
%s" msgstr "" "ファイル %s をリネームできません

エラーメッセージ:
%s" #: spyder/widgets/explorer.py:709 msgid "Unable to move %s

Error message:
%s" msgstr " %s を移動できません

エラーメッセージ:
%s" #: spyder/widgets/explorer.py:727 msgid "Unable to create folder %s

Error message:
%s" msgstr "" "フォルダ %s を作成できません

エラーメッセージ:
%s" #: spyder/widgets/explorer.py:740 spyder/widgets/explorer.py:774 msgid "Unable to create file %s

Error message:
%s" msgstr "" "ファイル %s を作成できません

エラーメッセージ:
%s" #: spyder/widgets/explorer.py:748 msgid "New folder" msgstr "新規フォルダー" #: spyder/widgets/explorer.py:749 msgid "Folder name:" msgstr "フォルダ名:" #: spyder/widgets/explorer.py:754 msgid "New package" msgstr "新規パッケージ" #: spyder/widgets/explorer.py:755 msgid "Package name:" msgstr "パッケージ名:" #: spyder/widgets/explorer.py:795 msgid "New module" msgstr "新規モジュール" #: spyder/widgets/explorer.py:810 msgid "" "For %s support, please install one of the
following tools:

%s" msgstr "" " %s をサポートするためには以下のツールをインストールしてください。
ツー" "ル:

%s" #: spyder/widgets/explorer.py:814 msgid "Unable to find external program.

%s" msgstr "外部プログラムが見つかりません。

%s" #: spyder/widgets/explorer.py:1035 msgid "Show current directory only" msgstr "現在のディレクトリのみを表示" #: spyder/widgets/explorer.py:1145 msgid "You don't have the right permissions to open this directory" msgstr "このディレクトリを開く権限がありません" #: spyder/widgets/explorer.py:1176 msgid "Show icons and text" msgstr "アイコンとテキストを表示" #: spyder/widgets/explorer.py:1178 #: spyder/widgets/variableexplorer/importwizard.py:535 msgid "Previous" msgstr "前" #: spyder/widgets/explorer.py:1184 msgid "Parent" msgstr "親" #: spyder/widgets/fileswitcher.py:110 msgid "unsaved file" msgstr "保存されていないファイル" #: spyder/widgets/fileswitcher.py:249 msgid "" "Press Enter to switch files or Esc to cancel.

Type to " "filter filenames.

Use :number to go to a line, e.g. " "main:42
Use @symbol_text to go to a symbol, e." "g. @init

Press Ctrl+W to close current " "tab.
" msgstr "" "ファイルを切り替えるために Enter を押すか Esc でキャンセルして" "ください。.

ファイルをフィルターするために入力してください。

行" "移動には:数字 を使ってください。例: main:42
シ" "ンボルへの移動は@symbol_text を使ってください。例: @init

現在のタブを閉じるには Ctrl+W を押してください。
" #: spyder/widgets/fileswitcher.py:663 msgid "lines" msgstr "行" #: spyder/widgets/findinfiles.py:121 msgid "Unexpected error: see internal console" msgstr "予期しないエラー: 内部コンソールを参照してください" #: spyder/widgets/findinfiles.py:149 msgid "invalid regular expression" msgstr "無効な正規表現" #: spyder/widgets/findinfiles.py:199 msgid "permission denied errors were encountered" msgstr "エラーが発生しました(権限がありません)" #: spyder/widgets/findinfiles.py:258 msgid "Search pattern" msgstr "パターンを検索" #: spyder/widgets/findinfiles.py:261 spyder/widgets/findinfiles.py:301 #: spyder/widgets/findreplace.py:99 msgid "Regular expression" msgstr "正規表現" #: spyder/widgets/findinfiles.py:264 spyder/widgets/findreplace.py:105 msgid "Case Sensitive" msgstr "大文字/小文字を区別" #: spyder/widgets/findinfiles.py:275 msgid "Search" msgstr "検索" #: spyder/widgets/findinfiles.py:278 msgid "Start search" msgstr "検索開始" #: spyder/widgets/findinfiles.py:285 msgid "Stop search" msgstr "検索終了" #: spyder/widgets/findinfiles.py:295 msgid "Excluded filenames pattern" msgstr "除外されるファイル名パターン" #: spyder/widgets/findinfiles.py:304 msgid "Exclude:" msgstr "除外:" #: spyder/widgets/findinfiles.py:313 msgid "Search in:" msgstr "検索:" #: spyder/widgets/findinfiles.py:315 msgid "Search directory" msgstr "ディレクトリを検索" #: spyder/widgets/findinfiles.py:324 msgid "Search in all files and directories present on thecurrent Spyder path" msgstr "現在のSpyderパス内に存在している全てのファイルとディレクトリを検索" #: spyder/widgets/findinfiles.py:328 msgid "Project" msgstr "プロジェクト" #: spyder/widgets/findinfiles.py:330 msgid "" "Search in all files and directories present on thecurrent project path (If " "opened)" msgstr "" "現在のプロジェクトパス内に存在している全てのファイルとディレクトリを検索" #: spyder/widgets/findinfiles.py:336 msgid "File" msgstr "ファイル" #: spyder/widgets/findinfiles.py:338 msgid "Search in current opened file" msgstr "現在開いているファイルを検索" #: spyder/widgets/findinfiles.py:340 msgid "Select other directory" msgstr "他のディレクトリを選択" #: spyder/widgets/findinfiles.py:342 msgid "Search in other folder present on the file system" msgstr "ファイルシステム上の他フォルダを検索" #: spyder/widgets/findinfiles.py:378 msgid "Hide advanced options" msgstr "詳細オプションを隠す" #: spyder/widgets/findinfiles.py:381 msgid "Show advanced options" msgstr "詳細オプションを表示" #: spyder/widgets/findinfiles.py:675 spyder/widgets/findinfiles.py:759 msgid "String not found" msgstr "文字列が見つかりませんでした" #: spyder/widgets/findinfiles.py:761 msgid "matches in" msgstr "一致" #: spyder/widgets/findinfiles.py:762 msgid "file" msgstr "ファイル" #: spyder/widgets/findinfiles.py:794 msgid " Scanning: {0}" msgstr "スキャン中: {0}" #: spyder/widgets/findinfiles.py:796 msgid " Searching for files in folder: {0}" msgstr " フォルダ内のファイルを検索中: {0}" #: spyder/widgets/findinfiles.py:800 msgid " Searching for files..." msgstr " ファイルを検索しています..." #: spyder/widgets/findreplace.py:48 msgid "No matches" msgstr "一致なし" #: spyder/widgets/findreplace.py:49 spyder/widgets/findreplace.py:50 #: spyder/widgets/findreplace.py:72 msgid "Search string" msgstr "検索文字列" #: spyder/widgets/findreplace.py:51 msgid "Regular expression error" msgstr "正規表現エラー" #: spyder/widgets/findreplace.py:111 msgid "Whole words" msgstr "単語全体" #: spyder/widgets/findreplace.py:117 msgid "Highlight matches" msgstr "一致箇所を強調" #: spyder/widgets/findreplace.py:131 msgid "Replace with:" msgstr "以下で置換:" #: spyder/widgets/findreplace.py:133 msgid "Replace string" msgstr "置換文字列" #: spyder/widgets/findreplace.py:137 msgid "Replace/find next" msgstr "次へ置換/検索" #: spyder/widgets/findreplace.py:142 msgid "Replace selection" msgstr "選択部分を置換" #: spyder/widgets/findreplace.py:150 msgid "Replace all" msgstr "全て置換" #: spyder/widgets/findreplace.py:572 msgid "of" msgstr "of" #: spyder/widgets/findreplace.py:576 msgid "matches" msgstr "一致" #: spyder/widgets/findreplace.py:579 msgid "no matches" msgstr "一致なし" #: spyder/widgets/internalshell.py:262 msgid "Help..." msgstr "ヘルプ..." #: spyder/widgets/internalshell.py:279 msgid "Shell special commands:" msgstr "特別なシェルコマンド:" #: spyder/widgets/internalshell.py:280 msgid "Internal editor:" msgstr "内部エディタ" #: spyder/widgets/internalshell.py:281 msgid "External editor:" msgstr "外部エディタ" #: spyder/widgets/internalshell.py:282 msgid "Run script:" msgstr "スクリプトを実行:" #: spyder/widgets/internalshell.py:283 msgid "Remove references:" msgstr "参照を削除" #: spyder/widgets/internalshell.py:284 msgid "System commands:" msgstr "システムコマンド:" #: spyder/widgets/internalshell.py:285 msgid "Python help:" msgstr "Pythonヘルプ:" #: spyder/widgets/internalshell.py:286 msgid "GUI-based editor:" msgstr "GUIエディタ:" #: spyder/widgets/ipythonconsole/client.py:275 msgid "An error ocurred while starting the kernel" msgstr "カーネルを開始中にエラーが発生しました" #: spyder/widgets/ipythonconsole/client.py:316 #: spyder/widgets/ipythonconsole/client.py:372 #: spyder/widgets/ipythonconsole/client.py:405 #: spyder/widgets/ipythonconsole/shell.py:232 #: spyder/widgets/variableexplorer/namespacebrowser.py:193 msgid "Remove all variables" msgstr "全ての変数を削除" #: spyder/widgets/ipythonconsole/client.py:325 msgid "Show environment variables" msgstr "環境変数を表示" #: spyder/widgets/ipythonconsole/client.py:332 msgid "Show sys.path contents" msgstr "sys.pathの中身を表示" #: spyder/widgets/ipythonconsole/client.py:359 msgid "Stop the current command" msgstr "現在のコマンドを停止する" #: spyder/widgets/ipythonconsole/client.py:370 #: spyder/widgets/variableexplorer/collectionseditor.py:696 #: spyder/widgets/variableexplorer/collectionseditor.py:931 msgid "Remove" msgstr "除去" #: spyder/widgets/ipythonconsole/client.py:393 msgid "Inspect current object" msgstr "現在のオブジェクトを調査する" #: spyder/widgets/ipythonconsole/client.py:399 msgid "Clear line or block" msgstr "ラインやブロックをクリアする" #: spyder/widgets/ipythonconsole/client.py:412 msgid "Clear console" msgstr "コンソールをクリアする" #: spyder/widgets/ipythonconsole/client.py:460 msgid "Are you sure you want to restart the kernel?" msgstr "本当にカーネルを再起動しますか?" #: spyder/widgets/ipythonconsole/client.py:462 msgid "Restart kernel?" msgstr "カーネルを再起動しますか?" #: spyder/widgets/ipythonconsole/client.py:474 msgid "Error restarting kernel: %s\n" msgstr "カーネルを開始中にエラーが発生しました:%s\n" #: spyder/widgets/ipythonconsole/client.py:479 msgid "" "
Restarting kernel...\n" "

" msgstr "" "
カーネルを再起動しています...\n" "

" #: spyder/widgets/ipythonconsole/client.py:483 msgid "Cannot restart a kernel not started by Spyder\n" msgstr "Spyder以外によって起動されたカーネルは再起動できません\n" #: spyder/widgets/ipythonconsole/client.py:592 msgid "Connecting to kernel..." msgstr "カーネルへ接続中..." #: spyder/widgets/ipythonconsole/help.py:128 spyder/widgets/mixins.py:712 msgid "Arguments" msgstr "引数" #: spyder/widgets/ipythonconsole/namespacebrowser.py:129 msgid "Loading this kind of data while debugging is not supported." msgstr "この種のデータのデバッグ中の読み込みはサポートされていません。" #: spyder/widgets/ipythonconsole/namespacebrowser.py:148 msgid "Saving data while debugging is not supported." msgstr "デバッグ中のデータ保存はサポートされていません。" #: spyder/widgets/ipythonconsole/shell.py:233 msgid "" "All user-defined variables will be removed. Are you sure you want to proceed?" msgstr "全てのユーザー定義変数は削除されます。本当に実行しますか?" #: spyder/widgets/ipythonconsole/shell.py:239 msgid "Don't show again." msgstr "次回以降表示しない。" #: spyder/widgets/ipythonconsole/shell.py:262 msgid "" "

Removing all variables...\n" "
" msgstr "" "

全ての変数を削除しています…\n" "
" #: spyder/widgets/ipythonconsole/shell.py:426 msgid "Changing backend to Qt for Mayavi" msgstr "MayaviのバックエンドをQtに変更中" #: spyder/widgets/ipythonconsole/shell.py:471 msgid "Kernel died, restarting" msgstr "カーネル停止しました。再起動中" #: spyder/widgets/ipythonconsole/shell.py:471 msgid "Kernel restarting" msgstr "カーネル再起動中" #: spyder/widgets/onecolumntree.py:52 msgid "Collapse all" msgstr "全て折りたたむ" #: spyder/widgets/onecolumntree.py:56 msgid "Expand all" msgstr "すべて展開" #: spyder/widgets/onecolumntree.py:60 msgid "Restore" msgstr "復元" #: spyder/widgets/onecolumntree.py:61 msgid "Restore original tree layout" msgstr "元のツリーレイアウトを復元" #: spyder/widgets/onecolumntree.py:65 msgid "Collapse selection" msgstr "現在の選択を折りたたむ" #: spyder/widgets/onecolumntree.py:69 msgid "Expand selection" msgstr "現在の選択を展開する" #: spyder/widgets/pathmanager.py:97 msgid "Move to top" msgstr "一番上へ移動" #: spyder/widgets/pathmanager.py:103 msgid "Move up" msgstr "上へ移動" #: spyder/widgets/pathmanager.py:109 msgid "Move down" msgstr "下へ移動" #: spyder/widgets/pathmanager.py:115 msgid "Move to bottom" msgstr "一番下へ移動" #: spyder/widgets/pathmanager.py:126 spyder/widgets/pathmanager.py:267 msgid "Add path" msgstr "パスを追加" #: spyder/widgets/pathmanager.py:131 spyder/widgets/pathmanager.py:246 msgid "Remove path" msgstr "パスを削除" #: spyder/widgets/pathmanager.py:141 msgid "Synchronize..." msgstr "同期..." #: spyder/widgets/pathmanager.py:143 msgid "Synchronize Spyder's path list with PYTHONPATH environment variable" msgstr "SpyderのパスリストをPYTHONPATH環境変数に同期させる" #: spyder/widgets/pathmanager.py:155 msgid "Synchronize" msgstr "同期" #: spyder/widgets/pathmanager.py:156 msgid "" "This will synchronize Spyder's path list with PYTHONPATH environment " "variable for current user, allowing you to run your Python modules outside " "Spyder without having to configure sys.path.
Do you want to clear " "contents of PYTHONPATH before adding Spyder's path list?" msgstr "" "sys.pathを変更することなくSpypder外でPythonモジュールを実行できるように、" "Spyderのパスはユーザーの PYTHONPATH 環境変数に同期されます。 " "
Spyderのパスリストを追加する前にPYTHONPATHの値をクリアしますか?" #: spyder/widgets/pathmanager.py:247 msgid "Do you really want to remove selected path?" msgstr "本当に選択したパスを削除しますか?" #: spyder/widgets/pathmanager.py:268 msgid "" "This directory is already included in Spyder path list.
Do you want to " "move it to the top of the list?" msgstr "" "このディレクトリは既にSpyderのパスリストに含まれています。
リストの一番上" "にパスを移動させますか?" #: spyder/widgets/projects/configdialog.py:30 msgid "Project preferences" msgstr "プロジェクト設定" #: spyder/widgets/projects/configdialog.py:82 #: spyder/widgets/projects/configdialog.py:119 msgid "Restore data on startup" msgstr "起動時にデータを復元" #: spyder/widgets/projects/configdialog.py:84 #: spyder/widgets/projects/configdialog.py:121 msgid "Save data on exit" msgstr "データを保存して終了" #: spyder/widgets/projects/configdialog.py:86 #: spyder/widgets/projects/configdialog.py:123 msgid "Save history" msgstr "ヒストリログを保存" #: spyder/widgets/projects/configdialog.py:88 #: spyder/widgets/projects/configdialog.py:125 msgid "Save non project files opened" msgstr "開いているプロジェクト外のファイルを保存する" #: spyder/widgets/projects/configdialog.py:111 msgid "Code" msgstr "コード" #: spyder/widgets/projects/configdialog.py:118 msgid "Workspace" msgstr "ワークスペース" #: spyder/widgets/projects/configdialog.py:148 #: spyder/widgets/projects/configdialog.py:155 msgid "Version control" msgstr "バージョンコントロール" #: spyder/widgets/projects/configdialog.py:156 msgid "Use version control" msgstr "バージョンコントロールを使用する" #: spyder/widgets/projects/configdialog.py:161 msgid "Version control system" msgstr "バージョンコントロールシステム" #: spyder/widgets/projects/explorer.py:51 msgid "Show horizontal scrollbar" msgstr "水平スクロールバーを表示" #: spyder/widgets/projects/explorer.py:113 msgid "File %s already exists.
Do you want to overwrite it?" msgstr "ファイル %s は既に存在します。
上書きしますか?" #: spyder/widgets/projects/explorer.py:127 msgid "Folder %s already exists." msgstr "フォルダ %s は既に存在します。" #: spyder/widgets/projects/explorer.py:145 msgid "copy" msgstr "コピー" #: spyder/widgets/projects/explorer.py:147 msgid "move" msgstr "移動" #: spyder/widgets/projects/explorer.py:243 msgid "" "Do you really want to delete {filename}?

Note: This " "action will only delete the project. Its files are going to be preserved on " "disk." msgstr "" "本当に{filename}を削除しますか?

注: プロジェクトファイ" "ルはディスク上からは削除されません。

注: " #: spyder/widgets/projects/explorer.py:256 msgid "" "Unable to delete {varpath}

The error message was:" "
{error}" msgstr "" "{varpath}を削除できません。

エラーメッセージ:
{error}" #: spyder/widgets/projects/projectdialog.py:69 msgid "New directory" msgstr "新規ディクショナリ" #: spyder/widgets/projects/projectdialog.py:70 msgid "Existing directory" msgstr "存在するディレクトリ" #: spyder/widgets/projects/projectdialog.py:72 msgid "Project name" msgstr "プロジェクト名" #: spyder/widgets/projects/projectdialog.py:73 msgid "Location" msgstr "位置" #: spyder/widgets/projects/projectdialog.py:74 msgid "Project type" msgstr "プロジェクトタイプ" #: spyder/widgets/projects/projectdialog.py:75 msgid "Python version" msgstr "Pythonバージョン" #: spyder/widgets/projects/projectdialog.py:83 #: spyder/widgets/variableexplorer/importwizard.py:529 msgid "Cancel" msgstr "キャンセル" #: spyder/widgets/projects/projectdialog.py:84 msgid "Create" msgstr "作成" #: spyder/widgets/projects/projectdialog.py:102 msgid "Create new project" msgstr "新規プロジェクト作成" #: spyder/widgets/projects/type/__init__.py:216 msgid "Empty project" msgstr "空のプロジェクト" #: spyder/widgets/projects/type/python.py:20 msgid "Python project" msgstr "Pythonプロジェクト" #: spyder/widgets/projects/type/python.py:76 msgid "Python package" msgstr "Pythonパッケージ" #: spyder/widgets/pydocgui.py:110 msgid "Module or package:" msgstr "モジュールあるいはパッケージ:" #: spyder/widgets/shell.py:131 msgid "Save history log..." msgstr "ヒストリログを保存..." #: spyder/widgets/shell.py:133 msgid "Save current history log (i.e. all inputs and outputs) in a text file" msgstr "現在のヒストリログ(全ての入出力)をテキストファイルに保存" #: spyder/widgets/shell.py:253 msgid "Save history log" msgstr "ヒストリログを保存" #: spyder/widgets/shell.py:256 msgid "History logs" msgstr "ヒストリログ" #: spyder/widgets/shell.py:670 msgid "Copy without prompts" msgstr "プロンプトなしでコピー" #: spyder/widgets/shell.py:673 spyder/widgets/shell.py:677 msgid "Clear line" msgstr "行をクリア" #: spyder/widgets/shell.py:679 msgid "Clear shell" msgstr "シェルをクリア" #: spyder/widgets/shell.py:683 msgid "Clear shell contents ('cls' command)" msgstr "シェルの中身をクリア(clsコマンド)" #: spyder/widgets/shortcutssummary.py:42 msgid "Spyder Keyboard ShortCuts" msgstr "Spyderキーボード・ショートカット" #: spyder/widgets/sourcecode/codeeditor.py:101 msgid "Go to line:" msgstr "行へ移動:" #: spyder/widgets/sourcecode/codeeditor.py:109 msgid "Line count:" msgstr "行数:" #: spyder/widgets/sourcecode/codeeditor.py:1327 msgid "Breakpoint" msgstr "ブレークポイント" #: spyder/widgets/sourcecode/codeeditor.py:1328 msgid "Condition:" msgstr "条件:" #: spyder/widgets/sourcecode/codeeditor.py:1733 msgid "Code analysis" msgstr "コード分析" #: spyder/widgets/sourcecode/codeeditor.py:1787 msgid "To do" msgstr "To do" #: spyder/widgets/sourcecode/codeeditor.py:2147 msgid "Removal error" msgstr "削除エラー" #: spyder/widgets/sourcecode/codeeditor.py:2148 msgid "" "It was not possible to remove outputs from this notebook. The error is:\n" "\n" msgstr "" "notebookからoutputを削除できませんでした。エラー:\n" "\n" #: spyder/widgets/sourcecode/codeeditor.py:2684 msgid "Clear all ouput" msgstr "全ての出力をクリア" #: spyder/widgets/sourcecode/codeeditor.py:2690 msgid "Go to definition" msgstr "定義へ移動" #: spyder/widgets/sourcecode/codeeditor.py:2723 msgid "Zoom reset" msgstr "ズームリセット" #: spyder/widgets/status.py:25 msgid "CPU and memory usage info in the status bar" msgstr "CPUとメモリの使用状況をステータスバーに表示" #: spyder/widgets/status.py:117 msgid "Memory:" msgstr "メモリ:" #: spyder/widgets/status.py:118 msgid "" "Memory usage status: requires the `psutil` (>=v0.3) library on non-Windows " "platforms" msgstr "" "メモリ使用状況の表示には非Windows環境では`psutil` (>=v0.3) が必要になります" #: spyder/widgets/status.py:134 msgid "CPU:" msgstr "CPU:" #: spyder/widgets/status.py:135 msgid "CPU usage status: requires the `psutil` (>=v0.3) library" msgstr "" "CPU使用状況の表示には非Windows環境では`psutil` (>=v0.3) が必要になります" #: spyder/widgets/status.py:162 msgid "Permissions:" msgstr "権限:" #: spyder/widgets/status.py:189 msgid "End-of-lines:" msgstr "改行:" #: spyder/widgets/status.py:216 msgid "Encoding:" msgstr "エンコード" #: spyder/widgets/status.py:242 msgid "Line:" msgstr "行:" #: spyder/widgets/status.py:243 msgid "Column:" msgstr "列:" #: spyder/widgets/tabs.py:274 msgid "Browse tabs" msgstr "tabを表示" #: spyder/widgets/tabs.py:403 msgid "Close current tab" msgstr "現在のタブを閉じる" #: spyder/widgets/variableexplorer/arrayeditor.py:511 msgid "It was not possible to copy values for this array" msgstr "配列の値をコピーできませんでした" #: spyder/widgets/variableexplorer/arrayeditor.py:546 #: spyder/widgets/variableexplorer/arrayeditor.py:579 #: spyder/widgets/variableexplorer/dataframeeditor.py:697 #: spyder/widgets/variableexplorer/dataframeeditor.py:742 msgid "Format" msgstr "フォーマット" #: spyder/widgets/variableexplorer/arrayeditor.py:551 #: spyder/widgets/variableexplorer/dataframeeditor.py:701 msgid "Resize" msgstr "リサイズ" #: spyder/widgets/variableexplorer/arrayeditor.py:554 #: spyder/widgets/variableexplorer/dataframeeditor.py:705 msgid "Background color" msgstr "背景色" #: spyder/widgets/variableexplorer/arrayeditor.py:580 #: spyder/widgets/variableexplorer/dataframeeditor.py:743 msgid "Float formatting" msgstr "浮動小数点フォーマット" #: spyder/widgets/variableexplorer/arrayeditor.py:588 msgid "Format (%s) is incorrect" msgstr "フォーマット (%s) が不正です" #: spyder/widgets/variableexplorer/arrayeditor.py:624 msgid "Arrays with more than 3 dimensions are not supported" msgstr "3次元以上の配列はサポートされていません" #: spyder/widgets/variableexplorer/arrayeditor.py:628 msgid "The 'xlabels' argument length do no match array column number" msgstr "'xlabels'引数の長さが配列の列数に一致していません" #: spyder/widgets/variableexplorer/arrayeditor.py:632 msgid "The 'ylabels' argument length do no match array row number" msgstr "'ylabels'引数の長さが配列の行数に一致していません" #: spyder/widgets/variableexplorer/arrayeditor.py:639 msgid "%s arrays" msgstr "%s 配列" #: spyder/widgets/variableexplorer/arrayeditor.py:640 msgid "%s are currently not supported" msgstr "%s は現在サポートされていません" #: spyder/widgets/variableexplorer/arrayeditor.py:647 msgid "NumPy array" msgstr "NumPy配列" #: spyder/widgets/variableexplorer/arrayeditor.py:649 #: spyder/widgets/variableexplorer/arrayeditor.py:806 msgid "Array editor" msgstr "配列エディタ" #: spyder/widgets/variableexplorer/arrayeditor.py:651 msgid "read only" msgstr "読み取り専用" #: spyder/widgets/variableexplorer/arrayeditor.py:681 msgid "Record array fields:" msgstr "配列のフィールドを記録:" #: spyder/widgets/variableexplorer/arrayeditor.py:693 msgid "Data" msgstr "データ" #: spyder/widgets/variableexplorer/arrayeditor.py:693 msgid "Mask" msgstr "マスク" #: spyder/widgets/variableexplorer/arrayeditor.py:693 msgid "Masked data" msgstr "Maskedデータ" #: spyder/widgets/variableexplorer/arrayeditor.py:704 msgid "Axis:" msgstr "軸:" #: spyder/widgets/variableexplorer/arrayeditor.py:709 msgid "Index:" msgstr "インデックス:" #: spyder/widgets/variableexplorer/arrayeditor.py:722 msgid "Warning: changes are applied separately" msgstr "警告: 変更は別々に適用されます" #: spyder/widgets/variableexplorer/arrayeditor.py:723 msgid "" "For performance reasons, changes applied to masked array won't be reflected " "in array's data (and vice-versa)." msgstr "" "実行性能に関する理由により、masked配列に適用された変更は配列内のデータには反" "映されません(逆もまた同様)。" #: spyder/widgets/variableexplorer/collectionseditor.py:126 msgid "Index" msgstr "インデックス" #: spyder/widgets/variableexplorer/collectionseditor.py:131 msgid "Tuple" msgstr "タプル" #: spyder/widgets/variableexplorer/collectionseditor.py:134 msgid "List" msgstr "リスト" #: spyder/widgets/variableexplorer/collectionseditor.py:137 msgid "Dictionary" msgstr "ディクショナリ" #: spyder/widgets/variableexplorer/collectionseditor.py:139 msgid "Key" msgstr "キー" #: spyder/widgets/variableexplorer/collectionseditor.py:144 msgid "Attribute" msgstr "属性" #: spyder/widgets/variableexplorer/collectionseditor.py:148 msgid "elements" msgstr "要素" #: spyder/widgets/variableexplorer/collectionseditor.py:319 msgid "Size" msgstr "サイズ" #: spyder/widgets/variableexplorer/collectionseditor.py:319 msgid "Type" msgstr "型" #: spyder/widgets/variableexplorer/collectionseditor.py:319 msgid "Value" msgstr "値" #: spyder/widgets/variableexplorer/collectionseditor.py:417 msgid "" "Opening this variable can be slow\n" "\n" "Do you want to continue anyway?" msgstr "" "この変数を開くには時間がかかる場合があります\n" "\n" "続行しますか?" #: spyder/widgets/variableexplorer/collectionseditor.py:428 msgid "" "Spyder was unable to retrieve the value of this variable from the console." "

The error mesage was:
%s" msgstr "" "Spyderはコンソールから変数の値を読み取ることができませんでした。

エ" "ラーメッセージ:
%s" #: spyder/widgets/variableexplorer/collectionseditor.py:605 msgid "Edit item" msgstr "アイテムを編集" #: spyder/widgets/variableexplorer/collectionseditor.py:606 msgid "Unable to assign data to item.

Error message:
%s" msgstr "" "アイテムにデータを割り当てられません。

エラーメッセージ:
%s" #: spyder/widgets/variableexplorer/collectionseditor.py:666 msgid "Resize rows to contents" msgstr "行数を中身に応じて変更" #: spyder/widgets/variableexplorer/collectionseditor.py:677 #: spyder/widgets/variableexplorer/collectionseditor.py:1027 #: spyder/widgets/variableexplorer/collectionseditor.py:1044 msgid "Plot" msgstr "プロット" #: spyder/widgets/variableexplorer/collectionseditor.py:681 msgid "Histogram" msgstr "ヒストグラム" #: spyder/widgets/variableexplorer/collectionseditor.py:685 msgid "Show image" msgstr "画像を表示" #: spyder/widgets/variableexplorer/collectionseditor.py:689 #: spyder/widgets/variableexplorer/collectionseditor.py:1052 msgid "Save array" msgstr "配列を保存" #: spyder/widgets/variableexplorer/collectionseditor.py:693 #: spyder/widgets/variableexplorer/collectionseditor.py:991 #: spyder/widgets/variableexplorer/collectionseditor.py:999 msgid "Insert" msgstr "挿入" #: spyder/widgets/variableexplorer/collectionseditor.py:706 #: spyder/widgets/variableexplorer/collectionseditor.py:952 msgid "Duplicate" msgstr "複製" #: spyder/widgets/variableexplorer/collectionseditor.py:929 msgid "Do you want to remove the selected item?" msgstr "選択されたアイテムを除去しますか?" #: spyder/widgets/variableexplorer/collectionseditor.py:930 msgid "Do you want to remove all selected items?" msgstr "選択された全てのアイテムを除去しますか?" #: spyder/widgets/variableexplorer/collectionseditor.py:950 msgid "New variable name:" msgstr "新しい変数名:" #: spyder/widgets/variableexplorer/collectionseditor.py:953 msgid "Variable name:" msgstr "変数名:" #: spyder/widgets/variableexplorer/collectionseditor.py:991 msgid "Key:" msgstr "キー:" #: spyder/widgets/variableexplorer/collectionseditor.py:999 msgid "Value:" msgstr "値:" #: spyder/widgets/variableexplorer/collectionseditor.py:1015 msgid "Import error" msgstr "インポートエラー" #: spyder/widgets/variableexplorer/collectionseditor.py:1016 msgid "Please install matplotlib or guiqwt." msgstr "matplotlibguiqwt をインストールしてください。" #: spyder/widgets/variableexplorer/collectionseditor.py:1028 msgid "Unable to plot data.

Error message:
%s" msgstr "データをプロットできません。

エラーメッセージ:
%s" #: spyder/widgets/variableexplorer/collectionseditor.py:1045 msgid "Unable to show image.

Error message:
%s" msgstr "画像を表示できません。

エラーメッセージ:
%s" #: spyder/widgets/variableexplorer/collectionseditor.py:1068 msgid "Unable to save array

Error message:
%s" msgstr "配列を保存できません

エラーメッセージ:
%s" #: spyder/widgets/variableexplorer/collectionseditor.py:1093 msgid "It was not possible to copy this array" msgstr "配列をコピーできませんでした" #: spyder/widgets/variableexplorer/collectionseditor.py:1118 msgid "Clipboard contents" msgstr "クリップボードの内容" #: spyder/widgets/variableexplorer/collectionseditor.py:1133 msgid "Import from clipboard" msgstr "クリップボードからインポート" #: spyder/widgets/variableexplorer/collectionseditor.py:1135 msgid "Empty clipboard" msgstr "クリップボードを空にする" #: spyder/widgets/variableexplorer/collectionseditor.py:1136 msgid "Nothing to be imported from clipboard." msgstr "クリップボードからインポートするものはありません。" #: spyder/widgets/variableexplorer/dataframeeditor.py:591 msgid "To bool" msgstr "真偽値へ" #: spyder/widgets/variableexplorer/dataframeeditor.py:591 msgid "To complex" msgstr "複素数へ" #: spyder/widgets/variableexplorer/dataframeeditor.py:592 msgid "To float" msgstr "浮動小数点数へ" #: spyder/widgets/variableexplorer/dataframeeditor.py:592 msgid "To int" msgstr "整数へ" #: spyder/widgets/variableexplorer/dataframeeditor.py:593 msgid "To str" msgstr "文字列へ" #: spyder/widgets/variableexplorer/dataframeeditor.py:677 msgid "%s editor" msgstr "%s エディタ" #: spyder/widgets/variableexplorer/dataframeeditor.py:711 msgid "Column min/max" msgstr "列の 最小/最大" #: spyder/widgets/variableexplorer/dataframeeditor.py:751 msgid "Format ({}) is incorrect" msgstr "フォーマット ({}) が不正です" #: spyder/widgets/variableexplorer/dataframeeditor.py:755 msgid "Format ({}) should start with '%'" msgstr "フォーマット({}) は'%'で開始する必要があります" #: spyder/widgets/variableexplorer/importwizard.py:118 #: spyder/widgets/variableexplorer/importwizard.py:438 msgid "Import as" msgstr "形式を指定してインポート" #: spyder/widgets/variableexplorer/importwizard.py:120 msgid "data" msgstr "データ" #: spyder/widgets/variableexplorer/importwizard.py:124 msgid "code" msgstr "コード" #: spyder/widgets/variableexplorer/importwizard.py:127 #: spyder/widgets/variableexplorer/importwizard.py:514 msgid "text" msgstr "テキスト" #: spyder/widgets/variableexplorer/importwizard.py:140 msgid "Column separator:" msgstr "列セパレータ" #: spyder/widgets/variableexplorer/importwizard.py:144 msgid "Tab" msgstr "タブ" #: spyder/widgets/variableexplorer/importwizard.py:147 msgid "Whitespace" msgstr "空白スペース" #: spyder/widgets/variableexplorer/importwizard.py:150 #: spyder/widgets/variableexplorer/importwizard.py:168 msgid "other" msgstr "その他" #: spyder/widgets/variableexplorer/importwizard.py:161 msgid "Row separator:" msgstr "行セパレーター" #: spyder/widgets/variableexplorer/importwizard.py:165 msgid "EOL" msgstr "EOL" #: spyder/widgets/variableexplorer/importwizard.py:180 msgid "Additional options" msgstr "追加オプション" #: spyder/widgets/variableexplorer/importwizard.py:184 msgid "Skip rows:" msgstr "行を飛ばす:" #: spyder/widgets/variableexplorer/importwizard.py:195 msgid "Comments:" msgstr "コメント:" #: spyder/widgets/variableexplorer/importwizard.py:201 msgid "Transpose" msgstr "転置" #: spyder/widgets/variableexplorer/importwizard.py:441 msgid "array" msgstr "配列" #: spyder/widgets/variableexplorer/importwizard.py:446 msgid "list" msgstr "リスト" #: spyder/widgets/variableexplorer/importwizard.py:451 msgid "DataFrame" msgstr "DataFrame" #: spyder/widgets/variableexplorer/importwizard.py:497 #: spyder/widgets/variableexplorer/importwizard.py:581 msgid "Import wizard" msgstr "インポートウィザード" #: spyder/widgets/variableexplorer/importwizard.py:502 msgid "Raw text" msgstr "Rawテキスト" #: spyder/widgets/variableexplorer/importwizard.py:505 msgid "variable_name" msgstr "variable_name" #: spyder/widgets/variableexplorer/importwizard.py:516 msgid "table" msgstr "テーブル" #: spyder/widgets/variableexplorer/importwizard.py:517 msgid "Preview" msgstr "プレビュー" #: spyder/widgets/variableexplorer/importwizard.py:521 msgid "Variable Name" msgstr "変数名" #: spyder/widgets/variableexplorer/importwizard.py:544 msgid "Done" msgstr "完了" #: spyder/widgets/variableexplorer/importwizard.py:582 msgid "" "Unable to proceed to next step

Please check your entries." "

Error message:
%s" msgstr "" "次のステップを実行できません

入力をチェックしてください。" "

エラーメッセージ:
%s" #: spyder/widgets/variableexplorer/namespacebrowser.py:181 #: spyder/widgets/variableexplorer/namespacebrowser.py:385 msgid "Import data" msgstr "データをインポート" #: spyder/widgets/variableexplorer/namespacebrowser.py:184 #: spyder/widgets/variableexplorer/namespacebrowser.py:465 #: spyder/widgets/variableexplorer/namespacebrowser.py:479 msgid "Save data" msgstr "データを保存" #: spyder/widgets/variableexplorer/namespacebrowser.py:189 msgid "Save data as..." msgstr "形式を指定してデータ保存" #: spyder/widgets/variableexplorer/namespacebrowser.py:201 msgid "Exclude references which name starts with an underscore" msgstr "アンダースコアで始まる参照を除外" #: spyder/widgets/variableexplorer/namespacebrowser.py:209 msgid "Exclude references which name is uppercase" msgstr "名前が大文字の参照を除外" #: spyder/widgets/variableexplorer/namespacebrowser.py:216 msgid "Exclude references which name starts with an uppercase character" msgstr "大文字で始まる参照を除外" #: spyder/widgets/variableexplorer/namespacebrowser.py:224 msgid "" "Exclude references to unsupported data types (i.e. which won't be handled/" "saved correctly)" msgstr "非サポートデータ型(例:正しくhandle/saveがができない型)への参照を除外 " #: spyder/widgets/variableexplorer/namespacebrowser.py:405 msgid "" "Unsupported file extension '%s'

Would you like to import it " "anyway (by selecting a known file format)?" msgstr "" "サポートされていないファイル拡張 '%s'

(既知のファイルフォーマッ" "トを選択して)とにかくインポートしますか ?" #: spyder/widgets/variableexplorer/namespacebrowser.py:413 msgid "Open file as:" msgstr "形式を指定して開く:" #: spyder/widgets/variableexplorer/namespacebrowser.py:447 msgid "Unable to load '%s'

Error message:
%s" msgstr " '%s' をロードできません

エラーメッセージ:
%s" #: spyder/widgets/variableexplorer/namespacebrowser.py:480 msgid "Unable to save current workspace

Error message:
%s" msgstr "" "現在のワークスペースを保存できません

エラーメッセージ:
%s" #: spyder/widgets/variableexplorer/texteditor.py:74 msgid "Text editor" msgstr "テキストエディタ" #: spyder/widgets/variableexplorer/utils.py:30 msgid "View and edit DataFrames and Series in the Variable Explorer" msgstr "変数エクスプローラーでのDataFrameとSeriesの表示・編集" #: spyder/widgets/variableexplorer/utils.py:35 msgid "View and edit two and three dimensional arrays in the Variable Explorer" msgstr "変数エクスプローラーでの2, 3次元配列の表示・編集" #: spyder/workers/updates.py:90 spyder/workers/updates.py:92 msgid "Unable to retrieve information." msgstr "情報が取得できません" #: spyder/workers/updates.py:94 msgid "" "Unable to connect to the internet.

Make sure the connection is " "working properly." msgstr "" "インターネットに接続できません。

接続が正しく動作しているか確認してく" "ださい。" #: spyder/workers/updates.py:97 msgid "Unable to check for updates." msgstr "更新をチェックできません" #~ msgid "At startup, the current working directory is:" #~ msgstr "スタートアップ時の作業ディレクトリ:" #~ msgid "At startup," #~ msgstr "スタートアップ" #~ msgid "At startup, the current working directory will be the specified path" #~ msgstr "" #~ "作業ディレクトリはスタートアップ時に設定されたパスにより決定されます" #~ msgid "Reset namespace" #~ msgstr "名前空間をリセットする" #~ msgid "Reset IPython namespace" #~ msgstr "IPythonの名前空間をリセット" #~ msgid "Loading external console..." #~ msgstr "外部コンソールをロード中..." #~ msgid "The Python console" #~ msgstr "Pythonコンソール" #~ msgid "" #~ "You can also run your code on a Python console. These consoles are useful " #~ "because they let you run a file in a console dedicated only to it.To " #~ "select this behavior, please press the F6 key.

By pressing " #~ "the button below and then focusing the Variable Explorer, you will notice " #~ "that Python consoles are also connected to that pane, and that the " #~ "Variable Explorer only shows the variables of the currently focused " #~ "console." #~ msgstr "" #~ "Pythonコンソールでもpythonコードを実行することができます。これらのコンソー" #~ "ルはファイルに書かれたコードを実行することに特化しており有用です。挙動を選" #~ "択するためには F6 キーを押してください。

下のボタンを押し変" #~ "数エクスプローラーをフォーカスすると、Pythonコンソールもペインに連結されて" #~ "いることや変数エクスプローラーは現在フォーカスされているコンソールの変数の" #~ "みを表示するということがわかります。" #~ msgid "Sort files according to full path" #~ msgstr "フルパスでファイルをソート" #~ msgid "&Configure..." #~ msgstr "設定(&C)..." #~ msgid "Show TODO/FIXME/XXX/HINT/TIP/@todo comments list" #~ msgstr "TODO/FIXME/XXX/HINT/TIP/@todo リストを表示" #~ msgid "Interactive data plotting in the consoles" #~ msgstr "コンソールでの対話的データプロット" #~ msgid "Python console" #~ msgstr "Pythonコンソール" #~ msgid "One tab per script" #~ msgstr "1スクリプト1タブ" #~ msgid "Buffer: " #~ msgstr "バッファー:" #~ msgid "Merge process standard output/error channels" #~ msgstr "プロセス標準出力/エラーチャンネルをマージ" #~ msgid "" #~ "Merging the output channels of the process means that\n" #~ "the standard error won't be written in red anymore,\n" #~ "but this has the effect of speeding up display." #~ msgstr "" #~ "プロセスの出力チャンネルをマージした場合\n" #~ "標準エラーは赤色で表示されなくなりますが、\n" #~ "表示は高速化されます。" #~ msgid "Colorize standard error channel using ANSI escape codes" #~ msgstr "標準エラーチャンネルをANSIエスケープコードで色分け" #~ msgid "" #~ "This method is the only way to have colorized standard\n" #~ "error channel when the output channels have been merged." #~ msgstr "" #~ "出力チャンネルがマージされた場合、これは標準エラーチャンネルを\n" #~ "色分けする唯一の方法となります。" #~ msgid "" #~ "This option will be applied the next time a Python console or a terminal " #~ "is opened." #~ msgstr "" #~ "このオプションは次回Pythonコンソールかターミナルが開かれた時適用されます。" #~ msgid "Light background (white color)" #~ msgstr "明るい背景(白色)" #~ msgid "PYTHONSTARTUP replacement" #~ msgstr "PYTHONSTARTUP代替物" #~ msgid "" #~ "This option will override the PYTHONSTARTUP environment variable which\n" #~ "defines the script to be executed during the Python console startup." #~ msgstr "" #~ "このオプションはPYTHONSTARTUP環境変数(Pythonコンソール起動時に実行する\n" #~ "スクリプトを指定する)を上書きします。" #~ msgid "Default PYTHONSTARTUP script" #~ msgstr "デフォルトPYTHONSTARTUPスクリプト" #~ msgid "Use the following startup script:" #~ msgstr "以下のスタートアップスクリプトを実行:" #~ msgid "Monitor" #~ msgstr "モニター" #~ msgid "" #~ "The monitor provides introspection features to console: code completion, " #~ "calltips and variable explorer. Because it relies on several modules, " #~ "disabling the monitor may be useful to accelerate console startup." #~ msgstr "" #~ "モニターによりコンソールでコード補完、 コールティップス及び変数エクスプ" #~ "ローラー等のintrospection機能が利用できます。モニターは複数のモジュールに" #~ "依存するため、無効化した場合コンソールのスタートアップを高速化できます。" #~ msgid "Enable monitor" #~ msgstr "モニターを有効化" #~ msgid "Default library" #~ msgstr "デフォルトライブラリ" #~ msgid "Qt-Python Bindings" #~ msgstr "Qt-Pythonバインディング" #~ msgid "Library:" #~ msgstr "ライブラリ:" #~ msgid "" #~ "This option will act on
libraries such as Matplotlib, guidata or ETS" #~ msgstr "" #~ "このオプションは
Matplotlib、guidata、ETS等のライブラリで機能します" #~ msgid "" #~ "Decide which backend to use to display graphics. If unsure, please select " #~ "the Automatic backend.

Note: We support a very " #~ "limited number of backends in our Python consoles. If you prefer to work " #~ "with a different one, please use an IPython console." #~ msgstr "" #~ "画像を表示するためにどのバックエンドを使うか選択してください。よくわからな" #~ "い場合Automatic バックエンドを選んでください。

注: " #~ "Pythonコンソールでサポートされるバックエンドは非常に限られています。もし別" #~ "のバックエンドを使いたい場合IPythonコンソールを使ってください。" #~ msgid "None" #~ msgstr "なし" #~ msgid "Enthought Tool Suite" #~ msgstr "Enthoughtツールスイート" #~ msgid "" #~ "Enthought Tool Suite (ETS) supports PyQt4 (qt4) and wxPython (wx) " #~ "graphical user interfaces." #~ msgstr "" #~ "Enthoughtツールスイート(ETS)はPyQt4(qt4)とwxPython(wx)GUIをサポートしま" #~ "す。" #~ msgid "ETS_TOOLKIT:" #~ msgstr "ETS_TOOLKIT:" #~ msgid "External modules" #~ msgstr "外部モジュール" #~ msgid "" #~ "No Python console is currently selected to run %s.

Please " #~ "select or open a new Python console and try again." #~ msgstr "" #~ "実行対象として選ばれているPythonコンソールがありません: %s。" #~ "

選択するか新規Pythonコンソールを開いて再試行してください。" #~ msgid "" #~ "%s is already running in a separate process.\n" #~ "Do you want to kill the process before starting a new one?" #~ msgstr "" #~ "%s は既に別プロセスで実行されています。\n" #~ "新しいプロセスを開始する前にそのプロセスを殺しますか?" #~ msgid "Command Window" #~ msgstr "コマンドウインドウ" #~ msgid "Open a &Python console" #~ msgstr "Pythonコンソールを開く(&O)" #~ msgid "Open &command prompt" #~ msgstr "コマンドプロンプトを開く(&C)" #~ msgid "Open a Windows command prompt" #~ msgstr "Windowsコマンドプロンプトを開く" #~ msgid "Open a &terminal" #~ msgstr "ターミナルを開く(&T)" #~ msgid "Open a terminal window" #~ msgstr "ターミナルウインドウを開く" #~ msgid "Python Console" #~ msgstr "Pythonコンソール" #~ msgid "Light background" #~ msgstr "明るい背景" #~ msgid "Dark background" #~ msgstr "暗い背景" #~ msgid "Working directory:" #~ msgstr "作業ディレクトリ:" #~ msgid "Dedicated Python console" #~ msgstr "Dedicated Pythonコンソール" #~ msgid "Show warning when killing running process" #~ msgstr "実行中プロセスが殺された場合には警告を表示" #~ msgid "Run Settings" #~ msgstr "実行設定" #~ msgid "the script directory" #~ msgstr "スクリプトディレクトリ" #~ msgid "Show warning when killing running processes" #~ msgstr "実行中のプロセスが殺された場合警告を表示" #~ msgid "Autorefresh" #~ msgstr "自動リフレッシュ" #~ msgid "Enable autorefresh" #~ msgstr "自動リフレッシュを有効化" #~ msgid "Refresh interval: " #~ msgstr "リフレッシュ間隔:" #~ msgid "" #~ "The global working directory is the working directory for newly " #~ "opened consoles (Python/IPython consoles and terminals), for the " #~ "file explorer, for the find in files plugin and for new " #~ "files created in the editor." #~ msgstr "" #~ "グローバル作業ディレクトリファイルエクスプローラー" #~ "ファイル検索プラグイン、コンソール(Python/IPython コンソールと" #~ "ターミナル) を新しく開いた場合、エディタで新規ファイルを開いた場合" #~ "の作業ディレクトリです。 " #~ msgid "the same as in last session" #~ msgstr "最後のセッションと同じ" #~ msgid "" #~ "At startup, Spyder will restore the global directory from last session" #~ msgstr "" #~ "Spyderはスタートアップ時に最後のセッションからグローバル作業ディレクトリを" #~ "復元します" #~ msgid "Files are opened from:" #~ msgstr "ファイルは以下のディレクトリから開かれます:" #~ msgid "the current file directory" #~ msgstr "現在のファイルディレクトリ" #~ msgid "the global working directory" #~ msgstr "グローバル作業ディレクトリ" #~ msgid "Files are created in:" #~ msgstr "新規ファイルは以下のディレクトリに作成されます:" #~ msgid "Change to file base directory" #~ msgstr "ファイルディレクトリを変更するタイミング" #~ msgid "When opening a file" #~ msgstr "ファイルを開いた時" #~ msgid "When saving a file" #~ msgstr "ファイルを保存する時" #~ msgid "Global working directory" #~ msgstr "グローバル作業ディレクトリ" #~ msgid "Unable to save script '%s'

Error message:
%s" #~ msgstr "" #~ "スクリプト '%s' を保存できません

エラーメッセージ:
%s" #~ msgid "Run again this program" #~ msgstr "プログラムを再度実行する" #~ msgid "Kill" #~ msgstr "殺す" #~ msgid "Kills the current process, causing it to exit immediately" #~ msgstr "現在のプロセスを殺し、直ちにexit" #~ msgid "Running..." #~ msgstr "実行中..." #~ msgid "Terminated." #~ msgstr "終了。" #~ msgid "Command line arguments:" #~ msgstr "コマンドライン引数:" #~ msgid "" #~ "NOTE: The Python console is going to be REMOVED in Spyder 3.2. Please " #~ "start to migrate your work to the IPython console instead.\n" #~ "\n" #~ msgstr "" #~ "注:PythonコンソールはSpyder3.2で*削除*される予定です。代わりとなるIPython" #~ "コンソールへの移行を検討して下さい。\n" #~ "\n" #~ "\n" #~ msgid "Variables" #~ msgstr "変数" #~ msgid "Show/hide global variables explorer" #~ msgstr "変数エクスプローラの表示/隠す" #~ msgid "Terminate" #~ msgstr "終了" #~ msgid "" #~ "Attempts to stop the process. The process\n" #~ "may not exit as a result of clicking this\n" #~ "button (it is given the chance to prompt\n" #~ "the user for any unsaved files, etc)." #~ msgstr "" #~ "プロセスを停止させる。 このボタンを\n" #~ "押しただけではプロセスはまだ停止\n" #~ "しません。(未保存のファイルの扱いを\n" #~ "尋ねる,etc)" #~ msgid "Interact" #~ msgstr "相互作用" #~ msgid "Debug" #~ msgstr "デバッグ" #~ msgid "Arguments..." #~ msgstr "引数..." #~ msgid "Post Mortem Debug" #~ msgstr "事後デバッグ" #~ msgid "Arguments: %s" #~ msgstr "引数: %s" #~ msgid "No argument" #~ msgstr "引数なし" #~ msgid "A Python console failed to start!" #~ msgstr "Pythonコンソールを開始できませんでした!" #~ msgid "Process failed to start" #~ msgstr "プロセスを開始できませんでした" #~ msgid "Included filenames pattern" #~ msgstr "含まれるファイル名パターン" #~ msgid "Include:" #~ msgstr "含む:" #~ msgid "PYTHONPATH" #~ msgstr "PYTHONPATH" #~ msgid "" #~ "Search in all directories listed in sys.path which are outside the Python " #~ "installation directory" #~ msgstr "" #~ "Pythonインストールディレクトリ外のsys.pathにリストアップされたディレクトリ" #~ "内を検索" #~ msgid "Hg repository" #~ msgstr "Hgレポジトリ" #~ msgid "Search in current directory hg repository" #~ msgstr "カレントディレクトリのHgレポジトリを検索" #~ msgid "Here:" #~ msgstr "ここ:" #~ msgid "Search recursively in this directory" #~ msgstr "ディレクトリ内を再帰的に検索" #~ msgid "Browse a search directory" #~ msgstr "検索ディレクトリを表示" #~ msgid "Search canceled" #~ msgstr "検索をキャンセル" #~ msgid "interrupted" #~ msgstr "中断" #~ msgid "" #~ "
Restarting kernel because an error occurred while debugging\n" #~ "

" #~ msgstr "" #~ "
デバッグ中にエラーが発生したのでカーネルを再起動しています\n" #~ "

" #~ msgid "" #~ "Inspecting and setting values while debugging in IPython consoles is not " #~ "supported yet by Spyder." #~ msgstr "" #~ "IPythonコンソール内でのデバッグ中の変数変更及びインスペクションは、まだサ" #~ "ポートされていません。" #~ msgid "Refresh" #~ msgstr "リフレッシュ" #~ msgid "Refresh periodically" #~ msgstr "定期的にリフレッシュ" #~ msgid "Python(x,y)" #~ msgstr "Python(x,y)" #~ msgid "Python(x,y) launcher" #~ msgstr "Python(x,y)ランチャー" #~ msgid "Python(x,y) documentation folder" #~ msgstr "Python(x,y) ドキュメントフォルダ" #~ msgid "guidata documentation" #~ msgstr "guidataドキュメント" #~ msgid "guiqwt documentation" #~ msgstr "guiqwtドキュメント" #~ msgid "NumPy documentation" #~ msgstr "NumPyドキュメント" #~ msgid "NumPy reference guide" #~ msgstr "NumPyリファレンスガイド" #~ msgid "NumPy user guide" #~ msgstr "NumPyユーザーガイド" #~ msgid "SciPy documentation" #~ msgstr "SciPyドキュメント" #~ msgid "Show/hide project explorer" #~ msgstr "プロジェクトエクスプローラーの表示/隠す" #~ msgid "?" #~ msgstr "?" #~ msgid "Use %s+T when the console is selected to open a new one" #~ msgstr "コンソールを新しく開く場合 %s+T を使う" #~ msgid "Edit data in the remote process" #~ msgstr "リモートプロセスのデータを編集する" #~ msgid "" #~ "Editors are opened in the remote process for NumPy arrays, PIL images, " #~ "lists, tuples and dictionaries.\n" #~ "This avoids transfering large amount of data between the remote process " #~ "and Spyder (through the socket)." #~ msgstr "" #~ "エディタはリモートプロセスで開かれています(NumPy配列、PILイメージ、リスト" #~ "タプル及び辞書型のため)。\n" #~ "これによりリモートプロセスとSpyder間のsokectによる膨大なデータ転送を避ける" #~ "ことができます。" #~ msgid "Array is empty" #~ msgstr "配列が空です" #~ msgid "Object %s is not picklable" #~ msgstr "オブジェクト %s はpickle化できません" #~ msgid "Truncate values" #~ msgstr "値を切り捨て" #~ msgid "" #~ "\n" #~ "\n" #~ "{0}" #~ msgstr "" #~ "\n" #~ "\n" #~ "{0}" #~ msgid "Reload last session" #~ msgstr "前回のセッションをリロードする" #~ msgid "Load session..." #~ msgstr "セッションをロード..." #~ msgid "Load Spyder session" #~ msgstr "Spyderのセッションをロード" #, fuzzy #~ msgid "Save session..." #~ msgstr "セッションを保存" #~ msgid "Save current session and quit application" #~ msgstr "現在のセッションを保存しアプリケーションを終了" #~ msgid "Open session" #~ msgstr "セッションを開く" #~ msgid "Spyder sessions" #~ msgstr "Spyderセッション" #~ msgid "Save session" #~ msgstr "セッションを保存" #~ msgid "Jupyter Qtconsole integration" #~ msgstr "Jupyter Qtconsole 統合" #~ msgid "Python executable" #~ msgstr "Python実行可能ファイル" #~ msgid "Trying to kill a kernel?" #~ msgstr "カーネルをキルしますか?" #~ msgid "" #~ "You can't close this kernel because it has one or more consoles connected " #~ "to it.

You need to close them instead or you can kill the kernel " #~ "using the second button from right to left." #~ msgstr "" #~ "接続されているコンソールがあるためカーネルを閉じることができません。" #~ "

接続済みコンソールを閉じるか、右から2番めのボタンを押してカーネル" #~ "をキルしてください。" #~ msgid "Kernel" #~ msgstr "カーネル" #~ msgid "" #~ "Either:
  1. Your IPython frontend and kernel versions are " #~ "incompatible or
  2. You don't have IPython installed in " #~ "your external interpreter.
In any case, we're sorry but we can't " #~ "create a console for you." #~ msgstr "" #~ "どちらか:
  1. IPythonフロントエンドとカーネルのバージョンは 非互換
  2. 外部インタープリターとしてIPythonがインストールされていま" #~ "せん
いずれの理由にせよコンソールを作成できません。" #~ msgid "Kernel %s" #~ msgstr "カーネル %s" #~ msgid "Open an IPython console" #~ msgstr "IPythonコンソールを開く" #~ msgid "" #~ "The console monitor was disabled: the IPython kernel will be started as " #~ "expected, but an IPython console will have to be connected manually to " #~ "the kernel." #~ msgstr "" #~ "コンソールモニターは無効化されています:IPythonカーネルは開始されましたが" #~ "IPythonコンソールは手動でカーネルに接続する必要が有ります。" #~ msgid "" #~ "UMR excluded modules:\n" #~ "(example: guidata, guiqwt)" #~ msgstr "" #~ "UMRから除外するモジュール:\n" #~ "(例: guidata, guiqwt)" #~ msgid "" #~ "This feature requires the Matplotlib library.\n" #~ "It seems you don't have it installed." #~ msgstr "" #~ "この機能にはMatplotlibライブラリが必要です。\n" #~ "Matplotlibはインストールされていないようです。" #~ msgid "" #~ "This feature requires the Sympy library.\n" #~ "It seems you don't have it installed." #~ msgstr "" #~ "この機能にはSympyライブラリが必要です。\n" #~ "インストールされていないようです。" #~ msgid "&Font..." #~ msgstr "フォント(&F)..." #~ msgid "Set font style" #~ msgstr "フォントスタイルを設定" #~ msgid "Select a new font" #~ msgstr "新規フォントを選択" #~ msgid "" #~ "The kernel failed to start!! That's all we know... Please close this " #~ "console and open a new one." #~ msgstr "" #~ "カーネルは開始できませんでした!!これがわかっていることの全てです...この" #~ "コンソールを閉じて再度新しく開いてください。" #~ msgid "" #~ "It seems the kernel died unexpectedly. Use 'Restart kernel' to continue " #~ "using this console." #~ msgstr "" #~ "カーネルが予期せず停止したようです。このコンソールを続行するには\"カーネル" #~ "の再起動\"を利用してください。" #~ msgid "Kernel process is either remote or unspecified. Cannot interrupt" #~ msgstr "カーネルプロセスはリモートあるいは詳細不明です。中断できません" #~ msgid "Kernel process is either remote or unspecified. Cannot restart." #~ msgstr "カーネルプロセスはリモートあるいは詳細不明です。再起動できません。" #~ msgid "its own configuration file" #~ msgstr "独自の設定ファイル" #~ msgid " and " #~ msgstr "及び" #~ msgid "the following projects:
%s" #~ msgstr "以下のプロジェクト:
%s" #~ msgid "Existing Pydev project" #~ msgstr "存在するPydevプロジェクト" #~ msgid "Close unrelated projects" #~ msgstr "関係のないプロジェクトを閉じる" #~ msgid "Edit related projects" #~ msgstr "関係するプロジェクトを編集" #~ msgid "Add to PYTHONPATH" #~ msgstr "PYTHONPATHに追加" #~ msgid "Remove from PYTHONPATH" #~ msgstr "PYTHONPATHから削除" #~ msgid "Properties" #~ msgstr "プロパティ" #~ msgid "" #~ "The workspace was unable to load or save %s

Please check if you " #~ "have the permission to write the associated configuration files." #~ msgstr "" #~ "ワークスペースは保存あるいは復元できませんでした。 %s

関係づけられ" #~ "ている設定ファイルへの書き込み権限があるかチェックしてください。" #~ msgid "Import directory" #~ msgstr "ディレクトリのインポート" #~ msgid "" #~ "The following directory is not in workspace:
%s

Do you " #~ "want to continue (and copy the directory to workspace)?" #~ msgstr "" #~ "以下のディレクトリがワークスーペース内にありません。
%s

(ディレクトリをワークスペースにコピーして)続行しますか?" #~ msgid "The project %s is already opened!" #~ msgstr "プロジェクト%sは既に開いています!" #~ msgid "" #~ "The project root path directory is inside the workspace but not as the " #~ "expected tree level. It is not a directory of the workspace:
%s" #~ msgstr "" #~ "プロジェクトのルートディレクトリはワークスペース内に有りますが想定された階" #~ "層にありません。 ワークスペース:
%sのディレクトリではありません" #~ msgid "A project named %s already exists" #~ msgstr "%sという名前のプロジェクトは既に存在します" #~ msgid "" #~ "Invalid project name.

Name must match the following regular " #~ "expression:
%s" #~ msgstr "" #~ "無効なプロジェクト名。

プロジェクト名は以下の正規表現に従ってくださ" #~ "い:
%s" #~ msgid "" #~ "The following directory is not empty:
%s

Do you want to " #~ "continue?" #~ msgstr "" #~ "以下のディレクトリは空ではありません:
%s

続行しますか?" #~ msgid "New project" #~ msgstr "New project_" #~ msgid "" #~ "The current workspace has not been configured yet.\n" #~ "Do you want to do this now?" #~ msgstr "" #~ "現在のワークスペースはまだ設定がされていません。\n" #~ "すぐに設定しますか?" #~ msgid "Import existing project" #~ msgstr "既存のプロジェクトをインポート" #~ msgid "Select projects to import" #~ msgstr "インポートするプロジェクトを選択" #~ msgid "The folder %s does not contain a valid %s project" #~ msgstr "フォルダー %s は有効な %s プロジェクトを含んでいません" #~ msgid "Import existing Pydev project" #~ msgstr "既存のPydevプロジェクトをインポート" #~ msgid "" #~ "Unable to read Pydev project %s

Error message:
%s" #~ msgstr "" #~ "Pydevプロジェクト%sを読み取れません

エラーメッセージ:" #~ "
%s" #~ msgid "Select projects which are related to %s" #~ msgstr "%sに関連するプロジェクトを選択" #~ msgid "" #~ "Statistics on source files only:
(Python, Cython, IPython, Enaml,C/C+" #~ "+, Fortran)

%s files.
%s lines of code." #~ msgstr "" #~ "ソースファイルのみの統計:
(Python, Cython, IPython, Enaml,C/C++, " #~ "Fortran)

%s ファイル。
%s 行のコード。" #~ msgid "Select an existing workspace directory, or create a new one" #~ msgstr "既存のワークスペースを選択するか新規に作成する" #~ msgid "" #~ "What is the workspace?

A Spyder workspace is " #~ "a directory on your filesystem that contains Spyder projects and ." #~ "spyderworkspace configuration file.

A Spyder project is " #~ "a directory with source code (and other related files) and a " #~ "configuration file (named .spyderproject) with project settings " #~ "(PYTHONPATH, linked projects, ...).
" #~ msgstr "" #~ "ワークスペースとは何か?

Spyderワークスペース " #~ "とはファイルシステム上のSpyderプロジェクトと.spyderworkspace設定" #~ "ファイルを含むディレクトリである。

Spyderプロジェクト は" #~ "ソースコード(とその他関連ファイル)や(PYTHONPATHや関連プロジェクト.等の)設" #~ "定ファイル(.spyderproject)を保存しているディレクトリである。
" #~ msgid "This is the current workspace directory" #~ msgstr "これは現在のワークスペースディレクトリです" #~ msgid "" #~ "The following directory is not a Spyder workspace:
%s

Do you " #~ "want to create a new workspace in this directory?" #~ msgstr "" #~ "以下のディレクトリはSpyderワークスペースではありません:
%s

この" #~ "ディレクトリに新規ワークスペースを作成しますか?" #~ msgid "Unable to retrieve data.

Error message:
%s" #~ msgstr "データを取得できません。

エラーメッセージ:
%s" #~ msgid "Save session and quit..." #~ msgstr "セッションを保存して終了" #~ msgid "Breakpoints" #~ msgstr "ブレークポイント" #~ msgid "Exit" #~ msgstr "Exit" #~ msgid "Exit Debug" #~ msgstr "デバッグを終了する" spyder-3.2.6/spyder/locale/es/0000775000175000017500000000000013225025006016771 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/locale/es/LC_MESSAGES/0000775000175000017500000000000013225025007020557 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/locale/es/LC_MESSAGES/spyder.mo0000664000175000017500000032275713224121062022437 0ustar carloscarlos000000000000007!CZY Zwc[\ \ ] ]#]>]G]N]R] q] {]]]]]]] ]] ]] ] ]^ ^^!^)^.^6^<^D^K^Q^Z^c^l^u^~^^W^b^<K_"_x_4$`Y`xaFbDVc9cAcBdDZdQd1d6#e;Ze7eceB2f7ufCf;f8-gtfg!ggh&j!j;jljr'Ɓ+aQQ߂"1)T(~'σ  + D N\ z3„ ҄ ׅ  ,:ZWȆ %DZ_*7@^} &̈ !,=L \}ى> 8 FT erz   .ˊ  < I S^eMkm'?F_!x Ō -> W e&q*ލ .@HMU= ( 6@Wn  ʐ א #&9` r}{Jƒ  ̔{ڔV ]~ ǖ ֖ %C0Y ї *<KP=&ژ1`3I9ޙd<} ؚ͚ *.3FOXk!4 <HY_f Ɯߜ &=Y;u ʝ ם>#*8cr w Ӟ!T7=u   ɠѠ ٠  4 = H S ] iw ǡgڡB"]  &  0B IUY ,/8h mz:ߤ & 0> O\ oB|ǥϥ ޥ "+JP$e&P+w  çΧMާ,2B%uRC237 k x+"ë!ʬ * ;H \i}խ  !.AP_n}  Үޮ116LUg{%ʯ+$94>s %ɰ5 %1D[ b mw *±   #D\n ²βֲ 5!Rt 'ճ# 7BV_t}75) 2 >L jw ,Dĵ  $$3 XcsE  1 ;HYm- ƷηԷ" E!Rg1ظ  $2P_ hs ù5ҹ'0NUl#º=|WԻ>42^gƼۼ6 ?M_8o½ ׽ \9xƾ"ؾLHdvDֿ =Og  4 O[`e lw} !%#7 M[4<N8M=_89&9N`ptSH P] ep u ,  !=Mbs+ C:#^ o{  =:.i  .fD1Nl(ChF+Lx;':c *iTl-Y[  Wp]n&>{P#/7Mg   &0LRW[X& &"[29 !%3Yq}7= DRds<G\*d#  }ap ns$;1ImxA   .>E`fk s~ )  # ,9B Ygz & 0:%Kqz&  ,3: A KV] o z   i _w=&</cU@)DjARODOZ>?@~DHoMSGYYLIJ(8.!&Pvw  ?)Ri J  Ub S - D f] ,  .  2 )<  f *q /  +  = AT H ,       "%H`9z"A95SB  ,$8]s    *MlqB,%@= ~33,& St:&&>eCy"8Rk% .ZN7&@ g s    t!% .E8~% ,.3[# *J9g* 3FK?'*LMM     5%[j%0x T P O!3m!*!*!!"%"+" 4"B"*I"t" ""("""+"#'##7#[$6j$$$$$2$%%%%.% &.,&[&v&?&:;'5v'$''(' ( (00(a((((((#()#) 3)#T),x)):))**0* A*L*T*f*w*!**=**+-+M+ c+n+ u+ +g++,,,,$, --$-*-!C- e-s-----&--...&F..m.%. .. .../ //)/F0A1"\11111 1 1 122 52 A2N2`2 i2v2~2222223446 6666678&89#9+9 49A9 R9\9n9999 9'9,95:R:e:n::: ::::::R;6b;";/;h;CU<5<X<@(=i=q= == ==-== >>>*>9>B>=`>+>> >> ?"?*?%3?Y?a?g?"v??%???&@*@$I@&n@X@ @@AA'AG7AA+AAAAAB'BDB^B$zB%B(BoB^C gCJCCCwDD D D DDD D D DDE E*EY YYY YY Y"YZ'Z@Z1QZZZZ Z1Z![!%['G[%o[ [[ [ [[[ \ \\4\"N\(q\ \\\\\*\4']\]w]]]"]]]^!^(8^Ba^?^^__*_'>_f_|__7_T_ ;`I`Q`b`)}```(`!`Zasa aaaaaab7bKWbbbbb1bccP4cfcc1 d ;dFd [d"hdddd-ddde,eHBe4e?e f[!f$}f4f@fCg\gNhhQhOhl i,wi6i$ijjj #j.j@jCUj3jjjjk3kzNkAk( l4l8OlYl"lm $m:Em.mmm!m0m.nJn2hnnnnno!o9o'Xo*o*ooooo o pp(p/p>p&Vp}p8pp6pq4q EqOrRkrrrtu=.uluCuFu v2vNvjv}vuv\ w jwtwwwwww5w-x5xLxax{xxx)xxxyy02y cyMoyyyKy.zDz Sz!_zz zzzzzzzUzRT{{ 5|?|Y|r||u|5}P}j}V~1v~A~~q.2azAY>,ځ2n:Ă4Ã`Ys8CȆ sӊG{NjIC&'qg ? Ȕ Ӕޔ - D%Ntz%+<xh ( +74@u4 ʗZ*Ep;t"Θ!/Niw(AGNay #Ú->I] ,+%!:\.K R\z (=fy  y+0[mi   &-3< @JRcw ̤ݤ()0 P^gms  ĥܥE^Y Ti2f\!s"iL?'j&9CmH9S >1ln ;2+@r>g|XO'b}8T6l1qB <$Ed`FCge:#>or5 jkx"avEU{h 3oog a,aMMdX] $B[n-I[I!3-y`m5Oh \H'$~0x^D JR;y6Uf[t#P.jR0./ ~DcW4Q(Pp  -=7*H6G|9G%e!\{a ;2!z/ .b5P"17q<)w,D*J)4}4."+MnZw\_AG$F|%vR<&14Txs>'J(F Y)!SY#ww h0u3m}_S#&i I 0t-C4DVfyA3mN, QN6c[@(9Nt:qu=p(]LZ2`-,%u+l$3/V eQV+=xfpL7 5nKpIT1lbvRU*rz:*&Z0hugCrEvA8BO+jSe%{b|)^kM*"7?  z Adt%/^oB5K(Q~W']=cUJkW c&K?GK O]`kizVy?Z NPs6<:X@.Y~7,sX#}{ 28FW/;qH d8@L__) Numpy Array/Matrix Helper
Enter an array in the table.
Use Tab to move between cells.

Hit 'Enter' for array or 'Ctrl+Enter' for matrix.

Hint:
Use two tabs at the end of a row to move to the next row. Numpy Array/Matrix Helper
Type an array in Matlab : [1 2;3 4]
or Spyder simplified syntax : 1 2;3 4

Hit 'Enter' for array or 'Ctrl+Enter' for matrix.

Hint:
Use two spaces or two tabs to generate a ';'. Searching for files... Installed Required Scanning: {0} Searching for files in folder: {0} entries lines ms%s are currently not supported%s arrays%s editor&Close&Configuration per file...&Debug&Edit&File&Find in files&Find text&Help&New file...&Open...&Print...&Projects&Quit&Replace text&Restart&Revert&Run&Run...&Save&Search&Tools&View2 spaces3 spaces4 spaces5 spaces6 spaces7 spaces8 spaces%s contains mixed end-of-line characters.
Spyder will fix this automatically.%s has been modified outside Spyder.
Do you want to reload it and lose all your changes?%s has been modified.
Do you want to save changes?%s is not a Spyder project!%s is unavailable (this file may have been removed, moved or renamed outside Spyder).
Do you want to close it?-u is added to the other options you set hereSpyder %s is available!

Please use your package manager to update Spyder or go to our Releases page to download this new version.

If you are not sure how to proceed to update Spyder please refer to our Installation instructions.Spyder has encountered a problem.
Sorry for the inconvenience.

You can automatically submit this error to our Github issues tracker.

Note: You need a Github account for that.Spyder is a powerful Interactive Development Environment (or IDE) for the Python programming language.

Here we are going to guide you through its most important features.

Please use the arrow keys or click on the buttons below to move along the tour.Spyder is an interactive development environment based on blaUnable to %s %s

Error message:
%sUnable to assign data to item.

Error message:
%sUnable to create file %s

Error message:
%sUnable to create folder %s

Error message:
%sUnable to delete {varpath}

The error message was:
{error}Unable to find external program.

%sUnable to load '%s'

Error message:
%sUnable to move %s

Error message:
%sUnable to plot data.

Error message:
%sUnable to proceed to next step

Please check your entries.

Error message:
%sUnable to rename file %s

Error message:
%sUnable to save array

Error message:
%sUnable to save current workspace

Error message:
%sUnable to save file '%s'

Error message:
%sUnable to show image.

Error message:
%sUnsupported file extension '%s'

Would you like to import it anyway (by selecting a known file format)?Unsupported file type '%s'Warning:
The Python module rope is not installed on this computer: calltips, code completion and go-to-definition features won't be available.You have missing dependencies!

%s

Please install them to avoid this message.

Note: Spyder could work without some of these dependencies, however to have a smooth experience when using Spyder we strongly recommend you to install all the listed missing dependencies.

Failing to install these dependencies might result in bugs. Please be sure that any found bugs are not the direct result of missing dependencies, prior to reporting a new issue.

Removing all variables...

Restarting kernel...


IMPORTANT NOTE: It seems that you are using Spyder with Anaconda/Miniconda. Please don't use pip to update it as that will probably break your installation.

Instead, please wait until new conda packages are available and use conda to perform the update.
(Refer to the {} page)

If enabled, Python source code will be analyzed using pycodestyle, lines that are not following PEP8 style guide will be highlighted.

Note: add analysis:ignore in a comment to ignore style analysis warnings.

If enabled, Python source code will be analyzed using pyflakes, lines containing errors or warnings will be highlighted.

Note: add analysis:ignore in a comment to ignore code analysis warnings.

Warning: changes are applied separatelyA compound sequence can have {break} a maximum of 4 subsequences.{break}About %sAbout %s...Activate supportAdd &block commentAdd block comment around current line or selectionAdd pathAdditional featuresAdditional optionsAddress:Advanced SettingsAdvanced settingsAll changes to %s will be lost.
Do you want to revert file from disk?All filesAll files (*)All files (*.*)All user-defined variables will be removed. Are you sure you want to proceed?Always show %s on a first file runAn error occurred while creating a socket needed by Spyder. Please, try to run as an Administrator from cmd.exe the following command and then restart your computer:

netsh winsock reset
An error ocurred while starting the kernelAnalysisAnimated toolbars and panesAppearanceAre you sure you want to delete this scheme?Are you sure you want to restart the kernel?ArgumentsArray dimensions not validArray editorArrays with more than 3 dimensions are not supportedAsk for confirmation before closingAsk for confirmation before removing all user-defined variablesAttached console window (debugging)AttributeAutocallAutocall makes IPython automatically call any callable object even if you didn't type explicit parentheses.
For example, if you type str 43 it becomes str(43) automatically.Autocall: AutomaticAutomatic code completionAutomatic connectionsAutomatic importAutomatic indentation after 'else', 'elif', etc.Automatic insertion of closing quotesAutomatic insertion of colons after 'for', 'if', 'def', etcAutomatic insertion of parentheses, braces and bracketsAutomatically load Pylab and NumPy modulesAutomatically remove trailing spaces when saving filesAxis:BackBackend:BackgroundBackground colorBackground:Batch filesBoldBreakpointBrowseBrowse a working directoryBrowse repositoryBrowse tabsBufferBuffer...Buffer: Builtin:C filesC&lose allC&onsolesC++ filesCPU and memory usage info in the status barCPU usage status: requires the `psutil` (>=v0.3) libraryCPU:CSV text filesCancelCannot restart a kernel not started by Spyder Carriage return (Mac)Carriage return and line feed (Windows)Case SensitiveCase sensitive code completionCell starts at line %sChange to lowercase current line or selectionChange to parent directoryChange to uppercase current line or selectionChanging backend to Qt for MayaviCheck for updates on startupCheck for updates...Class defined at line %sClear all ouputClear breakpoints in all filesClear consoleClear lineClear line or blockClear recent files listClear shellClear shell contents ('cls' command)Clear this listClipboard contentsClose ProjectClose all but thisClose all opened filesClose all to the rightClose current fileClose current paneClose current tabClose this panelClose this windowClose windowClosing SpyderCodeCode Introspection/AnalysisCode analysisCode analysis requires pyflakes %s+Code annotations (TODO, FIXME, XXX, HINT, TIP, @todo, HACK, BUG, OPTIMIZE, !!!, ???)Collapse allCollapse selectionColor scheme editorColumn min/maxColumn separator:Column:Command line options:CommentComment current line or selectionComment:Comments:CommitCompletion TypeCompletion:Condition:Configuration filesConfiguration for high DPI screens

Please see {0}<> for more information about these options (in English).ConflictsConnect to an existing kernelConnecting to kernel...Connection errorConnection info:ConsoleConsole directoryConsole helpContextContinueContinue execution until next breakpointConversion errorConvert end-of-line charactersConvert to Python scriptCopyCopy path to clipboardCopy to clipboardCopy without promptsCould not connect to remote hostCould not open ssh tunnel. The error was: CreateCreate a new editor windowCreate new projectCreate new schemeCurrent cell:Current line:Current shortcut:Current user environment variables...Current working directoryCurrently used to delete lines on editorCursor blinking:Custom margin for panes:CutCython/Pyrex filesDataDataFrameDebug fileDebug toolbarDebug with winpdbDecide how graphics are going to be displayed in the console. If unsure, please select %s to put graphics inside the console or %s to interact with them (through zooming and panning) in a separate window.Decide how to render the figures created by this backendDecide what type of completion to useDefault (i.e. the same as Spyder's)Default is 4Default is 6Default is
In [<span class="in-prompt-number">%i</span>]:Default is
Out[<span class="out-prompt-number">%i</span>]:Default working directory is:Definition:DeleteDelete LayoutDelete ProjectDelete...DependenciesDependencies...DictionaryDirectly enter debugging when errors appearDisplayDisplay balloon tipsDisplay initial bannerDo you really want to delete %s?Do you really want to delete {filename}?

Note: This action will only delete the project. Its files are going to be preserved on disk.Do you really want to remove selected path?Do you really want to rename %s and overwrite the existing file %s?Do you want to close all other consoles connected to the same kernel as this one?Do you want to close this console?Do you want to remove all selected items?Do you want to remove the selected item?Do you want to reset to default values?Do you wish to restart now?Don't show again.DoneDuplicateEOLEditEdit filename filtersEdit filename filters...Edit itemEdit selectedEdit template for new modulesEdit toolbarEditorEditor's code completion, go-to-definition and helpEmpty clipboardEmpty projectEnable Tab completion on elements of lists, results of function calls, etc, without assigning them to a variable.
For example, you can get completions on things like li[0].<Tab> or ins.meth().<Tab>Enable UMREnable auto high DPI scalingEnaml filesEncoding:End-of-line charactersEnd-of-lines:Enter key selects completionEnter values for different screens separated by semicolons ';', float values are supportedEnvironment variablesEnvironment variables...ErrorError restarting kernel: %s Exclude all-uppercase referencesExclude capitalized referencesExclude private referencesExclude references to unsupported data types (i.e. which won't be handled/saved correctly)Exclude references which name is uppercaseExclude references which name starts with an underscoreExclude references which name starts with an uppercase characterExclude unsupported data typesExclude:Excluded filenames patternExecutablesExecute in a dedicated consoleExecute in an external system terminalExecute in current consoleExisting directoryExpand allExpand selectionExternal ToolsExternal editorExternal editor executable path:External editor path...External editor:External system terminalFast switch between filesFast symbol search in fileFileFile %s already exists.
Do you want to overwrite it?File ExplorerFile explorerFile switcher...File toolbarFile...FilterFind &nextFind &previousFind in filesFind symbols in file...Find textFix automatically and show warning message boxFix indentationFloat formattingFolder %s already exists.Folder name:Folder...Font styleFont: FontsFor %s support, please install one of the
following tools:

%sFor performance reasons, changes applied to masked array won't be reflected in array's data (and vice-versa).Forbidden key sequence!FormatFormat (%s) is incorrectFormat ({}) is incorrectFormat ({}) should start with '%'Format:Fortran filesFullFullscreen modeFunction defined at line %sGIF imagesGUI-based editor:GeneralGeneral settingsGo to cursor positionGo to definitionGo to last edit locationGo to line...Go to line:Go to next code analysis warning/errorGo to next cursor positionGo to previous code analysis warning/errorGo to previous cursor positionGo to step: GraphicalGraphicsGraphics backendGreedy completionHeight:HelpHelp...Here you can get help of any object by pressing %s in front of it, either on the Editor or the Console.%sHelp can also be shown automatically after writing a left parenthesis next to an object. You can activate this behavior in %s.Here you can select the color scheme used in the Editor and all other Spyder plugins.

You can also edit the color schemes provided by Spyder or create your own ones by using the options provided below.
Hide advanced optionsHide toolbarsHighlightHighlight current cellHighlight current lineHighlight matchesHighlight occurrences afterHistogramHistoryHistory depth: History logHistory logsHistory...HomeHost nameIDL filesIPythonIPython ConsoleIPython consoleIPython documentationIPython interactive python environmentIPython notebooksIcon themeIf enabled, pressing Tab will always indent, even when the cursor is not at the beginning of a line (when this option is enabled, code completion may be triggered using the alternate shortcut: Ctrl+Space)If this option is enabled, clicking on an object name (left-click + Ctrl key) will go this object definition (if resolved).If you accept changes, this will modify the current user environment variables directly in Windows registry. Use it with precautions, at your own risks.

Note that for changes to take effect, you will need to restart the parent process of this application (simply restart Spyder if you have executed it from a Windows shortcut, otherwise restart any application from which you may have executed it, like Python(x,y) Home for example)ImportImport asImport dataImport errorImport from clipboardImport wizardIn this pane you can view and edit the variables generated during the execution of a program, or those entered directly in one of Spyder consoles.

As you can see, the Variable Explorer is showing the variables generated during the last step of this tour. By doing a double-click on any of them, a new window will be opened, where you can inspect and modify their contents.IndentIndent current line or selectionIndentation characters: IndexIndex:InformationInitializing...InlineInline backendInput prompt:InsertInspect current objectInstalled Python modulesInstance:Integrate the IPython consoleIntelligent backspaceInteract with the Python console after executionInteractive toursInterfaceInternal consoleInternal console settingsInternal editor:Intro to IPythonIntroduction tourIntrospectionInvalid directory pathInvalid file pathInvalid key enteredIt was not possible to close the previous Spyder instance. Restart aborted.It was not possible to convert this notebook. The error is: It was not possible to copy this arrayIt was not possible to copy values for this arrayIt was not possible to generate rich text help for this object.
Please see it in plain text.It was not possible to remove outputs from this notebook. The error is: It was not possible to restart Spyder. Operation aborted.It was not possible to restart the IPython console when switching to this project. The error was {0}It was not possible to run this file in an external terminalItalicJPEG imagesJSON filesJavascript filesJson filesJulia filesKernel died, restartingKernel restartingKeyKey:Keyboard shortcutsKeyword:LanguageLast edit locationLayout %s will be overwritten. Do you want to continue?Layout Display and OrderLayout preferencesLine %sLine count:Line feed (UNIX)Line:Lines:Link to object definitionLink:ListLoading %s...Loading IPython console...Loading editor...Loading file explorer...Loading help...Loading history plugin...Loading namespace browser...Loading online help...Loading outline explorer...Loading project explorer...Loading this kind of data while debugging is not supported.LocationLockLock panesMATLAB filesMain toolbarMaintain focus in the Editor after running cells or selectionsManage color schemesManipulate Jupyter notebooks on the EditorMarkdown filesMaskMasked dataMatched
parens:Matlab filesMatplotlib documentationMaximize current paneMaximum entriesMaximum line countMaximum number of recent filesMaximum number of recent files...Memory usage status: requires the `psutil` (>=v0.3) library on non-Windows platformsMemory:Method defined at line %sModify how Input and Output prompts are shown in the console.ModuleModule pywin32 was not found.
Please restart this Windows session (not the computer) for changes to take effect.Module or package:Module...Move DownMove UpMove downMove to bottomMove to topMove upMove...NSIS filesNameName filters:NewNew Project...New directoryNew features in version 3.0New fileNew folderNew moduleNew name:New packageNew shortcut:New to Spyder? Read ourNew variable name:New windowNextNext cursor positionNext warning/errorNo IPython console is currently available to run %s.

Please open a new one and try again.No documentation availableNo further documentation availableNo matchesNo source code available.NormalNormal text:Nothing to be imported from clipboard.NumPy arrayNumPy arraysNumPy zip arraysNumber:Numpy and Scipy documentationO&pen last closedObjectOccurrence:OffOn %s mode, Autocall is not applied if there are no arguments after the callable. On %s mode, all callable objects are automatically called (even if no arguments are present).Online documentationOnline helpOnly used when the format is PNG. Default is 72OpenOpen &recentOpen IPython console hereOpen Project...Open a new IPython console connected to an existing kernelOpen an &IPython consoleOpen command prompt hereOpen connection fileOpen fileOpen file as:Open last closedOpen projectOpen terminal hereOpenCL filesOpening this variable can be slow Do you want to continue anyway?OptionsOutlineOutput prompt:PNG imagesPYTHONPATH managerPackage name:Package...PanesParentPasswordPassword or ssh key passphrasePastePatch and diff filesPath to connection file or kernel idPath to ssh key filePerfom symbolic operations in the console (e.g. integrals, derivatives, vector calculus, etc) and get the outputs in a beautifully printed style (it requires the Sympy module).Perform analysis only when saving filePerform analysis when saving file and everyPermissions:Pickle filesPlainPlain TextPlain text fontPlease consider installing Sphinx to get documentation rendered in rich text.Please enter the connection info of the kernel you want to connect to. For that you can either select its JSON connection file using the Browse button, or write directly its id, in case it's a local kernel (for example kernel-3764.json or just 3764).Please install matplotlib or guiqwt.Please introduce a different shortcutPlease note that these changes will be applied only to new Python/IPython consolesPlease note that these changes will be applied only to new consolesPlotPop up internal console when internal errors appearPre&ferencesPreferencesPreferences > HelpPress Enter to switch files or Esc to cancel.

Type to filter filenames.

Use :number to go to a line, e.g. main:42
Use @symbol_text to go to a symbol, e.g. @init

Press Ctrl+W to close current tab.
Press enter to validate this entryPress enter to validate this pathPress the new shortcut and select 'Ok': (Press 'Tab' once to switch focus between the shortcut entry and the buttons below it)PreviewPreviousPrevious cursor positionPrevious warning/errorPrint current file...Print preview...Printing...ProjectProject ExplorerProject PreferencesProject explorerProject nameProject preferencesProject typePrompt when exitingPromptsProvided featuresPyQt4 API ReferencePyQt4 Reference GuidePyQt5 API ReferencePyQt5 Reference GuidePython Path ManagerPython documentationPython filesPython help:Python interpreterPython packagePython projectPython scriptsPython versionPython2 documentationPython3 documentationQt DesignerQt LinguistQt documentationQt examplesQt windows styleQuick referenceQuick switch layout #%s has not yet been defined.QuitR&emove block commentRaw textRe run last cell Re-run &last scriptRe-run last cellReal-time code analysisReal-time code analysis on the EditorReal-time code style analysisReal-time code style analysis on the EditorRecent ProjectsRecord array fields:RedoRefresh list of module names available in PYTHONPATHRegular expressionRegular expression errorRemoval errorRemoveRemove all variablesRemove all variables before executionRemove comment block around current line or selectionRemove pathRemove references:Remove trailing spacesRenameRename tabRename...Render mathematical equationsReplace allReplace selectionReplace stringReplace tab characters by space charactersReplace with:Replace/find nextReport issue...ResetReset Spyder to factory defaultsReset to default valuesReset to defaultsReset to spyder defaultResetting Spyder to defaultsResizeResize rows to contentsResolution:RestartRestart kernelRestart kernel?RestartingRestoreRestore current paneRestore data on startupRestore original tree layoutRestore pane to its original sizeRevert file from diskRich TextRich text fontRow separator:RunRun &selection or current lineRun Cython files in the IPython ConsoleRun Python scriptRun Settings dialogRun a Python scriptRun a fileRun again last fileRun cellRun cell and advanceRun codeRun configurationRun configuration per fileRun current cell (Ctrl+Enter) [Use #%% to create cells]Run current cell and go to the next one (Shift+Enter)Run current lineRun fileRun script:Run selectionRun selection or current lineRun settingsRun settings for %sRun toolbarRun until current function or method returnsRunning an external system terminal is not supported on platform %s.Sav&e allSaveSave &as...Save all filesSave all files before running scriptSave arraySave copy as...Save copy of current file as...Save current file as...Save current history log (i.e. all inputs and outputs) in a text fileSave current layoutSave dataSave data as...Save data on exitSave fileSave historySave history logSave history log...Save non project files openedSaving data while debugging is not supported.Scheme name:Scheme:ScoreScreen resolutionScroll automatically to last entrySearchSearch directorySearch in all files and directories present on thecurrent Spyder pathSearch in all files and directories present on thecurrent project path (If opened)Search in current opened fileSearch in other folder present on the file systemSearch in:Search patternSearch stringSearch text in multiple filesSearch toolbarSearch: Select AllSelect a run configuration:Select directorySelect fileSelect other directorySelect ssh keySelect the Python interpreter for all Spyder consolesSet UMR excluded (not reloaded) modulesSet a custom high DPI scalingSet console working directorySet current console (and file explorer) working directory to current script directorySet external editor executable pathSet history maximum entriesSet maximum line countSet the list of excluded modules as this: numpy, scipySet the maximum number of lines of text shown in the console before truncation. Specifying -1 disables it (not recommended!)Set this for high DPI displaysSet this for high DPI displays when auto scaling does not workSet this to detach any
menu from the main windowSet this to open external
Python files in an already running instance (Requires a restart)Set/Clear breakpointSet/Edit conditional breakpointSetting up main window...SettingsShell special commands:ShortcutShortcut: {0}Shortcuts SummaryShortcuts resetShortcuts that use Shift and another key are unsupportedShow (read-only) sys.pathShow CPU usage everyShow SourceShow absolute pathShow advanced optionsShow all filesShow and edit current user environment variables in Windows registry (i.e. for all sessions)Show and edit environment variables (for current session)Show arrays min/maxShow blank spacesShow code analysis warnings/errorsShow comments list (TODO/FIXME/XXX/HINT/TIP/@todo/HACK/BUG/OPTIMIZE/!!!/???)Show current directory onlyShow elapsed timeShow environment variablesShow help for objects in the Editor and Consoles in a dedicated paneShow horizontal scrollbarShow icons and textShow imageShow in FinderShow in external file explorerShow line numbersShow memory usage everyShow reloaded modules listShow special commentsShow status barShow sys.path contentsShow sys.path contents...Show tab barShow todo listShow toolbarsShow vertical line afterShow warning/error listShow/hide outline explorerSide areas:SiftSizeSize: Skip rows:SmartSour&ceSourceSource codeSource toolbarSphinx %s is currently installed.Split horizontallySplit horizontally this editor windowSplit verticallySplit vertically this editor windowSpyder Default LayoutSpyder EditorSpyder Internal Console This console is used to report application internal errors and to inspect Spyder internals with the following commands: spy.app, spy.window, dir(spy) Please don't use it to run your code Spyder Keyboard ShortCutsSpyder could not reset to factory defaults. Restart aborted.Spyder data filesSpyder depends on several Python modules to provide the right functionality for all its panes. The table below shows the required and installed versions (if any) of all of them.

Note: You can safely use Spyder without the following modules installed: %s and %s.

Please also note that new dependencies or changed ones will be correctly detected only after Spyder is restarted.Spyder documentationSpyder exit errorSpyder is an interactive development environment based on blaSpyder is up to date.Spyder needs to restart to change the following setting:Spyder needs to restart to change the following settings:Spyder reset errorSpyder restart errorSpyder support...Spyder tutorialSpyder updatesSpyder was unable to retrieve the value of this variable from the console.

The error mesage was:
%sSpyder will restart and reset to default settings:

Do you want to continue?Ssh keyStart searchStartupStatus barStepStep IntoStep ReturnStep into function or method of current lineStopStop debuggingStop searchStop the current commandString not foundString:Submit to GithubSupport for graphics (Matplotlib)Supported filesSupported text filesSymbol finder...Symbolic MathematicsSymbolic mathematics in the IPython ConsoleSynchronizeSynchronize Spyder's path list with PYTHONPATH environment variableSynchronize...Syntax coloringSyntax highlighting for Matlab, Julia and other file typesSystem commands:TIFF imagesTabTab always indentTab stop width:TabulationsTear off menusTemporary fileTerminalTextText editorText filesThe 'xlabels' argument length do no match array column numberThe 'ylabels' argument length do no match array row numberThe current working directory is the working directory for IPython consoles and the current directory for the File Explorer.The EditorThe File ExplorerThe History LogThe IPython consoleThe Variable ExplorerThe authenticity of host %s can't be established. Are you sure you want to continue connecting?The authenticity of the host can't be establishedThe current directory contains a project.

If you want to delete the project, please go to Projects » Delete ProjectThe current project directory or user home directory (if no project is active)The current working directoryThe directory of the file being executedThe directory when a new console is open will be the specified pathThe directory {} is not writable and it is required to create IPython consoles. Please make it writable.The following are the default options for running files.These options may be overriden using the Configuration per file entry of the Run menu.The following conflicts have been detected:The following directory:The following error occured when calling Sphinx %s.
Incompatible Sphinx version or doc string decoding failed.

Error message:
%sThe following modules are not installed on your machine: %sThe following working directory is not valid:
%sThe new shortcut conflicts with:The working directory for new consoles is:This directory is already included in Spyder path list.
Do you want to move it to the top of the list?This entry is incorrectThis error was most probably caused by installing Spyder in a directory with non-ascii characters (i.e. characters with tildes, apostrophes or non-latin symbols).

To fix it, please reinstall Spyder in a different location.This feature requires Sphinx 1.1 or superior.This feature requires the Rope or Jedi libraries. It seems you don't have either installed.This is a remote kernelThis is a temporary script file.This is one of panes where you can run or execute the code you wrote on the Editor. To do it you need to press the F5 key.

This console comes with several useful features that greatly improve your programming workflow (like syntax highlighting and inline plots). If you want to know more about them, please follow this link.

Please click on the button below to run some simple code in this console. This will be useful to show you other important features.This is the pane where you write Python code before evaluating it. You can get automatic suggestions and completions while writing, by pressing the Tab key next to a given text.

The Editor comes with a line number area (highlighted here in red), where Spyder shows warnings and syntax errors. They can help you to detect potential problems before running the code.

You can also set debug breakpoints in the line number area, by doing a double click next to a non-empty line.This is the working directory for newly opened consoles (Python/IPython consoles and terminals), for the file explorer, for the find in files plugin and for new files created in the editorThis lets you load graphics support without importing the commands to do plots. Useful to work with other plotting libraries different to Matplotlib or to develop GUIs with Spyder.This option lets you hide the message shown at the top of the console when it's opened.This option lets you hide the warning message shown when resetting the namespace from Spyder.This option loads the Sympy library to work with.
Please refer to its documentation to learn how to use it.This option will be applied the next time a console is opened.This option will enable the User Module Reloader (UMR) in Python/IPython consoles. UMR forces Python to reload deeply modules during import when running a Python script using the Spyder's builtin function runfile.

1. UMR may require to restart the console in which it will be called (otherwise only newly imported modules will be reloaded when executing files).

2. If errors occur when re-running a PyQt-based program, please check that the Qt objects are properly destroyed (e.g. you may have to use the attribute Qt.WA_DeleteOnClose on your main window, using the setAttribute method)This pane can automatically show an object's help information after a left parenthesis is written next to it. Below you can decide to which plugin you want to connect it to turn on this feature.This pane displays documentation of the functions, classes, methods or modules you are currently using in the Editor or the Consoles.

To use it, you need to press Ctrl+I in front of an object. If that object has some documentation associated with it, it will be displayed here.This pane lets you navigate through the directories and files present in your computer.

You can also open any of these files with its corresponding application, by doing a double click on it.

There is one exception to this rule: plain-text files will always be opened in the Spyder Editor.This pane records all commands introduced in the Python and IPython consoles.This will synchronize Spyder's path list with PYTHONPATH environment variable for current user, allowing you to run your Python modules outside Spyder without having to configure sys.path.
Do you want to clear contents of PYTHONPATH before adding Spyder's path list?To boolTo complexTo doTo floatTo intTo strToggle LowercaseToggle UppercaseToolbarsTransposeTunnel '%s' failed to startTupleTypeUMRUMR forces Python to reload modules which were imported when executing a file in a Python or IPython console with the runfile function.Unable to check for updates.Unable to connect to %sUnable to connect to the internet.

Make sure the connection is working properly.Unable to load pageUnable to retrieve information.UncommentUndoUnexpected error: see internal consoleUnindentUnindent current line or selectionUnlockUnmatched
parens:Update LANGUAGE_CODES (inside config/base.py) if a new translation has been added to SpyderUpdate module names listUsageUse a pager to display additional text inside the consoleUse a single instanceUse next layoutUse previous layoutUse symbolic mathUse the following Python interpreter:Use the following file:Use the greedy completerUse version controlUseful if you don't want to fill the console with long help or completion texts. Note: Use the Q key to get out of the pager.User Module Reloader (UMR)ValueValue:Variable NameVariable explorerVariable name:Version controlVersion control systemVertical tabs in panesVertical title bars in panesViTablesView and edit DataFrames and Series in the Variable ExplorerView and edit two and three dimensional arrays in the Variable ExplorerWarningWe cannot support this shortcut on WindowsWeb page filesWelcome to Spyder introduction tourWelcome to Spyder!Welcome to the Introduction tourWhen opening a text file containing mixed end-of-line characters (this may raise syntax errors in the consoles on Windows platforms), Spyder may fix the file automatically.WhitespaceWhole wordsWidth:WinPythonWinPython control panelWindow layout will be reset to default settings: this affects window position, size and dockwidgets. Do you want to continue?Window layoutsWorking Directory settingsWorkspaceWrap linesXML filesYaml filesYou are working with Python 2, this means that you can not import a module that contains non-ascii characters.You can also run a whole file at startup instead of just some lines (This is similar to have a PYTHONSTARTUP file).You can run several lines of code when a console is started. Please introduce each one separated by commas, for example:
import os, import sysYou don't have the right permissions to open this directoryYou selected a Python %d interpreter for the console but Spyder is running on Python %d!.

Although this is possible, we recommend you to install and run Spyder directly with your selected interpreter, to avoid seeing false warnings and errors due to the incompatible syntax between these two Python versions.You selected an invalid Python interpreter for the console so the previous interpreter will stay. Please make sure to select a valid one.Your Python environment or installation doesn't have the ipykernel and cloudpickle modules installed on it. Without these modules is not possible for Spyder to create a console for you.

You can install them by running in a system terminal:

pip install ipykernel cloudpickle

or

conda install ipykernel cloudpickleZoom inZoom outZoom resetarraycharacterscodecopydatadeletedpielementsfilegettext filesguidata examplesguiqwt examplesinchesinvalid regular expressionlineslistmatchesmatches inmovemsno matchesofotherpermission denied errors were encounteredpixelsreStructuredText filesread onlyspacestabletextthe following directory:this dialogtutorialunsaved fileuntitledusername@hostname:portvariable_nameProject-Id-Version: 2.1 POT-Creation-Date: 2017-12-14 15:40+-05 PO-Revision-Date: 2017-12-16 14:20-0500 Last-Translator: Carlos Cordoba Language-Team: Python Language: es MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generated-By: pygettext.py 1.5 X-Poedit-SourceCharset: utf-8 X-Poedit-Basepath: ../../../.. X-Generator: Poedit 2.0.1 Ayuda para arreglos de Numpy
Introduzca un arreglo en la tabla.
Use Tab para moverse entre las celdas.

Oprima 'Enter' para un arreglo o 'Ctrl+Enter' para una matriz.

Consejo:
Use dos tabs al final de una fila para moverse a la siguiente. Ayuda para arreglos de Numpy
Escriba un arreglo en Matlab : [1 2;3 4]
o sintaxis simplificada de Spyder : 1 2;3 4

Oprima 'Enter' para un arreglo o 'Ctrl+Enter' para una matriz.

Consejo:
Use dos espacios o tabs para generar un ';'. Buscando archivos...InstaladoRequerido Escaneando: {0} Buscando archivos en la carpeta: {0}entradaslíneasms%s no están soportados por el momentoLos arreglos %sEditor de %s&Cerrar&Configuración por archivo...&Depurar&Editar&ArchivoBus&car en archivos&Buscar textoA&yuda&Nuevo&AbrirIm&primir&Proyectos&Salir&Reemplazar texto&Reiniciar&RestaurarE&jecutarE&jecutar...&Guardar&Buscar&Herramientas&Ver2 espacios3 espacios4 espacios5 espacios6 espacios7 espacios8 espacios%s contiene varios tipos de caracteres de fin de línea.
Spyder lo arreglará automáticamente.%s fue modificado por fuera de Spyder.
¿Desea recargarlo y perder todos sus cambios?%s ha sido modificado.
¿Desea guardar los cambios?%s no es un proyecto de Spyder!%s no está disponible (el archivo puede haber sido eliminado, movido o renombrado por fuera de Spyder).
¿Desea cerrarlo?La opción -u se añade a estas opcionesSpyder %s está disponible!

Por favor utilice su instalador de paquetes para actualizar Spyder o vaya a nuestra página de Lanzamientos para descargar esta nueva versión.

Si no está seguro de cómo proceder para actualizar Spyder, por favor lea nuestra instrucciones de Instalación (en inglés).Spyder ha encontrado un problema.
Disculpa las molestias.

Puedes enviar automáticamente este error a nuestro rastreador de problemas en Github.
Necesitas una cuenta de Github para esto.Spyder es un potente entorno de desarrollo integrado para el lenguaje de programación Python.

A continuación vamos a guiarlo a través de sus características más importantes.

Por favor utilice las teclas de flechas o haga click en los botones que aparecen abajo para moverse a lo largo del tour.Spyder es un ambiente interactivo de desarrollo basado en blaNo fue posible %s %s

Mensaje de error:
%sNo fue posible asignarle los datos al ítem.

Mensaje de error:
%sNo fue posible crear el archivo %s

Mensaje de error:
%sNo fue posible crear la carpeta %s

Mensaje de error:
%sNo fue posible eliminar {varpath}

El mensaje de error fue:
{error}No fue posible encontrar el programa externo.

%sNo fue posible cargar '%s'

Mensaje de error:
%sNo fue posible mover %s

Mensaje de error:
%sNo fue posible graficar los datos.

Mensaje de error:
%sNo fue posible pasar al siguiente paso

Por favor revise sus daros.

Mensaje de error:
%sNo fue posible renombrar el archivo %s

Mensaje de error:
%sNo fue posible guardar el arreglo

Mensaje de error:
%sNo fue posible guardar el espacio de trabajo actual

Mensaje de error:
%sNo fue posible guardar el archivo '%s'

Mensaje de error:
%sNo fue posible generar la gráfica.

Mensaje de error:
%sExtensión de archivo no soportada: '%s'

¿Desea importar el archivo de todas formas (seleccionando un formato conocido)?Tipo de archivo no soportado '%s'Advertencia:
El módulo de Pythonrope no está instalado en este computador. Por tanto el completado de código, el ir a la definición de una función o método y los globos de sugerencias se encontrarán desactivados.Algunas dependencias no están instaladas!

%s

Por favor instálelas para evitar este mensaje.

Nota: Spyder puede funcionar sin algunas de estas dependencias. Sin embargo, para no tener problemas al usar Spyder nosotros firmemente le recomendamos instalar todas las dependencias faltantes.

El no instalar estas dependencias puede resultar en errores. Por favor asegúrese de que cualquier error que encuentre no sea el resultado directo de las dependencias faltantes, antes de reportar un nuevo problema.

Eliminando todas las variables...

Reiniciando el núcleo...


NOTA IMPORTANTE: Al parecer Spyder está siendo usando junto con Anaconda o Miniconda. Por favor no use pip para actualizarlo, ya que ello probablemente dañará su instalación.

En su lugar, por favor espere hasta que nuevos paquetes de conda estén disponibles y utilice conda para realizar la actualización.
(Mirar la página {})

Si activado, el código fuente de Python será analizado usando pycodestyle, las líneas que no sigan la guía de estilo PEP8 se resaltarán.

Nota: add analysis:ignore en un comentario para ignorar las advertencias de análisis de estilo.

Si esta opción está activada, los archivos de Python serán analizados automáticamente y y las líneas que contengan errores o advertencias serán resaltadas.

Nota: Puede añadir analysis:ignore en un comentario para ignorar estas advertencias.

Advertencia: los cambios son aplicados de forma separadaUna secuencia compuesta puede tener {break} un máximo de 4 sub-secuencias.{break}Acerca de %sAcerca de %s...Activar el soporteAñadir comentario de &bloqueAñadir un comentario de bloque alrededor de la línea o selección actualAñadir rutaCaracterísticas adicionalesOpciones adicionalesDirección:Opciones avanzadasOpciones avanzadasTodos los cambios a %s se perderán.
Desea revertir el archivo del disco?Todos los archivosTodos los archivos (*)Todos los archivos (*.*)Todas las variables definidas por el usuario serán eliminadas. ¿Está seguro de que desea continuar?Siempre muestre %s en una primera ejecuciónSe ha producido un error al crear un socket necesario para ejecutar Spyder. Intente abrir una terminal de sistema (cmd.exe) como administrador, ejecute el siguiente comando y reinicie su equipo:

netsh winsock reset
Ocurrió un error mientras iniciaba el núcleoAnálisisBarras de herramientas y paneles animadosApariencia¿Está seguro de que borrar este esquema?Está seguro de que desea reiniciar el núcleo?ArgumentosLas dimensiones del arreglo no son válidasEditor de arreglosLos arreglos de más de tres dimensiones no están soportadosMostrar un diálogo de confirmación antes de cerrar una terminalPreguntar antes de eliminar todas las variables definidas por el usuarioVentana de terminal anexa (para depuración)AtributoAutollamarEsta opción hace que IPython llame automáticamente cualquier objeto "llamable" (callable) aún si no se escriben paréntesis a su alrededor.
Por ejemplo, al escribir str 43, se convertirá automáticamente en str(43).Autollamar:AutomáticoCompletar código automáticamenteConexiones automáticasImportar automáticamenteIndentación automática después de 'else', 'elif', etc.Inserción automática de comillasInserción automática de ':' después de 'for', 'if', 'def', etcInserción automática de paréntesis, llaves y corchetesCargar automáticamente los módulos de Pylab y NumPyEliminar automáticamente espacios en blanco al guardar un archivoEje:AnteriorSalida:FondoColor de fondoFondo:Archivos BatchNegritaPunto de interrupciónSeleccionarSeleccionar un directorio de trabajoExplorar repositorio Navegar por las pestañasMostrarMostrar líneas...MostrarObjeto integrado:Archivos CC&errar todo&TerminalesArchivos C++Uso de memoria y CPU en la barra de estadoPara reportar el estado del CPU se requiere de la librería `psutil` (>=v0.3)CPU:Archivos de texto CSVCancelarNo es posible reiniciar un núcleo que no fue iniciado por Spyder Retorno de carro (Mac)Retorno de carro y salto de línea (Windows)Distinguir mayúsculas de minúsculasDiferenciar entre mayúsculas y minúsculas al completar códigoLa celda empieza en la línea %sCambiar a minúsculas la línea o selección actualMoverse al directorio superiorCambiar a mayúsculas la línea o selección actualCambiando la salida gráfica a Qt por MayaviBuscar actualizaciones al inicioBuscar actualizaciones...Clase definida en la línea %sEliminar todas las salidasEliminar los puntos de interrupción de todos los archivosLimpiar la terminalLimpiar líneaLimpiar línea o bloqueLimpiar la lista de archivos recientesLimpiar la terminalLimpia los contenidos de la terminal (equivalente al comando 'cls')Limpiar esta listaContenidos del portapapelesCerrar proyectoCerrar todos menos ésteCerrar todos los archivos abiertosCerrar todos a la derechaCerrar el archivo actualCerrar panel actualCerrar pestaña actualCerrar este panelCierra esta ventanaCerrar ventanaCerrando SpyderCódigoAnálisis e introspección de códigoAnálisis del códigoEl análisis del código requiere pyflakes %s+Anotaciones de código (TODO, FIXME, XXX, HINT, TIP, @todo, HACK, BUG, OPTIMIZE, !!!, ???)Colapsar resultadosColapsar selecciónEditor de esquemasMin/max de columnaSeparador de columnas:Columna:Opciones de línea de comandos:ComentarComentar la línea o selección actualComentario:Comentarios:ConsignarTipo de completadoCompletado:Condición:Archivos de ConfiguraciónConfiguración para pantallas de alta densidad de pixeles

Visite {0}<> para obtener más información sobre estas opciones (en inglés).Conflicto conConectarse a un núcleo existenteConectándose al núcleo...Error de conexiónInformación de conexión:TerminalDirectorio de la consolaAyuda de la terminalContextoContinuarContinuar con la ejecución hasta el siguiente punto de interrupciónError de conversiónConvertir caracteres de fin de líneaConvertir a un archivo de PythonCopiarCopiar la ruta al portapapelesCopiar al portapapelesCopiar sin los promptsNo fue posible conectarse al servidor remotoNo fue posible crear un túnel ssh. El error fue: CrearCrear una nueva ventana de ediciónCrear nuevo proyectoCrear nuevo esquemaCelda seleccionada:Línea seleccionada:Atajo seleccionado:Variables de entorno del usuario actual...Directorio de trabajo actualSe utiliza actualmente para eliminar líneas en el editorParpadeo del cursor:Márgenes personalizadas para los paneles:CortarArchivos Cython/PyrexDatosDataFrameDepurar archivoBarra de depuraciónDepurar con winpdbDecidir como se mostrarán las gráficas en la terminal. Si no está seguro, por favor seleccione %s para colocar las gráficas en la consola o %s para interactuar con ellas (a través de acercamientos y paneos) en una ventana aparte.Decida como renderizar las figuras creadas por este tipo de salida gráficaDecidir que tipo de completado utilizarPor defecto (es decir, el mismo de Spyder)Por defecto es 4Por defecto es 6Por defecto es
In [<span class="in-prompt-number">%i</span>]:Por defecto es
Out[<span class="out-prompt-number">%i</span>]:Directorio de trabajo:Definición:EliminarEliminar disposiciónEliminar proyectoEliminar...DependenciasDependencias...DiccionarioEntrar en modo de depuración cuando aparecen erroresVisualizaciónMostrar globos de sugerenciasMostrar el banner inicial¿Realmente desea eliminar %s?¿Realmente desea eliminar el proyecto {filename}?

Nota: Esta acción sólo eliminará el proyecto. Los archivos del mismo no serán eliminados del disco.¿Realmente desea eliminar la ruta seleccionada?¿Realmente desea renombrar %s y sobrescribir el archivo existente %s?¿Desea cerrar todas las otras terminales conectadas al mismo núcleo que ésta?¿Desea cerrar esta terminal?¿Desea eliminar todas las variables seleccionadas?¿Desea eliminar la variable seleccionada?¿Desea restaurar los valores por defecto?¿Desea reiniciar ahora?No mostrar de nuevo.HechoDuplicarFin de líneaEditarEditar los filtros para nombres de archivoEditar filtros...Editar ítemEditar esquemaEditar la plantilla para nuevos módulosBarra de ediciónEditorCompletado del código y ayuda en el EditorVaciar el portapapelesProyecto vacíoHabilita el completado usando la tecla Tab en elementos de listas, resultados de llamadas de funciones, etc, sin asignarlos a una variable.
De esta forma se pueden obtener sugerencias de completado en cosas como li[0].<Tab> o ins.meth().<Tab>Activar el RMUActivar el escalado para pantallas de alta resoluciónArchivos EnamlCodificación:Caracteres de fin de líneaFin de línea:La tecla Enter selecciona el resultado a completarIntroduzca los valores para las diferentes pantallas separadas por punto y coma ';', es posible utilizar tanto números reales como enterosVariables de entornoVariables de entorno...ErrorOcurrió un error al reiniciar el núcleo: %s Excluir variables en mayúsculasExcluir variables que comienzan en mayúsculasExcluir variables privadasExcluir variables que referencian tipos de datos no soportados (es decir aquellos que no pueden manejarse y guardarse correctamente)Excluir variables cuyo nombre está por completo en mayúsculasExcluir variables cuyo nombre comienza con un guión abajoExcluir variables cuyo nombre comienza en mayúsculasExcluir tipos de datos no soportadosExcluir:Patrones de nombres de archivo a excluirEjecutablesEjecutar en una consola dedicadaEjecutar en una terminal de comandos del sistemaEjecutar en la consola actualUn directorio existenteExpandir resultadosExpandir selecciónHerramientas externasEditor externoRuta ejecutable del editor externo:Ruta del editor externo...Editor externo:Terminal de comandos del sistemaCambiar rápidamente entre archivosBúsqueda rápida de símbolos en el archivo&ArchivoEl archivo %s ya existe.
¿Desea sobrescribirlo?Explorador de archivosExplorador de archivosCambiador de archivos...Barra de archivoArchivo...FiltrarBuscar &siguienteBuscar &anteriorBuscar en archivosBuscar símbolos en el archivo...Encontrar textoArreglar automáticamente y mostrar un mensaje de advertenciaCorregir la indentaciónFormato de punto flotanteLa carpeta %s ya existe.Nombre de la carpeta:Carpeta...FuenteTipo de letraTipo de letraPara contar con soporte de %s, por favor instale una de
las siguientes herramientas:

%sPor razones de rendimiento, los cambios aplicados a arreglos enmascarados no se verán reflejados en los datos del arreglo (y viceversa).Secuencia de teclas prohibidaFormatoEl formato (%s) es incorrectoEl formato ({}) es incorrectoEl formato ({}) debe iniciar con '%'Formato:Archivos FortranTotalModo a pantalla completaFunción definida en la línea %sImágenes GIFEditor gráfico:GeneralAjustes generalesIr a la posición del cursorIr a la definiciónIr a la anterior posición de ediciónIr a la línea...Ir a la líneaIr a la próxima línea de advertencia o errorIr a la siguiente posición del cursorIr a la línea anterior de advertencia o errorIr a la anterior posición del cursorIr al paso:GráficoGráficasSalida gráfica:Completado ambiciosoAlto:AyudaAyuda...En este panel es posible obtener la ayuda de cualquier objeto al oprimir %s estando al frente del mismo, bien sea en el Editor o en la Terminal.%sEsta ayuda también se puede mostrar automáticamente después de escribir un paréntesis junto a un objeto. Este comportamiento puede activarse en %s.Aquí puede seleccionar el esquema de colores usado en el Editor y todos los demás paneles de Spyder.

También puede editar los esquemas de colores que vienen con Spyder o crear los suyos al usar las opciones que aparecen a continuación.
Ocultar opciones avanzadasOcultar las barras de herramientasResaltarResaltar la celda actualResaltar la línea actualResaltar coincidenciasResaltar ocurrencias después deHistogramaHistorialLongitud del historialHistorial de comandosHistorialesHistorial...Página de inicioServidorArchivos IDLIPythonTerminal de IPythonTerminal de IPythonDocumentación de IPythonEntorno interactivo IPythonNotebooks de IPythonTema de iconosSi esta opción está activada, el oprimir Tab siempre indentará el código, aún cuando el cursor no esté al principio de una línea (de seleccionar esta opción, se puede usar la combinación de teclas Ctrl+Espacio para activar el completado de código)Si está opción está activada, al hacer click sobre el nombre de un objeto (click-izquierdo + la tecla Ctrl), el Editor se ubicará en la definición del mismo (de poder resolverse el nombre).Si acepta los cambios, se modificarán las variables de entorno del usuario actual directamente en el registro de Windows. Hágalo con precaución y bajo su propio riesgo.

Tenga en cuenta que para que los cambios tengan efecto, deberá reiniciar el proceso padre de esta aplicación (simplemente reinicie Spyder si lo ejecutó desde un acceso directo, de otra forma reinicie la aplicación desde la cual lo inició, como por ejemplo Python(x,y) Home)ImportarImportar comoImportar datosError de importaciónImportar desde el portapapelesAsistente de importaciónEn este panel se pueden ver y editar las variables generadas durante la ejecución de un programa, o de los comandos introducidos directamente en alguna de las terminales de Spyder.

Como se puede observar, el Explorador de Variables está mostrando las variables generadas durante el último paso de este tour. Al hacer doble click en alguna de ellas, se mostrará una nueva ventana, en la cual se pueden inspeccionar y modificar sus contenidos.IndentarIndentar la línea o selección actualCaracteres de indentación:ÍndiceÍndice:InformaciónInicializando...En líneaSalida en línea:Prompt de entrada:InsertarInspeccionar objetoMódulos instalados de PythonInstancia:Integración con la Terminal de IPythonTecla de retroceso ("backspace") inteligenteInteractuar con la terminal después de la ejecuciónTours interactivosInterfazTerminal internaOpcionesEditor interno:Ayuda básicaTour IntroductorioIntrospecciónRuta de directorio inválidaRuta de archivo inválidaTecla inválidaNo fue posible cerrar la instancia anterior de Spyder. Reinicialización abortada.No fue posible convertir este notebook. El error es: No fue posible copiar este arregloNo fue posible copiar valores para este arregloNo fue posible generar ayuda en texto enriquecido para este objeto.
Por favor véala en texto plano.No fue posible remover las outputs de este notebook. El error es: No fue posible reiniciar Spyder. Operación abortada.No fue posible reiniciar la terminal de IPython al abrir este proyecto. El error fue {0}No fue posible ejecutar este archivo en una terminal del sistemaCursivaImágenes JPEGArchivos JSONArchivos JavascriptArchivos JsonArchivos JuliaEl núcleo dejó de funcionar, reiniciándoloReiniciando el núcleoClave/TeclaNombre:Atajos de tecladoPalabra clave:LenguajeÚltima posición de ediciónLa disposición %s será sobrescrita. Desea continuar?Orden y visualización de las disposicionesPreferencias de disposiciónLínea %sNúmero total de líneas:Salto de línea (UNIX)Línea:Líneas:Enlazar a la definición de un objetoEnlace:ListaCargando %s...Cargando la terminal de IPython...Cargando el editor...Cargando el explorador de archivos...Cargando la ayuda...Cargando el historial...Cargando el explorador de variables...Cargando la ayuda en línea...Cargando el explorador de código...Cargando el explorador de proyectos...No se admite la carga de este tipo de datos mientras se ejecuta el depurador de código.UbicaciónBloquearBloquear los panelesArchivos MATLABBarra principalMantener el foco en el Editor después de ejecutar celdas o seleccionesManejar esquemas de coloreadoManipular notebooks de Jupyter en el EditorArchivos MarkdownMáscaraDatos enmascaradosParéntesis
emparejados:Archivos de MatlabDocumentación de MatplotlibMaximizar el panel actualMáximo número de entradasMáximo número de líneas a mostrarMáximo número de archivos recientesMáximo número de archivos recientes...Para reportar el uso de memoria se requiere de la librería `psutil` (>=0.3) en plataformas distintas a WindowsMemoria:Método definido en la línea %sModifique como se muestran los prompts de entrada y salida en la terminal.MóduloNo se pudo encontrar el módulo pywin32.
Por favor reinicie esta sesión de Windows (no el computador) para que los cambios surtan efecto.Módulo o paquete:MóduloMover abajoMover arribaMover abajoMover al finalMover al principioMover arribaMover a...Archivos NSISNombreNombres de los filtros:Crear nuevoNuevo proyecto...Nuevo directorioNuevas características en Spyder 3.0Nuevo archivoNueva carpetaNuevo móduloNuevo nombre:Nuevo paqueteNuevo atajo:Nuevo en Spyder? Lee nuestroNuevo nombre de variable:Nueva ventanaSiguienteSiguiente posición del cursorSiguiente advertencia o errorNo existe un intérprete de IPython para ejecutar %s.

Por favor abra uno nuevo e intente otra vez.No existe documentación disponibleNo existe más documentación disponibleSin coincidenciasNo está disponible el código fuenteNormalTexto normal:No hay nada para importar desde el portapapeles.Arreglo de NumPyArreglos de NumPyArreglos comprimidos de NumPyNúmero:Documentación de Numpy y ScipyAbrir el último cerradoObjetoOcurrencia:DesactivadoEn modo %s, Autollamar no se usa si no hay argumentos después del objeto llamable. En modo %s, todos los objetos llamables son llamados automáticamente (aún si no hay argumentos presentes).Documentación en líneaAyuda en líneaSólo se usa cuando el formato es PNG. Por defecto es 72.AbrirAbrir &recienteAbrir una terminal de Python aquíAbrir proyecto...Abrir una nueva terminal de IPython conectada a un núcleo existenteAbrir una terminal de IPythonAbrir símbolo del sistema aquíAbrir un archivo de conexiónAbrir archivoAbrir archivo como:Abrir el último archivo cerradoAbrir proyectoAbrir terminal del sistema aquíArchivos OpenCLAbrir e inspeccionar esta variable puede tomar mucho tiempo ¿Desea continuar de todas formas?OpcionesExplorador de códigoPrompt de salida:Imágenes PNGAdministrador del PYTHONPATHNombre del paquete:Paquete...PanelesDirectorio superiorContraseñaContraseña o frase de contraseña de la clave sshPegarArchivos Patch y diffRuta al archivo de conexión o id del núcleoRuta al archivo de clave sshRealice operaciones simbólicas en la terminal (integrales, derivadas o cálculo vectorial) y obtenga los resultados en un bello estilo impreso (requiere el módulo Sympy).Realizar análisis sólo cuando se guarde el archivoRealizar los análisis al guardar el archivo y cadaPermisos:Archivos picklePlanoTexto planoTexto planoPor favor considere instalar Sphinx para obtener la documentación en texto enriquecido Por favor introduzca la información de conexión del núcleo al cual desea conectarse. Para ello puede seleccionar su archivo de conexión JSON, usando el botón Seleccionar, o escribir directamente su id, en caso de que sea un núcleo local (por ejemplo, kernel-3764.json o sólo 3764)Por favor instale Matplotlib o guiqwt.Por favor introduzca un nuevo atajoPor favor tenga en cuenta que estos cambios sólo se aplicarán a nuevas terminales de IPython y PythonPor favor tenga en cuenta que estos cambios sólo se aplicarán a nuevas terminalesGraficarMostrar la terminal interna cuando se produzcan erroresPre&ferenciasPreferenciasPreferencias > AyudaPresione Enter para cambiar entre archivos o Esc para cancelar.

Escriba un texto para filtrar los nombres de archivos.

Use :número para ir a una línea dada, e.g. main:42
Use @símbolo para ir a un símbolo, e.g. @init

Presione Ctrl+W para cerrar la pestaña actual.
Presione Enter para validar esta entradaPresione Enter para validar esta rutaTeclee el nuevo atajo y seleccione 'Ok': (Presione 'Tab' una vez para cambiar el foco entre la entrada del atajo y los botones que aparecen abajo)Vista previaAnteriorAnterior posición del cursorAnterior advertencia o errorImprimir el archivo actual...Presentación preliminar...Imprimir...ProyectoExplorador de proyectosPreferencias del proyectoExplorador de proyectosNombre del proyectoPreferencias del proyectoTipo del proyectoPreguntar antes de salirPromptsCaracterísticas proporcionadasReferencia del API de PyQt4Manual de referencia de PyQt4Referencia del API de PyQt5Manual de referencia de PyQt5Manejador de rutas de PythonDocumentación de PythonArchivos PythonAyuda de Python:Intérprete de PythonPaquete de PythonProyecto de PythonArchivos de PythonVersión de PythonDocumentación de Python2Documentación de Python3Diseñador de interfaces de QtTraductor de aplicaciones de QtDocumentación de QtEjemplos de QtEstilo de QtReferencia rápidaAún no se ha definido la disposición de componentes #%dSalir&Eliminar comentario de bloqueTexto sin formatoEjecutar de nuevo la última celda Ejecutar de &nuevo el último archivoEjecutar de nuevo la última celdaAnálisis del código en tiempo real en el EditorAnálisis del código en tiempo real en el EditorAnálisis de estilo del código en el EditorAnálisis de estilo del código en el EditorProyectos recientesCampos del arreglo de records:RehacerActualiza la lista de nombres de los módulos disponibles en su PYTHONPATHExpresión regularError en la expresión regularError de remociónEliminarEliminar todas las variablesEliminar todas las variables antes de la ejecuciónEliminar comentario de bloque alrededor de la línea o selección actualEliminar rutaEliminar referencias:Eliminar espacios en blancoRenombrarRenombrar la pestañaRenombrar...Renderizar ecuaciones matemáticasReemplazar todoReemplazar la selecciónReemplazar textoReemplazar caracteres de tabulación por espaciosReemplazar con:Buscar/reemplazar siguienteReportar un problema...RestaurarRestaurar Spyder a su configuración por defectoRestaurar los valores por defectoRestaurar los valores por defectoRestaurar a la disposición por defectoRestaurando a los valores por defectoRedimensionarAjustar filas a los contenidosResolución:ReiniciarReiniciar el núcleoReiniciar el núcleo?ReiniciandoRestaurarRestaurar el panel actualRestaurar datos al inicioRestaurar la disposición originalRestaurar el panel a su tamaño originalRestaurar archivo desde el discoTexto enriquecidoTexto enriquecidoSeparador de filas:EjecutarEjecutar la &selección o la línea actualEjecute archivos de Cython en la terminal de IPythonEjecutar archivo de PythonAjustes de ejecuciónEjecutar un archivo de PythonEjecutar un archivoEjecutar de nuevo el mismo archivoEjecutar la celdaEjecutar la celda y avanzarEjecutar códigoOpciones de ejecuciónConfiguración de ejecución por archivoEjecutar la celda actual (Ctrl+Enter) [Usar #%% para crear celdas]Ejecutar la celda actual y avanzar a la siguiente (Shift+Enter)Ejecutar la línea seleccionadaEjecutar archivoEjecutar un archivo:Ejecutar selecciónEjecutar la &selección o línea actualAjustes de ejecuciónAjustes de ejecución para %sBarra de ejecuciónEjecutar hasta que la función o método actual termineEjecutar en una terminal externa del sistema no está soportado en la plataforma %s.Guardar t&odoGuardarGu&ardar como...Guardar todos los archivosGuardar todo antes de ejecutar un archivoGuardar arregloGuardar copia como...Guardar copia del archivo actual como...Guardar el archivo actual como...Guardar el historial actual (es decir todas las entradas y salidas) en un archivo de textoGuardar la disposición actualGuardar datosGuardar datos como...Guardar datos al salirGuardar archivoGuardar el historialGuardar el historialGuardar el historial...Guardar archivos abiertos que no pertenecen al proyectoNo es posible guardar datos durante la ejecución del depurador de código.Nombre del esquema:Esquema:PuntajeResolución de la pantallaDesplazarse automáticamente a la última entradaBuscarDirectorio de búsquedaBuscar en todos los archivos y directorios presentes en la ruta actual de SpyderBuscar en todos los archivos y directorios presentes en la ruta del proyecto actual (si está abierto)Buscar en el archivo abiertoBuscar en otro directorio del sistema de archivosBuscar en:Patrón de búsquedaBuscar textoBuscar en varios archivos a la vezBarra de búsquedaBuscar:Seleccionar todoSeleccionar una configuración de ejecución:Seleccionar directorioSeleccionar archivoSeleccionar otro directorioSeleccionar clave sshSeleccionar el intérprete de Python para todas las terminales de SpyderEstablecer la lista de módulos excluidos por el RMUDefina el valor del escalado para pantallas de alta resoluciónEstablecer directorio de trabajoFija el directorio de trabajo para la terminal actual como el directorio del archivo actualEstablece la ruta del editor externoEstablece el máximo número de entradas a almacenarEstablece el máximo número de líneas a mostrar en la terminalEstablezca la lista de módulos excluidos como: numpy, scipyEstablece el máximo número de líneas que se mostrarán en la terminal en cualquier momento. Si se introduce -1 se mostrarán todas las líneas (no se recomienda!)Activar esta opción para escalar la interfaz a pantallas de alta resoluciónActivar esta opción en pantallas de alta resolución cuando el auto-escalado de la interfaz no funcioneEstablezca esta opción
si desea separar los menús de la ventana principalSeleccione esta opción
para abrir archivos externos de Python en la ventana actual (Requiere reiniciar)Añadir o eliminar un punto de interrupciónAñadir o editar un punto de interrupción condicionalConstruyendo la ventana principal...AjustesComandos especiales:AtajoAtajo: {0}Resumen de atajosRestaurar los atajosLos accesos directos que usan Shift más otra tecla no son válidosMuestra los contenidos del sys.path en modo lecturaMostrar el uso de CPU cadaMostrar código fuenteMostrar la ruta completaMostrar opciones avanzadasMostrar todos los archivosMostrar y editar las variables de entorno del usuario actual en el registro de Windows (es decir, para todas las sesiones)Muestra y edita las variables de entorno (para la sesión actual)Mostrar el máximo y mínimo de arreglosMostrar espacios en blancoMostrar errores o advertencias del análisis del códigoMostrar la lista de comentarios (TODO/FIXME/XXX/HINT/TIP/@todo/HACK/BUG/OPTIMIZE/!!!/???)Mostrar sólo el directorio actualMostrar el tiempo transcurridoMostrar las variables de entornoMostrar ayuda para los objetos del Editor y las terminalesMostrar una barra de desplazamiento horizontalMostrar iconos y texto Mostrar como imagenMostrar en explorador del sistemaMostrar en el explorador de archivos del sistemaMostrar números de líneasMostrar la memoria usada cadaMostrar la lista de módulos que fueron recargadosMostrar comentarios especialesMostrar la barra de estatusContenidos del sys.pathContenidos del sys.pathMostrar barra de pestañasMostrar lista de TODO'sMostrar barras de herramientasMostrar una línea vertical después deMostrar la lista de errores y advertenciasMostrar u ocultar el explorador de códigoÁreas laterales:SiftTamañoTamaño:Saltar filas:Inteligente&Código fuenteOrigenCódigo fuenteBarra de código fuenteSphinx %s está instalado actualmente.Dividir horizontalmenteDividir horizontalmente esta ventana o panel de ediciónDividir verticalmenteDividir verticalmente esta panel o ventana de ediciónDisposición por defectoEditor de SpyderTerminal interna de Spyder! Esta terminal se utiliza para reportar errores de la aplicación y para inspeccionar las características internas de Spyder con los siguientes comandos: spy.app, spy.window, dir(spy) Por favor no ejecuta su código en esta terminal Atajos de teclado de SpyderSpyder no pudo volver a la configuración por defecto. Reinicialización abortada.Archivos de datos de SpyderSpyder depende de varios módulos de Python para proveer la funcionalidad correcta para todos sus paneles. La tabla que aparece a continuación muestra las versiones requeridas e instaladas (de existir) de todos ellos.

Nota: Usted puede utilizar Spyder sin problemas si no cuenta con los siguientes módulos instalados: %s y %s.

Por favor también tenga en cuenta que dependencias nuevas o que hayan sido cambiadas en esta lista, sólo serán detectadas correctamente después de que Spyder sea reiniciado.Documentación de SpyderError de salida de de SpyderSpyder es un ambiente de desarrollo interactivo basado en blaSpyder está actualizado.Spyder necesita reiniciar para cambiar la siguiente configuración:Spyder necesita reiniciar para cambiar las siguientes configuraciones:Error de restauración de SpyderError de reinicio de SpyderObtener soporte para SpyderTutorial de SpyderActualizaciones de SpyderSpyder no fue capaz de extraer el valor de esta variable de la terminal.

El mensaje de error fue:
%sSpyder se reiniciará y volverá a su configuración por defecto:

¿Desea continuar?Clave sshComenzar la búsquedaInicializaciónBarra de estadoEjecutar líneaIngresar en la función/métodoSalir de la función/métodoIngresar en la función o método de la línea actualDetenerDetener la depuraciónDetener la búsquedaDetener el comando actualTexto no encontradoCadena:Enviar a GithubSoporte para crear gráficas (Matplotlib)Archivos soportadosArchivos de texto soportadosBuscador de símbolos...Matemática simbólicaMatemática simbólica en la terminal de IPythonSincronizarSincronizar la lista de rutas de Spyder con la variable de entorno PYTHONPATHSincronizar...Coloreado de sintaxisColoreado del código para archivos tipo Matlab, Julia y varios otros tiposComandos del sistema:Imágenes TIFFTabulaciónSiempre indentar con la tecla TabAncho de las tabulaciones:TabulacionesSeparar los menúsArchivo temporalTerminalTextoEditor de textoArchivos de TextoEl argumento de longitud 'xlabels' no coincide con el número de columnas del arregloEl argumento de longitud 'ylabels' no coincide con el número de filas del arregloEl directorio de trabajo actual es el directorio de trabajo de las consolas IPython y el directorio actual del explorador de archivos.El EditorEl Explorador de archivosEl Historial de comandosLa Terminal de IPythonEl Explorador de variablesLa autenticidad del servidor %s no puede ser establecida. ¿Está seguro de que desea continuar conectándose?La autenticidad del servidor no puede ser establecidaEl directorio actual contiene un proyecto.

Si desea eliminar este proyecto, por favor diríjase a Proyectos » Eliminar proyectoEl directorio del proyecto actual o el directorio personal del usuario (si no hay ningún proyecto activo)El directorio de trabajo actualEl directorio del archivo que se está ejecutandoEl directorio cuando una nueva consola se abre será el siguienteEl directorio {} no tiene permisos de escritura, lo cual es requerido para crear terminales de IPython. Por favor cambie sus permisos.A continuación se muestran las opciones predeterminadas para ejecutar archivos. Estas opciones se pueden sobre escribir mediante laConfiguración por archivo del menú Ejecutar.Los siguientes conflictos han sido detectados:El siguiente directorio:Ocurrió el siguiente error cuando se trató de utilizar Sphinx %s.
Ello se debe a una versión incompatible de Sphinx o bien a que no fue posible leer la documentación solicitada.

Mensaje de error:
%sLos siguientes módulos no están instalados en su computador: %sEl siguiente directorio de trabajo no es válido:
%sEl nuevo atajo tiene entra en conflicto con:El directorio de trabajo para la nueva consola es:Este directorio ya está incluido en la lista de rutas de Spyder.
¿Desea moverlo al principio de la lista?Esta entrada es incorrectaEste error fue causado probablemente por la instalación de Spyder en un directorio con caracteres no ascii (es decir, caracteres con tildes, apóstrofes o símbolos no latinos). Para solucionarlo, por favor reinstale Spyder en un lugar diferente.Esta característica requiere Sphinx 1.1 o superior.Esta característica requiere las librerías Rope o Jedi. Al parecer no tiene ninguna instalada.Este es un núcleo remotoEste es un archivo temporalEste es uno de los paneles en los que es posible ejecutar el código escrito en el Editor. Para hacerlo es necesario presionar la teclar F5.

Esta terminal viene dotada con varias características que mejoran significativamente la experiencia de programar en Python (como el resaltado de sintaxis). Si desea saber más al respecto, por favor siga este enlace.

Por favor oprima el botón que aparece abajo para ejecutar un código muy sencillo en esta terminal. Esto será útil para mostrarle otras características más adelante.Este es el panel en el que puede escribir su código de Python antes de evaluarlo. Para obtener sugerencias automáticas de completado mientras escribe, puede presionar la tecla Tab junto a un texto dado.

El Editor viene con un área para los números de línea (resaltada aquí en rojo), donde Spyder también muestra advertencias y mensajes de error. Estos pueden ayudarle a detectar posibles problemas antes de correr el código.

También se pueden establecer puntos de breakpoint en esta área al hacer doble click junto a una línea que no esté vacía.Este es el directorio de trabajo para las terminales que se abran de aquí en adelante (de IPython y Python y terminales de comandos), para el Explorador de archivos, y Buscar en archivos y para los nuevos archivos creados en el EditorEsto le permite cargar el soporte gráfico sin importar los comandos para crear figuras. Es útil para trabajar con otras librerías gráficas diferentes a Matplotlib o para desarrollar interfaces gráficas con Spyder.Esta opción le permite ocultar el mensaje que aparece al principio de la terminal cuando se abre por primera vez.Esta opción le permite ocultar el mensaje que aparece cuando se van a eliminar todas las variables definidas por el usuario.Esta opción carga la librería Sympy para trabajar
con ella. Por favor lea su documentación para aprender como usarla.Esta opción será aplicada la próxima vez que una terminal sea abierta.Esta opción activará el Recargador de Módulos del Usuario (RMU) en las terminales de Python y IPython. El RMU obliga a Python a recargar profundamente los módulos que fueron importados al ejecutar un archivo de Python, usando la función incorporada de Spyder llamada runfile.

1. El RMU puede requerir que se reinicie la terminal en la cual será utilizado (de otra forma, sólo los módulos que fueron importados en último lugar serán recargados al ejecutar un archivo).

2. Si ocurre algún error al re-ejecutar programas basados en PyQt, por favor verifique que los objetos de Qt sean destruidos apropiadamente (por ejemplo, puede tener que usar el atributo Qt.WA_DeleteOnClose en su ventana principal, utilizando para ello el método setAttribute).Este panel puede mostrar automáticamente la ayuda de un objeto después de escribir un paréntesis junto al mismo. A continuación puede decidir a que panel desea conectarlo para activar esta característica.Este panel muestra la documentación de las funciones, clases, métodos o módulos que se estén usando en el Editor o las Terminales.

Para usarlo, por favor oprima la tecla Ctrl+I frente a un objeto dado. Si ese objeto cuenta con documentación asociada, ésta se mostrará aquí.Este panel le permite navegar a través de los directorios y archivos presentes en su computador.

También es posible abrir cualquier archivo desde este panel con su aplicación correspondiente, al hacer doble click en el mismo.

Sin embargo, existe una excepción a esta regla: todos los archivos de texto plano siempre se abrirán en el Editor de Spyder.Este panel guarda un registro de todos los comandos introducidos en las terminales de IPython y Python.Esta acción sincronizará la lista de rutas de Spyder con la variable de entorno PYTHONPATH para el usuario actual, permitiéndole ejecutar sus módulos de Python por fuera de Spyder sin tener que configurar sys.path.
¿Desea borrar los contenidos del PYTHONPATH antes de añadir la lista de rutas de Spyder?A booleanoA complejoTo doA flotanteA enteroA cadenaCambiar a minúsculasCambiar a mayúsculasBarras de herramientasTrasponerEl túnel '%s' falló en ser iniciadoTuplaTipoRMUEl RMU obliga a Python a recargar los módulos que fueron importados durante la ejecución de un archivo en la terminal con la función 'runfile'.No fue posible buscar actualizacionesNo se pudo establecer conexión con `%s`No fue posible conectarse a Internet.

Por favor asegúrese de que la conexión está funcionando apropiadamente.No fue posible cargar la páginaNo fue posible recuperar la informaciónDescomentarDeshacerError inesperado. Por favor vea la terminal interna.Quitar indentaciónQuitar indentación de la línea o selección actualDesbloquearParéntesis
desemparejados:Actualice LANGUAGE_CODES (en config/base.py) si una nueva traducción se añadió a SpyderActualizar la lista de nombres de módulosUsoUsar un paginador para mostrar textos dentro de la terminalUtilizar una única instanciaUtilizar la siguiente disposiciónUtilizar la disposición anteriorUsar matemática simbólicaUsar el siguiente intérprete:Usar el siguiente archivo:Usar el completado ambiciosoUsar control de versionesEs útil si no desea llenar la terminal con largos textos de ayuda. Nota: Debe usar la tecla Q para salir del paginadorRecargador de Módulos del Usuario (RMU)ValorValor:Nombre de variableExplorador de variablesNombre de variable:Control de versionesSistema de versión de controlesPestañas verticales en los panelesBarras de título verticales para los panelesViTablesVer y editar DataFrames y Series en el Explorador de VariablesVer y editar arreglos bi y tridimensionales en el Explorador de VariablesAdvertenciaNo soportamos este acceso directo en WindowsArchivos de Páginas webBienvenido al Tour Introductorio de Spyder!Bienvenido a Spyder!Bienvenido al Tour introductorio!Cuando se abra un archivo de texto que contenga varios tipos de caracteres de fin de línea (lo cual puede dar lugar a errores en Windows), Spyder puede arreglar el archivo automáticamente.Espacios en blancoSolamente palabras completasAncho:WinPythonPanel de control de WinPythonLa disposición de componentes será restablecida a los ajustes por defecto. Esto afecta a la posición y tamaño de la ventana y los componentes. ¿Desea continuar?Disposiciones de componentesConfiguración del directorio de trabajoEspacio de trabajoAjuste de línea automáticoArchivos XMLArchivos YamlNo es posible importar un módulo con caracteres que no son ascii en Python 2. Por favor introduzca un módulo diferente.También se puede ejecutar un archivo completo al inicio, en lugar de unas pocas líneas (Esto es similar a tener un archivo PYTHONSTARTUP).Se pueden ejecutar varias líneas de código al abrir una terminal. Por favor introduzca cada una separada por comas, por ejemplo:
import os, import sysNo tiene con permisos para abrir este directorioUsted seleccionó un intérprete de Python %d para la terminal, pero Spyder está corriendo bajo Python %d!.

Aunque esto es posible, le recomendamos instalar y correr Spyder directamente con el intérprete seleccionado, para evitar ver falsos errores y alarmas en el Editor debido a la sintaxis incompatible entre estas dos versiones de Python.Se seleccionó un interprete de Python inválido así que se dejará el anterior. Por favor asegúrese de seleccionar un intérprete válido.Su entorno o instalación de Python no cuenta con los módulos ipykernel y cloudpickle. Sin estos módulos no es posible para Spyder el crear una terminal.

Puede instalarlos al ejecutar en una consola de comandos del sistema:

pip install ipykernel cloudpickle

o

conda install ipykernel cloudpickleAcercarAlejarRestaurararreglocaracterescódigocopiardatoseliminardpielementosarchivoArchivos gettextEjemplos de guidataEjemplos de guiqwtpulgadasexpresión regular inválidalíneaslistacoincidenciascoincidencias enmovermssin coincidenciasdeotropermiso denegado, se encontraron errorespixelsArchivos de Texto reStructuradosólo lecturaespaciostablatextoel siguiente directorio:este diálogotutorialArchivo sin guardarSin título usuario@servidor:puertonombre_de_variablespyder-3.2.6/spyder/locale/es/LC_MESSAGES/spyder.po0000664000175000017500000057666713224121062022455 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # Spyder's spanish translation file # Copyright (C) 2011 Spyder Development team # msgid "" msgstr "" "Project-Id-Version: 2.1\n" "POT-Creation-Date: 2017-12-14 15:40+-05\n" "PO-Revision-Date: 2017-12-16 14:20-0500\n" "Last-Translator: Carlos Cordoba \n" "Language-Team: Python\n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "X-Poedit-SourceCharset: utf-8\n" "X-Poedit-Basepath: ../../../..\n" "X-Generator: Poedit 2.0.1\n" #: spyder/app/mainwindow.py:134 msgid "Initializing..." msgstr "Inicializando..." #: spyder/app/mainwindow.py:237 msgid "Python2 documentation" msgstr "Documentación de Python2" #: spyder/app/mainwindow.py:239 msgid "Python3 documentation" msgstr "Documentación de Python3" #: spyder/app/mainwindow.py:241 msgid "Numpy and Scipy documentation" msgstr "Documentación de Numpy y Scipy" #: spyder/app/mainwindow.py:243 msgid "Matplotlib documentation" msgstr "Documentación de Matplotlib" #: spyder/app/mainwindow.py:246 msgid "PyQt4 Reference Guide" msgstr "Manual de referencia de PyQt4" #: spyder/app/mainwindow.py:249 msgid "PyQt4 API Reference" msgstr "Referencia del API de PyQt4" #: spyder/app/mainwindow.py:252 msgid "PyQt5 Reference Guide" msgstr "Manual de referencia de PyQt5" #: spyder/app/mainwindow.py:255 msgid "PyQt5 API Reference" msgstr "Referencia del API de PyQt5" #: spyder/app/mainwindow.py:257 msgid "WinPython" msgstr "WinPython" #: spyder/app/mainwindow.py:530 msgid "" "An error occurred while creating a socket needed by Spyder. Please, try to " "run as an Administrator from cmd.exe the following command and then restart " "your computer:

netsh winsock reset
" msgstr "" "Se ha producido un error al crear un socket necesario para ejecutar Spyder. " "Intente abrir una terminal de sistema (cmd.exe) como administrador, ejecute " "el siguiente comando y reinicie su equipo:

netsh winsock reset
" #: spyder/app/mainwindow.py:562 msgid "Close current pane" msgstr "Cerrar panel actual" #: spyder/app/mainwindow.py:567 msgid "Lock panes" msgstr "Bloquear los paneles" #: spyder/app/mainwindow.py:574 msgid "Use next layout" msgstr "Utilizar la siguiente disposición" #: spyder/app/mainwindow.py:578 msgid "Use previous layout" msgstr "Utilizar la disposición anterior" #: spyder/app/mainwindow.py:588 spyder/widgets/editor.py:497 msgid "File switcher..." msgstr "Cambiador de archivos..." #: spyder/app/mainwindow.py:590 msgid "Fast switch between files" msgstr "Cambiar rápidamente entre archivos" #: spyder/app/mainwindow.py:596 msgid "Symbol finder..." msgstr "Buscador de símbolos..." #: spyder/app/mainwindow.py:598 msgid "Fast symbol search in file" msgstr "Búsqueda rápida de símbolos en el archivo" #: spyder/app/mainwindow.py:617 spyder/widgets/sourcecode/codeeditor.py:2661 msgid "Undo" msgstr "Deshacer" #: spyder/app/mainwindow.py:619 spyder/widgets/sourcecode/codeeditor.py:2664 msgid "Redo" msgstr "Rehacer" #: spyder/app/mainwindow.py:621 spyder/widgets/shell.py:123 #: spyder/widgets/sourcecode/codeeditor.py:2670 #: spyder/widgets/variableexplorer/arrayeditor.py:467 #: spyder/widgets/variableexplorer/collectionseditor.py:671 #: spyder/widgets/variableexplorer/dataframeeditor.py:586 msgid "Copy" msgstr "Copiar" #: spyder/app/mainwindow.py:623 spyder/widgets/shell.py:119 #: spyder/widgets/sourcecode/codeeditor.py:2667 msgid "Cut" msgstr "Cortar" #: spyder/app/mainwindow.py:625 spyder/widgets/shell.py:127 #: spyder/widgets/sourcecode/codeeditor.py:2673 #: spyder/widgets/variableexplorer/collectionseditor.py:668 msgid "Paste" msgstr "Pegar" #: spyder/app/mainwindow.py:628 spyder/widgets/shell.py:140 #: spyder/widgets/sourcecode/codeeditor.py:2676 msgid "Select All" msgstr "Seleccionar todo" #: spyder/app/mainwindow.py:638 spyder/plugins/editor.py:1423 msgid "&File" msgstr "&Archivo" #: spyder/app/mainwindow.py:639 spyder/plugins/editor.py:1411 msgid "File toolbar" msgstr "Barra de archivo" #: spyder/app/mainwindow.py:643 spyder/plugins/editor.py:1424 msgid "&Edit" msgstr "&Editar" #: spyder/app/mainwindow.py:644 spyder/plugins/editor.py:1421 msgid "Edit toolbar" msgstr "Barra de edición" #: spyder/app/mainwindow.py:648 spyder/plugins/editor.py:1425 msgid "&Search" msgstr "&Buscar" #: spyder/app/mainwindow.py:649 spyder/plugins/editor.py:1413 msgid "Search toolbar" msgstr "Barra de búsqueda" #: spyder/app/mainwindow.py:653 spyder/plugins/editor.py:1426 msgid "Sour&ce" msgstr "&Código fuente" #: spyder/app/mainwindow.py:654 spyder/plugins/editor.py:1415 msgid "Source toolbar" msgstr "Barra de código fuente" #: spyder/app/mainwindow.py:658 spyder/plugins/editor.py:803 #: spyder/plugins/editor.py:1427 msgid "&Run" msgstr "E&jecutar" #: spyder/app/mainwindow.py:659 spyder/plugins/editor.py:1417 msgid "Run toolbar" msgstr "Barra de ejecución" #: spyder/app/mainwindow.py:663 spyder/plugins/editor.py:762 msgid "&Debug" msgstr "&Depurar" #: spyder/app/mainwindow.py:664 spyder/plugins/editor.py:1419 msgid "Debug toolbar" msgstr "Barra de depuración" #: spyder/app/mainwindow.py:668 msgid "C&onsoles" msgstr "&Terminales" #: spyder/app/mainwindow.py:671 msgid "&Projects" msgstr "&Proyectos" #: spyder/app/mainwindow.py:674 spyder/plugins/editor.py:1428 msgid "&Tools" msgstr "&Herramientas" #: spyder/app/mainwindow.py:677 spyder/plugins/editor.py:1429 msgid "&View" msgstr "&Ver" #: spyder/app/mainwindow.py:680 spyder/plugins/editor.py:1430 msgid "&Help" msgstr "A&yuda" #: spyder/app/mainwindow.py:685 msgid "Welcome to Spyder!" msgstr "Bienvenido a Spyder!" #: spyder/app/mainwindow.py:690 msgid "Pre&ferences" msgstr "Pre&ferencias" #: spyder/app/mainwindow.py:697 spyder/widgets/pathmanager.py:53 msgid "PYTHONPATH manager" msgstr "Administrador del PYTHONPATH" #: spyder/app/mainwindow.py:700 msgid "Python Path Manager" msgstr "Manejador de rutas de Python" #: spyder/app/mainwindow.py:703 msgid "Update module names list" msgstr "Actualizar la lista de nombres de módulos" #: spyder/app/mainwindow.py:706 msgid "Refresh list of module names available in PYTHONPATH" msgstr "" "Actualiza la lista de nombres de los módulos disponibles en su PYTHONPATH" #: spyder/app/mainwindow.py:709 msgid "Reset Spyder to factory defaults" msgstr "Restaurar Spyder a su configuración por defecto" #: spyder/app/mainwindow.py:714 msgid "Current user environment variables..." msgstr "Variables de entorno del usuario actual..." #: spyder/app/mainwindow.py:716 msgid "" "Show and edit current user environment variables in Windows registry (i.e. " "for all sessions)" msgstr "" "Mostrar y editar las variables de\n" "entorno del usuario actual en el\n" "registro de Windows (es decir,\n" "para todas las sesiones)" #: spyder/app/mainwindow.py:725 spyder/app/mainwindow.py:1147 msgid "External Tools" msgstr "Herramientas externas" #: spyder/app/mainwindow.py:728 msgid "WinPython control panel" msgstr "Panel de control de WinPython" #: spyder/app/mainwindow.py:737 msgid "Qt Designer" msgstr "Diseñador de interfaces de Qt" #: spyder/app/mainwindow.py:742 msgid "Qt Linguist" msgstr "Traductor de aplicaciones de Qt" #: spyder/app/mainwindow.py:748 msgid "Qt examples" msgstr "Ejemplos de Qt" #: spyder/app/mainwindow.py:768 msgid "guidata examples" msgstr "Ejemplos de guidata" #: spyder/app/mainwindow.py:779 msgid "guiqwt examples" msgstr "Ejemplos de guiqwt" #: spyder/app/mainwindow.py:784 msgid "Sift" msgstr "Sift" #: spyder/app/mainwindow.py:794 msgid "ViTables" msgstr "ViTables" #: spyder/app/mainwindow.py:808 msgid "Fullscreen mode" msgstr "Modo a pantalla completa" #: spyder/app/mainwindow.py:820 msgid "Main toolbar" msgstr "Barra principal" #: spyder/app/mainwindow.py:829 msgid "" "Spyder Internal Console\n" "\n" "This console is used to report application\n" "internal errors and to inspect Spyder\n" "internals with the following commands:\n" " spy.app, spy.window, dir(spy)\n" "\n" "Please don't use it to run your code\n" "\n" msgstr "" "Terminal interna de Spyder!\n" "\n" "Esta terminal se utiliza para reportar errores de la\n" "aplicación y para inspeccionar las características\n" "internas de Spyder con los siguientes comandos:\n" " spy.app, spy.window, dir(spy)\n" "\n" "Por favor no ejecuta su código en esta terminal\n" #: spyder/app/mainwindow.py:846 msgid "Loading help..." msgstr "Cargando la ayuda..." #: spyder/app/mainwindow.py:853 msgid "Loading outline explorer..." msgstr "Cargando el explorador de código..." #: spyder/app/mainwindow.py:861 msgid "Loading editor..." msgstr "Cargando el editor..." #: spyder/app/mainwindow.py:867 spyder/plugins/console.py:140 #: spyder/widgets/ipythonconsole/client.py:417 msgid "&Quit" msgstr "&Salir" #: spyder/app/mainwindow.py:869 spyder/plugins/console.py:142 msgid "Quit" msgstr "Salir" #: spyder/app/mainwindow.py:873 msgid "&Restart" msgstr "&Reiniciar" #: spyder/app/mainwindow.py:875 msgid "Restart" msgstr "Reiniciar" #: spyder/app/mainwindow.py:889 msgid "Loading file explorer..." msgstr "Cargando el explorador de archivos..." #: spyder/app/mainwindow.py:896 msgid "Loading history plugin..." msgstr "Cargando el historial..." #: spyder/app/mainwindow.py:907 msgid "Loading online help..." msgstr "Cargando la ayuda en línea..." #: spyder/app/mainwindow.py:912 msgid "Loading project explorer..." msgstr "Cargando el explorador de proyectos..." #: spyder/app/mainwindow.py:925 msgid "Loading namespace browser..." msgstr "Cargando el explorador de variables..." #: spyder/app/mainwindow.py:931 msgid "Loading IPython console..." msgstr "Cargando la terminal de IPython..." #: spyder/app/mainwindow.py:936 msgid "Setting up main window..." msgstr "Construyendo la ventana principal..." #: spyder/app/mainwindow.py:939 msgid "Dependencies..." msgstr "Dependencias..." #: spyder/app/mainwindow.py:943 msgid "Report issue..." msgstr "Reportar un problema..." #: spyder/app/mainwindow.py:947 msgid "Spyder support..." msgstr "Obtener soporte para Spyder" #: spyder/app/mainwindow.py:950 msgid "Check for updates..." msgstr "Buscar actualizaciones..." #: spyder/app/mainwindow.py:973 msgid "Spyder documentation" msgstr "Documentación de Spyder" #: spyder/app/mainwindow.py:981 msgid "Spyder tutorial" msgstr "Tutorial de Spyder" #: spyder/app/mainwindow.py:986 msgid "Shortcuts Summary" msgstr "Resumen de atajos" #: spyder/app/mainwindow.py:992 msgid "Interactive tours" msgstr "Tours interactivos" #: spyder/app/mainwindow.py:1018 msgid "Python documentation" msgstr "Documentación de Python" #: spyder/app/mainwindow.py:1024 msgid "IPython documentation" msgstr "Documentación de IPython" #: spyder/app/mainwindow.py:1025 msgid "Intro to IPython" msgstr "Ayuda básica" #: spyder/app/mainwindow.py:1027 msgid "Quick reference" msgstr "Referencia rápida" #: spyder/app/mainwindow.py:1029 msgid "Console help" msgstr "Ayuda de la terminal" #: spyder/app/mainwindow.py:1059 msgid "Installed Python modules" msgstr "Módulos instalados de Python" #: spyder/app/mainwindow.py:1063 msgid "Online documentation" msgstr "Documentación en línea" #: spyder/app/mainwindow.py:1076 msgid "Qt documentation" msgstr "Documentación de Qt" #: spyder/app/mainwindow.py:1082 msgid "About %s..." msgstr "Acerca de %s..." #: spyder/app/mainwindow.py:1113 msgid "Panes" msgstr "Paneles" #: spyder/app/mainwindow.py:1115 msgid "Toolbars" msgstr "Barras de herramientas" #: spyder/app/mainwindow.py:1116 msgid "Window layouts" msgstr "Disposiciones de componentes" #: spyder/app/mainwindow.py:1125 spyder/app/mainwindow.py:1924 #: spyder/app/mainwindow.py:1925 msgid "Show toolbars" msgstr "Mostrar barras de herramientas" #: spyder/app/mainwindow.py:1140 msgid "Attached console window (debugging)" msgstr "Ventana de terminal anexa (para depuración)" #: spyder/app/mainwindow.py:1317 spyder/plugins/console.py:220 #: spyder/plugins/projects.py:248 spyder/widgets/explorer.py:708 #: spyder/widgets/explorer.py:813 #: spyder/widgets/variableexplorer/arrayeditor.py:587 #: spyder/widgets/variableexplorer/collectionseditor.py:427 #: spyder/widgets/variableexplorer/dataframeeditor.py:752 #: spyder/widgets/variableexplorer/dataframeeditor.py:756 #: spyder/widgets/variableexplorer/namespacebrowser.py:299 msgid "Error" msgstr "Error" #: spyder/app/mainwindow.py:1318 msgid "" "You have missing dependencies!

%s

Please " "install them to avoid this message.

Note: Spyder could " "work without some of these dependencies, however to have a smooth experience " "when using Spyder we strongly recommend you to install all the listed " "missing dependencies.

Failing to install these dependencies might " "result in bugs. Please be sure that any found bugs are not the direct result " "of missing dependencies, prior to reporting a new issue." msgstr "" "Algunas dependencias no están instaladas!

%s

Por favor instálelas para evitar este mensaje.

Nota: Spyder puede funcionar sin algunas de estas " "dependencias. Sin embargo, para no tener problemas al usar Spyder nosotros " "firmemente le recomendamos instalar todas las dependencias faltantes." "

El no instalar estas dependencias puede resultar en errores. Por " "favor asegúrese de que cualquier error que encuentre no sea el resultado " "directo de las dependencias faltantes, antes de reportar un nuevo problema." #: spyder/app/mainwindow.py:1771 msgid "Spyder Default Layout" msgstr "Disposición por defecto" #: spyder/app/mainwindow.py:1789 msgid "Save current layout" msgstr "Guardar la disposición actual" #: spyder/app/mainwindow.py:1793 msgid "Layout preferences" msgstr "Preferencias de disposición" #: spyder/app/mainwindow.py:1797 msgid "Reset to spyder default" msgstr "Restaurar a la disposición por defecto" #: spyder/app/mainwindow.py:1817 spyder/app/mainwindow.py:1839 #: spyder/app/mainwindow.py:1902 spyder/app/mainwindow.py:2722 #: spyder/plugins/configdialog.py:1346 spyder/plugins/ipythonconsole.py:131 #: spyder/plugins/ipythonconsole.py:927 spyder/plugins/ipythonconsole.py:1365 #: spyder/plugins/maininterpreter.py:149 spyder/plugins/maininterpreter.py:174 #: spyder/plugins/maininterpreter.py:203 spyder/utils/environ.py:95 #: spyder/utils/environ.py:108 #: spyder/widgets/ipythonconsole/namespacebrowser.py:131 #: spyder/widgets/ipythonconsole/namespacebrowser.py:149 #: spyder/widgets/variableexplorer/arrayeditor.py:510 #: spyder/widgets/variableexplorer/collectionseditor.py:416 #: spyder/widgets/variableexplorer/collectionseditor.py:1092 msgid "Warning" msgstr "Advertencia" #: spyder/app/mainwindow.py:1818 msgid "" "Window layout will be reset to default settings: this affects window " "position, size and dockwidgets.\n" "Do you want to continue?" msgstr "" "La disposición de componentes será restablecida a los ajustes por defecto. " "Esto afecta a la posición y tamaño de la ventana y los componentes.\n" "¿Desea continuar?" #: spyder/app/mainwindow.py:1840 msgid "" "Layout %s will be " "overwritten. Do you want to " "continue?" msgstr "La disposición %s será sobrescrita. Desea continuar?" #: spyder/app/mainwindow.py:1903 msgid "Quick switch layout #%s has not yet been defined." msgstr "Aún no se ha definido la disposición de componentes #%d" #: spyder/app/mainwindow.py:1921 spyder/app/mainwindow.py:1922 msgid "Hide toolbars" msgstr "Ocultar las barras de herramientas" #: spyder/app/mainwindow.py:2237 spyder/app/mainwindow.py:2238 msgid "Maximize current pane" msgstr "Maximizar el panel actual" #: spyder/app/mainwindow.py:2241 msgid "Restore current pane" msgstr "Restaurar el panel actual" #: spyder/app/mainwindow.py:2242 msgid "Restore pane to its original size" msgstr "Restaurar el panel a su tamaño original" #: spyder/app/mainwindow.py:2327 msgid "About %s" msgstr "Acerca de %s" #: spyder/app/mainwindow.py:2460 spyder/plugins/editor.py:168 #: spyder/plugins/runconfig.py:354 spyder/plugins/runconfig.py:476 #: spyder/utils/programs.py:286 spyder/widgets/explorer.py:335 msgid "Run" msgstr "Ejecutar" #: spyder/app/mainwindow.py:2461 msgid "Running an external system terminal is not supported on platform %s." msgstr "" "Ejecutar en una terminal externa del sistema no está soportado en la " "plataforma %s." #: spyder/app/mainwindow.py:2723 msgid "" "Spyder will restart and reset to default settings:

Do you want to " "continue?" msgstr "" "Spyder se reiniciará y volverá a su configuración por defecto: " "

¿Desea continuar?" #: spyder/app/mainwindow.py:2851 spyder/widgets/helperwidgets.py:254 msgid "Spyder updates" msgstr "Actualizaciones de Spyder" #: spyder/app/mainwindow.py:2852 spyder/plugins/configdialog.py:836 msgid "Check for updates on startup" msgstr "Buscar actualizaciones al inicio" #: spyder/app/mainwindow.py:2871 msgid "" "
IMPORTANT NOTE: It seems that you are using Spyder with " "Anaconda/Miniconda. Please don't use pip to " "update it as that will probably break your installation.

Instead, " "please wait until new conda packages are available and use conda to perform the update.
" msgstr "" "
NOTA IMPORTANTE: Al parecer Spyder está siendo usando junto con " "Anaconda o Miniconda. Por favor no use pip para " "actualizarlo, ya que ello probablemente dañará su instalación.

En su " "lugar, por favor espere hasta que nuevos paquetes de conda estén disponibles " "y utilice conda para realizar la actualización.
" #: spyder/app/mainwindow.py:2881 msgid "" "Spyder %s is available!

Please use your package manager to " "update Spyder or go to our Releases page to download this " "new version.

If you are not sure how to proceed to update Spyder " "please refer to our Installation instructions." msgstr "" "Spyder %s está disponible!

Por favor utilice su instalador de " "paquetes para actualizar Spyder o vaya a nuestra página de Lanzamientos para descargar esta nueva versión.

Si no está " "seguro de cómo proceder para actualizar Spyder, por favor lea nuestra " "instrucciones de Instalación (en inglés)." #: spyder/app/mainwindow.py:2894 msgid "Spyder is up to date." msgstr "Spyder está actualizado." #: spyder/app/restart.py:134 msgid "" "It was not possible to close the previous Spyder instance.\n" "Restart aborted." msgstr "" "No fue posible cerrar la instancia anterior de Spyder.\n" "Reinicialización abortada." #: spyder/app/restart.py:136 msgid "" "Spyder could not reset to factory defaults.\n" "Restart aborted." msgstr "" "Spyder no pudo volver a la configuración por defecto.\n" "Reinicialización abortada." #: spyder/app/restart.py:138 msgid "" "It was not possible to restart Spyder.\n" "Operation aborted." msgstr "" "No fue posible reiniciar Spyder.\n" "Operación abortada." #: spyder/app/restart.py:140 msgid "Spyder exit error" msgstr "Error de salida de de Spyder" #: spyder/app/restart.py:141 msgid "Spyder reset error" msgstr "Error de restauración de Spyder" #: spyder/app/restart.py:142 msgid "Spyder restart error" msgstr "Error de reinicio de Spyder" #: spyder/app/restart.py:183 msgid "Closing Spyder" msgstr "Cerrando Spyder" #: spyder/app/restart.py:257 msgid "Resetting Spyder to defaults" msgstr "Restaurando a los valores por defecto" #: spyder/app/restart.py:289 msgid "Restarting" msgstr "Reiniciando" #: spyder/app/tour.py:123 msgid "Welcome to the Introduction tour" msgstr "Bienvenido al Tour introductorio!" #: spyder/app/tour.py:124 msgid "" "Spyder is a powerful Interactive Development Environment (or IDE) for " "the Python programming language.

Here we are going to guide you " "through its most important features.

Please use the arrow keys or " "click on the buttons below to move along the tour." msgstr "" "Spyder es un potente entorno de desarrollo integrado para el lenguaje " "de programación Python.

A continuación vamos a guiarlo a través de " "sus características más importantes.

Por favor utilice las teclas de " "flechas o haga click en los botones que aparecen abajo para moverse a lo " "largo del tour." #: spyder/app/tour.py:133 msgid "The Editor" msgstr "El Editor" #: spyder/app/tour.py:134 msgid "" "This is the pane where you write Python code before evaluating it. You can " "get automatic suggestions and completions while writing, by pressing the " "Tab key next to a given text.

The Editor comes with a line " "number area (highlighted here in red), where Spyder shows warnings and " "syntax errors. They can help you to detect potential problems before running " "the code.

You can also set debug breakpoints in the line number area, " "by doing a double click next to a non-empty line." msgstr "" "Este es el panel en el que puede escribir su código de Python antes de " "evaluarlo. Para obtener sugerencias automáticas de completado mientras " "escribe, puede presionar la tecla Tab junto a un texto dado." "

El Editor viene con un área para los números de línea (resaltada " "aquí en rojo), donde Spyder también muestra advertencias y mensajes de " "error. Estos pueden ayudarle a detectar posibles problemas antes de correr " "el código.

También se pueden establecer puntos de breakpoint en esta " "área al hacer doble click junto a una línea que no esté vacía." #: spyder/app/tour.py:149 msgid "The IPython console" msgstr "La Terminal de IPython" #: spyder/app/tour.py:150 msgid "" "This is one of panes where you can run or execute the code you wrote on the " "Editor. To do it you need to press the F5 key.

This console " "comes with several useful features that greatly improve your programming " "workflow (like syntax highlighting and inline plots). If you want to know " "more about them, please follow this link.

Please " "click on the button below to run some simple code in this console. This will " "be useful to show you other important features." msgstr "" "Este es uno de los paneles en los que es posible ejecutar el código escrito " "en el Editor. Para hacerlo es necesario presionar la teclar F5." "

Esta terminal viene dotada con varias características que mejoran " "significativamente la experiencia de programar en Python (como el resaltado " "de sintaxis). Si desea saber más al respecto, por favor siga este enlace.

Por favor oprima el botón que aparece abajo para " "ejecutar un código muy sencillo en esta terminal. Esto será útil para " "mostrarle otras características más adelante." #: spyder/app/tour.py:166 msgid "The Variable Explorer" msgstr "El Explorador de variables" #: spyder/app/tour.py:167 msgid "" "In this pane you can view and edit the variables generated during the " "execution of a program, or those entered directly in one of Spyder consoles." "

As you can see, the Variable Explorer is showing the variables " "generated during the last step of this tour. By doing a double-click on any " "of them, a new window will be opened, where you can inspect and modify their " "contents." msgstr "" "En este panel se pueden ver y editar las variables generadas durante la " "ejecución de un programa, o de los comandos introducidos directamente en " "alguna de las terminales de Spyder.

Como se puede observar, el " "Explorador de Variables está mostrando las variables generadas durante el " "último paso de este tour. Al hacer doble click en alguna de ellas, se " "mostrará una nueva ventana, en la cual se pueden inspeccionar y modificar " "sus contenidos." #: spyder/app/tour.py:179 spyder/plugins/help.py:479 spyder/plugins/help.py:921 #: spyder/widgets/internalshell.py:270 msgid "Help" msgstr "Ayuda" #: spyder/app/tour.py:180 msgid "" "This pane displays documentation of the functions, classes, methods or " "modules you are currently using in the Editor or the Consoles.

To use " "it, you need to press Ctrl+I in front of an object. If that object " "has some documentation associated with it, it will be displayed here." msgstr "" "Este panel muestra la documentación de las funciones, clases, métodos o " "módulos que se estén usando en el Editor o las Terminales.

Para " "usarlo, por favor oprima la tecla Ctrl+I frente a un objeto dado. Si " "ese objeto cuenta con documentación asociada, ésta se mostrará aquí." #: spyder/app/tour.py:190 msgid "The File Explorer" msgstr "El Explorador de archivos" #: spyder/app/tour.py:191 msgid "" "This pane lets you navigate through the directories and files present in " "your computer.

You can also open any of these files with its " "corresponding application, by doing a double click on it.

There is " "one exception to this rule: plain-text files will always be opened in the " "Spyder Editor." msgstr "" "Este panel le permite navegar a través de los directorios y archivos " "presentes en su computador.

También es posible abrir cualquier " "archivo desde este panel con su aplicación correspondiente, al hacer doble " "click en el mismo.

Sin embargo, existe una excepción a esta regla: " "todos los archivos de texto plano siempre se abrirán en el Editor de Spyder." #: spyder/app/tour.py:201 msgid "The History Log" msgstr "El Historial de comandos" #: spyder/app/tour.py:202 msgid "" "This pane records all commands introduced in the Python and IPython consoles." msgstr "" "Este panel guarda un registro de todos los comandos introducidos en las " "terminales de IPython y Python." #: spyder/app/tour.py:250 msgid "Spyder is an interactive development environment based on bla" msgstr "Spyder es un ambiente interactivo de desarrollo basado en bla" #: spyder/app/tour.py:254 msgid "Welcome to Spyder introduction tour" msgstr "Bienvenido al Tour Introductorio de Spyder!" #: spyder/app/tour.py:255 msgid "Spyder is an interactive development environment based on bla" msgstr "Spyder es un ambiente de desarrollo interactivo basado en bla" #: spyder/app/tour.py:260 msgid "Introduction tour" msgstr "Tour Introductorio" #: spyder/app/tour.py:261 msgid "New features in version 3.0" msgstr "Nuevas características en Spyder 3.0" #: spyder/app/tour.py:555 spyder/plugins/ipythonconsole.py:446 msgid "Run code" msgstr "Ejecutar código" #: spyder/app/tour.py:830 msgid "Go to step: " msgstr "Ir al paso:" #: spyder/config/base.py:257 msgid "" "Update LANGUAGE_CODES (inside config/base.py) if a new translation has been " "added to Spyder" msgstr "" "Actualice LANGUAGE_CODES (en config/base.py) si una nueva traducción se " "añadió a Spyder" #: spyder/config/utils.py:24 msgid "Python files" msgstr "Archivos Python" #: spyder/config/utils.py:25 msgid "Cython/Pyrex files" msgstr "Archivos Cython/Pyrex" #: spyder/config/utils.py:26 msgid "C files" msgstr "Archivos C" #: spyder/config/utils.py:27 msgid "C++ files" msgstr "Archivos C++" #: spyder/config/utils.py:28 msgid "OpenCL files" msgstr "Archivos OpenCL" #: spyder/config/utils.py:29 msgid "Fortran files" msgstr "Archivos Fortran" #: spyder/config/utils.py:30 msgid "IDL files" msgstr "Archivos IDL" #: spyder/config/utils.py:31 msgid "MATLAB files" msgstr "Archivos MATLAB" #: spyder/config/utils.py:32 msgid "Julia files" msgstr "Archivos Julia" #: spyder/config/utils.py:33 msgid "Yaml files" msgstr "Archivos Yaml" #: spyder/config/utils.py:34 msgid "Patch and diff files" msgstr "Archivos Patch y diff" #: spyder/config/utils.py:35 msgid "Batch files" msgstr "Archivos Batch" #: spyder/config/utils.py:36 spyder/utils/iofuncs.py:426 msgid "Text files" msgstr "Archivos de Texto" #: spyder/config/utils.py:37 msgid "reStructuredText files" msgstr "Archivos de Texto reStructurado" #: spyder/config/utils.py:38 msgid "gettext files" msgstr "Archivos gettext" #: spyder/config/utils.py:39 msgid "NSIS files" msgstr "Archivos NSIS" #: spyder/config/utils.py:40 msgid "Web page files" msgstr "Archivos de Páginas web" #: spyder/config/utils.py:41 msgid "XML files" msgstr "Archivos XML" #: spyder/config/utils.py:42 msgid "Javascript files" msgstr "Archivos Javascript" #: spyder/config/utils.py:43 msgid "Json files" msgstr "Archivos Json" #: spyder/config/utils.py:44 msgid "IPython notebooks" msgstr "Notebooks de IPython" #: spyder/config/utils.py:45 msgid "Enaml files" msgstr "Archivos Enaml" #: spyder/config/utils.py:46 msgid "Configuration files" msgstr "Archivos de Configuración" #: spyder/config/utils.py:48 msgid "Markdown files" msgstr "Archivos Markdown" #: spyder/config/utils.py:52 spyder/widgets/explorer.py:781 msgid "All files" msgstr "Todos los archivos" #: spyder/config/utils.py:134 msgid "Supported text files" msgstr "Archivos de texto soportados" #: spyder/plugins/__init__.py:508 spyder/plugins/editor.py:105 #: spyder/plugins/editor.py:568 spyder/plugins/editor.py:1819 #: spyder/plugins/help.py:117 spyder/plugins/help.py:380 #: spyder/widgets/editor.py:534 spyder/widgets/sourcecode/codeeditor.py:98 #: spyder/widgets/sourcecode/codeeditor.py:3193 msgid "Editor" msgstr "Editor" #: spyder/plugins/configdialog.py:144 msgid "Reset to defaults" msgstr "Restaurar los valores por defecto" #: spyder/plugins/configdialog.py:156 msgid "Preferences" msgstr "Preferencias" #: spyder/plugins/configdialog.py:508 msgid "Invalid directory path" msgstr "Ruta de directorio inválida" #: spyder/plugins/configdialog.py:511 spyder/plugins/configdialog.py:526 #: spyder/plugins/runconfig.py:220 spyder/plugins/runconfig.py:268 #: spyder/plugins/workingdirectory.py:240 spyder/widgets/explorer.py:695 #: spyder/widgets/findinfiles.py:494 spyder/widgets/pathmanager.py:258 #: spyder/widgets/projects/projectdialog.py:155 msgid "Select directory" msgstr "Seleccionar directorio" #: spyder/plugins/configdialog.py:538 msgid "Invalid file path" msgstr "Ruta de archivo inválida" #: spyder/plugins/configdialog.py:541 spyder/plugins/configdialog.py:558 msgid "Select file" msgstr "Seleccionar archivo" #: spyder/plugins/configdialog.py:557 msgid "All files (*)" msgstr "Todos los archivos (*)" #: spyder/plugins/configdialog.py:630 msgid "Bold" msgstr "Negrita" #: spyder/plugins/configdialog.py:633 msgid "Italic" msgstr "Cursiva" #: spyder/plugins/configdialog.py:687 msgid "Font: " msgstr "Tipo de letra" #: spyder/plugins/configdialog.py:693 msgid "Size: " msgstr "Tamaño:" #: spyder/plugins/configdialog.py:712 msgid "Font style" msgstr "Fuente" #: spyder/plugins/configdialog.py:789 msgid "Spyder needs to restart to change the following setting:" msgstr "Spyder necesita reiniciar para cambiar la siguiente configuración:" #: spyder/plugins/configdialog.py:792 msgid "Spyder needs to restart to change the following settings:" msgstr "Spyder necesita reiniciar para cambiar las siguientes configuraciones:" #: spyder/plugins/configdialog.py:794 msgid "Do you wish to restart now?" msgstr "¿Desea reiniciar ahora?" #: spyder/plugins/configdialog.py:800 msgid "Information" msgstr "Información" #: spyder/plugins/configdialog.py:814 spyder/plugins/configdialog.py:821 #: spyder/widgets/projects/configdialog.py:74 msgid "General" msgstr "General" #: spyder/plugins/configdialog.py:824 msgid "Language" msgstr "Lenguaje" #: spyder/plugins/configdialog.py:827 msgid "Use a single instance" msgstr "Utilizar una única instancia" #: spyder/plugins/configdialog.py:829 msgid "" "Set this to open external
Python files in an already running instance " "(Requires a restart)" msgstr "" "Seleccione esta opción
para abrir archivos externos de Python en la " "ventana actual (Requiere reiniciar)" #: spyder/plugins/configdialog.py:832 msgid "Prompt when exiting" msgstr "Preguntar antes de salir" #: spyder/plugins/configdialog.py:833 msgid "Pop up internal console when internal errors appear" msgstr "Mostrar la terminal interna cuando se produzcan errores" #: spyder/plugins/configdialog.py:853 spyder/plugins/editor.py:114 #: spyder/plugins/ipythonconsole.py:290 #: spyder/widgets/projects/configdialog.py:81 msgid "Interface" msgstr "Interfaz" #: spyder/plugins/configdialog.py:861 msgid "Qt windows style" msgstr "Estilo de Qt" #: spyder/plugins/configdialog.py:867 msgid "Icon theme" msgstr "Tema de iconos" #: spyder/plugins/configdialog.py:871 msgid "Vertical title bars in panes" msgstr "Barras de título verticales para los paneles" #: spyder/plugins/configdialog.py:873 msgid "Vertical tabs in panes" msgstr "Pestañas verticales en los paneles" #: spyder/plugins/configdialog.py:875 msgid "Animated toolbars and panes" msgstr "Barras de herramientas y paneles animados" #: spyder/plugins/configdialog.py:877 msgid "Tear off menus" msgstr "Separar los menús" #: spyder/plugins/configdialog.py:878 msgid "Set this to detach any
menu from the main window" msgstr "" "Establezca esta opción
si desea separar los menús de la ventana principal" #: spyder/plugins/configdialog.py:880 msgid "Custom margin for panes:" msgstr "Márgenes personalizadas para los paneles:" #: spyder/plugins/configdialog.py:882 msgid "pixels" msgstr "pixels" #: spyder/plugins/configdialog.py:889 msgid "Cursor blinking:" msgstr "Parpadeo del cursor:" #: spyder/plugins/configdialog.py:891 msgid "ms" msgstr "ms" #: spyder/plugins/configdialog.py:930 msgid "Status bar" msgstr "Barra de estado" #: spyder/plugins/configdialog.py:931 msgid "Show status bar" msgstr "Mostrar la barra de estatus" #: spyder/plugins/configdialog.py:933 msgid "Show memory usage every" msgstr "Mostrar la memoria usada cada" #: spyder/plugins/configdialog.py:935 spyder/plugins/configdialog.py:944 #: spyder/plugins/editor.py:139 spyder/plugins/editor.py:283 msgid " ms" msgstr "ms" #: spyder/plugins/configdialog.py:942 msgid "Show CPU usage every" msgstr "Mostrar el uso de CPU cada" #: spyder/plugins/configdialog.py:975 msgid "Screen resolution" msgstr "Resolución de la pantalla" #: spyder/plugins/configdialog.py:977 msgid "" "Configuration for high DPI screens

Please see {0}<> for more information about these options (in English)." msgstr "" "Configuración para pantallas de alta densidad de pixeles

Visite
{0}<> para obtener más información sobre estas opciones (en " "inglés)." #: spyder/plugins/configdialog.py:987 msgid "Normal" msgstr "Normal" #: spyder/plugins/configdialog.py:991 msgid "Enable auto high DPI scaling" msgstr "Activar el escalado para pantallas de alta resolución" #: spyder/plugins/configdialog.py:994 msgid "Set this for high DPI displays" msgstr "" "Activar esta opción para escalar la interfaz \n" "a pantallas de alta resolución" #: spyder/plugins/configdialog.py:998 msgid "Set a custom high DPI scaling" msgstr "Defina el valor del escalado para pantallas de alta resolución" #: spyder/plugins/configdialog.py:1001 msgid "Set this for high DPI displays when auto scaling does not work" msgstr "" "Activar esta opción en pantallas de alta resolución cuando el auto-escalado " "de la interfaz no funcione" #: spyder/plugins/configdialog.py:1007 msgid "" "Enter values for different screens separated by semicolons ';', float values " "are supported" msgstr "" "Introduzca los valores para las diferentes pantallas separadas por punto y " "coma ';', es posible utilizar tanto números reales como enteros" #: spyder/plugins/configdialog.py:1034 msgid "Plain text font" msgstr "Texto plano" #: spyder/plugins/configdialog.py:1040 msgid "Rich text font" msgstr "Texto enriquecido" #: spyder/plugins/configdialog.py:1043 msgid "Fonts" msgstr "Tipo de letra" #: spyder/plugins/configdialog.py:1057 msgid "Appearance" msgstr "Apariencia" #: spyder/plugins/configdialog.py:1059 spyder/plugins/ipythonconsole.py:579 msgid "Advanced Settings" msgstr "Opciones avanzadas" #: spyder/plugins/configdialog.py:1095 msgid "Syntax coloring" msgstr "Coloreado de sintaxis" #: spyder/plugins/configdialog.py:1108 msgid "" "Here you can select the color scheme used in the Editor and all other Spyder " "plugins.

You can also edit the color schemes provided by Spyder or " "create your own ones by using the options provided below.
" msgstr "" "Aquí puede seleccionar el esquema de colores usado en el Editor y todos los " "demás paneles de Spyder.

También puede editar los esquemas de colores " "que vienen con Spyder o crear los suyos al usar las opciones que aparecen a " "continuación.
" #: spyder/plugins/configdialog.py:1113 msgid "Edit selected" msgstr "Editar esquema" #: spyder/plugins/configdialog.py:1114 msgid "Create new scheme" msgstr "Crear nuevo esquema" #: spyder/plugins/configdialog.py:1115 spyder/widgets/explorer.py:574 #: spyder/widgets/projects/explorer.py:242 spyder/widgets/shell.py:136 msgid "Delete" msgstr "Eliminar" #: spyder/plugins/configdialog.py:1118 msgid "Reset" msgstr "Restaurar" #: spyder/plugins/configdialog.py:1125 msgid "Scheme:" msgstr "Esquema:" #: spyder/plugins/configdialog.py:1156 msgid "Manage color schemes" msgstr "Manejar esquemas de coloreado" #: spyder/plugins/configdialog.py:1347 msgid "Are you sure you want to delete this scheme?" msgstr "¿Está seguro de que borrar este esquema?" #: spyder/plugins/configdialog.py:1464 msgid "Text" msgstr "Texto" #: spyder/plugins/configdialog.py:1466 msgid "Highlight" msgstr "Resaltar" #: spyder/plugins/configdialog.py:1468 msgid "Background" msgstr "Fondo" #: spyder/plugins/configdialog.py:1472 msgid "Scheme name:" msgstr "Nombre del esquema:" #: spyder/plugins/configdialog.py:1479 msgid "Color scheme editor" msgstr "Editor de esquemas" #: spyder/plugins/console.py:115 msgid "Internal console" msgstr "Terminal interna" #: spyder/plugins/console.py:145 msgid "&Run..." msgstr "E&jecutar..." #: spyder/plugins/console.py:147 msgid "Run a Python script" msgstr "Ejecutar un archivo de Python" #: spyder/plugins/console.py:150 msgid "Environment variables..." msgstr "Variables de entorno..." #: spyder/plugins/console.py:152 msgid "Show and edit environment variables (for current session)" msgstr "Muestra y edita las variables de entorno (para la sesión actual)" #: spyder/plugins/console.py:156 msgid "Show sys.path contents..." msgstr "Contenidos del sys.path" #: spyder/plugins/console.py:158 msgid "Show (read-only) sys.path" msgstr "Muestra los contenidos del sys.path en modo lectura" #: spyder/plugins/console.py:161 msgid "Buffer..." msgstr "Mostrar líneas..." #: spyder/plugins/console.py:162 spyder/plugins/history.py:43 msgid "Set maximum line count" msgstr "Establece el máximo número de líneas a mostrar en la terminal" #: spyder/plugins/console.py:165 msgid "External editor path..." msgstr "Ruta del editor externo..." #: spyder/plugins/console.py:166 msgid "Set external editor executable path" msgstr "Establece la ruta del editor externo" #: spyder/plugins/console.py:169 spyder/plugins/editor.py:149 #: spyder/plugins/help.py:152 spyder/plugins/help.py:355 #: spyder/plugins/history.py:46 spyder/plugins/history.py:157 msgid "Wrap lines" msgstr "Ajuste de línea automático" #: spyder/plugins/console.py:172 spyder/plugins/editor.py:185 #: spyder/plugins/ipythonconsole.py:300 msgid "Display balloon tips" msgstr "Mostrar globos de sugerencias" #: spyder/plugins/console.py:176 spyder/plugins/editor.py:179 msgid "Automatic code completion" msgstr "Completar código automáticamente" #: spyder/plugins/console.py:180 spyder/plugins/editor.py:183 msgid "Enter key selects completion" msgstr "La tecla Enter selecciona el resultado a completar" #: spyder/plugins/console.py:185 msgid "Internal console settings" msgstr "Opciones" #: spyder/plugins/console.py:221 msgid "" "Spyder has encountered a problem.
Sorry for the inconvenience." "

You can automatically submit this error to our Github issues tracker." "

Note: You need a Github account for that." msgstr "" "Spyder ha encontrado un problema.
Disculpa las molestias." "

Puedes enviar automáticamente este error a nuestro rastreador de " "problemas en Github.
Necesitas una cuenta de Github para esto." #: spyder/plugins/console.py:231 msgid "Submit to Github" msgstr "Enviar a Github" #: spyder/plugins/console.py:283 msgid "Run Python script" msgstr "Ejecutar archivo de Python" #: spyder/plugins/console.py:284 spyder/widgets/explorer.py:796 msgid "Python scripts" msgstr "Archivos de Python" #: spyder/plugins/console.py:329 msgid "Buffer" msgstr "Mostrar" #: spyder/plugins/console.py:330 msgid "Maximum line count" msgstr "Máximo número de líneas a mostrar" #: spyder/plugins/console.py:340 msgid "External editor" msgstr "Editor externo" #: spyder/plugins/console.py:341 msgid "External editor executable path:" msgstr "Ruta ejecutable del editor externo:" #: spyder/plugins/editor.py:59 msgid "Manipulate Jupyter notebooks on the Editor" msgstr "Manipular notebooks de Jupyter en el Editor" #: spyder/plugins/editor.py:111 msgid "Edit template for new modules" msgstr "Editar la plantilla para nuevos módulos" #: spyder/plugins/editor.py:116 msgid "Show tab bar" msgstr "Mostrar barra de pestañas" #: spyder/plugins/editor.py:122 spyder/plugins/editor.py:199 #: spyder/plugins/help.py:151 spyder/plugins/history.py:45 #: spyder/plugins/ipythonconsole.py:332 msgid "Source code" msgstr "Código fuente" #: spyder/plugins/editor.py:123 msgid "Show line numbers" msgstr "Mostrar números de líneas" #: spyder/plugins/editor.py:124 spyder/plugins/editor.py:985 msgid "Show blank spaces" msgstr "Mostrar espacios en blanco" #: spyder/plugins/editor.py:125 msgid "Show vertical line after" msgstr "Mostrar una línea vertical después de" #: spyder/plugins/editor.py:126 msgid "characters" msgstr "caracteres" #: spyder/plugins/editor.py:133 msgid "Highlight current line" msgstr "Resaltar la línea actual" #: spyder/plugins/editor.py:135 msgid "Highlight current cell" msgstr "Resaltar la celda actual" #: spyder/plugins/editor.py:137 msgid "Highlight occurrences after" msgstr "Resaltar ocurrencias después de" #: spyder/plugins/editor.py:169 msgid "Save all files before running script" msgstr "Guardar todo antes de ejecutar un archivo" #: spyder/plugins/editor.py:172 msgid "Run selection" msgstr "Ejecutar selección" #: spyder/plugins/editor.py:173 msgid "Maintain focus in the Editor after running cells or selections" msgstr "Mantener el foco en el Editor después de ejecutar celdas o selecciones" #: spyder/plugins/editor.py:176 msgid "Introspection" msgstr "Introspección" #: spyder/plugins/editor.py:181 msgid "Case sensitive code completion" msgstr "Diferenciar entre mayúsculas y minúsculas al completar código" #: spyder/plugins/editor.py:186 msgid "Link to object definition" msgstr "Enlazar a la definición de un objeto" #: spyder/plugins/editor.py:188 msgid "" "If this option is enabled, clicking on an object\n" "name (left-click + Ctrl key) will go this object\n" "definition (if resolved)." msgstr "" "Si está opción está activada, al hacer click\n" "sobre el nombre de un objeto (click-izquierdo +\n" "la tecla Ctrl), el Editor se ubicará en la definición\n" "del mismo (de poder resolverse el nombre)." #: spyder/plugins/editor.py:192 msgid "" "Warning:
The Python module rope is not installed on this " "computer: calltips, code completion and go-to-definition features won't be " "available." msgstr "" "Advertencia:
El módulo de Pythonrope no está instalado en " "este computador. Por tanto el completado de código, el ir a la definición de " "una función o método y los globos de sugerencias se encontrarán desactivados." #: spyder/plugins/editor.py:200 msgid "Automatic insertion of parentheses, braces and brackets" msgstr "Inserción automática de paréntesis, llaves y corchetes" #: spyder/plugins/editor.py:203 msgid "Automatic insertion of closing quotes" msgstr "Inserción automática de comillas" #: spyder/plugins/editor.py:205 msgid "Automatic insertion of colons after 'for', 'if', 'def', etc" msgstr "Inserción automática de ':' después de 'for', 'if', 'def', etc" #: spyder/plugins/editor.py:208 msgid "Automatic indentation after 'else', 'elif', etc." msgstr "Indentación automática después de 'else', 'elif', etc." #: spyder/plugins/editor.py:210 msgid "Indentation characters: " msgstr "Caracteres de indentación:" #: spyder/plugins/editor.py:211 msgid "2 spaces" msgstr "2 espacios" #: spyder/plugins/editor.py:212 msgid "3 spaces" msgstr "3 espacios" #: spyder/plugins/editor.py:213 msgid "4 spaces" msgstr "4 espacios" #: spyder/plugins/editor.py:214 msgid "5 spaces" msgstr "5 espacios" #: spyder/plugins/editor.py:215 msgid "6 spaces" msgstr "6 espacios" #: spyder/plugins/editor.py:216 msgid "7 spaces" msgstr "7 espacios" #: spyder/plugins/editor.py:217 msgid "8 spaces" msgstr "8 espacios" #: spyder/plugins/editor.py:218 msgid "Tabulations" msgstr "Tabulaciones" #: spyder/plugins/editor.py:219 msgid "Tab stop width:" msgstr "Ancho de las tabulaciones:" #: spyder/plugins/editor.py:219 msgid "spaces" msgstr "espacios" #: spyder/plugins/editor.py:231 msgid "Tab always indent" msgstr "Siempre indentar con la tecla Tab" #: spyder/plugins/editor.py:233 msgid "" "If enabled, pressing Tab will always indent,\n" "even when the cursor is not at the beginning\n" "of a line (when this option is enabled, code\n" "completion may be triggered using the alternate\n" "shortcut: Ctrl+Space)" msgstr "" "Si esta opción está activada, el oprimir Tab\n" "siempre indentará el código, aún cuando el\n" "cursor no esté al principio de una línea\n" "(de seleccionar esta opción, se puede usar\n" "la combinación de teclas Ctrl+Espacio para\n" "activar el completado de código)" #: spyder/plugins/editor.py:238 msgid "Intelligent backspace" msgstr "Tecla de retroceso (\"backspace\") inteligente" #: spyder/plugins/editor.py:240 msgid "Automatically remove trailing spaces when saving files" msgstr "Eliminar automáticamente espacios en blanco al guardar un archivo" #: spyder/plugins/editor.py:244 msgid "Analysis" msgstr "Análisis" #: spyder/plugins/editor.py:246 msgid "(Refer to the {} page)" msgstr "(Mirar la página {})" #: spyder/plugins/editor.py:251 msgid "Real-time code analysis" msgstr "Análisis del código en tiempo real en el Editor" #: spyder/plugins/editor.py:253 msgid "" "

If enabled, Python source code will be analyzed using pyflakes, lines " "containing errors or warnings will be highlighted.

Note: add " "analysis:ignore in a comment to ignore code analysis warnings.

" msgstr "" "

Si esta opción está activada, los archivos de Python serán analizados " "automáticamente y y las líneas que contengan errores o advertencias serán " "resaltadas.

Nota: Puede añadir analysis:ignore en un " "comentario para ignorar estas advertencias.

" #: spyder/plugins/editor.py:261 msgid "Code analysis requires pyflakes %s+" msgstr "El análisis del código requiere pyflakes %s+" #: spyder/plugins/editor.py:263 msgid "Real-time code style analysis" msgstr "Análisis de estilo del código en el Editor" #: spyder/plugins/editor.py:265 msgid "" "

If enabled, Python source code will be analyzed using pycodestyle, lines " "that are not following PEP8 style guide will be highlighted.

Note: add analysis:ignore in a comment to ignore style analysis " "warnings.

" msgstr "" "

Si activado, el código fuente de Python será analizado usando " "pycodestyle, las líneas que no sigan la guía de estilo PEP8 se resaltarán.

Nota: add analysis:ignore en un comentario para ignorar " "las advertencias de análisis de estilo.

" #: spyder/plugins/editor.py:272 msgid "" "Code annotations (TODO, FIXME, XXX, HINT, TIP, @todo, HACK, BUG, " "OPTIMIZE, !!!, ???)" msgstr "" "Anotaciones de código (TODO, FIXME, XXX, HINT, TIP, @todo, HACK, BUG, " "OPTIMIZE, !!!, ???)" #: spyder/plugins/editor.py:276 msgid "Perform analysis when saving file and every" msgstr "Realizar los análisis al guardar el archivo y cada" #: spyder/plugins/editor.py:280 msgid "Perform analysis only when saving file" msgstr "Realizar análisis sólo cuando se guarde el archivo" #: spyder/plugins/editor.py:339 msgid "End-of-line characters" msgstr "Caracteres de fin de línea" #: spyder/plugins/editor.py:340 msgid "" "When opening a text file containing mixed end-of-line characters (this may " "raise syntax errors in the consoles on Windows platforms), Spyder may fix " "the file automatically." msgstr "" "Cuando se abra un archivo de texto que contenga varios tipos de caracteres " "de fin de línea (lo cual puede dar lugar a errores en Windows), Spyder puede " "arreglar el archivo automáticamente." #: spyder/plugins/editor.py:346 msgid "Fix automatically and show warning message box" msgstr "Arreglar automáticamente y mostrar un mensaje de advertencia" #: spyder/plugins/editor.py:357 spyder/plugins/ipythonconsole.py:573 #: spyder/plugins/variableexplorer.py:35 msgid "Display" msgstr "Visualización" #: spyder/plugins/editor.py:359 msgid "Code Introspection/Analysis" msgstr "Análisis e introspección de código" #: spyder/plugins/editor.py:362 msgid "Advanced settings" msgstr "Opciones avanzadas" #: spyder/plugins/editor.py:644 msgid "&New file..." msgstr "&Nuevo" #: spyder/plugins/editor.py:645 spyder/widgets/explorer.py:773 #: spyder/widgets/explorer.py:780 msgid "New file" msgstr "Nuevo archivo" #: spyder/plugins/editor.py:654 msgid "O&pen last closed" msgstr "Abrir el último cerrado" #: spyder/plugins/editor.py:655 msgid "Open last closed" msgstr "Abrir el último archivo cerrado" #: spyder/plugins/editor.py:661 msgid "&Open..." msgstr "&Abrir" #: spyder/plugins/editor.py:662 spyder/plugins/editor.py:1870 #: spyder/plugins/editor.py:1876 msgid "Open file" msgstr "Abrir archivo" #: spyder/plugins/editor.py:668 msgid "&Revert" msgstr "&Restaurar" #: spyder/plugins/editor.py:669 msgid "Revert file from disk" msgstr "Restaurar archivo desde el disco" #: spyder/plugins/editor.py:672 msgid "&Save" msgstr "&Guardar" #: spyder/plugins/editor.py:673 spyder/widgets/editor.py:1681 msgid "Save file" msgstr "Guardar archivo" #: spyder/plugins/editor.py:679 msgid "Sav&e all" msgstr "Guardar t&odo" #: spyder/plugins/editor.py:680 msgid "Save all files" msgstr "Guardar todos los archivos" #: spyder/plugins/editor.py:686 msgid "Save &as..." msgstr "Gu&ardar como..." #: spyder/plugins/editor.py:687 msgid "Save current file as..." msgstr "Guardar el archivo actual como..." #: spyder/plugins/editor.py:692 msgid "Save copy as..." msgstr "Guardar copia como..." #: spyder/plugins/editor.py:693 msgid "Save copy of current file as..." msgstr "Guardar copia del archivo actual como..." #: spyder/plugins/editor.py:696 spyder/plugins/editor.py:697 msgid "Print preview..." msgstr "Presentación preliminar..." #: spyder/plugins/editor.py:698 msgid "&Print..." msgstr "Im&primir" #: spyder/plugins/editor.py:699 msgid "Print current file..." msgstr "Imprimir el archivo actual..." #: spyder/plugins/editor.py:702 msgid "&Close" msgstr "&Cerrar" #: spyder/plugins/editor.py:703 msgid "Close current file" msgstr "Cerrar el archivo actual" #: spyder/plugins/editor.py:706 msgid "C&lose all" msgstr "C&errar todo" #: spyder/plugins/editor.py:707 msgid "Close all opened files" msgstr "Cerrar todos los archivos abiertos" #: spyder/plugins/editor.py:714 msgid "&Find text" msgstr "&Buscar texto" #: spyder/plugins/editor.py:720 msgid "Find &next" msgstr "Buscar &siguiente" #: spyder/plugins/editor.py:726 msgid "Find &previous" msgstr "Buscar &anterior" #: spyder/plugins/editor.py:732 msgid "&Replace text" msgstr "&Reemplazar texto" #: spyder/plugins/editor.py:741 msgid "Set/Clear breakpoint" msgstr "Añadir o eliminar un punto de interrupción" #: spyder/plugins/editor.py:748 msgid "Set/Edit conditional breakpoint" msgstr "Añadir o editar un punto de interrupción condicional" #: spyder/plugins/editor.py:755 msgid "Clear breakpoints in all files" msgstr "Eliminar los puntos de interrupción de todos los archivos" #: spyder/plugins/editor.py:757 msgid "Debug with winpdb" msgstr "Depurar con winpdb" #: spyder/plugins/editor.py:764 msgid "Debug file" msgstr "Depurar archivo" #: spyder/plugins/editor.py:769 msgid "Step" msgstr "Ejecutar línea" #: spyder/plugins/editor.py:770 msgid "Run current line" msgstr "Ejecutar la línea seleccionada" #: spyder/plugins/editor.py:775 msgid "Continue" msgstr "Continuar" #: spyder/plugins/editor.py:777 msgid "Continue execution until next breakpoint" msgstr "Continuar con la ejecución hasta el siguiente punto de interrupción" #: spyder/plugins/editor.py:782 msgid "Step Into" msgstr "Ingresar en la función/método" #: spyder/plugins/editor.py:784 msgid "Step into function or method of current line" msgstr "Ingresar en la función o método de la línea actual" #: spyder/plugins/editor.py:789 msgid "Step Return" msgstr "Salir de la función/método" #: spyder/plugins/editor.py:791 msgid "Run until current function or method returns" msgstr "Ejecutar hasta que la función o método actual termine" #: spyder/plugins/editor.py:796 spyder/widgets/findinfiles.py:281 #: spyder/widgets/ipythonconsole/client.py:357 msgid "Stop" msgstr "Detener" #: spyder/plugins/editor.py:797 msgid "Stop debugging" msgstr "Detener la depuración" #: spyder/plugins/editor.py:804 msgid "Run file" msgstr "Ejecutar archivo" #: spyder/plugins/editor.py:809 msgid "&Configuration per file..." msgstr "&Configuración por archivo..." #: spyder/plugins/editor.py:811 msgid "Run settings" msgstr "Ajustes de ejecución" #: spyder/plugins/editor.py:817 msgid "Re-run &last script" msgstr "Ejecutar de &nuevo el último archivo" #: spyder/plugins/editor.py:819 msgid "Run again last file" msgstr "Ejecutar de nuevo el mismo archivo" #: spyder/plugins/editor.py:825 spyder/widgets/sourcecode/codeeditor.py:2708 msgid "Run &selection or current line" msgstr "Ejecutar la &selección o la línea actual" #: spyder/plugins/editor.py:828 msgid "Run selection or current line" msgstr "Ejecutar la &selección o línea actual" #: spyder/plugins/editor.py:836 spyder/widgets/sourcecode/codeeditor.py:2696 msgid "Run cell" msgstr "Ejecutar la celda" #: spyder/plugins/editor.py:839 msgid "" "Run current cell (Ctrl+Enter)\n" "[Use #%% to create cells]" msgstr "" "Ejecutar la celda actual (Ctrl+Enter)\n" "[Usar #%% para crear celdas]" #: spyder/plugins/editor.py:845 spyder/widgets/sourcecode/codeeditor.py:2700 msgid "Run cell and advance" msgstr "Ejecutar la celda y avanzar" #: spyder/plugins/editor.py:848 msgid "Run current cell and go to the next one (Shift+Enter)" msgstr "Ejecutar la celda actual y avanzar a la siguiente (Shift+Enter)" #: spyder/plugins/editor.py:854 spyder/widgets/sourcecode/codeeditor.py:2704 msgid "Re-run last cell" msgstr "Ejecutar de nuevo la última celda" #: spyder/plugins/editor.py:855 msgid "Re run last cell " msgstr "Ejecutar de nuevo la última celda " #: spyder/plugins/editor.py:865 msgid "Show todo list" msgstr "Mostrar lista de TODO's" #: spyder/plugins/editor.py:866 msgid "" "Show comments list (TODO/FIXME/XXX/HINT/TIP/@todo/HACK/BUG/OPTIMIZE/!!!/???)" msgstr "" "Mostrar la lista de comentarios (TODO/FIXME/XXX/HINT/TIP/@todo/HACK/BUG/" "OPTIMIZE/!!!/???)" #: spyder/plugins/editor.py:874 msgid "Show warning/error list" msgstr "" "Mostrar la lista de errores\n" "y advertencias" #: spyder/plugins/editor.py:875 msgid "Show code analysis warnings/errors" msgstr "" "Mostrar errores o advertencias\n" "del análisis del código" #: spyder/plugins/editor.py:881 msgid "Previous warning/error" msgstr "Anterior advertencia o error" #: spyder/plugins/editor.py:882 msgid "Go to previous code analysis warning/error" msgstr "" "Ir a la línea anterior de\n" "advertencia o error" #: spyder/plugins/editor.py:885 msgid "Next warning/error" msgstr "Siguiente advertencia o error" #: spyder/plugins/editor.py:886 msgid "Go to next code analysis warning/error" msgstr "" "Ir a la próxima línea de\n" "advertencia o error" #: spyder/plugins/editor.py:890 msgid "Last edit location" msgstr "Última posición de edición" #: spyder/plugins/editor.py:891 msgid "Go to last edit location" msgstr "" "Ir a la anterior posición\n" "de edición" #: spyder/plugins/editor.py:899 msgid "Previous cursor position" msgstr "Anterior posición del cursor" #: spyder/plugins/editor.py:900 msgid "Go to previous cursor position" msgstr "Ir a la anterior posición del cursor" #: spyder/plugins/editor.py:908 msgid "Next cursor position" msgstr "Siguiente posición del cursor" #: spyder/plugins/editor.py:909 msgid "Go to next cursor position" msgstr "Ir a la siguiente posición del cursor" #: spyder/plugins/editor.py:919 spyder/widgets/sourcecode/codeeditor.py:2680 msgid "Comment" msgstr "Comentar" #: spyder/plugins/editor.py:919 spyder/widgets/sourcecode/codeeditor.py:2680 msgid "Uncomment" msgstr "Descomentar" #: spyder/plugins/editor.py:920 msgid "Comment current line or selection" msgstr "Comentar la línea o selección actual" #: spyder/plugins/editor.py:924 msgid "Add &block comment" msgstr "Añadir comentario de &bloque" #: spyder/plugins/editor.py:925 msgid "Add block comment around current line or selection" msgstr "" "Añadir un comentario de bloque alrededor de la línea o selección actual" #: spyder/plugins/editor.py:931 msgid "R&emove block comment" msgstr "&Eliminar comentario de bloque" #: spyder/plugins/editor.py:932 msgid "Remove comment block around current line or selection" msgstr "Eliminar comentario de bloque alrededor de la línea o selección actual" #: spyder/plugins/editor.py:943 msgid "Indent" msgstr "Indentar" #: spyder/plugins/editor.py:944 msgid "Indent current line or selection" msgstr "Indentar la línea o selección actual" #: spyder/plugins/editor.py:947 msgid "Unindent" msgstr "Quitar indentación" #: spyder/plugins/editor.py:948 msgid "Unindent current line or selection" msgstr "Quitar indentación de la línea o selección actual" #: spyder/plugins/editor.py:952 msgid "Toggle Uppercase" msgstr "Cambiar a mayúsculas" #: spyder/plugins/editor.py:953 msgid "Change to uppercase current line or selection" msgstr "Cambiar a mayúsculas la línea o selección actual" #: spyder/plugins/editor.py:959 msgid "Toggle Lowercase" msgstr "Cambiar a minúsculas" #: spyder/plugins/editor.py:960 msgid "Change to lowercase current line or selection" msgstr "Cambiar a minúsculas la línea o selección actual" #: spyder/plugins/editor.py:967 msgid "Carriage return and line feed (Windows)" msgstr "Retorno de carro y salto de línea (Windows)" #: spyder/plugins/editor.py:970 msgid "Line feed (UNIX)" msgstr "Salto de línea (UNIX)" #: spyder/plugins/editor.py:973 msgid "Carriage return (Mac)" msgstr "Retorno de carro (Mac)" #: spyder/plugins/editor.py:979 msgid "Convert end-of-line characters" msgstr "Convertir caracteres de fin de línea" #: spyder/plugins/editor.py:983 msgid "Remove trailing spaces" msgstr "Eliminar espacios en blanco" #: spyder/plugins/editor.py:987 msgid "Fix indentation" msgstr "Corregir la indentación" #: spyder/plugins/editor.py:988 msgid "Replace tab characters by space characters" msgstr "Reemplazar caracteres de tabulación por espacios" #: spyder/plugins/editor.py:991 msgid "Go to line..." msgstr "Ir a la línea..." #: spyder/plugins/editor.py:999 msgid "Set console working directory" msgstr "Establecer directorio de trabajo" #: spyder/plugins/editor.py:1001 msgid "" "Set current console (and file explorer) working directory to current script " "directory" msgstr "" "Fija el directorio de trabajo para la terminal actual como el directorio del " "archivo actual" #: spyder/plugins/editor.py:1006 msgid "Maximum number of recent files..." msgstr "Máximo número de archivos recientes..." #: spyder/plugins/editor.py:1009 msgid "Clear recent files list" msgstr "Limpiar la lista de archivos recientes" #: spyder/plugins/editor.py:1009 spyder/plugins/projects.py:102 msgid "Clear this list" msgstr "Limpiar esta lista" #: spyder/plugins/editor.py:1013 msgid "Open &recent" msgstr "Abrir &reciente" #: spyder/plugins/editor.py:1678 msgid "Spyder Editor" msgstr "Editor de Spyder" #: spyder/plugins/editor.py:1679 msgid "This is a temporary script file." msgstr "Este es un archivo temporal" #: spyder/plugins/editor.py:1748 msgid "untitled" msgstr "Sin título " #: spyder/plugins/editor.py:1820 msgid "Maximum number of recent files" msgstr "Máximo número de archivos recientes" #: spyder/plugins/editor.py:1966 msgid "Printing..." msgstr "Imprimir..." #: spyder/plugins/explorer.py:54 msgid "File explorer" msgstr "Explorador de archivos" #: spyder/plugins/findinfiles.py:119 spyder/widgets/findinfiles.py:829 msgid "Find in files" msgstr "Buscar en archivos" #: spyder/plugins/findinfiles.py:143 msgid "&Find in files" msgstr "Bus&car en archivos" #: spyder/plugins/findinfiles.py:146 msgid "Search text in multiple files" msgstr "Buscar en varios archivos a la vez" #: spyder/plugins/help.py:43 msgid "Show help for objects in the Editor and Consoles in a dedicated pane" msgstr "Mostrar ayuda para los objetos del Editor y las terminales" #: spyder/plugins/help.py:109 msgid "Automatic connections" msgstr "Conexiones automáticas" #: spyder/plugins/help.py:110 msgid "" "This pane can automatically show an object's help information after a left " "parenthesis is written next to it. Below you can decide to which plugin you " "want to connect it to turn on this feature." msgstr "" "Este panel puede mostrar automáticamente la ayuda de un objeto después de " "escribir un paréntesis junto al mismo. A continuación puede decidir a que " "panel desea conectarlo para activar esta característica." #: spyder/plugins/help.py:122 msgid "" "This feature requires the Rope or Jedi libraries.\n" "It seems you don't have either installed." msgstr "" "Esta característica requiere las librerías Rope o Jedi.\n" "Al parecer no tiene ninguna instalada." #: spyder/plugins/help.py:125 msgid "IPython Console" msgstr "Terminal de IPython" #: spyder/plugins/help.py:135 msgid "Additional features" msgstr "Características adicionales" #: spyder/plugins/help.py:136 msgid "Render mathematical equations" msgstr "Renderizar ecuaciones matemáticas" #: spyder/plugins/help.py:142 msgid "This feature requires Sphinx 1.1 or superior." msgstr "Esta característica requiere Sphinx 1.1 o superior." #: spyder/plugins/help.py:143 msgid "Sphinx %s is currently installed." msgstr "Sphinx %s está instalado actualmente." #: spyder/plugins/help.py:304 msgid "No further documentation available" msgstr "No existe más documentación disponible" #: spyder/plugins/help.py:342 msgid "No documentation available" msgstr "No existe documentación disponible" #: spyder/plugins/help.py:373 msgid "Source" msgstr "Origen" #: spyder/plugins/help.py:380 spyder/plugins/runconfig.py:170 #: spyder/plugins/runconfig.py:486 spyder/widgets/ipythonconsole/client.py:291 msgid "Console" msgstr "Terminal" #: spyder/plugins/help.py:388 msgid "Object" msgstr "Objeto" #: spyder/plugins/help.py:402 msgid "Plain Text" msgstr "Texto plano" #: spyder/plugins/help.py:406 msgid "Show Source" msgstr "Mostrar código fuente" #: spyder/plugins/help.py:410 msgid "Rich Text" msgstr "Texto enriquecido" #: spyder/plugins/help.py:420 msgid "Automatic import" msgstr "Importar automáticamente" #: spyder/plugins/help.py:432 spyder/plugins/history.py:106 #: spyder/widgets/editor.py:720 spyder/widgets/explorer.py:1187 #: spyder/widgets/ipythonconsole/client.py:381 #: spyder/widgets/variableexplorer/namespacebrowser.py:148 msgid "Options" msgstr "Opciones" #: spyder/plugins/help.py:687 msgid "" "Here you can get help of any object by pressing %s in front of it, either on " "the Editor or the Console.%sHelp can also be shown automatically after " "writing a left parenthesis next to an object. You can activate this behavior " "in %s." msgstr "" "En este panel es posible obtener la ayuda de cualquier objeto al oprimir %s " "estando al frente del mismo, bien sea en el Editor o en la Terminal.%sEsta " "ayuda también se puede mostrar automáticamente después de escribir un " "paréntesis junto a un objeto. Este comportamiento puede activarse en %s." #: spyder/plugins/help.py:693 msgid "Preferences > Help" msgstr "Preferencias > Ayuda" #: spyder/plugins/help.py:700 msgid "Usage" msgstr "Uso" #: spyder/plugins/help.py:701 msgid "New to Spyder? Read our" msgstr "Nuevo en Spyder? Lee nuestro" #: spyder/plugins/help.py:702 msgid "tutorial" msgstr "tutorial" #: spyder/plugins/help.py:709 msgid "" "Please consider installing Sphinx to get documentation rendered in rich text." msgstr "" "Por favor considere instalar Sphinx para obtener la documentación en texto " "enriquecido " #: spyder/plugins/help.py:878 msgid "Lock" msgstr "Bloquear" #: spyder/plugins/help.py:878 msgid "Unlock" msgstr "Desbloquear" #: spyder/plugins/help.py:922 msgid "" "The following error occured when calling Sphinx %s.
Incompatible " "Sphinx version or doc string decoding failed.

Error message:
%s" msgstr "" "Ocurrió el siguiente error cuando se trató de utilizar Sphinx %s." "
Ello se debe a una versión incompatible de Sphinx o bien a que no fue " "posible leer la documentación solicitada.

Mensaje de error:
%s" #: spyder/plugins/help.py:966 msgid "No source code available." msgstr "No está disponible el código fuente" #: spyder/plugins/history.py:39 msgid "Settings" msgstr "Ajustes" #: spyder/plugins/history.py:41 msgid " entries" msgstr "entradas" #: spyder/plugins/history.py:41 msgid "History depth: " msgstr "Longitud del historial" #: spyder/plugins/history.py:48 msgid "Scroll automatically to last entry" msgstr "Desplazarse automáticamente a la última entrada" #: spyder/plugins/history.py:126 msgid "History log" msgstr "Historial de comandos" #: spyder/plugins/history.py:153 msgid "History..." msgstr "Historial..." #: spyder/plugins/history.py:155 msgid "Set history maximum entries" msgstr "Establece el máximo número de entradas a almacenar" #: spyder/plugins/history.py:260 msgid "History" msgstr "Historial" #: spyder/plugins/history.py:261 msgid "Maximum entries" msgstr "Máximo número de entradas" #: spyder/plugins/ipythonconsole.py:65 msgid "Symbolic mathematics in the IPython Console" msgstr "Matemática simbólica en la terminal de IPython" #: spyder/plugins/ipythonconsole.py:69 msgid "Run Cython files in the IPython Console" msgstr "Ejecute archivos de Cython en la terminal de IPython" #: spyder/plugins/ipythonconsole.py:73 msgid "Integrate the IPython console" msgstr "Integración con la Terminal de IPython" #: spyder/plugins/ipythonconsole.py:77 msgid "IPython interactive python environment" msgstr "Entorno interactivo IPython" #: spyder/plugins/ipythonconsole.py:128 msgid "" "The authenticity of host %s can't be established. Are you sure you " "want to continue connecting?" msgstr "" "La autenticidad del servidor %s no puede ser establecida. ¿Está " "seguro de que desea continuar conectándose?" #: spyder/plugins/ipythonconsole.py:140 msgid "The authenticity of the host can't be established" msgstr "La autenticidad del servidor no puede ser establecida" #: spyder/plugins/ipythonconsole.py:147 msgid "Tunnel '%s' failed to start" msgstr "El túnel '%s' falló en ser iniciado" #: spyder/plugins/ipythonconsole.py:152 msgid "Could not connect to remote host" msgstr "No fue posible conectarse al servidor remoto" #: spyder/plugins/ipythonconsole.py:169 spyder/plugins/ipythonconsole.py:799 msgid "Connect to an existing kernel" msgstr "Conectarse a un núcleo existente" #: spyder/plugins/ipythonconsole.py:171 msgid "" "Please enter the connection info of the kernel you want to connect to. For " "that you can either select its JSON connection file using the Browse button, or write directly its id, in case it's a local kernel (for " "example kernel-3764.json or just 3764)." msgstr "" "Por favor introduzca la información de conexión del núcleo al cual desea " "conectarse. Para ello puede seleccionar su archivo de conexión JSON, usando " "el botón Seleccionar, o escribir directamente su id, en caso de que " "sea un núcleo local (por ejemplo, kernel-3764.json o sólo 3764)" #: spyder/plugins/ipythonconsole.py:182 msgid "Connection info:" msgstr "Información de conexión:" #: spyder/plugins/ipythonconsole.py:184 msgid "Path to connection file or kernel id" msgstr "Ruta al archivo de conexión o id del núcleo" #: spyder/plugins/ipythonconsole.py:186 spyder/plugins/ipythonconsole.py:203 msgid "Browse" msgstr "Seleccionar" #: spyder/plugins/ipythonconsole.py:195 msgid "This is a remote kernel" msgstr "Este es un núcleo remoto" #: spyder/plugins/ipythonconsole.py:199 msgid "username@hostname:port" msgstr "usuario@servidor:puerto" #: spyder/plugins/ipythonconsole.py:202 msgid "Path to ssh key file" msgstr "Ruta al archivo de clave ssh" #: spyder/plugins/ipythonconsole.py:211 msgid "Password or ssh key passphrase" msgstr "Contraseña o frase de contraseña de la clave ssh" #: spyder/plugins/ipythonconsole.py:215 msgid "Host name" msgstr "Servidor" #: spyder/plugins/ipythonconsole.py:216 msgid "Ssh key" msgstr "Clave ssh" #: spyder/plugins/ipythonconsole.py:217 msgid "Password" msgstr "Contraseña" #: spyder/plugins/ipythonconsole.py:246 msgid "Open connection file" msgstr "Abrir un archivo de conexión" #: spyder/plugins/ipythonconsole.py:251 msgid "Select ssh key" msgstr "Seleccionar clave ssh" #: spyder/plugins/ipythonconsole.py:284 spyder/plugins/ipythonconsole.py:734 msgid "IPython console" msgstr "Terminal de IPython" #: spyder/plugins/ipythonconsole.py:291 msgid "Display initial banner" msgstr "Mostrar el banner inicial" #: spyder/plugins/ipythonconsole.py:292 msgid "" "This option lets you hide the message shown at\n" "the top of the console when it's opened." msgstr "" "Esta opción le permite ocultar el mensaje que \n" "aparece al principio de la terminal cuando se abre\n" "por primera vez." #: spyder/plugins/ipythonconsole.py:294 msgid "Use a pager to display additional text inside the console" msgstr "Usar un paginador para mostrar textos dentro de la terminal" #: spyder/plugins/ipythonconsole.py:296 msgid "" "Useful if you don't want to fill the console with long help or completion " "texts.\n" "Note: Use the Q key to get out of the pager." msgstr "" "Es útil si no desea llenar la terminal con largos textos de ayuda.\n" "Nota: Debe usar la tecla Q para salir del paginador" #: spyder/plugins/ipythonconsole.py:301 msgid "Ask for confirmation before closing" msgstr "Mostrar un diálogo de confirmación antes de cerrar una terminal" #: spyder/plugins/ipythonconsole.py:304 msgid "Ask for confirmation before removing all user-defined variables" msgstr "" "Preguntar antes de eliminar todas las variables definidas por el usuario" #: spyder/plugins/ipythonconsole.py:307 msgid "" "This option lets you hide the warning message shown\n" "when resetting the namespace from Spyder." msgstr "" "Esta opción le permite ocultar el mensaje que \n" "aparece cuando se van a eliminar todas las \n" "variables definidas por el usuario." #: spyder/plugins/ipythonconsole.py:309 #: spyder/widgets/ipythonconsole/client.py:320 msgid "Show elapsed time" msgstr "Mostrar el tiempo transcurrido" #: spyder/plugins/ipythonconsole.py:320 msgid "Completion Type" msgstr "Tipo de completado" #: spyder/plugins/ipythonconsole.py:321 msgid "Decide what type of completion to use" msgstr "Decidir que tipo de completado utilizar" #: spyder/plugins/ipythonconsole.py:323 msgid "Graphical" msgstr "Gráfico" #: spyder/plugins/ipythonconsole.py:323 msgid "Plain" msgstr "Plano" #: spyder/plugins/ipythonconsole.py:323 msgid "Terminal" msgstr "Terminal" #: spyder/plugins/ipythonconsole.py:324 msgid "Completion:" msgstr "Completado:" #: spyder/plugins/ipythonconsole.py:334 msgid " lines" msgstr "líneas" #: spyder/plugins/ipythonconsole.py:334 msgid "Buffer: " msgstr "Mostrar" #: spyder/plugins/ipythonconsole.py:336 msgid "" "Set the maximum number of lines of text shown in the\n" "console before truncation. Specifying -1 disables it\n" "(not recommended!)" msgstr "" "Establece el máximo número de líneas que se mostrarán\n" "en la terminal en cualquier momento. Si se introduce -1 se\n" "mostrarán todas las líneas (no se recomienda!)" #: spyder/plugins/ipythonconsole.py:345 msgid "Support for graphics (Matplotlib)" msgstr "Soporte para crear gráficas (Matplotlib)" #: spyder/plugins/ipythonconsole.py:346 msgid "Activate support" msgstr "Activar el soporte" #: spyder/plugins/ipythonconsole.py:347 msgid "Automatically load Pylab and NumPy modules" msgstr "Cargar automáticamente los módulos de Pylab y NumPy" #: spyder/plugins/ipythonconsole.py:350 msgid "" "This lets you load graphics support without importing \n" "the commands to do plots. Useful to work with other\n" "plotting libraries different to Matplotlib or to develop \n" "GUIs with Spyder." msgstr "" "Esto le permite cargar el soporte gráfico sin importar\n" "los comandos para crear figuras. Es útil para trabajar con\n" "otras librerías gráficas diferentes a Matplotlib o para\n" "desarrollar interfaces gráficas con Spyder." #: spyder/plugins/ipythonconsole.py:365 msgid "Inline" msgstr "En línea" #: spyder/plugins/ipythonconsole.py:366 msgid "Automatic" msgstr "Automático" #: spyder/plugins/ipythonconsole.py:367 msgid "Graphics backend" msgstr "Salida gráfica:" #: spyder/plugins/ipythonconsole.py:368 msgid "" "Decide how graphics are going to be displayed in the console. If unsure, " "please select %s to put graphics inside the console or %s to " "interact with them (through zooming and panning) in a separate window." msgstr "" "Decidir como se mostrarán las gráficas en la terminal. Si no está seguro, " "por favor seleccione %s para colocar las gráficas en la consola o " "%s para interactuar con ellas (a través de acercamientos y paneos) en " "una ventana aparte." #: spyder/plugins/ipythonconsole.py:388 msgid "Backend:" msgstr "Salida:" #: spyder/plugins/ipythonconsole.py:390 msgid "This option will be applied the next time a console is opened." msgstr "Esta opción será aplicada la próxima vez que una terminal sea abierta." #: spyder/plugins/ipythonconsole.py:401 msgid "Inline backend" msgstr "Salida en línea:" #: spyder/plugins/ipythonconsole.py:402 msgid "Decide how to render the figures created by this backend" msgstr "" "Decida como renderizar las figuras creadas por este tipo de salida gráfica" #: spyder/plugins/ipythonconsole.py:406 msgid "Format:" msgstr "Formato:" #: spyder/plugins/ipythonconsole.py:409 msgid "Resolution:" msgstr "Resolución:" #: spyder/plugins/ipythonconsole.py:409 msgid "dpi" msgstr "dpi" #: spyder/plugins/ipythonconsole.py:411 msgid "Only used when the format is PNG. Default is 72" msgstr "Sólo se usa cuando el formato es PNG. Por defecto es 72." #: spyder/plugins/ipythonconsole.py:414 msgid "Width:" msgstr "Ancho:" #: spyder/plugins/ipythonconsole.py:414 spyder/plugins/ipythonconsole.py:418 msgid "inches" msgstr "pulgadas" #: spyder/plugins/ipythonconsole.py:416 msgid "Default is 6" msgstr "Por defecto es 6" #: spyder/plugins/ipythonconsole.py:418 msgid "Height:" msgstr "Alto:" #: spyder/plugins/ipythonconsole.py:420 msgid "Default is 4" msgstr "Por defecto es 4" #: spyder/plugins/ipythonconsole.py:447 msgid "" "You can run several lines of code when a console is started. Please " "introduce each one separated by commas, for example:
import os, import " "sys" msgstr "" "Se pueden ejecutar varias líneas de código al abrir una terminal. Por favor " "introduzca cada una separada por comas, por ejemplo:
import os, import " "sys" #: spyder/plugins/ipythonconsole.py:453 msgid "Lines:" msgstr "Líneas:" #: spyder/plugins/ipythonconsole.py:462 msgid "Run a file" msgstr "Ejecutar un archivo" #: spyder/plugins/ipythonconsole.py:463 msgid "" "You can also run a whole file at startup instead of just some lines (This is " "similar to have a PYTHONSTARTUP file)." msgstr "" "También se puede ejecutar un archivo completo al inicio, en lugar de unas " "pocas líneas (Esto es similar a tener un archivo PYTHONSTARTUP)." #: spyder/plugins/ipythonconsole.py:467 msgid "Use the following file:" msgstr "Usar el siguiente archivo:" #: spyder/plugins/ipythonconsole.py:481 msgid "Greedy completion" msgstr "Completado ambicioso" #: spyder/plugins/ipythonconsole.py:482 msgid "" "Enable Tab completion on elements of lists, results of function " "calls, etc, without assigning them to a variable.
For example, you " "can get completions on things like li[0].<Tab> or ins." "meth().<Tab>" msgstr "" "Habilita el completado usando la tecla Tab en elementos de listas, " "resultados de llamadas de funciones, etc, sin asignarlos a una " "variable.
De esta forma se pueden obtener sugerencias de completado en " "cosas como li[0].<Tab> o ins.meth().<Tab>" #: spyder/plugins/ipythonconsole.py:490 msgid "Use the greedy completer" msgstr "Usar el completado ambicioso" #: spyder/plugins/ipythonconsole.py:501 msgid "Autocall" msgstr "Autollamar" #: spyder/plugins/ipythonconsole.py:502 msgid "" "Autocall makes IPython automatically call any callable object even if you " "didn't type explicit parentheses.
For example, if you type str 43 " "it becomes str(43) automatically." msgstr "" "Esta opción hace que IPython llame automáticamente cualquier objeto " "\"llamable\" (callable) aún si no se escriben paréntesis a su alrededor." "
Por ejemplo, al escribir str 43, se convertirá automáticamente en " "str(43)." #: spyder/plugins/ipythonconsole.py:509 msgid "Smart" msgstr "Inteligente" #: spyder/plugins/ipythonconsole.py:510 msgid "Full" msgstr "Total" #: spyder/plugins/ipythonconsole.py:511 msgid "Off" msgstr "Desactivado" #: spyder/plugins/ipythonconsole.py:513 msgid "Autocall: " msgstr "Autollamar:" #: spyder/plugins/ipythonconsole.py:514 msgid "" "On %s mode, Autocall is not applied if there are no arguments after " "the callable. On %s mode, all callable objects are automatically " "called (even if no arguments are present)." msgstr "" "En modo %s, Autollamar no se usa si no hay argumentos después del " "objeto llamable. En modo %s, todos los objetos llamables son llamados " "automáticamente (aún si no hay argumentos presentes)." #: spyder/plugins/ipythonconsole.py:526 msgid "Symbolic Mathematics" msgstr "Matemática simbólica" #: spyder/plugins/ipythonconsole.py:527 msgid "" "Perfom symbolic operations in the console (e.g. integrals, derivatives, " "vector calculus, etc) and get the outputs in a beautifully printed style (it " "requires the Sympy module)." msgstr "" "Realice operaciones simbólicas en la terminal (integrales, derivadas o " "cálculo vectorial) y obtenga los resultados en un bello estilo impreso " "(requiere el módulo Sympy)." #: spyder/plugins/ipythonconsole.py:532 msgid "Use symbolic math" msgstr "Usar matemática simbólica" #: spyder/plugins/ipythonconsole.py:533 msgid "" "This option loads the Sympy library to work with.
Please refer to its " "documentation to learn how to use it." msgstr "" "Esta opción carga la librería Sympy para trabajar
con ella. Por favor lea " "su documentación para aprender como usarla." #: spyder/plugins/ipythonconsole.py:543 msgid "Prompts" msgstr "Prompts" #: spyder/plugins/ipythonconsole.py:544 msgid "Modify how Input and Output prompts are shown in the console." msgstr "" "Modifique como se muestran los prompts de entrada y salida en la terminal." #: spyder/plugins/ipythonconsole.py:547 msgid "Input prompt:" msgstr "Prompt de entrada:" #: spyder/plugins/ipythonconsole.py:549 msgid "" "Default is
In [<span class=\"in-prompt-number\">%i</span>]:" msgstr "" "Por defecto es
In [<span class=\"in-prompt-number\">%i</" "span>]:" #: spyder/plugins/ipythonconsole.py:553 msgid "Output prompt:" msgstr "Prompt de salida:" #: spyder/plugins/ipythonconsole.py:555 msgid "" "Default is
Out[<span class=\"out-prompt-number\">%i</span>]:" msgstr "" "Por defecto es
Out[<span class=\"out-prompt-number\">%i</" "span>]:" #: spyder/plugins/ipythonconsole.py:575 msgid "Graphics" msgstr "Gráficas" #: spyder/plugins/ipythonconsole.py:577 msgid "Startup" msgstr "Inicialización" #: spyder/plugins/ipythonconsole.py:604 msgid "" "The directory {} is not writable and it is required to create IPython " "consoles. Please make it writable." msgstr "" "El directorio {} no tiene permisos de escritura, lo cual es requerido para " "crear terminales de IPython. Por favor cambie sus permisos." #: spyder/plugins/ipythonconsole.py:784 msgid "Open an &IPython console" msgstr "Abrir una terminal de IPython" #: spyder/plugins/ipythonconsole.py:791 msgid "Restart kernel" msgstr "Reiniciar el núcleo" #: spyder/plugins/ipythonconsole.py:800 msgid "Open a new IPython console connected to an existing kernel" msgstr "Abrir una nueva terminal de IPython conectada a un núcleo existente" #: spyder/plugins/ipythonconsole.py:803 msgid "Rename tab" msgstr "Renombrar la pestaña" #: spyder/plugins/ipythonconsole.py:928 msgid "" "No IPython console is currently available to run %s.

Please " "open a new one and try again." msgstr "" "No existe un intérprete de IPython para ejecutar %s.

Por favor " "abra uno nuevo e intente otra vez." #: spyder/plugins/ipythonconsole.py:1018 msgid "" "Your Python environment or installation doesn't have the ipykernel " "and cloudpickle modules installed on it. Without these modules is " "not possible for Spyder to create a console for you.

You can install " "them by running in a system terminal:

pip install ipykernel " "cloudpickle

or

conda install ipykernel cloudpickle" msgstr "" "Su entorno o instalación de Python no cuenta con los módulos ipykernel y cloudpickle. Sin estos módulos no es posible para Spyder el " "crear una terminal.

Puede instalarlos al ejecutar en una consola de " "comandos del sistema:

pip install ipykernel cloudpickle

o

conda install ipykernel cloudpickle" #: spyder/plugins/ipythonconsole.py:1295 msgid "Do you want to close this console?" msgstr "¿Desea cerrar esta terminal?" #: spyder/plugins/ipythonconsole.py:1301 msgid "" "Do you want to close all other consoles connected to the same kernel as this " "one?" msgstr "" "¿Desea cerrar todas las otras terminales conectadas al mismo núcleo que ésta?" #: spyder/plugins/ipythonconsole.py:1366 msgid "" "It was not possible to restart the IPython console when switching to this " "project. The error was {0}" msgstr "" "No fue posible reiniciar la terminal de IPython al abrir este proyecto. El " "error fue {0}" #: spyder/plugins/ipythonconsole.py:1467 msgid "" "This error was most probably caused by installing Spyder in a directory with " "non-ascii characters (i.e. characters with tildes, apostrophes or non-latin " "symbols).

To fix it, please reinstall Spyder in a different " "location." msgstr "" "Este error fue causado probablemente por la instalación de Spyder en un " "directorio con caracteres no ascii (es decir, caracteres con tildes, " "apóstrofes o símbolos no latinos). Para solucionarlo, por favor " "reinstale Spyder en un lugar diferente." #: spyder/plugins/ipythonconsole.py:1659 msgid "IPython" msgstr "IPython" #: spyder/plugins/ipythonconsole.py:1660 msgid "Unable to connect to %s" msgstr "No se pudo establecer conexión con `%s`" #: spyder/plugins/ipythonconsole.py:1730 msgid "Connection error" msgstr "Error de conexión" #: spyder/plugins/ipythonconsole.py:1731 msgid "" "Could not open ssh tunnel. The error was:\n" "\n" msgstr "" "No fue posible crear un túnel ssh. El error fue:\n" "\n" #: spyder/plugins/layoutdialog.py:177 msgid "Move Up" msgstr "Mover arriba" #: spyder/plugins/layoutdialog.py:178 msgid "Move Down" msgstr "Mover abajo" #: spyder/plugins/layoutdialog.py:179 msgid "Delete Layout" msgstr "Eliminar disposición" #: spyder/plugins/layoutdialog.py:183 msgid "Layout Display and Order" msgstr "Orden y visualización de las disposiciones" #: spyder/plugins/maininterpreter.py:31 spyder/plugins/maininterpreter.py:66 msgid "Python interpreter" msgstr "Intérprete de Python" #: spyder/plugins/maininterpreter.py:68 msgid "Select the Python interpreter for all Spyder consoles" msgstr "" "Seleccionar el intérprete de Python para todas las terminales de Spyder" #: spyder/plugins/maininterpreter.py:71 msgid "Default (i.e. the same as Spyder's)" msgstr "Por defecto (es decir, el mismo de Spyder)" #: spyder/plugins/maininterpreter.py:74 msgid "Use the following Python interpreter:" msgstr "Usar el siguiente intérprete:" #: spyder/plugins/maininterpreter.py:77 msgid "Executables" msgstr "Ejecutables" #: spyder/plugins/maininterpreter.py:94 msgid "User Module Reloader (UMR)" msgstr "Recargador de Módulos del Usuario (RMU)" #: spyder/plugins/maininterpreter.py:95 msgid "" "UMR forces Python to reload modules which were imported when executing a " "file in a Python or IPython console with the runfile function." msgstr "" "El RMU obliga a Python a recargar los módulos que fueron importados durante " "la ejecución de un archivo en la terminal con la función 'runfile'." #: spyder/plugins/maininterpreter.py:100 msgid "Enable UMR" msgstr "Activar el RMU" #: spyder/plugins/maininterpreter.py:101 msgid "" "This option will enable the User Module Reloader (UMR) in Python/IPython " "consoles. UMR forces Python to reload deeply modules during import when " "running a Python script using the Spyder's builtin function runfile." "

1. UMR may require to restart the console in which it will be " "called (otherwise only newly imported modules will be reloaded when " "executing files).

2. If errors occur when re-running a PyQt-" "based program, please check that the Qt objects are properly destroyed (e.g. " "you may have to use the attribute Qt.WA_DeleteOnClose on your main " "window, using the setAttribute method)" msgstr "" "Esta opción activará el Recargador de Módulos del Usuario (RMU) en las " "terminales de Python y IPython. El RMU obliga a Python a recargar " "profundamente los módulos que fueron importados al ejecutar un archivo de " "Python, usando la función incorporada de Spyder llamada runfile." "

1. El RMU puede requerir que se reinicie la terminal en la " "cual será utilizado (de otra forma, sólo los módulos que fueron importados " "en último lugar serán recargados al ejecutar un archivo).

2. " "Si ocurre algún error al re-ejecutar programas basados en PyQt, por favor " "verifique que los objetos de Qt sean destruidos apropiadamente (por ejemplo, " "puede tener que usar el atributo Qt.WA_DeleteOnClose en su ventana " "principal, utilizando para ello el método setAttribute)." #: spyder/plugins/maininterpreter.py:117 msgid "Show reloaded modules list" msgstr "Mostrar la lista de módulos que fueron recargados" #: spyder/plugins/maininterpreter.py:118 msgid "Please note that these changes will be applied only to new consoles" msgstr "" "Por favor tenga en cuenta que estos cambios sólo se aplicarán a nuevas " "terminales" #: spyder/plugins/maininterpreter.py:122 msgid "Set UMR excluded (not reloaded) modules" msgstr "Establecer la lista de módulos excluidos por el RMU" #: spyder/plugins/maininterpreter.py:150 msgid "" "You selected an invalid Python interpreter for the console so the previous " "interpreter will stay. Please make sure to select a valid one." msgstr "" "Se seleccionó un interprete de Python inválido así que se dejará el " "anterior. Por favor asegúrese de seleccionar un intérprete válido." #: spyder/plugins/maininterpreter.py:175 msgid "" "You selected a Python %d interpreter for the console but Spyder is " "running on Python %d!.

Although this is possible, we recommend " "you to install and run Spyder directly with your selected interpreter, to " "avoid seeing false warnings and errors due to the incompatible syntax " "between these two Python versions." msgstr "" "Usted seleccionó un intérprete de Python %d para la terminal, pero " "Spyder está corriendo bajo Python %d!.

Aunque esto es posible, " "le recomendamos instalar y correr Spyder directamente con el intérprete " "seleccionado, para evitar ver falsos errores y alarmas en el Editor debido a " "la sintaxis incompatible entre estas dos versiones de Python." #: spyder/plugins/maininterpreter.py:186 spyder/plugins/maininterpreter.py:213 #: spyder/plugins/maininterpreter.py:217 msgid "UMR" msgstr "RMU" #: spyder/plugins/maininterpreter.py:187 msgid "Set the list of excluded modules as this: numpy, scipy" msgstr "Establezca la lista de módulos excluidos como: numpy, scipy" #: spyder/plugins/maininterpreter.py:204 msgid "" "You are working with Python 2, this means that you can not import a module " "that contains non-ascii characters." msgstr "" "No es posible importar un módulo con caracteres que no son ascii en Python " "2. Por favor introduzca un módulo diferente." #: spyder/plugins/maininterpreter.py:214 msgid "" "The following modules are not installed on your machine:\n" "%s" msgstr "" "Los siguientes módulos no están instalados en su computador:\n" "%s" #: spyder/plugins/maininterpreter.py:218 msgid "" "Please note that these changes will be applied only to new Python/IPython " "consoles" msgstr "" "Por favor tenga en cuenta que estos cambios sólo se aplicarán a nuevas " "terminales de IPython y Python" #: spyder/plugins/onlinehelp.py:70 msgid "Online help" msgstr "Ayuda en línea" #: spyder/plugins/outlineexplorer.py:49 spyder/widgets/editortools.py:195 msgid "Outline" msgstr "Explorador de código" #: spyder/plugins/projects.py:78 spyder/widgets/projects/explorer.py:112 #: spyder/widgets/projects/explorer.py:126 msgid "Project explorer" msgstr "Explorador de proyectos" #: spyder/plugins/projects.py:90 msgid "New Project..." msgstr "Nuevo proyecto..." #: spyder/plugins/projects.py:93 msgid "Open Project..." msgstr "Abrir proyecto..." #: spyder/plugins/projects.py:96 msgid "Close Project" msgstr "Cerrar proyecto" #: spyder/plugins/projects.py:99 msgid "Delete Project" msgstr "Eliminar proyecto" #: spyder/plugins/projects.py:105 msgid "Project Preferences" msgstr "Preferencias del proyecto" #: spyder/plugins/projects.py:107 msgid "Recent Projects" msgstr "Proyectos recientes" #: spyder/plugins/projects.py:244 msgid "Open project" msgstr "Abrir proyecto" #: spyder/plugins/projects.py:249 msgid "%s is not a Spyder project!" msgstr "%s no es un proyecto de Spyder!" #: spyder/plugins/runconfig.py:29 msgid "Execute in current console" msgstr "Ejecutar en la consola actual" #: spyder/plugins/runconfig.py:30 msgid "Execute in a dedicated console" msgstr "Ejecutar en una consola dedicada" #: spyder/plugins/runconfig.py:31 msgid "Execute in an external system terminal" msgstr "Ejecutar en una terminal de comandos del sistema" #: spyder/plugins/runconfig.py:42 msgid "Always show %s on a first file run" msgstr "Siempre muestre %s en una primera ejecución" #: spyder/plugins/runconfig.py:45 msgid "Remove all variables before execution" msgstr "Eliminar todas las variables antes de la ejecución" #: spyder/plugins/runconfig.py:46 msgid "Directly enter debugging when errors appear" msgstr "Entrar en modo de depuración cuando aparecen errores" #: spyder/plugins/runconfig.py:47 msgid "Interact with the Python console after execution" msgstr "Interactuar con la terminal después de la ejecución" #: spyder/plugins/runconfig.py:49 msgid "The directory of the file being executed" msgstr "El directorio del archivo que se está ejecutando" #: spyder/plugins/runconfig.py:50 spyder/plugins/workingdirectory.py:56 msgid "The current working directory" msgstr "El directorio de trabajo actual" #: spyder/plugins/runconfig.py:51 msgid "The following directory:" msgstr "El siguiente directorio:" #: spyder/plugins/runconfig.py:184 spyder/plugins/runconfig.py:504 msgid "General settings" msgstr "Ajustes generales" #: spyder/plugins/runconfig.py:194 spyder/plugins/runconfig.py:236 msgid "Command line options:" msgstr "Opciones de línea de comandos:" #: spyder/plugins/runconfig.py:202 spyder/plugins/runconfig.py:514 msgid "Working Directory settings" msgstr "Configuración del directorio de trabajo" #: spyder/plugins/runconfig.py:226 spyder/plugins/runconfig.py:548 msgid "External system terminal" msgstr "Terminal de comandos del sistema" #: spyder/plugins/runconfig.py:241 msgid "-u is added to the other options you set here" msgstr "La opción -u se añade a estas opciones" #: spyder/plugins/runconfig.py:250 msgid "this dialog" msgstr "este diálogo" #: spyder/plugins/runconfig.py:315 msgid "Run configuration" msgstr "Opciones de ejecución" #: spyder/plugins/runconfig.py:316 msgid "The following working directory is not valid:
%s" msgstr "El siguiente directorio de trabajo no es válido:
%s" #: spyder/plugins/runconfig.py:394 msgid "Run settings for %s" msgstr "Ajustes de ejecución para %s" #: spyder/plugins/runconfig.py:426 msgid "Select a run configuration:" msgstr "Seleccionar una configuración de ejecución:" #: spyder/plugins/runconfig.py:455 msgid "Run configuration per file" msgstr "Configuración de ejecución por archivo" #: spyder/plugins/runconfig.py:480 msgid "" "The following are the default options for running files.These options may be " "overriden using the Configuration per file entry of the Run " "menu." msgstr "" "A continuación se muestran las opciones predeterminadas para ejecutar " "archivos. Estas opciones se pueden sobre escribir mediante " "laConfiguración por archivo del menú Ejecutar." #: spyder/plugins/runconfig.py:516 msgid "Default working directory is:" msgstr "Directorio de trabajo:" #: spyder/plugins/runconfig.py:556 msgid "Run Settings dialog" msgstr "Ajustes de ejecución" #: spyder/plugins/shortcuts.py:65 msgid "Currently used to delete lines on editor" msgstr "Se utiliza actualmente para eliminar líneas en el editor" #: spyder/plugins/shortcuts.py:69 msgid "We cannot support this shortcut on Windows" msgstr "No soportamos este acceso directo en Windows" #: spyder/plugins/shortcuts.py:72 msgid "Shortcuts that use Shift and another key are unsupported" msgstr "Los accesos directos que usan Shift más otra tecla no son válidos" #: spyder/plugins/shortcuts.py:149 msgid "" "Press the new shortcut and select 'Ok': \n" "(Press 'Tab' once to switch focus between the shortcut entry \n" "and the buttons below it)" msgstr "" "Teclee el nuevo atajo y seleccione 'Ok': \n" "(Presione 'Tab' una vez para cambiar el foco entre la entrada del atajo \n" "y los botones que aparecen abajo)" #: spyder/plugins/shortcuts.py:152 msgid "Current shortcut:" msgstr "Atajo seleccionado:" #: spyder/plugins/shortcuts.py:154 msgid "New shortcut:" msgstr "Nuevo atajo:" #: spyder/plugins/shortcuts.py:167 msgid "Shortcut: {0}" msgstr "Atajo: {0}" #: spyder/plugins/shortcuts.py:288 msgid "Please introduce a different shortcut" msgstr "Por favor introduzca un nuevo atajo" #: spyder/plugins/shortcuts.py:325 msgid "The new shortcut conflicts with:" msgstr "El nuevo atajo tiene entra en conflicto con:" #: spyder/plugins/shortcuts.py:334 spyder/plugins/shortcuts.py:343 msgid "Forbidden key sequence!" msgstr "Secuencia de teclas prohibida" #: spyder/plugins/shortcuts.py:354 msgid "" "A compound sequence can have {break} a maximum of 4 subsequences.{break}" msgstr "" "Una secuencia compuesta puede tener {break} un máximo de 4 sub-secuencias." "{break}" #: spyder/plugins/shortcuts.py:359 msgid "Invalid key entered" msgstr "Tecla inválida" #: spyder/plugins/shortcuts.py:567 msgid "Context" msgstr "Contexto" #: spyder/plugins/shortcuts.py:569 #: spyder/widgets/variableexplorer/collectionseditor.py:128 msgid "Name" msgstr "Nombre" #: spyder/plugins/shortcuts.py:571 msgid "Shortcut" msgstr "Atajo" #: spyder/plugins/shortcuts.py:573 msgid "Score" msgstr "Puntaje" #: spyder/plugins/shortcuts.py:734 msgid "Conflicts" msgstr "Conflicto con" #: spyder/plugins/shortcuts.py:735 msgid "The following conflicts have been detected:" msgstr "Los siguientes conflictos han sido detectados:" #: spyder/plugins/shortcuts.py:820 msgid "Keyboard shortcuts" msgstr "Atajos de teclado" #: spyder/plugins/shortcuts.py:828 msgid "Search: " msgstr "Buscar:" #: spyder/plugins/shortcuts.py:829 msgid "Reset to default values" msgstr "Restaurar los valores por defecto" #: spyder/plugins/shortcuts.py:859 msgid "Shortcuts reset" msgstr "Restaurar los atajos" #: spyder/plugins/shortcuts.py:860 msgid "Do you want to reset to default values?" msgstr "¿Desea restaurar los valores por defecto?" #: spyder/plugins/variableexplorer.py:25 msgid "Filter" msgstr "Filtrar" #: spyder/plugins/variableexplorer.py:27 #: spyder/widgets/variableexplorer/namespacebrowser.py:200 msgid "Exclude private references" msgstr "Excluir variables privadas" #: spyder/plugins/variableexplorer.py:28 #: spyder/widgets/variableexplorer/namespacebrowser.py:215 msgid "Exclude capitalized references" msgstr "Excluir variables que comienzan en mayúsculas" #: spyder/plugins/variableexplorer.py:29 #: spyder/widgets/variableexplorer/namespacebrowser.py:208 msgid "Exclude all-uppercase references" msgstr "Excluir variables en mayúsculas" #: spyder/plugins/variableexplorer.py:30 #: spyder/widgets/variableexplorer/namespacebrowser.py:223 msgid "Exclude unsupported data types" msgstr "Excluir tipos de datos no soportados" #: spyder/plugins/variableexplorer.py:36 #: spyder/widgets/variableexplorer/collectionseditor.py:699 msgid "Show arrays min/max" msgstr "Mostrar el máximo y mínimo de arreglos" #: spyder/plugins/variableexplorer.py:178 msgid "Variable explorer" msgstr "Explorador de variables" #: spyder/plugins/workingdirectory.py:39 msgid "" "The current working directory is the working directory for IPython " "consoles and the current directory for the File Explorer." msgstr "" "El directorio de trabajo actual es el directorio de trabajo de las " "consolas IPython y el directorio actual del explorador de archivos." #: spyder/plugins/workingdirectory.py:44 msgid "Console directory" msgstr "Directorio de la consola" #: spyder/plugins/workingdirectory.py:45 msgid "The working directory for new consoles is:" msgstr "El directorio de trabajo para la nueva consola es:" #: spyder/plugins/workingdirectory.py:49 msgid "" "The current project directory or user home directory (if no project is " "active)" msgstr "" "El directorio del proyecto actual o el directorio personal del usuario (si " "no hay ningún proyecto activo)" #: spyder/plugins/workingdirectory.py:62 msgid "the following directory:" msgstr "el siguiente directorio:" #: spyder/plugins/workingdirectory.py:64 msgid "The directory when a new console is open will be the specified path" msgstr "El directorio cuando una nueva consola se abre será el siguiente" #: spyder/plugins/workingdirectory.py:124 msgid "Back" msgstr "Anterior" #: spyder/plugins/workingdirectory.py:132 spyder/widgets/explorer.py:1181 #: spyder/widgets/variableexplorer/importwizard.py:539 msgid "Next" msgstr "Siguiente" #: spyder/plugins/workingdirectory.py:143 msgid "" "This is the working directory for newly\n" "opened consoles (Python/IPython consoles and\n" "terminals), for the file explorer, for the\n" "find in files plugin and for new files\n" "created in the editor" msgstr "" "Este es el directorio de trabajo para las\n" "terminales que se abran de aquí en\n" "adelante (de IPython y Python y terminales de\n" "comandos), para el Explorador de archivos,\n" "y Buscar en archivos y para los nuevos\n" "archivos creados en el Editor" #: spyder/plugins/workingdirectory.py:168 msgid "Browse a working directory" msgstr "Seleccionar un directorio de trabajo" #: spyder/plugins/workingdirectory.py:175 msgid "Change to parent directory" msgstr "Moverse al directorio superior" #: spyder/plugins/workingdirectory.py:182 spyder/widgets/findinfiles.py:322 msgid "Current working directory" msgstr "Directorio de trabajo actual" #: spyder/utils/codeanalysis.py:92 msgid "Real-time code analysis on the Editor" msgstr "Análisis del código en tiempo real en el Editor" #: spyder/utils/codeanalysis.py:96 msgid "Real-time code style analysis on the Editor" msgstr "Análisis de estilo del código en el Editor" #: spyder/utils/environ.py:46 msgid "Environment variables" msgstr "Variables de entorno" #: spyder/utils/environ.py:96 msgid "" "Module pywin32 was not found.
Please restart this Windows " "session (not the computer) for changes to take effect." msgstr "" "No se pudo encontrar el módulo pywin32.
Por favor reinicie esta " "sesión de Windows (no el computador) para que los cambios surtan " "efecto." #: spyder/utils/environ.py:109 msgid "" "If you accept changes, this will modify the current user environment " "variables directly in Windows registry. Use it with precautions, at " "your own risks.

Note that for changes to take effect, you will need " "to restart the parent process of this application (simply restart Spyder if " "you have executed it from a Windows shortcut, otherwise restart any " "application from which you may have executed it, like Python(x,y) Home for example)" msgstr "" "Si acepta los cambios, se modificarán las variables de entorno del usuario " "actual directamente en el registro de Windows. Hágalo con precaución " "y bajo su propio riesgo.

Tenga en cuenta que para que los cambios " "tengan efecto, deberá reiniciar el proceso padre de esta aplicación " "(simplemente reinicie Spyder si lo ejecutó desde un acceso directo, de otra " "forma reinicie la aplicación desde la cual lo inició, como por ejemplo " "Python(x,y) Home)" #: spyder/utils/help/sphinxify.py:217 spyder/utils/help/sphinxify.py:227 msgid "" "It was not possible to generate rich text help for this object.
Please " "see it in plain text." msgstr "" "No fue posible generar ayuda en texto enriquecido para este objeto.
Por " "favor véala en texto plano." #: spyder/utils/introspection/manager.py:34 #: spyder/utils/introspection/manager.py:39 msgid "Editor's code completion, go-to-definition and help" msgstr "Completado del código y ayuda en el Editor" #: spyder/utils/iofuncs.py:408 msgid "Supported files" msgstr "Archivos soportados" #: spyder/utils/iofuncs.py:410 msgid "All files (*.*)" msgstr "Todos los archivos (*.*)" #: spyder/utils/iofuncs.py:420 msgid "Spyder data files" msgstr "Archivos de datos de Spyder" #: spyder/utils/iofuncs.py:422 #: spyder/widgets/variableexplorer/collectionseditor.py:1058 msgid "NumPy arrays" msgstr "Arreglos de NumPy" #: spyder/utils/iofuncs.py:423 msgid "NumPy zip arrays" msgstr "Arreglos comprimidos de NumPy" #: spyder/utils/iofuncs.py:424 msgid "Matlab files" msgstr "Archivos de Matlab" #: spyder/utils/iofuncs.py:425 msgid "CSV text files" msgstr "Archivos de texto CSV" #: spyder/utils/iofuncs.py:427 msgid "JPEG images" msgstr "Imágenes JPEG" #: spyder/utils/iofuncs.py:428 msgid "PNG images" msgstr "Imágenes PNG" #: spyder/utils/iofuncs.py:429 msgid "GIF images" msgstr "Imágenes GIF" #: spyder/utils/iofuncs.py:430 msgid "TIFF images" msgstr "Imágenes TIFF" #: spyder/utils/iofuncs.py:431 spyder/utils/iofuncs.py:432 msgid "Pickle files" msgstr "Archivos pickle" #: spyder/utils/iofuncs.py:433 msgid "JSON files" msgstr "Archivos JSON" #: spyder/utils/iofuncs.py:452 spyder/utils/iofuncs.py:459 msgid "Unsupported file type '%s'" msgstr "Tipo de archivo no soportado '%s'" #: spyder/utils/programs.py:287 msgid "It was not possible to run this file in an external terminal" msgstr "No fue posible ejecutar este archivo en una terminal del sistema" #: spyder/utils/syntaxhighlighters.py:34 msgid "Syntax highlighting for Matlab, Julia and other file types" msgstr "" "Coloreado del código para archivos tipo Matlab, Julia y varios otros tipos" #: spyder/utils/syntaxhighlighters.py:43 msgid "Background:" msgstr "Fondo:" #: spyder/utils/syntaxhighlighters.py:44 #: spyder/widgets/sourcecode/codeeditor.py:107 msgid "Current line:" msgstr "Línea seleccionada:" #: spyder/utils/syntaxhighlighters.py:45 msgid "Current cell:" msgstr "Celda seleccionada:" #: spyder/utils/syntaxhighlighters.py:46 msgid "Occurrence:" msgstr "Ocurrencia:" #: spyder/utils/syntaxhighlighters.py:47 msgid "Link:" msgstr "Enlace:" #: spyder/utils/syntaxhighlighters.py:48 msgid "Side areas:" msgstr "Áreas laterales:" #: spyder/utils/syntaxhighlighters.py:49 msgid "Matched
parens:" msgstr "Paréntesis
emparejados:" #: spyder/utils/syntaxhighlighters.py:50 msgid "Unmatched
parens:" msgstr "Paréntesis
desemparejados:" #: spyder/utils/syntaxhighlighters.py:51 msgid "Normal text:" msgstr "Texto normal:" #: spyder/utils/syntaxhighlighters.py:52 msgid "Keyword:" msgstr "Palabra clave:" #: spyder/utils/syntaxhighlighters.py:53 msgid "Builtin:" msgstr "Objeto integrado:" #: spyder/utils/syntaxhighlighters.py:54 msgid "Definition:" msgstr "Definición:" #: spyder/utils/syntaxhighlighters.py:55 msgid "Comment:" msgstr "Comentario:" #: spyder/utils/syntaxhighlighters.py:56 msgid "String:" msgstr "Cadena:" #: spyder/utils/syntaxhighlighters.py:57 msgid "Number:" msgstr "Número:" #: spyder/utils/syntaxhighlighters.py:58 msgid "Instance:" msgstr "Instancia:" #: spyder/widgets/arraybuilder.py:179 msgid "" "\n" " Numpy Array/Matrix Helper
\n" " Type an array in Matlab : [1 2;3 4]
\n" " or Spyder simplified syntax : 1 2;3 4\n" "

\n" " Hit 'Enter' for array or 'Ctrl+Enter' for matrix.\n" "

\n" " Hint:
\n" " Use two spaces or two tabs to generate a ';'.\n" " " msgstr "" "\n" " Ayuda para arreglos de Numpy
\n" " Escriba un arreglo en Matlab : [1 2;3 4]
\n" " o sintaxis simplificada de Spyder : 1 2;3 4\n" "

\n" " Oprima 'Enter' para un arreglo o 'Ctrl+Enter' para una matriz.\n" "

\n" " Consejo:
\n" " Use dos espacios o tabs para generar un ';'.\n" " " #: spyder/widgets/arraybuilder.py:190 msgid "" "\n" " Numpy Array/Matrix Helper
\n" " Enter an array in the table.
\n" " Use Tab to move between cells.\n" "

\n" " Hit 'Enter' for array or 'Ctrl+Enter' for matrix.\n" "

\n" " Hint:
\n" " Use two tabs at the end of a row to move to the next row.\n" " " msgstr "" "\n" " Ayuda para arreglos de Numpy
\n" " Introduzca un arreglo en la tabla.
\n" " Use Tab para moverse entre las celdas.\n" "

\n" " Oprima 'Enter' para un arreglo o 'Ctrl+Enter' para una matriz.\n" "

\n" " Consejo:
\n" " Use dos tabs al final de una fila para moverse a la siguiente.\n" " " #: spyder/widgets/arraybuilder.py:365 msgid "Array dimensions not valid" msgstr "Las dimensiones del arreglo no son válidas" #: spyder/widgets/browser.py:58 spyder/widgets/sourcecode/codeeditor.py:2719 msgid "Zoom out" msgstr "Alejar" #: spyder/widgets/browser.py:61 spyder/widgets/sourcecode/codeeditor.py:2715 msgid "Zoom in" msgstr "Acercar" #: spyder/widgets/browser.py:213 msgid "Home" msgstr "Página de inicio" #: spyder/widgets/browser.py:249 msgid "Find text" msgstr "Encontrar texto" #: spyder/widgets/browser.py:266 msgid "Address:" msgstr "Dirección:" #: spyder/widgets/browser.py:302 msgid "Unable to load page" msgstr "No fue posible cargar la página" #: spyder/widgets/comboboxes.py:164 msgid "Press enter to validate this entry" msgstr "Presione Enter para validar esta entrada" #: spyder/widgets/comboboxes.py:165 msgid "This entry is incorrect" msgstr "Esta entrada es incorrecta" #: spyder/widgets/comboboxes.py:208 msgid "Press enter to validate this path" msgstr "Presione Enter para validar esta ruta" #: spyder/widgets/dependencies.py:63 msgid " Required " msgstr "Requerido" #: spyder/widgets/dependencies.py:63 msgid "Module" msgstr "Módulo" #: spyder/widgets/dependencies.py:64 msgid " Installed " msgstr "Instalado" #: spyder/widgets/dependencies.py:64 msgid "Provided features" msgstr "Características proporcionadas" #: spyder/widgets/dependencies.py:134 msgid "Dependencies" msgstr "Dependencias" #: spyder/widgets/dependencies.py:141 msgid "" "Spyder depends on several Python modules to provide the right functionality " "for all its panes. The table below shows the required and installed versions " "(if any) of all of them.

Note: You can safely use Spyder " "without the following modules installed: %s and %s." "

Please also note that new dependencies or changed ones will be " "correctly detected only after Spyder is restarted." msgstr "" "Spyder depende de varios módulos de Python para proveer la funcionalidad " "correcta para todos sus paneles. La tabla que aparece a continuación muestra " "las versiones requeridas e instaladas (de existir) de todos ellos." "

Nota: Usted puede utilizar Spyder sin problemas si no cuenta " "con los siguientes módulos instalados: %s y %s.

Por " "favor también tenga en cuenta que dependencias nuevas o que hayan sido " "cambiadas en esta lista, sólo serán detectadas correctamente después de que " "Spyder sea reiniciado." #: spyder/widgets/dependencies.py:157 msgid "Copy to clipboard" msgstr "Copiar al portapapeles" #: spyder/widgets/editor.py:501 msgid "Find symbols in file..." msgstr "Buscar símbolos en el archivo..." #: spyder/widgets/editor.py:504 msgid "Copy path to clipboard" msgstr "Copiar la ruta al portapapeles" #: spyder/widgets/editor.py:508 msgid "Close all to the right" msgstr "Cerrar todos a la derecha" #: spyder/widgets/editor.py:510 msgid "Close all but this" msgstr "Cerrar todos menos éste" #: spyder/widgets/editor.py:514 spyder/widgets/explorer.py:361 msgid "Show in Finder" msgstr "Mostrar en explorador del sistema" #: spyder/widgets/editor.py:516 spyder/widgets/explorer.py:363 msgid "Show in external file explorer" msgstr "Mostrar en el explorador de archivos del sistema" #: spyder/widgets/editor.py:1197 msgid "Temporary file" msgstr "Archivo temporal" #: spyder/widgets/editor.py:1289 msgid "New window" msgstr "Nueva ventana" #: spyder/widgets/editor.py:1290 msgid "Create a new editor window" msgstr "Crear una nueva ventana de edición" #: spyder/widgets/editor.py:1293 msgid "Split vertically" msgstr "Dividir verticalmente" #: spyder/widgets/editor.py:1295 msgid "Split vertically this editor window" msgstr "Dividir verticalmente esta panel o ventana de edición" #: spyder/widgets/editor.py:1297 msgid "Split horizontally" msgstr "Dividir horizontalmente" #: spyder/widgets/editor.py:1299 msgid "Split horizontally this editor window" msgstr "Dividir horizontalmente esta ventana o panel de edición" #: spyder/widgets/editor.py:1301 msgid "Close this panel" msgstr "Cerrar este panel" #: spyder/widgets/editor.py:1540 msgid "%s has been modified.
Do you want to save changes?" msgstr "%s ha sido modificado.
¿Desea guardar los cambios?" #: spyder/widgets/editor.py:1626 spyder/widgets/editor.py:1789 msgid "Save" msgstr "Guardar" #: spyder/widgets/editor.py:1627 spyder/widgets/editor.py:1790 #: spyder/widgets/shell.py:267 msgid "Unable to save file '%s'

Error message:
%s" msgstr "" "No fue posible guardar el archivo '%s'

Mensaje de error:
%s" #: spyder/widgets/editor.py:1977 msgid "" "%s is unavailable (this file may have been removed, moved or renamed " "outside Spyder).
Do you want to close it?" msgstr "" "%s no está disponible (el archivo puede haber sido eliminado, movido " "o renombrado por fuera de Spyder).
¿Desea cerrarlo?" #: spyder/widgets/editor.py:2000 msgid "" "%s has been modified outside Spyder.
Do you want to reload it and " "lose all your changes?" msgstr "" "%s fue modificado por fuera de Spyder.
¿Desea recargarlo y perder " "todos sus cambios?" #: spyder/widgets/editor.py:2110 msgid "" "All changes to %s will be lost.
Do you want to revert file from " "disk?" msgstr "" "Todos los cambios a %s se perderán.
Desea revertir el archivo del " "disco?" #: spyder/widgets/editor.py:2254 msgid "Loading %s..." msgstr "Cargando %s..." #: spyder/widgets/editor.py:2266 msgid "" "%s contains mixed end-of-line characters.
Spyder will fix this " "automatically." msgstr "" "%s contiene varios tipos de caracteres de fin de línea.
Spyder lo " "arreglará automáticamente." #: spyder/widgets/editor.py:2675 msgid "Close window" msgstr "Cerrar ventana" #: spyder/widgets/editor.py:2677 msgid "Close this window" msgstr "Cierra esta ventana" #: spyder/widgets/editortools.py:94 spyder/widgets/editortools.py:130 msgid "Line %s" msgstr "Línea %s" #: spyder/widgets/editortools.py:99 msgid "Class defined at line %s" msgstr "Clase definida en la línea %s" #: spyder/widgets/editortools.py:107 msgid "Method defined at line %s" msgstr "Método definido en la línea %s" #: spyder/widgets/editortools.py:117 msgid "Function defined at line %s" msgstr "Función definida en la línea %s" #: spyder/widgets/editortools.py:149 msgid "Cell starts at line %s" msgstr "La celda empieza en la línea %s" #: spyder/widgets/editortools.py:202 spyder/widgets/editortools.py:535 msgid "Go to cursor position" msgstr "Ir a la posición del cursor" #: spyder/widgets/editortools.py:205 msgid "Show absolute path" msgstr "Mostrar la ruta completa" #: spyder/widgets/editortools.py:208 spyder/widgets/explorer.py:274 msgid "Show all files" msgstr "Mostrar todos los archivos" #: spyder/widgets/editortools.py:211 msgid "Show special comments" msgstr "Mostrar comentarios especiales" #: spyder/widgets/editortools.py:509 msgid "Show/hide outline explorer" msgstr "" "Mostrar u ocultar el\n" "explorador de código" #: spyder/widgets/explorer.py:270 msgid "Edit filename filters..." msgstr "Editar filtros..." #: spyder/widgets/explorer.py:284 msgid "Edit filename filters" msgstr "Editar los filtros para nombres de archivo" #: spyder/widgets/explorer.py:285 msgid "Name filters:" msgstr "Nombres de los filtros:" #: spyder/widgets/explorer.py:304 msgid "File..." msgstr "Archivo..." #: spyder/widgets/explorer.py:308 msgid "Module..." msgstr "Módulo" #: spyder/widgets/explorer.py:312 msgid "Folder..." msgstr "Carpeta..." #: spyder/widgets/explorer.py:316 msgid "Package..." msgstr "Paquete..." #: spyder/widgets/explorer.py:337 #: spyder/widgets/variableexplorer/collectionseditor.py:674 msgid "Edit" msgstr "Editar" #: spyder/widgets/explorer.py:339 msgid "Move..." msgstr "Mover a..." #: spyder/widgets/explorer.py:342 msgid "Delete..." msgstr "Eliminar..." #: spyder/widgets/explorer.py:345 msgid "Rename..." msgstr "Renombrar..." #: spyder/widgets/explorer.py:348 msgid "Open" msgstr "Abrir" #: spyder/widgets/explorer.py:349 spyder/widgets/sourcecode/codeeditor.py:2687 msgid "Convert to Python script" msgstr "Convertir a un archivo de Python" #: spyder/widgets/explorer.py:390 msgid "Commit" msgstr "Consignar" #: spyder/widgets/explorer.py:393 msgid "Browse repository" msgstr "Explorar repositorio " #: spyder/widgets/explorer.py:404 msgid "Open command prompt here" msgstr "Abrir símbolo del sistema aquí" #: spyder/widgets/explorer.py:406 msgid "Open terminal here" msgstr "Abrir terminal del sistema aquí" #: spyder/widgets/explorer.py:407 msgid "Open IPython console here" msgstr "Abrir una terminal de Python aquí" #: spyder/widgets/explorer.py:421 msgid "New" msgstr "Crear nuevo" #: spyder/widgets/explorer.py:429 msgid "Import" msgstr "Importar" #: spyder/widgets/explorer.py:575 msgid "Do you really want to delete %s?" msgstr "¿Realmente desea eliminar %s?" #: spyder/widgets/explorer.py:593 msgid "delete" msgstr "eliminar" #: spyder/widgets/explorer.py:594 spyder/widgets/projects/explorer.py:148 #: spyder/widgets/projects/explorer.py:255 msgid "Project Explorer" msgstr "Explorador de proyectos" #: spyder/widgets/explorer.py:595 spyder/widgets/projects/explorer.py:149 msgid "Unable to %s %s

Error message:
%s" msgstr "No fue posible %s %s

Mensaje de error:
%s" #: spyder/widgets/explorer.py:610 msgid "File Explorer" msgstr "Explorador de archivos" #: spyder/widgets/explorer.py:611 msgid "" "The current directory contains a project.

If you want to delete the " "project, please go to Projects » Delete Project" msgstr "" "El directorio actual contiene un proyecto.

Si desea eliminar este " "proyecto, por favor diríjase a Proyectos » Eliminar " "proyecto" #: spyder/widgets/explorer.py:628 spyder/widgets/sourcecode/codeeditor.py:2160 msgid "Conversion error" msgstr "Error de conversión" #: spyder/widgets/explorer.py:629 spyder/widgets/sourcecode/codeeditor.py:2161 msgid "" "It was not possible to convert this notebook. The error is:\n" "\n" msgstr "" "No fue posible convertir este notebook. El error es:\n" "\n" #: spyder/widgets/explorer.py:646 spyder/widgets/explorer.py:654 #: spyder/widgets/explorer.py:665 #: spyder/widgets/variableexplorer/collectionseditor.py:703 #: spyder/widgets/variableexplorer/collectionseditor.py:949 msgid "Rename" msgstr "Renombrar" #: spyder/widgets/explorer.py:647 msgid "New name:" msgstr "Nuevo nombre:" #: spyder/widgets/explorer.py:655 msgid "" "Do you really want to rename %s and overwrite the existing file " "%s?" msgstr "" "¿Realmente desea renombrar %s y sobrescribir el archivo existente " "%s?" #: spyder/widgets/explorer.py:666 msgid "Unable to rename file %s

Error message:
%s" msgstr "" "No fue posible renombrar el archivo %s

Mensaje de error:" "
%s" #: spyder/widgets/explorer.py:709 msgid "Unable to move %s

Error message:
%s" msgstr "No fue posible mover %s

Mensaje de error:
%s" #: spyder/widgets/explorer.py:727 msgid "Unable to create folder %s

Error message:
%s" msgstr "" "No fue posible crear la carpeta %s

Mensaje de error:
" "%s" #: spyder/widgets/explorer.py:740 spyder/widgets/explorer.py:774 msgid "Unable to create file %s

Error message:
%s" msgstr "" "No fue posible crear el archivo %s

Mensaje de error:
" "%s" #: spyder/widgets/explorer.py:748 msgid "New folder" msgstr "Nueva carpeta" #: spyder/widgets/explorer.py:749 msgid "Folder name:" msgstr "Nombre de la carpeta:" #: spyder/widgets/explorer.py:754 msgid "New package" msgstr "Nuevo paquete" #: spyder/widgets/explorer.py:755 msgid "Package name:" msgstr "Nombre del paquete:" #: spyder/widgets/explorer.py:795 msgid "New module" msgstr "Nuevo módulo" #: spyder/widgets/explorer.py:810 msgid "" "For %s support, please install one of the
following tools:

%s" msgstr "" "Para contar con soporte de %s, por favor instale una de
las siguientes " "herramientas:

%s" #: spyder/widgets/explorer.py:814 msgid "Unable to find external program.

%s" msgstr "No fue posible encontrar el programa externo.

%s" #: spyder/widgets/explorer.py:1035 msgid "Show current directory only" msgstr "Mostrar sólo el directorio actual" #: spyder/widgets/explorer.py:1145 msgid "You don't have the right permissions to open this directory" msgstr "No tiene con permisos para abrir este directorio" #: spyder/widgets/explorer.py:1176 msgid "Show icons and text" msgstr "Mostrar iconos y texto " #: spyder/widgets/explorer.py:1178 #: spyder/widgets/variableexplorer/importwizard.py:535 msgid "Previous" msgstr "Anterior" #: spyder/widgets/explorer.py:1184 msgid "Parent" msgstr "Directorio superior" #: spyder/widgets/fileswitcher.py:110 msgid "unsaved file" msgstr "Archivo sin guardar" #: spyder/widgets/fileswitcher.py:249 msgid "" "Press Enter to switch files or Esc to cancel.

Type to " "filter filenames.

Use :number to go to a line, e.g. " "main:42
Use @symbol_text to go to a symbol, e." "g. @init

Press Ctrl+W to close current " "tab.
" msgstr "" "Presione Enter para cambiar entre archivos o Esc para cancelar." "

Escriba un texto para filtrar los nombres de archivos.

Use " ":número para ir a una línea dada, e.g. main:42
Use @símbolo para ir a un símbolo, e.g. @init

Presione Ctrl+W para cerrar la pestaña actual.
" #: spyder/widgets/fileswitcher.py:663 msgid "lines" msgstr "líneas" #: spyder/widgets/findinfiles.py:121 msgid "Unexpected error: see internal console" msgstr "Error inesperado. Por favor vea la terminal interna." #: spyder/widgets/findinfiles.py:149 msgid "invalid regular expression" msgstr "expresión regular inválida" #: spyder/widgets/findinfiles.py:199 msgid "permission denied errors were encountered" msgstr "permiso denegado, se encontraron errores" #: spyder/widgets/findinfiles.py:258 msgid "Search pattern" msgstr "Patrón de búsqueda" #: spyder/widgets/findinfiles.py:261 spyder/widgets/findinfiles.py:301 #: spyder/widgets/findreplace.py:99 msgid "Regular expression" msgstr "Expresión regular" #: spyder/widgets/findinfiles.py:264 spyder/widgets/findreplace.py:105 msgid "Case Sensitive" msgstr "" "Distinguir mayúsculas\n" "de minúsculas" #: spyder/widgets/findinfiles.py:275 msgid "Search" msgstr "Buscar" #: spyder/widgets/findinfiles.py:278 msgid "Start search" msgstr "Comenzar la búsqueda" #: spyder/widgets/findinfiles.py:285 msgid "Stop search" msgstr "Detener la búsqueda" #: spyder/widgets/findinfiles.py:295 msgid "Excluded filenames pattern" msgstr "" "Patrones de nombres de\n" "archivo a excluir" #: spyder/widgets/findinfiles.py:304 msgid "Exclude:" msgstr "Excluir:" #: spyder/widgets/findinfiles.py:313 msgid "Search in:" msgstr "Buscar en:" #: spyder/widgets/findinfiles.py:315 msgid "Search directory" msgstr "Directorio de búsqueda" #: spyder/widgets/findinfiles.py:324 msgid "Search in all files and directories present on thecurrent Spyder path" msgstr "" "Buscar en todos los archivos y directorios presentes en la ruta actual de " "Spyder" #: spyder/widgets/findinfiles.py:328 msgid "Project" msgstr "Proyecto" #: spyder/widgets/findinfiles.py:330 msgid "" "Search in all files and directories present on thecurrent project path (If " "opened)" msgstr "" "Buscar en todos los archivos y directorios presentes en la ruta del proyecto " "actual (si está abierto)" #: spyder/widgets/findinfiles.py:336 msgid "File" msgstr "&Archivo" #: spyder/widgets/findinfiles.py:338 msgid "Search in current opened file" msgstr "Buscar en el archivo abierto" #: spyder/widgets/findinfiles.py:340 msgid "Select other directory" msgstr "Seleccionar otro directorio" #: spyder/widgets/findinfiles.py:342 msgid "Search in other folder present on the file system" msgstr "Buscar en otro directorio del sistema de archivos" #: spyder/widgets/findinfiles.py:378 msgid "Hide advanced options" msgstr "Ocultar opciones avanzadas" #: spyder/widgets/findinfiles.py:381 msgid "Show advanced options" msgstr "Mostrar opciones avanzadas" #: spyder/widgets/findinfiles.py:675 spyder/widgets/findinfiles.py:759 msgid "String not found" msgstr "Texto no encontrado" #: spyder/widgets/findinfiles.py:761 msgid "matches in" msgstr "coincidencias en" #: spyder/widgets/findinfiles.py:762 msgid "file" msgstr "archivo" #: spyder/widgets/findinfiles.py:794 msgid " Scanning: {0}" msgstr " Escaneando: {0}" #: spyder/widgets/findinfiles.py:796 msgid " Searching for files in folder: {0}" msgstr " Buscando archivos en la carpeta: {0}" #: spyder/widgets/findinfiles.py:800 msgid " Searching for files..." msgstr " Buscando archivos..." #: spyder/widgets/findreplace.py:48 msgid "No matches" msgstr "Sin coincidencias" #: spyder/widgets/findreplace.py:49 spyder/widgets/findreplace.py:50 #: spyder/widgets/findreplace.py:72 msgid "Search string" msgstr "Buscar texto" #: spyder/widgets/findreplace.py:51 msgid "Regular expression error" msgstr "Error en la expresión regular" #: spyder/widgets/findreplace.py:111 msgid "Whole words" msgstr "" "Solamente palabras\n" "completas" #: spyder/widgets/findreplace.py:117 msgid "Highlight matches" msgstr "Resaltar coincidencias" #: spyder/widgets/findreplace.py:131 msgid "Replace with:" msgstr "Reemplazar con:" #: spyder/widgets/findreplace.py:133 msgid "Replace string" msgstr "Reemplazar texto" #: spyder/widgets/findreplace.py:137 msgid "Replace/find next" msgstr "Buscar/reemplazar siguiente" #: spyder/widgets/findreplace.py:142 msgid "Replace selection" msgstr "Reemplazar la selección" #: spyder/widgets/findreplace.py:150 msgid "Replace all" msgstr "Reemplazar todo" #: spyder/widgets/findreplace.py:572 msgid "of" msgstr "de" #: spyder/widgets/findreplace.py:576 msgid "matches" msgstr "coincidencias" #: spyder/widgets/findreplace.py:579 msgid "no matches" msgstr "sin coincidencias" #: spyder/widgets/internalshell.py:262 msgid "Help..." msgstr "Ayuda..." #: spyder/widgets/internalshell.py:279 msgid "Shell special commands:" msgstr "Comandos especiales:" #: spyder/widgets/internalshell.py:280 msgid "Internal editor:" msgstr "Editor interno:" #: spyder/widgets/internalshell.py:281 msgid "External editor:" msgstr "Editor externo:" #: spyder/widgets/internalshell.py:282 msgid "Run script:" msgstr "Ejecutar un archivo:" #: spyder/widgets/internalshell.py:283 msgid "Remove references:" msgstr "Eliminar referencias:" #: spyder/widgets/internalshell.py:284 msgid "System commands:" msgstr "Comandos del sistema:" #: spyder/widgets/internalshell.py:285 msgid "Python help:" msgstr "Ayuda de Python:" #: spyder/widgets/internalshell.py:286 msgid "GUI-based editor:" msgstr "Editor gráfico:" #: spyder/widgets/ipythonconsole/client.py:275 msgid "An error ocurred while starting the kernel" msgstr "Ocurrió un error mientras iniciaba el núcleo" #: spyder/widgets/ipythonconsole/client.py:316 #: spyder/widgets/ipythonconsole/client.py:372 #: spyder/widgets/ipythonconsole/client.py:405 #: spyder/widgets/ipythonconsole/shell.py:232 #: spyder/widgets/variableexplorer/namespacebrowser.py:193 msgid "Remove all variables" msgstr "Eliminar todas las variables" #: spyder/widgets/ipythonconsole/client.py:325 msgid "Show environment variables" msgstr "Mostrar las variables de entorno" #: spyder/widgets/ipythonconsole/client.py:332 msgid "Show sys.path contents" msgstr "Contenidos del sys.path" #: spyder/widgets/ipythonconsole/client.py:359 msgid "Stop the current command" msgstr "Detener el comando actual" #: spyder/widgets/ipythonconsole/client.py:370 #: spyder/widgets/variableexplorer/collectionseditor.py:696 #: spyder/widgets/variableexplorer/collectionseditor.py:931 msgid "Remove" msgstr "Eliminar" #: spyder/widgets/ipythonconsole/client.py:393 msgid "Inspect current object" msgstr "Inspeccionar objeto" #: spyder/widgets/ipythonconsole/client.py:399 msgid "Clear line or block" msgstr "Limpiar línea o bloque" #: spyder/widgets/ipythonconsole/client.py:412 msgid "Clear console" msgstr "Limpiar la terminal" #: spyder/widgets/ipythonconsole/client.py:460 msgid "Are you sure you want to restart the kernel?" msgstr "Está seguro de que desea reiniciar el núcleo?" #: spyder/widgets/ipythonconsole/client.py:462 msgid "Restart kernel?" msgstr "Reiniciar el núcleo?" #: spyder/widgets/ipythonconsole/client.py:474 msgid "Error restarting kernel: %s\n" msgstr "Ocurrió un error al reiniciar el núcleo: %s\n" #: spyder/widgets/ipythonconsole/client.py:479 msgid "" "
Restarting kernel...\n" "

" msgstr "" "
Reiniciando el núcleo...\n" "

" #: spyder/widgets/ipythonconsole/client.py:483 msgid "Cannot restart a kernel not started by Spyder\n" msgstr "No es posible reiniciar un núcleo que no fue iniciado por Spyder\n" #: spyder/widgets/ipythonconsole/client.py:592 msgid "Connecting to kernel..." msgstr "Conectándose al núcleo..." #: spyder/widgets/ipythonconsole/help.py:128 spyder/widgets/mixins.py:712 msgid "Arguments" msgstr "Argumentos" #: spyder/widgets/ipythonconsole/namespacebrowser.py:129 msgid "Loading this kind of data while debugging is not supported." msgstr "" "No se admite la carga de este tipo de datos mientras se ejecuta el depurador " "de código." #: spyder/widgets/ipythonconsole/namespacebrowser.py:148 msgid "Saving data while debugging is not supported." msgstr "" "No es posible guardar datos durante la ejecución del depurador de código." #: spyder/widgets/ipythonconsole/shell.py:233 msgid "" "All user-defined variables will be removed. Are you sure you want to proceed?" msgstr "" "Todas las variables definidas por el usuario serán eliminadas. ¿Está seguro " "de que desea continuar?" #: spyder/widgets/ipythonconsole/shell.py:239 msgid "Don't show again." msgstr "No mostrar de nuevo." #: spyder/widgets/ipythonconsole/shell.py:262 msgid "" "

Removing all variables...\n" "
" msgstr "" "

Eliminando todas las variables...\n" "
" #: spyder/widgets/ipythonconsole/shell.py:426 msgid "Changing backend to Qt for Mayavi" msgstr "Cambiando la salida gráfica a Qt por Mayavi" #: spyder/widgets/ipythonconsole/shell.py:471 msgid "Kernel died, restarting" msgstr "El núcleo dejó de funcionar, reiniciándolo" #: spyder/widgets/ipythonconsole/shell.py:471 msgid "Kernel restarting" msgstr "Reiniciando el núcleo" #: spyder/widgets/onecolumntree.py:52 msgid "Collapse all" msgstr "Colapsar resultados" #: spyder/widgets/onecolumntree.py:56 msgid "Expand all" msgstr "Expandir resultados" #: spyder/widgets/onecolumntree.py:60 msgid "Restore" msgstr "Restaurar" #: spyder/widgets/onecolumntree.py:61 msgid "Restore original tree layout" msgstr "Restaurar la disposición original" #: spyder/widgets/onecolumntree.py:65 msgid "Collapse selection" msgstr "Colapsar selección" #: spyder/widgets/onecolumntree.py:69 msgid "Expand selection" msgstr "Expandir selección" #: spyder/widgets/pathmanager.py:97 msgid "Move to top" msgstr "Mover al principio" #: spyder/widgets/pathmanager.py:103 msgid "Move up" msgstr "Mover arriba" #: spyder/widgets/pathmanager.py:109 msgid "Move down" msgstr "Mover abajo" #: spyder/widgets/pathmanager.py:115 msgid "Move to bottom" msgstr "Mover al final" #: spyder/widgets/pathmanager.py:126 spyder/widgets/pathmanager.py:267 msgid "Add path" msgstr "Añadir ruta" #: spyder/widgets/pathmanager.py:131 spyder/widgets/pathmanager.py:246 msgid "Remove path" msgstr "Eliminar ruta" #: spyder/widgets/pathmanager.py:141 msgid "Synchronize..." msgstr "Sincronizar..." #: spyder/widgets/pathmanager.py:143 msgid "Synchronize Spyder's path list with PYTHONPATH environment variable" msgstr "" "Sincronizar la lista de rutas de Spyder con la variable\n" "de entorno PYTHONPATH" #: spyder/widgets/pathmanager.py:155 msgid "Synchronize" msgstr "Sincronizar" #: spyder/widgets/pathmanager.py:156 msgid "" "This will synchronize Spyder's path list with PYTHONPATH environment " "variable for current user, allowing you to run your Python modules outside " "Spyder without having to configure sys.path.
Do you want to clear " "contents of PYTHONPATH before adding Spyder's path list?" msgstr "" "Esta acción sincronizará la lista de rutas de Spyder con la variable de " "entorno PYTHONPATH para el usuario actual, permitiéndole ejecutar sus " "módulos de Python por fuera de Spyder sin tener que configurar sys.path." "
¿Desea borrar los contenidos del PYTHONPATH antes de añadir la lista de " "rutas de Spyder?" #: spyder/widgets/pathmanager.py:247 msgid "Do you really want to remove selected path?" msgstr "¿Realmente desea eliminar la ruta seleccionada?" #: spyder/widgets/pathmanager.py:268 msgid "" "This directory is already included in Spyder path list.
Do you want to " "move it to the top of the list?" msgstr "" "Este directorio ya está incluido en la lista de rutas de Spyder.
¿Desea " "moverlo al principio de la lista?" #: spyder/widgets/projects/configdialog.py:30 msgid "Project preferences" msgstr "Preferencias del proyecto" #: spyder/widgets/projects/configdialog.py:82 #: spyder/widgets/projects/configdialog.py:119 msgid "Restore data on startup" msgstr "Restaurar datos al inicio" #: spyder/widgets/projects/configdialog.py:84 #: spyder/widgets/projects/configdialog.py:121 msgid "Save data on exit" msgstr "Guardar datos al salir" #: spyder/widgets/projects/configdialog.py:86 #: spyder/widgets/projects/configdialog.py:123 msgid "Save history" msgstr "Guardar el historial" #: spyder/widgets/projects/configdialog.py:88 #: spyder/widgets/projects/configdialog.py:125 msgid "Save non project files opened" msgstr "Guardar archivos abiertos que no pertenecen al proyecto" #: spyder/widgets/projects/configdialog.py:111 msgid "Code" msgstr "Código" #: spyder/widgets/projects/configdialog.py:118 msgid "Workspace" msgstr "Espacio de trabajo" #: spyder/widgets/projects/configdialog.py:148 #: spyder/widgets/projects/configdialog.py:155 msgid "Version control" msgstr "Control de versiones" #: spyder/widgets/projects/configdialog.py:156 msgid "Use version control" msgstr "Usar control de versiones" #: spyder/widgets/projects/configdialog.py:161 msgid "Version control system" msgstr "Sistema de versión de controles" #: spyder/widgets/projects/explorer.py:51 msgid "Show horizontal scrollbar" msgstr "Mostrar una barra de desplazamiento horizontal" #: spyder/widgets/projects/explorer.py:113 msgid "File %s already exists.
Do you want to overwrite it?" msgstr "El archivo %s ya existe.
¿Desea sobrescribirlo?" #: spyder/widgets/projects/explorer.py:127 msgid "Folder %s already exists." msgstr "La carpeta %s ya existe." #: spyder/widgets/projects/explorer.py:145 msgid "copy" msgstr "copiar" #: spyder/widgets/projects/explorer.py:147 msgid "move" msgstr "mover" #: spyder/widgets/projects/explorer.py:243 msgid "" "Do you really want to delete {filename}?

Note: This " "action will only delete the project. Its files are going to be preserved on " "disk." msgstr "" "¿Realmente desea eliminar el proyecto {filename}?

Nota: " "Esta acción sólo eliminará el proyecto. Los archivos del mismo no serán " "eliminados del disco." #: spyder/widgets/projects/explorer.py:256 msgid "" "Unable to delete {varpath}

The error message was:" "
{error}" msgstr "" "No fue posible eliminar {varpath}

El mensaje de error " "fue:
{error}" #: spyder/widgets/projects/projectdialog.py:69 msgid "New directory" msgstr "Nuevo directorio" #: spyder/widgets/projects/projectdialog.py:70 msgid "Existing directory" msgstr "Un directorio existente" #: spyder/widgets/projects/projectdialog.py:72 msgid "Project name" msgstr "Nombre del proyecto" #: spyder/widgets/projects/projectdialog.py:73 msgid "Location" msgstr "Ubicación" #: spyder/widgets/projects/projectdialog.py:74 msgid "Project type" msgstr "Tipo del proyecto" #: spyder/widgets/projects/projectdialog.py:75 msgid "Python version" msgstr "Versión de Python" #: spyder/widgets/projects/projectdialog.py:83 #: spyder/widgets/variableexplorer/importwizard.py:529 msgid "Cancel" msgstr "Cancelar" #: spyder/widgets/projects/projectdialog.py:84 msgid "Create" msgstr "Crear" #: spyder/widgets/projects/projectdialog.py:102 msgid "Create new project" msgstr "Crear nuevo proyecto" #: spyder/widgets/projects/type/__init__.py:216 msgid "Empty project" msgstr "Proyecto vacío" #: spyder/widgets/projects/type/python.py:20 msgid "Python project" msgstr "Proyecto de Python" #: spyder/widgets/projects/type/python.py:76 msgid "Python package" msgstr "Paquete de Python" #: spyder/widgets/pydocgui.py:110 msgid "Module or package:" msgstr "Módulo o paquete:" #: spyder/widgets/shell.py:131 msgid "Save history log..." msgstr "Guardar el historial..." #: spyder/widgets/shell.py:133 msgid "Save current history log (i.e. all inputs and outputs) in a text file" msgstr "" "Guardar el historial actual (es decir\n" "todas las entradas y salidas) en un\n" "archivo de texto" #: spyder/widgets/shell.py:253 msgid "Save history log" msgstr "Guardar el historial" #: spyder/widgets/shell.py:256 msgid "History logs" msgstr "Historiales" #: spyder/widgets/shell.py:670 msgid "Copy without prompts" msgstr "Copiar sin los prompts" #: spyder/widgets/shell.py:673 spyder/widgets/shell.py:677 msgid "Clear line" msgstr "Limpiar línea" #: spyder/widgets/shell.py:679 msgid "Clear shell" msgstr "Limpiar la terminal" #: spyder/widgets/shell.py:683 msgid "Clear shell contents ('cls' command)" msgstr "Limpia los contenidos de la terminal (equivalente al comando 'cls')" #: spyder/widgets/shortcutssummary.py:42 msgid "Spyder Keyboard ShortCuts" msgstr "Atajos de teclado de Spyder" #: spyder/widgets/sourcecode/codeeditor.py:101 msgid "Go to line:" msgstr "Ir a la línea" #: spyder/widgets/sourcecode/codeeditor.py:109 msgid "Line count:" msgstr "Número total de líneas:" #: spyder/widgets/sourcecode/codeeditor.py:1327 msgid "Breakpoint" msgstr "Punto de interrupción" #: spyder/widgets/sourcecode/codeeditor.py:1328 msgid "Condition:" msgstr "Condición:" #: spyder/widgets/sourcecode/codeeditor.py:1733 msgid "Code analysis" msgstr "Análisis del código" #: spyder/widgets/sourcecode/codeeditor.py:1787 msgid "To do" msgstr "To do" #: spyder/widgets/sourcecode/codeeditor.py:2147 msgid "Removal error" msgstr "Error de remoción" #: spyder/widgets/sourcecode/codeeditor.py:2148 msgid "" "It was not possible to remove outputs from this notebook. The error is:\n" "\n" msgstr "" "No fue posible remover las outputs de este notebook. El error es:\n" "\n" #: spyder/widgets/sourcecode/codeeditor.py:2684 msgid "Clear all ouput" msgstr "Eliminar todas las salidas" #: spyder/widgets/sourcecode/codeeditor.py:2690 msgid "Go to definition" msgstr "Ir a la definición" #: spyder/widgets/sourcecode/codeeditor.py:2723 msgid "Zoom reset" msgstr "Restaurar" #: spyder/widgets/status.py:25 msgid "CPU and memory usage info in the status bar" msgstr "Uso de memoria y CPU en la barra de estado" #: spyder/widgets/status.py:117 msgid "Memory:" msgstr "Memoria:" #: spyder/widgets/status.py:118 msgid "" "Memory usage status: requires the `psutil` (>=v0.3) library on non-Windows " "platforms" msgstr "" "Para reportar el uso de memoria se requiere de\n" "la librería `psutil` (>=0.3) en plataformas distintas\n" "a Windows" #: spyder/widgets/status.py:134 msgid "CPU:" msgstr "CPU:" #: spyder/widgets/status.py:135 msgid "CPU usage status: requires the `psutil` (>=v0.3) library" msgstr "" "Para reportar el estado del CPU se requiere\n" "de la librería `psutil` (>=v0.3)" #: spyder/widgets/status.py:162 msgid "Permissions:" msgstr "Permisos:" #: spyder/widgets/status.py:189 msgid "End-of-lines:" msgstr "Fin de línea:" #: spyder/widgets/status.py:216 msgid "Encoding:" msgstr "Codificación:" #: spyder/widgets/status.py:242 msgid "Line:" msgstr "Línea:" #: spyder/widgets/status.py:243 msgid "Column:" msgstr "Columna:" #: spyder/widgets/tabs.py:274 msgid "Browse tabs" msgstr "" "Navegar por\n" "las pestañas" #: spyder/widgets/tabs.py:403 msgid "Close current tab" msgstr "Cerrar pestaña actual" #: spyder/widgets/variableexplorer/arrayeditor.py:511 msgid "It was not possible to copy values for this array" msgstr "No fue posible copiar valores para este arreglo" #: spyder/widgets/variableexplorer/arrayeditor.py:546 #: spyder/widgets/variableexplorer/arrayeditor.py:579 #: spyder/widgets/variableexplorer/dataframeeditor.py:697 #: spyder/widgets/variableexplorer/dataframeeditor.py:742 msgid "Format" msgstr "Formato" #: spyder/widgets/variableexplorer/arrayeditor.py:551 #: spyder/widgets/variableexplorer/dataframeeditor.py:701 msgid "Resize" msgstr "Redimensionar" #: spyder/widgets/variableexplorer/arrayeditor.py:554 #: spyder/widgets/variableexplorer/dataframeeditor.py:705 msgid "Background color" msgstr "Color de fondo" #: spyder/widgets/variableexplorer/arrayeditor.py:580 #: spyder/widgets/variableexplorer/dataframeeditor.py:743 msgid "Float formatting" msgstr "Formato de punto flotante" #: spyder/widgets/variableexplorer/arrayeditor.py:588 msgid "Format (%s) is incorrect" msgstr "El formato (%s) es incorrecto" #: spyder/widgets/variableexplorer/arrayeditor.py:624 msgid "Arrays with more than 3 dimensions are not supported" msgstr "Los arreglos de más de tres dimensiones no están soportados" #: spyder/widgets/variableexplorer/arrayeditor.py:628 msgid "The 'xlabels' argument length do no match array column number" msgstr "" "El argumento de longitud 'xlabels' no coincide con el número de columnas del " "arreglo" #: spyder/widgets/variableexplorer/arrayeditor.py:632 msgid "The 'ylabels' argument length do no match array row number" msgstr "" "El argumento de longitud 'ylabels' no coincide con el número de filas del " "arreglo" #: spyder/widgets/variableexplorer/arrayeditor.py:639 msgid "%s arrays" msgstr "Los arreglos %s" #: spyder/widgets/variableexplorer/arrayeditor.py:640 msgid "%s are currently not supported" msgstr "%s no están soportados por el momento" #: spyder/widgets/variableexplorer/arrayeditor.py:647 msgid "NumPy array" msgstr "Arreglo de NumPy" #: spyder/widgets/variableexplorer/arrayeditor.py:649 #: spyder/widgets/variableexplorer/arrayeditor.py:806 msgid "Array editor" msgstr "Editor de arreglos" #: spyder/widgets/variableexplorer/arrayeditor.py:651 msgid "read only" msgstr "sólo lectura" #: spyder/widgets/variableexplorer/arrayeditor.py:681 msgid "Record array fields:" msgstr "Campos del arreglo de records:" #: spyder/widgets/variableexplorer/arrayeditor.py:693 msgid "Data" msgstr "Datos" #: spyder/widgets/variableexplorer/arrayeditor.py:693 msgid "Mask" msgstr "Máscara" #: spyder/widgets/variableexplorer/arrayeditor.py:693 msgid "Masked data" msgstr "Datos enmascarados" #: spyder/widgets/variableexplorer/arrayeditor.py:704 msgid "Axis:" msgstr "Eje:" #: spyder/widgets/variableexplorer/arrayeditor.py:709 msgid "Index:" msgstr "Índice:" #: spyder/widgets/variableexplorer/arrayeditor.py:722 msgid "Warning: changes are applied separately" msgstr "Advertencia: los cambios son aplicados de forma separada" #: spyder/widgets/variableexplorer/arrayeditor.py:723 msgid "" "For performance reasons, changes applied to masked array won't be reflected " "in array's data (and vice-versa)." msgstr "" "Por razones de rendimiento, los cambios\n" "aplicados a arreglos enmascarados no se\n" "verán reflejados en los datos del arreglo\n" "(y viceversa)." #: spyder/widgets/variableexplorer/collectionseditor.py:126 msgid "Index" msgstr "Índice" #: spyder/widgets/variableexplorer/collectionseditor.py:131 msgid "Tuple" msgstr "Tupla" #: spyder/widgets/variableexplorer/collectionseditor.py:134 msgid "List" msgstr "Lista" #: spyder/widgets/variableexplorer/collectionseditor.py:137 msgid "Dictionary" msgstr "Diccionario" #: spyder/widgets/variableexplorer/collectionseditor.py:139 msgid "Key" msgstr "Clave/Tecla" #: spyder/widgets/variableexplorer/collectionseditor.py:144 msgid "Attribute" msgstr "Atributo" #: spyder/widgets/variableexplorer/collectionseditor.py:148 msgid "elements" msgstr "elementos" #: spyder/widgets/variableexplorer/collectionseditor.py:319 msgid "Size" msgstr "Tamaño" #: spyder/widgets/variableexplorer/collectionseditor.py:319 msgid "Type" msgstr "Tipo" #: spyder/widgets/variableexplorer/collectionseditor.py:319 msgid "Value" msgstr "Valor" #: spyder/widgets/variableexplorer/collectionseditor.py:417 msgid "" "Opening this variable can be slow\n" "\n" "Do you want to continue anyway?" msgstr "" "Abrir e inspeccionar esta variable puede tomar mucho tiempo\n" "\n" "¿Desea continuar de todas formas?" #: spyder/widgets/variableexplorer/collectionseditor.py:428 msgid "" "Spyder was unable to retrieve the value of this variable from the console." "

The error mesage was:
%s" msgstr "" "Spyder no fue capaz de extraer el valor de esta variable de la terminal." "

El mensaje de error fue:
%s" #: spyder/widgets/variableexplorer/collectionseditor.py:605 msgid "Edit item" msgstr "Editar ítem" #: spyder/widgets/variableexplorer/collectionseditor.py:606 msgid "Unable to assign data to item.

Error message:
%s" msgstr "" "No fue posible asignarle los datos al ítem.

Mensaje de error:" "
%s" #: spyder/widgets/variableexplorer/collectionseditor.py:666 msgid "Resize rows to contents" msgstr "Ajustar filas a los contenidos" #: spyder/widgets/variableexplorer/collectionseditor.py:677 #: spyder/widgets/variableexplorer/collectionseditor.py:1027 #: spyder/widgets/variableexplorer/collectionseditor.py:1044 msgid "Plot" msgstr "Graficar" #: spyder/widgets/variableexplorer/collectionseditor.py:681 msgid "Histogram" msgstr "Histograma" #: spyder/widgets/variableexplorer/collectionseditor.py:685 msgid "Show image" msgstr "Mostrar como imagen" #: spyder/widgets/variableexplorer/collectionseditor.py:689 #: spyder/widgets/variableexplorer/collectionseditor.py:1052 msgid "Save array" msgstr "Guardar arreglo" #: spyder/widgets/variableexplorer/collectionseditor.py:693 #: spyder/widgets/variableexplorer/collectionseditor.py:991 #: spyder/widgets/variableexplorer/collectionseditor.py:999 msgid "Insert" msgstr "Insertar" #: spyder/widgets/variableexplorer/collectionseditor.py:706 #: spyder/widgets/variableexplorer/collectionseditor.py:952 msgid "Duplicate" msgstr "Duplicar" #: spyder/widgets/variableexplorer/collectionseditor.py:929 msgid "Do you want to remove the selected item?" msgstr "¿Desea eliminar la variable seleccionada?" #: spyder/widgets/variableexplorer/collectionseditor.py:930 msgid "Do you want to remove all selected items?" msgstr "¿Desea eliminar todas las variables seleccionadas?" #: spyder/widgets/variableexplorer/collectionseditor.py:950 msgid "New variable name:" msgstr "Nuevo nombre de variable:" #: spyder/widgets/variableexplorer/collectionseditor.py:953 msgid "Variable name:" msgstr "Nombre de variable:" #: spyder/widgets/variableexplorer/collectionseditor.py:991 msgid "Key:" msgstr "Nombre:" #: spyder/widgets/variableexplorer/collectionseditor.py:999 msgid "Value:" msgstr "Valor:" #: spyder/widgets/variableexplorer/collectionseditor.py:1015 msgid "Import error" msgstr "Error de importación" #: spyder/widgets/variableexplorer/collectionseditor.py:1016 msgid "Please install matplotlib or guiqwt." msgstr "Por favor instale Matplotlib o guiqwt." #: spyder/widgets/variableexplorer/collectionseditor.py:1028 msgid "Unable to plot data.

Error message:
%s" msgstr "" "No fue posible graficar los datos.

Mensaje de error:
%s" #: spyder/widgets/variableexplorer/collectionseditor.py:1045 msgid "Unable to show image.

Error message:
%s" msgstr "" "No fue posible generar la gráfica.

Mensaje de error:
%s" #: spyder/widgets/variableexplorer/collectionseditor.py:1068 msgid "Unable to save array

Error message:
%s" msgstr "" "No fue posible guardar el arreglo

Mensaje de error:
%s" #: spyder/widgets/variableexplorer/collectionseditor.py:1093 msgid "It was not possible to copy this array" msgstr "No fue posible copiar este arreglo" #: spyder/widgets/variableexplorer/collectionseditor.py:1118 msgid "Clipboard contents" msgstr "Contenidos del portapapeles" #: spyder/widgets/variableexplorer/collectionseditor.py:1133 msgid "Import from clipboard" msgstr "Importar desde el portapapeles" #: spyder/widgets/variableexplorer/collectionseditor.py:1135 msgid "Empty clipboard" msgstr "Vaciar el portapapeles" #: spyder/widgets/variableexplorer/collectionseditor.py:1136 msgid "Nothing to be imported from clipboard." msgstr "No hay nada para importar desde el portapapeles." #: spyder/widgets/variableexplorer/dataframeeditor.py:591 msgid "To bool" msgstr "A booleano" #: spyder/widgets/variableexplorer/dataframeeditor.py:591 msgid "To complex" msgstr "A complejo" #: spyder/widgets/variableexplorer/dataframeeditor.py:592 msgid "To float" msgstr "A flotante" #: spyder/widgets/variableexplorer/dataframeeditor.py:592 msgid "To int" msgstr "A entero" #: spyder/widgets/variableexplorer/dataframeeditor.py:593 msgid "To str" msgstr "A cadena" #: spyder/widgets/variableexplorer/dataframeeditor.py:677 msgid "%s editor" msgstr "Editor de %s" #: spyder/widgets/variableexplorer/dataframeeditor.py:711 msgid "Column min/max" msgstr "Min/max de columna" #: spyder/widgets/variableexplorer/dataframeeditor.py:751 msgid "Format ({}) is incorrect" msgstr "El formato ({}) es incorrecto" #: spyder/widgets/variableexplorer/dataframeeditor.py:755 msgid "Format ({}) should start with '%'" msgstr "El formato ({}) debe iniciar con '%'" #: spyder/widgets/variableexplorer/importwizard.py:118 #: spyder/widgets/variableexplorer/importwizard.py:438 msgid "Import as" msgstr "Importar como" #: spyder/widgets/variableexplorer/importwizard.py:120 msgid "data" msgstr "datos" #: spyder/widgets/variableexplorer/importwizard.py:124 msgid "code" msgstr "código" #: spyder/widgets/variableexplorer/importwizard.py:127 #: spyder/widgets/variableexplorer/importwizard.py:514 msgid "text" msgstr "texto" #: spyder/widgets/variableexplorer/importwizard.py:140 msgid "Column separator:" msgstr "Separador de columnas:" #: spyder/widgets/variableexplorer/importwizard.py:144 msgid "Tab" msgstr "Tabulación" #: spyder/widgets/variableexplorer/importwizard.py:147 msgid "Whitespace" msgstr "Espacios en blanco" #: spyder/widgets/variableexplorer/importwizard.py:150 #: spyder/widgets/variableexplorer/importwizard.py:168 msgid "other" msgstr "otro" #: spyder/widgets/variableexplorer/importwizard.py:161 msgid "Row separator:" msgstr "Separador de filas:" #: spyder/widgets/variableexplorer/importwizard.py:165 msgid "EOL" msgstr "Fin de línea" #: spyder/widgets/variableexplorer/importwizard.py:180 msgid "Additional options" msgstr "Opciones adicionales" #: spyder/widgets/variableexplorer/importwizard.py:184 msgid "Skip rows:" msgstr "Saltar filas:" #: spyder/widgets/variableexplorer/importwizard.py:195 msgid "Comments:" msgstr "Comentarios:" #: spyder/widgets/variableexplorer/importwizard.py:201 msgid "Transpose" msgstr "Trasponer" #: spyder/widgets/variableexplorer/importwizard.py:441 msgid "array" msgstr "arreglo" #: spyder/widgets/variableexplorer/importwizard.py:446 msgid "list" msgstr "lista" #: spyder/widgets/variableexplorer/importwizard.py:451 msgid "DataFrame" msgstr "DataFrame" #: spyder/widgets/variableexplorer/importwizard.py:497 #: spyder/widgets/variableexplorer/importwizard.py:581 msgid "Import wizard" msgstr "Asistente de importación" #: spyder/widgets/variableexplorer/importwizard.py:502 msgid "Raw text" msgstr "Texto sin formato" #: spyder/widgets/variableexplorer/importwizard.py:505 msgid "variable_name" msgstr "nombre_de_variable" #: spyder/widgets/variableexplorer/importwizard.py:516 msgid "table" msgstr "tabla" #: spyder/widgets/variableexplorer/importwizard.py:517 msgid "Preview" msgstr "Vista previa" #: spyder/widgets/variableexplorer/importwizard.py:521 msgid "Variable Name" msgstr "Nombre de variable" #: spyder/widgets/variableexplorer/importwizard.py:544 msgid "Done" msgstr "Hecho" #: spyder/widgets/variableexplorer/importwizard.py:582 msgid "" "Unable to proceed to next step

Please check your entries." "

Error message:
%s" msgstr "" "No fue posible pasar al siguiente paso

Por favor revise sus " "daros.

Mensaje de error:
%s" #: spyder/widgets/variableexplorer/namespacebrowser.py:181 #: spyder/widgets/variableexplorer/namespacebrowser.py:385 msgid "Import data" msgstr "Importar datos" #: spyder/widgets/variableexplorer/namespacebrowser.py:184 #: spyder/widgets/variableexplorer/namespacebrowser.py:465 #: spyder/widgets/variableexplorer/namespacebrowser.py:479 msgid "Save data" msgstr "Guardar datos" #: spyder/widgets/variableexplorer/namespacebrowser.py:189 msgid "Save data as..." msgstr "Guardar datos como..." #: spyder/widgets/variableexplorer/namespacebrowser.py:201 msgid "Exclude references which name starts with an underscore" msgstr "" "Excluir variables cuyo nombre comienza\n" "con un guión abajo" #: spyder/widgets/variableexplorer/namespacebrowser.py:209 msgid "Exclude references which name is uppercase" msgstr "" "Excluir variables cuyo nombre está\n" "por completo en mayúsculas" #: spyder/widgets/variableexplorer/namespacebrowser.py:216 msgid "Exclude references which name starts with an uppercase character" msgstr "Excluir variables cuyo nombre comienza en mayúsculas" #: spyder/widgets/variableexplorer/namespacebrowser.py:224 msgid "" "Exclude references to unsupported data types (i.e. which won't be handled/" "saved correctly)" msgstr "" "Excluir variables que referencian tipos de datos no soportados\n" "(es decir aquellos que no pueden manejarse y guardarse\n" "correctamente)" #: spyder/widgets/variableexplorer/namespacebrowser.py:405 msgid "" "Unsupported file extension '%s'

Would you like to import it " "anyway (by selecting a known file format)?" msgstr "" "Extensión de archivo no soportada: '%s'

¿Desea importar el " "archivo de todas formas (seleccionando un formato conocido)?" #: spyder/widgets/variableexplorer/namespacebrowser.py:413 msgid "Open file as:" msgstr "Abrir archivo como:" #: spyder/widgets/variableexplorer/namespacebrowser.py:447 msgid "Unable to load '%s'

Error message:
%s" msgstr "No fue posible cargar '%s'

Mensaje de error:
%s" #: spyder/widgets/variableexplorer/namespacebrowser.py:480 msgid "Unable to save current workspace

Error message:
%s" msgstr "" "No fue posible guardar el espacio de trabajo actual

Mensaje de " "error:
%s" #: spyder/widgets/variableexplorer/texteditor.py:74 msgid "Text editor" msgstr "Editor de texto" #: spyder/widgets/variableexplorer/utils.py:30 msgid "View and edit DataFrames and Series in the Variable Explorer" msgstr "Ver y editar DataFrames y Series en el Explorador de Variables" #: spyder/widgets/variableexplorer/utils.py:35 msgid "View and edit two and three dimensional arrays in the Variable Explorer" msgstr "" "Ver y editar arreglos bi y tridimensionales en el Explorador de Variables" #: spyder/workers/updates.py:90 spyder/workers/updates.py:92 msgid "Unable to retrieve information." msgstr "No fue posible recuperar la información" #: spyder/workers/updates.py:94 msgid "" "Unable to connect to the internet.

Make sure the connection is " "working properly." msgstr "" "No fue posible conectarse a Internet.

Por favor asegúrese de que la " "conexión está funcionando apropiadamente." #: spyder/workers/updates.py:97 msgid "Unable to check for updates." msgstr "No fue posible buscar actualizaciones" #~ msgid "At startup, the current working directory is:" #~ msgstr "Al inicio, el directorio de trabajo global es:" #~ msgid "At startup," #~ msgstr "Al reiniciar," #~ msgid "At startup, the current working directory will be the specified path" #~ msgstr "Al inicio, el directorio de trabajo actual será el siguiente" #~ msgid "Reset namespace" #~ msgstr "Restaurar el namespace" #~ msgid "Reset IPython namespace" #~ msgstr "Reiniciar el espacio de trabajo de IPython" #~ msgid "Loading external console..." #~ msgstr "Cargando la terminal externa..." #~ msgid "The Python console" #~ msgstr "La Terminal de Python" #~ msgid "" #~ "You can also run your code on a Python console. These consoles are useful " #~ "because they let you run a file in a console dedicated only to it.To " #~ "select this behavior, please press the F6 key.

By pressing " #~ "the button below and then focusing the Variable Explorer, you will notice " #~ "that Python consoles are also connected to that pane, and that the " #~ "Variable Explorer only shows the variables of the currently focused " #~ "console." #~ msgstr "" #~ "También es posible ejecutar su código en una terminal de Python. Estas " #~ "terminales son útiles porque le permiten ejecutar un archivo en una " #~ "terminal exclusivamente dedicada al mismo. Por favor oprima la tecla " #~ "Ctrl+F6 para seleccionar este comportamiento.

Al oprimir el " #~ "botón que aparece abajo y luego enfocar el Explorador de Variables, podrá " #~ "notar que las terminales de Python están también conectadas a ese panel, " #~ "y que el Explorador de Variables sólo muestra las variables de la " #~ "terminal que actualmente está enfocada." #~ msgid "Sort files according to full path" #~ msgstr "Ordenar archivos según su ruta completa" #~ msgid "&Configure..." #~ msgstr "&Configurar..." #~ msgid "Show TODO/FIXME/XXX/HINT/TIP/@todo comments list" #~ msgstr "" #~ "Mostrar la lista de comentarios de\n" #~ "los TODO/FIXME/XXX/HINT/TIP/@todo" #~ msgid "Interactive data plotting in the consoles" #~ msgstr "Graficar datos interactivamente en la terminal" #~ msgid "Python console" #~ msgstr "Terminal de Python" #~ msgid "One tab per script" #~ msgstr "Una pestaña por archivo" #~ msgid "Buffer: " #~ msgstr "Mostrar:" #~ msgid "Merge process standard output/error channels" #~ msgstr "Combinar los canales de salida y error estándar del proceso" #~ msgid "" #~ "Merging the output channels of the process means that\n" #~ "the standard error won't be written in red anymore,\n" #~ "but this has the effect of speeding up display." #~ msgstr "" #~ "Combinar los canales de salida del proceso quiere decir que\n" #~ "el error estándar no será escrito en rojo , pero esto ayuda a\n" #~ "mejorar la velocidad en que aparece el texto en la terminal." #~ msgid "Colorize standard error channel using ANSI escape codes" #~ msgstr "Colorear el canal de error estándar usando códigos de escape ANSI " #~ msgid "" #~ "This method is the only way to have colorized standard\n" #~ "error channel when the output channels have been merged." #~ msgstr "" #~ "Éste método es la única forma de darle color al canal de error\n" #~ "estándar cuando los canales de salida han sido combinados." #~ msgid "" #~ "This option will be applied the next time a Python console or a terminal " #~ "is opened." #~ msgstr "" #~ "Esta opción será aplicada la próxima vez que una terminal de Python o una " #~ "consola sea abierta." #~ msgid "Light background (white color)" #~ msgstr "Fondo claro (color blanco)" #~ msgid "PYTHONSTARTUP replacement" #~ msgstr "Reemplazo de PYTHONSTARTUP" #~ msgid "" #~ "This option will override the PYTHONSTARTUP environment variable which\n" #~ "defines the script to be executed during the Python console startup." #~ msgstr "" #~ "Esta opción modificará la variable de entorno PYTHONSTARTUP, la cual\n" #~ "define el archivo que es ejecutado durante el arranque de la terminal de\n" #~ "Python." #~ msgid "Default PYTHONSTARTUP script" #~ msgstr "Utilizar el archivo por defecto de PYTHONSTARTUP" #~ msgid "Use the following startup script:" #~ msgstr "Utilizar el siguiente archivo de arranque:" #~ msgid "Monitor" #~ msgstr "Monitor" #~ msgid "" #~ "The monitor provides introspection features to console: code completion, " #~ "calltips and variable explorer. Because it relies on several modules, " #~ "disabling the monitor may be useful to accelerate console startup." #~ msgstr "" #~ "El monitor es el que brinda características de introspección a la " #~ "terminal: completado del código, globos de sugerencias y el explorador de " #~ "variables. Dado que depende de varios módulos adicionales, desactivar el " #~ "monitor puede acelerar el arranque de la terminal." #~ msgid "Enable monitor" #~ msgstr "Activar el monitor" #~ msgid "Default library" #~ msgstr "Librería por defecto" #~ msgid "Qt-Python Bindings" #~ msgstr "Librerías de enlace entre Qt y Python" #~ msgid "Library:" #~ msgstr "Librería" #~ msgid "" #~ "This option will act on
libraries such as Matplotlib, guidata or ETS" #~ msgstr "" #~ "Esta opción tendrá efecto
en librerías como Matplotlib, guidata o ETS" #~ msgid "" #~ "Decide which backend to use to display graphics. If unsure, please select " #~ "the Automatic backend.

Note: We support a very " #~ "limited number of backends in our Python consoles. If you prefer to work " #~ "with a different one, please use an IPython console." #~ msgstr "" #~ "Decidir que salida gráfica utilizar para mostrar gráficas. Si no está " #~ "seguro, por favor seleccione la salida Automática.

Nota:" #~ " La terminal de Python soporta un número muy limitado de salidas " #~ "gráficas. Si prefiere trabajar con alguna salida diferente, por favor " #~ "utilice una terminal de IPython." #~ msgid "None" #~ msgstr "Ninguno" #~ msgid "Enthought Tool Suite" #~ msgstr "Enthought Tool Suite" #~ msgid "" #~ "Enthought Tool Suite (ETS) supports PyQt4 (qt4) and wxPython (wx) " #~ "graphical user interfaces." #~ msgstr "" #~ "Enthought Tool Suite (ETS) funciona con las librerías gráficas PyQt4 " #~ "(qt4) y \n" #~ "wxPython (wx). Esta opción establece cual desea utilizar el usuario." #~ msgid "ETS_TOOLKIT:" #~ msgstr "ETS_TOOLKIT:" #~ msgid "External modules" #~ msgstr "Módulos externos" #~ msgid "" #~ "No Python console is currently selected to run %s.

Please " #~ "select or open a new Python console and try again." #~ msgstr "" #~ "No existe una terminal de Python para ejecutar %s.

Por " #~ "favor abra una nueva y pruebe otra vez." #~ msgid "" #~ "%s is already running in a separate process.\n" #~ "Do you want to kill the process before starting a new one?" #~ msgstr "" #~ "%s ya se está ejecutando en proceso aparte.\n" #~ "¿Desea terminar este proceso antes de empezar uno nuevo?" #~ msgid "Command Window" #~ msgstr "Símbolo" #~ msgid "Open a &Python console" #~ msgstr "Abrir una terminal de Python" #~ msgid "Open &command prompt" #~ msgstr "Abrir &símbolo del sistema" #~ msgid "Open a Windows command prompt" #~ msgstr "Abre el símbolo del sistema de Windows" #~ msgid "Open a &terminal" #~ msgstr "Abrir &terminal de comandos" #~ msgid "Open a terminal window" #~ msgstr "Abre una terminal del sistema" #~ msgid "Python Console" #~ msgstr "Terminal de IPython" #~ msgid "Light background" #~ msgstr "Fondo claro" #~ msgid "Dark background" #~ msgstr "Fondo oscuro" #~ msgid "Working directory:" #~ msgstr "Directorio de trabajo:" #~ msgid "Dedicated Python console" #~ msgstr "Terminal de Python dedicada" #~ msgid "Show warning when killing running process" #~ msgstr "Mostrar una advertencia cuando se termine el proceso" #~ msgid "Run Settings" #~ msgstr "Ajustes de ejecución" #~ msgid "the script directory" #~ msgstr "El directorio en el que se encuentra el archivo actual" #~ msgid "Show warning when killing running processes" #~ msgstr "Mostrar una advertencia cuando se termine el proceso" #~ msgid "Autorefresh" #~ msgstr "Actualizar automáticamente" #~ msgid "Enable autorefresh" #~ msgstr "Activar las actualizaciones automáticas" #~ msgid "Refresh interval: " #~ msgstr "Intervalo de actualización" #~ msgid "" #~ "The global working directory is the working directory for newly " #~ "opened consoles (Python/IPython consoles and terminals), for the " #~ "file explorer, for the find in files plugin and for new " #~ "files created in the editor." #~ msgstr "" #~ "El directorio de trabajo global es el directorio de trabajo para " #~ "las terminales que se abran de aquí en adelante (de IPython y " #~ "Python, y terminales de comandos), para el Explorador de archivos " #~ "y Buscar en archivos y para los nuevos archivos creados en el " #~ "Editor." #~ msgid "the same as in last session" #~ msgstr "El mismo de la última sesión" #~ msgid "" #~ "At startup, Spyder will restore the global directory from last session" #~ msgstr "" #~ "Al inicio Spyder restaurará el directorio global de la última sesión" #~ msgid "Files are opened from:" #~ msgstr "Los archivos deben abrirse desde:" #~ msgid "the current file directory" #~ msgstr "El directorio en el que se encuentra el archivo actual" #~ msgid "the global working directory" #~ msgstr "El directorio de trabajo global" #~ msgid "Files are created in:" #~ msgstr "Los archivos son creados en:" #~ msgid "Change to file base directory" #~ msgstr "Cambiarse al directorio base de un archivo" #~ msgid "When opening a file" #~ msgstr "Cuando se abra un archivo" #~ msgid "When saving a file" #~ msgstr "Cuando se guarde un archivo" #~ msgid "Global working directory" #~ msgstr "Directorio de trabajo global" #~ msgid "Unable to save script '%s'

Error message:
%s" #~ msgstr "" #~ "No fue posible guardar el archivo '%s'

Mensaje de error:
" #~ "%s" #~ msgid "Run again this program" #~ msgstr "Ejecutar de nuevo este programa" #~ msgid "Kill" #~ msgstr "Terminar" #~ msgid "Kills the current process, causing it to exit immediately" #~ msgstr "" #~ "Termina el proceso actual, provocando\n" #~ "que culmine inmediatamente" #~ msgid "Running..." #~ msgstr "Corriendo..." #~ msgid "Terminated." #~ msgstr "Terminado." #~ msgid "Command line arguments:" #~ msgstr "Argumentos de la línea de comandos:" #~ msgid "" #~ "NOTE: The Python console is going to be REMOVED in Spyder 3.2. Please " #~ "start to migrate your work to the IPython console instead.\n" #~ "\n" #~ msgstr "" #~ "NOTA: La terminal de Python va a ser ELIMINADA en Spyder 3.2. Por favor " #~ "empiece a migrar su trabajo a la terminal de IPython.\n" #~ "\n" #~ msgid "Variables" #~ msgstr "Variables" #~ msgid "Show/hide global variables explorer" #~ msgstr "" #~ "Mostrar u ocultar el\n" #~ "explorador de variables" #~ msgid "Terminate" #~ msgstr "Interrumpir" #~ msgid "" #~ "Attempts to stop the process. The process\n" #~ "may not exit as a result of clicking this\n" #~ "button (it is given the chance to prompt\n" #~ "the user for any unsaved files, etc)." #~ msgstr "" #~ "Intenta interrumpir este proceso, pero éste\n" #~ "puede no concluir tras oprimir este botón\n" #~ "(pues es posible que se le pida al usuario\n" #~ "guardar archivos sin salvar, etc)." #~ msgid "Interact" #~ msgstr "Interactuar" #~ msgid "Debug" #~ msgstr "Depurar" #~ msgid "Arguments..." #~ msgstr "Argumentos..." #~ msgid "Post Mortem Debug" #~ msgstr "Depuración Post Mortem" #~ msgid "Arguments: %s" #~ msgstr "Argumentos: %s" #~ msgid "No argument" #~ msgstr "Sin argumentos" #~ msgid "A Python console failed to start!" #~ msgstr "No se pudo iniciar una terminal de Python!" #~ msgid "Process failed to start" #~ msgstr "El proceso falló al empezar" #~ msgid "Included filenames pattern" #~ msgstr "" #~ "Patrones de nombres de\n" #~ "archivo a incluir" #~ msgid "Include:" #~ msgstr "Incluir:" #~ msgid "PYTHONPATH" #~ msgstr "PYTHONPATH" #~ msgid "" #~ "Search in all directories listed in sys.path which are outside the Python " #~ "installation directory" #~ msgstr "" #~ "Buscar en todos los directorios del\n" #~ "sys.path que están por fuera del\n" #~ "directorio de instalación de Python" #~ msgid "Hg repository" #~ msgstr "Repositorio Hg" #~ msgid "Search in current directory hg repository" #~ msgstr "" #~ "Buscar en el repositorio\n" #~ "actual de Mercurial" #~ msgid "Here:" #~ msgstr "Aquí" #~ msgid "Search recursively in this directory" #~ msgstr "" #~ "Buscar recursivamente\n" #~ "en este directorio" #~ msgid "Browse a search directory" #~ msgstr "" #~ "Seleccionar el directorio\n" #~ "de búsqueda" #~ msgid "Search canceled" #~ msgstr "Búsqueda cancelada" #~ msgid "interrupted" #~ msgstr "interrumpido" #~ msgid "" #~ "
Restarting kernel because an error occurred while debugging\n" #~ "

" #~ msgstr "" #~ "
Reiniciando el núcleo porque ocurrió un error mientras se realizaba " #~ "la depuración\n" #~ "

" #~ msgid "" #~ "Inspecting and setting values while debugging in IPython consoles is not " #~ "supported yet by Spyder." #~ msgstr "" #~ "Spyder aún no soporta inspeccionar y establecer valores mientras se está " #~ "depurando." #~ msgid "Refresh" #~ msgstr "Actualizar" #~ msgid "Refresh periodically" #~ msgstr "" #~ "Actualizar\n" #~ "periódicamente" #~ msgid "Python(x,y)" #~ msgstr "Python(x,y)" #~ msgid "Python(x,y) launcher" #~ msgstr "Lanzador de Python(x,y)" #~ msgid "Python(x,y) documentation folder" #~ msgstr "Carpeta de documentación de Python(x,y)" #~ msgid "guidata documentation" #~ msgstr "Documentación de guidata" #~ msgid "guiqwt documentation" #~ msgstr "Documentación de guiqwt" #~ msgid "NumPy documentation" #~ msgstr "Documentación de NumPy" #~ msgid "NumPy reference guide" #~ msgstr "Manual de referencia de NumPy" #~ msgid "NumPy user guide" #~ msgstr "Guía del usuario de Numpy" #~ msgid "SciPy documentation" #~ msgstr "Documentación de SciPy" #~ msgid "Show/hide project explorer" #~ msgstr "Mostrar/cerrar el explorador de proyectos" #~ msgid "?" #~ msgstr "?" #~ msgid "Use %s+T when the console is selected to open a new one" #~ msgstr "Usar %s+T para abrir una nueva terminal" #~ msgid "Edit data in the remote process" #~ msgstr "Editar los datos en un proceso remoto" #~ msgid "" #~ "Editors are opened in the remote process for NumPy arrays, PIL images, " #~ "lists, tuples and dictionaries.\n" #~ "This avoids transfering large amount of data between the remote process " #~ "and Spyder (through the socket)." #~ msgstr "" #~ "Esta opción permite modificar arreglos de NumPy, imágenes de\n" #~ "de PIL/Pillow, Dataframes, y listas, tuplas y diccionarios en el\n" #~ "proceso remoto. Esto impide transferir grandes cantidades de\n" #~ "datos entre el proceso remoto y Spyder." #~ msgid "Array is empty" #~ msgstr "El arreglo está vacío" #~ msgid "Object %s is not picklable" #~ msgstr "El objeto %s no es picklable" #~ msgid "Truncate values" #~ msgstr "Abreviar valores" #~ msgid "Reload last session" #~ msgstr "Recargar la última sesión" #~ msgid "Load session..." #~ msgstr "Cargar sesión..." #~ msgid "Load Spyder session" #~ msgstr "Cargar sesión de Spyder" #~ msgid "Save session..." #~ msgstr "Guardar sesión..." #~ msgid "Save current session and quit application" #~ msgstr "Guardar sesión actual y salir de la aplicación" #~ msgid "Open session" #~ msgstr "Abrir sesión" #~ msgid "Spyder sessions" #~ msgstr "Sesiones de Spyder" #~ msgid "Save session" #~ msgstr "Guardar sesión" #~ msgid "Jupyter Qtconsole integration" #~ msgstr "Integración con la terminal de IPython" #~ msgid "Python executable" #~ msgstr "Archivo ejecutable de Python" #~ msgid "Trying to kill a kernel?" #~ msgstr "Desea cerrar un núcleo?" #~ msgid "" #~ "You can't close this kernel because it has one or more consoles connected " #~ "to it.

You need to close them instead or you can kill the kernel " #~ "using the second button from right to left." #~ msgstr "" #~ "No puede cerrar este núcleo porque tiene una o más terminales conectadas " #~ "a él.

Debe cerrarlas previamente o puede terminar el proceso " #~ "usando el segundo botón ubicado de derecha a izquierda." #~ msgid "Kernel" #~ msgstr "Núcleo" #~ msgid "" #~ "Either:
  1. Your IPython frontend and kernel versions are " #~ "incompatible or
  2. You don't have IPython installed in " #~ "your external interpreter.
In any case, we're sorry but we can't " #~ "create a console for you." #~ msgstr "" #~ "O bien:
  1. Sus versiones del núcleo y la interfaz gráfica de IPython " #~ "son incompatibles o
  2. Usted no tiene IPython " #~ "instalado en su intérprete externo.
Lo lamentamos, pero en " #~ "cualquier caso no podemos crear una terminal de IPython para usted." #~ msgid "Kernel %s" #~ msgstr "Núcleo %s" #~ msgid "Open an IPython console" #~ msgstr "Abrir una terminal de IPython" #~ msgid "" #~ "The console monitor was disabled: the IPython kernel will be started as " #~ "expected, but an IPython console will have to be connected manually to " #~ "the kernel." #~ msgstr "" #~ "El monitor está desactivado, por tanto se creará un kernel de IPython " #~ "pero usted deberá conectar manualmente un intérprete al mismo." #~ msgid "" #~ "UMR excluded modules:\n" #~ "(example: guidata, guiqwt)" #~ msgstr "" #~ "Módulos excluidos del RMU:\n" #~ "(por ejemplo: guidata, guiqwt)" #~ msgid "" #~ "This feature requires the Matplotlib library.\n" #~ "It seems you don't have it installed." #~ msgstr "" #~ "Esta característica requiere la librería Matplotlib.\n" #~ "Al parecer no la tiene instalada." #~ msgid "" #~ "This feature requires the Sympy library.\n" #~ "It seems you don't have it installed." #~ msgstr "" #~ "Esta característica requiere la librería Sympy.\n" #~ "Al parecer no la tiene instalada." #~ msgid "&Font..." #~ msgstr "&Tipo de letra..." #~ msgid "Set font style" #~ msgstr "Establece el tipo de fuente" #~ msgid "Select a new font" #~ msgstr "Seleccionar una nueva fuente" #~ msgid "" #~ "The kernel failed to start!! That's all we know... Please close this " #~ "console and open a new one." #~ msgstr "" #~ "No fue posible crear un núcleo!! Es todo lo que sabemos... Por favor " #~ "cierre esta terminal y abra una nueva." #~ msgid "" #~ "It seems the kernel died unexpectedly. Use 'Restart kernel' to continue " #~ "using this console." #~ msgstr "" #~ "Al parecer el núcleo murió de forma inesperada. Use 'Reiniciar el núcleo' " #~ "para continuar usando esta terminal." #~ msgid "Kernel process is either remote or unspecified. Cannot interrupt" #~ msgstr "" #~ "El núcleo es remoto o no está especificado. Por ello no se puede " #~ "interrumpir." #~ msgid "Kernel process is either remote or unspecified. Cannot restart." #~ msgstr "" #~ "El núcleo es remoto o no está especificado. Por ello no se puede " #~ "reiniciar." #~ msgid "its own configuration file" #~ msgstr "su propio archivo de configuración" #~ msgid " and " #~ msgstr " y" #~ msgid "the following projects:
%s" #~ msgstr "los siguientes proyectos:
%s" #~ msgid "Existing Pydev project" #~ msgstr "Un proyecto de Pydev existente" #~ msgid "Close unrelated projects" #~ msgstr "Cerrar proyectos no relacionados" #~ msgid "Edit related projects" #~ msgstr "Editar proyectos relacionados" #~ msgid "Add to PYTHONPATH" #~ msgstr "Añadir al PYTHONPATH" #~ msgid "Remove from PYTHONPATH" #~ msgstr "Eliminar del PYTHONPATH" #~ msgid "Properties" #~ msgstr "Propiedades" #~ msgid "" #~ "The workspace was unable to load or save %s

Please check if you " #~ "have the permission to write the associated configuration files." #~ msgstr "" #~ "No fue posible cargar o guardar el espacio de trabajo%s

Por favor " #~ "verifique si cuenta con los permisos necesarios para escribir los " #~ "archivos de configuración del proyecto al disco." #~ msgid "Import directory" #~ msgstr "Importar directorio" #~ msgid "" #~ "The following directory is not in workspace:
%s

Do you " #~ "want to continue (and copy the directory to workspace)?" #~ msgstr "" #~ "El siguiente directorio no está en el espacio de trabajo:
%s

¿Desea continuar (y copiar el directorio al espacio de trabajo)?" #~ msgid "The project %s is already opened!" #~ msgstr "El proyecto %s ya está abierto!" #~ msgid "" #~ "The project root path directory is inside the workspace but not as the " #~ "expected tree level. It is not a directory of the workspace:
%s" #~ msgstr "" #~ "La ruta del directorio del proyecto está dentro del espacio de trabajo " #~ "pero no al nivel esperado de profundidad, pues no es un directorio sino " #~ "un subdirectorio del espacio de trabajo:
%s" #~ msgid "A project named %s already exists" #~ msgstr "Un proyecto llamado %s ya existe" #~ msgid "" #~ "Invalid project name.

Name must match the following regular " #~ "expression:
%s" #~ msgstr "" #~ "Nombre de proyecto inválido.

El nombre debe ajustarse a una " #~ "expresión del tipo:
%s" #~ msgid "" #~ "The following directory is not empty:
%s

Do you want to " #~ "continue?" #~ msgstr "" #~ "El siguiente directorio no está vacío:
%s

¿Desear " #~ "continuar?" #~ msgid "New project" #~ msgstr "Nuevo proyecto" #~ msgid "" #~ "The current workspace has not been configured yet.\n" #~ "Do you want to do this now?" #~ msgstr "" #~ "El siguiente espacio de trabajo no ha sido configurado.\n" #~ "¿Desea hacerlo ahora?" #~ msgid "Import existing project" #~ msgstr "Importar proyecto existente" #~ msgid "Select projects to import" #~ msgstr "Seleccionar proyectos a importar" #~ msgid "The folder %s does not contain a valid %s project" #~ msgstr "La carpeta %s no contiene un proyecto de %s válido" #~ msgid "Import existing Pydev project" #~ msgstr "Importar un proyecto existente de Pydev" #~ msgid "" #~ "Unable to read Pydev project %s

Error message:
%s" #~ msgstr "" #~ "No fue posible cargar el proyecto de Pydev %s

Mensaje de error:
%s" #~ msgid "Select projects which are related to %s" #~ msgstr "Seleccionar los proyectos que están relacionados a %s" #~ msgid "" #~ "Statistics on source files only:
(Python, Cython, IPython, Enaml,C/C+" #~ "+, Fortran)

%s files.
%s lines of code." #~ msgstr "" #~ "Estadísticas para los archivos de código únicamente:
(Python, Cython, " #~ "IPython, Enaml, C/C++, Fortran)

%s archivos.
%s " #~ "líneas de código." #~ msgid "Select an existing workspace directory, or create a new one" #~ msgstr "" #~ "Seleccionar un directorio existente para que\n" #~ "sea el espacio de trabajo, o crear uno nuevo" #~ msgid "" #~ "What is the workspace?

A Spyder workspace is " #~ "a directory on your filesystem that contains Spyder projects and ." #~ "spyderworkspace configuration file.

A Spyder project is " #~ "a directory with source code (and other related files) and a " #~ "configuration file (named .spyderproject) with project settings " #~ "(PYTHONPATH, linked projects, ...).
" #~ msgstr "" #~ "¿Qué es un espacio de trabajo?

Un espacio de " #~ "trabajo de Spyder es un directorio en su sistema de archivos que " #~ "contiene un proyecto de Spyder y un archivo de configuración ." #~ "spyderworkspace.

Un proyecto de Spyder es un directorio " #~ "con código fuente (y otros archivos relacionados) y un archivo de " #~ "configuración (llamado .spyderproject) con los ajustes del " #~ "proyecto (PYTHONPATH, proyectos referenciados, etc).
" #~ msgid "This is the current workspace directory" #~ msgstr "Este es el directorio actual del espacio de trabajo" #~ msgid "" #~ "The following directory is not a Spyder workspace:
%s

Do you " #~ "want to create a new workspace in this directory?" #~ msgstr "" #~ "El siguiente directorio no es un espacio de trabajo de Spyder:
" #~ "%s

¿Desea crear un nuevo espacio de trabajo en este directorio?" #~ msgid "Unable to retrieve data.

Error message:
%s" #~ msgstr "" #~ "No fue posible obtener los datos.

Mensaje de error:
%s" #~ msgid "Set shell font style" #~ msgstr "Establece el tipo de fuente de la terminal" #~ msgid "Text and margin font style" #~ msgstr "Tipo de letra para el texto y las márgenes" #~ msgid "tab" #~ msgstr "tabulador" #~ msgid "Breakpoints" #~ msgstr "Puntos de interrupción (Breakpoints)" #~ msgid "Exit" #~ msgstr "Terminar" #~ msgid "Exit Debug" #~ msgstr "Terminar depuración" #~ msgid "Rich text help on the Object Inspector" #~ msgstr "Ayuda en texto enriquecido en el Inspector de Objetos" #~ msgid "Object inspector" #~ msgstr "Inspector de objetos" #~ msgid "Preferences > Object Inspector" #~ msgstr "Preferencias > Inspector de objetos" #~ msgid "Set as current console's working directory" #~ msgstr "Establece el directorio de trabajo para la terminal actual" #~ msgid "Save session and quit..." #~ msgstr "Guardar sesión y salir..." #~ msgid "Loading object inspector..." #~ msgstr "Cargando el inspector de objetos..." #, fuzzy #~ msgid "The Object Inspector" #~ msgstr "Inspector de objetos" #~ msgid "(Experimental) Editor's code completion, go-to-definition and help" #~ msgstr "(Experimental) Completado del código y ayuda en el Editor" #~ msgid "" #~ "This path is incorrect.\n" #~ "Enter a correct directory path,\n" #~ "then press enter to validate" #~ msgstr "" #~ "Esta ruta es incorrecta.\n" #~ "Introduzca una ruta de\n" #~ "directorio correcta y después\n" #~ "presione Enter para validarla" #~ msgid "Save Python script" #~ msgstr "Guardar archivo de Python" #~ msgid "PyQt" #~ msgstr "PyQt" #~ msgid "API selection for QString and QVariant objects:" #~ msgstr "Selección del API para objetos QString and QVariant:" #~ msgid "API #1" #~ msgstr "API #1" #~ msgid "API #2" #~ msgstr "API #2" #~ msgid "Default API" #~ msgstr "API por defecto" #~ msgid "" #~ "PyQt API #1 is the default
API for Python 2. PyQt API #2 is the " #~ "default API for Python 3 and is compatible with PySide." #~ msgstr "" #~ "El API #1 de PyQt es el API por
defecto para Python 2. El API #2 de " #~ "PyQt es el API por defecto para Python 3 y es compatible con PySide." #~ msgid "Ignore API change errors (sip.setapi)" #~ msgstr "Ignorar los errores de cambio de API (sip.setapi)" #~ msgid "" #~ "Enabling this option will ignore
errors when changing PyQt API. As " #~ "PyQt does not support dynamic API changes, it is strongly recommended to " #~ "use this feature wisely, e.g. for debugging purpose." #~ msgstr "" #~ "Al activar esta opción se ignorarán
los errores generados al cambiar " #~ "de API de PyQt. Dado que PyQt no soporta los cambios dinámicos de API, se " #~ "recomienda usar esta característica con sumo cuidado, por ejemplo, para " #~ "propósitos de depuración." #~ msgid "Matplotlib" #~ msgstr "Matplotlib" #~ msgid "GUI backend:" #~ msgstr "Salida gráfica:" #~ msgid "" #~ "Set the GUI toolkit used by
Matplotlib to show figures (default: " #~ "Qt4Agg)" #~ msgstr "" #~ "Establecer la librería gráfica
utilizada para generar las gráficas de " #~ "Matplotlib (por defecto: Qt4Agg)" #~ msgid "Mod1" #~ msgstr "Mod1" #~ msgid "Mod2" #~ msgstr "Mod2" #~ msgid "Mod3" #~ msgstr "Mod3" #, fuzzy #~ msgid "The Internal Console" #~ msgstr "Terminal interna" #~ msgid "File list management" #~ msgstr "Gestión de la lista de archivos" #~ msgid "Filter:" #~ msgstr "Filtro:" #~ msgid "(press Enter to edit file)" #~ msgstr "(Oprimir Enter para editar)" #~ msgid "&Edit file" #~ msgstr "Editar" #~ msgid "&Close file" #~ msgstr "Cerrar" #~ msgid "Hint: press Alt to show accelerators" #~ msgstr "Sugerencia: oprimir Alt para mostrar aceleradores" #~ msgid "Vertical dockwidget tabs" #~ msgstr "Componentes en pestañas verticales" #~ msgid "Custom dockwidget margin:" #~ msgstr "Márgenes de componente personalizadas:" #~ msgid "" #~ "Note: add analysis:ignore in a comment to ignore code/style " #~ "analysis warnings. For more informations on style guide for Python code, " #~ "please refer to the %s page." #~ msgstr "" #~ "Nota: Añada analysis:ignore a un comentario para ignorar " #~ "advertencias de análisis de código o estilo. Para más información sobre " #~ "una guía de estilo para escribir código en Python, por favor refiérase a " #~ "la página de %s (en inglés).
" #~ msgid "Style analysis" #~ msgstr "Análisis de estilo" #~ msgid "Qt (PyQt/PySide)" #~ msgstr "Qt (PyQt/PySide)" #~ msgid "Use a completion widget" #~ msgstr "Usar un widget para completar texto" #~ msgid "Use a widget instead of plain text output for tab completion" #~ msgstr "" #~ "Puede decidir si usar un widget en lugar de texto plano \n" #~ "para mostrar las posibilidades de completado usando la\n" #~ "tecla Tab." #~ msgid "Switch to/from layout %d" #~ msgstr "Cambiarse a la disposición %d" #~ msgid "Set layout %d" #~ msgstr "Establecer la disposición %d" #~ msgid "" #~ "%s will be closed.\n" #~ "Do you want to kill the associated kernel and all of its clients?" #~ msgstr "" #~ "La %s será cerrada.\n" #~ "Desea cerrar el núcleo asociado y todos sus clientes?" #~ msgid "Install Spyder's input hook for Qt" #~ msgstr "Instalar el \"input hook\" de Spyder para Qt" #~ msgid "" #~ "PyQt installs an input hook that allows
creating and interacting with " #~ "Qt widgets in an interactive console without blocking it. On Windows " #~ "platforms, it is strongly recommended to replace it by Spyder's. " #~ "Regarding PySide, note that it does not install an input hook, so it is " #~ "required to enable this feature in order to be able to manipulate PySide/" #~ "Qtobjects interactively." #~ msgstr "" #~ "PyQt instala un mecanismo de \"input hook\"
que permite crear e " #~ "interactuar con widgets de Qt en una terminal sin bloquearla. En Windows, " #~ "es altamente recomendable reemplazar este mecanismo por el de Spyder. Con " #~ "respecto a PySide, debe decirse que no instala un \"inputhook\", así que " #~ "se requiere activar esta característica para poder manipular objectos de " #~ "PySide/Qt interactivamente." #~ msgid "Could not open ssh tunnel\n" #~ msgstr "No fue posible crear un túnel ssh\n" #~ msgid "Mismatch between kernel and frontend" #~ msgstr "Incompatibilidad entre el núcleo y la interfaz gráfica" #~ msgid "" #~ "Your IPython frontend and kernel versions are incompatible!!

We're sorry but we can't create an IPython console for you." #~ msgstr "" #~ "Sus versiones del núcleo y la interfaz gráfica de IPython son " #~ "incompatibles!!

Lo lamentamos pero no podemos crear una " #~ "terminal de IPython para usted." #~ msgid "Always edit in-place" #~ msgstr "Siempre editar en línea" #~ msgid "Show collection contents" #~ msgstr "Mostrar contenidos de listas" #~ msgid "" #~ "Resizing cells of a table of such size could take a long time.\n" #~ "Do you want to continue anyway?" #~ msgstr "" #~ "Redimensionar las celdas de una tabla de este tamaño puede\n" #~ "tomar mucho tiempo.\n" #~ "\n" #~ "¿Desea continuar de todas formas?" #~ msgid "Interrupt kernel" #~ msgstr "Interrumpir el núcleo" #~ msgid "Run &selection" #~ msgstr "Ejecutar &selección" #~ msgid "Patch Matplotlib figures" #~ msgstr "Parchear las gráficas de Matplotlib" #~ msgid "" #~ "Patching Matplotlib library will add a button to customize figure options " #~ "(Qt4Agg only) and fix some issues." #~ msgstr "" #~ "Al aplicar este parche a la librería Matplotlib se añadirá un botón (sólo " #~ "con\n" #~ "el backend Qt4Agg) para ajustar las opciones de curvas y gráficas y para\n" #~ "corregir algunos problemas." #~ msgid "(for example: kernel-3764.json, or simply 3764)" #~ msgstr "(por ejemplo: `kernel-3764.json`, o simplemente `3764`)" #~ msgid "Provide an IPython kernel connection file:" #~ msgstr "Provea un archivo de conexión para un núcleo de IPython" #~ msgid "Interpreter" #~ msgstr "Intérprete" #~ msgid "Dedicated Python interpreter" #~ msgstr "Intérprete de Python dedicado" #~ msgid "Open Python interpreter here" #~ msgstr "Abrir intérprete de Python aquí" #~ msgid "Import as array" #~ msgstr "Importar como arreglo" #~ msgid "(not installed)" #~ msgstr "(no está instalado)" #~ msgid "" #~ "This feature requires the pywin32 module.\n" #~ "It seems you don't have it installed." #~ msgstr "" #~ "Esta característica requiere la librería pywin32.\n" #~ "Al parecer no la tiene instalada." #~ msgid "Balloon tips" #~ msgstr "Mostrar globos de sugerencias" #~ msgid "Show single completion" #~ msgstr "" #~ "Mostrar la lista de resultados a completar aún con una sola elección" #~ msgid "Automatic notification to object inspector" #~ msgstr "Notificación automática al Inspector de objetos" #~ msgid "" #~ "If this option is enabled, object inspector\n" #~ "will automatically show informations on functions\n" #~ "entered in editor (this is triggered when entering\n" #~ "a left parenthesis after a valid function name)" #~ msgstr "" #~ "Si esta opción está activada, el Inspector de\n" #~ "objetos mostrará automáticamente información\n" #~ "sobre las funciones introducidas en el Editor\n" #~ "(esto se activa cuando se introduce un paréntesis\n" #~ "izquierdo después de un nombre de función válido" #~ msgid "" #~ "If this option is enabled, object inspector\n" #~ "will automatically show informations on functions\n" #~ "entered in console (this is triggered when entering\n" #~ "a left parenthesis after a valid function name)" #~ msgstr "" #~ "Si esta opción está activada, el Inspector de\n" #~ "objetos mostrará automáticamente información\n" #~ "sobre funciones introducidas en la Terminal \n" #~ "(esto se activa cuando se introduce un paréntesis\n" #~ "izquierdo después de un nombre de función válido)" #~ msgid "Open a Python interpreter at startup" #~ msgstr "Abrir un intérprete de Python al inicio" #~ msgid "
Installed version: %s" #~ msgstr "
Versión instalada: %s" #~ msgid "" #~ "Unable to open IPython console because no supported IPython version was " #~ "found.

Supported IPython versions: %s" #~ msgstr "" #~ "No es posible abrir un intérprete de IPython porque no se encontró " #~ "ninguna versión de IPython soportada por Spyder.

Versiones " #~ "soportadas son: %s" #~ msgid "Open an IPython console at startup" #~ msgstr "Abrir una terminal de IPython al inicio" #~ msgid "IPython Help" #~ msgstr "Ayuda de IPython" #~ msgid "Close current dockwidget" #~ msgstr "Cerrar el componente actual" #~ msgid "&Interpreters" #~ msgstr "&Intérpretes" #~ msgid "Qt Assistant" #~ msgstr "Documentación de Qt" #~ msgid "Web Resources" #~ msgstr "Recursos en la Web" #~ msgid "Windows and toolbars" #~ msgstr "Componentes y barras de herramientas" #~ msgid "Create a new Python script" #~ msgstr "Crear un nuevo archivo de Python" #~ msgid "Open text file" #~ msgstr "Abrir archivo de texto" #~ msgid "" #~ "Run selection or current \n" #~ "block of lines" #~ msgstr "" #~ "Ejecutar la selección \n" #~ "o el bloque actual" #~ msgid "Open Spyder path manager" #~ msgstr "Abrir el administrador de rutas de Spyder" #~ msgid "Maximize current plugin to fit the whole application window" #~ msgstr "" #~ "Maximizar el componente actual\n" #~ "para que ocupe toda la ventana" #~ msgid "" #~ "Restore current plugin to its original size and position within the " #~ "application window" #~ msgstr "" #~ "Restaurar el componente actual\n" #~ "a su tamaño y posición originales\n" #~ "dentro de la ventana principal" #~ msgid "Step Over" #~ msgstr "Saltar paso" #~ msgid "Debug Step Over" #~ msgstr "Depurar - Saltar paso" #~ msgid "Debug Continue" #~ msgstr "Continuar depurando" #~ msgid "Debug Step Into" #~ msgstr "Depurar - Ingresar en el paso" #~ msgid "Debug Step Return" #~ msgstr "Depurar - Salir del paso" #~ msgid "Run active script in a new Python interpreter" #~ msgstr "Ejecutar el archivo actual en un nuevo intérprete de Python" #~ msgid "" #~ "Debug current script in external console\n" #~ "(external console is executed in a separate process)" #~ msgstr "" #~ "Depurar el archivo actual en una terminal\n" #~ "externa, la cual es ejecutada en proceso\n" #~ "separado" #~ msgid "Edit run configurations" #~ msgstr "Editar las opciones de ejecución" #~ msgid "Run again last script in external console with the same options" #~ msgstr "" #~ "Ejecutar de nuevo el último archivo en un\n" #~ "intérprete externo con las mismas opciones" #~ msgid "" #~ "Run selected text or current block of lines \n" #~ "inside current external console's interpreter" #~ msgstr "" #~ "Ejecutar el texto seleccionado o el bloque\n" #~ "de líneas actual dentro del intérprete en uso" #~ msgid "Run %s" #~ msgstr "Ejecutar %s" #~ msgid "Run configurations" #~ msgstr "Opciones de ejecución" #~ msgid "Type \"copyright\", \"credits\" or \"license\" for more information." #~ msgstr "" #~ "Escriba \"copyright\", \"credits\" o \"license\" para más información." #~ msgid "Start an IPython kernel at startup" #~ msgstr "Abrir un núcleo de IPython al inicio" #~ msgid "This option is not available for IPython versions prior to v0.12." #~ msgstr "" #~ "Esta opción no está disponible para versiones de IPython\n" #~ "anteriores a la 0.12" #~ msgid "Format: " #~ msgstr "Formato:" #, fuzzy #~ msgid " Source" #~ msgstr "Origen" #~ msgid "Builtin Modules: spy.app, spy.window" #~ msgstr "Módulos integrados: spy.app, spy.window" #~ msgid "Open &interpreter" #~ msgstr "Abrir un &intérprete de Python" #~ msgid "Set the appropriate IPython color option" #~ msgstr "Ajustar la opción apropiada de color para IPython" #~ msgid "IPython interpreter command line options" #~ msgstr "Opciones de línea de comandos del intérprete de IPython" spyder-3.2.6/spyder/locale/spyder.pot0000664000175000017500000032611513224121062020422 0ustar carloscarlos00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR ORGANIZATION # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2017-12-14 15:40+-05\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: ENCODING\n" "Generated-By: pygettext.py 1.5\n" #: spyder/app/mainwindow.py:134 msgid "Initializing..." msgstr "" #: spyder/app/mainwindow.py:237 msgid "Python2 documentation" msgstr "" #: spyder/app/mainwindow.py:239 msgid "Python3 documentation" msgstr "" #: spyder/app/mainwindow.py:241 msgid "Numpy and Scipy documentation" msgstr "" #: spyder/app/mainwindow.py:243 msgid "Matplotlib documentation" msgstr "" #: spyder/app/mainwindow.py:246 msgid "PyQt4 Reference Guide" msgstr "" #: spyder/app/mainwindow.py:249 msgid "PyQt4 API Reference" msgstr "" #: spyder/app/mainwindow.py:252 msgid "PyQt5 Reference Guide" msgstr "" #: spyder/app/mainwindow.py:255 msgid "PyQt5 API Reference" msgstr "" #: spyder/app/mainwindow.py:257 msgid "WinPython" msgstr "" #: spyder/app/mainwindow.py:530 msgid "An error occurred while creating a socket needed by Spyder. Please, try to run as an Administrator from cmd.exe the following command and then restart your computer:

netsh winsock reset
" msgstr "" #: spyder/app/mainwindow.py:562 msgid "Close current pane" msgstr "" #: spyder/app/mainwindow.py:567 msgid "Lock panes" msgstr "" #: spyder/app/mainwindow.py:574 msgid "Use next layout" msgstr "" #: spyder/app/mainwindow.py:578 msgid "Use previous layout" msgstr "" #: spyder/app/mainwindow.py:588 spyder/widgets/editor.py:497 msgid "File switcher..." msgstr "" #: spyder/app/mainwindow.py:590 msgid "Fast switch between files" msgstr "" #: spyder/app/mainwindow.py:596 msgid "Symbol finder..." msgstr "" #: spyder/app/mainwindow.py:598 msgid "Fast symbol search in file" msgstr "" #: spyder/app/mainwindow.py:617 spyder/widgets/sourcecode/codeeditor.py:2661 msgid "Undo" msgstr "" #: spyder/app/mainwindow.py:619 spyder/widgets/sourcecode/codeeditor.py:2664 msgid "Redo" msgstr "" #: spyder/app/mainwindow.py:621 spyder/widgets/shell.py:123 #: spyder/widgets/sourcecode/codeeditor.py:2670 #: spyder/widgets/variableexplorer/arrayeditor.py:467 #: spyder/widgets/variableexplorer/collectionseditor.py:671 #: spyder/widgets/variableexplorer/dataframeeditor.py:586 msgid "Copy" msgstr "" #: spyder/app/mainwindow.py:623 spyder/widgets/shell.py:119 #: spyder/widgets/sourcecode/codeeditor.py:2667 msgid "Cut" msgstr "" #: spyder/app/mainwindow.py:625 spyder/widgets/shell.py:127 #: spyder/widgets/sourcecode/codeeditor.py:2673 #: spyder/widgets/variableexplorer/collectionseditor.py:668 msgid "Paste" msgstr "" #: spyder/app/mainwindow.py:628 spyder/widgets/shell.py:140 #: spyder/widgets/sourcecode/codeeditor.py:2676 msgid "Select All" msgstr "" #: spyder/app/mainwindow.py:638 spyder/plugins/editor.py:1423 msgid "&File" msgstr "" #: spyder/app/mainwindow.py:639 spyder/plugins/editor.py:1411 msgid "File toolbar" msgstr "" #: spyder/app/mainwindow.py:643 spyder/plugins/editor.py:1424 msgid "&Edit" msgstr "" #: spyder/app/mainwindow.py:644 spyder/plugins/editor.py:1421 msgid "Edit toolbar" msgstr "" #: spyder/app/mainwindow.py:648 spyder/plugins/editor.py:1425 msgid "&Search" msgstr "" #: spyder/app/mainwindow.py:649 spyder/plugins/editor.py:1413 msgid "Search toolbar" msgstr "" #: spyder/app/mainwindow.py:653 spyder/plugins/editor.py:1426 msgid "Sour&ce" msgstr "" #: spyder/app/mainwindow.py:654 spyder/plugins/editor.py:1415 msgid "Source toolbar" msgstr "" #: spyder/app/mainwindow.py:658 spyder/plugins/editor.py:803 #: spyder/plugins/editor.py:1427 msgid "&Run" msgstr "" #: spyder/app/mainwindow.py:659 spyder/plugins/editor.py:1417 msgid "Run toolbar" msgstr "" #: spyder/app/mainwindow.py:663 spyder/plugins/editor.py:762 msgid "&Debug" msgstr "" #: spyder/app/mainwindow.py:664 spyder/plugins/editor.py:1419 msgid "Debug toolbar" msgstr "" #: spyder/app/mainwindow.py:668 msgid "C&onsoles" msgstr "" #: spyder/app/mainwindow.py:671 msgid "&Projects" msgstr "" #: spyder/app/mainwindow.py:674 spyder/plugins/editor.py:1428 msgid "&Tools" msgstr "" #: spyder/app/mainwindow.py:677 spyder/plugins/editor.py:1429 msgid "&View" msgstr "" #: spyder/app/mainwindow.py:680 spyder/plugins/editor.py:1430 msgid "&Help" msgstr "" #: spyder/app/mainwindow.py:685 msgid "Welcome to Spyder!" msgstr "" #: spyder/app/mainwindow.py:690 msgid "Pre&ferences" msgstr "" #: spyder/app/mainwindow.py:697 spyder/widgets/pathmanager.py:53 msgid "PYTHONPATH manager" msgstr "" #: spyder/app/mainwindow.py:700 msgid "Python Path Manager" msgstr "" #: spyder/app/mainwindow.py:703 msgid "Update module names list" msgstr "" #: spyder/app/mainwindow.py:706 msgid "Refresh list of module names available in PYTHONPATH" msgstr "" #: spyder/app/mainwindow.py:709 msgid "Reset Spyder to factory defaults" msgstr "" #: spyder/app/mainwindow.py:714 msgid "Current user environment variables..." msgstr "" #: spyder/app/mainwindow.py:716 msgid "Show and edit current user environment variables in Windows registry (i.e. for all sessions)" msgstr "" #: spyder/app/mainwindow.py:725 spyder/app/mainwindow.py:1147 msgid "External Tools" msgstr "" #: spyder/app/mainwindow.py:728 msgid "WinPython control panel" msgstr "" #: spyder/app/mainwindow.py:737 msgid "Qt Designer" msgstr "" #: spyder/app/mainwindow.py:742 msgid "Qt Linguist" msgstr "" #: spyder/app/mainwindow.py:748 msgid "Qt examples" msgstr "" #: spyder/app/mainwindow.py:768 msgid "guidata examples" msgstr "" #: spyder/app/mainwindow.py:779 msgid "guiqwt examples" msgstr "" #: spyder/app/mainwindow.py:784 msgid "Sift" msgstr "" #: spyder/app/mainwindow.py:794 msgid "ViTables" msgstr "" #: spyder/app/mainwindow.py:808 msgid "Fullscreen mode" msgstr "" #: spyder/app/mainwindow.py:820 msgid "Main toolbar" msgstr "" #: spyder/app/mainwindow.py:829 msgid "" "Spyder Internal Console\n" "\n" "This console is used to report application\n" "internal errors and to inspect Spyder\n" "internals with the following commands:\n" " spy.app, spy.window, dir(spy)\n" "\n" "Please don't use it to run your code\n" "\n" msgstr "" #: spyder/app/mainwindow.py:846 msgid "Loading help..." msgstr "" #: spyder/app/mainwindow.py:853 msgid "Loading outline explorer..." msgstr "" #: spyder/app/mainwindow.py:861 msgid "Loading editor..." msgstr "" #: spyder/app/mainwindow.py:867 spyder/plugins/console.py:140 #: spyder/widgets/ipythonconsole/client.py:417 msgid "&Quit" msgstr "" #: spyder/app/mainwindow.py:869 spyder/plugins/console.py:142 msgid "Quit" msgstr "" #: spyder/app/mainwindow.py:873 msgid "&Restart" msgstr "" #: spyder/app/mainwindow.py:875 msgid "Restart" msgstr "" #: spyder/app/mainwindow.py:889 msgid "Loading file explorer..." msgstr "" #: spyder/app/mainwindow.py:896 msgid "Loading history plugin..." msgstr "" #: spyder/app/mainwindow.py:907 msgid "Loading online help..." msgstr "" #: spyder/app/mainwindow.py:912 msgid "Loading project explorer..." msgstr "" #: spyder/app/mainwindow.py:925 msgid "Loading namespace browser..." msgstr "" #: spyder/app/mainwindow.py:931 msgid "Loading IPython console..." msgstr "" #: spyder/app/mainwindow.py:936 msgid "Setting up main window..." msgstr "" #: spyder/app/mainwindow.py:939 msgid "Dependencies..." msgstr "" #: spyder/app/mainwindow.py:943 msgid "Report issue..." msgstr "" #: spyder/app/mainwindow.py:947 msgid "Spyder support..." msgstr "" #: spyder/app/mainwindow.py:950 msgid "Check for updates..." msgstr "" #: spyder/app/mainwindow.py:973 msgid "Spyder documentation" msgstr "" #: spyder/app/mainwindow.py:981 msgid "Spyder tutorial" msgstr "" #: spyder/app/mainwindow.py:986 msgid "Shortcuts Summary" msgstr "" #: spyder/app/mainwindow.py:992 msgid "Interactive tours" msgstr "" #: spyder/app/mainwindow.py:1018 msgid "Python documentation" msgstr "" #: spyder/app/mainwindow.py:1024 msgid "IPython documentation" msgstr "" #: spyder/app/mainwindow.py:1025 msgid "Intro to IPython" msgstr "" #: spyder/app/mainwindow.py:1027 msgid "Quick reference" msgstr "" #: spyder/app/mainwindow.py:1029 msgid "Console help" msgstr "" #: spyder/app/mainwindow.py:1059 msgid "Installed Python modules" msgstr "" #: spyder/app/mainwindow.py:1063 msgid "Online documentation" msgstr "" #: spyder/app/mainwindow.py:1076 msgid "Qt documentation" msgstr "" #: spyder/app/mainwindow.py:1082 msgid "About %s..." msgstr "" #: spyder/app/mainwindow.py:1113 msgid "Panes" msgstr "" #: spyder/app/mainwindow.py:1115 msgid "Toolbars" msgstr "" #: spyder/app/mainwindow.py:1116 msgid "Window layouts" msgstr "" #: spyder/app/mainwindow.py:1125 spyder/app/mainwindow.py:1924 #: spyder/app/mainwindow.py:1925 msgid "Show toolbars" msgstr "" #: spyder/app/mainwindow.py:1140 msgid "Attached console window (debugging)" msgstr "" #: spyder/app/mainwindow.py:1317 spyder/plugins/console.py:220 #: spyder/plugins/projects.py:248 spyder/widgets/explorer.py:708 #: spyder/widgets/explorer.py:813 #: spyder/widgets/variableexplorer/arrayeditor.py:587 #: spyder/widgets/variableexplorer/collectionseditor.py:427 #: spyder/widgets/variableexplorer/dataframeeditor.py:752 #: spyder/widgets/variableexplorer/dataframeeditor.py:756 #: spyder/widgets/variableexplorer/namespacebrowser.py:299 msgid "Error" msgstr "" #: spyder/app/mainwindow.py:1318 msgid "You have missing dependencies!

%s

Please install them to avoid this message.

Note: Spyder could work without some of these dependencies, however to have a smooth experience when using Spyder we strongly recommend you to install all the listed missing dependencies.

Failing to install these dependencies might result in bugs. Please be sure that any found bugs are not the direct result of missing dependencies, prior to reporting a new issue." msgstr "" #: spyder/app/mainwindow.py:1771 msgid "Spyder Default Layout" msgstr "" #: spyder/app/mainwindow.py:1789 msgid "Save current layout" msgstr "" #: spyder/app/mainwindow.py:1793 msgid "Layout preferences" msgstr "" #: spyder/app/mainwindow.py:1797 msgid "Reset to spyder default" msgstr "" #: spyder/app/mainwindow.py:1817 spyder/app/mainwindow.py:1839 #: spyder/app/mainwindow.py:1902 spyder/app/mainwindow.py:2722 #: spyder/plugins/configdialog.py:1346 spyder/plugins/ipythonconsole.py:131 #: spyder/plugins/ipythonconsole.py:927 spyder/plugins/ipythonconsole.py:1365 #: spyder/plugins/maininterpreter.py:149 spyder/plugins/maininterpreter.py:174 #: spyder/plugins/maininterpreter.py:203 spyder/utils/environ.py:95 #: spyder/utils/environ.py:108 #: spyder/widgets/ipythonconsole/namespacebrowser.py:131 #: spyder/widgets/ipythonconsole/namespacebrowser.py:149 #: spyder/widgets/variableexplorer/arrayeditor.py:510 #: spyder/widgets/variableexplorer/collectionseditor.py:416 #: spyder/widgets/variableexplorer/collectionseditor.py:1092 msgid "Warning" msgstr "" #: spyder/app/mainwindow.py:1818 msgid "" "Window layout will be reset to default settings: this affects window position, size and dockwidgets.\n" "Do you want to continue?" msgstr "" #: spyder/app/mainwindow.py:1840 msgid "Layout %s will be overwritten. Do you want to continue?" msgstr "" #: spyder/app/mainwindow.py:1903 msgid "Quick switch layout #%s has not yet been defined." msgstr "" #: spyder/app/mainwindow.py:1921 spyder/app/mainwindow.py:1922 msgid "Hide toolbars" msgstr "" #: spyder/app/mainwindow.py:2237 spyder/app/mainwindow.py:2238 msgid "Maximize current pane" msgstr "" #: spyder/app/mainwindow.py:2241 msgid "Restore current pane" msgstr "" #: spyder/app/mainwindow.py:2242 msgid "Restore pane to its original size" msgstr "" #: spyder/app/mainwindow.py:2327 msgid "About %s" msgstr "" #: spyder/app/mainwindow.py:2460 spyder/plugins/editor.py:168 #: spyder/plugins/runconfig.py:354 spyder/plugins/runconfig.py:476 #: spyder/utils/programs.py:286 spyder/widgets/explorer.py:335 msgid "Run" msgstr "" #: spyder/app/mainwindow.py:2461 msgid "Running an external system terminal is not supported on platform %s." msgstr "" #: spyder/app/mainwindow.py:2723 msgid "Spyder will restart and reset to default settings:

Do you want to continue?" msgstr "" #: spyder/app/mainwindow.py:2851 spyder/widgets/helperwidgets.py:254 msgid "Spyder updates" msgstr "" #: spyder/app/mainwindow.py:2852 spyder/plugins/configdialog.py:836 msgid "Check for updates on startup" msgstr "" #: spyder/app/mainwindow.py:2871 msgid "
IMPORTANT NOTE: It seems that you are using Spyder with Anaconda/Miniconda. Please don't use pip to update it as that will probably break your installation.

Instead, please wait until new conda packages are available and use conda to perform the update.
" msgstr "" #: spyder/app/mainwindow.py:2881 msgid "Spyder %s is available!

Please use your package manager to update Spyder or go to our Releases page to download this new version.

If you are not sure how to proceed to update Spyder please refer to our Installation instructions." msgstr "" #: spyder/app/mainwindow.py:2894 msgid "Spyder is up to date." msgstr "" #: spyder/app/restart.py:134 msgid "" "It was not possible to close the previous Spyder instance.\n" "Restart aborted." msgstr "" #: spyder/app/restart.py:136 msgid "" "Spyder could not reset to factory defaults.\n" "Restart aborted." msgstr "" #: spyder/app/restart.py:138 msgid "" "It was not possible to restart Spyder.\n" "Operation aborted." msgstr "" #: spyder/app/restart.py:140 msgid "Spyder exit error" msgstr "" #: spyder/app/restart.py:141 msgid "Spyder reset error" msgstr "" #: spyder/app/restart.py:142 msgid "Spyder restart error" msgstr "" #: spyder/app/restart.py:183 msgid "Closing Spyder" msgstr "" #: spyder/app/restart.py:257 msgid "Resetting Spyder to defaults" msgstr "" #: spyder/app/restart.py:289 msgid "Restarting" msgstr "" #: spyder/app/tour.py:123 msgid "Welcome to the Introduction tour" msgstr "" #: spyder/app/tour.py:124 msgid "Spyder is a powerful Interactive Development Environment (or IDE) for the Python programming language.

Here we are going to guide you through its most important features.

Please use the arrow keys or click on the buttons below to move along the tour." msgstr "" #: spyder/app/tour.py:133 msgid "The Editor" msgstr "" #: spyder/app/tour.py:134 msgid "This is the pane where you write Python code before evaluating it. You can get automatic suggestions and completions while writing, by pressing the Tab key next to a given text.

The Editor comes with a line number area (highlighted here in red), where Spyder shows warnings and syntax errors. They can help you to detect potential problems before running the code.

You can also set debug breakpoints in the line number area, by doing a double click next to a non-empty line." msgstr "" #: spyder/app/tour.py:149 msgid "The IPython console" msgstr "" #: spyder/app/tour.py:150 msgid "This is one of panes where you can run or execute the code you wrote on the Editor. To do it you need to press the F5 key.

This console comes with several useful features that greatly improve your programming workflow (like syntax highlighting and inline plots). If you want to know more about them, please follow this link.

Please click on the button below to run some simple code in this console. This will be useful to show you other important features." msgstr "" #: spyder/app/tour.py:166 msgid "The Variable Explorer" msgstr "" #: spyder/app/tour.py:167 msgid "In this pane you can view and edit the variables generated during the execution of a program, or those entered directly in one of Spyder consoles.

As you can see, the Variable Explorer is showing the variables generated during the last step of this tour. By doing a double-click on any of them, a new window will be opened, where you can inspect and modify their contents." msgstr "" #: spyder/app/tour.py:179 spyder/plugins/help.py:479 #: spyder/plugins/help.py:921 spyder/widgets/internalshell.py:270 msgid "Help" msgstr "" #: spyder/app/tour.py:180 msgid "This pane displays documentation of the functions, classes, methods or modules you are currently using in the Editor or the Consoles.

To use it, you need to press Ctrl+I in front of an object. If that object has some documentation associated with it, it will be displayed here." msgstr "" #: spyder/app/tour.py:190 msgid "The File Explorer" msgstr "" #: spyder/app/tour.py:191 msgid "This pane lets you navigate through the directories and files present in your computer.

You can also open any of these files with its corresponding application, by doing a double click on it.

There is one exception to this rule: plain-text files will always be opened in the Spyder Editor." msgstr "" #: spyder/app/tour.py:201 msgid "The History Log" msgstr "" #: spyder/app/tour.py:202 msgid "This pane records all commands introduced in the Python and IPython consoles." msgstr "" #: spyder/app/tour.py:250 msgid "Spyder is an interactive development environment based on bla" msgstr "" #: spyder/app/tour.py:254 msgid "Welcome to Spyder introduction tour" msgstr "" #: spyder/app/tour.py:255 msgid "Spyder is an interactive development environment based on bla" msgstr "" #: spyder/app/tour.py:260 msgid "Introduction tour" msgstr "" #: spyder/app/tour.py:261 msgid "New features in version 3.0" msgstr "" #: spyder/app/tour.py:555 spyder/plugins/ipythonconsole.py:446 msgid "Run code" msgstr "" #: spyder/app/tour.py:830 msgid "Go to step: " msgstr "" #: spyder/config/base.py:257 msgid "Update LANGUAGE_CODES (inside config/base.py) if a new translation has been added to Spyder" msgstr "" #: spyder/config/utils.py:24 msgid "Python files" msgstr "" #: spyder/config/utils.py:25 msgid "Cython/Pyrex files" msgstr "" #: spyder/config/utils.py:26 msgid "C files" msgstr "" #: spyder/config/utils.py:27 msgid "C++ files" msgstr "" #: spyder/config/utils.py:28 msgid "OpenCL files" msgstr "" #: spyder/config/utils.py:29 msgid "Fortran files" msgstr "" #: spyder/config/utils.py:30 msgid "IDL files" msgstr "" #: spyder/config/utils.py:31 msgid "MATLAB files" msgstr "" #: spyder/config/utils.py:32 msgid "Julia files" msgstr "" #: spyder/config/utils.py:33 msgid "Yaml files" msgstr "" #: spyder/config/utils.py:34 msgid "Patch and diff files" msgstr "" #: spyder/config/utils.py:35 msgid "Batch files" msgstr "" #: spyder/config/utils.py:36 spyder/utils/iofuncs.py:426 msgid "Text files" msgstr "" #: spyder/config/utils.py:37 msgid "reStructuredText files" msgstr "" #: spyder/config/utils.py:38 msgid "gettext files" msgstr "" #: spyder/config/utils.py:39 msgid "NSIS files" msgstr "" #: spyder/config/utils.py:40 msgid "Web page files" msgstr "" #: spyder/config/utils.py:41 msgid "XML files" msgstr "" #: spyder/config/utils.py:42 msgid "Javascript files" msgstr "" #: spyder/config/utils.py:43 msgid "Json files" msgstr "" #: spyder/config/utils.py:44 msgid "IPython notebooks" msgstr "" #: spyder/config/utils.py:45 msgid "Enaml files" msgstr "" #: spyder/config/utils.py:46 msgid "Configuration files" msgstr "" #: spyder/config/utils.py:48 msgid "Markdown files" msgstr "" #: spyder/config/utils.py:52 spyder/widgets/explorer.py:781 msgid "All files" msgstr "" #: spyder/config/utils.py:134 msgid "Supported text files" msgstr "" #: spyder/plugins/__init__.py:508 spyder/plugins/editor.py:105 #: spyder/plugins/editor.py:568 spyder/plugins/editor.py:1819 #: spyder/plugins/help.py:117 spyder/plugins/help.py:380 #: spyder/widgets/editor.py:534 spyder/widgets/sourcecode/codeeditor.py:98 #: spyder/widgets/sourcecode/codeeditor.py:3193 msgid "Editor" msgstr "" #: spyder/plugins/configdialog.py:144 msgid "Reset to defaults" msgstr "" #: spyder/plugins/configdialog.py:156 msgid "Preferences" msgstr "" #: spyder/plugins/configdialog.py:508 msgid "Invalid directory path" msgstr "" #: spyder/plugins/configdialog.py:511 spyder/plugins/configdialog.py:526 #: spyder/plugins/runconfig.py:220 spyder/plugins/runconfig.py:268 #: spyder/plugins/workingdirectory.py:240 spyder/widgets/explorer.py:695 #: spyder/widgets/findinfiles.py:494 spyder/widgets/pathmanager.py:258 #: spyder/widgets/projects/projectdialog.py:155 msgid "Select directory" msgstr "" #: spyder/plugins/configdialog.py:538 msgid "Invalid file path" msgstr "" #: spyder/plugins/configdialog.py:541 spyder/plugins/configdialog.py:558 msgid "Select file" msgstr "" #: spyder/plugins/configdialog.py:557 msgid "All files (*)" msgstr "" #: spyder/plugins/configdialog.py:630 msgid "Bold" msgstr "" #: spyder/plugins/configdialog.py:633 msgid "Italic" msgstr "" #: spyder/plugins/configdialog.py:687 msgid "Font: " msgstr "" #: spyder/plugins/configdialog.py:693 msgid "Size: " msgstr "" #: spyder/plugins/configdialog.py:712 msgid "Font style" msgstr "" #: spyder/plugins/configdialog.py:789 msgid "Spyder needs to restart to change the following setting:" msgstr "" #: spyder/plugins/configdialog.py:792 msgid "Spyder needs to restart to change the following settings:" msgstr "" #: spyder/plugins/configdialog.py:794 msgid "Do you wish to restart now?" msgstr "" #: spyder/plugins/configdialog.py:800 msgid "Information" msgstr "" #: spyder/plugins/configdialog.py:814 spyder/plugins/configdialog.py:821 #: spyder/widgets/projects/configdialog.py:74 msgid "General" msgstr "" #: spyder/plugins/configdialog.py:824 msgid "Language" msgstr "" #: spyder/plugins/configdialog.py:827 msgid "Use a single instance" msgstr "" #: spyder/plugins/configdialog.py:829 msgid "Set this to open external
Python files in an already running instance (Requires a restart)" msgstr "" #: spyder/plugins/configdialog.py:832 msgid "Prompt when exiting" msgstr "" #: spyder/plugins/configdialog.py:833 msgid "Pop up internal console when internal errors appear" msgstr "" #: spyder/plugins/configdialog.py:853 spyder/plugins/editor.py:114 #: spyder/plugins/ipythonconsole.py:290 #: spyder/widgets/projects/configdialog.py:81 msgid "Interface" msgstr "" #: spyder/plugins/configdialog.py:861 msgid "Qt windows style" msgstr "" #: spyder/plugins/configdialog.py:867 msgid "Icon theme" msgstr "" #: spyder/plugins/configdialog.py:871 msgid "Vertical title bars in panes" msgstr "" #: spyder/plugins/configdialog.py:873 msgid "Vertical tabs in panes" msgstr "" #: spyder/plugins/configdialog.py:875 msgid "Animated toolbars and panes" msgstr "" #: spyder/plugins/configdialog.py:877 msgid "Tear off menus" msgstr "" #: spyder/plugins/configdialog.py:878 msgid "Set this to detach any
menu from the main window" msgstr "" #: spyder/plugins/configdialog.py:880 msgid "Custom margin for panes:" msgstr "" #: spyder/plugins/configdialog.py:882 msgid "pixels" msgstr "" #: spyder/plugins/configdialog.py:889 msgid "Cursor blinking:" msgstr "" #: spyder/plugins/configdialog.py:891 msgid "ms" msgstr "" #: spyder/plugins/configdialog.py:930 msgid "Status bar" msgstr "" #: spyder/plugins/configdialog.py:931 msgid "Show status bar" msgstr "" #: spyder/plugins/configdialog.py:933 msgid "Show memory usage every" msgstr "" #: spyder/plugins/configdialog.py:935 spyder/plugins/configdialog.py:944 #: spyder/plugins/editor.py:139 spyder/plugins/editor.py:283 msgid " ms" msgstr "" #: spyder/plugins/configdialog.py:942 msgid "Show CPU usage every" msgstr "" #: spyder/plugins/configdialog.py:975 msgid "Screen resolution" msgstr "" #: spyder/plugins/configdialog.py:977 msgid "Configuration for high DPI screens

Please see {0}<> for more information about these options (in English)." msgstr "" #: spyder/plugins/configdialog.py:987 msgid "Normal" msgstr "" #: spyder/plugins/configdialog.py:991 msgid "Enable auto high DPI scaling" msgstr "" #: spyder/plugins/configdialog.py:994 msgid "Set this for high DPI displays" msgstr "" #: spyder/plugins/configdialog.py:998 msgid "Set a custom high DPI scaling" msgstr "" #: spyder/plugins/configdialog.py:1001 msgid "Set this for high DPI displays when auto scaling does not work" msgstr "" #: spyder/plugins/configdialog.py:1007 msgid "Enter values for different screens separated by semicolons ';', float values are supported" msgstr "" #: spyder/plugins/configdialog.py:1034 msgid "Plain text font" msgstr "" #: spyder/plugins/configdialog.py:1040 msgid "Rich text font" msgstr "" #: spyder/plugins/configdialog.py:1043 msgid "Fonts" msgstr "" #: spyder/plugins/configdialog.py:1057 msgid "Appearance" msgstr "" #: spyder/plugins/configdialog.py:1059 spyder/plugins/ipythonconsole.py:579 msgid "Advanced Settings" msgstr "" #: spyder/plugins/configdialog.py:1095 msgid "Syntax coloring" msgstr "" #: spyder/plugins/configdialog.py:1108 msgid "Here you can select the color scheme used in the Editor and all other Spyder plugins.

You can also edit the color schemes provided by Spyder or create your own ones by using the options provided below.
" msgstr "" #: spyder/plugins/configdialog.py:1113 msgid "Edit selected" msgstr "" #: spyder/plugins/configdialog.py:1114 msgid "Create new scheme" msgstr "" #: spyder/plugins/configdialog.py:1115 spyder/widgets/explorer.py:574 #: spyder/widgets/projects/explorer.py:242 spyder/widgets/shell.py:136 msgid "Delete" msgstr "" #: spyder/plugins/configdialog.py:1118 msgid "Reset" msgstr "" #: spyder/plugins/configdialog.py:1125 msgid "Scheme:" msgstr "" #: spyder/plugins/configdialog.py:1156 msgid "Manage color schemes" msgstr "" #: spyder/plugins/configdialog.py:1347 msgid "Are you sure you want to delete this scheme?" msgstr "" #: spyder/plugins/configdialog.py:1464 msgid "Text" msgstr "" #: spyder/plugins/configdialog.py:1466 msgid "Highlight" msgstr "" #: spyder/plugins/configdialog.py:1468 msgid "Background" msgstr "" #: spyder/plugins/configdialog.py:1472 msgid "Scheme name:" msgstr "" #: spyder/plugins/configdialog.py:1479 msgid "Color scheme editor" msgstr "" #: spyder/plugins/console.py:115 msgid "Internal console" msgstr "" #: spyder/plugins/console.py:145 msgid "&Run..." msgstr "" #: spyder/plugins/console.py:147 msgid "Run a Python script" msgstr "" #: spyder/plugins/console.py:150 msgid "Environment variables..." msgstr "" #: spyder/plugins/console.py:152 msgid "Show and edit environment variables (for current session)" msgstr "" #: spyder/plugins/console.py:156 msgid "Show sys.path contents..." msgstr "" #: spyder/plugins/console.py:158 msgid "Show (read-only) sys.path" msgstr "" #: spyder/plugins/console.py:161 msgid "Buffer..." msgstr "" #: spyder/plugins/console.py:162 spyder/plugins/history.py:43 msgid "Set maximum line count" msgstr "" #: spyder/plugins/console.py:165 msgid "External editor path..." msgstr "" #: spyder/plugins/console.py:166 msgid "Set external editor executable path" msgstr "" #: spyder/plugins/console.py:169 spyder/plugins/editor.py:149 #: spyder/plugins/help.py:152 spyder/plugins/help.py:355 #: spyder/plugins/history.py:46 spyder/plugins/history.py:157 msgid "Wrap lines" msgstr "" #: spyder/plugins/console.py:172 spyder/plugins/editor.py:185 #: spyder/plugins/ipythonconsole.py:300 msgid "Display balloon tips" msgstr "" #: spyder/plugins/console.py:176 spyder/plugins/editor.py:179 msgid "Automatic code completion" msgstr "" #: spyder/plugins/console.py:180 spyder/plugins/editor.py:183 msgid "Enter key selects completion" msgstr "" #: spyder/plugins/console.py:185 msgid "Internal console settings" msgstr "" #: spyder/plugins/console.py:221 msgid "Spyder has encountered a problem.
Sorry for the inconvenience.

You can automatically submit this error to our Github issues tracker.

Note: You need a Github account for that." msgstr "" #: spyder/plugins/console.py:231 msgid "Submit to Github" msgstr "" #: spyder/plugins/console.py:283 msgid "Run Python script" msgstr "" #: spyder/plugins/console.py:284 spyder/widgets/explorer.py:796 msgid "Python scripts" msgstr "" #: spyder/plugins/console.py:329 msgid "Buffer" msgstr "" #: spyder/plugins/console.py:330 msgid "Maximum line count" msgstr "" #: spyder/plugins/console.py:340 msgid "External editor" msgstr "" #: spyder/plugins/console.py:341 msgid "External editor executable path:" msgstr "" #: spyder/plugins/editor.py:59 msgid "Manipulate Jupyter notebooks on the Editor" msgstr "" #: spyder/plugins/editor.py:111 msgid "Edit template for new modules" msgstr "" #: spyder/plugins/editor.py:116 msgid "Show tab bar" msgstr "" #: spyder/plugins/editor.py:122 spyder/plugins/editor.py:199 #: spyder/plugins/help.py:151 spyder/plugins/history.py:45 #: spyder/plugins/ipythonconsole.py:332 msgid "Source code" msgstr "" #: spyder/plugins/editor.py:123 msgid "Show line numbers" msgstr "" #: spyder/plugins/editor.py:124 spyder/plugins/editor.py:985 msgid "Show blank spaces" msgstr "" #: spyder/plugins/editor.py:125 msgid "Show vertical line after" msgstr "" #: spyder/plugins/editor.py:126 msgid "characters" msgstr "" #: spyder/plugins/editor.py:133 msgid "Highlight current line" msgstr "" #: spyder/plugins/editor.py:135 msgid "Highlight current cell" msgstr "" #: spyder/plugins/editor.py:137 msgid "Highlight occurrences after" msgstr "" #: spyder/plugins/editor.py:169 msgid "Save all files before running script" msgstr "" #: spyder/plugins/editor.py:172 msgid "Run selection" msgstr "" #: spyder/plugins/editor.py:173 msgid "Maintain focus in the Editor after running cells or selections" msgstr "" #: spyder/plugins/editor.py:176 msgid "Introspection" msgstr "" #: spyder/plugins/editor.py:181 msgid "Case sensitive code completion" msgstr "" #: spyder/plugins/editor.py:186 msgid "Link to object definition" msgstr "" #: spyder/plugins/editor.py:188 msgid "" "If this option is enabled, clicking on an object\n" "name (left-click + Ctrl key) will go this object\n" "definition (if resolved)." msgstr "" #: spyder/plugins/editor.py:192 msgid "Warning:
The Python module rope is not installed on this computer: calltips, code completion and go-to-definition features won't be available." msgstr "" #: spyder/plugins/editor.py:200 msgid "Automatic insertion of parentheses, braces and brackets" msgstr "" #: spyder/plugins/editor.py:203 msgid "Automatic insertion of closing quotes" msgstr "" #: spyder/plugins/editor.py:205 msgid "Automatic insertion of colons after 'for', 'if', 'def', etc" msgstr "" #: spyder/plugins/editor.py:208 msgid "Automatic indentation after 'else', 'elif', etc." msgstr "" #: spyder/plugins/editor.py:210 msgid "Indentation characters: " msgstr "" #: spyder/plugins/editor.py:211 msgid "2 spaces" msgstr "" #: spyder/plugins/editor.py:212 msgid "3 spaces" msgstr "" #: spyder/plugins/editor.py:213 msgid "4 spaces" msgstr "" #: spyder/plugins/editor.py:214 msgid "5 spaces" msgstr "" #: spyder/plugins/editor.py:215 msgid "6 spaces" msgstr "" #: spyder/plugins/editor.py:216 msgid "7 spaces" msgstr "" #: spyder/plugins/editor.py:217 msgid "8 spaces" msgstr "" #: spyder/plugins/editor.py:218 msgid "Tabulations" msgstr "" #: spyder/plugins/editor.py:219 msgid "Tab stop width:" msgstr "" #: spyder/plugins/editor.py:219 msgid "spaces" msgstr "" #: spyder/plugins/editor.py:231 msgid "Tab always indent" msgstr "" #: spyder/plugins/editor.py:233 msgid "" "If enabled, pressing Tab will always indent,\n" "even when the cursor is not at the beginning\n" "of a line (when this option is enabled, code\n" "completion may be triggered using the alternate\n" "shortcut: Ctrl+Space)" msgstr "" #: spyder/plugins/editor.py:238 msgid "Intelligent backspace" msgstr "" #: spyder/plugins/editor.py:240 msgid "Automatically remove trailing spaces when saving files" msgstr "" #: spyder/plugins/editor.py:244 msgid "Analysis" msgstr "" #: spyder/plugins/editor.py:246 msgid "(Refer to the {} page)" msgstr "" #: spyder/plugins/editor.py:251 msgid "Real-time code analysis" msgstr "" #: spyder/plugins/editor.py:253 msgid "

If enabled, Python source code will be analyzed using pyflakes, lines containing errors or warnings will be highlighted.

Note: add analysis:ignore in a comment to ignore code analysis warnings.

" msgstr "" #: spyder/plugins/editor.py:261 msgid "Code analysis requires pyflakes %s+" msgstr "" #: spyder/plugins/editor.py:263 msgid "Real-time code style analysis" msgstr "" #: spyder/plugins/editor.py:265 msgid "

If enabled, Python source code will be analyzed using pycodestyle, lines that are not following PEP8 style guide will be highlighted.

Note: add analysis:ignore in a comment to ignore style analysis warnings.

" msgstr "" #: spyder/plugins/editor.py:272 msgid "Code annotations (TODO, FIXME, XXX, HINT, TIP, @todo, HACK, BUG, OPTIMIZE, !!!, ???)" msgstr "" #: spyder/plugins/editor.py:276 msgid "Perform analysis when saving file and every" msgstr "" #: spyder/plugins/editor.py:280 msgid "Perform analysis only when saving file" msgstr "" #: spyder/plugins/editor.py:339 msgid "End-of-line characters" msgstr "" #: spyder/plugins/editor.py:340 msgid "When opening a text file containing mixed end-of-line characters (this may raise syntax errors in the consoles on Windows platforms), Spyder may fix the file automatically." msgstr "" #: spyder/plugins/editor.py:346 msgid "Fix automatically and show warning message box" msgstr "" #: spyder/plugins/editor.py:357 spyder/plugins/ipythonconsole.py:573 #: spyder/plugins/variableexplorer.py:35 msgid "Display" msgstr "" #: spyder/plugins/editor.py:359 msgid "Code Introspection/Analysis" msgstr "" #: spyder/plugins/editor.py:362 msgid "Advanced settings" msgstr "" #: spyder/plugins/editor.py:644 msgid "&New file..." msgstr "" #: spyder/plugins/editor.py:645 spyder/widgets/explorer.py:773 #: spyder/widgets/explorer.py:780 msgid "New file" msgstr "" #: spyder/plugins/editor.py:654 msgid "O&pen last closed" msgstr "" #: spyder/plugins/editor.py:655 msgid "Open last closed" msgstr "" #: spyder/plugins/editor.py:661 msgid "&Open..." msgstr "" #: spyder/plugins/editor.py:662 spyder/plugins/editor.py:1870 #: spyder/plugins/editor.py:1876 msgid "Open file" msgstr "" #: spyder/plugins/editor.py:668 msgid "&Revert" msgstr "" #: spyder/plugins/editor.py:669 msgid "Revert file from disk" msgstr "" #: spyder/plugins/editor.py:672 msgid "&Save" msgstr "" #: spyder/plugins/editor.py:673 spyder/widgets/editor.py:1681 msgid "Save file" msgstr "" #: spyder/plugins/editor.py:679 msgid "Sav&e all" msgstr "" #: spyder/plugins/editor.py:680 msgid "Save all files" msgstr "" #: spyder/plugins/editor.py:686 msgid "Save &as..." msgstr "" #: spyder/plugins/editor.py:687 msgid "Save current file as..." msgstr "" #: spyder/plugins/editor.py:692 msgid "Save copy as..." msgstr "" #: spyder/plugins/editor.py:693 msgid "Save copy of current file as..." msgstr "" #: spyder/plugins/editor.py:696 spyder/plugins/editor.py:697 msgid "Print preview..." msgstr "" #: spyder/plugins/editor.py:698 msgid "&Print..." msgstr "" #: spyder/plugins/editor.py:699 msgid "Print current file..." msgstr "" #: spyder/plugins/editor.py:702 msgid "&Close" msgstr "" #: spyder/plugins/editor.py:703 msgid "Close current file" msgstr "" #: spyder/plugins/editor.py:706 msgid "C&lose all" msgstr "" #: spyder/plugins/editor.py:707 msgid "Close all opened files" msgstr "" #: spyder/plugins/editor.py:714 msgid "&Find text" msgstr "" #: spyder/plugins/editor.py:720 msgid "Find &next" msgstr "" #: spyder/plugins/editor.py:726 msgid "Find &previous" msgstr "" #: spyder/plugins/editor.py:732 msgid "&Replace text" msgstr "" #: spyder/plugins/editor.py:741 msgid "Set/Clear breakpoint" msgstr "" #: spyder/plugins/editor.py:748 msgid "Set/Edit conditional breakpoint" msgstr "" #: spyder/plugins/editor.py:755 msgid "Clear breakpoints in all files" msgstr "" #: spyder/plugins/editor.py:757 msgid "Debug with winpdb" msgstr "" #: spyder/plugins/editor.py:764 msgid "Debug file" msgstr "" #: spyder/plugins/editor.py:769 msgid "Step" msgstr "" #: spyder/plugins/editor.py:770 msgid "Run current line" msgstr "" #: spyder/plugins/editor.py:775 msgid "Continue" msgstr "" #: spyder/plugins/editor.py:777 msgid "Continue execution until next breakpoint" msgstr "" #: spyder/plugins/editor.py:782 msgid "Step Into" msgstr "" #: spyder/plugins/editor.py:784 msgid "Step into function or method of current line" msgstr "" #: spyder/plugins/editor.py:789 msgid "Step Return" msgstr "" #: spyder/plugins/editor.py:791 msgid "Run until current function or method returns" msgstr "" #: spyder/plugins/editor.py:796 spyder/widgets/findinfiles.py:281 #: spyder/widgets/ipythonconsole/client.py:357 msgid "Stop" msgstr "" #: spyder/plugins/editor.py:797 msgid "Stop debugging" msgstr "" #: spyder/plugins/editor.py:804 msgid "Run file" msgstr "" #: spyder/plugins/editor.py:809 msgid "&Configuration per file..." msgstr "" #: spyder/plugins/editor.py:811 msgid "Run settings" msgstr "" #: spyder/plugins/editor.py:817 msgid "Re-run &last script" msgstr "" #: spyder/plugins/editor.py:819 msgid "Run again last file" msgstr "" #: spyder/plugins/editor.py:825 spyder/widgets/sourcecode/codeeditor.py:2708 msgid "Run &selection or current line" msgstr "" #: spyder/plugins/editor.py:828 msgid "Run selection or current line" msgstr "" #: spyder/plugins/editor.py:836 spyder/widgets/sourcecode/codeeditor.py:2696 msgid "Run cell" msgstr "" #: spyder/plugins/editor.py:839 msgid "" "Run current cell (Ctrl+Enter)\n" "[Use #%% to create cells]" msgstr "" #: spyder/plugins/editor.py:845 spyder/widgets/sourcecode/codeeditor.py:2700 msgid "Run cell and advance" msgstr "" #: spyder/plugins/editor.py:848 msgid "Run current cell and go to the next one (Shift+Enter)" msgstr "" #: spyder/plugins/editor.py:854 spyder/widgets/sourcecode/codeeditor.py:2704 msgid "Re-run last cell" msgstr "" #: spyder/plugins/editor.py:855 msgid "Re run last cell " msgstr "" #: spyder/plugins/editor.py:865 msgid "Show todo list" msgstr "" #: spyder/plugins/editor.py:866 msgid "Show comments list (TODO/FIXME/XXX/HINT/TIP/@todo/HACK/BUG/OPTIMIZE/!!!/???)" msgstr "" #: spyder/plugins/editor.py:874 msgid "Show warning/error list" msgstr "" #: spyder/plugins/editor.py:875 msgid "Show code analysis warnings/errors" msgstr "" #: spyder/plugins/editor.py:881 msgid "Previous warning/error" msgstr "" #: spyder/plugins/editor.py:882 msgid "Go to previous code analysis warning/error" msgstr "" #: spyder/plugins/editor.py:885 msgid "Next warning/error" msgstr "" #: spyder/plugins/editor.py:886 msgid "Go to next code analysis warning/error" msgstr "" #: spyder/plugins/editor.py:890 msgid "Last edit location" msgstr "" #: spyder/plugins/editor.py:891 msgid "Go to last edit location" msgstr "" #: spyder/plugins/editor.py:899 msgid "Previous cursor position" msgstr "" #: spyder/plugins/editor.py:900 msgid "Go to previous cursor position" msgstr "" #: spyder/plugins/editor.py:908 msgid "Next cursor position" msgstr "" #: spyder/plugins/editor.py:909 msgid "Go to next cursor position" msgstr "" #: spyder/plugins/editor.py:919 spyder/widgets/sourcecode/codeeditor.py:2680 msgid "Comment" msgstr "" #: spyder/plugins/editor.py:919 spyder/widgets/sourcecode/codeeditor.py:2680 msgid "Uncomment" msgstr "" #: spyder/plugins/editor.py:920 msgid "Comment current line or selection" msgstr "" #: spyder/plugins/editor.py:924 msgid "Add &block comment" msgstr "" #: spyder/plugins/editor.py:925 msgid "Add block comment around current line or selection" msgstr "" #: spyder/plugins/editor.py:931 msgid "R&emove block comment" msgstr "" #: spyder/plugins/editor.py:932 msgid "Remove comment block around current line or selection" msgstr "" #: spyder/plugins/editor.py:943 msgid "Indent" msgstr "" #: spyder/plugins/editor.py:944 msgid "Indent current line or selection" msgstr "" #: spyder/plugins/editor.py:947 msgid "Unindent" msgstr "" #: spyder/plugins/editor.py:948 msgid "Unindent current line or selection" msgstr "" #: spyder/plugins/editor.py:952 msgid "Toggle Uppercase" msgstr "" #: spyder/plugins/editor.py:953 msgid "Change to uppercase current line or selection" msgstr "" #: spyder/plugins/editor.py:959 msgid "Toggle Lowercase" msgstr "" #: spyder/plugins/editor.py:960 msgid "Change to lowercase current line or selection" msgstr "" #: spyder/plugins/editor.py:967 msgid "Carriage return and line feed (Windows)" msgstr "" #: spyder/plugins/editor.py:970 msgid "Line feed (UNIX)" msgstr "" #: spyder/plugins/editor.py:973 msgid "Carriage return (Mac)" msgstr "" #: spyder/plugins/editor.py:979 msgid "Convert end-of-line characters" msgstr "" #: spyder/plugins/editor.py:983 msgid "Remove trailing spaces" msgstr "" #: spyder/plugins/editor.py:987 msgid "Fix indentation" msgstr "" #: spyder/plugins/editor.py:988 msgid "Replace tab characters by space characters" msgstr "" #: spyder/plugins/editor.py:991 msgid "Go to line..." msgstr "" #: spyder/plugins/editor.py:999 msgid "Set console working directory" msgstr "" #: spyder/plugins/editor.py:1001 msgid "Set current console (and file explorer) working directory to current script directory" msgstr "" #: spyder/plugins/editor.py:1006 msgid "Maximum number of recent files..." msgstr "" #: spyder/plugins/editor.py:1009 msgid "Clear recent files list" msgstr "" #: spyder/plugins/editor.py:1009 spyder/plugins/projects.py:102 msgid "Clear this list" msgstr "" #: spyder/plugins/editor.py:1013 msgid "Open &recent" msgstr "" #: spyder/plugins/editor.py:1678 msgid "Spyder Editor" msgstr "" #: spyder/plugins/editor.py:1679 msgid "This is a temporary script file." msgstr "" #: spyder/plugins/editor.py:1748 msgid "untitled" msgstr "" #: spyder/plugins/editor.py:1820 msgid "Maximum number of recent files" msgstr "" #: spyder/plugins/editor.py:1966 msgid "Printing..." msgstr "" #: spyder/plugins/explorer.py:54 msgid "File explorer" msgstr "" #: spyder/plugins/findinfiles.py:119 spyder/widgets/findinfiles.py:829 msgid "Find in files" msgstr "" #: spyder/plugins/findinfiles.py:143 msgid "&Find in files" msgstr "" #: spyder/plugins/findinfiles.py:146 msgid "Search text in multiple files" msgstr "" #: spyder/plugins/help.py:43 msgid "Show help for objects in the Editor and Consoles in a dedicated pane" msgstr "" #: spyder/plugins/help.py:109 msgid "Automatic connections" msgstr "" #: spyder/plugins/help.py:110 msgid "This pane can automatically show an object's help information after a left parenthesis is written next to it. Below you can decide to which plugin you want to connect it to turn on this feature." msgstr "" #: spyder/plugins/help.py:122 msgid "" "This feature requires the Rope or Jedi libraries.\n" "It seems you don't have either installed." msgstr "" #: spyder/plugins/help.py:125 msgid "IPython Console" msgstr "" #: spyder/plugins/help.py:135 msgid "Additional features" msgstr "" #: spyder/plugins/help.py:136 msgid "Render mathematical equations" msgstr "" #: spyder/plugins/help.py:142 msgid "This feature requires Sphinx 1.1 or superior." msgstr "" #: spyder/plugins/help.py:143 msgid "Sphinx %s is currently installed." msgstr "" #: spyder/plugins/help.py:304 msgid "No further documentation available" msgstr "" #: spyder/plugins/help.py:342 msgid "No documentation available" msgstr "" #: spyder/plugins/help.py:373 msgid "Source" msgstr "" #: spyder/plugins/help.py:380 spyder/plugins/runconfig.py:170 #: spyder/plugins/runconfig.py:486 spyder/widgets/ipythonconsole/client.py:291 msgid "Console" msgstr "" #: spyder/plugins/help.py:388 msgid "Object" msgstr "" #: spyder/plugins/help.py:402 msgid "Plain Text" msgstr "" #: spyder/plugins/help.py:406 msgid "Show Source" msgstr "" #: spyder/plugins/help.py:410 msgid "Rich Text" msgstr "" #: spyder/plugins/help.py:420 msgid "Automatic import" msgstr "" #: spyder/plugins/help.py:432 spyder/plugins/history.py:106 #: spyder/widgets/editor.py:720 spyder/widgets/explorer.py:1187 #: spyder/widgets/ipythonconsole/client.py:381 #: spyder/widgets/variableexplorer/namespacebrowser.py:148 msgid "Options" msgstr "" #: spyder/plugins/help.py:687 msgid "Here you can get help of any object by pressing %s in front of it, either on the Editor or the Console.%sHelp can also be shown automatically after writing a left parenthesis next to an object. You can activate this behavior in %s." msgstr "" #: spyder/plugins/help.py:693 msgid "Preferences > Help" msgstr "" #: spyder/plugins/help.py:700 msgid "Usage" msgstr "" #: spyder/plugins/help.py:701 msgid "New to Spyder? Read our" msgstr "" #: spyder/plugins/help.py:702 msgid "tutorial" msgstr "" #: spyder/plugins/help.py:709 msgid "Please consider installing Sphinx to get documentation rendered in rich text." msgstr "" #: spyder/plugins/help.py:878 msgid "Lock" msgstr "" #: spyder/plugins/help.py:878 msgid "Unlock" msgstr "" #: spyder/plugins/help.py:922 msgid "The following error occured when calling Sphinx %s.
Incompatible Sphinx version or doc string decoding failed.

Error message:
%s" msgstr "" #: spyder/plugins/help.py:966 msgid "No source code available." msgstr "" #: spyder/plugins/history.py:39 msgid "Settings" msgstr "" #: spyder/plugins/history.py:41 msgid " entries" msgstr "" #: spyder/plugins/history.py:41 msgid "History depth: " msgstr "" #: spyder/plugins/history.py:48 msgid "Scroll automatically to last entry" msgstr "" #: spyder/plugins/history.py:126 msgid "History log" msgstr "" #: spyder/plugins/history.py:153 msgid "History..." msgstr "" #: spyder/plugins/history.py:155 msgid "Set history maximum entries" msgstr "" #: spyder/plugins/history.py:260 msgid "History" msgstr "" #: spyder/plugins/history.py:261 msgid "Maximum entries" msgstr "" #: spyder/plugins/ipythonconsole.py:65 msgid "Symbolic mathematics in the IPython Console" msgstr "" #: spyder/plugins/ipythonconsole.py:69 msgid "Run Cython files in the IPython Console" msgstr "" #: spyder/plugins/ipythonconsole.py:73 msgid "Integrate the IPython console" msgstr "" #: spyder/plugins/ipythonconsole.py:77 msgid "IPython interactive python environment" msgstr "" #: spyder/plugins/ipythonconsole.py:128 msgid "The authenticity of host %s can't be established. Are you sure you want to continue connecting?" msgstr "" #: spyder/plugins/ipythonconsole.py:140 msgid "The authenticity of the host can't be established" msgstr "" #: spyder/plugins/ipythonconsole.py:147 msgid "Tunnel '%s' failed to start" msgstr "" #: spyder/plugins/ipythonconsole.py:152 msgid "Could not connect to remote host" msgstr "" #: spyder/plugins/ipythonconsole.py:169 spyder/plugins/ipythonconsole.py:799 msgid "Connect to an existing kernel" msgstr "" #: spyder/plugins/ipythonconsole.py:171 msgid "Please enter the connection info of the kernel you want to connect to. For that you can either select its JSON connection file using the Browse button, or write directly its id, in case it's a local kernel (for example kernel-3764.json or just 3764)." msgstr "" #: spyder/plugins/ipythonconsole.py:182 msgid "Connection info:" msgstr "" #: spyder/plugins/ipythonconsole.py:184 msgid "Path to connection file or kernel id" msgstr "" #: spyder/plugins/ipythonconsole.py:186 spyder/plugins/ipythonconsole.py:203 msgid "Browse" msgstr "" #: spyder/plugins/ipythonconsole.py:195 msgid "This is a remote kernel" msgstr "" #: spyder/plugins/ipythonconsole.py:199 msgid "username@hostname:port" msgstr "" #: spyder/plugins/ipythonconsole.py:202 msgid "Path to ssh key file" msgstr "" #: spyder/plugins/ipythonconsole.py:211 msgid "Password or ssh key passphrase" msgstr "" #: spyder/plugins/ipythonconsole.py:215 msgid "Host name" msgstr "" #: spyder/plugins/ipythonconsole.py:216 msgid "Ssh key" msgstr "" #: spyder/plugins/ipythonconsole.py:217 msgid "Password" msgstr "" #: spyder/plugins/ipythonconsole.py:246 msgid "Open connection file" msgstr "" #: spyder/plugins/ipythonconsole.py:251 msgid "Select ssh key" msgstr "" #: spyder/plugins/ipythonconsole.py:284 spyder/plugins/ipythonconsole.py:734 msgid "IPython console" msgstr "" #: spyder/plugins/ipythonconsole.py:291 msgid "Display initial banner" msgstr "" #: spyder/plugins/ipythonconsole.py:292 msgid "" "This option lets you hide the message shown at\n" "the top of the console when it's opened." msgstr "" #: spyder/plugins/ipythonconsole.py:294 msgid "Use a pager to display additional text inside the console" msgstr "" #: spyder/plugins/ipythonconsole.py:296 msgid "" "Useful if you don't want to fill the console with long help or completion texts.\n" "Note: Use the Q key to get out of the pager." msgstr "" #: spyder/plugins/ipythonconsole.py:301 msgid "Ask for confirmation before closing" msgstr "" #: spyder/plugins/ipythonconsole.py:304 msgid "Ask for confirmation before removing all user-defined variables" msgstr "" #: spyder/plugins/ipythonconsole.py:307 msgid "" "This option lets you hide the warning message shown\n" "when resetting the namespace from Spyder." msgstr "" #: spyder/plugins/ipythonconsole.py:309 #: spyder/widgets/ipythonconsole/client.py:320 msgid "Show elapsed time" msgstr "" #: spyder/plugins/ipythonconsole.py:320 msgid "Completion Type" msgstr "" #: spyder/plugins/ipythonconsole.py:321 msgid "Decide what type of completion to use" msgstr "" #: spyder/plugins/ipythonconsole.py:323 msgid "Graphical" msgstr "" #: spyder/plugins/ipythonconsole.py:323 msgid "Plain" msgstr "" #: spyder/plugins/ipythonconsole.py:323 msgid "Terminal" msgstr "" #: spyder/plugins/ipythonconsole.py:324 msgid "Completion:" msgstr "" #: spyder/plugins/ipythonconsole.py:334 msgid " lines" msgstr "" #: spyder/plugins/ipythonconsole.py:334 msgid "Buffer: " msgstr "" #: spyder/plugins/ipythonconsole.py:336 msgid "" "Set the maximum number of lines of text shown in the\n" "console before truncation. Specifying -1 disables it\n" "(not recommended!)" msgstr "" #: spyder/plugins/ipythonconsole.py:345 msgid "Support for graphics (Matplotlib)" msgstr "" #: spyder/plugins/ipythonconsole.py:346 msgid "Activate support" msgstr "" #: spyder/plugins/ipythonconsole.py:347 msgid "Automatically load Pylab and NumPy modules" msgstr "" #: spyder/plugins/ipythonconsole.py:350 msgid "" "This lets you load graphics support without importing \n" "the commands to do plots. Useful to work with other\n" "plotting libraries different to Matplotlib or to develop \n" "GUIs with Spyder." msgstr "" #: spyder/plugins/ipythonconsole.py:365 msgid "Inline" msgstr "" #: spyder/plugins/ipythonconsole.py:366 msgid "Automatic" msgstr "" #: spyder/plugins/ipythonconsole.py:367 msgid "Graphics backend" msgstr "" #: spyder/plugins/ipythonconsole.py:368 msgid "Decide how graphics are going to be displayed in the console. If unsure, please select %s to put graphics inside the console or %s to interact with them (through zooming and panning) in a separate window." msgstr "" #: spyder/plugins/ipythonconsole.py:388 msgid "Backend:" msgstr "" #: spyder/plugins/ipythonconsole.py:390 msgid "This option will be applied the next time a console is opened." msgstr "" #: spyder/plugins/ipythonconsole.py:401 msgid "Inline backend" msgstr "" #: spyder/plugins/ipythonconsole.py:402 msgid "Decide how to render the figures created by this backend" msgstr "" #: spyder/plugins/ipythonconsole.py:406 msgid "Format:" msgstr "" #: spyder/plugins/ipythonconsole.py:409 msgid "Resolution:" msgstr "" #: spyder/plugins/ipythonconsole.py:409 msgid "dpi" msgstr "" #: spyder/plugins/ipythonconsole.py:411 msgid "Only used when the format is PNG. Default is 72" msgstr "" #: spyder/plugins/ipythonconsole.py:414 msgid "Width:" msgstr "" #: spyder/plugins/ipythonconsole.py:414 spyder/plugins/ipythonconsole.py:418 msgid "inches" msgstr "" #: spyder/plugins/ipythonconsole.py:416 msgid "Default is 6" msgstr "" #: spyder/plugins/ipythonconsole.py:418 msgid "Height:" msgstr "" #: spyder/plugins/ipythonconsole.py:420 msgid "Default is 4" msgstr "" #: spyder/plugins/ipythonconsole.py:447 msgid "You can run several lines of code when a console is started. Please introduce each one separated by commas, for example:
import os, import sys" msgstr "" #: spyder/plugins/ipythonconsole.py:453 msgid "Lines:" msgstr "" #: spyder/plugins/ipythonconsole.py:462 msgid "Run a file" msgstr "" #: spyder/plugins/ipythonconsole.py:463 msgid "You can also run a whole file at startup instead of just some lines (This is similar to have a PYTHONSTARTUP file)." msgstr "" #: spyder/plugins/ipythonconsole.py:467 msgid "Use the following file:" msgstr "" #: spyder/plugins/ipythonconsole.py:481 msgid "Greedy completion" msgstr "" #: spyder/plugins/ipythonconsole.py:482 msgid "Enable Tab completion on elements of lists, results of function calls, etc, without assigning them to a variable.
For example, you can get completions on things like li[0].<Tab> or ins.meth().<Tab>" msgstr "" #: spyder/plugins/ipythonconsole.py:490 msgid "Use the greedy completer" msgstr "" #: spyder/plugins/ipythonconsole.py:501 msgid "Autocall" msgstr "" #: spyder/plugins/ipythonconsole.py:502 msgid "Autocall makes IPython automatically call any callable object even if you didn't type explicit parentheses.
For example, if you type str 43 it becomes str(43) automatically." msgstr "" #: spyder/plugins/ipythonconsole.py:509 msgid "Smart" msgstr "" #: spyder/plugins/ipythonconsole.py:510 msgid "Full" msgstr "" #: spyder/plugins/ipythonconsole.py:511 msgid "Off" msgstr "" #: spyder/plugins/ipythonconsole.py:513 msgid "Autocall: " msgstr "" #: spyder/plugins/ipythonconsole.py:514 msgid "On %s mode, Autocall is not applied if there are no arguments after the callable. On %s mode, all callable objects are automatically called (even if no arguments are present)." msgstr "" #: spyder/plugins/ipythonconsole.py:526 msgid "Symbolic Mathematics" msgstr "" #: spyder/plugins/ipythonconsole.py:527 msgid "Perfom symbolic operations in the console (e.g. integrals, derivatives, vector calculus, etc) and get the outputs in a beautifully printed style (it requires the Sympy module)." msgstr "" #: spyder/plugins/ipythonconsole.py:532 msgid "Use symbolic math" msgstr "" #: spyder/plugins/ipythonconsole.py:533 msgid "This option loads the Sympy library to work with.
Please refer to its documentation to learn how to use it." msgstr "" #: spyder/plugins/ipythonconsole.py:543 msgid "Prompts" msgstr "" #: spyder/plugins/ipythonconsole.py:544 msgid "Modify how Input and Output prompts are shown in the console." msgstr "" #: spyder/plugins/ipythonconsole.py:547 msgid "Input prompt:" msgstr "" #: spyder/plugins/ipythonconsole.py:549 msgid "Default is
In [<span class=\"in-prompt-number\">%i</span>]:" msgstr "" #: spyder/plugins/ipythonconsole.py:553 msgid "Output prompt:" msgstr "" #: spyder/plugins/ipythonconsole.py:555 msgid "Default is
Out[<span class=\"out-prompt-number\">%i</span>]:" msgstr "" #: spyder/plugins/ipythonconsole.py:575 msgid "Graphics" msgstr "" #: spyder/plugins/ipythonconsole.py:577 msgid "Startup" msgstr "" #: spyder/plugins/ipythonconsole.py:604 msgid "The directory {} is not writable and it is required to create IPython consoles. Please make it writable." msgstr "" #: spyder/plugins/ipythonconsole.py:784 msgid "Open an &IPython console" msgstr "" #: spyder/plugins/ipythonconsole.py:791 msgid "Restart kernel" msgstr "" #: spyder/plugins/ipythonconsole.py:800 msgid "Open a new IPython console connected to an existing kernel" msgstr "" #: spyder/plugins/ipythonconsole.py:803 msgid "Rename tab" msgstr "" #: spyder/plugins/ipythonconsole.py:928 msgid "No IPython console is currently available to run %s.

Please open a new one and try again." msgstr "" #: spyder/plugins/ipythonconsole.py:1018 msgid "Your Python environment or installation doesn't have the ipykernel and cloudpickle modules installed on it. Without these modules is not possible for Spyder to create a console for you.

You can install them by running in a system terminal:

pip install ipykernel cloudpickle

or

conda install ipykernel cloudpickle" msgstr "" #: spyder/plugins/ipythonconsole.py:1295 msgid "Do you want to close this console?" msgstr "" #: spyder/plugins/ipythonconsole.py:1301 msgid "Do you want to close all other consoles connected to the same kernel as this one?" msgstr "" #: spyder/plugins/ipythonconsole.py:1366 msgid "It was not possible to restart the IPython console when switching to this project. The error was {0}" msgstr "" #: spyder/plugins/ipythonconsole.py:1467 msgid "This error was most probably caused by installing Spyder in a directory with non-ascii characters (i.e. characters with tildes, apostrophes or non-latin symbols).

To fix it, please reinstall Spyder in a different location." msgstr "" #: spyder/plugins/ipythonconsole.py:1659 msgid "IPython" msgstr "" #: spyder/plugins/ipythonconsole.py:1660 msgid "Unable to connect to %s" msgstr "" #: spyder/plugins/ipythonconsole.py:1730 msgid "Connection error" msgstr "" #: spyder/plugins/ipythonconsole.py:1731 msgid "" "Could not open ssh tunnel. The error was:\n" "\n" msgstr "" #: spyder/plugins/layoutdialog.py:177 msgid "Move Up" msgstr "" #: spyder/plugins/layoutdialog.py:178 msgid "Move Down" msgstr "" #: spyder/plugins/layoutdialog.py:179 msgid "Delete Layout" msgstr "" #: spyder/plugins/layoutdialog.py:183 msgid "Layout Display and Order" msgstr "" #: spyder/plugins/maininterpreter.py:31 spyder/plugins/maininterpreter.py:66 msgid "Python interpreter" msgstr "" #: spyder/plugins/maininterpreter.py:68 msgid "Select the Python interpreter for all Spyder consoles" msgstr "" #: spyder/plugins/maininterpreter.py:71 msgid "Default (i.e. the same as Spyder's)" msgstr "" #: spyder/plugins/maininterpreter.py:74 msgid "Use the following Python interpreter:" msgstr "" #: spyder/plugins/maininterpreter.py:77 msgid "Executables" msgstr "" #: spyder/plugins/maininterpreter.py:94 msgid "User Module Reloader (UMR)" msgstr "" #: spyder/plugins/maininterpreter.py:95 msgid "UMR forces Python to reload modules which were imported when executing a file in a Python or IPython console with the runfile function." msgstr "" #: spyder/plugins/maininterpreter.py:100 msgid "Enable UMR" msgstr "" #: spyder/plugins/maininterpreter.py:101 msgid "This option will enable the User Module Reloader (UMR) in Python/IPython consoles. UMR forces Python to reload deeply modules during import when running a Python script using the Spyder's builtin function runfile.

1. UMR may require to restart the console in which it will be called (otherwise only newly imported modules will be reloaded when executing files).

2. If errors occur when re-running a PyQt-based program, please check that the Qt objects are properly destroyed (e.g. you may have to use the attribute Qt.WA_DeleteOnClose on your main window, using the setAttribute method)" msgstr "" #: spyder/plugins/maininterpreter.py:117 msgid "Show reloaded modules list" msgstr "" #: spyder/plugins/maininterpreter.py:118 msgid "Please note that these changes will be applied only to new consoles" msgstr "" #: spyder/plugins/maininterpreter.py:122 msgid "Set UMR excluded (not reloaded) modules" msgstr "" #: spyder/plugins/maininterpreter.py:150 msgid "You selected an invalid Python interpreter for the console so the previous interpreter will stay. Please make sure to select a valid one." msgstr "" #: spyder/plugins/maininterpreter.py:175 msgid "You selected a Python %d interpreter for the console but Spyder is running on Python %d!.

Although this is possible, we recommend you to install and run Spyder directly with your selected interpreter, to avoid seeing false warnings and errors due to the incompatible syntax between these two Python versions." msgstr "" #: spyder/plugins/maininterpreter.py:186 spyder/plugins/maininterpreter.py:213 #: spyder/plugins/maininterpreter.py:217 msgid "UMR" msgstr "" #: spyder/plugins/maininterpreter.py:187 msgid "Set the list of excluded modules as this: numpy, scipy" msgstr "" #: spyder/plugins/maininterpreter.py:204 msgid "You are working with Python 2, this means that you can not import a module that contains non-ascii characters." msgstr "" #: spyder/plugins/maininterpreter.py:214 msgid "" "The following modules are not installed on your machine:\n" "%s" msgstr "" #: spyder/plugins/maininterpreter.py:218 msgid "Please note that these changes will be applied only to new Python/IPython consoles" msgstr "" #: spyder/plugins/onlinehelp.py:70 msgid "Online help" msgstr "" #: spyder/plugins/outlineexplorer.py:49 spyder/widgets/editortools.py:195 msgid "Outline" msgstr "" #: spyder/plugins/projects.py:78 spyder/widgets/projects/explorer.py:112 #: spyder/widgets/projects/explorer.py:126 msgid "Project explorer" msgstr "" #: spyder/plugins/projects.py:90 msgid "New Project..." msgstr "" #: spyder/plugins/projects.py:93 msgid "Open Project..." msgstr "" #: spyder/plugins/projects.py:96 msgid "Close Project" msgstr "" #: spyder/plugins/projects.py:99 msgid "Delete Project" msgstr "" #: spyder/plugins/projects.py:105 msgid "Project Preferences" msgstr "" #: spyder/plugins/projects.py:107 msgid "Recent Projects" msgstr "" #: spyder/plugins/projects.py:244 msgid "Open project" msgstr "" #: spyder/plugins/projects.py:249 msgid "%s is not a Spyder project!" msgstr "" #: spyder/plugins/runconfig.py:29 msgid "Execute in current console" msgstr "" #: spyder/plugins/runconfig.py:30 msgid "Execute in a dedicated console" msgstr "" #: spyder/plugins/runconfig.py:31 msgid "Execute in an external system terminal" msgstr "" #: spyder/plugins/runconfig.py:42 msgid "Always show %s on a first file run" msgstr "" #: spyder/plugins/runconfig.py:45 msgid "Remove all variables before execution" msgstr "" #: spyder/plugins/runconfig.py:46 msgid "Directly enter debugging when errors appear" msgstr "" #: spyder/plugins/runconfig.py:47 msgid "Interact with the Python console after execution" msgstr "" #: spyder/plugins/runconfig.py:49 msgid "The directory of the file being executed" msgstr "" #: spyder/plugins/runconfig.py:50 spyder/plugins/workingdirectory.py:56 msgid "The current working directory" msgstr "" #: spyder/plugins/runconfig.py:51 msgid "The following directory:" msgstr "" #: spyder/plugins/runconfig.py:184 spyder/plugins/runconfig.py:504 msgid "General settings" msgstr "" #: spyder/plugins/runconfig.py:194 spyder/plugins/runconfig.py:236 msgid "Command line options:" msgstr "" #: spyder/plugins/runconfig.py:202 spyder/plugins/runconfig.py:514 msgid "Working Directory settings" msgstr "" #: spyder/plugins/runconfig.py:226 spyder/plugins/runconfig.py:548 msgid "External system terminal" msgstr "" #: spyder/plugins/runconfig.py:241 msgid "-u is added to the other options you set here" msgstr "" #: spyder/plugins/runconfig.py:250 msgid "this dialog" msgstr "" #: spyder/plugins/runconfig.py:315 msgid "Run configuration" msgstr "" #: spyder/plugins/runconfig.py:316 msgid "The following working directory is not valid:
%s" msgstr "" #: spyder/plugins/runconfig.py:394 msgid "Run settings for %s" msgstr "" #: spyder/plugins/runconfig.py:426 msgid "Select a run configuration:" msgstr "" #: spyder/plugins/runconfig.py:455 msgid "Run configuration per file" msgstr "" #: spyder/plugins/runconfig.py:480 msgid "The following are the default options for running files.These options may be overriden using the Configuration per file entry of the Run menu." msgstr "" #: spyder/plugins/runconfig.py:516 msgid "Default working directory is:" msgstr "" #: spyder/plugins/runconfig.py:556 msgid "Run Settings dialog" msgstr "" #: spyder/plugins/shortcuts.py:65 msgid "Currently used to delete lines on editor" msgstr "" #: spyder/plugins/shortcuts.py:69 msgid "We cannot support this shortcut on Windows" msgstr "" #: spyder/plugins/shortcuts.py:72 msgid "Shortcuts that use Shift and another key are unsupported" msgstr "" #: spyder/plugins/shortcuts.py:149 msgid "" "Press the new shortcut and select 'Ok': \n" "(Press 'Tab' once to switch focus between the shortcut entry \n" "and the buttons below it)" msgstr "" #: spyder/plugins/shortcuts.py:152 msgid "Current shortcut:" msgstr "" #: spyder/plugins/shortcuts.py:154 msgid "New shortcut:" msgstr "" #: spyder/plugins/shortcuts.py:167 msgid "Shortcut: {0}" msgstr "" #: spyder/plugins/shortcuts.py:288 msgid "Please introduce a different shortcut" msgstr "" #: spyder/plugins/shortcuts.py:325 msgid "The new shortcut conflicts with:" msgstr "" #: spyder/plugins/shortcuts.py:334 spyder/plugins/shortcuts.py:343 msgid "Forbidden key sequence!" msgstr "" #: spyder/plugins/shortcuts.py:354 msgid "A compound sequence can have {break} a maximum of 4 subsequences.{break}" msgstr "" #: spyder/plugins/shortcuts.py:359 msgid "Invalid key entered" msgstr "" #: spyder/plugins/shortcuts.py:567 msgid "Context" msgstr "" #: spyder/plugins/shortcuts.py:569 #: spyder/widgets/variableexplorer/collectionseditor.py:128 msgid "Name" msgstr "" #: spyder/plugins/shortcuts.py:571 msgid "Shortcut" msgstr "" #: spyder/plugins/shortcuts.py:573 msgid "Score" msgstr "" #: spyder/plugins/shortcuts.py:734 msgid "Conflicts" msgstr "" #: spyder/plugins/shortcuts.py:735 msgid "The following conflicts have been detected:" msgstr "" #: spyder/plugins/shortcuts.py:820 msgid "Keyboard shortcuts" msgstr "" #: spyder/plugins/shortcuts.py:828 msgid "Search: " msgstr "" #: spyder/plugins/shortcuts.py:829 msgid "Reset to default values" msgstr "" #: spyder/plugins/shortcuts.py:859 msgid "Shortcuts reset" msgstr "" #: spyder/plugins/shortcuts.py:860 msgid "Do you want to reset to default values?" msgstr "" #: spyder/plugins/variableexplorer.py:25 msgid "Filter" msgstr "" #: spyder/plugins/variableexplorer.py:27 #: spyder/widgets/variableexplorer/namespacebrowser.py:200 msgid "Exclude private references" msgstr "" #: spyder/plugins/variableexplorer.py:28 #: spyder/widgets/variableexplorer/namespacebrowser.py:215 msgid "Exclude capitalized references" msgstr "" #: spyder/plugins/variableexplorer.py:29 #: spyder/widgets/variableexplorer/namespacebrowser.py:208 msgid "Exclude all-uppercase references" msgstr "" #: spyder/plugins/variableexplorer.py:30 #: spyder/widgets/variableexplorer/namespacebrowser.py:223 msgid "Exclude unsupported data types" msgstr "" #: spyder/plugins/variableexplorer.py:36 #: spyder/widgets/variableexplorer/collectionseditor.py:699 msgid "Show arrays min/max" msgstr "" #: spyder/plugins/variableexplorer.py:178 msgid "Variable explorer" msgstr "" #: spyder/plugins/workingdirectory.py:39 msgid "The current working directory is the working directory for IPython consoles and the current directory for the File Explorer." msgstr "" #: spyder/plugins/workingdirectory.py:44 msgid "Console directory" msgstr "" #: spyder/plugins/workingdirectory.py:45 msgid "The working directory for new consoles is:" msgstr "" #: spyder/plugins/workingdirectory.py:49 msgid "The current project directory or user home directory (if no project is active)" msgstr "" #: spyder/plugins/workingdirectory.py:62 msgid "the following directory:" msgstr "" #: spyder/plugins/workingdirectory.py:64 msgid "The directory when a new console is open will be the specified path" msgstr "" #: spyder/plugins/workingdirectory.py:124 msgid "Back" msgstr "" #: spyder/plugins/workingdirectory.py:132 spyder/widgets/explorer.py:1181 #: spyder/widgets/variableexplorer/importwizard.py:539 msgid "Next" msgstr "" #: spyder/plugins/workingdirectory.py:143 msgid "" "This is the working directory for newly\n" "opened consoles (Python/IPython consoles and\n" "terminals), for the file explorer, for the\n" "find in files plugin and for new files\n" "created in the editor" msgstr "" #: spyder/plugins/workingdirectory.py:168 msgid "Browse a working directory" msgstr "" #: spyder/plugins/workingdirectory.py:175 msgid "Change to parent directory" msgstr "" #: spyder/plugins/workingdirectory.py:182 spyder/widgets/findinfiles.py:322 msgid "Current working directory" msgstr "" #: spyder/utils/codeanalysis.py:92 msgid "Real-time code analysis on the Editor" msgstr "" #: spyder/utils/codeanalysis.py:96 msgid "Real-time code style analysis on the Editor" msgstr "" #: spyder/utils/environ.py:46 msgid "Environment variables" msgstr "" #: spyder/utils/environ.py:96 msgid "Module pywin32 was not found.
Please restart this Windows session (not the computer) for changes to take effect." msgstr "" #: spyder/utils/environ.py:109 msgid "If you accept changes, this will modify the current user environment variables directly in Windows registry. Use it with precautions, at your own risks.

Note that for changes to take effect, you will need to restart the parent process of this application (simply restart Spyder if you have executed it from a Windows shortcut, otherwise restart any application from which you may have executed it, like Python(x,y) Home for example)" msgstr "" #: spyder/utils/help/sphinxify.py:217 spyder/utils/help/sphinxify.py:227 msgid "It was not possible to generate rich text help for this object.
Please see it in plain text." msgstr "" #: spyder/utils/introspection/manager.py:34 #: spyder/utils/introspection/manager.py:39 msgid "Editor's code completion, go-to-definition and help" msgstr "" #: spyder/utils/iofuncs.py:408 msgid "Supported files" msgstr "" #: spyder/utils/iofuncs.py:410 msgid "All files (*.*)" msgstr "" #: spyder/utils/iofuncs.py:420 msgid "Spyder data files" msgstr "" #: spyder/utils/iofuncs.py:422 #: spyder/widgets/variableexplorer/collectionseditor.py:1058 msgid "NumPy arrays" msgstr "" #: spyder/utils/iofuncs.py:423 msgid "NumPy zip arrays" msgstr "" #: spyder/utils/iofuncs.py:424 msgid "Matlab files" msgstr "" #: spyder/utils/iofuncs.py:425 msgid "CSV text files" msgstr "" #: spyder/utils/iofuncs.py:427 msgid "JPEG images" msgstr "" #: spyder/utils/iofuncs.py:428 msgid "PNG images" msgstr "" #: spyder/utils/iofuncs.py:429 msgid "GIF images" msgstr "" #: spyder/utils/iofuncs.py:430 msgid "TIFF images" msgstr "" #: spyder/utils/iofuncs.py:431 spyder/utils/iofuncs.py:432 msgid "Pickle files" msgstr "" #: spyder/utils/iofuncs.py:433 msgid "JSON files" msgstr "" #: spyder/utils/iofuncs.py:452 spyder/utils/iofuncs.py:459 msgid "Unsupported file type '%s'" msgstr "" #: spyder/utils/programs.py:287 msgid "It was not possible to run this file in an external terminal" msgstr "" #: spyder/utils/syntaxhighlighters.py:34 msgid "Syntax highlighting for Matlab, Julia and other file types" msgstr "" #: spyder/utils/syntaxhighlighters.py:43 msgid "Background:" msgstr "" #: spyder/utils/syntaxhighlighters.py:44 #: spyder/widgets/sourcecode/codeeditor.py:107 msgid "Current line:" msgstr "" #: spyder/utils/syntaxhighlighters.py:45 msgid "Current cell:" msgstr "" #: spyder/utils/syntaxhighlighters.py:46 msgid "Occurrence:" msgstr "" #: spyder/utils/syntaxhighlighters.py:47 msgid "Link:" msgstr "" #: spyder/utils/syntaxhighlighters.py:48 msgid "Side areas:" msgstr "" #: spyder/utils/syntaxhighlighters.py:49 msgid "Matched
parens:" msgstr "" #: spyder/utils/syntaxhighlighters.py:50 msgid "Unmatched
parens:" msgstr "" #: spyder/utils/syntaxhighlighters.py:51 msgid "Normal text:" msgstr "" #: spyder/utils/syntaxhighlighters.py:52 msgid "Keyword:" msgstr "" #: spyder/utils/syntaxhighlighters.py:53 msgid "Builtin:" msgstr "" #: spyder/utils/syntaxhighlighters.py:54 msgid "Definition:" msgstr "" #: spyder/utils/syntaxhighlighters.py:55 msgid "Comment:" msgstr "" #: spyder/utils/syntaxhighlighters.py:56 msgid "String:" msgstr "" #: spyder/utils/syntaxhighlighters.py:57 msgid "Number:" msgstr "" #: spyder/utils/syntaxhighlighters.py:58 msgid "Instance:" msgstr "" #: spyder/widgets/arraybuilder.py:179 msgid "" "\n" " Numpy Array/Matrix Helper
\n" " Type an array in Matlab : [1 2;3 4]
\n" " or Spyder simplified syntax : 1 2;3 4\n" "

\n" " Hit 'Enter' for array or 'Ctrl+Enter' for matrix.\n" "

\n" " Hint:
\n" " Use two spaces or two tabs to generate a ';'.\n" " " msgstr "" #: spyder/widgets/arraybuilder.py:190 msgid "" "\n" " Numpy Array/Matrix Helper
\n" " Enter an array in the table.
\n" " Use Tab to move between cells.\n" "

\n" " Hit 'Enter' for array or 'Ctrl+Enter' for matrix.\n" "

\n" " Hint:
\n" " Use two tabs at the end of a row to move to the next row.\n" " " msgstr "" #: spyder/widgets/arraybuilder.py:365 msgid "Array dimensions not valid" msgstr "" #: spyder/widgets/browser.py:58 spyder/widgets/sourcecode/codeeditor.py:2719 msgid "Zoom out" msgstr "" #: spyder/widgets/browser.py:61 spyder/widgets/sourcecode/codeeditor.py:2715 msgid "Zoom in" msgstr "" #: spyder/widgets/browser.py:213 msgid "Home" msgstr "" #: spyder/widgets/browser.py:249 msgid "Find text" msgstr "" #: spyder/widgets/browser.py:266 msgid "Address:" msgstr "" #: spyder/widgets/browser.py:302 msgid "Unable to load page" msgstr "" #: spyder/widgets/comboboxes.py:164 msgid "Press enter to validate this entry" msgstr "" #: spyder/widgets/comboboxes.py:165 msgid "This entry is incorrect" msgstr "" #: spyder/widgets/comboboxes.py:208 msgid "Press enter to validate this path" msgstr "" #: spyder/widgets/dependencies.py:63 msgid " Required " msgstr "" #: spyder/widgets/dependencies.py:63 msgid "Module" msgstr "" #: spyder/widgets/dependencies.py:64 msgid " Installed " msgstr "" #: spyder/widgets/dependencies.py:64 msgid "Provided features" msgstr "" #: spyder/widgets/dependencies.py:134 msgid "Dependencies" msgstr "" #: spyder/widgets/dependencies.py:141 msgid "Spyder depends on several Python modules to provide the right functionality for all its panes. The table below shows the required and installed versions (if any) of all of them.

Note: You can safely use Spyder without the following modules installed: %s and %s.

Please also note that new dependencies or changed ones will be correctly detected only after Spyder is restarted." msgstr "" #: spyder/widgets/dependencies.py:157 msgid "Copy to clipboard" msgstr "" #: spyder/widgets/editor.py:501 msgid "Find symbols in file..." msgstr "" #: spyder/widgets/editor.py:504 msgid "Copy path to clipboard" msgstr "" #: spyder/widgets/editor.py:508 msgid "Close all to the right" msgstr "" #: spyder/widgets/editor.py:510 msgid "Close all but this" msgstr "" #: spyder/widgets/editor.py:514 spyder/widgets/explorer.py:361 msgid "Show in Finder" msgstr "" #: spyder/widgets/editor.py:516 spyder/widgets/explorer.py:363 msgid "Show in external file explorer" msgstr "" #: spyder/widgets/editor.py:1197 msgid "Temporary file" msgstr "" #: spyder/widgets/editor.py:1289 msgid "New window" msgstr "" #: spyder/widgets/editor.py:1290 msgid "Create a new editor window" msgstr "" #: spyder/widgets/editor.py:1293 msgid "Split vertically" msgstr "" #: spyder/widgets/editor.py:1295 msgid "Split vertically this editor window" msgstr "" #: spyder/widgets/editor.py:1297 msgid "Split horizontally" msgstr "" #: spyder/widgets/editor.py:1299 msgid "Split horizontally this editor window" msgstr "" #: spyder/widgets/editor.py:1301 msgid "Close this panel" msgstr "" #: spyder/widgets/editor.py:1540 msgid "%s has been modified.
Do you want to save changes?" msgstr "" #: spyder/widgets/editor.py:1626 spyder/widgets/editor.py:1789 msgid "Save" msgstr "" #: spyder/widgets/editor.py:1627 spyder/widgets/editor.py:1790 #: spyder/widgets/shell.py:267 msgid "Unable to save file '%s'

Error message:
%s" msgstr "" #: spyder/widgets/editor.py:1977 msgid "%s is unavailable (this file may have been removed, moved or renamed outside Spyder).
Do you want to close it?" msgstr "" #: spyder/widgets/editor.py:2000 msgid "%s has been modified outside Spyder.
Do you want to reload it and lose all your changes?" msgstr "" #: spyder/widgets/editor.py:2110 msgid "All changes to %s will be lost.
Do you want to revert file from disk?" msgstr "" #: spyder/widgets/editor.py:2254 msgid "Loading %s..." msgstr "" #: spyder/widgets/editor.py:2266 msgid "%s contains mixed end-of-line characters.
Spyder will fix this automatically." msgstr "" #: spyder/widgets/editor.py:2675 msgid "Close window" msgstr "" #: spyder/widgets/editor.py:2677 msgid "Close this window" msgstr "" #: spyder/widgets/editortools.py:94 spyder/widgets/editortools.py:130 msgid "Line %s" msgstr "" #: spyder/widgets/editortools.py:99 msgid "Class defined at line %s" msgstr "" #: spyder/widgets/editortools.py:107 msgid "Method defined at line %s" msgstr "" #: spyder/widgets/editortools.py:117 msgid "Function defined at line %s" msgstr "" #: spyder/widgets/editortools.py:149 msgid "Cell starts at line %s" msgstr "" #: spyder/widgets/editortools.py:202 spyder/widgets/editortools.py:535 msgid "Go to cursor position" msgstr "" #: spyder/widgets/editortools.py:205 msgid "Show absolute path" msgstr "" #: spyder/widgets/editortools.py:208 spyder/widgets/explorer.py:274 msgid "Show all files" msgstr "" #: spyder/widgets/editortools.py:211 msgid "Show special comments" msgstr "" #: spyder/widgets/editortools.py:509 msgid "Show/hide outline explorer" msgstr "" #: spyder/widgets/explorer.py:270 msgid "Edit filename filters..." msgstr "" #: spyder/widgets/explorer.py:284 msgid "Edit filename filters" msgstr "" #: spyder/widgets/explorer.py:285 msgid "Name filters:" msgstr "" #: spyder/widgets/explorer.py:304 msgid "File..." msgstr "" #: spyder/widgets/explorer.py:308 msgid "Module..." msgstr "" #: spyder/widgets/explorer.py:312 msgid "Folder..." msgstr "" #: spyder/widgets/explorer.py:316 msgid "Package..." msgstr "" #: spyder/widgets/explorer.py:337 #: spyder/widgets/variableexplorer/collectionseditor.py:674 msgid "Edit" msgstr "" #: spyder/widgets/explorer.py:339 msgid "Move..." msgstr "" #: spyder/widgets/explorer.py:342 msgid "Delete..." msgstr "" #: spyder/widgets/explorer.py:345 msgid "Rename..." msgstr "" #: spyder/widgets/explorer.py:348 msgid "Open" msgstr "" #: spyder/widgets/explorer.py:349 spyder/widgets/sourcecode/codeeditor.py:2687 msgid "Convert to Python script" msgstr "" #: spyder/widgets/explorer.py:390 msgid "Commit" msgstr "" #: spyder/widgets/explorer.py:393 msgid "Browse repository" msgstr "" #: spyder/widgets/explorer.py:404 msgid "Open command prompt here" msgstr "" #: spyder/widgets/explorer.py:406 msgid "Open terminal here" msgstr "" #: spyder/widgets/explorer.py:407 msgid "Open IPython console here" msgstr "" #: spyder/widgets/explorer.py:421 msgid "New" msgstr "" #: spyder/widgets/explorer.py:429 msgid "Import" msgstr "" #: spyder/widgets/explorer.py:575 msgid "Do you really want to delete %s?" msgstr "" #: spyder/widgets/explorer.py:593 msgid "delete" msgstr "" #: spyder/widgets/explorer.py:594 spyder/widgets/projects/explorer.py:148 #: spyder/widgets/projects/explorer.py:255 msgid "Project Explorer" msgstr "" #: spyder/widgets/explorer.py:595 spyder/widgets/projects/explorer.py:149 msgid "Unable to %s %s

Error message:
%s" msgstr "" #: spyder/widgets/explorer.py:610 msgid "File Explorer" msgstr "" #: spyder/widgets/explorer.py:611 msgid "The current directory contains a project.

If you want to delete the project, please go to Projects » Delete Project" msgstr "" #: spyder/widgets/explorer.py:628 spyder/widgets/sourcecode/codeeditor.py:2160 msgid "Conversion error" msgstr "" #: spyder/widgets/explorer.py:629 spyder/widgets/sourcecode/codeeditor.py:2161 msgid "" "It was not possible to convert this notebook. The error is:\n" "\n" msgstr "" #: spyder/widgets/explorer.py:646 spyder/widgets/explorer.py:654 #: spyder/widgets/explorer.py:665 #: spyder/widgets/variableexplorer/collectionseditor.py:703 #: spyder/widgets/variableexplorer/collectionseditor.py:949 msgid "Rename" msgstr "" #: spyder/widgets/explorer.py:647 msgid "New name:" msgstr "" #: spyder/widgets/explorer.py:655 msgid "Do you really want to rename %s and overwrite the existing file %s?" msgstr "" #: spyder/widgets/explorer.py:666 msgid "Unable to rename file %s

Error message:
%s" msgstr "" #: spyder/widgets/explorer.py:709 msgid "Unable to move %s

Error message:
%s" msgstr "" #: spyder/widgets/explorer.py:727 msgid "Unable to create folder %s

Error message:
%s" msgstr "" #: spyder/widgets/explorer.py:740 spyder/widgets/explorer.py:774 msgid "Unable to create file %s

Error message:
%s" msgstr "" #: spyder/widgets/explorer.py:748 msgid "New folder" msgstr "" #: spyder/widgets/explorer.py:749 msgid "Folder name:" msgstr "" #: spyder/widgets/explorer.py:754 msgid "New package" msgstr "" #: spyder/widgets/explorer.py:755 msgid "Package name:" msgstr "" #: spyder/widgets/explorer.py:795 msgid "New module" msgstr "" #: spyder/widgets/explorer.py:810 msgid "For %s support, please install one of the
following tools:

%s" msgstr "" #: spyder/widgets/explorer.py:814 msgid "Unable to find external program.

%s" msgstr "" #: spyder/widgets/explorer.py:1035 msgid "Show current directory only" msgstr "" #: spyder/widgets/explorer.py:1145 msgid "You don't have the right permissions to open this directory" msgstr "" #: spyder/widgets/explorer.py:1176 msgid "Show icons and text" msgstr "" #: spyder/widgets/explorer.py:1178 #: spyder/widgets/variableexplorer/importwizard.py:535 msgid "Previous" msgstr "" #: spyder/widgets/explorer.py:1184 msgid "Parent" msgstr "" #: spyder/widgets/fileswitcher.py:110 msgid "unsaved file" msgstr "" #: spyder/widgets/fileswitcher.py:249 msgid "Press Enter to switch files or Esc to cancel.

Type to filter filenames.

Use :number to go to a line, e.g. main:42
Use @symbol_text to go to a symbol, e.g. @init

Press Ctrl+W to close current tab.
" msgstr "" #: spyder/widgets/fileswitcher.py:663 msgid "lines" msgstr "" #: spyder/widgets/findinfiles.py:121 msgid "Unexpected error: see internal console" msgstr "" #: spyder/widgets/findinfiles.py:149 msgid "invalid regular expression" msgstr "" #: spyder/widgets/findinfiles.py:199 msgid "permission denied errors were encountered" msgstr "" #: spyder/widgets/findinfiles.py:258 msgid "Search pattern" msgstr "" #: spyder/widgets/findinfiles.py:261 spyder/widgets/findinfiles.py:301 #: spyder/widgets/findreplace.py:99 msgid "Regular expression" msgstr "" #: spyder/widgets/findinfiles.py:264 spyder/widgets/findreplace.py:105 msgid "Case Sensitive" msgstr "" #: spyder/widgets/findinfiles.py:275 msgid "Search" msgstr "" #: spyder/widgets/findinfiles.py:278 msgid "Start search" msgstr "" #: spyder/widgets/findinfiles.py:285 msgid "Stop search" msgstr "" #: spyder/widgets/findinfiles.py:295 msgid "Excluded filenames pattern" msgstr "" #: spyder/widgets/findinfiles.py:304 msgid "Exclude:" msgstr "" #: spyder/widgets/findinfiles.py:313 msgid "Search in:" msgstr "" #: spyder/widgets/findinfiles.py:315 msgid "Search directory" msgstr "" #: spyder/widgets/findinfiles.py:324 msgid "Search in all files and directories present on thecurrent Spyder path" msgstr "" #: spyder/widgets/findinfiles.py:328 msgid "Project" msgstr "" #: spyder/widgets/findinfiles.py:330 msgid "Search in all files and directories present on thecurrent project path (If opened)" msgstr "" #: spyder/widgets/findinfiles.py:336 msgid "File" msgstr "" #: spyder/widgets/findinfiles.py:338 msgid "Search in current opened file" msgstr "" #: spyder/widgets/findinfiles.py:340 msgid "Select other directory" msgstr "" #: spyder/widgets/findinfiles.py:342 msgid "Search in other folder present on the file system" msgstr "" #: spyder/widgets/findinfiles.py:378 msgid "Hide advanced options" msgstr "" #: spyder/widgets/findinfiles.py:381 msgid "Show advanced options" msgstr "" #: spyder/widgets/findinfiles.py:675 spyder/widgets/findinfiles.py:759 msgid "String not found" msgstr "" #: spyder/widgets/findinfiles.py:761 msgid "matches in" msgstr "" #: spyder/widgets/findinfiles.py:762 msgid "file" msgstr "" #: spyder/widgets/findinfiles.py:794 msgid " Scanning: {0}" msgstr "" #: spyder/widgets/findinfiles.py:796 msgid " Searching for files in folder: {0}" msgstr "" #: spyder/widgets/findinfiles.py:800 msgid " Searching for files..." msgstr "" #: spyder/widgets/findreplace.py:48 msgid "No matches" msgstr "" #: spyder/widgets/findreplace.py:49 spyder/widgets/findreplace.py:50 #: spyder/widgets/findreplace.py:72 msgid "Search string" msgstr "" #: spyder/widgets/findreplace.py:51 msgid "Regular expression error" msgstr "" #: spyder/widgets/findreplace.py:111 msgid "Whole words" msgstr "" #: spyder/widgets/findreplace.py:117 msgid "Highlight matches" msgstr "" #: spyder/widgets/findreplace.py:131 msgid "Replace with:" msgstr "" #: spyder/widgets/findreplace.py:133 msgid "Replace string" msgstr "" #: spyder/widgets/findreplace.py:137 msgid "Replace/find next" msgstr "" #: spyder/widgets/findreplace.py:142 msgid "Replace selection" msgstr "" #: spyder/widgets/findreplace.py:150 msgid "Replace all" msgstr "" #: spyder/widgets/findreplace.py:572 msgid "of" msgstr "" #: spyder/widgets/findreplace.py:576 msgid "matches" msgstr "" #: spyder/widgets/findreplace.py:579 msgid "no matches" msgstr "" #: spyder/widgets/internalshell.py:262 msgid "Help..." msgstr "" #: spyder/widgets/internalshell.py:279 msgid "Shell special commands:" msgstr "" #: spyder/widgets/internalshell.py:280 msgid "Internal editor:" msgstr "" #: spyder/widgets/internalshell.py:281 msgid "External editor:" msgstr "" #: spyder/widgets/internalshell.py:282 msgid "Run script:" msgstr "" #: spyder/widgets/internalshell.py:283 msgid "Remove references:" msgstr "" #: spyder/widgets/internalshell.py:284 msgid "System commands:" msgstr "" #: spyder/widgets/internalshell.py:285 msgid "Python help:" msgstr "" #: spyder/widgets/internalshell.py:286 msgid "GUI-based editor:" msgstr "" #: spyder/widgets/ipythonconsole/client.py:275 msgid "An error ocurred while starting the kernel" msgstr "" #: spyder/widgets/ipythonconsole/client.py:316 #: spyder/widgets/ipythonconsole/client.py:372 #: spyder/widgets/ipythonconsole/client.py:405 #: spyder/widgets/ipythonconsole/shell.py:232 #: spyder/widgets/variableexplorer/namespacebrowser.py:193 msgid "Remove all variables" msgstr "" #: spyder/widgets/ipythonconsole/client.py:325 msgid "Show environment variables" msgstr "" #: spyder/widgets/ipythonconsole/client.py:332 msgid "Show sys.path contents" msgstr "" #: spyder/widgets/ipythonconsole/client.py:359 msgid "Stop the current command" msgstr "" #: spyder/widgets/ipythonconsole/client.py:370 #: spyder/widgets/variableexplorer/collectionseditor.py:696 #: spyder/widgets/variableexplorer/collectionseditor.py:931 msgid "Remove" msgstr "" #: spyder/widgets/ipythonconsole/client.py:393 msgid "Inspect current object" msgstr "" #: spyder/widgets/ipythonconsole/client.py:399 msgid "Clear line or block" msgstr "" #: spyder/widgets/ipythonconsole/client.py:412 msgid "Clear console" msgstr "" #: spyder/widgets/ipythonconsole/client.py:460 msgid "Are you sure you want to restart the kernel?" msgstr "" #: spyder/widgets/ipythonconsole/client.py:462 msgid "Restart kernel?" msgstr "" #: spyder/widgets/ipythonconsole/client.py:474 msgid "" "Error restarting kernel: %s\n" msgstr "" #: spyder/widgets/ipythonconsole/client.py:479 msgid "" "
Restarting kernel...\n" "

" msgstr "" #: spyder/widgets/ipythonconsole/client.py:483 msgid "" "Cannot restart a kernel not started by Spyder\n" msgstr "" #: spyder/widgets/ipythonconsole/client.py:592 msgid "Connecting to kernel..." msgstr "" #: spyder/widgets/ipythonconsole/help.py:128 spyder/widgets/mixins.py:712 msgid "Arguments" msgstr "" #: spyder/widgets/ipythonconsole/namespacebrowser.py:129 msgid "Loading this kind of data while debugging is not supported." msgstr "" #: spyder/widgets/ipythonconsole/namespacebrowser.py:148 msgid "Saving data while debugging is not supported." msgstr "" #: spyder/widgets/ipythonconsole/shell.py:233 msgid "All user-defined variables will be removed. Are you sure you want to proceed?" msgstr "" #: spyder/widgets/ipythonconsole/shell.py:239 msgid "Don't show again." msgstr "" #: spyder/widgets/ipythonconsole/shell.py:262 msgid "" "

Removing all variables...\n" "
" msgstr "" #: spyder/widgets/ipythonconsole/shell.py:426 msgid "Changing backend to Qt for Mayavi" msgstr "" #: spyder/widgets/ipythonconsole/shell.py:471 msgid "Kernel died, restarting" msgstr "" #: spyder/widgets/ipythonconsole/shell.py:471 msgid "Kernel restarting" msgstr "" #: spyder/widgets/onecolumntree.py:52 msgid "Collapse all" msgstr "" #: spyder/widgets/onecolumntree.py:56 msgid "Expand all" msgstr "" #: spyder/widgets/onecolumntree.py:60 msgid "Restore" msgstr "" #: spyder/widgets/onecolumntree.py:61 msgid "Restore original tree layout" msgstr "" #: spyder/widgets/onecolumntree.py:65 msgid "Collapse selection" msgstr "" #: spyder/widgets/onecolumntree.py:69 msgid "Expand selection" msgstr "" #: spyder/widgets/pathmanager.py:97 msgid "Move to top" msgstr "" #: spyder/widgets/pathmanager.py:103 msgid "Move up" msgstr "" #: spyder/widgets/pathmanager.py:109 msgid "Move down" msgstr "" #: spyder/widgets/pathmanager.py:115 msgid "Move to bottom" msgstr "" #: spyder/widgets/pathmanager.py:126 spyder/widgets/pathmanager.py:267 msgid "Add path" msgstr "" #: spyder/widgets/pathmanager.py:131 spyder/widgets/pathmanager.py:246 msgid "Remove path" msgstr "" #: spyder/widgets/pathmanager.py:141 msgid "Synchronize..." msgstr "" #: spyder/widgets/pathmanager.py:143 msgid "Synchronize Spyder's path list with PYTHONPATH environment variable" msgstr "" #: spyder/widgets/pathmanager.py:155 msgid "Synchronize" msgstr "" #: spyder/widgets/pathmanager.py:156 msgid "This will synchronize Spyder's path list with PYTHONPATH environment variable for current user, allowing you to run your Python modules outside Spyder without having to configure sys.path.
Do you want to clear contents of PYTHONPATH before adding Spyder's path list?" msgstr "" #: spyder/widgets/pathmanager.py:247 msgid "Do you really want to remove selected path?" msgstr "" #: spyder/widgets/pathmanager.py:268 msgid "This directory is already included in Spyder path list.
Do you want to move it to the top of the list?" msgstr "" #: spyder/widgets/projects/configdialog.py:30 msgid "Project preferences" msgstr "" #: spyder/widgets/projects/configdialog.py:82 #: spyder/widgets/projects/configdialog.py:119 msgid "Restore data on startup" msgstr "" #: spyder/widgets/projects/configdialog.py:84 #: spyder/widgets/projects/configdialog.py:121 msgid "Save data on exit" msgstr "" #: spyder/widgets/projects/configdialog.py:86 #: spyder/widgets/projects/configdialog.py:123 msgid "Save history" msgstr "" #: spyder/widgets/projects/configdialog.py:88 #: spyder/widgets/projects/configdialog.py:125 msgid "Save non project files opened" msgstr "" #: spyder/widgets/projects/configdialog.py:111 msgid "Code" msgstr "" #: spyder/widgets/projects/configdialog.py:118 msgid "Workspace" msgstr "" #: spyder/widgets/projects/configdialog.py:148 #: spyder/widgets/projects/configdialog.py:155 msgid "Version control" msgstr "" #: spyder/widgets/projects/configdialog.py:156 msgid "Use version control" msgstr "" #: spyder/widgets/projects/configdialog.py:161 msgid "Version control system" msgstr "" #: spyder/widgets/projects/explorer.py:51 msgid "Show horizontal scrollbar" msgstr "" #: spyder/widgets/projects/explorer.py:113 msgid "File %s already exists.
Do you want to overwrite it?" msgstr "" #: spyder/widgets/projects/explorer.py:127 msgid "Folder %s already exists." msgstr "" #: spyder/widgets/projects/explorer.py:145 msgid "copy" msgstr "" #: spyder/widgets/projects/explorer.py:147 msgid "move" msgstr "" #: spyder/widgets/projects/explorer.py:243 msgid "Do you really want to delete {filename}?

Note: This action will only delete the project. Its files are going to be preserved on disk." msgstr "" #: spyder/widgets/projects/explorer.py:256 msgid "Unable to delete {varpath}

The error message was:
{error}" msgstr "" #: spyder/widgets/projects/projectdialog.py:69 msgid "New directory" msgstr "" #: spyder/widgets/projects/projectdialog.py:70 msgid "Existing directory" msgstr "" #: spyder/widgets/projects/projectdialog.py:72 msgid "Project name" msgstr "" #: spyder/widgets/projects/projectdialog.py:73 msgid "Location" msgstr "" #: spyder/widgets/projects/projectdialog.py:74 msgid "Project type" msgstr "" #: spyder/widgets/projects/projectdialog.py:75 msgid "Python version" msgstr "" #: spyder/widgets/projects/projectdialog.py:83 #: spyder/widgets/variableexplorer/importwizard.py:529 msgid "Cancel" msgstr "" #: spyder/widgets/projects/projectdialog.py:84 msgid "Create" msgstr "" #: spyder/widgets/projects/projectdialog.py:102 msgid "Create new project" msgstr "" #: spyder/widgets/projects/type/__init__.py:216 msgid "Empty project" msgstr "" #: spyder/widgets/projects/type/python.py:20 msgid "Python project" msgstr "" #: spyder/widgets/projects/type/python.py:76 msgid "Python package" msgstr "" #: spyder/widgets/pydocgui.py:110 msgid "Module or package:" msgstr "" #: spyder/widgets/shell.py:131 msgid "Save history log..." msgstr "" #: spyder/widgets/shell.py:133 msgid "Save current history log (i.e. all inputs and outputs) in a text file" msgstr "" #: spyder/widgets/shell.py:253 msgid "Save history log" msgstr "" #: spyder/widgets/shell.py:256 msgid "History logs" msgstr "" #: spyder/widgets/shell.py:670 msgid "Copy without prompts" msgstr "" #: spyder/widgets/shell.py:673 spyder/widgets/shell.py:677 msgid "Clear line" msgstr "" #: spyder/widgets/shell.py:679 msgid "Clear shell" msgstr "" #: spyder/widgets/shell.py:683 msgid "Clear shell contents ('cls' command)" msgstr "" #: spyder/widgets/shortcutssummary.py:42 msgid "Spyder Keyboard ShortCuts" msgstr "" #: spyder/widgets/sourcecode/codeeditor.py:101 msgid "Go to line:" msgstr "" #: spyder/widgets/sourcecode/codeeditor.py:109 msgid "Line count:" msgstr "" #: spyder/widgets/sourcecode/codeeditor.py:1327 msgid "Breakpoint" msgstr "" #: spyder/widgets/sourcecode/codeeditor.py:1328 msgid "Condition:" msgstr "" #: spyder/widgets/sourcecode/codeeditor.py:1733 msgid "Code analysis" msgstr "" #: spyder/widgets/sourcecode/codeeditor.py:1787 msgid "To do" msgstr "" #: spyder/widgets/sourcecode/codeeditor.py:2147 msgid "Removal error" msgstr "" #: spyder/widgets/sourcecode/codeeditor.py:2148 msgid "" "It was not possible to remove outputs from this notebook. The error is:\n" "\n" msgstr "" #: spyder/widgets/sourcecode/codeeditor.py:2684 msgid "Clear all ouput" msgstr "" #: spyder/widgets/sourcecode/codeeditor.py:2690 msgid "Go to definition" msgstr "" #: spyder/widgets/sourcecode/codeeditor.py:2723 msgid "Zoom reset" msgstr "" #: spyder/widgets/status.py:25 msgid "CPU and memory usage info in the status bar" msgstr "" #: spyder/widgets/status.py:117 msgid "Memory:" msgstr "" #: spyder/widgets/status.py:118 msgid "Memory usage status: requires the `psutil` (>=v0.3) library on non-Windows platforms" msgstr "" #: spyder/widgets/status.py:134 msgid "CPU:" msgstr "" #: spyder/widgets/status.py:135 msgid "CPU usage status: requires the `psutil` (>=v0.3) library" msgstr "" #: spyder/widgets/status.py:162 msgid "Permissions:" msgstr "" #: spyder/widgets/status.py:189 msgid "End-of-lines:" msgstr "" #: spyder/widgets/status.py:216 msgid "Encoding:" msgstr "" #: spyder/widgets/status.py:242 msgid "Line:" msgstr "" #: spyder/widgets/status.py:243 msgid "Column:" msgstr "" #: spyder/widgets/tabs.py:274 msgid "Browse tabs" msgstr "" #: spyder/widgets/tabs.py:403 msgid "Close current tab" msgstr "" #: spyder/widgets/variableexplorer/arrayeditor.py:511 msgid "It was not possible to copy values for this array" msgstr "" #: spyder/widgets/variableexplorer/arrayeditor.py:546 #: spyder/widgets/variableexplorer/arrayeditor.py:579 #: spyder/widgets/variableexplorer/dataframeeditor.py:697 #: spyder/widgets/variableexplorer/dataframeeditor.py:742 msgid "Format" msgstr "" #: spyder/widgets/variableexplorer/arrayeditor.py:551 #: spyder/widgets/variableexplorer/dataframeeditor.py:701 msgid "Resize" msgstr "" #: spyder/widgets/variableexplorer/arrayeditor.py:554 #: spyder/widgets/variableexplorer/dataframeeditor.py:705 msgid "Background color" msgstr "" #: spyder/widgets/variableexplorer/arrayeditor.py:580 #: spyder/widgets/variableexplorer/dataframeeditor.py:743 msgid "Float formatting" msgstr "" #: spyder/widgets/variableexplorer/arrayeditor.py:588 msgid "Format (%s) is incorrect" msgstr "" #: spyder/widgets/variableexplorer/arrayeditor.py:624 msgid "Arrays with more than 3 dimensions are not supported" msgstr "" #: spyder/widgets/variableexplorer/arrayeditor.py:628 msgid "The 'xlabels' argument length do no match array column number" msgstr "" #: spyder/widgets/variableexplorer/arrayeditor.py:632 msgid "The 'ylabels' argument length do no match array row number" msgstr "" #: spyder/widgets/variableexplorer/arrayeditor.py:639 msgid "%s arrays" msgstr "" #: spyder/widgets/variableexplorer/arrayeditor.py:640 msgid "%s are currently not supported" msgstr "" #: spyder/widgets/variableexplorer/arrayeditor.py:647 msgid "NumPy array" msgstr "" #: spyder/widgets/variableexplorer/arrayeditor.py:649 #: spyder/widgets/variableexplorer/arrayeditor.py:806 msgid "Array editor" msgstr "" #: spyder/widgets/variableexplorer/arrayeditor.py:651 msgid "read only" msgstr "" #: spyder/widgets/variableexplorer/arrayeditor.py:681 msgid "Record array fields:" msgstr "" #: spyder/widgets/variableexplorer/arrayeditor.py:693 msgid "Data" msgstr "" #: spyder/widgets/variableexplorer/arrayeditor.py:693 msgid "Mask" msgstr "" #: spyder/widgets/variableexplorer/arrayeditor.py:693 msgid "Masked data" msgstr "" #: spyder/widgets/variableexplorer/arrayeditor.py:704 msgid "Axis:" msgstr "" #: spyder/widgets/variableexplorer/arrayeditor.py:709 msgid "Index:" msgstr "" #: spyder/widgets/variableexplorer/arrayeditor.py:722 msgid "Warning: changes are applied separately" msgstr "" #: spyder/widgets/variableexplorer/arrayeditor.py:723 msgid "For performance reasons, changes applied to masked array won't be reflected in array's data (and vice-versa)." msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:126 msgid "Index" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:131 msgid "Tuple" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:134 msgid "List" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:137 msgid "Dictionary" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:139 msgid "Key" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:144 msgid "Attribute" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:148 msgid "elements" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:319 msgid "Size" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:319 msgid "Type" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:319 msgid "Value" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:417 msgid "" "Opening this variable can be slow\n" "\n" "Do you want to continue anyway?" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:428 msgid "Spyder was unable to retrieve the value of this variable from the console.

The error mesage was:
%s" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:605 msgid "Edit item" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:606 msgid "Unable to assign data to item.

Error message:
%s" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:666 msgid "Resize rows to contents" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:677 #: spyder/widgets/variableexplorer/collectionseditor.py:1027 #: spyder/widgets/variableexplorer/collectionseditor.py:1044 msgid "Plot" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:681 msgid "Histogram" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:685 msgid "Show image" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:689 #: spyder/widgets/variableexplorer/collectionseditor.py:1052 msgid "Save array" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:693 #: spyder/widgets/variableexplorer/collectionseditor.py:991 #: spyder/widgets/variableexplorer/collectionseditor.py:999 msgid "Insert" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:706 #: spyder/widgets/variableexplorer/collectionseditor.py:952 msgid "Duplicate" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:929 msgid "Do you want to remove the selected item?" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:930 msgid "Do you want to remove all selected items?" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:950 msgid "New variable name:" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:953 msgid "Variable name:" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:991 msgid "Key:" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:999 msgid "Value:" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:1015 msgid "Import error" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:1016 msgid "Please install matplotlib or guiqwt." msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:1028 msgid "Unable to plot data.

Error message:
%s" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:1045 msgid "Unable to show image.

Error message:
%s" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:1068 msgid "Unable to save array

Error message:
%s" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:1093 msgid "It was not possible to copy this array" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:1118 msgid "Clipboard contents" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:1133 msgid "Import from clipboard" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:1135 msgid "Empty clipboard" msgstr "" #: spyder/widgets/variableexplorer/collectionseditor.py:1136 msgid "Nothing to be imported from clipboard." msgstr "" #: spyder/widgets/variableexplorer/dataframeeditor.py:591 msgid "To bool" msgstr "" #: spyder/widgets/variableexplorer/dataframeeditor.py:591 msgid "To complex" msgstr "" #: spyder/widgets/variableexplorer/dataframeeditor.py:592 msgid "To float" msgstr "" #: spyder/widgets/variableexplorer/dataframeeditor.py:592 msgid "To int" msgstr "" #: spyder/widgets/variableexplorer/dataframeeditor.py:593 msgid "To str" msgstr "" #: spyder/widgets/variableexplorer/dataframeeditor.py:677 msgid "%s editor" msgstr "" #: spyder/widgets/variableexplorer/dataframeeditor.py:711 msgid "Column min/max" msgstr "" #: spyder/widgets/variableexplorer/dataframeeditor.py:751 msgid "Format ({}) is incorrect" msgstr "" #: spyder/widgets/variableexplorer/dataframeeditor.py:755 msgid "Format ({}) should start with '%'" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:118 #: spyder/widgets/variableexplorer/importwizard.py:438 msgid "Import as" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:120 msgid "data" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:124 msgid "code" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:127 #: spyder/widgets/variableexplorer/importwizard.py:514 msgid "text" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:140 msgid "Column separator:" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:144 msgid "Tab" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:147 msgid "Whitespace" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:150 #: spyder/widgets/variableexplorer/importwizard.py:168 msgid "other" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:161 msgid "Row separator:" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:165 msgid "EOL" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:180 msgid "Additional options" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:184 msgid "Skip rows:" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:195 msgid "Comments:" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:201 msgid "Transpose" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:441 msgid "array" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:446 msgid "list" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:451 msgid "DataFrame" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:497 #: spyder/widgets/variableexplorer/importwizard.py:581 msgid "Import wizard" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:502 msgid "Raw text" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:505 msgid "variable_name" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:516 msgid "table" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:517 msgid "Preview" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:521 msgid "Variable Name" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:544 msgid "Done" msgstr "" #: spyder/widgets/variableexplorer/importwizard.py:582 msgid "Unable to proceed to next step

Please check your entries.

Error message:
%s" msgstr "" #: spyder/widgets/variableexplorer/namespacebrowser.py:181 #: spyder/widgets/variableexplorer/namespacebrowser.py:385 msgid "Import data" msgstr "" #: spyder/widgets/variableexplorer/namespacebrowser.py:184 #: spyder/widgets/variableexplorer/namespacebrowser.py:465 #: spyder/widgets/variableexplorer/namespacebrowser.py:479 msgid "Save data" msgstr "" #: spyder/widgets/variableexplorer/namespacebrowser.py:189 msgid "Save data as..." msgstr "" #: spyder/widgets/variableexplorer/namespacebrowser.py:201 msgid "Exclude references which name starts with an underscore" msgstr "" #: spyder/widgets/variableexplorer/namespacebrowser.py:209 msgid "Exclude references which name is uppercase" msgstr "" #: spyder/widgets/variableexplorer/namespacebrowser.py:216 msgid "Exclude references which name starts with an uppercase character" msgstr "" #: spyder/widgets/variableexplorer/namespacebrowser.py:224 msgid "Exclude references to unsupported data types (i.e. which won't be handled/saved correctly)" msgstr "" #: spyder/widgets/variableexplorer/namespacebrowser.py:405 msgid "Unsupported file extension '%s'

Would you like to import it anyway (by selecting a known file format)?" msgstr "" #: spyder/widgets/variableexplorer/namespacebrowser.py:413 msgid "Open file as:" msgstr "" #: spyder/widgets/variableexplorer/namespacebrowser.py:447 msgid "Unable to load '%s'

Error message:
%s" msgstr "" #: spyder/widgets/variableexplorer/namespacebrowser.py:480 msgid "Unable to save current workspace

Error message:
%s" msgstr "" #: spyder/widgets/variableexplorer/texteditor.py:74 msgid "Text editor" msgstr "" #: spyder/widgets/variableexplorer/utils.py:30 msgid "View and edit DataFrames and Series in the Variable Explorer" msgstr "" #: spyder/widgets/variableexplorer/utils.py:35 msgid "View and edit two and three dimensional arrays in the Variable Explorer" msgstr "" #: spyder/workers/updates.py:90 spyder/workers/updates.py:92 msgid "Unable to retrieve information." msgstr "" #: spyder/workers/updates.py:94 msgid "Unable to connect to the internet.

Make sure the connection is working properly." msgstr "" #: spyder/workers/updates.py:97 msgid "Unable to check for updates." msgstr "" spyder-3.2.6/spyder/locale/fr/0000775000175000017500000000000013225025006016771 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/locale/fr/LC_MESSAGES/0000775000175000017500000000000013225025007020557 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/locale/fr/LC_MESSAGES/spyder.mo0000664000175000017500000032713713224121062022434 0ustar carloscarlos000000000000007!CZY Zwc[\ \ ] ]#]>]G]N]R] q] {]]]]]]] ]] ]] ] ]^ ^^!^)^.^6^<^D^K^Q^Z^c^l^u^~^^W^b^<K_"_x_4$`Y`xaFbDVc9cAcBdDZdQd1d6#e;Ze7eceB2f7ufCf;f8-gtfg!ggh&j!j;jljr'Ɓ+aQQ߂"1)T(~'σ  + D N\ z3„ ҄ ׅ  ,:ZWȆ %DZ_*7@^} &̈ !,=L \}ى> 8 FT erz   .ˊ  < I S^eMkm'?F_!x Ō -> W e&q*ލ .@HMU= ( 6@Wn  ʐ א #&9` r}{Jƒ  ̔{ڔV ]~ ǖ ֖ %C0Y ї *<KP=&ژ1`3I9ޙd<} ؚ͚ *.3FOXk!4 <HY_f Ɯߜ &=Y;u ʝ ם>#*8cr w Ӟ!T7=u   ɠѠ ٠  4 = H S ] iw ǡgڡB"]  &  0B IUY ,/8h mz:ߤ & 0> O\ oB|ǥϥ ޥ "+JP$e&P+w  çΧMާ,2B%uRC237 k x+"ë!ʬ * ;H \i}խ  !.AP_n}  Үޮ116LUg{%ʯ+$94>s %ɰ5 %1D[ b mw *±   #D\n ²βֲ 5!Rt 'ճ# 7BV_t}75) 2 >L jw ,Dĵ  $$3 XcsE  1 ;HYm- ƷηԷ" E!Rg1ظ  $2P_ hs ù5ҹ'0NUl#º=|WԻ>42^gƼۼ6 ?M_8o½ ׽ \9xƾ"ؾLHdvDֿ =Og  4 O[`e lw} !%#7 M[4<N8M=_89&9N`ptSH P] ep u ,  !=Mbs+ C:#^ o{  =:.i  .fD1Nl(ChF+Lx;':c *iTl-Y[  Wp]n&>{P#/7Mg   &0LRW[X& &"[29 !%3Yq}7= DRds<G\*d#  }ap ns$;1ImxA   .>E`fk s~ )  # ,9B YYg` { ,*(7? ] hr{      + 8C K V ` j t ~ jrKz&C>4 I@ARPTpS<?VHIx)SJSAOD*.F3%Hn F64}ELE U h  p Z     0 : L ^    _1 @ 1 3 8 !@  b $l .  !  C1ERw) )3</p<='NC '-G N Xc u   K<-3F<N.( B(kB%):U4q&  AUo &% "2 Bcv 'K 7D Z{  7 ,5Q gs!@Vj 7)Ea/h6?F'Mu- @-n) (4*6_OK LR +   ! ! ! #!0! @!@M! !!!0!";"Y"[!#%}#8#4#2$#D$h$}$ $$$$$$$&$%%<$%a% u%#% &C&& ''-'%='c'' (((9/(-i(6(!((By)>)F) B* c*)m* *,*+*"* + 5+C+Z+j+"{+++++,+$,D,,q,,,, ,,,,-*4- _-?j---#-- .. '.1.fG..S/q/x//,////00 70B0 W0a0u0"0)000; 1(G17p1,11 1 112 %2/242<2K3L4j4 4(4&44 4 5 &515 K5V5 l5z5 5 55555'566)67g7:%:::P:!`:::Y<6b<<<< <<<< < ==0= J=U=)r=4== ===>/>G> ]>(k>$>$>_>9>?!x?.??6R@E@@:OAA A AA AA(ABB#B*B =BHBOBVmB!B BBBC*C2C#;C_CfClC#CC*C C%D/=D mD+D(DXD HH H II I!I3IEI LI YIgI"kIIII!III J J(J7J$KJpJJJJJJmKKKKKK@K8LGLVLqLzLLL L LLM M?MMNN6NBJNN!N&NNO$O:OKObOUrOO O O OO P P&P-P 4P&APhPoP;PPP,Q/QQRR R %RHFR@R5S0Tj7TbTU6 UCU RU`UuU-W30WdWX X"X?X*UXXXXXXX YY'Y6YLY`Y|YYYY'Y Z8Z HZVZ kZ yZZZZZ Z ZZ Z[[L0[}["[ [*['['\.-\+\\.\+\\\ ]P]c]z]] ]]/]H ^ R^\^%y^^^ ^&^^^&_7=_u____!_!_! `!+`)M`w`` ` ``` ` ``$a,:a)ga;a a#aa b- b5Nbb bbb'bc-cMc_c&zcJcczdddd,dee8e4Re^ee eff<7ftff.f?fWg#lgg ggggh+h4GhM|hhh hh4i JiUiZoifi'1j0Yjjj$jHj!k =kKk.^kkk"kkHl6JlYl$lum1vm5m$mHnLn3nyoOoo#yp/p*pp$q%q7qOq gqSq/q$ r1rFrdrrrM,s!zssKs\s*Ztt(tUtu?uZuku1uu)uu#vBv\v"|vvvv#v,w+Gwswww ww www wwwx:)xdx8zx1xx xzI3z}zRz||B}V};j}?}%} ~+~J~]~pu~r~Yb y B$ :#[ (ƀۀ 2 JhWЁE, BN$Rw Â̂҂IG= 2 JUef~3p 1?Oqb, MfE)Ao*;܉'?b  L)'__uiՒ?L͓a|0SBOǚu Ĝۜ " 06;?*ʝ5p+$ ߞ( :*etw$ '&3#Z ~$Ġ)ޠ &Gwfޡ 2DX"x(ĢL͢T o>y ,ţ. 9 " - : DNmm)ۥ%+= \ i~wA8SM7@Ic kw|  Ϭ߬!% DNQgk:q  ϭ׭߭  .8OE^Y Ti2f\!s"iL?'j&9CmH9S >1ln ;2+@r>g|XO'b}8T6l1qB <$Ed`FCge:#>or5 jkx"avEU{h 3oog a,aMMdX] $B[n-I[I!3-y`m5Oh \H'$~0x^D JR;y6Uf[t#P.jR0./ ~DcW4Q(Pp  -=7*H6G|9G%e!\{a ;2!z/ .b5P"17q<)w,D*J)4}4."+MnZw\_AG$F|%vR<&14Txs>'J(F Y)!SY#ww h0u3m}_S#&i I 0t-C4DVfyA3mN, QN6c[@(9Nt:qu=p(]LZ2`-,%u+l$3/V eQV+=xfpL7 5nKpIT1lbvRU*rz:*&Z0hugCrEvA8BO+jSe%{b|)^kM*"7?  z Adt%/^oB5K(Q~W']=cUJkW c&K?GK O]`kizVy?Z NPs6<:X@.Y~7,sX#}{ 28FW/;qH d8@L__) Numpy Array/Matrix Helper
Enter an array in the table.
Use Tab to move between cells.

Hit 'Enter' for array or 'Ctrl+Enter' for matrix.

Hint:
Use two tabs at the end of a row to move to the next row. Numpy Array/Matrix Helper
Type an array in Matlab : [1 2;3 4]
or Spyder simplified syntax : 1 2;3 4

Hit 'Enter' for array or 'Ctrl+Enter' for matrix.

Hint:
Use two spaces or two tabs to generate a ';'. Searching for files... Installed Required Scanning: {0} Searching for files in folder: {0} entries lines ms%s are currently not supported%s arrays%s editor&Close&Configuration per file...&Debug&Edit&File&Find in files&Find text&Help&New file...&Open...&Print...&Projects&Quit&Replace text&Restart&Revert&Run&Run...&Save&Search&Tools&View2 spaces3 spaces4 spaces5 spaces6 spaces7 spaces8 spaces%s contains mixed end-of-line characters.
Spyder will fix this automatically.%s has been modified outside Spyder.
Do you want to reload it and lose all your changes?%s has been modified.
Do you want to save changes?%s is not a Spyder project!%s is unavailable (this file may have been removed, moved or renamed outside Spyder).
Do you want to close it?-u is added to the other options you set hereSpyder %s is available!

Please use your package manager to update Spyder or go to our Releases page to download this new version.

If you are not sure how to proceed to update Spyder please refer to our Installation instructions.Spyder has encountered a problem.
Sorry for the inconvenience.

You can automatically submit this error to our Github issues tracker.

Note: You need a Github account for that.Spyder is a powerful Interactive Development Environment (or IDE) for the Python programming language.

Here we are going to guide you through its most important features.

Please use the arrow keys or click on the buttons below to move along the tour.Spyder is an interactive development environment based on blaUnable to %s %s

Error message:
%sUnable to assign data to item.

Error message:
%sUnable to create file %s

Error message:
%sUnable to create folder %s

Error message:
%sUnable to delete {varpath}

The error message was:
{error}Unable to find external program.

%sUnable to load '%s'

Error message:
%sUnable to move %s

Error message:
%sUnable to plot data.

Error message:
%sUnable to proceed to next step

Please check your entries.

Error message:
%sUnable to rename file %s

Error message:
%sUnable to save array

Error message:
%sUnable to save current workspace

Error message:
%sUnable to save file '%s'

Error message:
%sUnable to show image.

Error message:
%sUnsupported file extension '%s'

Would you like to import it anyway (by selecting a known file format)?Unsupported file type '%s'Warning:
The Python module rope is not installed on this computer: calltips, code completion and go-to-definition features won't be available.You have missing dependencies!

%s

Please install them to avoid this message.

Note: Spyder could work without some of these dependencies, however to have a smooth experience when using Spyder we strongly recommend you to install all the listed missing dependencies.

Failing to install these dependencies might result in bugs. Please be sure that any found bugs are not the direct result of missing dependencies, prior to reporting a new issue.

Removing all variables...

Restarting kernel...


IMPORTANT NOTE: It seems that you are using Spyder with Anaconda/Miniconda. Please don't use pip to update it as that will probably break your installation.

Instead, please wait until new conda packages are available and use conda to perform the update.
(Refer to the {} page)

If enabled, Python source code will be analyzed using pycodestyle, lines that are not following PEP8 style guide will be highlighted.

Note: add analysis:ignore in a comment to ignore style analysis warnings.

If enabled, Python source code will be analyzed using pyflakes, lines containing errors or warnings will be highlighted.

Note: add analysis:ignore in a comment to ignore code analysis warnings.

Warning: changes are applied separatelyA compound sequence can have {break} a maximum of 4 subsequences.{break}About %sAbout %s...Activate supportAdd &block commentAdd block comment around current line or selectionAdd pathAdditional featuresAdditional optionsAddress:Advanced SettingsAdvanced settingsAll changes to %s will be lost.
Do you want to revert file from disk?All filesAll files (*)All files (*.*)All user-defined variables will be removed. Are you sure you want to proceed?Always show %s on a first file runAn error occurred while creating a socket needed by Spyder. Please, try to run as an Administrator from cmd.exe the following command and then restart your computer:

netsh winsock reset
An error ocurred while starting the kernelAnalysisAnimated toolbars and panesAppearanceAre you sure you want to delete this scheme?Are you sure you want to restart the kernel?ArgumentsArray dimensions not validArray editorArrays with more than 3 dimensions are not supportedAsk for confirmation before closingAsk for confirmation before removing all user-defined variablesAttached console window (debugging)AttributeAutocallAutocall makes IPython automatically call any callable object even if you didn't type explicit parentheses.
For example, if you type str 43 it becomes str(43) automatically.Autocall: AutomaticAutomatic code completionAutomatic connectionsAutomatic importAutomatic indentation after 'else', 'elif', etc.Automatic insertion of closing quotesAutomatic insertion of colons after 'for', 'if', 'def', etcAutomatic insertion of parentheses, braces and bracketsAutomatically load Pylab and NumPy modulesAutomatically remove trailing spaces when saving filesAxis:BackBackend:BackgroundBackground colorBackground:Batch filesBoldBreakpointBrowseBrowse a working directoryBrowse repositoryBrowse tabsBufferBuffer...Buffer: Builtin:C filesC&lose allC&onsolesC++ filesCPU and memory usage info in the status barCPU usage status: requires the `psutil` (>=v0.3) libraryCPU:CSV text filesCancelCannot restart a kernel not started by Spyder Carriage return (Mac)Carriage return and line feed (Windows)Case SensitiveCase sensitive code completionCell starts at line %sChange to lowercase current line or selectionChange to parent directoryChange to uppercase current line or selectionChanging backend to Qt for MayaviCheck for updates on startupCheck for updates...Class defined at line %sClear all ouputClear breakpoints in all filesClear consoleClear lineClear line or blockClear recent files listClear shellClear shell contents ('cls' command)Clear this listClipboard contentsClose ProjectClose all but thisClose all opened filesClose all to the rightClose current fileClose current paneClose current tabClose this panelClose this windowClose windowClosing SpyderCodeCode Introspection/AnalysisCode analysisCode analysis requires pyflakes %s+Code annotations (TODO, FIXME, XXX, HINT, TIP, @todo, HACK, BUG, OPTIMIZE, !!!, ???)Collapse allCollapse selectionColor scheme editorColumn min/maxColumn separator:Column:Command line options:CommentComment current line or selectionComment:Comments:CommitCompletion TypeCompletion:Condition:Configuration filesConfiguration for high DPI screens

Please see {0}<> for more information about these options (in English).ConflictsConnect to an existing kernelConnecting to kernel...Connection errorConnection info:ConsoleConsole directoryConsole helpContextContinueContinue execution until next breakpointConversion errorConvert end-of-line charactersConvert to Python scriptCopyCopy path to clipboardCopy to clipboardCopy without promptsCould not connect to remote hostCould not open ssh tunnel. The error was: CreateCreate a new editor windowCreate new projectCreate new schemeCurrent cell:Current line:Current shortcut:Current user environment variables...Current working directoryCurrently used to delete lines on editorCursor blinking:Custom margin for panes:CutCython/Pyrex filesDataDataFrameDebug fileDebug toolbarDebug with winpdbDecide how graphics are going to be displayed in the console. If unsure, please select %s to put graphics inside the console or %s to interact with them (through zooming and panning) in a separate window.Decide how to render the figures created by this backendDecide what type of completion to useDefault (i.e. the same as Spyder's)Default is 4Default is 6Default is
In [<span class="in-prompt-number">%i</span>]:Default is
Out[<span class="out-prompt-number">%i</span>]:Default working directory is:Definition:DeleteDelete LayoutDelete ProjectDelete...DependenciesDependencies...DictionaryDirectly enter debugging when errors appearDisplayDisplay balloon tipsDisplay initial bannerDo you really want to delete %s?Do you really want to delete {filename}?

Note: This action will only delete the project. Its files are going to be preserved on disk.Do you really want to remove selected path?Do you really want to rename %s and overwrite the existing file %s?Do you want to close all other consoles connected to the same kernel as this one?Do you want to close this console?Do you want to remove all selected items?Do you want to remove the selected item?Do you want to reset to default values?Do you wish to restart now?Don't show again.DoneDuplicateEOLEditEdit filename filtersEdit filename filters...Edit itemEdit selectedEdit template for new modulesEdit toolbarEditorEditor's code completion, go-to-definition and helpEmpty clipboardEmpty projectEnable Tab completion on elements of lists, results of function calls, etc, without assigning them to a variable.
For example, you can get completions on things like li[0].<Tab> or ins.meth().<Tab>Enable UMREnable auto high DPI scalingEnaml filesEncoding:End-of-line charactersEnd-of-lines:Enter key selects completionEnter values for different screens separated by semicolons ';', float values are supportedEnvironment variablesEnvironment variables...ErrorError restarting kernel: %s Exclude all-uppercase referencesExclude capitalized referencesExclude private referencesExclude references to unsupported data types (i.e. which won't be handled/saved correctly)Exclude references which name is uppercaseExclude references which name starts with an underscoreExclude references which name starts with an uppercase characterExclude unsupported data typesExclude:Excluded filenames patternExecutablesExecute in a dedicated consoleExecute in an external system terminalExecute in current consoleExisting directoryExpand allExpand selectionExternal ToolsExternal editorExternal editor executable path:External editor path...External editor:External system terminalFast switch between filesFast symbol search in fileFileFile %s already exists.
Do you want to overwrite it?File ExplorerFile explorerFile switcher...File toolbarFile...FilterFind &nextFind &previousFind in filesFind symbols in file...Find textFix automatically and show warning message boxFix indentationFloat formattingFolder %s already exists.Folder name:Folder...Font styleFont: FontsFor %s support, please install one of the
following tools:

%sFor performance reasons, changes applied to masked array won't be reflected in array's data (and vice-versa).Forbidden key sequence!FormatFormat (%s) is incorrectFormat ({}) is incorrectFormat ({}) should start with '%'Format:Fortran filesFullFullscreen modeFunction defined at line %sGIF imagesGUI-based editor:GeneralGeneral settingsGo to cursor positionGo to definitionGo to last edit locationGo to line...Go to line:Go to next code analysis warning/errorGo to next cursor positionGo to previous code analysis warning/errorGo to previous cursor positionGo to step: GraphicalGraphicsGraphics backendGreedy completionHeight:HelpHelp...Here you can get help of any object by pressing %s in front of it, either on the Editor or the Console.%sHelp can also be shown automatically after writing a left parenthesis next to an object. You can activate this behavior in %s.Here you can select the color scheme used in the Editor and all other Spyder plugins.

You can also edit the color schemes provided by Spyder or create your own ones by using the options provided below.
Hide advanced optionsHide toolbarsHighlightHighlight current cellHighlight current lineHighlight matchesHighlight occurrences afterHistogramHistoryHistory depth: History logHistory logsHistory...HomeHost nameIDL filesIPythonIPython ConsoleIPython consoleIPython documentationIPython interactive python environmentIPython notebooksIcon themeIf enabled, pressing Tab will always indent, even when the cursor is not at the beginning of a line (when this option is enabled, code completion may be triggered using the alternate shortcut: Ctrl+Space)If this option is enabled, clicking on an object name (left-click + Ctrl key) will go this object definition (if resolved).If you accept changes, this will modify the current user environment variables directly in Windows registry. Use it with precautions, at your own risks.

Note that for changes to take effect, you will need to restart the parent process of this application (simply restart Spyder if you have executed it from a Windows shortcut, otherwise restart any application from which you may have executed it, like Python(x,y) Home for example)ImportImport asImport dataImport errorImport from clipboardImport wizardIn this pane you can view and edit the variables generated during the execution of a program, or those entered directly in one of Spyder consoles.

As you can see, the Variable Explorer is showing the variables generated during the last step of this tour. By doing a double-click on any of them, a new window will be opened, where you can inspect and modify their contents.IndentIndent current line or selectionIndentation characters: IndexIndex:InformationInitializing...InlineInline backendInput prompt:InsertInspect current objectInstalled Python modulesInstance:Integrate the IPython consoleIntelligent backspaceInteract with the Python console after executionInteractive toursInterfaceInternal consoleInternal console settingsInternal editor:Intro to IPythonIntroduction tourIntrospectionInvalid directory pathInvalid file pathInvalid key enteredIt was not possible to close the previous Spyder instance. Restart aborted.It was not possible to convert this notebook. The error is: It was not possible to copy this arrayIt was not possible to copy values for this arrayIt was not possible to generate rich text help for this object.
Please see it in plain text.It was not possible to remove outputs from this notebook. The error is: It was not possible to restart Spyder. Operation aborted.It was not possible to restart the IPython console when switching to this project. The error was {0}It was not possible to run this file in an external terminalItalicJPEG imagesJSON filesJavascript filesJson filesJulia filesKernel died, restartingKernel restartingKeyKey:Keyboard shortcutsKeyword:LanguageLast edit locationLayout %s will be overwritten. Do you want to continue?Layout Display and OrderLayout preferencesLine %sLine count:Line feed (UNIX)Line:Lines:Link to object definitionLink:ListLoading %s...Loading IPython console...Loading editor...Loading file explorer...Loading help...Loading history plugin...Loading namespace browser...Loading online help...Loading outline explorer...Loading project explorer...Loading this kind of data while debugging is not supported.LocationLockLock panesMATLAB filesMain toolbarMaintain focus in the Editor after running cells or selectionsManage color schemesManipulate Jupyter notebooks on the EditorMarkdown filesMaskMasked dataMatched
parens:Matlab filesMatplotlib documentationMaximize current paneMaximum entriesMaximum line countMaximum number of recent filesMaximum number of recent files...Memory usage status: requires the `psutil` (>=v0.3) library on non-Windows platformsMemory:Method defined at line %sModify how Input and Output prompts are shown in the console.ModuleModule pywin32 was not found.
Please restart this Windows session (not the computer) for changes to take effect.Module or package:Module...Move DownMove UpMove downMove to bottomMove to topMove upMove...NSIS filesNameName filters:NewNew Project...New directoryNew features in version 3.0New fileNew folderNew moduleNew name:New packageNew shortcut:New to Spyder? Read ourNew variable name:New windowNextNext cursor positionNext warning/errorNo IPython console is currently available to run %s.

Please open a new one and try again.No documentation availableNo further documentation availableNo matchesNo source code available.NormalNormal text:Nothing to be imported from clipboard.NumPy arrayNumPy arraysNumPy zip arraysNumber:Numpy and Scipy documentationO&pen last closedObjectOccurrence:OffOn %s mode, Autocall is not applied if there are no arguments after the callable. On %s mode, all callable objects are automatically called (even if no arguments are present).Online documentationOnline helpOnly used when the format is PNG. Default is 72OpenOpen &recentOpen IPython console hereOpen Project...Open a new IPython console connected to an existing kernelOpen an &IPython consoleOpen command prompt hereOpen connection fileOpen fileOpen file as:Open last closedOpen projectOpen terminal hereOpenCL filesOpening this variable can be slow Do you want to continue anyway?OptionsOutlineOutput prompt:PNG imagesPYTHONPATH managerPackage name:Package...PanesParentPasswordPassword or ssh key passphrasePastePatch and diff filesPath to connection file or kernel idPath to ssh key filePerfom symbolic operations in the console (e.g. integrals, derivatives, vector calculus, etc) and get the outputs in a beautifully printed style (it requires the Sympy module).Perform analysis only when saving filePerform analysis when saving file and everyPermissions:Pickle filesPlainPlain TextPlain text fontPlease consider installing Sphinx to get documentation rendered in rich text.Please enter the connection info of the kernel you want to connect to. For that you can either select its JSON connection file using the Browse button, or write directly its id, in case it's a local kernel (for example kernel-3764.json or just 3764).Please install matplotlib or guiqwt.Please introduce a different shortcutPlease note that these changes will be applied only to new Python/IPython consolesPlease note that these changes will be applied only to new consolesPlotPop up internal console when internal errors appearPre&ferencesPreferencesPreferences > HelpPress Enter to switch files or Esc to cancel.

Type to filter filenames.

Use :number to go to a line, e.g. main:42
Use @symbol_text to go to a symbol, e.g. @init

Press Ctrl+W to close current tab.
Press enter to validate this entryPress enter to validate this pathPress the new shortcut and select 'Ok': (Press 'Tab' once to switch focus between the shortcut entry and the buttons below it)PreviewPreviousPrevious cursor positionPrevious warning/errorPrint current file...Print preview...Printing...ProjectProject ExplorerProject PreferencesProject explorerProject nameProject preferencesProject typePrompt when exitingPromptsProvided featuresPyQt4 API ReferencePyQt4 Reference GuidePyQt5 API ReferencePyQt5 Reference GuidePython Path ManagerPython documentationPython filesPython help:Python interpreterPython packagePython projectPython scriptsPython versionPython2 documentationPython3 documentationQt DesignerQt LinguistQt documentationQt examplesQt windows styleQuick referenceQuick switch layout #%s has not yet been defined.QuitR&emove block commentRaw textRe run last cell Re-run &last scriptRe-run last cellReal-time code analysisReal-time code analysis on the EditorReal-time code style analysisReal-time code style analysis on the EditorRecent ProjectsRecord array fields:RedoRefresh list of module names available in PYTHONPATHRegular expressionRegular expression errorRemoval errorRemoveRemove all variablesRemove all variables before executionRemove comment block around current line or selectionRemove pathRemove references:Remove trailing spacesRenameRename tabRename...Render mathematical equationsReplace allReplace selectionReplace stringReplace tab characters by space charactersReplace with:Replace/find nextReport issue...ResetReset Spyder to factory defaultsReset to default valuesReset to defaultsReset to spyder defaultResetting Spyder to defaultsResizeResize rows to contentsResolution:RestartRestart kernelRestart kernel?RestartingRestoreRestore current paneRestore data on startupRestore original tree layoutRestore pane to its original sizeRevert file from diskRich TextRich text fontRow separator:RunRun &selection or current lineRun Cython files in the IPython ConsoleRun Python scriptRun Settings dialogRun a Python scriptRun a fileRun again last fileRun cellRun cell and advanceRun codeRun configurationRun configuration per fileRun current cell (Ctrl+Enter) [Use #%% to create cells]Run current cell and go to the next one (Shift+Enter)Run current lineRun fileRun script:Run selectionRun selection or current lineRun settingsRun settings for %sRun toolbarRun until current function or method returnsRunning an external system terminal is not supported on platform %s.Sav&e allSaveSave &as...Save all filesSave all files before running scriptSave arraySave copy as...Save copy of current file as...Save current file as...Save current history log (i.e. all inputs and outputs) in a text fileSave current layoutSave dataSave data as...Save data on exitSave fileSave historySave history logSave history log...Save non project files openedSaving data while debugging is not supported.Scheme name:Scheme:ScoreScreen resolutionScroll automatically to last entrySearchSearch directorySearch in all files and directories present on thecurrent Spyder pathSearch in all files and directories present on thecurrent project path (If opened)Search in current opened fileSearch in other folder present on the file systemSearch in:Search patternSearch stringSearch text in multiple filesSearch toolbarSearch: Select AllSelect a run configuration:Select directorySelect fileSelect other directorySelect ssh keySelect the Python interpreter for all Spyder consolesSet UMR excluded (not reloaded) modulesSet a custom high DPI scalingSet console working directorySet current console (and file explorer) working directory to current script directorySet external editor executable pathSet history maximum entriesSet maximum line countSet the list of excluded modules as this: numpy, scipySet the maximum number of lines of text shown in the console before truncation. Specifying -1 disables it (not recommended!)Set this for high DPI displaysSet this for high DPI displays when auto scaling does not workSet this to detach any
menu from the main windowSet this to open external
Python files in an already running instance (Requires a restart)Set/Clear breakpointSet/Edit conditional breakpointSetting up main window...SettingsShell special commands:ShortcutShortcut: {0}Shortcuts SummaryShortcuts resetShortcuts that use Shift and another key are unsupportedShow (read-only) sys.pathShow CPU usage everyShow SourceShow absolute pathShow advanced optionsShow all filesShow and edit current user environment variables in Windows registry (i.e. for all sessions)Show and edit environment variables (for current session)Show arrays min/maxShow blank spacesShow code analysis warnings/errorsShow comments list (TODO/FIXME/XXX/HINT/TIP/@todo/HACK/BUG/OPTIMIZE/!!!/???)Show current directory onlyShow elapsed timeShow environment variablesShow help for objects in the Editor and Consoles in a dedicated paneShow horizontal scrollbarShow icons and textShow imageShow in FinderShow in external file explorerShow line numbersShow memory usage everyShow reloaded modules listShow special commentsShow status barShow sys.path contentsShow sys.path contents...Show tab barShow todo listShow toolbarsShow vertical line afterShow warning/error listShow/hide outline explorerSide areas:SiftSizeSize: Skip rows:SmartSour&ceSourceSource codeSource toolbarSphinx %s is currently installed.Split horizontallySplit horizontally this editor windowSplit verticallySplit vertically this editor windowSpyder Default LayoutSpyder EditorSpyder Internal Console This console is used to report application internal errors and to inspect Spyder internals with the following commands: spy.app, spy.window, dir(spy) Please don't use it to run your code Spyder Keyboard ShortCutsSpyder could not reset to factory defaults. Restart aborted.Spyder data filesSpyder depends on several Python modules to provide the right functionality for all its panes. The table below shows the required and installed versions (if any) of all of them.

Note: You can safely use Spyder without the following modules installed: %s and %s.

Please also note that new dependencies or changed ones will be correctly detected only after Spyder is restarted.Spyder documentationSpyder exit errorSpyder is an interactive development environment based on blaSpyder is up to date.Spyder needs to restart to change the following setting:Spyder needs to restart to change the following settings:Spyder reset errorSpyder restart errorSpyder support...Spyder tutorialSpyder updatesSpyder was unable to retrieve the value of this variable from the console.

The error mesage was:
%sSpyder will restart and reset to default settings:

Do you want to continue?Ssh keyStart searchStartupStatus barStepStep IntoStep ReturnStep into function or method of current lineStopStop debuggingStop searchStop the current commandString not foundString:Submit to GithubSupport for graphics (Matplotlib)Supported filesSupported text filesSymbol finder...Symbolic MathematicsSymbolic mathematics in the IPython ConsoleSynchronizeSynchronize Spyder's path list with PYTHONPATH environment variableSynchronize...Syntax coloringSyntax highlighting for Matlab, Julia and other file typesSystem commands:TIFF imagesTabTab always indentTab stop width:TabulationsTear off menusTemporary fileTerminalTextText editorText filesThe 'xlabels' argument length do no match array column numberThe 'ylabels' argument length do no match array row numberThe current working directory is the working directory for IPython consoles and the current directory for the File Explorer.The EditorThe File ExplorerThe History LogThe IPython consoleThe Variable ExplorerThe authenticity of host %s can't be established. Are you sure you want to continue connecting?The authenticity of the host can't be establishedThe current directory contains a project.

If you want to delete the project, please go to Projects » Delete ProjectThe current project directory or user home directory (if no project is active)The current working directoryThe directory of the file being executedThe directory when a new console is open will be the specified pathThe directory {} is not writable and it is required to create IPython consoles. Please make it writable.The following are the default options for running files.These options may be overriden using the Configuration per file entry of the Run menu.The following conflicts have been detected:The following directory:The following error occured when calling Sphinx %s.
Incompatible Sphinx version or doc string decoding failed.

Error message:
%sThe following modules are not installed on your machine: %sThe following working directory is not valid:
%sThe new shortcut conflicts with:The working directory for new consoles is:This directory is already included in Spyder path list.
Do you want to move it to the top of the list?This entry is incorrectThis error was most probably caused by installing Spyder in a directory with non-ascii characters (i.e. characters with tildes, apostrophes or non-latin symbols).

To fix it, please reinstall Spyder in a different location.This feature requires Sphinx 1.1 or superior.This feature requires the Rope or Jedi libraries. It seems you don't have either installed.This is a remote kernelThis is a temporary script file.This is one of panes where you can run or execute the code you wrote on the Editor. To do it you need to press the F5 key.

This console comes with several useful features that greatly improve your programming workflow (like syntax highlighting and inline plots). If you want to know more about them, please follow this link.

Please click on the button below to run some simple code in this console. This will be useful to show you other important features.This is the pane where you write Python code before evaluating it. You can get automatic suggestions and completions while writing, by pressing the Tab key next to a given text.

The Editor comes with a line number area (highlighted here in red), where Spyder shows warnings and syntax errors. They can help you to detect potential problems before running the code.

You can also set debug breakpoints in the line number area, by doing a double click next to a non-empty line.This is the working directory for newly opened consoles (Python/IPython consoles and terminals), for the file explorer, for the find in files plugin and for new files created in the editorThis lets you load graphics support without importing the commands to do plots. Useful to work with other plotting libraries different to Matplotlib or to develop GUIs with Spyder.This option lets you hide the message shown at the top of the console when it's opened.This option lets you hide the warning message shown when resetting the namespace from Spyder.This option loads the Sympy library to work with.
Please refer to its documentation to learn how to use it.This option will be applied the next time a console is opened.This option will enable the User Module Reloader (UMR) in Python/IPython consoles. UMR forces Python to reload deeply modules during import when running a Python script using the Spyder's builtin function runfile.

1. UMR may require to restart the console in which it will be called (otherwise only newly imported modules will be reloaded when executing files).

2. If errors occur when re-running a PyQt-based program, please check that the Qt objects are properly destroyed (e.g. you may have to use the attribute Qt.WA_DeleteOnClose on your main window, using the setAttribute method)This pane can automatically show an object's help information after a left parenthesis is written next to it. Below you can decide to which plugin you want to connect it to turn on this feature.This pane displays documentation of the functions, classes, methods or modules you are currently using in the Editor or the Consoles.

To use it, you need to press Ctrl+I in front of an object. If that object has some documentation associated with it, it will be displayed here.This pane lets you navigate through the directories and files present in your computer.

You can also open any of these files with its corresponding application, by doing a double click on it.

There is one exception to this rule: plain-text files will always be opened in the Spyder Editor.This pane records all commands introduced in the Python and IPython consoles.This will synchronize Spyder's path list with PYTHONPATH environment variable for current user, allowing you to run your Python modules outside Spyder without having to configure sys.path.
Do you want to clear contents of PYTHONPATH before adding Spyder's path list?To boolTo complexTo doTo floatTo intTo strToggle LowercaseToggle UppercaseToolbarsTransposeTunnel '%s' failed to startTupleTypeUMRUMR forces Python to reload modules which were imported when executing a file in a Python or IPython console with the runfile function.Unable to check for updates.Unable to connect to %sUnable to connect to the internet.

Make sure the connection is working properly.Unable to load pageUnable to retrieve information.UncommentUndoUnexpected error: see internal consoleUnindentUnindent current line or selectionUnlockUnmatched
parens:Update LANGUAGE_CODES (inside config/base.py) if a new translation has been added to SpyderUpdate module names listUsageUse a pager to display additional text inside the consoleUse a single instanceUse next layoutUse previous layoutUse symbolic mathUse the following Python interpreter:Use the following file:Use the greedy completerUse version controlUseful if you don't want to fill the console with long help or completion texts. Note: Use the Q key to get out of the pager.User Module Reloader (UMR)ValueValue:Variable NameVariable explorerVariable name:Version controlVersion control systemVertical tabs in panesVertical title bars in panesViTablesView and edit DataFrames and Series in the Variable ExplorerView and edit two and three dimensional arrays in the Variable ExplorerWarningWe cannot support this shortcut on WindowsWeb page filesWelcome to Spyder introduction tourWelcome to Spyder!Welcome to the Introduction tourWhen opening a text file containing mixed end-of-line characters (this may raise syntax errors in the consoles on Windows platforms), Spyder may fix the file automatically.WhitespaceWhole wordsWidth:WinPythonWinPython control panelWindow layout will be reset to default settings: this affects window position, size and dockwidgets. Do you want to continue?Window layoutsWorking Directory settingsWorkspaceWrap linesXML filesYaml filesYou are working with Python 2, this means that you can not import a module that contains non-ascii characters.You can also run a whole file at startup instead of just some lines (This is similar to have a PYTHONSTARTUP file).You can run several lines of code when a console is started. Please introduce each one separated by commas, for example:
import os, import sysYou don't have the right permissions to open this directoryYou selected a Python %d interpreter for the console but Spyder is running on Python %d!.

Although this is possible, we recommend you to install and run Spyder directly with your selected interpreter, to avoid seeing false warnings and errors due to the incompatible syntax between these two Python versions.You selected an invalid Python interpreter for the console so the previous interpreter will stay. Please make sure to select a valid one.Your Python environment or installation doesn't have the ipykernel and cloudpickle modules installed on it. Without these modules is not possible for Spyder to create a console for you.

You can install them by running in a system terminal:

pip install ipykernel cloudpickle

or

conda install ipykernel cloudpickleZoom inZoom outZoom resetarraycharacterscodecopydatadeletedpielementsfilegettext filesguidata examplesguiqwt examplesinchesinvalid regular expressionlineslistmatchesmatches inmovemsno matchesofotherpermission denied errors were encounteredpixelsreStructuredText filesread onlyspacestabletextthe following directory:this dialogtutorialunsaved fileuntitledusername@hostname:portvariable_nameProject-Id-Version: 2.1 POT-Creation-Date: 2017-12-14 15:40+-05 PO-Revision-Date: 2017-12-17 21:09+0100 Last-Translator: Sylvain Corlay Language-Team: Python Language: fr MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: pygettext.py 1.5 X-Generator: Poedit 2.0.4 Constructeur de Tableau/Matrice Numpy
Entrez un tableau Numpy dans le tableau.
Appyuyez sur la touche 'Tab' pour vous déplacer entre les cellules.

Appuyez sur la touche 'Entrée' pour le tableau ou 'Ctrl + Entrée' pour la matrice.

Conseil : appuyez deux fois sur la touche 'Tab' à la fin d'une ligne pour passer à la ligne suivante. Constructeur de Tableau/Matrice Numpy
Tapez un tableau dans Matlab : [1 2; 3 4]
ou la syntaxe simplifiée de Spyder: 1 2; 3 4

Appuyez sur la touche 'Entrée' pour le tableau Numpy ou 'Ctrl+Entrée' pour la matrice Numpy.

Conseil:
Utilisez deux espaces ou deux onglets pour générer un ';'. Recherche de fichiers… Installé Requis Recherche en cours : {0} Recherche de fichiers dans le dossier : {0} lignes lignes ms%s ne sont actuellement pas pris en chargeLes tableaux %sÉditeur de %s&Fermer&Configuration par fichier…&Déboguer&Édition&FichierRechercher dans des &fichiersRec&hercherA&ide&Nouveau fichier...&Ouvrir...Im&primer...&Projets&Quitter&Remplacer&Redémarrer&RéinitialiserE&xécutionExécute&r...&Enregistrer&RechercheOu&tils&Affichage2 espaces3 espaces4 espaces5 espaces6 espaces7 espaces8 espaces%s contient des caractères de fin de ligne mélangés.
Spyder va corriger ceci automatiquement.%s a été modifié en dehors de Spyder.
Souhaitez-vous le recharger et perdre ainsi vos modifications ?%s a été modifié.
Souhaitez-vous enregistrer ces changements ?%s n'est pas un projet Spyder !%s n'est pas accessible (ce fichier a peut-être été supprimé, déplacé ou renommé en dehors de Spyder).
Souhaitez-vous le fermer ?L'option -u est ajoutée aux autres options spécifiées iciSpyder %s est disponible !

Utiliser le gestionnaire de paquets pour mettre à jour Spyder, consultez le site pour télécharger le programme directement.

Si vous ne savez pas comment procéder pour mettre Spyder à jour, veuillez consulter notre documentation.Spyder a rencontré un problème.
Désolé pour les inconvénients.

Vous pouvez envoyer automatiquement cette erreur à notre agent de suivi des problèmes sur Github.

Remarque : Vous avez besoin d’un compte Github pour cela.Spyder est un environnement de développement interactif (ou IDE) pour le langage de programmation Python.

Nous allons vous guider à travers ses caractéristiques les plus importantes. Utilisez les touches fléchées ou cliquez sur les boutons ci-dessous pour parcourir la visite interactive.Spyder est un environnement de développement interactif basé surImpossible de %s %s

Message d'erreur :
%sImpossible d'assigner la valeur de l'objet.

Message d'erreur :
%sImpossible de créer le fichier %s

Message d'erreur :
%sImpossible de créer le répertoire %s

Message d'erreur :
%sImpossible de supprimer {varpath

Message d'erreur :
{error}Impossible de trouver un programme externe.

%sImpossible d'ouvrir '%s'

Message d'erreur :
%sImpossible de déplacer %s

Message d'erreur :
%sImpossible d'afficher les données

Message d'erreur :
%sImpossible de passer à l'étape suivante

Merci de vérifier votre saisie.

Message d'erreur :
%sImpossible de renommer l'élément %s

Message d'erreur :
%sImpossible d'enregistrer le tableau

Message d'erreur :
%sImpossible d'enregistrer l'espace de travail

Message d'erreur :
%sImpossible d'enregistrer le fichier '%s'

Message d'erreur :
%sImpossible d'afficher l'image

Message d'erreur :
%sExtension de fichier non pris en charge '%s'

Souhaitez-vous néanmoins ouvrir ce fichier (en choisissant un format de fichier connu) ?Type de fichier non pris en charge '%s'Avertissement :
Le module Python rope n'est pas installé sur cet ordinateur : les fonctionnalités telles que la complétion de code ou le lien vers la définition d'un objet ne sont donc pas accessibles.Il manque certaines dépendances

%s
Veuillez les installer pour éviter ce message

Remarque
: Spyder pourrait fonctionner sans certaines de ces dépendances, mais pour avoir une bonne expérience lors de l'utilisation de Spyder nous fortement vous recommandons d'installer toutes les dépendances manquantes.

L'impossibilité d'installer ces dépendances peut entraîner des bogues. Assurez-vous que les bogues trouvés ne résultent pas directement des dépendances manquantes avant de signaler un nouveau problème.

Suppression de toutes les variables...

Redémarrage du noyau...


IMPORTANT : il semble que vous utilisiez Spyder avec Anaconda/Miniconda. Il est fortement conseillé de ne pas recourir à pip pour le mettre à jour, puisqu'il est probable que cela casse votre installation.

À la place, il est suggéré de simplement attendre la disponibilité de nouveaux paquets conda avant d'utiliser conda pour effectuer la mise à jour.
(référer à la page {})

Si cette option est activée, le style du code source Python sera analysé avec l'outil d'introspection de code PEP8 et les lignes ne suivant pas les recommandations officielles seront indiquées.

Note : rajouter analysis:ignore dans un commentaire pour ignorer les avertissements d'analyse de code.

Si cette option est activée, le code source Python sera analysé avec des outils l'outil d'introspection de code pyflakes, et les lignes contenant des erreurs seront indiquées.

Note : rajouter analysis:ignore dans un commentaire pour ignorer les avertissements d'analyse de code.

Attention : les changements seront pris en compte séparémentUne séquence composée peut avoir {break} au plus 4 sous-séquences.{break}À propos de %sÀ propos de %s...ActiverAjouter un &bloc de commentairesAjouter un bloc de commentaires autour de la sélection ou de la ligne en cours d'éditionAjouter un cheminOptions supplémentairesOptions supplémentairesAdresse :Options avancéesOptions avancéesToutes les modifications effectuées sur %s seront perdues.
Souhaitez-vous revenir à la version du fichier enregistrée sur le disque ?Tous les fichiersTous les fichiers (*)Tous les fichiers (*.*)Toutes les variables définies par l'utilisateur seront supprimées. Souhaitez-vous continuer ?Toujours afficher %s lors de la première exécution d'un scriptUne erreur s’est produite lors de la création d’un websocket requis par Spyder. S’il vous plaît, essayez d’exécuter la commande suivante comme administrateur dans une console cmd.exe, puis redémarrez votre ordinateur :

netsh winsock reset
Une erreur est survenue lors du démarrage du noyauAnalyseVolets et barres d'outils animésApparenceSouhaitez-vous supprimer ce thème ?Souhaitez-vous vraiment redémarrer le noyau ?ArgumentsDimensions du tableau non validesÉditeur de tableauxLes tableaux de plus de trois dimensions ne sont pas pris en chargeDemander confirmation avant de fermer une consoleDemander confirmation avant de supprimer les variables définies par l'utilisateurInvite de commandes attachée (débogage)AttributAppel automatiqueL'appel automatique dans IPython va automatiquement appeler les objets appelables même sans parenthèses explicites.
Par exemple str 43 deviendra automatiquement str(43).Appel automatique : AutomatiqueComplétion de code automatiqueConnexions automatiquesImport automatiqueIndentation automatique après 'else', 'elif', etc.Insertion automatique de guillemets de clôtureInsertion automatique de ':' après 'for', 'if', 'def', etc.Insertion automatique des parenthèses, crochets et accoladesImporter automatiquement Pylab et NumPySupprimer automatiquement les espaces en fin de ligne lors de l'enregistrementAxe :RetourSortie :FondCouleur de fondFond :Fichiers BatchGrasPoint d'arrêtParcourirSélectionner un répertoire de travailExplorer le dépôtNaviguer dans les ongletsTamponTampon...Tampon : Objet intégré :Fichiers CFermer t&outC&onsolesFichiers C++Informations sur l'utilisation processeur et mémoire dans la barre d'étatOccupation CPU : requiert la bibliothèque `psutil` (>=v0.3)CPU :Fichiers texte CSVAnnulerImpossible de redémarrer un noyau non démarré par Spyder Retour chariot (Mac)Retour chariot et retour à la ligne (Windows)Respecter la casseComplétion de code sensible à la casseCellule commençant ligne %sConvertir en minuscule la sélection ou le mot en cours d'éditionAller au répertoire parentConvertir en majuscule la sélection ou le mot en cours d'éditionUtilisation du backend Qt pour MayaviVérifier les mises à jour au démarrageRechercher les mises à jour...Classe déclarée ligne %sEffacer tous les résultatsSupprimer les points d'arrêt dans tous les fichiersEffacer la consoleEffacer la ligneEffacer la ligne ou le blocEffacer la liste des fichiers récentsEffacer la consoleEffacer le contenu de la consoleEffacer cette listeContenu du presse-papiersFermer le projetFermer tout sauf cet ongletFermer tous les fichiers ouvertsFermer tous les onglets vers la droiteFermer le fichier en cours d'éditionFermer le volet courantFermer l'ongletFermer ce voletFermer cette fenêtre d'éditionFermer la fenêtreFermeture du programmeCodeIntrospection et analyse de codeAnalyse de codeL'analyse de code requiert pyflakes %s+Tâches (TODO, FIXME, XXX, HINT, TIP, @todo, HACK, BUG, OPTIMIZE, !!!, ???)Replier toutReplier la sélectionEditeur de coloration syntaxiqueColonne min/maxSéparateur de colonne :Colonne :Options en ligne de commande :CommenterCommenter la sélection ou la ligne en cours d'éditionCommentaire :Commentaires :CommiterType de complétion de codeComplétion de code :Condition :ConfigurationsConfiguration pour les écrans PPP/DPI élevés

Consultez {0}<> pour plus d’informations sur ces options (en anglais).ConflitsConnecter à un noyau existantConnexion au noyau...Erreur de connexionInformation de connexion :ConsoleRépertoire de la consoleAide sur la consoleContexteContinuerContinuer l'exécution jusqu'au prochain point d'arrêtErreur de conversionConvertir les caractères de fin de ligneConvertir en fichier PythonCopierCopier le chemin d'accès dans le presse-papierCopier dans le presse-papierCopier sans les préfixesImpossible d'établir la connection au serveur distantImpossible d'ouvrir un tunnel ssh. L'erreur rencontrée est : CréerCréer une nouvelle fenêtre d'éditionCréer un nouveau projetCréer un nouveau thèmeCellule actuelle :Ligne actuelle :Raccourci actuel :Variables d'environnement de l'utilisateur...Le répertoire de travail actuelActuellement utilisé pour supprimer des lignes sur l’éditeurClignotement du curseur :Marges personnalisées pour les onglets :CouperFichiers Cython/PyrexDonnéesDataFrameDéboguer le scriptBarre d'outils de débogageDéboguer avec winpdbCette option permet de régler la manière dont les graphes seront affichés dans la console. Par exemple, le mode %s permet l'affichage en ligne des graphes tandis que le mode %s permet d'interagir avec (zoom/pan) dans une fenêtre séparée.Option relative au rendu des figures dans ce backendSélectionner le type de completion de code a utiliserPar défaut (interpréteur identique à celui dans lequel Spyder est exécuté)Par défaut : 4Par défaut : 6Par défaut :
In [<span class="in-prompt-number">%i</span>]:Par défaut :
Out[<span class="out-prompt-number">%i</span>]:Le répertoire de travail par défaut est :Définition :SupprimerSupprimer disposition de fenêtreSupprimer projetSupprimer...DépendancesDépendances...DictionnaireEntrez directement le débogage lorsque des erreurs apparaissentAffichageAfficher des info-bullesAfficher le message d'accueilSouhaitez-vous réellement supprimer %s ?Souhaitez-vous supprimer le projet %s ?

Notez que les fichiers et répertoires du projet ne seront pas supprimés du disque.Souhaitez-vous vraiment supprimer le chemin sélectionné ?Souhaitez-vous réellement renommer %s et remplacer le ficher existant %s ?Voulez-vous fermer les toutes les autres consoles connectées au même noyau que celle-ci ?Souhaitez-vous fermer cette console ?Souhaitez-vous supprimer les éléments sélectionnés ?Souhaitez-vous supprimer l'élément sélectionné ?Souhaitez-vous rétablir les valeurs par défaut ?Souhaitez-vous redémarrer Spyder ?Ne plus me demander.TerminerDupliquerEOLModifierModifier les filtresModifier les filtres...ModifierModifierModifier le modèle (nouveaux modules)Barre d'outils éditionÉditeurEditeur : complétion de code, aller à la définition, etc.Presse-papiers videProjet videActive la complétion par Tab sur les éléments de liste, les résultats de fonctions, etc. sans les avoir assignés à une variable.
Par exemple vous pourrez avoir la complétion pour des expressions du type li[0].<Tab> ou ins.meth().<Tab>.Activer l'UMRActiver la mise à l'échelle pour les écrans à haute résolutionFichiers EnamlEncodage :Caractères de fin de ligneFins de ligne :Entrée valide la complétion de codeEntrez les valeurs pour différents écrans séparés par des points-virgules ‘;’, les valeurs de virgule flottante sont prises en chargeVariables d'environnementVariables d'environnement...ErreurUne erreur est survenue lors du démarrage du noyau : %s Exclure les références en lettres capitalesExclure les références commençant par une majusculeExclure les références privéesExclure les références dont le type n'est pas supporté par l'espace de travail (en particulier, l'enregistrement ne fonctionnera pas)Exclure les références dont le nom s'écrit en lettres capitalesExclure les références dont le nom commence par un tiret basExclure les références dont le nom commence par une lettre majusculeExclure les types non supportésExclure :Expression des noms de fichier à exclureExécutablesExécuter dans une nouvelle console dédiéeExécuter dans un terminal système externeExécuter dans la console actuelleRépertoire existantDéplier toutDéplier la sélectionOutils externesÉditeur externeChemin d'accès de l'exécutable :Éditeur externe...Éditeur externe :Terminal système externeCommutateur de fichiersRecherche rapide de symboles dans le fichierFichierLe fichier %s existe déjà.
Souhaitez-vous le remplacer ?Explorateur de FichiersExplorateur de fichiersCommutateur de fichiers...Barre d'outils fichiersFichier...FiltreRechercher le &suivantRechercher le &précédentRecherche dans des fichiersRechercher des symboles dans le fichier…RechercherRéparer automatiquement et afficher un message d'avertissementCorriger l'indentationFormat de flottantLe dossier %s existe déjà.Nom du dossier :Dossier...Police d'écriturePolice : Police de caractèresPour ajouter la prise en charge de %s, merci d'installer
l'un des outils suivants :

%sPour des questions de performance, les changements effectués sur les données masquées ne seront pas reflétées sur les données du tableau (et réciproquement).Séquence de clé interdite !FormatLe format (%s) n'est pas valideLe format (%s) n'est pas valideLe format ({}) devrait commencer par ‘%’Format :Fichiers FortranToujoursMode plein écranFonction déclarée ligne %sImages GIFÉditeur graphique :GénéralOptions généralesAller à la position du curseurAller à la définition de l'objetAller à la dernière position d'éditionAller à la ligne...Aller à la ligne :Afficher le message d'avertissement ou d'erreur précédentAller à la position suivante du curseurAfficher le message d'avertissement ou d'erreur suivantAller à la position précédente du curseurAllez à l'étape : GraphiqueGraphiquesSortie graphiqueComplétion avancéeHauteur :AideAide...Pour obtenir de l'aide ici, sélectionner (ou placer le curseur sur) un objet dans l'éditeur ou la console, puis appuyer sur %s.%sL'aide apparaît automatiquement après la saisie d'une parenthèse gauche après un objet si l'option correspondante est activée dans %s.Ici, vous pouvez sélectionner le theme de couleurs utilisé dans l'éditeur et tous les autres plugins Spyder.

Vous pouvez également modifier les couleurs fournies par Spyder ou créer les vôtres en utilisant les options fournies ci-dessous.
Masquer les options avancéesMasquer les barres d'outilsSurlignerSurligner la cellule en cours d'éditionSurligner la ligne en cours d'éditionSurligner les résultatsSurligner les occurrences aprèsHistogrammeHistoriqueTaille de l'historique : HistoriqueFichiers d'historiqueHistorique...AccueilNom d'hôteFichiers IDLIPythonConsole IPythonConsole IPythonDocumentation de IPythonEnvironnement python interactif IPythonNotebooks IPythonThème des icônesSi cette option est activée, presser la touche Tab provoquera toujours l'indentation de la ligne, quelle que soit la position du curseur (lorsque cette option est activée, la complétion de code reste accessible via le raccourci Ctrl+Espace)Si cette option est activée, cliquer sur le nom d'un objet (click gauche + touche Ctrl) ira à la définition de cet objet (si celle-ci est trouvée).Si vous acceptez les changements effectués, cela modifiera les variables d'environnement de l'utilisateur courant directement dans la base de registre Windows. Utilisez cette fonctionnalité avec précautions et à vos risques et périls.

Notez que pour que les changements effectués prennent effet, il sera nécessaire de redémarrer le processus parent de cette application (redémarrez simplement Spyder si vous l'avez exécuté à partir d'un raccourci Windows, sinon redémarrez toute application ayant servie à exécuter Spyder : Python(x,y) Home ou un invite de commandes par exemple)ImportImporter en tant queImporter des donnéesErreur d'importImporter depuis le presse-papiersAssistant d'importationDans ce volet, vous pouvez visualiser et éditer les variables générées lors de l'exécution d'un programme, ou celles entrées directement dans une des consoles Spyder. Comme vous pouvez le voir, l'explorateur de variables affiche les variables générées au cours de la dernière étape de la visite interactive. En faisant un double-clic sur l'une d'elles, une nouvelle fenêtre s'ouvre, où vous pouvez inspecter et modifier leur contenu.IndenterIndenter la sélection ou la ligne en cours d'éditionCaractères d'indentation : IndiceIndice :InformationInitialisation...En ligneBackend intégréEn entrée :InsérerInspecter l'onglet courantModules Python installésInstance :Intégrer la console IPythonRetour arrière ("backspace") intelligentInteragir avec la console Python après l'exécutionVisite interactiveInterfaceConsole interneOptions de la console interneÉditeur interne :Introduction à IPythonVisite d'introductionIntrospectionChemin d'accès de répertoire incorrectChemin d'accès de fichier incorrectVous avez entré une clé non valideIl n'a pas été possible de fermer l'instance précédente de Spyder. Redémarrage interrompu.Impossible de convertir ce notebook. Message d'erreur : Impossible de copier cet tableauxImpossible de copier les valeurs de ce tableauLe processus de génération de l'aide sous la forme de texte enrichi a échoué.
Merci d'activer le mode d'affichage en texte brut.Impossible d'effacer les résultats de ce notebook : Il n'a pas été possible de redémarrer Spyder. Opération annulée.Il n’a pas été possible de redémarrer la console IPython lors du passage à ce projet. L’erreur était la suivante : {0}Impossible d'exécuter ce fichier dans un terminal externeItaliqueImages JPEGFichiers JSONFichiers JavascriptFichiers JsonFichiers JuliaLe noyau est mort, redémarrage en coursRedémarrage du kernelCléClé :Raccourcis clavierMot-clé :LangueDernière position d'éditionLa disposisiton de fenêtres%s sera réinitialisée. Souhaitez-vous continuer ?Configurer l'affichage et l'ordrePréférencesLigne %sNombre de lignes :Retour à la ligne (UNIX)Ligne :Lignes :Lien vers la définition d'un objetLien :ListeChargement de "%s" en cours...Chargement de la console IPython...Chargement de l'éditeur...Chargement de l'explorateur de fichiers...Chargement de l'aide en ligne...Chargement du journal d'historique...Chargement de l'explorateur d'espace de noms...Chargement de l'aide en ligne...Chargement de l'explorateur de structure...Chargement de l'explorateur de projet...Le chargement de ce type de données alors que le déboggage n’est pas pris en charge.RépertoireVerrouillerVerrouiller les ongletsFichiers MATLABBarre d'outils principaleGarder le focus dans l'éditeur après l'exécution d'une cellule ou d'une sélectionGérer les thèmes de coloration syntaxiqueUtiliser les Jupyter Notebooks sur l'éditeurFichiers MarkdownMasqueDonnées masquéesParenthèses correspondantes :Fichiers MatlabDocumentation de MatplotlibAgrandir le volet courantNombre maximum d'entréesNombre maximum de lignesNombre maximum de fichiers récentsNombre maximum de fichiers récents...Occupation mémoire : requiert la bibliothèque `psutil` (>=v0.3) sur les plateformes autres que WindowsMémoire :Méthode déclarée ligne %sChange l'affichage des invites de commande d'entrée et de sortie de la console.ModuleLe module pywin32 n'est pas installé.
Merci de redémarrer la session en cours (et non l'ordinateur) pour que les changements effectués prennent effet.Module ou paquet :Module...DescendreMonterDescendrePlacer en dernierPlacer en premierMonterDéplacer...Fichiers NSISNomFiltres sur les noms de fichiers :NouveauNouveau Projet...Sélectionner un répertoireLes nouveautés de la version 3.0Nouveau fichierNouveau répertoireNouveau moduleNouveau nom :Nouveau paquetNouveau raccourci :Vous découvrez Spyder ? Lisez notreNouveau nom de variable :Nouvelle fenêtreSuivantPosition suivante du curseurAvertissement précédentAucun client IPython n'est actuellement sélectionné pour exécuter %s.

Merci d'ouvrir un nouveau client IPython et de réessayer.Aucune documentation disponibleAucune documentation disponiblePas de correspondanceAucun code source disponible.NormalTexte normal :Aucune donnée ne peut être importée depuis le presse-papiers.Tableaux NumPyTableaux NumPyTableaux NumPy compressésNombre :Documentation de Numpy et ScipyO&uvrir le dernier ferméObjetOccurrence :DésactivéEn mode %s, l'appel automatique n'est pas activé si il n'y a pas d'arguments. En mode %s, tous les objets appelables sont automatiquement appelés (même s'il n'y a pas d'arguments)Documentation en ligneAide en ligneUtilisé uniquement dans le cas du format PNG. Par défaut : 72OuvrirFichiers &récentsOuvrir une console IPython iciOuvrir un Projet...Ouvrir une nouvelle console IPython connecté à un noyau existantOuvrir une console &IPythonOuvrir un invite de commandes iciOuvrir un fichier de connexion IPythonOuvrir un fichierOuvrir le fichier en tant que :Ouvert dernier ferméOuvrir le projetOuvrir un terminal iciFichiers OpenCLAfficher cette variable peut prendre du temps. Souhaitez-vous néanmoins continuer ?OptionsStructureEn sortie :Images PNGGestionnaire de PYTHONPATHNom du paquet :Paquet...VoletsParentMot de passeMot de passe ou passphrase de clé sshCollerFichiers patch et diffChemin vers un fichier de connexion ou identifiant de noyauChemin vers la clé sshUtilise le calcul formel pour réaliser des opérations dans la console (par exemple intégrales, dérivées, calcul vectoriel, etc...) et affiche les résultats de manière élégante.Analyser uniquement lors de l'enregistrementAnalyser lors de l'enregistrement et toutes lesDroits d'accès :Fichiers pickleSimpleTexte brutPolice d'écriture du texte brutMerci d'installer Sphinx pour obtenir la documentation en texte enrichi.Entrez les informations de connexion du noyau auquel vous voulez vous connecter. Pour cela vous pouvez soit sélectionner son fichier de connexion JSON en utilisant le bouton Parcourir, ou écrivez directement son identifiant si c'est un noyau local (Exemple : kernel-3764.json ou juste 3764).Merci d'installer matplotlib ou guiqwt.Merci d'utiliser un raccourci clavier différentVeuillez noter que ces changements ne seront pris en compte que dans les nouvelles consoles Python/IPythonVeuillez noter que ces changements ne seront pris en compte que dans les nouvelles consoles PythonTracerAfficher la console interne en cas d'erreur inattenduePré&férencesPréférencesPréférences > AideAppuyez sur la touche Entrée pour changer de fichier ou Esc pour annuler.

Tapez pour filtrer les noms de fichiers.

Utilisez:numberpour aller à une ligne, par exemple main: 42
Utilisez@symbol_text pour accéder à un symbole, par example @init

Appuyez sur Ctrl + W pour fermer l'onglet actuel.Appuyer sur Entrée pour valider cette saisieAppuyez sur Entrée pour valider ce chemin d'accèsÉcrivez le nouveau raccourci et sélectionnez 'OK' : (Appuyez sur la touche 'Tab' une fois pour changer de focus entre l'entrée de raccourci et les boutons ci-dessous)AperçuPrécédentPosition suivante du curseurAvertissement suivantImprimer le fichier en cours d'édition...Aperçu avant impression...Impression en cours...ProjetsExplorateur de projetsPréférences du projetExplorateur de projetsNom du projetPréférences du projetType de projetDemander à la sortieInvites de commandeFonctionnalités associéesDocumentation de l'API de PyQt4Guide de référence de PyQt4Documentation de l'API de PyQt5Guide de référence de PyQt5Gestionnaire de chemins d'accès PythonDocumentation de PythonFichiers PythonAide Python :Interpréteur PythonPaquet PythonProjet PythonScripts PythonPythonDocumentation de Python2Documentation de Python3Qt DesignerQt LinguistDocumentation de QtExemples QtStyle de fenêtres QtRéférence rapideLa disposition de fenêtre personnalisée #%s n'a pas encore été définie.Quitter&Supprimer un bloc de commentairesText brutExécuter de nouveau la dernière cellule Exécuter de nouveau le &dernier scriptExécuter de nouveau le dernier celluleAnalyse de code en temps réel dans l'éditeurAnalyse de code temps réel dans l'éditeurAnalyse de code en temps réel dans l'éditeurAnalyse de code temps réel dans l'éditeurProjets récentsChamps du tableau :RépéterMise à jour de la liste des modules disponibles notamment à travers PYTHONPATHExpression régulièreErreur d'expression régulièreErreur de suppressionSupprimerSupprimer toutes les variablesEffacer toutes les variables avant l'exécutionSupprimer le bloc de commentaires autour de la ligne en cours d'éditionSupprimerSupprimer des références :Supprimer les espaces en fin de ligneRenommerRenommer l’ongletRenommer...Styliser les équations mathématiquesRemplacer toutRemplacer la sélectionChaîne de caractères de remplacementRemplacer les caractères de tabulation par des espacesRemplacer par :Remplacer/rechercher suivantRapport d'erreur...RéinitialiserRétablir les valeurs par défautRétablir les valeurs par défautRétablir les valeurs par défautRétablir les valeurs par défautRéinitialisation des valeurs par défautAjusterAjuster la hauteur des lignesRésolution :RedémarrerRedémarrer le noyauRedémarrer le noyau ?RedémarrageRestaurerRestaurer le volet courantRestaurer les données au démarrageRestaurer l'organisation initiale de l'arbreRestaurer le volet à sa taille d'origineRevenir à la version du fichier enregistrée sur le disqueTexte enrichiPolice d'écriture du texte enrichiSéparateur de ligne :ExécuterExécuter la &sélection ou la ligne couranteExécutez les fichiers Cython dans la console IPythonExécuter un script Pythonla fenêtre Options d'exécutionExécuter un script PythonExécuter un fichierExécuter de nouveau le dernier fichierExécuter la celluleExécuter la cellule et avancerExécuter du codeConfiguration d'exécutionExécuter la configuration par fichierExécuter la cellule courante [Utiliser #%% pour délimiter les cellules]Exécuter la cellule en cours d'édition et aller à la suivante (voir la documentation de l'Editeur, pour plus de détails sur les cellules)Exécuter la ligne en coursExécuter le fichierExécuter un script :Exécuter la sélectionExécuter la sélection ou le bloc de lignesOptions d'exécutionOptions d'exécution pour %sBarre d'outils exécutionExécuter jusqu'au retour de la fonction ou méthodeL'exécution dans un terminal système externe n'est pas prise en charge sur la plateforme %s.Enregistrer &toutEnregistrerEnregistrer &sous...Enregistrer tous les fichiersEnregistrer tous les fichiers avant l'exécution d'un scriptEnregistrer le tableauSauvegarder copie sous…Enregistrez la copie du fichier actuel sous…Enregistrer le fichier en cours d'édition sous un autre nom...Enregistrer l'historique complet (toutes les entrées et sorties) dans un fichier texteEnregistrer la disposition actuelleEnregistrer les donnéesEnregistrer les données sous...Enregistrer les donnéesEnregitrer un fichierEnregistrer l'historiqueEnregistrer l'historiqueEnregistrer l'historique...Enregistrer les fichiers ouverts en dehors du projetL’enregistrement de données lors du déboggage n’est pas pris en charge.Nom du thème :Thème de coloration :Fuzzy pointsRésolution d’écranDéfiler automatiquement jusqu'à la dernière ligneRechercherRechercher un répertoireRecherchez dans tous les fichiers et répertoires présents sur le chemin actuel de SpyderRecherchez dans tous les fichiers et répertoires présents sur le chemin de projet actuel (si ouvert)Recherche dans le fichier ouvert actuelRechercher dans un autre répertoire du systèmeRechercher dans :Expression recherchéeChaîne de caractères à rechercherRechercher une chaîne de caractères dans plusieurs fichiers à la foisBarre d'outils de rechercheRechercher : Sélectionner toutSélectionner une configuration d'exécution :Sélectionner un répertoireSélectionner un fichierSélectionner un autre répertoireSélectionner une clé sshSélectionner l'interpréteur Python utilisé pour exécuter des scriptsDéfinir la liste des modules non rechargés par l'UMRDéfinissez une mise à l’échelle personnalisée pour les écrans à haute résolutionRépertoire de travail de la consoleChoisir le répertoire du script comme répertoire de travail de la console courante (et de l'explorateur de fichier)Modifier le chemin d'accès de l'éditeur externeModifier le nombre d'entrées maximum de l'historiqueModifier le nombre maximum de lignesDéfinissez la liste des modules exclus comme ceci : numpy, scipyNombre maximum de lignes de texte affichées dans la console avant troncature (saisir -1 désactive cette dernière, ce qui est fortement déconseillé).Sélectionner pour les écrans à haute résolutionRéglez ceci pour les écrans à haute résolution élevés lorsque la mise à l’échelle automatique ne fonctionne pasActiver cette option rend détachables tous les menus de la fenêtre principaleActiver cette option afin que les fichiers ouverts
depuis l'extérieur soit affichés dans une instance unique de Spyder
(redémarrage requis)Ajouter/supprimer un point d'arrêtAjouter/modifier un point d'arrêt conditionnelConfiguration de la fenêtre principale...OptionsCommandes spéciales de la console :Raccourci clavierRaccourci clavier : {0}Sommaire des raccourcisRéinitialisation des raccourcisLes raccourcis qui utilisent `Shift` et une autre touche ne sont pas pris en chargeAfficher le contenu de sys.path (lecture seule)Afficher la charge du CPU toutes lesAfficher les sourcesAfficher les chemins completsAfficher les options avancéesAfficher tous les fichiersAfficher et modifier les variables d'environnement de l'utilisateur courant dans Windows (c'est-à-dire directement dans la base de registre)Afficher et modifier les variables d'environnement (pour la session en cours)Afficher les min/max des tableauxAfficher les espacesAfficher la liste des avertissements/erreurs provenant de l'analyse de codeAfficher la liste des commentaires (TODO/FIXME/XXX/HINT/TIP/@todo/HACK/BUG/OPTIMIZE/!!!/???)Afficher uniquement le répertoire courantAfficher le temps écouléAfficher les variables d’environnementAfficher l'aide pour les objets dans l'éditeur et les consoles dans un volet dédiéBarre de défilement horizontalAfficher icônes et textesAfficher l'imageAfficher dans le FinderAfficher dans l’explorateur de fichiers externeAfficher les numéros de ligneAfficher l'occupation mémoire toutes lesAfficher les modules rechargésAfficher les commentaires spéciauxAfficher la barre d'étatAfficher le contenu de sys.pathAfficher le contenu de sys.path...Afficher la barre d'ongletsAfficher la liste des tâchesAfficher les barres d'outilsAfficher une ligne verticale aprèsAfficher la liste des avertissements/erreursAfficher/masquer l'explorateur de structureZones latérales :SiftTailleTaille : Sauter des lignes :IntelligentSour&ceSourceCode sourceBarre d'outils code sourceSphinx %s n'est pas installé.Séparation horizontaleSéparer en deux horizontalement cette fenêtre d'éditionSéparation verticaleSéparer en deux verticalement cette fenêtre d'éditionRétablir la disposition de fenêtres par défautÉditeur de SpyderConsole interne de Spyder Il s'agit d'une console de débogage utilisée par Spyder pour signaler des erreurs internes ou pour inspecter les entrailles de l'application avec les commandes ci-dessous : spy.app, spy.window, dir(spy) Ne l'utilisez pas pour exécuter votre propre code. Raccourcis clavier SpyderImpossible de rétablir les valeurs par défaut. Redémarrage interrompu.Fichiers SpyderSpyder dépend de nombreux modules Python pour disposer de l'intégralité des fonctionnalités potentiellement fournies par ses plugins. Le tableau suivant montre les versions requises et installées (le cas échéant) de toutes ces dépendances.

Même si Spyder est parfaitement fonctionnel sans tout ces modules, il est néanmoins fortement recommandé d'installer au minimum %s et %s afin de bénéficier des fonctionnalités les plus avancées.

Les nouvelles dépendances ou celles modifiées ne seront détectées correctement qu'après redémarrage de Spyder.Documentation de SpyderErreur de sortie de SpyderSpyder est un environnement de développement interactif basé surSpyder est à jour.Il faut redémarrer Spyder pour changer l'option suivante :Il faut redémarrer Spyder pour changer les options suivantes :Erreur de réinitialisation de SpyderErreur de démarrage de SpyderSupport technique de Spyder...Tutoriel de SpyderMises à jour de SpyderImpossible de récupérer la valeur de cette variable depuis la console.

Message d'erreur :
%sSpyder va redémarrer et réinitialiser les paramètres par défaut :

Souhaitez-vous néanmoins continuer ?Clé sshDémarrer la rechercheDémarrageBarre d'étatPasPas vers l'intérieurPas vers l'extérieurAvancer dans la fonction, méthode ou classe de la ligne en coursArrêterArrêter le débogageArrêter la rechercheInterrompre la commande en coursChaîne de caractères non trouvéeChaîne :Soumettre à GithubPrise en charge des graphes (Matplotlib)Fichiers compatiblesFichiers compatiblesRecherche de symboles…Calcul formelMathématiques symboliques pour la console IPythonSynchroniserSynchronise la liste des chemins d'accès de Spyder avec celle de la variable d'environnement PYTHONPATHSynchroniser...Coloration syntaxiqueColoration syntaxique pour Matlab, Julia et d'autres types de fichierCommandes systèmes :Images TIFFTabToujours indenter avec la touche TabLargeur des tabulations :TabulationsMenus détachablesFichier temporaireTerminalTexteÉditeur de texteFichiers texteLa taille de 'xlabels' ne correspond pas au nombre de colonnes du tableauLa taille de 'ylabels' ne correspond pas au nombre de lignes du tableauLe répertoire de travail actuel est le répertoire de travail pour les consoles IPython et le répertoire actuel pour l’Explorateur de fichiers.Éditeur de texteExplorateur de fichiersHistoriqueConsole IPythonExplorateur de variablesL'identité du serveur %s ne peut pas être confirmée. Êtes-vous sûr de vouloir poursuivre ?L'identité du serveur ne peut pas être confirméeLe dossier actuel contient un projet.

Si vous souhaitez supprimer le projet, allez dans Projets & raquo; Supprimer le projetLe répertoire actuel du projet ou le répertoire d’accueil de l’utilisateur (si aucun projet n’est actif)Le répertoire de travail actuelLe répertoire du fichier en cours d’exécutionLe répertoire quand une nouvelle console est ouverte sera le chemin spécifiéLe répertoire {} n’est pas accessible en écriture et il est nécessaire de créer des consoles IPython. Créez le chemin d’accès accessible en écriture.Voici les options par défaut pour l’exécution des fichiers. Ces options peuvent être remplacées en utilisant l’entrée Configuration par fichier du menu Exécuter .Les conflits suivants ont été détectés :Le répertoire suivant :L'erreur suivante s'est produite lors de l'exécution de Sphinx %s.
Veuillez vérifier si cette version de Sphinx est bien prise en charge par Spyder.

Message d'erreur :
%sLes modules suivants ne sont pas installés sur votre ordinateur : %sLe répertoire de travail suivant n'est pas valide :
%sLe nouveau raccourci est en conflit avec :Le répertoire de travail pour les nouvelles consoles est :Ce répertoire est déjà inclus dans la liste des chemins d'accès de Spyder.
Souhaitez-vous le placer en début de liste ?Cette saisie n'est pas correcteCette erreur est probablement causée par l’installation de Spyder dans un répertoire avec des caractères non ascii (c’est-à-dire des caractères avec des tildes, des apostrophes ou des symboles non latins).

Pour le réparer, réinstallez Spyder dans un endroit différent.Cette fonctionnalité nécessite l'installation de Sphinx 1.1+.Cette fonctionnalité nécessite Rope ou Jedi. Il semble qu'aucun de ces modules ne soit présent.Noyau distantCeci est un script temporaire.C'est l'un des volets où vous pouvez exécuter le code que vous avez écrit sur l'éditeur. Pour ce faire, vous devez appuyer sur la touche F5.

Cette console est livrée avec plusieurs fonctionnalités utiles qui améliorent considérablement votre flux de travail de programmation (comme la coloration syntaxique et les graphiques en ligne). Pour en savoir en savoir plus à ce sujet suivez ce lien. Cliquez sur le bouton ci-dessous pour exécuter un code simple dans cette console. Ce sera utile pour vous montrer d'autres fonctionnalités importantes.Dans ce volet, vous pouvez écrire du code Python avant de l'évaluer. Vous pouvez obtenir des suggestions et des complétions de code automatiques pendant l'écriture, en appuyant sur la touche Tab à la suite d'un texte donné. Spyder affiche des avertissements et des erreurs de syntaxe. Ils peuvent vous aider à détecter les problèmes potentiels avant d'exécuter le code.

Vous pouvez également définir des points d'arrêt de débogage dans la zone de numéro de ligne, en faisant un double clic à côté d'une ligne non vide.Ceci est le répertoire de travail utilisé pour les nouvelles consoles (consoles Python/IPython et fenêtres de commandes), pour l'explorateur de fichiers, pour la recherche dans les fichiers et pour les fichiers créés dans l'éditeurImport automatique de toutes les fonctions de représentation graphique et de calcul numériqueCette option permet de masquer la message d'accueil qui s'affiche à l'ouverture de la console.Cette option permet de masquer le message de confirmation lors de la suppression des variables de Spyder.Activer cette option permet de travailler avec la bibliothèque Sympy.
Merci de consulter la documentation pour savoir comment l'utiliser.Cette option sera prise en compte lors de la prochaine ouverture de console.Cette option active le User Module Deleter (UMR) dans les consoles Python. L'UMR force Python à recharger complètement les modules lors de leur importation, dans le cadre de l'exécution d'un script Python avec la fonction Spyder runfile.

1. UMR peut nécessiter le redémarrage de la console Python dans lequel il va être utilisé (dans le cas contraire, seuls les modules importés après activation de l'UMR seront rechargés complètement lors de l'exécution de scripts).

2. Si des erreurs survenaient lors de la réexécution de programmes utilisant PyQt, veuillez vérifier que les objets Qt sont correctement détruits à la sortie du programme (par exemple, il sera probablement nécessaire d'utiliser l'attribut Qt.WA_DeleteOnClose sur votre objet fenêtre principale grâce à la méthode setAttribute)L'inspecteur d'objet peut automatiquement afficher l'aide sur un objet dès l'ouverture d'une parenthèse. Ci-dessous vous pouvez décider à quel plugin vous voulez le connecter pour activer cette fonctionnalité.Ce volet affiche la documentation des fonctions, classes, méthodes ou modules que vous utilisez actuellement dans l'éditeur ou dans les consoles.

Pour l'utiliser, vous devez appuyer sur Ctrl + I devant un objet. Si cet objet possède une documentation associée, elle sera affichée ici.Ce volet vous permet de naviguer dans les répertoires et les fichiers présents dans votre ordinateur.

Vous pouvez également ouvrir l'un de ces fichiers avec l'application correspondante, en double-cliquant dessus. Une exception à cette règle : les fichiers texte sont toujours ouverts dans l'éditeur Spyder.Ce volet enregistre toutes les commandes introduites dans les consoles IPython.Ceci synchronisera la liste des chemins d'accès de Spyder avec celle de la variable d'environnement PYTHONPATH pour l'utilisateur courant, vous permettant ainsi d'exécuter vos modules Python en dehors de Spyder sans avoir besoin de configurer sys.path.
Souhaitez-vous effacer le contenu de PYTHONPATH avant d'y ajouter la liste des chemins d'accès de Spyder ?BooléenComplexeÀ faireFlottantEntierCaractèresConvertir en minusculeConvertir en majusculeBarres d'outilsTransposerImpossible d'ouvrir le tunnel '%s'TupleTypeUMRL'UMR force Python à recharger les modules importés lors de l'exécution d'un script dans la console interne avec la fonction 'runfile'.Impossible de vérifier les mises à jour.Impossible de se connecter au noyau IPython %sImpossible de se connecter à internet.

Vérifiez que votre accès à internet fonctionne correctement.Impossible de charger la pageImpossible de charger l'information.DécommenterAnnulerErreur inattendue : voir console interneDésindenterDésindenter la sélection ou la ligne en cours d'éditionDéverrouillerParenthèse isolée :Mettre à jour LANGUAGE_CODES (à l'intérieur de config/base.py) si une nouvelle traduction a été ajoutée à SpyderMise à jour de la liste des modulesUtilisationUtiliser un pager pour afficher l'aideOuvrir une seule instance de SpyderUtiliser la disposition suivanteUtiliser la disposition précédenteUtiliser le calcul formelUtiliser l'interpréteur Python suivant :Utiliser le fichier suivant :Utiliser la complétion avancéeUtiliser la gestion de versionLe pager permet d'éviter de remplir la console de texte d'aide. Remarque : utiliser la touche Q pour quitter le pager.User Module Reloader (UMR)ValeurValeur :Nom de variableExplorateur de variablesNom de variable :Gestion de versionsSystème de gestion de versionsLanguettes verticales dans ongletsBarres de titre orientées verticalementViTablesVoir et éditer les Dataframes et les Series dans l'explorateur de variablesVoir et éditer Tableaux de deux et trois dimensions dans l'explorateur de variablesAttentionNous ne pouvons pas prendre en charge ce raccourci sur WindowsFichiers webBienvenue à la visite interactive de SpyderBienvenue dans Spyder !Bienvenue dans la visite interactive de SpyderLors de l'ouverture d'un fichier contenant différents types de caractères de fin de ligne (ce qui peut se traduire par des erreurs de syntaxe dans les consoles Python sous Windows), Spyder peut réparer le fichier automatiquement.WhitespaceMots entiersLargeur :WinPythonPanneau de contrôle WinPythonLa disposition des fenêtres sera réinitialisée selon les réglages par défaut. Souhaitez-vous continuer ?Dispositions de fenêtres personnaliséesParamètres du répertoire de travailEspace de travailRetour à la ligne automatiqueFichiers XMLFichiers YamlVous travaillez avec Python 2, cela signifie que vous ne pouvez pas importer un module qui contient des caractères non ASCII.Option similaire à PYTHONSTARTUP pour un interpréteur standard.Plusieurs lignes de code peuvent être exécutées lors du démarrage de la console. Veuillez séparer deux lignes consécutives par une virgule - par exemple :
import os, import sysVous n'avez pas les permissions nécessaires pour afficher le contenu de ce dossierVous avez sélectionné un interpréteur Python %d pour la console. Or cette version de Spyder est exécutée par Python %d !.

Même si c'est techniquement possible, il est recommandé d'installer et d'exécuter Spyder directement dans la version de l'interpréteur sélectionnée, afin d'éviter l'apparition d'avertissements ou d'erreurs liées à une syntaxe incompatible entre ces deux versions de PythonVous avez sélectionné un interpréteur Python non valide pour la console afin que l’interprète précédent reste. Assurez-vous de sélectionner un interprète valide.Votre environnement Python ou l'installation ne dispose pas des modules ipykernel et cloudpickle installés sur celui-ci. Sans ces modules, Spyder ne peut pas créer une console pour vous.

Vous pouvez les installer en exécutant dans un terminal de commande :

pip install ipykernel cloudpickle

ou

conda install ipykernel cloudpickleAgrandirRéduireRéinitialisation du zoomtableaucaractèrescodecopierdonnéessupprimerpppélémentsfichierFichiers gettextExemples guidataExemples guiqwtpoucesexpression régulière incorrecteligneslistecorrespondancescorrespondances trouvées dansdéplacermsPas de correspondancesurautredes erreurs d'autorisation d'accès ont été rencontréespixelsFichiers reSTlecture seuleespacestableautextele répertoire suivant :cette fenêtreTutorielfichier non enregistrésanstitreutilisateur@hôte:portnom_de_variablespyder-3.2.6/spyder/locale/fr/LC_MESSAGES/spyder.po0000664000175000017500000062671113224121062022437 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # Spyder's french translation file # Copyright (C) 2009-2011 Pierre Raybaut # msgid "" msgstr "" "Project-Id-Version: 2.1\n" "POT-Creation-Date: 2017-12-14 15:40+-05\n" "PO-Revision-Date: 2017-12-17 21:09+0100\n" "Last-Translator: Melaine Euzenat \n" "Language-Team: Python\n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "X-Generator: Poedit 2.0.4\n" #: spyder/app/mainwindow.py:134 msgid "Initializing..." msgstr "Initialisation..." #: spyder/app/mainwindow.py:237 msgid "Python2 documentation" msgstr "Documentation de Python2" #: spyder/app/mainwindow.py:239 msgid "Python3 documentation" msgstr "Documentation de Python3" #: spyder/app/mainwindow.py:241 msgid "Numpy and Scipy documentation" msgstr "Documentation de Numpy et Scipy" #: spyder/app/mainwindow.py:243 msgid "Matplotlib documentation" msgstr "Documentation de Matplotlib" #: spyder/app/mainwindow.py:246 msgid "PyQt4 Reference Guide" msgstr "Guide de référence de PyQt4" #: spyder/app/mainwindow.py:249 msgid "PyQt4 API Reference" msgstr "Documentation de l'API de PyQt4" #: spyder/app/mainwindow.py:252 msgid "PyQt5 Reference Guide" msgstr "Guide de référence de PyQt5" #: spyder/app/mainwindow.py:255 msgid "PyQt5 API Reference" msgstr "Documentation de l'API de PyQt5" #: spyder/app/mainwindow.py:257 msgid "WinPython" msgstr "WinPython" #: spyder/app/mainwindow.py:530 msgid "" "An error occurred while creating a socket needed by Spyder. Please, try to " "run as an Administrator from cmd.exe the following command and then restart " "your computer:

netsh winsock reset
" msgstr "" "Une erreur s’est produite lors de la création d’un websocket requis par " "Spyder. S’il vous plaît, essayez d’exécuter la commande suivante comme " "administrateur dans une console cmd.exe, puis redémarrez votre ordinateur :" "

netsh winsock reset
" #: spyder/app/mainwindow.py:562 msgid "Close current pane" msgstr "Fermer le volet courant" #: spyder/app/mainwindow.py:567 msgid "Lock panes" msgstr "Verrouiller les onglets" #: spyder/app/mainwindow.py:574 msgid "Use next layout" msgstr "Utiliser la disposition suivante" #: spyder/app/mainwindow.py:578 msgid "Use previous layout" msgstr "Utiliser la disposition précédente" #: spyder/app/mainwindow.py:588 spyder/widgets/editor.py:497 msgid "File switcher..." msgstr "Commutateur de fichiers..." #: spyder/app/mainwindow.py:590 msgid "Fast switch between files" msgstr "Commutateur de fichiers" #: spyder/app/mainwindow.py:596 msgid "Symbol finder..." msgstr "Recherche de symboles…" #: spyder/app/mainwindow.py:598 msgid "Fast symbol search in file" msgstr "Recherche rapide de symboles dans le fichier" #: spyder/app/mainwindow.py:617 spyder/widgets/sourcecode/codeeditor.py:2661 msgid "Undo" msgstr "Annuler" #: spyder/app/mainwindow.py:619 spyder/widgets/sourcecode/codeeditor.py:2664 msgid "Redo" msgstr "Répéter" #: spyder/app/mainwindow.py:621 spyder/widgets/shell.py:123 #: spyder/widgets/sourcecode/codeeditor.py:2670 #: spyder/widgets/variableexplorer/arrayeditor.py:467 #: spyder/widgets/variableexplorer/collectionseditor.py:671 #: spyder/widgets/variableexplorer/dataframeeditor.py:586 msgid "Copy" msgstr "Copier" #: spyder/app/mainwindow.py:623 spyder/widgets/shell.py:119 #: spyder/widgets/sourcecode/codeeditor.py:2667 msgid "Cut" msgstr "Couper" #: spyder/app/mainwindow.py:625 spyder/widgets/shell.py:127 #: spyder/widgets/sourcecode/codeeditor.py:2673 #: spyder/widgets/variableexplorer/collectionseditor.py:668 msgid "Paste" msgstr "Coller" #: spyder/app/mainwindow.py:628 spyder/widgets/shell.py:140 #: spyder/widgets/sourcecode/codeeditor.py:2676 msgid "Select All" msgstr "Sélectionner tout" #: spyder/app/mainwindow.py:638 spyder/plugins/editor.py:1423 msgid "&File" msgstr "&Fichier" #: spyder/app/mainwindow.py:639 spyder/plugins/editor.py:1411 msgid "File toolbar" msgstr "Barre d'outils fichiers" #: spyder/app/mainwindow.py:643 spyder/plugins/editor.py:1424 msgid "&Edit" msgstr "&Édition" #: spyder/app/mainwindow.py:644 spyder/plugins/editor.py:1421 msgid "Edit toolbar" msgstr "Barre d'outils édition" #: spyder/app/mainwindow.py:648 spyder/plugins/editor.py:1425 msgid "&Search" msgstr "&Recherche" #: spyder/app/mainwindow.py:649 spyder/plugins/editor.py:1413 msgid "Search toolbar" msgstr "Barre d'outils de recherche" #: spyder/app/mainwindow.py:653 spyder/plugins/editor.py:1426 msgid "Sour&ce" msgstr "Sour&ce" #: spyder/app/mainwindow.py:654 spyder/plugins/editor.py:1415 msgid "Source toolbar" msgstr "Barre d'outils code source" #: spyder/app/mainwindow.py:658 spyder/plugins/editor.py:803 #: spyder/plugins/editor.py:1427 msgid "&Run" msgstr "E&xécution" #: spyder/app/mainwindow.py:659 spyder/plugins/editor.py:1417 msgid "Run toolbar" msgstr "Barre d'outils exécution" #: spyder/app/mainwindow.py:663 spyder/plugins/editor.py:762 msgid "&Debug" msgstr "&Déboguer" #: spyder/app/mainwindow.py:664 spyder/plugins/editor.py:1419 msgid "Debug toolbar" msgstr "Barre d'outils de débogage" #: spyder/app/mainwindow.py:668 msgid "C&onsoles" msgstr "C&onsoles" #: spyder/app/mainwindow.py:671 msgid "&Projects" msgstr "&Projets" #: spyder/app/mainwindow.py:674 spyder/plugins/editor.py:1428 msgid "&Tools" msgstr "Ou&tils" #: spyder/app/mainwindow.py:677 spyder/plugins/editor.py:1429 msgid "&View" msgstr "&Affichage" #: spyder/app/mainwindow.py:680 spyder/plugins/editor.py:1430 msgid "&Help" msgstr "A&ide" #: spyder/app/mainwindow.py:685 msgid "Welcome to Spyder!" msgstr "Bienvenue dans Spyder !" #: spyder/app/mainwindow.py:690 msgid "Pre&ferences" msgstr "Pré&férences" #: spyder/app/mainwindow.py:697 spyder/widgets/pathmanager.py:53 msgid "PYTHONPATH manager" msgstr "Gestionnaire de PYTHONPATH" #: spyder/app/mainwindow.py:700 msgid "Python Path Manager" msgstr "Gestionnaire de chemins d'accès Python" #: spyder/app/mainwindow.py:703 msgid "Update module names list" msgstr "Mise à jour de la liste des modules" #: spyder/app/mainwindow.py:706 msgid "Refresh list of module names available in PYTHONPATH" msgstr "" "Mise à jour de la liste des modules disponibles notamment à travers " "PYTHONPATH" #: spyder/app/mainwindow.py:709 msgid "Reset Spyder to factory defaults" msgstr "Rétablir les valeurs par défaut" #: spyder/app/mainwindow.py:714 msgid "Current user environment variables..." msgstr "Variables d'environnement de l'utilisateur..." #: spyder/app/mainwindow.py:716 msgid "" "Show and edit current user environment variables in Windows registry (i.e. " "for all sessions)" msgstr "" "Afficher et modifier les variables d'environnement de l'utilisateur courant " "dans Windows (c'est-à-dire directement dans la base de registre)" #: spyder/app/mainwindow.py:725 spyder/app/mainwindow.py:1147 msgid "External Tools" msgstr "Outils externes" #: spyder/app/mainwindow.py:728 msgid "WinPython control panel" msgstr "Panneau de contrôle WinPython" #: spyder/app/mainwindow.py:737 msgid "Qt Designer" msgstr "Qt Designer" #: spyder/app/mainwindow.py:742 msgid "Qt Linguist" msgstr "Qt Linguist" #: spyder/app/mainwindow.py:748 msgid "Qt examples" msgstr "Exemples Qt" #: spyder/app/mainwindow.py:768 msgid "guidata examples" msgstr "Exemples guidata" #: spyder/app/mainwindow.py:779 msgid "guiqwt examples" msgstr "Exemples guiqwt" #: spyder/app/mainwindow.py:784 msgid "Sift" msgstr "Sift" #: spyder/app/mainwindow.py:794 msgid "ViTables" msgstr "ViTables" #: spyder/app/mainwindow.py:808 msgid "Fullscreen mode" msgstr "Mode plein écran" #: spyder/app/mainwindow.py:820 msgid "Main toolbar" msgstr "Barre d'outils principale" #: spyder/app/mainwindow.py:829 msgid "" "Spyder Internal Console\n" "\n" "This console is used to report application\n" "internal errors and to inspect Spyder\n" "internals with the following commands:\n" " spy.app, spy.window, dir(spy)\n" "\n" "Please don't use it to run your code\n" "\n" msgstr "" "Console interne de Spyder\n" "\n" "Il s'agit d'une console de débogage\n" "utilisée par Spyder pour signaler des erreurs\n" "internes ou pour inspecter les entrailles de\n" "l'application avec les commandes ci-dessous :\n" " spy.app, spy.window, dir(spy)\n" "\n" "Ne l'utilisez pas pour exécuter votre propre code.\n" "\n" #: spyder/app/mainwindow.py:846 msgid "Loading help..." msgstr "Chargement de l'aide en ligne..." #: spyder/app/mainwindow.py:853 msgid "Loading outline explorer..." msgstr "Chargement de l'explorateur de structure..." #: spyder/app/mainwindow.py:861 msgid "Loading editor..." msgstr "Chargement de l'éditeur..." #: spyder/app/mainwindow.py:867 spyder/plugins/console.py:140 #: spyder/widgets/ipythonconsole/client.py:417 msgid "&Quit" msgstr "&Quitter" #: spyder/app/mainwindow.py:869 spyder/plugins/console.py:142 msgid "Quit" msgstr "Quitter" #: spyder/app/mainwindow.py:873 msgid "&Restart" msgstr "&Redémarrer" #: spyder/app/mainwindow.py:875 msgid "Restart" msgstr "Redémarrer" #: spyder/app/mainwindow.py:889 msgid "Loading file explorer..." msgstr "Chargement de l'explorateur de fichiers..." #: spyder/app/mainwindow.py:896 msgid "Loading history plugin..." msgstr "Chargement du journal d'historique..." #: spyder/app/mainwindow.py:907 msgid "Loading online help..." msgstr "Chargement de l'aide en ligne..." #: spyder/app/mainwindow.py:912 msgid "Loading project explorer..." msgstr "Chargement de l'explorateur de projet..." #: spyder/app/mainwindow.py:925 msgid "Loading namespace browser..." msgstr "Chargement de l'explorateur d'espace de noms..." #: spyder/app/mainwindow.py:931 msgid "Loading IPython console..." msgstr "Chargement de la console IPython..." #: spyder/app/mainwindow.py:936 msgid "Setting up main window..." msgstr "Configuration de la fenêtre principale..." #: spyder/app/mainwindow.py:939 msgid "Dependencies..." msgstr "Dépendances..." #: spyder/app/mainwindow.py:943 msgid "Report issue..." msgstr "Rapport d'erreur..." #: spyder/app/mainwindow.py:947 msgid "Spyder support..." msgstr "Support technique de Spyder..." #: spyder/app/mainwindow.py:950 msgid "Check for updates..." msgstr "Rechercher les mises à jour..." #: spyder/app/mainwindow.py:973 msgid "Spyder documentation" msgstr "Documentation de Spyder" #: spyder/app/mainwindow.py:981 msgid "Spyder tutorial" msgstr "Tutoriel de Spyder" #: spyder/app/mainwindow.py:986 msgid "Shortcuts Summary" msgstr "Sommaire des raccourcis" #: spyder/app/mainwindow.py:992 msgid "Interactive tours" msgstr "Visite interactive" #: spyder/app/mainwindow.py:1018 msgid "Python documentation" msgstr "Documentation de Python" #: spyder/app/mainwindow.py:1024 msgid "IPython documentation" msgstr "Documentation de IPython" #: spyder/app/mainwindow.py:1025 msgid "Intro to IPython" msgstr "Introduction à IPython" #: spyder/app/mainwindow.py:1027 msgid "Quick reference" msgstr "Référence rapide" #: spyder/app/mainwindow.py:1029 msgid "Console help" msgstr "Aide sur la console" #: spyder/app/mainwindow.py:1059 msgid "Installed Python modules" msgstr "Modules Python installés" #: spyder/app/mainwindow.py:1063 msgid "Online documentation" msgstr "Documentation en ligne" #: spyder/app/mainwindow.py:1076 msgid "Qt documentation" msgstr "Documentation de Qt" #: spyder/app/mainwindow.py:1082 msgid "About %s..." msgstr "À propos de %s..." #: spyder/app/mainwindow.py:1113 msgid "Panes" msgstr "Volets" #: spyder/app/mainwindow.py:1115 msgid "Toolbars" msgstr "Barres d'outils" #: spyder/app/mainwindow.py:1116 msgid "Window layouts" msgstr "Dispositions de fenêtres personnalisées" #: spyder/app/mainwindow.py:1125 spyder/app/mainwindow.py:1924 #: spyder/app/mainwindow.py:1925 msgid "Show toolbars" msgstr "Afficher les barres d'outils" #: spyder/app/mainwindow.py:1140 msgid "Attached console window (debugging)" msgstr "Invite de commandes attachée (débogage)" #: spyder/app/mainwindow.py:1317 spyder/plugins/console.py:220 #: spyder/plugins/projects.py:248 spyder/widgets/explorer.py:708 #: spyder/widgets/explorer.py:813 #: spyder/widgets/variableexplorer/arrayeditor.py:587 #: spyder/widgets/variableexplorer/collectionseditor.py:427 #: spyder/widgets/variableexplorer/dataframeeditor.py:752 #: spyder/widgets/variableexplorer/dataframeeditor.py:756 #: spyder/widgets/variableexplorer/namespacebrowser.py:299 msgid "Error" msgstr "Erreur" #: spyder/app/mainwindow.py:1318 msgid "" "You have missing dependencies!

%s

Please " "install them to avoid this message.

Note: Spyder could " "work without some of these dependencies, however to have a smooth experience " "when using Spyder we strongly recommend you to install all the listed " "missing dependencies.

Failing to install these dependencies might " "result in bugs. Please be sure that any found bugs are not the direct result " "of missing dependencies, prior to reporting a new issue." msgstr "" "Il manque certaines dépendances

%s
Veuillez les " "installer pour éviter ce message

Remarque : Spyder " "pourrait fonctionner sans certaines de ces dépendances, mais pour avoir une " "bonne expérience lors de l'utilisation de Spyder nous fortement vous " "recommandons d'installer toutes les dépendances manquantes.

" "L'impossibilité d'installer ces dépendances peut entraîner des bogues. " "Assurez-vous que les bogues trouvés ne résultent pas directement des " "dépendances manquantes avant de signaler un nouveau problème." #: spyder/app/mainwindow.py:1771 msgid "Spyder Default Layout" msgstr "Rétablir la disposition de fenêtres par défaut" #: spyder/app/mainwindow.py:1789 msgid "Save current layout" msgstr "Enregistrer la disposition actuelle" #: spyder/app/mainwindow.py:1793 msgid "Layout preferences" msgstr "Préférences" #: spyder/app/mainwindow.py:1797 msgid "Reset to spyder default" msgstr "Rétablir les valeurs par défaut" #: spyder/app/mainwindow.py:1817 spyder/app/mainwindow.py:1839 #: spyder/app/mainwindow.py:1902 spyder/app/mainwindow.py:2722 #: spyder/plugins/configdialog.py:1346 spyder/plugins/ipythonconsole.py:131 #: spyder/plugins/ipythonconsole.py:927 spyder/plugins/ipythonconsole.py:1365 #: spyder/plugins/maininterpreter.py:149 spyder/plugins/maininterpreter.py:174 #: spyder/plugins/maininterpreter.py:203 spyder/utils/environ.py:95 #: spyder/utils/environ.py:108 #: spyder/widgets/ipythonconsole/namespacebrowser.py:131 #: spyder/widgets/ipythonconsole/namespacebrowser.py:149 #: spyder/widgets/variableexplorer/arrayeditor.py:510 #: spyder/widgets/variableexplorer/collectionseditor.py:416 #: spyder/widgets/variableexplorer/collectionseditor.py:1092 msgid "Warning" msgstr "Attention" #: spyder/app/mainwindow.py:1818 msgid "" "Window layout will be reset to default settings: this affects window " "position, size and dockwidgets.\n" "Do you want to continue?" msgstr "" "La disposition des fenêtres sera réinitialisée selon les réglages par " "défaut.\n" "Souhaitez-vous continuer ?" #: spyder/app/mainwindow.py:1840 msgid "" "Layout %s will be " "overwritten. Do you want to " "continue?" msgstr "" "La disposisiton de fenêtres%s sera réinitialisée. Souhaitez-vous " "continuer ?" #: spyder/app/mainwindow.py:1903 msgid "Quick switch layout #%s has not yet been defined." msgstr "" "La disposition de fenêtre personnalisée #%s n'a pas encore été définie." #: spyder/app/mainwindow.py:1921 spyder/app/mainwindow.py:1922 msgid "Hide toolbars" msgstr "Masquer les barres d'outils" #: spyder/app/mainwindow.py:2237 spyder/app/mainwindow.py:2238 msgid "Maximize current pane" msgstr "Agrandir le volet courant" #: spyder/app/mainwindow.py:2241 msgid "Restore current pane" msgstr "Restaurer le volet courant" #: spyder/app/mainwindow.py:2242 msgid "Restore pane to its original size" msgstr "Restaurer le volet à sa taille d'origine" #: spyder/app/mainwindow.py:2327 msgid "About %s" msgstr "À propos de %s" #: spyder/app/mainwindow.py:2460 spyder/plugins/editor.py:168 #: spyder/plugins/runconfig.py:354 spyder/plugins/runconfig.py:476 #: spyder/utils/programs.py:286 spyder/widgets/explorer.py:335 msgid "Run" msgstr "Exécuter" #: spyder/app/mainwindow.py:2461 msgid "Running an external system terminal is not supported on platform %s." msgstr "" "L'exécution dans un terminal système externe n'est pas prise en charge sur " "la plateforme %s." #: spyder/app/mainwindow.py:2723 msgid "" "Spyder will restart and reset to default settings:

Do you want to " "continue?" msgstr "" "Spyder va redémarrer et réinitialiser les paramètres par défaut :" "

Souhaitez-vous néanmoins continuer ?" #: spyder/app/mainwindow.py:2851 spyder/widgets/helperwidgets.py:254 msgid "Spyder updates" msgstr "Mises à jour de Spyder" #: spyder/app/mainwindow.py:2852 spyder/plugins/configdialog.py:836 msgid "Check for updates on startup" msgstr "Vérifier les mises à jour au démarrage" #: spyder/app/mainwindow.py:2871 msgid "" "
IMPORTANT NOTE: It seems that you are using Spyder with " "Anaconda/Miniconda. Please don't use pip to " "update it as that will probably break your installation.

Instead, " "please wait until new conda packages are available and use conda to perform the update.
" msgstr "" "
IMPORTANT : il semble que vous utilisiez Spyder avec Anaconda/" "Miniconda. Il est fortement conseillé de ne pas recourir à " "pip pour le mettre à jour, puisqu'il est probable que cela " "casse votre installation.

À la place, il est suggéré de simplement " "attendre la disponibilité de nouveaux paquets conda avant d'utiliser " "conda pour effectuer la mise à jour.
" #: spyder/app/mainwindow.py:2881 msgid "" "Spyder %s is available!

Please use your package manager to " "update Spyder or go to our Releases page to download this " "new version.

If you are not sure how to proceed to update Spyder " "please refer to our Installation instructions." msgstr "" "Spyder %s est disponible !

Utiliser le gestionnaire de " "paquets pour mettre à jour Spyder, consultez le site pour " "télécharger le programme directement.

Si vous ne savez pas comment " "procéder pour mettre Spyder à jour, veuillez consulter notre documentation." #: spyder/app/mainwindow.py:2894 msgid "Spyder is up to date." msgstr "Spyder est à jour." #: spyder/app/restart.py:134 msgid "" "It was not possible to close the previous Spyder instance.\n" "Restart aborted." msgstr "" "Il n'a pas été possible de fermer l'instance précédente de Spyder.\n" "Redémarrage interrompu." #: spyder/app/restart.py:136 msgid "" "Spyder could not reset to factory defaults.\n" "Restart aborted." msgstr "" "Impossible de rétablir les valeurs par défaut.\n" "Redémarrage interrompu." #: spyder/app/restart.py:138 msgid "" "It was not possible to restart Spyder.\n" "Operation aborted." msgstr "" "Il n'a pas été possible de redémarrer Spyder.\n" "Opération annulée." #: spyder/app/restart.py:140 msgid "Spyder exit error" msgstr "Erreur de sortie de Spyder" #: spyder/app/restart.py:141 msgid "Spyder reset error" msgstr "Erreur de réinitialisation de Spyder" #: spyder/app/restart.py:142 msgid "Spyder restart error" msgstr "Erreur de démarrage de Spyder" #: spyder/app/restart.py:183 msgid "Closing Spyder" msgstr "Fermeture du programme" #: spyder/app/restart.py:257 msgid "Resetting Spyder to defaults" msgstr "Réinitialisation des valeurs par défaut" #: spyder/app/restart.py:289 msgid "Restarting" msgstr "Redémarrage" #: spyder/app/tour.py:123 msgid "Welcome to the Introduction tour" msgstr "Bienvenue dans la visite interactive de Spyder" #: spyder/app/tour.py:124 msgid "" "Spyder is a powerful Interactive Development Environment (or IDE) for " "the Python programming language.

Here we are going to guide you " "through its most important features.

Please use the arrow keys or " "click on the buttons below to move along the tour." msgstr "" "Spyder est un environnement de développement interactif (ou IDE) pour " "le langage de programmation Python.

Nous allons vous guider à " "travers ses caractéristiques les plus importantes. Utilisez les touches " "fléchées ou cliquez sur les boutons ci-dessous pour parcourir la visite " "interactive." #: spyder/app/tour.py:133 msgid "The Editor" msgstr "Éditeur de texte" #: spyder/app/tour.py:134 msgid "" "This is the pane where you write Python code before evaluating it. You can " "get automatic suggestions and completions while writing, by pressing the " "Tab key next to a given text.

The Editor comes with a line " "number area (highlighted here in red), where Spyder shows warnings and " "syntax errors. They can help you to detect potential problems before running " "the code.

You can also set debug breakpoints in the line number area, " "by doing a double click next to a non-empty line." msgstr "" "Dans ce volet, vous pouvez écrire du code Python avant de l'évaluer. Vous " "pouvez obtenir des suggestions et des complétions de code automatiques " "pendant l'écriture, en appuyant sur la touche Tab à la suite d'un " "texte donné. Spyder affiche des avertissements et des erreurs de syntaxe. " "Ils peuvent vous aider à détecter les problèmes potentiels avant d'exécuter " "le code.

Vous pouvez également définir des points d'arrêt de " "débogage dans la zone de numéro de ligne, en faisant un double clic à côté " "d'une ligne non vide." #: spyder/app/tour.py:149 msgid "The IPython console" msgstr "Console IPython" #: spyder/app/tour.py:150 msgid "" "This is one of panes where you can run or execute the code you wrote on the " "Editor. To do it you need to press the F5 key.

This console " "comes with several useful features that greatly improve your programming " "workflow (like syntax highlighting and inline plots). If you want to know " "more about them, please follow this link.

Please " "click on the button below to run some simple code in this console. This will " "be useful to show you other important features." msgstr "" "C'est l'un des volets où vous pouvez exécuter le code que vous avez écrit " "sur l'éditeur. Pour ce faire, vous devez appuyer sur la touche F5. " "

Cette console est livrée avec plusieurs fonctionnalités utiles qui " "améliorent considérablement votre flux de travail de programmation (comme la " "coloration syntaxique et les graphiques en ligne). Pour en savoir en savoir " "plus à ce sujet suivez ce lien. Cliquez sur le bouton ci-" "dessous pour exécuter un code simple dans cette console. Ce sera utile pour " "vous montrer d'autres fonctionnalités importantes." #: spyder/app/tour.py:166 msgid "The Variable Explorer" msgstr "Explorateur de variables" #: spyder/app/tour.py:167 msgid "" "In this pane you can view and edit the variables generated during the " "execution of a program, or those entered directly in one of Spyder consoles." "

As you can see, the Variable Explorer is showing the variables " "generated during the last step of this tour. By doing a double-click on any " "of them, a new window will be opened, where you can inspect and modify their " "contents." msgstr "" "Dans ce volet, vous pouvez visualiser et éditer les variables générées lors " "de l'exécution d'un programme, ou celles entrées directement dans une des " "consoles Spyder. Comme vous pouvez le voir, l'explorateur de variables " "affiche les variables générées au cours de la dernière étape de la visite " "interactive. En faisant un double-clic sur l'une d'elles, une nouvelle " "fenêtre s'ouvre, où vous pouvez inspecter et modifier leur contenu." #: spyder/app/tour.py:179 spyder/plugins/help.py:479 spyder/plugins/help.py:921 #: spyder/widgets/internalshell.py:270 msgid "Help" msgstr "Aide" #: spyder/app/tour.py:180 msgid "" "This pane displays documentation of the functions, classes, methods or " "modules you are currently using in the Editor or the Consoles.

To use " "it, you need to press Ctrl+I in front of an object. If that object " "has some documentation associated with it, it will be displayed here." msgstr "" "Ce volet affiche la documentation des fonctions, classes, méthodes ou " "modules que vous utilisez actuellement dans l'éditeur ou dans les consoles. " "

Pour l'utiliser, vous devez appuyer sur Ctrl + I devant un " "objet. Si cet objet possède une documentation associée, elle sera affichée " "ici." #: spyder/app/tour.py:190 msgid "The File Explorer" msgstr "Explorateur de fichiers" #: spyder/app/tour.py:191 msgid "" "This pane lets you navigate through the directories and files present in " "your computer.

You can also open any of these files with its " "corresponding application, by doing a double click on it.

There is " "one exception to this rule: plain-text files will always be opened in the " "Spyder Editor." msgstr "" "Ce volet vous permet de naviguer dans les répertoires et les fichiers " "présents dans votre ordinateur.

Vous pouvez également ouvrir l'un " "de ces fichiers avec l'application correspondante, en double-cliquant " "dessus. Une exception à cette règle : les fichiers texte sont toujours " "ouverts dans l'éditeur Spyder." #: spyder/app/tour.py:201 msgid "The History Log" msgstr "Historique" #: spyder/app/tour.py:202 msgid "" "This pane records all commands introduced in the Python and IPython consoles." msgstr "" "Ce volet enregistre toutes les commandes introduites dans les consoles " "IPython." #: spyder/app/tour.py:250 msgid "Spyder is an interactive development environment based on bla" msgstr "" "Spyder est un environnement de développement interactif basé sur" #: spyder/app/tour.py:254 msgid "Welcome to Spyder introduction tour" msgstr "Bienvenue à la visite interactive de Spyder" #: spyder/app/tour.py:255 msgid "Spyder is an interactive development environment based on bla" msgstr "Spyder est un environnement de développement interactif basé sur" #: spyder/app/tour.py:260 msgid "Introduction tour" msgstr "Visite d'introduction" #: spyder/app/tour.py:261 msgid "New features in version 3.0" msgstr "Les nouveautés de la version 3.0" #: spyder/app/tour.py:555 spyder/plugins/ipythonconsole.py:446 msgid "Run code" msgstr "Exécuter du code" #: spyder/app/tour.py:830 msgid "Go to step: " msgstr "Allez à l'étape : " #: spyder/config/base.py:257 msgid "" "Update LANGUAGE_CODES (inside config/base.py) if a new translation has been " "added to Spyder" msgstr "" "Mettre à jour LANGUAGE_CODES (à l'intérieur de config/base.py) si une " "nouvelle traduction a été ajoutée à Spyder" #: spyder/config/utils.py:24 msgid "Python files" msgstr "Fichiers Python" #: spyder/config/utils.py:25 msgid "Cython/Pyrex files" msgstr "Fichiers Cython/Pyrex" #: spyder/config/utils.py:26 msgid "C files" msgstr "Fichiers C" #: spyder/config/utils.py:27 msgid "C++ files" msgstr "Fichiers C++" #: spyder/config/utils.py:28 msgid "OpenCL files" msgstr "Fichiers OpenCL" #: spyder/config/utils.py:29 msgid "Fortran files" msgstr "Fichiers Fortran" #: spyder/config/utils.py:30 msgid "IDL files" msgstr "Fichiers IDL" #: spyder/config/utils.py:31 msgid "MATLAB files" msgstr "Fichiers MATLAB" #: spyder/config/utils.py:32 msgid "Julia files" msgstr "Fichiers Julia" #: spyder/config/utils.py:33 msgid "Yaml files" msgstr "Fichiers Yaml" #: spyder/config/utils.py:34 msgid "Patch and diff files" msgstr "Fichiers patch et diff" #: spyder/config/utils.py:35 msgid "Batch files" msgstr "Fichiers Batch" #: spyder/config/utils.py:36 spyder/utils/iofuncs.py:426 msgid "Text files" msgstr "Fichiers texte" #: spyder/config/utils.py:37 msgid "reStructuredText files" msgstr "Fichiers reST" #: spyder/config/utils.py:38 msgid "gettext files" msgstr "Fichiers gettext" #: spyder/config/utils.py:39 msgid "NSIS files" msgstr "Fichiers NSIS" #: spyder/config/utils.py:40 msgid "Web page files" msgstr "Fichiers web" #: spyder/config/utils.py:41 msgid "XML files" msgstr "Fichiers XML" #: spyder/config/utils.py:42 msgid "Javascript files" msgstr "Fichiers Javascript" #: spyder/config/utils.py:43 msgid "Json files" msgstr "Fichiers Json" #: spyder/config/utils.py:44 msgid "IPython notebooks" msgstr "Notebooks IPython" #: spyder/config/utils.py:45 msgid "Enaml files" msgstr "Fichiers Enaml" #: spyder/config/utils.py:46 msgid "Configuration files" msgstr "Configurations" #: spyder/config/utils.py:48 msgid "Markdown files" msgstr "Fichiers Markdown" #: spyder/config/utils.py:52 spyder/widgets/explorer.py:781 msgid "All files" msgstr "Tous les fichiers" #: spyder/config/utils.py:134 msgid "Supported text files" msgstr "Fichiers compatibles" #: spyder/plugins/__init__.py:508 spyder/plugins/editor.py:105 #: spyder/plugins/editor.py:568 spyder/plugins/editor.py:1819 #: spyder/plugins/help.py:117 spyder/plugins/help.py:380 #: spyder/widgets/editor.py:534 spyder/widgets/sourcecode/codeeditor.py:98 #: spyder/widgets/sourcecode/codeeditor.py:3193 msgid "Editor" msgstr "Éditeur" #: spyder/plugins/configdialog.py:144 msgid "Reset to defaults" msgstr "Rétablir les valeurs par défaut" #: spyder/plugins/configdialog.py:156 msgid "Preferences" msgstr "Préférences" #: spyder/plugins/configdialog.py:508 msgid "Invalid directory path" msgstr "Chemin d'accès de répertoire incorrect" #: spyder/plugins/configdialog.py:511 spyder/plugins/configdialog.py:526 #: spyder/plugins/runconfig.py:220 spyder/plugins/runconfig.py:268 #: spyder/plugins/workingdirectory.py:240 spyder/widgets/explorer.py:695 #: spyder/widgets/findinfiles.py:494 spyder/widgets/pathmanager.py:258 #: spyder/widgets/projects/projectdialog.py:155 msgid "Select directory" msgstr "Sélectionner un répertoire" #: spyder/plugins/configdialog.py:538 msgid "Invalid file path" msgstr "Chemin d'accès de fichier incorrect" #: spyder/plugins/configdialog.py:541 spyder/plugins/configdialog.py:558 msgid "Select file" msgstr "Sélectionner un fichier" #: spyder/plugins/configdialog.py:557 msgid "All files (*)" msgstr "Tous les fichiers (*)" #: spyder/plugins/configdialog.py:630 msgid "Bold" msgstr "Gras" #: spyder/plugins/configdialog.py:633 msgid "Italic" msgstr "Italique" #: spyder/plugins/configdialog.py:687 msgid "Font: " msgstr "Police : " #: spyder/plugins/configdialog.py:693 msgid "Size: " msgstr "Taille : " #: spyder/plugins/configdialog.py:712 msgid "Font style" msgstr "Police d'écriture" #: spyder/plugins/configdialog.py:789 msgid "Spyder needs to restart to change the following setting:" msgstr "Il faut redémarrer Spyder pour changer l'option suivante :" #: spyder/plugins/configdialog.py:792 msgid "Spyder needs to restart to change the following settings:" msgstr "Il faut redémarrer Spyder pour changer les options suivantes :" #: spyder/plugins/configdialog.py:794 msgid "Do you wish to restart now?" msgstr "Souhaitez-vous redémarrer Spyder ?" #: spyder/plugins/configdialog.py:800 msgid "Information" msgstr "Information" #: spyder/plugins/configdialog.py:814 spyder/plugins/configdialog.py:821 #: spyder/widgets/projects/configdialog.py:74 msgid "General" msgstr "Général" #: spyder/plugins/configdialog.py:824 msgid "Language" msgstr "Langue" #: spyder/plugins/configdialog.py:827 msgid "Use a single instance" msgstr "Ouvrir une seule instance de Spyder" #: spyder/plugins/configdialog.py:829 msgid "" "Set this to open external
Python files in an already running instance " "(Requires a restart)" msgstr "" "Activer cette option afin que les fichiers ouverts
depuis l'extérieur " "soit affichés dans une instance unique de Spyder
(redémarrage requis)" #: spyder/plugins/configdialog.py:832 msgid "Prompt when exiting" msgstr "Demander à la sortie" #: spyder/plugins/configdialog.py:833 msgid "Pop up internal console when internal errors appear" msgstr "Afficher la console interne en cas d'erreur inattendue" #: spyder/plugins/configdialog.py:853 spyder/plugins/editor.py:114 #: spyder/plugins/ipythonconsole.py:290 #: spyder/widgets/projects/configdialog.py:81 msgid "Interface" msgstr "Interface" #: spyder/plugins/configdialog.py:861 msgid "Qt windows style" msgstr "Style de fenêtres Qt" #: spyder/plugins/configdialog.py:867 msgid "Icon theme" msgstr "Thème des icônes" #: spyder/plugins/configdialog.py:871 msgid "Vertical title bars in panes" msgstr "Barres de titre orientées verticalement" #: spyder/plugins/configdialog.py:873 msgid "Vertical tabs in panes" msgstr "Languettes verticales dans onglets" #: spyder/plugins/configdialog.py:875 msgid "Animated toolbars and panes" msgstr "Volets et barres d'outils animés" #: spyder/plugins/configdialog.py:877 msgid "Tear off menus" msgstr "Menus détachables" #: spyder/plugins/configdialog.py:878 msgid "Set this to detach any
menu from the main window" msgstr "" "Activer cette option rend détachables tous les menus de la fenêtre principale" #: spyder/plugins/configdialog.py:880 msgid "Custom margin for panes:" msgstr "Marges personnalisées pour les onglets :" #: spyder/plugins/configdialog.py:882 msgid "pixels" msgstr "pixels" #: spyder/plugins/configdialog.py:889 msgid "Cursor blinking:" msgstr "Clignotement du curseur :" #: spyder/plugins/configdialog.py:891 msgid "ms" msgstr "ms" #: spyder/plugins/configdialog.py:930 msgid "Status bar" msgstr "Barre d'état" #: spyder/plugins/configdialog.py:931 msgid "Show status bar" msgstr "Afficher la barre d'état" #: spyder/plugins/configdialog.py:933 msgid "Show memory usage every" msgstr "Afficher l'occupation mémoire toutes les" #: spyder/plugins/configdialog.py:935 spyder/plugins/configdialog.py:944 #: spyder/plugins/editor.py:139 spyder/plugins/editor.py:283 msgid " ms" msgstr " ms" #: spyder/plugins/configdialog.py:942 msgid "Show CPU usage every" msgstr "Afficher la charge du CPU toutes les" #: spyder/plugins/configdialog.py:975 msgid "Screen resolution" msgstr "Résolution d’écran" #: spyder/plugins/configdialog.py:977 msgid "" "Configuration for high DPI screens

Please see {0}<> for more information about these options (in English)." msgstr "" "Configuration pour les écrans PPP/DPI élevés

Consultez
{0}<> pour plus d’informations sur ces options (en anglais)." #: spyder/plugins/configdialog.py:987 msgid "Normal" msgstr "Normal" #: spyder/plugins/configdialog.py:991 msgid "Enable auto high DPI scaling" msgstr "Activer la mise à l'échelle pour les écrans à haute résolution" #: spyder/plugins/configdialog.py:994 msgid "Set this for high DPI displays" msgstr "Sélectionner pour les écrans à haute résolution" #: spyder/plugins/configdialog.py:998 msgid "Set a custom high DPI scaling" msgstr "" "Définissez une mise à l’échelle personnalisée pour les écrans à haute " "résolution" #: spyder/plugins/configdialog.py:1001 msgid "Set this for high DPI displays when auto scaling does not work" msgstr "" "Réglez ceci pour les écrans à haute résolution élevés lorsque la mise à " "l’échelle automatique ne fonctionne pas" #: spyder/plugins/configdialog.py:1007 msgid "" "Enter values for different screens separated by semicolons ';', float values " "are supported" msgstr "" "Entrez les valeurs pour différents écrans séparés par des points-virgules " "‘;’, les valeurs de virgule flottante sont prises en charge" #: spyder/plugins/configdialog.py:1034 msgid "Plain text font" msgstr "Police d'écriture du texte brut" #: spyder/plugins/configdialog.py:1040 msgid "Rich text font" msgstr "Police d'écriture du texte enrichi" #: spyder/plugins/configdialog.py:1043 msgid "Fonts" msgstr "Police de caractères" #: spyder/plugins/configdialog.py:1057 msgid "Appearance" msgstr "Apparence" #: spyder/plugins/configdialog.py:1059 spyder/plugins/ipythonconsole.py:579 msgid "Advanced Settings" msgstr "Options avancées" #: spyder/plugins/configdialog.py:1095 msgid "Syntax coloring" msgstr "Coloration syntaxique" #: spyder/plugins/configdialog.py:1108 msgid "" "Here you can select the color scheme used in the Editor and all other Spyder " "plugins.

You can also edit the color schemes provided by Spyder or " "create your own ones by using the options provided below.
" msgstr "" "Ici, vous pouvez sélectionner le theme de couleurs utilisé dans l'éditeur et " "tous les autres plugins Spyder.

Vous pouvez également modifier les " "couleurs fournies par Spyder ou créer les vôtres en utilisant les options " "fournies ci-dessous.
" #: spyder/plugins/configdialog.py:1113 msgid "Edit selected" msgstr "Modifier" #: spyder/plugins/configdialog.py:1114 msgid "Create new scheme" msgstr "Créer un nouveau thème" #: spyder/plugins/configdialog.py:1115 spyder/widgets/explorer.py:574 #: spyder/widgets/projects/explorer.py:242 spyder/widgets/shell.py:136 msgid "Delete" msgstr "Supprimer" #: spyder/plugins/configdialog.py:1118 msgid "Reset" msgstr "Réinitialiser" #: spyder/plugins/configdialog.py:1125 msgid "Scheme:" msgstr "Thème de coloration :" #: spyder/plugins/configdialog.py:1156 msgid "Manage color schemes" msgstr "Gérer les thèmes de coloration syntaxique" #: spyder/plugins/configdialog.py:1347 msgid "Are you sure you want to delete this scheme?" msgstr "Souhaitez-vous supprimer ce thème ?" #: spyder/plugins/configdialog.py:1464 msgid "Text" msgstr "Texte" #: spyder/plugins/configdialog.py:1466 msgid "Highlight" msgstr "Surligner" #: spyder/plugins/configdialog.py:1468 msgid "Background" msgstr "Fond" #: spyder/plugins/configdialog.py:1472 msgid "Scheme name:" msgstr "Nom du thème :" #: spyder/plugins/configdialog.py:1479 msgid "Color scheme editor" msgstr "Editeur de coloration syntaxique" #: spyder/plugins/console.py:115 msgid "Internal console" msgstr "Console interne" #: spyder/plugins/console.py:145 msgid "&Run..." msgstr "Exécute&r..." #: spyder/plugins/console.py:147 msgid "Run a Python script" msgstr "Exécuter un script Python" #: spyder/plugins/console.py:150 msgid "Environment variables..." msgstr "Variables d'environnement..." #: spyder/plugins/console.py:152 msgid "Show and edit environment variables (for current session)" msgstr "" "Afficher et modifier les variables d'environnement (pour la session en cours)" #: spyder/plugins/console.py:156 msgid "Show sys.path contents..." msgstr "Afficher le contenu de sys.path..." #: spyder/plugins/console.py:158 msgid "Show (read-only) sys.path" msgstr "Afficher le contenu de sys.path (lecture seule)" #: spyder/plugins/console.py:161 msgid "Buffer..." msgstr "Tampon..." #: spyder/plugins/console.py:162 spyder/plugins/history.py:43 msgid "Set maximum line count" msgstr "Modifier le nombre maximum de lignes" #: spyder/plugins/console.py:165 msgid "External editor path..." msgstr "Éditeur externe..." #: spyder/plugins/console.py:166 msgid "Set external editor executable path" msgstr "Modifier le chemin d'accès de l'éditeur externe" #: spyder/plugins/console.py:169 spyder/plugins/editor.py:149 #: spyder/plugins/help.py:152 spyder/plugins/help.py:355 #: spyder/plugins/history.py:46 spyder/plugins/history.py:157 msgid "Wrap lines" msgstr "Retour à la ligne automatique" #: spyder/plugins/console.py:172 spyder/plugins/editor.py:185 #: spyder/plugins/ipythonconsole.py:300 msgid "Display balloon tips" msgstr "Afficher des info-bulles" #: spyder/plugins/console.py:176 spyder/plugins/editor.py:179 msgid "Automatic code completion" msgstr "Complétion de code automatique" #: spyder/plugins/console.py:180 spyder/plugins/editor.py:183 msgid "Enter key selects completion" msgstr "Entrée valide la complétion de code" #: spyder/plugins/console.py:185 msgid "Internal console settings" msgstr "Options de la console interne" #: spyder/plugins/console.py:221 msgid "" "Spyder has encountered a problem.
Sorry for the inconvenience." "

You can automatically submit this error to our Github issues tracker." "

Note: You need a Github account for that." msgstr "" "Spyder a rencontré un problème.
Désolé pour les inconvénients. " "

Vous pouvez envoyer automatiquement cette erreur à notre agent de " "suivi des problèmes sur Github.

Remarque : Vous avez besoin " "d’un compte Github pour cela." #: spyder/plugins/console.py:231 msgid "Submit to Github" msgstr "Soumettre à Github" #: spyder/plugins/console.py:283 msgid "Run Python script" msgstr "Exécuter un script Python" #: spyder/plugins/console.py:284 spyder/widgets/explorer.py:796 msgid "Python scripts" msgstr "Scripts Python" #: spyder/plugins/console.py:329 msgid "Buffer" msgstr "Tampon" #: spyder/plugins/console.py:330 msgid "Maximum line count" msgstr "Nombre maximum de lignes" #: spyder/plugins/console.py:340 msgid "External editor" msgstr "Éditeur externe" #: spyder/plugins/console.py:341 msgid "External editor executable path:" msgstr "Chemin d'accès de l'exécutable :" #: spyder/plugins/editor.py:59 msgid "Manipulate Jupyter notebooks on the Editor" msgstr "Utiliser les Jupyter Notebooks sur l'éditeur" #: spyder/plugins/editor.py:111 msgid "Edit template for new modules" msgstr "Modifier le modèle (nouveaux modules)" #: spyder/plugins/editor.py:116 msgid "Show tab bar" msgstr "Afficher la barre d'onglets" #: spyder/plugins/editor.py:122 spyder/plugins/editor.py:199 #: spyder/plugins/help.py:151 spyder/plugins/history.py:45 #: spyder/plugins/ipythonconsole.py:332 msgid "Source code" msgstr "Code source" #: spyder/plugins/editor.py:123 msgid "Show line numbers" msgstr "Afficher les numéros de ligne" #: spyder/plugins/editor.py:124 spyder/plugins/editor.py:985 msgid "Show blank spaces" msgstr "Afficher les espaces" #: spyder/plugins/editor.py:125 msgid "Show vertical line after" msgstr "Afficher une ligne verticale après" #: spyder/plugins/editor.py:126 msgid "characters" msgstr "caractères" #: spyder/plugins/editor.py:133 msgid "Highlight current line" msgstr "Surligner la ligne en cours d'édition" #: spyder/plugins/editor.py:135 msgid "Highlight current cell" msgstr "Surligner la cellule en cours d'édition" #: spyder/plugins/editor.py:137 msgid "Highlight occurrences after" msgstr "Surligner les occurrences après" #: spyder/plugins/editor.py:169 msgid "Save all files before running script" msgstr "Enregistrer tous les fichiers avant l'exécution d'un script" #: spyder/plugins/editor.py:172 msgid "Run selection" msgstr "Exécuter la sélection" #: spyder/plugins/editor.py:173 msgid "Maintain focus in the Editor after running cells or selections" msgstr "" "Garder le focus dans l'éditeur après l'exécution d'une cellule ou d'une " "sélection" #: spyder/plugins/editor.py:176 msgid "Introspection" msgstr "Introspection" #: spyder/plugins/editor.py:181 msgid "Case sensitive code completion" msgstr "Complétion de code sensible à la casse" #: spyder/plugins/editor.py:186 msgid "Link to object definition" msgstr "Lien vers la définition d'un objet" #: spyder/plugins/editor.py:188 msgid "" "If this option is enabled, clicking on an object\n" "name (left-click + Ctrl key) will go this object\n" "definition (if resolved)." msgstr "" "Si cette option est activée, cliquer sur le nom\n" "d'un objet (click gauche + touche Ctrl) ira à la\n" "définition de cet objet (si celle-ci est trouvée)." #: spyder/plugins/editor.py:192 msgid "" "Warning:
The Python module rope is not installed on this " "computer: calltips, code completion and go-to-definition features won't be " "available." msgstr "" "Avertissement :
Le module Python rope n'est pas installé " "sur cet ordinateur : les fonctionnalités telles que la complétion de code ou " "le lien vers la définition d'un objet ne sont donc pas accessibles." #: spyder/plugins/editor.py:200 msgid "Automatic insertion of parentheses, braces and brackets" msgstr "Insertion automatique des parenthèses, crochets et accolades" #: spyder/plugins/editor.py:203 msgid "Automatic insertion of closing quotes" msgstr "Insertion automatique de guillemets de clôture" #: spyder/plugins/editor.py:205 msgid "Automatic insertion of colons after 'for', 'if', 'def', etc" msgstr "Insertion automatique de ':' après 'for', 'if', 'def', etc." #: spyder/plugins/editor.py:208 msgid "Automatic indentation after 'else', 'elif', etc." msgstr "Indentation automatique après 'else', 'elif', etc." #: spyder/plugins/editor.py:210 msgid "Indentation characters: " msgstr "Caractères d'indentation : " #: spyder/plugins/editor.py:211 msgid "2 spaces" msgstr "2 espaces" #: spyder/plugins/editor.py:212 msgid "3 spaces" msgstr "3 espaces" #: spyder/plugins/editor.py:213 msgid "4 spaces" msgstr "4 espaces" #: spyder/plugins/editor.py:214 msgid "5 spaces" msgstr "5 espaces" #: spyder/plugins/editor.py:215 msgid "6 spaces" msgstr "6 espaces" #: spyder/plugins/editor.py:216 msgid "7 spaces" msgstr "7 espaces" #: spyder/plugins/editor.py:217 msgid "8 spaces" msgstr "8 espaces" #: spyder/plugins/editor.py:218 msgid "Tabulations" msgstr "Tabulations" #: spyder/plugins/editor.py:219 msgid "Tab stop width:" msgstr "Largeur des tabulations :" #: spyder/plugins/editor.py:219 msgid "spaces" msgstr "espaces" #: spyder/plugins/editor.py:231 msgid "Tab always indent" msgstr "Toujours indenter avec la touche Tab" #: spyder/plugins/editor.py:233 msgid "" "If enabled, pressing Tab will always indent,\n" "even when the cursor is not at the beginning\n" "of a line (when this option is enabled, code\n" "completion may be triggered using the alternate\n" "shortcut: Ctrl+Space)" msgstr "" "Si cette option est activée, presser la touche Tab\n" "provoquera toujours l'indentation de la ligne,\n" "quelle que soit la position du curseur (lorsque cette\n" "option est activée, la complétion de code reste \n" "accessible via le raccourci Ctrl+Espace)" #: spyder/plugins/editor.py:238 msgid "Intelligent backspace" msgstr "Retour arrière (\"backspace\") intelligent" #: spyder/plugins/editor.py:240 msgid "Automatically remove trailing spaces when saving files" msgstr "" "Supprimer automatiquement les espaces en fin de ligne lors de " "l'enregistrement" #: spyder/plugins/editor.py:244 msgid "Analysis" msgstr "Analyse" #: spyder/plugins/editor.py:246 msgid "(Refer to the {} page)" msgstr "(référer à la page {})" #: spyder/plugins/editor.py:251 msgid "Real-time code analysis" msgstr "Analyse de code en temps réel dans l'éditeur" #: spyder/plugins/editor.py:253 msgid "" "

If enabled, Python source code will be analyzed using pyflakes, lines " "containing errors or warnings will be highlighted.

Note: add " "analysis:ignore in a comment to ignore code analysis warnings.

" msgstr "" "

Si cette option est activée, le code source Python sera analysé avec des " "outils l'outil d'introspection de code pyflakes, et les lignes contenant des " "erreurs seront indiquées.

Note : rajouter analysis:ignore dans un commentaire pour ignorer les avertissements d'analyse de code.

" #: spyder/plugins/editor.py:261 msgid "Code analysis requires pyflakes %s+" msgstr "L'analyse de code requiert pyflakes %s+" #: spyder/plugins/editor.py:263 msgid "Real-time code style analysis" msgstr "Analyse de code en temps réel dans l'éditeur" #: spyder/plugins/editor.py:265 msgid "" "

If enabled, Python source code will be analyzed using pycodestyle, lines " "that are not following PEP8 style guide will be highlighted.

Note: add analysis:ignore in a comment to ignore style analysis " "warnings.

" msgstr "" "

Si cette option est activée, le style du code source Python sera analysé " "avec l'outil d'introspection de code PEP8 et les lignes ne suivant pas les " "recommandations officielles seront indiquées.

Note : rajouter " "analysis:ignore dans un commentaire pour ignorer les avertissements " "d'analyse de code.

" #: spyder/plugins/editor.py:272 msgid "" "Code annotations (TODO, FIXME, XXX, HINT, TIP, @todo, HACK, BUG, " "OPTIMIZE, !!!, ???)" msgstr "" "Tâches (TODO, FIXME, XXX, HINT, TIP, @todo, HACK, BUG, OPTIMIZE, !!!, ???)" #: spyder/plugins/editor.py:276 msgid "Perform analysis when saving file and every" msgstr "Analyser lors de l'enregistrement et toutes les" #: spyder/plugins/editor.py:280 msgid "Perform analysis only when saving file" msgstr "Analyser uniquement lors de l'enregistrement" #: spyder/plugins/editor.py:339 msgid "End-of-line characters" msgstr "Caractères de fin de ligne" #: spyder/plugins/editor.py:340 msgid "" "When opening a text file containing mixed end-of-line characters (this may " "raise syntax errors in the consoles on Windows platforms), Spyder may fix " "the file automatically." msgstr "" "Lors de l'ouverture d'un fichier contenant différents types de caractères de " "fin de ligne (ce qui peut se traduire par des erreurs de syntaxe dans les " "consoles Python sous Windows), Spyder peut réparer le fichier " "automatiquement." #: spyder/plugins/editor.py:346 msgid "Fix automatically and show warning message box" msgstr "Réparer automatiquement et afficher un message d'avertissement" #: spyder/plugins/editor.py:357 spyder/plugins/ipythonconsole.py:573 #: spyder/plugins/variableexplorer.py:35 msgid "Display" msgstr "Affichage" #: spyder/plugins/editor.py:359 msgid "Code Introspection/Analysis" msgstr "Introspection et analyse de code" #: spyder/plugins/editor.py:362 msgid "Advanced settings" msgstr "Options avancées" #: spyder/plugins/editor.py:644 msgid "&New file..." msgstr "&Nouveau fichier..." #: spyder/plugins/editor.py:645 spyder/widgets/explorer.py:773 #: spyder/widgets/explorer.py:780 msgid "New file" msgstr "Nouveau fichier" #: spyder/plugins/editor.py:654 msgid "O&pen last closed" msgstr "O&uvrir le dernier fermé" #: spyder/plugins/editor.py:655 msgid "Open last closed" msgstr "Ouvert dernier fermé" #: spyder/plugins/editor.py:661 msgid "&Open..." msgstr "&Ouvrir..." #: spyder/plugins/editor.py:662 spyder/plugins/editor.py:1870 #: spyder/plugins/editor.py:1876 msgid "Open file" msgstr "Ouvrir un fichier" #: spyder/plugins/editor.py:668 msgid "&Revert" msgstr "&Réinitialiser" #: spyder/plugins/editor.py:669 msgid "Revert file from disk" msgstr "Revenir à la version du fichier enregistrée sur le disque" #: spyder/plugins/editor.py:672 msgid "&Save" msgstr "&Enregistrer" #: spyder/plugins/editor.py:673 spyder/widgets/editor.py:1681 msgid "Save file" msgstr "Enregitrer un fichier" #: spyder/plugins/editor.py:679 msgid "Sav&e all" msgstr "Enregistrer &tout" #: spyder/plugins/editor.py:680 msgid "Save all files" msgstr "Enregistrer tous les fichiers" #: spyder/plugins/editor.py:686 msgid "Save &as..." msgstr "Enregistrer &sous..." #: spyder/plugins/editor.py:687 msgid "Save current file as..." msgstr "Enregistrer le fichier en cours d'édition sous un autre nom..." #: spyder/plugins/editor.py:692 msgid "Save copy as..." msgstr "Sauvegarder copie sous…" #: spyder/plugins/editor.py:693 msgid "Save copy of current file as..." msgstr "Enregistrez la copie du fichier actuel sous…" #: spyder/plugins/editor.py:696 spyder/plugins/editor.py:697 msgid "Print preview..." msgstr "Aperçu avant impression..." #: spyder/plugins/editor.py:698 msgid "&Print..." msgstr "Im&primer..." #: spyder/plugins/editor.py:699 msgid "Print current file..." msgstr "Imprimer le fichier en cours d'édition..." #: spyder/plugins/editor.py:702 msgid "&Close" msgstr "&Fermer" #: spyder/plugins/editor.py:703 msgid "Close current file" msgstr "Fermer le fichier en cours d'édition" #: spyder/plugins/editor.py:706 msgid "C&lose all" msgstr "Fermer t&out" #: spyder/plugins/editor.py:707 msgid "Close all opened files" msgstr "Fermer tous les fichiers ouverts" #: spyder/plugins/editor.py:714 msgid "&Find text" msgstr "Rec&hercher" #: spyder/plugins/editor.py:720 msgid "Find &next" msgstr "Rechercher le &suivant" #: spyder/plugins/editor.py:726 msgid "Find &previous" msgstr "Rechercher le &précédent" #: spyder/plugins/editor.py:732 msgid "&Replace text" msgstr "&Remplacer" #: spyder/plugins/editor.py:741 msgid "Set/Clear breakpoint" msgstr "Ajouter/supprimer un point d'arrêt" #: spyder/plugins/editor.py:748 msgid "Set/Edit conditional breakpoint" msgstr "Ajouter/modifier un point d'arrêt conditionnel" #: spyder/plugins/editor.py:755 msgid "Clear breakpoints in all files" msgstr "Supprimer les points d'arrêt dans tous les fichiers" #: spyder/plugins/editor.py:757 msgid "Debug with winpdb" msgstr "Déboguer avec winpdb" #: spyder/plugins/editor.py:764 msgid "Debug file" msgstr "Déboguer le script" #: spyder/plugins/editor.py:769 msgid "Step" msgstr "Pas" #: spyder/plugins/editor.py:770 msgid "Run current line" msgstr "Exécuter la ligne en cours" #: spyder/plugins/editor.py:775 msgid "Continue" msgstr "Continuer" #: spyder/plugins/editor.py:777 msgid "Continue execution until next breakpoint" msgstr "Continuer l'exécution jusqu'au prochain point d'arrêt" #: spyder/plugins/editor.py:782 msgid "Step Into" msgstr "Pas vers l'intérieur" #: spyder/plugins/editor.py:784 msgid "Step into function or method of current line" msgstr "" "Avancer dans la fonction, méthode \n" "ou classe de la ligne en cours" #: spyder/plugins/editor.py:789 msgid "Step Return" msgstr "Pas vers l'extérieur" #: spyder/plugins/editor.py:791 msgid "Run until current function or method returns" msgstr "Exécuter jusqu'au retour de la fonction ou méthode" #: spyder/plugins/editor.py:796 spyder/widgets/findinfiles.py:281 #: spyder/widgets/ipythonconsole/client.py:357 msgid "Stop" msgstr "Arrêter" #: spyder/plugins/editor.py:797 msgid "Stop debugging" msgstr "Arrêter le débogage" #: spyder/plugins/editor.py:804 msgid "Run file" msgstr "Exécuter le fichier" #: spyder/plugins/editor.py:809 msgid "&Configuration per file..." msgstr "&Configuration par fichier…" #: spyder/plugins/editor.py:811 msgid "Run settings" msgstr "Options d'exécution" #: spyder/plugins/editor.py:817 msgid "Re-run &last script" msgstr "Exécuter de nouveau le &dernier script" #: spyder/plugins/editor.py:819 msgid "Run again last file" msgstr "Exécuter de nouveau le dernier fichier" #: spyder/plugins/editor.py:825 spyder/widgets/sourcecode/codeeditor.py:2708 msgid "Run &selection or current line" msgstr "Exécuter la &sélection ou la ligne courante" #: spyder/plugins/editor.py:828 msgid "Run selection or current line" msgstr "Exécuter la sélection ou le bloc de lignes" #: spyder/plugins/editor.py:836 spyder/widgets/sourcecode/codeeditor.py:2696 msgid "Run cell" msgstr "Exécuter la cellule" #: spyder/plugins/editor.py:839 msgid "" "Run current cell (Ctrl+Enter)\n" "[Use #%% to create cells]" msgstr "" "Exécuter la cellule courante \n" "[Utiliser #%% pour délimiter les cellules]" #: spyder/plugins/editor.py:845 spyder/widgets/sourcecode/codeeditor.py:2700 msgid "Run cell and advance" msgstr "Exécuter la cellule et avancer" #: spyder/plugins/editor.py:848 msgid "Run current cell and go to the next one (Shift+Enter)" msgstr "" "Exécuter la cellule en cours d'édition et aller à la suivante\n" "(voir la documentation de l'Editeur, pour plus de détails sur les cellules)" #: spyder/plugins/editor.py:854 spyder/widgets/sourcecode/codeeditor.py:2704 msgid "Re-run last cell" msgstr "Exécuter de nouveau le dernier cellule" #: spyder/plugins/editor.py:855 msgid "Re run last cell " msgstr "Exécuter de nouveau la dernière cellule " #: spyder/plugins/editor.py:865 msgid "Show todo list" msgstr "Afficher la liste des tâches" #: spyder/plugins/editor.py:866 msgid "" "Show comments list (TODO/FIXME/XXX/HINT/TIP/@todo/HACK/BUG/OPTIMIZE/!!!/???)" msgstr "" "Afficher la liste des commentaires (TODO/FIXME/XXX/HINT/TIP/@todo/HACK/BUG/" "OPTIMIZE/!!!/???)" #: spyder/plugins/editor.py:874 msgid "Show warning/error list" msgstr "Afficher la liste des avertissements/erreurs" #: spyder/plugins/editor.py:875 msgid "Show code analysis warnings/errors" msgstr "" "Afficher la liste des avertissements/erreurs provenant de l'analyse de code" #: spyder/plugins/editor.py:881 msgid "Previous warning/error" msgstr "Avertissement suivant" #: spyder/plugins/editor.py:882 msgid "Go to previous code analysis warning/error" msgstr "Afficher le message d'avertissement ou d'erreur suivant" #: spyder/plugins/editor.py:885 msgid "Next warning/error" msgstr "Avertissement précédent" #: spyder/plugins/editor.py:886 msgid "Go to next code analysis warning/error" msgstr "Afficher le message d'avertissement ou d'erreur précédent" #: spyder/plugins/editor.py:890 msgid "Last edit location" msgstr "Dernière position d'édition" #: spyder/plugins/editor.py:891 msgid "Go to last edit location" msgstr "Aller à la dernière position d'édition" #: spyder/plugins/editor.py:899 msgid "Previous cursor position" msgstr "Position suivante du curseur" #: spyder/plugins/editor.py:900 msgid "Go to previous cursor position" msgstr "Aller à la position précédente du curseur" #: spyder/plugins/editor.py:908 msgid "Next cursor position" msgstr "Position suivante du curseur" #: spyder/plugins/editor.py:909 msgid "Go to next cursor position" msgstr "Aller à la position suivante du curseur" #: spyder/plugins/editor.py:919 spyder/widgets/sourcecode/codeeditor.py:2680 msgid "Comment" msgstr "Commenter" #: spyder/plugins/editor.py:919 spyder/widgets/sourcecode/codeeditor.py:2680 msgid "Uncomment" msgstr "Décommenter" #: spyder/plugins/editor.py:920 msgid "Comment current line or selection" msgstr "Commenter la sélection ou la ligne en cours d'édition" #: spyder/plugins/editor.py:924 msgid "Add &block comment" msgstr "Ajouter un &bloc de commentaires" #: spyder/plugins/editor.py:925 msgid "Add block comment around current line or selection" msgstr "" "Ajouter un bloc de commentaires autour de la sélection ou de la ligne en " "cours d'édition" #: spyder/plugins/editor.py:931 msgid "R&emove block comment" msgstr "&Supprimer un bloc de commentaires" #: spyder/plugins/editor.py:932 msgid "Remove comment block around current line or selection" msgstr "" "Supprimer le bloc de commentaires autour de la ligne en cours d'édition" #: spyder/plugins/editor.py:943 msgid "Indent" msgstr "Indenter" #: spyder/plugins/editor.py:944 msgid "Indent current line or selection" msgstr "Indenter la sélection ou la ligne en cours d'édition" #: spyder/plugins/editor.py:947 msgid "Unindent" msgstr "Désindenter" #: spyder/plugins/editor.py:948 msgid "Unindent current line or selection" msgstr "Désindenter la sélection ou la ligne en cours d'édition" #: spyder/plugins/editor.py:952 msgid "Toggle Uppercase" msgstr "Convertir en majuscule" #: spyder/plugins/editor.py:953 msgid "Change to uppercase current line or selection" msgstr "Convertir en majuscule la sélection ou le mot en cours d'édition" #: spyder/plugins/editor.py:959 msgid "Toggle Lowercase" msgstr "Convertir en minuscule" #: spyder/plugins/editor.py:960 msgid "Change to lowercase current line or selection" msgstr "Convertir en minuscule la sélection ou le mot en cours d'édition" #: spyder/plugins/editor.py:967 msgid "Carriage return and line feed (Windows)" msgstr "Retour chariot et retour à la ligne (Windows)" #: spyder/plugins/editor.py:970 msgid "Line feed (UNIX)" msgstr "Retour à la ligne (UNIX)" #: spyder/plugins/editor.py:973 msgid "Carriage return (Mac)" msgstr "Retour chariot (Mac)" #: spyder/plugins/editor.py:979 msgid "Convert end-of-line characters" msgstr "Convertir les caractères de fin de ligne" #: spyder/plugins/editor.py:983 msgid "Remove trailing spaces" msgstr "Supprimer les espaces en fin de ligne" #: spyder/plugins/editor.py:987 msgid "Fix indentation" msgstr "Corriger l'indentation" #: spyder/plugins/editor.py:988 msgid "Replace tab characters by space characters" msgstr "Remplacer les caractères de tabulation par des espaces" #: spyder/plugins/editor.py:991 msgid "Go to line..." msgstr "Aller à la ligne..." #: spyder/plugins/editor.py:999 msgid "Set console working directory" msgstr "Répertoire de travail de la console" #: spyder/plugins/editor.py:1001 msgid "" "Set current console (and file explorer) working directory to current script " "directory" msgstr "" "Choisir le répertoire du script comme répertoire de travail de la console " "courante (et de l'explorateur de fichier)" #: spyder/plugins/editor.py:1006 msgid "Maximum number of recent files..." msgstr "Nombre maximum de fichiers récents..." #: spyder/plugins/editor.py:1009 msgid "Clear recent files list" msgstr "Effacer la liste des fichiers récents" #: spyder/plugins/editor.py:1009 spyder/plugins/projects.py:102 msgid "Clear this list" msgstr "Effacer cette liste" #: spyder/plugins/editor.py:1013 msgid "Open &recent" msgstr "Fichiers &récents" #: spyder/plugins/editor.py:1678 msgid "Spyder Editor" msgstr "Éditeur de Spyder" #: spyder/plugins/editor.py:1679 msgid "This is a temporary script file." msgstr "Ceci est un script temporaire." #: spyder/plugins/editor.py:1748 msgid "untitled" msgstr "sanstitre" #: spyder/plugins/editor.py:1820 msgid "Maximum number of recent files" msgstr "Nombre maximum de fichiers récents" #: spyder/plugins/editor.py:1966 msgid "Printing..." msgstr "Impression en cours..." #: spyder/plugins/explorer.py:54 msgid "File explorer" msgstr "Explorateur de fichiers" #: spyder/plugins/findinfiles.py:119 spyder/widgets/findinfiles.py:829 msgid "Find in files" msgstr "Recherche dans des fichiers" #: spyder/plugins/findinfiles.py:143 msgid "&Find in files" msgstr "Rechercher dans des &fichiers" #: spyder/plugins/findinfiles.py:146 msgid "Search text in multiple files" msgstr "Rechercher une chaîne de caractères dans plusieurs fichiers à la fois" #: spyder/plugins/help.py:43 msgid "Show help for objects in the Editor and Consoles in a dedicated pane" msgstr "" "Afficher l'aide pour les objets dans l'éditeur et les consoles dans un volet " "dédié" #: spyder/plugins/help.py:109 msgid "Automatic connections" msgstr "Connexions automatiques" #: spyder/plugins/help.py:110 msgid "" "This pane can automatically show an object's help information after a left " "parenthesis is written next to it. Below you can decide to which plugin you " "want to connect it to turn on this feature." msgstr "" "L'inspecteur d'objet peut automatiquement afficher l'aide sur un objet dès " "l'ouverture d'une parenthèse. Ci-dessous vous pouvez décider à quel plugin " "vous voulez le connecter pour activer cette fonctionnalité." #: spyder/plugins/help.py:122 msgid "" "This feature requires the Rope or Jedi libraries.\n" "It seems you don't have either installed." msgstr "" "Cette fonctionnalité nécessite Rope ou Jedi.\n" "Il semble qu'aucun de ces modules ne soit présent." #: spyder/plugins/help.py:125 msgid "IPython Console" msgstr "Console IPython" #: spyder/plugins/help.py:135 msgid "Additional features" msgstr "Options supplémentaires" #: spyder/plugins/help.py:136 msgid "Render mathematical equations" msgstr "Styliser les équations mathématiques" #: spyder/plugins/help.py:142 msgid "This feature requires Sphinx 1.1 or superior." msgstr "Cette fonctionnalité nécessite l'installation de Sphinx 1.1+." #: spyder/plugins/help.py:143 msgid "Sphinx %s is currently installed." msgstr "Sphinx %s n'est pas installé." #: spyder/plugins/help.py:304 msgid "No further documentation available" msgstr "Aucune documentation disponible" #: spyder/plugins/help.py:342 msgid "No documentation available" msgstr "Aucune documentation disponible" #: spyder/plugins/help.py:373 msgid "Source" msgstr "Source" #: spyder/plugins/help.py:380 spyder/plugins/runconfig.py:170 #: spyder/plugins/runconfig.py:486 spyder/widgets/ipythonconsole/client.py:291 msgid "Console" msgstr "Console" #: spyder/plugins/help.py:388 msgid "Object" msgstr "Objet" #: spyder/plugins/help.py:402 msgid "Plain Text" msgstr "Texte brut" #: spyder/plugins/help.py:406 msgid "Show Source" msgstr "Afficher les sources" #: spyder/plugins/help.py:410 msgid "Rich Text" msgstr "Texte enrichi" #: spyder/plugins/help.py:420 msgid "Automatic import" msgstr "Import automatique" #: spyder/plugins/help.py:432 spyder/plugins/history.py:106 #: spyder/widgets/editor.py:720 spyder/widgets/explorer.py:1187 #: spyder/widgets/ipythonconsole/client.py:381 #: spyder/widgets/variableexplorer/namespacebrowser.py:148 msgid "Options" msgstr "Options" #: spyder/plugins/help.py:687 msgid "" "Here you can get help of any object by pressing %s in front of it, either on " "the Editor or the Console.%sHelp can also be shown automatically after " "writing a left parenthesis next to an object. You can activate this behavior " "in %s." msgstr "" "Pour obtenir de l'aide ici, sélectionner (ou placer le curseur sur) un objet " "dans l'éditeur ou la console, puis appuyer sur %s.%sL'aide apparaît " "automatiquement après la saisie d'une parenthèse gauche après un objet si " "l'option correspondante est activée dans %s." #: spyder/plugins/help.py:693 msgid "Preferences > Help" msgstr "Préférences > Aide" #: spyder/plugins/help.py:700 msgid "Usage" msgstr "Utilisation" #: spyder/plugins/help.py:701 msgid "New to Spyder? Read our" msgstr "Vous découvrez Spyder ? Lisez notre" #: spyder/plugins/help.py:702 msgid "tutorial" msgstr "Tutoriel" #: spyder/plugins/help.py:709 msgid "" "Please consider installing Sphinx to get documentation rendered in rich text." msgstr "" "Merci d'installer Sphinx pour obtenir la documentation en texte enrichi." #: spyder/plugins/help.py:878 msgid "Lock" msgstr "Verrouiller" #: spyder/plugins/help.py:878 msgid "Unlock" msgstr "Déverrouiller" #: spyder/plugins/help.py:922 msgid "" "The following error occured when calling Sphinx %s.
Incompatible " "Sphinx version or doc string decoding failed.

Error message:
%s" msgstr "" "L'erreur suivante s'est produite lors de l'exécution de Sphinx %s. " "
Veuillez vérifier si cette version de Sphinx est bien prise en charge " "par Spyder.

Message d'erreur :
%s" #: spyder/plugins/help.py:966 msgid "No source code available." msgstr "Aucun code source disponible." #: spyder/plugins/history.py:39 msgid "Settings" msgstr "Options" #: spyder/plugins/history.py:41 msgid " entries" msgstr " lignes" #: spyder/plugins/history.py:41 msgid "History depth: " msgstr "Taille de l'historique : " #: spyder/plugins/history.py:48 msgid "Scroll automatically to last entry" msgstr "Défiler automatiquement jusqu'à la dernière ligne" #: spyder/plugins/history.py:126 msgid "History log" msgstr "Historique" #: spyder/plugins/history.py:153 msgid "History..." msgstr "Historique..." #: spyder/plugins/history.py:155 msgid "Set history maximum entries" msgstr "Modifier le nombre d'entrées maximum de l'historique" #: spyder/plugins/history.py:260 msgid "History" msgstr "Historique" #: spyder/plugins/history.py:261 msgid "Maximum entries" msgstr "Nombre maximum d'entrées" #: spyder/plugins/ipythonconsole.py:65 msgid "Symbolic mathematics in the IPython Console" msgstr "Mathématiques symboliques pour la console IPython" #: spyder/plugins/ipythonconsole.py:69 msgid "Run Cython files in the IPython Console" msgstr "Exécutez les fichiers Cython dans la console IPython" #: spyder/plugins/ipythonconsole.py:73 msgid "Integrate the IPython console" msgstr "Intégrer la console IPython" #: spyder/plugins/ipythonconsole.py:77 msgid "IPython interactive python environment" msgstr "Environnement python interactif IPython" #: spyder/plugins/ipythonconsole.py:128 msgid "" "The authenticity of host %s can't be established. Are you sure you " "want to continue connecting?" msgstr "" "L'identité du serveur %s ne peut pas être confirmée. Êtes-vous sûr de " "vouloir poursuivre ?" #: spyder/plugins/ipythonconsole.py:140 msgid "The authenticity of the host can't be established" msgstr "L'identité du serveur ne peut pas être confirmée" #: spyder/plugins/ipythonconsole.py:147 msgid "Tunnel '%s' failed to start" msgstr "Impossible d'ouvrir le tunnel '%s'" #: spyder/plugins/ipythonconsole.py:152 msgid "Could not connect to remote host" msgstr "Impossible d'établir la connection au serveur distant" #: spyder/plugins/ipythonconsole.py:169 spyder/plugins/ipythonconsole.py:799 msgid "Connect to an existing kernel" msgstr "Connecter à un noyau existant" #: spyder/plugins/ipythonconsole.py:171 msgid "" "Please enter the connection info of the kernel you want to connect to. For " "that you can either select its JSON connection file using the Browse button, or write directly its id, in case it's a local kernel (for " "example kernel-3764.json or just 3764)." msgstr "" "Entrez les informations de connexion du noyau auquel vous voulez vous " "connecter. Pour cela vous pouvez soit sélectionner son fichier de connexion " "JSON en utilisant le bouton Parcourir, ou écrivez directement son " "identifiant si c'est un noyau local (Exemple : kernel-3764.json ou " "juste 3764)." #: spyder/plugins/ipythonconsole.py:182 msgid "Connection info:" msgstr "Information de connexion :" #: spyder/plugins/ipythonconsole.py:184 msgid "Path to connection file or kernel id" msgstr "Chemin vers un fichier de connexion ou identifiant de noyau" #: spyder/plugins/ipythonconsole.py:186 spyder/plugins/ipythonconsole.py:203 msgid "Browse" msgstr "Parcourir" #: spyder/plugins/ipythonconsole.py:195 msgid "This is a remote kernel" msgstr "Noyau distant" #: spyder/plugins/ipythonconsole.py:199 msgid "username@hostname:port" msgstr "utilisateur@hôte:port" #: spyder/plugins/ipythonconsole.py:202 msgid "Path to ssh key file" msgstr "Chemin vers la clé ssh" #: spyder/plugins/ipythonconsole.py:211 msgid "Password or ssh key passphrase" msgstr "Mot de passe ou passphrase de clé ssh" #: spyder/plugins/ipythonconsole.py:215 msgid "Host name" msgstr "Nom d'hôte" #: spyder/plugins/ipythonconsole.py:216 msgid "Ssh key" msgstr "Clé ssh" #: spyder/plugins/ipythonconsole.py:217 msgid "Password" msgstr "Mot de passe" #: spyder/plugins/ipythonconsole.py:246 msgid "Open connection file" msgstr "Ouvrir un fichier de connexion IPython" #: spyder/plugins/ipythonconsole.py:251 msgid "Select ssh key" msgstr "Sélectionner une clé ssh" #: spyder/plugins/ipythonconsole.py:284 spyder/plugins/ipythonconsole.py:734 msgid "IPython console" msgstr "Console IPython" #: spyder/plugins/ipythonconsole.py:291 msgid "Display initial banner" msgstr "Afficher le message d'accueil" #: spyder/plugins/ipythonconsole.py:292 msgid "" "This option lets you hide the message shown at\n" "the top of the console when it's opened." msgstr "" "Cette option permet de masquer la message d'accueil\n" "qui s'affiche à l'ouverture de la console." #: spyder/plugins/ipythonconsole.py:294 msgid "Use a pager to display additional text inside the console" msgstr "Utiliser un pager pour afficher l'aide" #: spyder/plugins/ipythonconsole.py:296 msgid "" "Useful if you don't want to fill the console with long help or completion " "texts.\n" "Note: Use the Q key to get out of the pager." msgstr "" "Le pager permet d'éviter de remplir la console de texte d'aide.\n" "Remarque : utiliser la touche Q pour quitter le pager." #: spyder/plugins/ipythonconsole.py:301 msgid "Ask for confirmation before closing" msgstr "Demander confirmation avant de fermer une console" #: spyder/plugins/ipythonconsole.py:304 msgid "Ask for confirmation before removing all user-defined variables" msgstr "" "Demander confirmation avant de supprimer les variables définies par " "l'utilisateur" #: spyder/plugins/ipythonconsole.py:307 msgid "" "This option lets you hide the warning message shown\n" "when resetting the namespace from Spyder." msgstr "" "Cette option permet de masquer le message de confirmation\n" "lors de la suppression des variables de Spyder." #: spyder/plugins/ipythonconsole.py:309 #: spyder/widgets/ipythonconsole/client.py:320 msgid "Show elapsed time" msgstr "Afficher le temps écoulé" #: spyder/plugins/ipythonconsole.py:320 msgid "Completion Type" msgstr "Type de complétion de code" #: spyder/plugins/ipythonconsole.py:321 msgid "Decide what type of completion to use" msgstr "Sélectionner le type de completion de code a utiliser" #: spyder/plugins/ipythonconsole.py:323 msgid "Graphical" msgstr "Graphique" #: spyder/plugins/ipythonconsole.py:323 msgid "Plain" msgstr "Simple" #: spyder/plugins/ipythonconsole.py:323 msgid "Terminal" msgstr "Terminal" #: spyder/plugins/ipythonconsole.py:324 msgid "Completion:" msgstr "Complétion de code :" #: spyder/plugins/ipythonconsole.py:334 msgid " lines" msgstr " lignes" #: spyder/plugins/ipythonconsole.py:334 msgid "Buffer: " msgstr "Tampon : " #: spyder/plugins/ipythonconsole.py:336 msgid "" "Set the maximum number of lines of text shown in the\n" "console before truncation. Specifying -1 disables it\n" "(not recommended!)" msgstr "" "Nombre maximum de lignes de texte affichées dans la console avant troncature " "(saisir -1 désactive cette dernière, ce qui est fortement déconseillé)." #: spyder/plugins/ipythonconsole.py:345 msgid "Support for graphics (Matplotlib)" msgstr "Prise en charge des graphes (Matplotlib)" #: spyder/plugins/ipythonconsole.py:346 msgid "Activate support" msgstr "Activer" #: spyder/plugins/ipythonconsole.py:347 msgid "Automatically load Pylab and NumPy modules" msgstr "Importer automatiquement Pylab et NumPy" #: spyder/plugins/ipythonconsole.py:350 msgid "" "This lets you load graphics support without importing \n" "the commands to do plots. Useful to work with other\n" "plotting libraries different to Matplotlib or to develop \n" "GUIs with Spyder." msgstr "" "Import automatique de toutes les fonctions de représentation graphique et de " "calcul numérique" #: spyder/plugins/ipythonconsole.py:365 msgid "Inline" msgstr "En ligne" #: spyder/plugins/ipythonconsole.py:366 msgid "Automatic" msgstr "Automatique" #: spyder/plugins/ipythonconsole.py:367 msgid "Graphics backend" msgstr "Sortie graphique" #: spyder/plugins/ipythonconsole.py:368 msgid "" "Decide how graphics are going to be displayed in the console. If unsure, " "please select %s to put graphics inside the console or %s to " "interact with them (through zooming and panning) in a separate window." msgstr "" "Cette option permet de régler la manière dont les graphes seront affichés " "dans la console. Par exemple, le mode %s permet l'affichage en ligne " "des graphes tandis que le mode %s permet d'interagir avec (zoom/pan) " "dans une fenêtre séparée." #: spyder/plugins/ipythonconsole.py:388 msgid "Backend:" msgstr "Sortie :" #: spyder/plugins/ipythonconsole.py:390 msgid "This option will be applied the next time a console is opened." msgstr "" "Cette option sera prise en compte lors de la prochaine ouverture de console." #: spyder/plugins/ipythonconsole.py:401 msgid "Inline backend" msgstr "Backend intégré" #: spyder/plugins/ipythonconsole.py:402 msgid "Decide how to render the figures created by this backend" msgstr "Option relative au rendu des figures dans ce backend" #: spyder/plugins/ipythonconsole.py:406 msgid "Format:" msgstr "Format :" #: spyder/plugins/ipythonconsole.py:409 msgid "Resolution:" msgstr "Résolution :" #: spyder/plugins/ipythonconsole.py:409 msgid "dpi" msgstr "ppp" #: spyder/plugins/ipythonconsole.py:411 msgid "Only used when the format is PNG. Default is 72" msgstr "Utilisé uniquement dans le cas du format PNG. Par défaut : 72" #: spyder/plugins/ipythonconsole.py:414 msgid "Width:" msgstr "Largeur :" #: spyder/plugins/ipythonconsole.py:414 spyder/plugins/ipythonconsole.py:418 msgid "inches" msgstr "pouces" #: spyder/plugins/ipythonconsole.py:416 msgid "Default is 6" msgstr "Par défaut : 6" #: spyder/plugins/ipythonconsole.py:418 msgid "Height:" msgstr "Hauteur :" #: spyder/plugins/ipythonconsole.py:420 msgid "Default is 4" msgstr "Par défaut : 4" #: spyder/plugins/ipythonconsole.py:447 msgid "" "You can run several lines of code when a console is started. Please " "introduce each one separated by commas, for example:
import os, import " "sys" msgstr "" "Plusieurs lignes de code peuvent être exécutées lors du démarrage de la " "console. Veuillez séparer deux lignes consécutives par une virgule - par " "exemple :
import os, import sys" #: spyder/plugins/ipythonconsole.py:453 msgid "Lines:" msgstr "Lignes :" #: spyder/plugins/ipythonconsole.py:462 msgid "Run a file" msgstr "Exécuter un fichier" #: spyder/plugins/ipythonconsole.py:463 msgid "" "You can also run a whole file at startup instead of just some lines (This is " "similar to have a PYTHONSTARTUP file)." msgstr "Option similaire à PYTHONSTARTUP pour un interpréteur standard." #: spyder/plugins/ipythonconsole.py:467 msgid "Use the following file:" msgstr "Utiliser le fichier suivant :" #: spyder/plugins/ipythonconsole.py:481 msgid "Greedy completion" msgstr "Complétion avancée" #: spyder/plugins/ipythonconsole.py:482 msgid "" "Enable Tab completion on elements of lists, results of function " "calls, etc, without assigning them to a variable.
For example, you " "can get completions on things like li[0].<Tab> or ins." "meth().<Tab>" msgstr "" "Active la complétion par Tab sur les éléments de liste, les " "résultats de fonctions, etc. sans les avoir assignés à une variable." "
Par exemple vous pourrez avoir la complétion pour des expressions du " "type li[0].<Tab> ou ins.meth().<Tab>." #: spyder/plugins/ipythonconsole.py:490 msgid "Use the greedy completer" msgstr "Utiliser la complétion avancée" #: spyder/plugins/ipythonconsole.py:501 msgid "Autocall" msgstr "Appel automatique" #: spyder/plugins/ipythonconsole.py:502 msgid "" "Autocall makes IPython automatically call any callable object even if you " "didn't type explicit parentheses.
For example, if you type str 43 " "it becomes str(43) automatically." msgstr "" "L'appel automatique dans IPython va automatiquement appeler les objets " "appelables même sans parenthèses explicites.
Par exemple str 43 " "deviendra automatiquement str(43)." #: spyder/plugins/ipythonconsole.py:509 msgid "Smart" msgstr "Intelligent" #: spyder/plugins/ipythonconsole.py:510 msgid "Full" msgstr "Toujours" #: spyder/plugins/ipythonconsole.py:511 msgid "Off" msgstr "Désactivé" #: spyder/plugins/ipythonconsole.py:513 msgid "Autocall: " msgstr "Appel automatique : " #: spyder/plugins/ipythonconsole.py:514 msgid "" "On %s mode, Autocall is not applied if there are no arguments after " "the callable. On %s mode, all callable objects are automatically " "called (even if no arguments are present)." msgstr "" "En mode %s, l'appel automatique n'est pas activé si il n'y a pas " "d'arguments. En mode %s, tous les objets appelables sont " "automatiquement appelés (même s'il n'y a pas d'arguments)" #: spyder/plugins/ipythonconsole.py:526 msgid "Symbolic Mathematics" msgstr "Calcul formel" #: spyder/plugins/ipythonconsole.py:527 msgid "" "Perfom symbolic operations in the console (e.g. integrals, derivatives, " "vector calculus, etc) and get the outputs in a beautifully printed style (it " "requires the Sympy module)." msgstr "" "Utilise le calcul formel pour réaliser des opérations dans la console (par " "exemple intégrales, dérivées, calcul vectoriel, etc...) et affiche les " "résultats de manière élégante." #: spyder/plugins/ipythonconsole.py:532 msgid "Use symbolic math" msgstr "Utiliser le calcul formel" #: spyder/plugins/ipythonconsole.py:533 msgid "" "This option loads the Sympy library to work with.
Please refer to its " "documentation to learn how to use it." msgstr "" "Activer cette option permet de travailler avec la bibliothèque Sympy." "
Merci de consulter la documentation pour savoir comment l'utiliser." #: spyder/plugins/ipythonconsole.py:543 msgid "Prompts" msgstr "Invites de commande" #: spyder/plugins/ipythonconsole.py:544 msgid "Modify how Input and Output prompts are shown in the console." msgstr "" "Change l'affichage des invites de commande d'entrée et de sortie de la " "console." #: spyder/plugins/ipythonconsole.py:547 msgid "Input prompt:" msgstr "En entrée :" #: spyder/plugins/ipythonconsole.py:549 msgid "" "Default is
In [<span class=\"in-prompt-number\">%i</span>]:" msgstr "" "Par défaut :
In [<span class=\"in-prompt-number\">%i</span>]:" #: spyder/plugins/ipythonconsole.py:553 msgid "Output prompt:" msgstr "En sortie :" #: spyder/plugins/ipythonconsole.py:555 msgid "" "Default is
Out[<span class=\"out-prompt-number\">%i</span>]:" msgstr "" "Par défaut :
Out[<span class=\"out-prompt-number\">%i</span>]:" #: spyder/plugins/ipythonconsole.py:575 msgid "Graphics" msgstr "Graphiques" #: spyder/plugins/ipythonconsole.py:577 msgid "Startup" msgstr "Démarrage" #: spyder/plugins/ipythonconsole.py:604 msgid "" "The directory {} is not writable and it is required to create IPython " "consoles. Please make it writable." msgstr "" "Le répertoire {} n’est pas accessible en écriture et il est nécessaire de " "créer des consoles IPython. Créez le chemin d’accès accessible en écriture." #: spyder/plugins/ipythonconsole.py:784 msgid "Open an &IPython console" msgstr "Ouvrir une console &IPython" #: spyder/plugins/ipythonconsole.py:791 msgid "Restart kernel" msgstr "Redémarrer le noyau" #: spyder/plugins/ipythonconsole.py:800 msgid "Open a new IPython console connected to an existing kernel" msgstr "Ouvrir une nouvelle console IPython connecté à un noyau existant" #: spyder/plugins/ipythonconsole.py:803 msgid "Rename tab" msgstr "Renommer l’onglet" #: spyder/plugins/ipythonconsole.py:928 msgid "" "No IPython console is currently available to run %s.

Please " "open a new one and try again." msgstr "" "Aucun client IPython n'est actuellement sélectionné pour exécuter %s." "

Merci d'ouvrir un nouveau client IPython et de réessayer." #: spyder/plugins/ipythonconsole.py:1018 msgid "" "Your Python environment or installation doesn't have the ipykernel " "and cloudpickle modules installed on it. Without these modules is " "not possible for Spyder to create a console for you.

You can install " "them by running in a system terminal:

pip install ipykernel " "cloudpickle

or

conda install ipykernel cloudpickle" msgstr "" "Votre environnement Python ou l'installation ne dispose pas des modules " "ipykernel et cloudpickle installés sur celui-ci. Sans ces " "modules, Spyder ne peut pas créer une console pour vous.

Vous pouvez " "les installer en exécutant dans un terminal de commande :

pip " "install ipykernel cloudpickle

ou

conda install " "ipykernel cloudpickle" #: spyder/plugins/ipythonconsole.py:1295 msgid "Do you want to close this console?" msgstr "Souhaitez-vous fermer cette console ?" #: spyder/plugins/ipythonconsole.py:1301 msgid "" "Do you want to close all other consoles connected to the same kernel as this " "one?" msgstr "" "Voulez-vous fermer les toutes les autres consoles connectées au même noyau " "que celle-ci ?" #: spyder/plugins/ipythonconsole.py:1366 msgid "" "It was not possible to restart the IPython console when switching to this " "project. The error was {0}" msgstr "" "Il n’a pas été possible de redémarrer la console IPython lors du passage à " "ce projet. L’erreur était la suivante : {0}" #: spyder/plugins/ipythonconsole.py:1467 msgid "" "This error was most probably caused by installing Spyder in a directory with " "non-ascii characters (i.e. characters with tildes, apostrophes or non-latin " "symbols).

To fix it, please reinstall Spyder in a different " "location." msgstr "" "Cette erreur est probablement causée par l’installation de Spyder dans un " "répertoire avec des caractères non ascii (c’est-à-dire des caractères avec " "des tildes, des apostrophes ou des symboles non latins).

Pour le " "réparer, réinstallez Spyder dans un endroit différent." #: spyder/plugins/ipythonconsole.py:1659 msgid "IPython" msgstr "IPython" #: spyder/plugins/ipythonconsole.py:1660 msgid "Unable to connect to %s" msgstr "Impossible de se connecter au noyau IPython %s" #: spyder/plugins/ipythonconsole.py:1730 msgid "Connection error" msgstr "Erreur de connexion" #: spyder/plugins/ipythonconsole.py:1731 msgid "" "Could not open ssh tunnel. The error was:\n" "\n" msgstr "" "Impossible d'ouvrir un tunnel ssh. L'erreur rencontrée est :\n" "\n" #: spyder/plugins/layoutdialog.py:177 msgid "Move Up" msgstr "Monter" #: spyder/plugins/layoutdialog.py:178 msgid "Move Down" msgstr "Descendre" #: spyder/plugins/layoutdialog.py:179 msgid "Delete Layout" msgstr "Supprimer disposition de fenêtre" #: spyder/plugins/layoutdialog.py:183 msgid "Layout Display and Order" msgstr "Configurer l'affichage et l'ordre" #: spyder/plugins/maininterpreter.py:31 spyder/plugins/maininterpreter.py:66 msgid "Python interpreter" msgstr "Interpréteur Python" #: spyder/plugins/maininterpreter.py:68 msgid "Select the Python interpreter for all Spyder consoles" msgstr "Sélectionner l'interpréteur Python utilisé pour exécuter des scripts" #: spyder/plugins/maininterpreter.py:71 msgid "Default (i.e. the same as Spyder's)" msgstr "" "Par défaut (interpréteur identique à celui dans lequel Spyder est exécuté)" #: spyder/plugins/maininterpreter.py:74 msgid "Use the following Python interpreter:" msgstr "Utiliser l'interpréteur Python suivant :" #: spyder/plugins/maininterpreter.py:77 msgid "Executables" msgstr "Exécutables" #: spyder/plugins/maininterpreter.py:94 msgid "User Module Reloader (UMR)" msgstr "User Module Reloader (UMR)" #: spyder/plugins/maininterpreter.py:95 msgid "" "UMR forces Python to reload modules which were imported when executing a " "file in a Python or IPython console with the runfile function." msgstr "" "L'UMR force Python à recharger les modules importés lors de l'exécution d'un " "script dans la console interne avec la fonction 'runfile'." #: spyder/plugins/maininterpreter.py:100 msgid "Enable UMR" msgstr "Activer l'UMR" #: spyder/plugins/maininterpreter.py:101 msgid "" "This option will enable the User Module Reloader (UMR) in Python/IPython " "consoles. UMR forces Python to reload deeply modules during import when " "running a Python script using the Spyder's builtin function runfile." "

1. UMR may require to restart the console in which it will be " "called (otherwise only newly imported modules will be reloaded when " "executing files).

2. If errors occur when re-running a PyQt-" "based program, please check that the Qt objects are properly destroyed (e.g. " "you may have to use the attribute Qt.WA_DeleteOnClose on your main " "window, using the setAttribute method)" msgstr "" "Cette option active le User Module Deleter (UMR) dans les consoles Python. " "L'UMR force Python à recharger complètement les modules lors de leur " "importation, dans le cadre de l'exécution d'un script Python avec la " "fonction Spyder runfile.

1. UMR peut nécessiter le " "redémarrage de la console Python dans lequel il va être utilisé (dans le cas " "contraire, seuls les modules importés après activation de l'UMR seront " "rechargés complètement lors de l'exécution de scripts).

2. Si " "des erreurs survenaient lors de la réexécution de programmes utilisant PyQt, " "veuillez vérifier que les objets Qt sont correctement détruits à la sortie " "du programme (par exemple, il sera probablement nécessaire d'utiliser " "l'attribut Qt.WA_DeleteOnClose sur votre objet fenêtre principale " "grâce à la méthode setAttribute)" #: spyder/plugins/maininterpreter.py:117 msgid "Show reloaded modules list" msgstr "Afficher les modules rechargés" #: spyder/plugins/maininterpreter.py:118 msgid "Please note that these changes will be applied only to new consoles" msgstr "" "Veuillez noter que ces changements ne seront pris en compte que dans les " "nouvelles consoles Python" #: spyder/plugins/maininterpreter.py:122 msgid "Set UMR excluded (not reloaded) modules" msgstr "Définir la liste des modules non rechargés par l'UMR" #: spyder/plugins/maininterpreter.py:150 msgid "" "You selected an invalid Python interpreter for the console so the previous " "interpreter will stay. Please make sure to select a valid one." msgstr "" "Vous avez sélectionné un interpréteur Python non valide pour la console afin " "que l’interprète précédent reste. Assurez-vous de sélectionner un interprète " "valide." #: spyder/plugins/maininterpreter.py:175 msgid "" "You selected a Python %d interpreter for the console but Spyder is " "running on Python %d!.

Although this is possible, we recommend " "you to install and run Spyder directly with your selected interpreter, to " "avoid seeing false warnings and errors due to the incompatible syntax " "between these two Python versions." msgstr "" "Vous avez sélectionné un interpréteur Python %d pour la console. Or " "cette version de Spyder est exécutée par Python %d !.

Même si " "c'est techniquement possible, il est recommandé d'installer et d'exécuter " "Spyder directement dans la version de l'interpréteur sélectionnée, afin " "d'éviter l'apparition d'avertissements ou d'erreurs liées à une syntaxe " "incompatible entre ces deux versions de Python" #: spyder/plugins/maininterpreter.py:186 spyder/plugins/maininterpreter.py:213 #: spyder/plugins/maininterpreter.py:217 msgid "UMR" msgstr "UMR" #: spyder/plugins/maininterpreter.py:187 msgid "Set the list of excluded modules as this: numpy, scipy" msgstr "" "Définissez la liste des modules exclus comme ceci : numpy, scipy" #: spyder/plugins/maininterpreter.py:204 msgid "" "You are working with Python 2, this means that you can not import a module " "that contains non-ascii characters." msgstr "" "Vous travaillez avec Python 2, cela signifie que vous ne pouvez pas importer " "un module qui contient des caractères non ASCII." #: spyder/plugins/maininterpreter.py:214 msgid "" "The following modules are not installed on your machine:\n" "%s" msgstr "" "Les modules suivants ne sont pas installés sur votre ordinateur :\n" "%s" #: spyder/plugins/maininterpreter.py:218 msgid "" "Please note that these changes will be applied only to new Python/IPython " "consoles" msgstr "" "Veuillez noter que ces changements ne seront pris en compte que dans les " "nouvelles consoles Python/IPython" #: spyder/plugins/onlinehelp.py:70 msgid "Online help" msgstr "Aide en ligne" #: spyder/plugins/outlineexplorer.py:49 spyder/widgets/editortools.py:195 msgid "Outline" msgstr "Structure" #: spyder/plugins/projects.py:78 spyder/widgets/projects/explorer.py:112 #: spyder/widgets/projects/explorer.py:126 msgid "Project explorer" msgstr "Explorateur de projets" #: spyder/plugins/projects.py:90 msgid "New Project..." msgstr "Nouveau Projet..." #: spyder/plugins/projects.py:93 msgid "Open Project..." msgstr "Ouvrir un Projet..." #: spyder/plugins/projects.py:96 msgid "Close Project" msgstr "Fermer le projet" #: spyder/plugins/projects.py:99 msgid "Delete Project" msgstr "Supprimer projet" #: spyder/plugins/projects.py:105 msgid "Project Preferences" msgstr "Préférences du projet" #: spyder/plugins/projects.py:107 msgid "Recent Projects" msgstr "Projets récents" #: spyder/plugins/projects.py:244 msgid "Open project" msgstr "Ouvrir le projet" #: spyder/plugins/projects.py:249 msgid "%s is not a Spyder project!" msgstr "%s n'est pas un projet Spyder !" #: spyder/plugins/runconfig.py:29 msgid "Execute in current console" msgstr "Exécuter dans la console actuelle" #: spyder/plugins/runconfig.py:30 msgid "Execute in a dedicated console" msgstr "Exécuter dans une nouvelle console dédiée" #: spyder/plugins/runconfig.py:31 msgid "Execute in an external system terminal" msgstr "Exécuter dans un terminal système externe" #: spyder/plugins/runconfig.py:42 msgid "Always show %s on a first file run" msgstr "Toujours afficher %s lors de la première exécution d'un script" #: spyder/plugins/runconfig.py:45 msgid "Remove all variables before execution" msgstr "Effacer toutes les variables avant l'exécution" #: spyder/plugins/runconfig.py:46 msgid "Directly enter debugging when errors appear" msgstr "Entrez directement le débogage lorsque des erreurs apparaissent" #: spyder/plugins/runconfig.py:47 msgid "Interact with the Python console after execution" msgstr "Interagir avec la console Python après l'exécution" #: spyder/plugins/runconfig.py:49 msgid "The directory of the file being executed" msgstr "Le répertoire du fichier en cours d’exécution" #: spyder/plugins/runconfig.py:50 spyder/plugins/workingdirectory.py:56 msgid "The current working directory" msgstr "Le répertoire de travail actuel" #: spyder/plugins/runconfig.py:51 msgid "The following directory:" msgstr "Le répertoire suivant :" #: spyder/plugins/runconfig.py:184 spyder/plugins/runconfig.py:504 msgid "General settings" msgstr "Options générales" #: spyder/plugins/runconfig.py:194 spyder/plugins/runconfig.py:236 msgid "Command line options:" msgstr "Options en ligne de commande :" #: spyder/plugins/runconfig.py:202 spyder/plugins/runconfig.py:514 msgid "Working Directory settings" msgstr "Paramètres du répertoire de travail" #: spyder/plugins/runconfig.py:226 spyder/plugins/runconfig.py:548 msgid "External system terminal" msgstr "Terminal système externe" #: spyder/plugins/runconfig.py:241 msgid "-u is added to the other options you set here" msgstr "L'option -u est ajoutée aux autres options spécifiées ici" #: spyder/plugins/runconfig.py:250 msgid "this dialog" msgstr "cette fenêtre" #: spyder/plugins/runconfig.py:315 msgid "Run configuration" msgstr "Configuration d'exécution" #: spyder/plugins/runconfig.py:316 msgid "The following working directory is not valid:
%s" msgstr "Le répertoire de travail suivant n'est pas valide :
%s" #: spyder/plugins/runconfig.py:394 msgid "Run settings for %s" msgstr "Options d'exécution pour %s" #: spyder/plugins/runconfig.py:426 msgid "Select a run configuration:" msgstr "Sélectionner une configuration d'exécution :" #: spyder/plugins/runconfig.py:455 msgid "Run configuration per file" msgstr "Exécuter la configuration par fichier" #: spyder/plugins/runconfig.py:480 msgid "" "The following are the default options for running files.These options may be " "overriden using the Configuration per file entry of the Run " "menu." msgstr "" "Voici les options par défaut pour l’exécution des fichiers. Ces options " "peuvent être remplacées en utilisant l’entrée Configuration par fichier " " du menu Exécuter ." #: spyder/plugins/runconfig.py:516 msgid "Default working directory is:" msgstr "Le répertoire de travail par défaut est :" #: spyder/plugins/runconfig.py:556 msgid "Run Settings dialog" msgstr "la fenêtre Options d'exécution" #: spyder/plugins/shortcuts.py:65 msgid "Currently used to delete lines on editor" msgstr "Actuellement utilisé pour supprimer des lignes sur l’éditeur" #: spyder/plugins/shortcuts.py:69 msgid "We cannot support this shortcut on Windows" msgstr "Nous ne pouvons pas prendre en charge ce raccourci sur Windows" #: spyder/plugins/shortcuts.py:72 msgid "Shortcuts that use Shift and another key are unsupported" msgstr "" "Les raccourcis qui utilisent `Shift` et une autre touche ne sont pas pris en " "charge" #: spyder/plugins/shortcuts.py:149 msgid "" "Press the new shortcut and select 'Ok': \n" "(Press 'Tab' once to switch focus between the shortcut entry \n" "and the buttons below it)" msgstr "" "Écrivez le nouveau raccourci et sélectionnez 'OK' :\n" "(Appuyez sur la touche 'Tab' une fois pour changer de focus entre l'entrée " "de raccourci\n" "et les boutons ci-dessous)" #: spyder/plugins/shortcuts.py:152 msgid "Current shortcut:" msgstr "Raccourci actuel :" #: spyder/plugins/shortcuts.py:154 msgid "New shortcut:" msgstr "Nouveau raccourci :" #: spyder/plugins/shortcuts.py:167 msgid "Shortcut: {0}" msgstr "Raccourci clavier : {0}" #: spyder/plugins/shortcuts.py:288 msgid "Please introduce a different shortcut" msgstr "Merci d'utiliser un raccourci clavier différent" #: spyder/plugins/shortcuts.py:325 msgid "The new shortcut conflicts with:" msgstr "Le nouveau raccourci est en conflit avec :" #: spyder/plugins/shortcuts.py:334 spyder/plugins/shortcuts.py:343 msgid "Forbidden key sequence!" msgstr "Séquence de clé interdite !" #: spyder/plugins/shortcuts.py:354 msgid "" "A compound sequence can have {break} a maximum of 4 subsequences.{break}" msgstr "" "Une séquence composée peut avoir {break} au plus 4 sous-séquences.{break}" #: spyder/plugins/shortcuts.py:359 msgid "Invalid key entered" msgstr "Vous avez entré une clé non valide" #: spyder/plugins/shortcuts.py:567 msgid "Context" msgstr "Contexte" #: spyder/plugins/shortcuts.py:569 #: spyder/widgets/variableexplorer/collectionseditor.py:128 msgid "Name" msgstr "Nom" #: spyder/plugins/shortcuts.py:571 msgid "Shortcut" msgstr "Raccourci clavier" #: spyder/plugins/shortcuts.py:573 msgid "Score" msgstr "Fuzzy points" #: spyder/plugins/shortcuts.py:734 msgid "Conflicts" msgstr "Conflits" #: spyder/plugins/shortcuts.py:735 msgid "The following conflicts have been detected:" msgstr "Les conflits suivants ont été détectés :" #: spyder/plugins/shortcuts.py:820 msgid "Keyboard shortcuts" msgstr "Raccourcis clavier" #: spyder/plugins/shortcuts.py:828 msgid "Search: " msgstr "Rechercher : " #: spyder/plugins/shortcuts.py:829 msgid "Reset to default values" msgstr "Rétablir les valeurs par défaut" #: spyder/plugins/shortcuts.py:859 msgid "Shortcuts reset" msgstr "Réinitialisation des raccourcis" #: spyder/plugins/shortcuts.py:860 msgid "Do you want to reset to default values?" msgstr "Souhaitez-vous rétablir les valeurs par défaut ?" #: spyder/plugins/variableexplorer.py:25 msgid "Filter" msgstr "Filtre" #: spyder/plugins/variableexplorer.py:27 #: spyder/widgets/variableexplorer/namespacebrowser.py:200 msgid "Exclude private references" msgstr "Exclure les références privées" #: spyder/plugins/variableexplorer.py:28 #: spyder/widgets/variableexplorer/namespacebrowser.py:215 msgid "Exclude capitalized references" msgstr "Exclure les références commençant par une majuscule" #: spyder/plugins/variableexplorer.py:29 #: spyder/widgets/variableexplorer/namespacebrowser.py:208 msgid "Exclude all-uppercase references" msgstr "Exclure les références en lettres capitales" #: spyder/plugins/variableexplorer.py:30 #: spyder/widgets/variableexplorer/namespacebrowser.py:223 msgid "Exclude unsupported data types" msgstr "Exclure les types non supportés" #: spyder/plugins/variableexplorer.py:36 #: spyder/widgets/variableexplorer/collectionseditor.py:699 msgid "Show arrays min/max" msgstr "Afficher les min/max des tableaux" #: spyder/plugins/variableexplorer.py:178 msgid "Variable explorer" msgstr "Explorateur de variables" #: spyder/plugins/workingdirectory.py:39 msgid "" "The current working directory is the working directory for IPython " "consoles and the current directory for the File Explorer." msgstr "" "Le répertoire de travail actuel est le répertoire de travail pour les " "consoles IPython et le répertoire actuel pour l’Explorateur de fichiers." #: spyder/plugins/workingdirectory.py:44 msgid "Console directory" msgstr "Répertoire de la console" #: spyder/plugins/workingdirectory.py:45 msgid "The working directory for new consoles is:" msgstr "Le répertoire de travail pour les nouvelles consoles est :" #: spyder/plugins/workingdirectory.py:49 msgid "" "The current project directory or user home directory (if no project is " "active)" msgstr "" "Le répertoire actuel du projet ou le répertoire d’accueil de l’utilisateur " "(si aucun projet n’est actif)" #: spyder/plugins/workingdirectory.py:62 msgid "the following directory:" msgstr "le répertoire suivant :" #: spyder/plugins/workingdirectory.py:64 msgid "The directory when a new console is open will be the specified path" msgstr "" "Le répertoire quand une nouvelle console est ouverte sera le chemin spécifié" #: spyder/plugins/workingdirectory.py:124 msgid "Back" msgstr "Retour" #: spyder/plugins/workingdirectory.py:132 spyder/widgets/explorer.py:1181 #: spyder/widgets/variableexplorer/importwizard.py:539 msgid "Next" msgstr "Suivant" #: spyder/plugins/workingdirectory.py:143 msgid "" "This is the working directory for newly\n" "opened consoles (Python/IPython consoles and\n" "terminals), for the file explorer, for the\n" "find in files plugin and for new files\n" "created in the editor" msgstr "" "Ceci est le répertoire de travail utilisé pour\n" "les nouvelles consoles (consoles Python/IPython\n" "et fenêtres de commandes), pour l'explorateur\n" "de fichiers, pour la recherche dans les fichiers\n" "et pour les fichiers créés dans l'éditeur" #: spyder/plugins/workingdirectory.py:168 msgid "Browse a working directory" msgstr "Sélectionner un répertoire de travail" #: spyder/plugins/workingdirectory.py:175 msgid "Change to parent directory" msgstr "Aller au répertoire parent" #: spyder/plugins/workingdirectory.py:182 spyder/widgets/findinfiles.py:322 msgid "Current working directory" msgstr "Le répertoire de travail actuel" #: spyder/utils/codeanalysis.py:92 msgid "Real-time code analysis on the Editor" msgstr "Analyse de code temps réel dans l'éditeur" #: spyder/utils/codeanalysis.py:96 msgid "Real-time code style analysis on the Editor" msgstr "Analyse de code temps réel dans l'éditeur" #: spyder/utils/environ.py:46 msgid "Environment variables" msgstr "Variables d'environnement" #: spyder/utils/environ.py:96 msgid "" "Module pywin32 was not found.
Please restart this Windows " "session (not the computer) for changes to take effect." msgstr "" "Le module pywin32 n'est pas installé.
Merci de redémarrer la " "session en cours (et non l'ordinateur) pour que les changements " "effectués prennent effet." #: spyder/utils/environ.py:109 msgid "" "If you accept changes, this will modify the current user environment " "variables directly in Windows registry. Use it with precautions, at " "your own risks.

Note that for changes to take effect, you will need " "to restart the parent process of this application (simply restart Spyder if " "you have executed it from a Windows shortcut, otherwise restart any " "application from which you may have executed it, like Python(x,y) Home for example)" msgstr "" "Si vous acceptez les changements effectués, cela modifiera les variables " "d'environnement de l'utilisateur courant directement dans la base de " "registre Windows. Utilisez cette fonctionnalité avec précautions et à " "vos risques et périls.

Notez que pour que les changements effectués " "prennent effet, il sera nécessaire de redémarrer le processus parent de " "cette application (redémarrez simplement Spyder si vous l'avez exécuté à " "partir d'un raccourci Windows, sinon redémarrez toute application ayant " "servie à exécuter Spyder : Python(x,y) Home ou un invite de commandes " "par exemple)" #: spyder/utils/help/sphinxify.py:217 spyder/utils/help/sphinxify.py:227 msgid "" "It was not possible to generate rich text help for this object.
Please " "see it in plain text." msgstr "" "Le processus de génération de l'aide sous la forme de texte enrichi a échoué." "
Merci d'activer le mode d'affichage en texte brut." #: spyder/utils/introspection/manager.py:34 #: spyder/utils/introspection/manager.py:39 msgid "Editor's code completion, go-to-definition and help" msgstr "Editeur : complétion de code, aller à la définition, etc." #: spyder/utils/iofuncs.py:408 msgid "Supported files" msgstr "Fichiers compatibles" #: spyder/utils/iofuncs.py:410 msgid "All files (*.*)" msgstr "Tous les fichiers (*.*)" #: spyder/utils/iofuncs.py:420 msgid "Spyder data files" msgstr "Fichiers Spyder" #: spyder/utils/iofuncs.py:422 #: spyder/widgets/variableexplorer/collectionseditor.py:1058 msgid "NumPy arrays" msgstr "Tableaux NumPy" #: spyder/utils/iofuncs.py:423 msgid "NumPy zip arrays" msgstr "Tableaux NumPy compressés" #: spyder/utils/iofuncs.py:424 msgid "Matlab files" msgstr "Fichiers Matlab" #: spyder/utils/iofuncs.py:425 msgid "CSV text files" msgstr "Fichiers texte CSV" #: spyder/utils/iofuncs.py:427 msgid "JPEG images" msgstr "Images JPEG" #: spyder/utils/iofuncs.py:428 msgid "PNG images" msgstr "Images PNG" #: spyder/utils/iofuncs.py:429 msgid "GIF images" msgstr "Images GIF" #: spyder/utils/iofuncs.py:430 msgid "TIFF images" msgstr "Images TIFF" #: spyder/utils/iofuncs.py:431 spyder/utils/iofuncs.py:432 msgid "Pickle files" msgstr "Fichiers pickle" #: spyder/utils/iofuncs.py:433 msgid "JSON files" msgstr "Fichiers JSON" #: spyder/utils/iofuncs.py:452 spyder/utils/iofuncs.py:459 msgid "Unsupported file type '%s'" msgstr "Type de fichier non pris en charge '%s'" #: spyder/utils/programs.py:287 msgid "It was not possible to run this file in an external terminal" msgstr "Impossible d'exécuter ce fichier dans un terminal externe" #: spyder/utils/syntaxhighlighters.py:34 msgid "Syntax highlighting for Matlab, Julia and other file types" msgstr "Coloration syntaxique pour Matlab, Julia et d'autres types de fichier" #: spyder/utils/syntaxhighlighters.py:43 msgid "Background:" msgstr "Fond :" #: spyder/utils/syntaxhighlighters.py:44 #: spyder/widgets/sourcecode/codeeditor.py:107 msgid "Current line:" msgstr "Ligne actuelle :" #: spyder/utils/syntaxhighlighters.py:45 msgid "Current cell:" msgstr "Cellule actuelle :" #: spyder/utils/syntaxhighlighters.py:46 msgid "Occurrence:" msgstr "Occurrence :" #: spyder/utils/syntaxhighlighters.py:47 msgid "Link:" msgstr "Lien :" #: spyder/utils/syntaxhighlighters.py:48 msgid "Side areas:" msgstr "Zones latérales :" #: spyder/utils/syntaxhighlighters.py:49 msgid "Matched
parens:" msgstr "Parenthèses correspondantes :" #: spyder/utils/syntaxhighlighters.py:50 msgid "Unmatched
parens:" msgstr "Parenthèse isolée :" #: spyder/utils/syntaxhighlighters.py:51 msgid "Normal text:" msgstr "Texte normal :" #: spyder/utils/syntaxhighlighters.py:52 msgid "Keyword:" msgstr "Mot-clé :" #: spyder/utils/syntaxhighlighters.py:53 msgid "Builtin:" msgstr "Objet intégré :" #: spyder/utils/syntaxhighlighters.py:54 msgid "Definition:" msgstr "Définition :" #: spyder/utils/syntaxhighlighters.py:55 msgid "Comment:" msgstr "Commentaire :" #: spyder/utils/syntaxhighlighters.py:56 msgid "String:" msgstr "Chaîne :" #: spyder/utils/syntaxhighlighters.py:57 msgid "Number:" msgstr "Nombre :" #: spyder/utils/syntaxhighlighters.py:58 msgid "Instance:" msgstr "Instance :" #: spyder/widgets/arraybuilder.py:179 msgid "" "\n" " Numpy Array/Matrix Helper
\n" " Type an array in Matlab : [1 2;3 4]
\n" " or Spyder simplified syntax : 1 2;3 4\n" "

\n" " Hit 'Enter' for array or 'Ctrl+Enter' for matrix.\n" "

\n" " Hint:
\n" " Use two spaces or two tabs to generate a ';'.\n" " " msgstr "" "\n" " Constructeur de Tableau/Matrice Numpy
\n" " Tapez un tableau dans Matlab : [1 2; 3 4]
\n" " ou la syntaxe simplifiée de Spyder: 1 2; 3 4 \n" "

\n" " Appuyez sur la touche 'Entrée' pour le tableau Numpy ou 'Ctrl" "+Entrée' pour la matrice Numpy.\n" "

\n" " Conseil:
\n" " Utilisez deux espaces ou deux onglets pour générer un ';'.\n" " " #: spyder/widgets/arraybuilder.py:190 msgid "" "\n" " Numpy Array/Matrix Helper
\n" " Enter an array in the table.
\n" " Use Tab to move between cells.\n" "

\n" " Hit 'Enter' for array or 'Ctrl+Enter' for matrix.\n" "

\n" " Hint:
\n" " Use two tabs at the end of a row to move to the next row.\n" " " msgstr "" "\n" " Constructeur de Tableau/Matrice Numpy
\n" " Entrez un tableau Numpy dans le tableau.
\n" " Appyuyez sur la touche 'Tab' pour vous déplacer entre les " "cellules.\n" "

\n" " Appuyez sur la touche 'Entrée' pour le tableau ou 'Ctrl + Entrée' " "pour la matrice.\n" "

\n" " Conseil : appuyez deux fois sur la touche 'Tab' à la fin " "d'une ligne pour passer à la ligne suivante.\n" " " #: spyder/widgets/arraybuilder.py:365 msgid "Array dimensions not valid" msgstr "Dimensions du tableau non valides" #: spyder/widgets/browser.py:58 spyder/widgets/sourcecode/codeeditor.py:2719 msgid "Zoom out" msgstr "Réduire" #: spyder/widgets/browser.py:61 spyder/widgets/sourcecode/codeeditor.py:2715 msgid "Zoom in" msgstr "Agrandir" #: spyder/widgets/browser.py:213 msgid "Home" msgstr "Accueil" #: spyder/widgets/browser.py:249 msgid "Find text" msgstr "Rechercher" #: spyder/widgets/browser.py:266 msgid "Address:" msgstr "Adresse :" #: spyder/widgets/browser.py:302 msgid "Unable to load page" msgstr "Impossible de charger la page" #: spyder/widgets/comboboxes.py:164 msgid "Press enter to validate this entry" msgstr "Appuyer sur Entrée pour valider cette saisie" #: spyder/widgets/comboboxes.py:165 msgid "This entry is incorrect" msgstr "Cette saisie n'est pas correcte" #: spyder/widgets/comboboxes.py:208 msgid "Press enter to validate this path" msgstr "Appuyez sur Entrée pour valider ce chemin d'accès" #: spyder/widgets/dependencies.py:63 msgid " Required " msgstr " Requis " #: spyder/widgets/dependencies.py:63 msgid "Module" msgstr "Module" #: spyder/widgets/dependencies.py:64 msgid " Installed " msgstr " Installé " #: spyder/widgets/dependencies.py:64 msgid "Provided features" msgstr "Fonctionnalités associées" #: spyder/widgets/dependencies.py:134 msgid "Dependencies" msgstr "Dépendances" #: spyder/widgets/dependencies.py:141 msgid "" "Spyder depends on several Python modules to provide the right functionality " "for all its panes. The table below shows the required and installed versions " "(if any) of all of them.

Note: You can safely use Spyder " "without the following modules installed: %s and %s." "

Please also note that new dependencies or changed ones will be " "correctly detected only after Spyder is restarted." msgstr "" "Spyder dépend de nombreux modules Python pour disposer de l'intégralité des " "fonctionnalités potentiellement fournies par ses plugins. Le tableau suivant " "montre les versions requises et installées (le cas échéant) de toutes ces " "dépendances.

Même si Spyder est parfaitement fonctionnel sans tout " "ces modules, il est néanmoins fortement recommandé d'installer au minimum " "%s et %s afin de bénéficier des fonctionnalités les plus avancées." "

Les nouvelles dépendances ou celles modifiées ne seront détectées " "correctement qu'après redémarrage de Spyder." #: spyder/widgets/dependencies.py:157 msgid "Copy to clipboard" msgstr "Copier dans le presse-papier" #: spyder/widgets/editor.py:501 msgid "Find symbols in file..." msgstr "Rechercher des symboles dans le fichier…" #: spyder/widgets/editor.py:504 msgid "Copy path to clipboard" msgstr "Copier le chemin d'accès dans le presse-papier" #: spyder/widgets/editor.py:508 msgid "Close all to the right" msgstr "Fermer tous les onglets vers la droite" #: spyder/widgets/editor.py:510 msgid "Close all but this" msgstr "Fermer tout sauf cet onglet" #: spyder/widgets/editor.py:514 spyder/widgets/explorer.py:361 msgid "Show in Finder" msgstr "Afficher dans le Finder" #: spyder/widgets/editor.py:516 spyder/widgets/explorer.py:363 msgid "Show in external file explorer" msgstr "Afficher dans l’explorateur de fichiers externe" #: spyder/widgets/editor.py:1197 msgid "Temporary file" msgstr "Fichier temporaire" #: spyder/widgets/editor.py:1289 msgid "New window" msgstr "Nouvelle fenêtre" #: spyder/widgets/editor.py:1290 msgid "Create a new editor window" msgstr "Créer une nouvelle fenêtre d'édition" #: spyder/widgets/editor.py:1293 msgid "Split vertically" msgstr "Séparation verticale" #: spyder/widgets/editor.py:1295 msgid "Split vertically this editor window" msgstr "Séparer en deux verticalement cette fenêtre d'édition" #: spyder/widgets/editor.py:1297 msgid "Split horizontally" msgstr "Séparation horizontale" #: spyder/widgets/editor.py:1299 msgid "Split horizontally this editor window" msgstr "Séparer en deux horizontalement cette fenêtre d'édition" #: spyder/widgets/editor.py:1301 msgid "Close this panel" msgstr "Fermer ce volet" #: spyder/widgets/editor.py:1540 msgid "%s has been modified.
Do you want to save changes?" msgstr "" "%s a été modifié.
Souhaitez-vous enregistrer ces changements ?" #: spyder/widgets/editor.py:1626 spyder/widgets/editor.py:1789 msgid "Save" msgstr "Enregistrer" #: spyder/widgets/editor.py:1627 spyder/widgets/editor.py:1790 #: spyder/widgets/shell.py:267 msgid "Unable to save file '%s'

Error message:
%s" msgstr "" "Impossible d'enregistrer le fichier '%s'

Message d'erreur :
" "%s" #: spyder/widgets/editor.py:1977 msgid "" "%s is unavailable (this file may have been removed, moved or renamed " "outside Spyder).
Do you want to close it?" msgstr "" "%s n'est pas accessible (ce fichier a peut-être été supprimé, déplacé " "ou renommé en dehors de Spyder).
Souhaitez-vous le fermer ?" #: spyder/widgets/editor.py:2000 msgid "" "%s has been modified outside Spyder.
Do you want to reload it and " "lose all your changes?" msgstr "" "%s a été modifié en dehors de Spyder.
Souhaitez-vous le recharger " "et perdre ainsi vos modifications ?" #: spyder/widgets/editor.py:2110 msgid "" "All changes to %s will be lost.
Do you want to revert file from " "disk?" msgstr "" "Toutes les modifications effectuées sur %s seront perdues." "
Souhaitez-vous revenir à la version du fichier enregistrée sur le " "disque ?" #: spyder/widgets/editor.py:2254 msgid "Loading %s..." msgstr "Chargement de \"%s\" en cours..." #: spyder/widgets/editor.py:2266 msgid "" "%s contains mixed end-of-line characters.
Spyder will fix this " "automatically." msgstr "" "%s contient des caractères de fin de ligne mélangés.
Spyder va " "corriger ceci automatiquement." #: spyder/widgets/editor.py:2675 msgid "Close window" msgstr "Fermer la fenêtre" #: spyder/widgets/editor.py:2677 msgid "Close this window" msgstr "Fermer cette fenêtre d'édition" #: spyder/widgets/editortools.py:94 spyder/widgets/editortools.py:130 msgid "Line %s" msgstr "Ligne %s" #: spyder/widgets/editortools.py:99 msgid "Class defined at line %s" msgstr "Classe déclarée ligne %s" #: spyder/widgets/editortools.py:107 msgid "Method defined at line %s" msgstr "Méthode déclarée ligne %s" #: spyder/widgets/editortools.py:117 msgid "Function defined at line %s" msgstr "Fonction déclarée ligne %s" #: spyder/widgets/editortools.py:149 msgid "Cell starts at line %s" msgstr "Cellule commençant ligne %s" #: spyder/widgets/editortools.py:202 spyder/widgets/editortools.py:535 msgid "Go to cursor position" msgstr "Aller à la position du curseur" #: spyder/widgets/editortools.py:205 msgid "Show absolute path" msgstr "Afficher les chemins complets" #: spyder/widgets/editortools.py:208 spyder/widgets/explorer.py:274 msgid "Show all files" msgstr "Afficher tous les fichiers" #: spyder/widgets/editortools.py:211 msgid "Show special comments" msgstr "Afficher les commentaires spéciaux" #: spyder/widgets/editortools.py:509 msgid "Show/hide outline explorer" msgstr "Afficher/masquer l'explorateur de structure" #: spyder/widgets/explorer.py:270 msgid "Edit filename filters..." msgstr "Modifier les filtres..." #: spyder/widgets/explorer.py:284 msgid "Edit filename filters" msgstr "Modifier les filtres" #: spyder/widgets/explorer.py:285 msgid "Name filters:" msgstr "Filtres sur les noms de fichiers :" #: spyder/widgets/explorer.py:304 msgid "File..." msgstr "Fichier..." #: spyder/widgets/explorer.py:308 msgid "Module..." msgstr "Module..." #: spyder/widgets/explorer.py:312 msgid "Folder..." msgstr "Dossier..." #: spyder/widgets/explorer.py:316 msgid "Package..." msgstr "Paquet..." #: spyder/widgets/explorer.py:337 #: spyder/widgets/variableexplorer/collectionseditor.py:674 msgid "Edit" msgstr "Modifier" #: spyder/widgets/explorer.py:339 msgid "Move..." msgstr "Déplacer..." #: spyder/widgets/explorer.py:342 msgid "Delete..." msgstr "Supprimer..." #: spyder/widgets/explorer.py:345 msgid "Rename..." msgstr "Renommer..." #: spyder/widgets/explorer.py:348 msgid "Open" msgstr "Ouvrir" #: spyder/widgets/explorer.py:349 spyder/widgets/sourcecode/codeeditor.py:2687 msgid "Convert to Python script" msgstr "Convertir en fichier Python" #: spyder/widgets/explorer.py:390 msgid "Commit" msgstr "Commiter" #: spyder/widgets/explorer.py:393 msgid "Browse repository" msgstr "Explorer le dépôt" #: spyder/widgets/explorer.py:404 msgid "Open command prompt here" msgstr "Ouvrir un invite de commandes ici" #: spyder/widgets/explorer.py:406 msgid "Open terminal here" msgstr "Ouvrir un terminal ici" #: spyder/widgets/explorer.py:407 msgid "Open IPython console here" msgstr "Ouvrir une console IPython ici" #: spyder/widgets/explorer.py:421 msgid "New" msgstr "Nouveau" #: spyder/widgets/explorer.py:429 msgid "Import" msgstr "Import" #: spyder/widgets/explorer.py:575 msgid "Do you really want to delete %s?" msgstr "Souhaitez-vous réellement supprimer %s ?" #: spyder/widgets/explorer.py:593 msgid "delete" msgstr "supprimer" #: spyder/widgets/explorer.py:594 spyder/widgets/projects/explorer.py:148 #: spyder/widgets/projects/explorer.py:255 msgid "Project Explorer" msgstr "Explorateur de projets" #: spyder/widgets/explorer.py:595 spyder/widgets/projects/explorer.py:149 msgid "Unable to %s %s

Error message:
%s" msgstr "Impossible de %s %s

Message d'erreur :
%s" #: spyder/widgets/explorer.py:610 msgid "File Explorer" msgstr "Explorateur de Fichiers" #: spyder/widgets/explorer.py:611 msgid "" "The current directory contains a project.

If you want to delete the " "project, please go to Projects » Delete Project" msgstr "" "Le dossier actuel contient un projet.

Si vous souhaitez supprimer le " "projet, allez dans Projets & raquo; Supprimer le projet" #: spyder/widgets/explorer.py:628 spyder/widgets/sourcecode/codeeditor.py:2160 msgid "Conversion error" msgstr "Erreur de conversion" #: spyder/widgets/explorer.py:629 spyder/widgets/sourcecode/codeeditor.py:2161 msgid "" "It was not possible to convert this notebook. The error is:\n" "\n" msgstr "" "Impossible de convertir ce notebook. Message d'erreur :\n" "\n" #: spyder/widgets/explorer.py:646 spyder/widgets/explorer.py:654 #: spyder/widgets/explorer.py:665 #: spyder/widgets/variableexplorer/collectionseditor.py:703 #: spyder/widgets/variableexplorer/collectionseditor.py:949 msgid "Rename" msgstr "Renommer" #: spyder/widgets/explorer.py:647 msgid "New name:" msgstr "Nouveau nom :" #: spyder/widgets/explorer.py:655 msgid "" "Do you really want to rename %s and overwrite the existing file " "%s?" msgstr "" "Souhaitez-vous réellement renommer %s et remplacer le ficher existant " "%s ?" #: spyder/widgets/explorer.py:666 msgid "Unable to rename file %s

Error message:
%s" msgstr "" "Impossible de renommer l'élément %s

Message d'erreur :" "
%s" #: spyder/widgets/explorer.py:709 msgid "Unable to move %s

Error message:
%s" msgstr "" "Impossible de déplacer %s

Message d'erreur :
%s" #: spyder/widgets/explorer.py:727 msgid "Unable to create folder %s

Error message:
%s" msgstr "" "Impossible de créer le répertoire %s

Message d'erreur :" "
%s" #: spyder/widgets/explorer.py:740 spyder/widgets/explorer.py:774 msgid "Unable to create file %s

Error message:
%s" msgstr "" "Impossible de créer le fichier %s

Message d'erreur :
" "%s" #: spyder/widgets/explorer.py:748 msgid "New folder" msgstr "Nouveau répertoire" #: spyder/widgets/explorer.py:749 msgid "Folder name:" msgstr "Nom du dossier :" #: spyder/widgets/explorer.py:754 msgid "New package" msgstr "Nouveau paquet" #: spyder/widgets/explorer.py:755 msgid "Package name:" msgstr "Nom du paquet :" #: spyder/widgets/explorer.py:795 msgid "New module" msgstr "Nouveau module" #: spyder/widgets/explorer.py:810 msgid "" "For %s support, please install one of the
following tools:

%s" msgstr "" "Pour ajouter la prise en charge de %s, merci d'installer
l'un des " "outils suivants :

%s" #: spyder/widgets/explorer.py:814 msgid "Unable to find external program.

%s" msgstr "Impossible de trouver un programme externe.

%s" #: spyder/widgets/explorer.py:1035 msgid "Show current directory only" msgstr "Afficher uniquement le répertoire courant" #: spyder/widgets/explorer.py:1145 msgid "You don't have the right permissions to open this directory" msgstr "" "Vous n'avez pas les permissions nécessaires pour afficher le contenu de ce " "dossier" #: spyder/widgets/explorer.py:1176 msgid "Show icons and text" msgstr "Afficher icônes et textes" #: spyder/widgets/explorer.py:1178 #: spyder/widgets/variableexplorer/importwizard.py:535 msgid "Previous" msgstr "Précédent" #: spyder/widgets/explorer.py:1184 msgid "Parent" msgstr "Parent" #: spyder/widgets/fileswitcher.py:110 msgid "unsaved file" msgstr "fichier non enregistré" #: spyder/widgets/fileswitcher.py:249 msgid "" "Press Enter to switch files or Esc to cancel.

Type to " "filter filenames.

Use :number to go to a line, e.g. " "main:42
Use @symbol_text to go to a symbol, e." "g. @init

Press Ctrl+W to close current " "tab.
" msgstr "" "Appuyez sur la touche Entrée pour changer de fichier ou Esc " "pour annuler.

Tapez pour filtrer les noms de fichiers. " "

Utilisez:numberpour aller à une ligne, par exemple " "main: 42
Utilisez@symbol_text pour accéder à un " "symbole, par example @init

Appuyez sur Ctrl + " "W pour fermer l'onglet actuel." #: spyder/widgets/fileswitcher.py:663 msgid "lines" msgstr "lignes" #: spyder/widgets/findinfiles.py:121 msgid "Unexpected error: see internal console" msgstr "Erreur inattendue : voir console interne" #: spyder/widgets/findinfiles.py:149 msgid "invalid regular expression" msgstr "expression régulière incorrecte" #: spyder/widgets/findinfiles.py:199 msgid "permission denied errors were encountered" msgstr "des erreurs d'autorisation d'accès ont été rencontrées" #: spyder/widgets/findinfiles.py:258 msgid "Search pattern" msgstr "Expression recherchée" #: spyder/widgets/findinfiles.py:261 spyder/widgets/findinfiles.py:301 #: spyder/widgets/findreplace.py:99 msgid "Regular expression" msgstr "Expression régulière" #: spyder/widgets/findinfiles.py:264 spyder/widgets/findreplace.py:105 msgid "Case Sensitive" msgstr "Respecter la casse" #: spyder/widgets/findinfiles.py:275 msgid "Search" msgstr "Rechercher" #: spyder/widgets/findinfiles.py:278 msgid "Start search" msgstr "Démarrer la recherche" #: spyder/widgets/findinfiles.py:285 msgid "Stop search" msgstr "Arrêter la recherche" #: spyder/widgets/findinfiles.py:295 msgid "Excluded filenames pattern" msgstr "Expression des noms de fichier à exclure" #: spyder/widgets/findinfiles.py:304 msgid "Exclude:" msgstr "Exclure :" #: spyder/widgets/findinfiles.py:313 msgid "Search in:" msgstr "Rechercher dans :" #: spyder/widgets/findinfiles.py:315 msgid "Search directory" msgstr "Rechercher un répertoire" #: spyder/widgets/findinfiles.py:324 msgid "Search in all files and directories present on thecurrent Spyder path" msgstr "" "Recherchez dans tous les fichiers et répertoires présents sur le chemin " "actuel de Spyder" #: spyder/widgets/findinfiles.py:328 msgid "Project" msgstr "Projets" #: spyder/widgets/findinfiles.py:330 msgid "" "Search in all files and directories present on thecurrent project path (If " "opened)" msgstr "" "Recherchez dans tous les fichiers et répertoires présents sur le chemin de " "projet actuel (si ouvert)" #: spyder/widgets/findinfiles.py:336 msgid "File" msgstr "Fichier" #: spyder/widgets/findinfiles.py:338 msgid "Search in current opened file" msgstr "Recherche dans le fichier ouvert actuel" #: spyder/widgets/findinfiles.py:340 msgid "Select other directory" msgstr "Sélectionner un autre répertoire" #: spyder/widgets/findinfiles.py:342 msgid "Search in other folder present on the file system" msgstr "Rechercher dans un autre répertoire du système" #: spyder/widgets/findinfiles.py:378 msgid "Hide advanced options" msgstr "Masquer les options avancées" #: spyder/widgets/findinfiles.py:381 msgid "Show advanced options" msgstr "Afficher les options avancées" #: spyder/widgets/findinfiles.py:675 spyder/widgets/findinfiles.py:759 msgid "String not found" msgstr "Chaîne de caractères non trouvée" #: spyder/widgets/findinfiles.py:761 msgid "matches in" msgstr "correspondances trouvées dans" #: spyder/widgets/findinfiles.py:762 msgid "file" msgstr "fichier" #: spyder/widgets/findinfiles.py:794 msgid " Scanning: {0}" msgstr " Recherche en cours : {0}" #: spyder/widgets/findinfiles.py:796 msgid " Searching for files in folder: {0}" msgstr " Recherche de fichiers dans le dossier : {0}" #: spyder/widgets/findinfiles.py:800 msgid " Searching for files..." msgstr " Recherche de fichiers…" #: spyder/widgets/findreplace.py:48 msgid "No matches" msgstr "Pas de correspondance" #: spyder/widgets/findreplace.py:49 spyder/widgets/findreplace.py:50 #: spyder/widgets/findreplace.py:72 msgid "Search string" msgstr "Chaîne de caractères à rechercher" #: spyder/widgets/findreplace.py:51 msgid "Regular expression error" msgstr "Erreur d'expression régulière" #: spyder/widgets/findreplace.py:111 msgid "Whole words" msgstr "Mots entiers" #: spyder/widgets/findreplace.py:117 msgid "Highlight matches" msgstr "Surligner les résultats" #: spyder/widgets/findreplace.py:131 msgid "Replace with:" msgstr "Remplacer par :" #: spyder/widgets/findreplace.py:133 msgid "Replace string" msgstr "Chaîne de caractères de remplacement" #: spyder/widgets/findreplace.py:137 msgid "Replace/find next" msgstr "Remplacer/rechercher suivant" #: spyder/widgets/findreplace.py:142 msgid "Replace selection" msgstr "Remplacer la sélection" #: spyder/widgets/findreplace.py:150 msgid "Replace all" msgstr "Remplacer tout" #: spyder/widgets/findreplace.py:572 msgid "of" msgstr "sur" #: spyder/widgets/findreplace.py:576 msgid "matches" msgstr "correspondances" #: spyder/widgets/findreplace.py:579 msgid "no matches" msgstr "Pas de correspondance" #: spyder/widgets/internalshell.py:262 msgid "Help..." msgstr "Aide..." #: spyder/widgets/internalshell.py:279 msgid "Shell special commands:" msgstr "Commandes spéciales de la console :" #: spyder/widgets/internalshell.py:280 msgid "Internal editor:" msgstr "Éditeur interne :" #: spyder/widgets/internalshell.py:281 msgid "External editor:" msgstr "Éditeur externe :" #: spyder/widgets/internalshell.py:282 msgid "Run script:" msgstr "Exécuter un script :" #: spyder/widgets/internalshell.py:283 msgid "Remove references:" msgstr "Supprimer des références :" #: spyder/widgets/internalshell.py:284 msgid "System commands:" msgstr "Commandes systèmes :" #: spyder/widgets/internalshell.py:285 msgid "Python help:" msgstr "Aide Python :" #: spyder/widgets/internalshell.py:286 msgid "GUI-based editor:" msgstr "Éditeur graphique :" #: spyder/widgets/ipythonconsole/client.py:275 msgid "An error ocurred while starting the kernel" msgstr "Une erreur est survenue lors du démarrage du noyau" #: spyder/widgets/ipythonconsole/client.py:316 #: spyder/widgets/ipythonconsole/client.py:372 #: spyder/widgets/ipythonconsole/client.py:405 #: spyder/widgets/ipythonconsole/shell.py:232 #: spyder/widgets/variableexplorer/namespacebrowser.py:193 msgid "Remove all variables" msgstr "Supprimer toutes les variables" #: spyder/widgets/ipythonconsole/client.py:325 msgid "Show environment variables" msgstr "Afficher les variables d’environnement" #: spyder/widgets/ipythonconsole/client.py:332 msgid "Show sys.path contents" msgstr "Afficher le contenu de sys.path" #: spyder/widgets/ipythonconsole/client.py:359 msgid "Stop the current command" msgstr "Interrompre la commande en cours" #: spyder/widgets/ipythonconsole/client.py:370 #: spyder/widgets/variableexplorer/collectionseditor.py:696 #: spyder/widgets/variableexplorer/collectionseditor.py:931 msgid "Remove" msgstr "Supprimer" #: spyder/widgets/ipythonconsole/client.py:393 msgid "Inspect current object" msgstr "Inspecter l'onglet courant" #: spyder/widgets/ipythonconsole/client.py:399 msgid "Clear line or block" msgstr "Effacer la ligne ou le bloc" #: spyder/widgets/ipythonconsole/client.py:412 msgid "Clear console" msgstr "Effacer la console" #: spyder/widgets/ipythonconsole/client.py:460 msgid "Are you sure you want to restart the kernel?" msgstr "Souhaitez-vous vraiment redémarrer le noyau ?" #: spyder/widgets/ipythonconsole/client.py:462 msgid "Restart kernel?" msgstr "Redémarrer le noyau ?" #: spyder/widgets/ipythonconsole/client.py:474 msgid "Error restarting kernel: %s\n" msgstr "Une erreur est survenue lors du démarrage du noyau : %s\n" #: spyder/widgets/ipythonconsole/client.py:479 msgid "" "
Restarting kernel...\n" "

" msgstr "" "
Redémarrage du noyau...\n" "

" #: spyder/widgets/ipythonconsole/client.py:483 msgid "Cannot restart a kernel not started by Spyder\n" msgstr "Impossible de redémarrer un noyau non démarré par Spyder\n" #: spyder/widgets/ipythonconsole/client.py:592 msgid "Connecting to kernel..." msgstr "Connexion au noyau..." #: spyder/widgets/ipythonconsole/help.py:128 spyder/widgets/mixins.py:712 msgid "Arguments" msgstr "Arguments" #: spyder/widgets/ipythonconsole/namespacebrowser.py:129 msgid "Loading this kind of data while debugging is not supported." msgstr "" "Le chargement de ce type de données alors que le déboggage n’est pas pris en " "charge." #: spyder/widgets/ipythonconsole/namespacebrowser.py:148 msgid "Saving data while debugging is not supported." msgstr "" "L’enregistrement de données lors du déboggage n’est pas pris en charge." #: spyder/widgets/ipythonconsole/shell.py:233 msgid "" "All user-defined variables will be removed. Are you sure you want to proceed?" msgstr "" "Toutes les variables définies par l'utilisateur seront supprimées. Souhaitez-" "vous continuer ?" #: spyder/widgets/ipythonconsole/shell.py:239 msgid "Don't show again." msgstr "Ne plus me demander." #: spyder/widgets/ipythonconsole/shell.py:262 msgid "" "

Removing all variables...\n" "
" msgstr "" "

Suppression de toutes les variables...\n" "
" #: spyder/widgets/ipythonconsole/shell.py:426 msgid "Changing backend to Qt for Mayavi" msgstr "Utilisation du backend Qt pour Mayavi" #: spyder/widgets/ipythonconsole/shell.py:471 msgid "Kernel died, restarting" msgstr "Le noyau est mort, redémarrage en cours" #: spyder/widgets/ipythonconsole/shell.py:471 msgid "Kernel restarting" msgstr "Redémarrage du kernel" #: spyder/widgets/onecolumntree.py:52 msgid "Collapse all" msgstr "Replier tout" #: spyder/widgets/onecolumntree.py:56 msgid "Expand all" msgstr "Déplier tout" #: spyder/widgets/onecolumntree.py:60 msgid "Restore" msgstr "Restaurer" #: spyder/widgets/onecolumntree.py:61 msgid "Restore original tree layout" msgstr "Restaurer l'organisation initiale de l'arbre" #: spyder/widgets/onecolumntree.py:65 msgid "Collapse selection" msgstr "Replier la sélection" #: spyder/widgets/onecolumntree.py:69 msgid "Expand selection" msgstr "Déplier la sélection" #: spyder/widgets/pathmanager.py:97 msgid "Move to top" msgstr "Placer en premier" #: spyder/widgets/pathmanager.py:103 msgid "Move up" msgstr "Monter" #: spyder/widgets/pathmanager.py:109 msgid "Move down" msgstr "Descendre" #: spyder/widgets/pathmanager.py:115 msgid "Move to bottom" msgstr "Placer en dernier" #: spyder/widgets/pathmanager.py:126 spyder/widgets/pathmanager.py:267 msgid "Add path" msgstr "Ajouter un chemin" #: spyder/widgets/pathmanager.py:131 spyder/widgets/pathmanager.py:246 msgid "Remove path" msgstr "Supprimer" #: spyder/widgets/pathmanager.py:141 msgid "Synchronize..." msgstr "Synchroniser..." #: spyder/widgets/pathmanager.py:143 msgid "Synchronize Spyder's path list with PYTHONPATH environment variable" msgstr "" "Synchronise la liste des chemins d'accès de Spyder avec celle de la variable " "d'environnement PYTHONPATH" #: spyder/widgets/pathmanager.py:155 msgid "Synchronize" msgstr "Synchroniser" #: spyder/widgets/pathmanager.py:156 msgid "" "This will synchronize Spyder's path list with PYTHONPATH environment " "variable for current user, allowing you to run your Python modules outside " "Spyder without having to configure sys.path.
Do you want to clear " "contents of PYTHONPATH before adding Spyder's path list?" msgstr "" "Ceci synchronisera la liste des chemins d'accès de Spyder avec celle de la " "variable d'environnement PYTHONPATH pour l'utilisateur courant, vous " "permettant ainsi d'exécuter vos modules Python en dehors de Spyder sans " "avoir besoin de configurer sys.path.
Souhaitez-vous effacer le contenu " "de PYTHONPATH avant d'y ajouter la liste des chemins d'accès de Spyder ?" #: spyder/widgets/pathmanager.py:247 msgid "Do you really want to remove selected path?" msgstr "Souhaitez-vous vraiment supprimer le chemin sélectionné ?" #: spyder/widgets/pathmanager.py:268 msgid "" "This directory is already included in Spyder path list.
Do you want to " "move it to the top of the list?" msgstr "" "Ce répertoire est déjà inclus dans la liste des chemins d'accès de Spyder." "
Souhaitez-vous le placer en début de liste ?" #: spyder/widgets/projects/configdialog.py:30 msgid "Project preferences" msgstr "Préférences du projet" #: spyder/widgets/projects/configdialog.py:82 #: spyder/widgets/projects/configdialog.py:119 msgid "Restore data on startup" msgstr "Restaurer les données au démarrage" #: spyder/widgets/projects/configdialog.py:84 #: spyder/widgets/projects/configdialog.py:121 msgid "Save data on exit" msgstr "Enregistrer les données" #: spyder/widgets/projects/configdialog.py:86 #: spyder/widgets/projects/configdialog.py:123 msgid "Save history" msgstr "Enregistrer l'historique" #: spyder/widgets/projects/configdialog.py:88 #: spyder/widgets/projects/configdialog.py:125 msgid "Save non project files opened" msgstr "Enregistrer les fichiers ouverts en dehors du projet" #: spyder/widgets/projects/configdialog.py:111 msgid "Code" msgstr "Code" #: spyder/widgets/projects/configdialog.py:118 msgid "Workspace" msgstr "Espace de travail" #: spyder/widgets/projects/configdialog.py:148 #: spyder/widgets/projects/configdialog.py:155 msgid "Version control" msgstr "Gestion de versions" #: spyder/widgets/projects/configdialog.py:156 msgid "Use version control" msgstr "Utiliser la gestion de version" #: spyder/widgets/projects/configdialog.py:161 msgid "Version control system" msgstr "Système de gestion de versions" #: spyder/widgets/projects/explorer.py:51 msgid "Show horizontal scrollbar" msgstr "Barre de défilement horizontal" #: spyder/widgets/projects/explorer.py:113 msgid "File %s already exists.
Do you want to overwrite it?" msgstr "Le fichier %s existe déjà.
Souhaitez-vous le remplacer ?" #: spyder/widgets/projects/explorer.py:127 msgid "Folder %s already exists." msgstr "Le dossier %s existe déjà." #: spyder/widgets/projects/explorer.py:145 msgid "copy" msgstr "copier" #: spyder/widgets/projects/explorer.py:147 msgid "move" msgstr "déplacer" #: spyder/widgets/projects/explorer.py:243 msgid "" "Do you really want to delete {filename}?

Note: This " "action will only delete the project. Its files are going to be preserved on " "disk." msgstr "" "Souhaitez-vous supprimer le projet %s ?

Notez que les fichiers " "et répertoires du projet ne seront pas supprimés du disque." #: spyder/widgets/projects/explorer.py:256 msgid "" "Unable to delete {varpath}

The error message was:" "
{error}" msgstr "" "Impossible de supprimer {varpath

Message d'erreur :" "
{error}" #: spyder/widgets/projects/projectdialog.py:69 msgid "New directory" msgstr "Sélectionner un répertoire" #: spyder/widgets/projects/projectdialog.py:70 msgid "Existing directory" msgstr "Répertoire existant" #: spyder/widgets/projects/projectdialog.py:72 msgid "Project name" msgstr "Nom du projet" #: spyder/widgets/projects/projectdialog.py:73 msgid "Location" msgstr "Répertoire" #: spyder/widgets/projects/projectdialog.py:74 msgid "Project type" msgstr "Type de projet" #: spyder/widgets/projects/projectdialog.py:75 msgid "Python version" msgstr "Python" #: spyder/widgets/projects/projectdialog.py:83 #: spyder/widgets/variableexplorer/importwizard.py:529 msgid "Cancel" msgstr "Annuler" #: spyder/widgets/projects/projectdialog.py:84 msgid "Create" msgstr "Créer" #: spyder/widgets/projects/projectdialog.py:102 msgid "Create new project" msgstr "Créer un nouveau projet" #: spyder/widgets/projects/type/__init__.py:216 msgid "Empty project" msgstr "Projet vide" #: spyder/widgets/projects/type/python.py:20 msgid "Python project" msgstr "Projet Python" #: spyder/widgets/projects/type/python.py:76 msgid "Python package" msgstr "Paquet Python" #: spyder/widgets/pydocgui.py:110 msgid "Module or package:" msgstr "Module ou paquet :" #: spyder/widgets/shell.py:131 msgid "Save history log..." msgstr "Enregistrer l'historique..." #: spyder/widgets/shell.py:133 msgid "Save current history log (i.e. all inputs and outputs) in a text file" msgstr "" "Enregistrer l'historique complet (toutes les entrées et sorties) dans un " "fichier texte" #: spyder/widgets/shell.py:253 msgid "Save history log" msgstr "Enregistrer l'historique" #: spyder/widgets/shell.py:256 msgid "History logs" msgstr "Fichiers d'historique" #: spyder/widgets/shell.py:670 msgid "Copy without prompts" msgstr "Copier sans les préfixes" #: spyder/widgets/shell.py:673 spyder/widgets/shell.py:677 msgid "Clear line" msgstr "Effacer la ligne" #: spyder/widgets/shell.py:679 msgid "Clear shell" msgstr "Effacer la console" #: spyder/widgets/shell.py:683 msgid "Clear shell contents ('cls' command)" msgstr "Effacer le contenu de la console" #: spyder/widgets/shortcutssummary.py:42 msgid "Spyder Keyboard ShortCuts" msgstr "Raccourcis clavier Spyder" #: spyder/widgets/sourcecode/codeeditor.py:101 msgid "Go to line:" msgstr "Aller à la ligne :" #: spyder/widgets/sourcecode/codeeditor.py:109 msgid "Line count:" msgstr "Nombre de lignes :" #: spyder/widgets/sourcecode/codeeditor.py:1327 msgid "Breakpoint" msgstr "Point d'arrêt" #: spyder/widgets/sourcecode/codeeditor.py:1328 msgid "Condition:" msgstr "Condition :" #: spyder/widgets/sourcecode/codeeditor.py:1733 msgid "Code analysis" msgstr "Analyse de code" #: spyder/widgets/sourcecode/codeeditor.py:1787 msgid "To do" msgstr "À faire" #: spyder/widgets/sourcecode/codeeditor.py:2147 msgid "Removal error" msgstr "Erreur de suppression" #: spyder/widgets/sourcecode/codeeditor.py:2148 msgid "" "It was not possible to remove outputs from this notebook. The error is:\n" "\n" msgstr "" "Impossible d'effacer les résultats de ce notebook :\n" "\n" #: spyder/widgets/sourcecode/codeeditor.py:2684 msgid "Clear all ouput" msgstr "Effacer tous les résultats" #: spyder/widgets/sourcecode/codeeditor.py:2690 msgid "Go to definition" msgstr "Aller à la définition de l'objet" #: spyder/widgets/sourcecode/codeeditor.py:2723 msgid "Zoom reset" msgstr "Réinitialisation du zoom" #: spyder/widgets/status.py:25 msgid "CPU and memory usage info in the status bar" msgstr "" "Informations sur l'utilisation processeur et mémoire dans la barre d'état" #: spyder/widgets/status.py:117 msgid "Memory:" msgstr "Mémoire :" #: spyder/widgets/status.py:118 msgid "" "Memory usage status: requires the `psutil` (>=v0.3) library on non-Windows " "platforms" msgstr "" "Occupation mémoire : requiert la bibliothèque `psutil` (>=v0.3) sur les " "plateformes autres que Windows" #: spyder/widgets/status.py:134 msgid "CPU:" msgstr "CPU :" #: spyder/widgets/status.py:135 msgid "CPU usage status: requires the `psutil` (>=v0.3) library" msgstr "Occupation CPU : requiert la bibliothèque `psutil` (>=v0.3)" #: spyder/widgets/status.py:162 msgid "Permissions:" msgstr "Droits d'accès :" #: spyder/widgets/status.py:189 msgid "End-of-lines:" msgstr "Fins de ligne :" #: spyder/widgets/status.py:216 msgid "Encoding:" msgstr "Encodage :" #: spyder/widgets/status.py:242 msgid "Line:" msgstr "Ligne :" #: spyder/widgets/status.py:243 msgid "Column:" msgstr "Colonne :" #: spyder/widgets/tabs.py:274 msgid "Browse tabs" msgstr "Naviguer dans les onglets" #: spyder/widgets/tabs.py:403 msgid "Close current tab" msgstr "Fermer l'onglet" #: spyder/widgets/variableexplorer/arrayeditor.py:511 msgid "It was not possible to copy values for this array" msgstr "Impossible de copier les valeurs de ce tableau" #: spyder/widgets/variableexplorer/arrayeditor.py:546 #: spyder/widgets/variableexplorer/arrayeditor.py:579 #: spyder/widgets/variableexplorer/dataframeeditor.py:697 #: spyder/widgets/variableexplorer/dataframeeditor.py:742 msgid "Format" msgstr "Format" #: spyder/widgets/variableexplorer/arrayeditor.py:551 #: spyder/widgets/variableexplorer/dataframeeditor.py:701 msgid "Resize" msgstr "Ajuster" #: spyder/widgets/variableexplorer/arrayeditor.py:554 #: spyder/widgets/variableexplorer/dataframeeditor.py:705 msgid "Background color" msgstr "Couleur de fond" #: spyder/widgets/variableexplorer/arrayeditor.py:580 #: spyder/widgets/variableexplorer/dataframeeditor.py:743 msgid "Float formatting" msgstr "Format de flottant" #: spyder/widgets/variableexplorer/arrayeditor.py:588 msgid "Format (%s) is incorrect" msgstr "Le format (%s) n'est pas valide" #: spyder/widgets/variableexplorer/arrayeditor.py:624 msgid "Arrays with more than 3 dimensions are not supported" msgstr "Les tableaux de plus de trois dimensions ne sont pas pris en charge" #: spyder/widgets/variableexplorer/arrayeditor.py:628 msgid "The 'xlabels' argument length do no match array column number" msgstr "" "La taille de 'xlabels' ne correspond pas au nombre de colonnes du tableau" #: spyder/widgets/variableexplorer/arrayeditor.py:632 msgid "The 'ylabels' argument length do no match array row number" msgstr "" "La taille de 'ylabels' ne correspond pas au nombre de lignes du tableau" #: spyder/widgets/variableexplorer/arrayeditor.py:639 msgid "%s arrays" msgstr "Les tableaux %s" #: spyder/widgets/variableexplorer/arrayeditor.py:640 msgid "%s are currently not supported" msgstr "%s ne sont actuellement pas pris en charge" #: spyder/widgets/variableexplorer/arrayeditor.py:647 msgid "NumPy array" msgstr "Tableaux NumPy" #: spyder/widgets/variableexplorer/arrayeditor.py:649 #: spyder/widgets/variableexplorer/arrayeditor.py:806 msgid "Array editor" msgstr "Éditeur de tableaux" #: spyder/widgets/variableexplorer/arrayeditor.py:651 msgid "read only" msgstr "lecture seule" #: spyder/widgets/variableexplorer/arrayeditor.py:681 msgid "Record array fields:" msgstr "Champs du tableau :" #: spyder/widgets/variableexplorer/arrayeditor.py:693 msgid "Data" msgstr "Données" #: spyder/widgets/variableexplorer/arrayeditor.py:693 msgid "Mask" msgstr "Masque" #: spyder/widgets/variableexplorer/arrayeditor.py:693 msgid "Masked data" msgstr "Données masquées" #: spyder/widgets/variableexplorer/arrayeditor.py:704 msgid "Axis:" msgstr "Axe :" #: spyder/widgets/variableexplorer/arrayeditor.py:709 msgid "Index:" msgstr "Indice :" #: spyder/widgets/variableexplorer/arrayeditor.py:722 msgid "Warning: changes are applied separately" msgstr "Attention : les changements seront pris en compte séparément" #: spyder/widgets/variableexplorer/arrayeditor.py:723 msgid "" "For performance reasons, changes applied to masked array won't be reflected " "in array's data (and vice-versa)." msgstr "" "Pour des questions de performance, les changements effectués sur les données " "masquées ne seront pas reflétées sur les données du tableau (et " "réciproquement)." #: spyder/widgets/variableexplorer/collectionseditor.py:126 msgid "Index" msgstr "Indice" #: spyder/widgets/variableexplorer/collectionseditor.py:131 msgid "Tuple" msgstr "Tuple" #: spyder/widgets/variableexplorer/collectionseditor.py:134 msgid "List" msgstr "Liste" #: spyder/widgets/variableexplorer/collectionseditor.py:137 msgid "Dictionary" msgstr "Dictionnaire" #: spyder/widgets/variableexplorer/collectionseditor.py:139 msgid "Key" msgstr "Clé" #: spyder/widgets/variableexplorer/collectionseditor.py:144 msgid "Attribute" msgstr "Attribut" #: spyder/widgets/variableexplorer/collectionseditor.py:148 msgid "elements" msgstr "éléments" #: spyder/widgets/variableexplorer/collectionseditor.py:319 msgid "Size" msgstr "Taille" #: spyder/widgets/variableexplorer/collectionseditor.py:319 msgid "Type" msgstr "Type" #: spyder/widgets/variableexplorer/collectionseditor.py:319 msgid "Value" msgstr "Valeur" #: spyder/widgets/variableexplorer/collectionseditor.py:417 msgid "" "Opening this variable can be slow\n" "\n" "Do you want to continue anyway?" msgstr "" "Afficher cette variable peut prendre du temps.\n" "\n" "Souhaitez-vous néanmoins continuer ?" #: spyder/widgets/variableexplorer/collectionseditor.py:428 msgid "" "Spyder was unable to retrieve the value of this variable from the console." "

The error mesage was:
%s" msgstr "" "Impossible de récupérer la valeur de cette variable depuis la console. " "

Message d'erreur :
%s" #: spyder/widgets/variableexplorer/collectionseditor.py:605 msgid "Edit item" msgstr "Modifier" #: spyder/widgets/variableexplorer/collectionseditor.py:606 msgid "Unable to assign data to item.

Error message:
%s" msgstr "" "Impossible d'assigner la valeur de l'objet.

Message d'erreur :" "
%s" #: spyder/widgets/variableexplorer/collectionseditor.py:666 msgid "Resize rows to contents" msgstr "Ajuster la hauteur des lignes" #: spyder/widgets/variableexplorer/collectionseditor.py:677 #: spyder/widgets/variableexplorer/collectionseditor.py:1027 #: spyder/widgets/variableexplorer/collectionseditor.py:1044 msgid "Plot" msgstr "Tracer" #: spyder/widgets/variableexplorer/collectionseditor.py:681 msgid "Histogram" msgstr "Histogramme" #: spyder/widgets/variableexplorer/collectionseditor.py:685 msgid "Show image" msgstr "Afficher l'image" #: spyder/widgets/variableexplorer/collectionseditor.py:689 #: spyder/widgets/variableexplorer/collectionseditor.py:1052 msgid "Save array" msgstr "Enregistrer le tableau" #: spyder/widgets/variableexplorer/collectionseditor.py:693 #: spyder/widgets/variableexplorer/collectionseditor.py:991 #: spyder/widgets/variableexplorer/collectionseditor.py:999 msgid "Insert" msgstr "Insérer" #: spyder/widgets/variableexplorer/collectionseditor.py:706 #: spyder/widgets/variableexplorer/collectionseditor.py:952 msgid "Duplicate" msgstr "Dupliquer" #: spyder/widgets/variableexplorer/collectionseditor.py:929 msgid "Do you want to remove the selected item?" msgstr "Souhaitez-vous supprimer l'élément sélectionné ?" #: spyder/widgets/variableexplorer/collectionseditor.py:930 msgid "Do you want to remove all selected items?" msgstr "Souhaitez-vous supprimer les éléments sélectionnés ?" #: spyder/widgets/variableexplorer/collectionseditor.py:950 msgid "New variable name:" msgstr "Nouveau nom de variable :" #: spyder/widgets/variableexplorer/collectionseditor.py:953 msgid "Variable name:" msgstr "Nom de variable :" #: spyder/widgets/variableexplorer/collectionseditor.py:991 msgid "Key:" msgstr "Clé :" #: spyder/widgets/variableexplorer/collectionseditor.py:999 msgid "Value:" msgstr "Valeur :" #: spyder/widgets/variableexplorer/collectionseditor.py:1015 msgid "Import error" msgstr "Erreur d'import" #: spyder/widgets/variableexplorer/collectionseditor.py:1016 msgid "Please install matplotlib or guiqwt." msgstr "Merci d'installer matplotlib ou guiqwt." #: spyder/widgets/variableexplorer/collectionseditor.py:1028 msgid "Unable to plot data.

Error message:
%s" msgstr "" "Impossible d'afficher les données

Message d'erreur :
%s" #: spyder/widgets/variableexplorer/collectionseditor.py:1045 msgid "Unable to show image.

Error message:
%s" msgstr "Impossible d'afficher l'image

Message d'erreur :
%s" #: spyder/widgets/variableexplorer/collectionseditor.py:1068 msgid "Unable to save array

Error message:
%s" msgstr "" "Impossible d'enregistrer le tableau

Message d'erreur :
%s" #: spyder/widgets/variableexplorer/collectionseditor.py:1093 msgid "It was not possible to copy this array" msgstr "Impossible de copier cet tableaux" #: spyder/widgets/variableexplorer/collectionseditor.py:1118 msgid "Clipboard contents" msgstr "Contenu du presse-papiers" #: spyder/widgets/variableexplorer/collectionseditor.py:1133 msgid "Import from clipboard" msgstr "Importer depuis le presse-papiers" #: spyder/widgets/variableexplorer/collectionseditor.py:1135 msgid "Empty clipboard" msgstr "Presse-papiers vide" #: spyder/widgets/variableexplorer/collectionseditor.py:1136 msgid "Nothing to be imported from clipboard." msgstr "Aucune donnée ne peut être importée depuis le presse-papiers." #: spyder/widgets/variableexplorer/dataframeeditor.py:591 msgid "To bool" msgstr "Booléen" #: spyder/widgets/variableexplorer/dataframeeditor.py:591 msgid "To complex" msgstr "Complexe" #: spyder/widgets/variableexplorer/dataframeeditor.py:592 msgid "To float" msgstr "Flottant" #: spyder/widgets/variableexplorer/dataframeeditor.py:592 msgid "To int" msgstr "Entier" #: spyder/widgets/variableexplorer/dataframeeditor.py:593 msgid "To str" msgstr "Caractères" #: spyder/widgets/variableexplorer/dataframeeditor.py:677 msgid "%s editor" msgstr "Éditeur de %s" #: spyder/widgets/variableexplorer/dataframeeditor.py:711 msgid "Column min/max" msgstr "Colonne min/max" #: spyder/widgets/variableexplorer/dataframeeditor.py:751 msgid "Format ({}) is incorrect" msgstr "Le format (%s) n'est pas valide" #: spyder/widgets/variableexplorer/dataframeeditor.py:755 msgid "Format ({}) should start with '%'" msgstr "Le format ({}) devrait commencer par ‘%’" #: spyder/widgets/variableexplorer/importwizard.py:118 #: spyder/widgets/variableexplorer/importwizard.py:438 msgid "Import as" msgstr "Importer en tant que" #: spyder/widgets/variableexplorer/importwizard.py:120 msgid "data" msgstr "données" #: spyder/widgets/variableexplorer/importwizard.py:124 msgid "code" msgstr "code" #: spyder/widgets/variableexplorer/importwizard.py:127 #: spyder/widgets/variableexplorer/importwizard.py:514 msgid "text" msgstr "texte" #: spyder/widgets/variableexplorer/importwizard.py:140 msgid "Column separator:" msgstr "Séparateur de colonne :" #: spyder/widgets/variableexplorer/importwizard.py:144 msgid "Tab" msgstr "Tab" #: spyder/widgets/variableexplorer/importwizard.py:147 msgid "Whitespace" msgstr "Whitespace" #: spyder/widgets/variableexplorer/importwizard.py:150 #: spyder/widgets/variableexplorer/importwizard.py:168 msgid "other" msgstr "autre" #: spyder/widgets/variableexplorer/importwizard.py:161 msgid "Row separator:" msgstr "Séparateur de ligne :" #: spyder/widgets/variableexplorer/importwizard.py:165 msgid "EOL" msgstr "EOL" #: spyder/widgets/variableexplorer/importwizard.py:180 msgid "Additional options" msgstr "Options supplémentaires" #: spyder/widgets/variableexplorer/importwizard.py:184 msgid "Skip rows:" msgstr "Sauter des lignes :" #: spyder/widgets/variableexplorer/importwizard.py:195 msgid "Comments:" msgstr "Commentaires :" #: spyder/widgets/variableexplorer/importwizard.py:201 msgid "Transpose" msgstr "Transposer" #: spyder/widgets/variableexplorer/importwizard.py:441 msgid "array" msgstr "tableau" #: spyder/widgets/variableexplorer/importwizard.py:446 msgid "list" msgstr "liste" #: spyder/widgets/variableexplorer/importwizard.py:451 msgid "DataFrame" msgstr "DataFrame" #: spyder/widgets/variableexplorer/importwizard.py:497 #: spyder/widgets/variableexplorer/importwizard.py:581 msgid "Import wizard" msgstr "Assistant d'importation" #: spyder/widgets/variableexplorer/importwizard.py:502 msgid "Raw text" msgstr "Text brut" #: spyder/widgets/variableexplorer/importwizard.py:505 msgid "variable_name" msgstr "nom_de_variable" #: spyder/widgets/variableexplorer/importwizard.py:516 msgid "table" msgstr "tableau" #: spyder/widgets/variableexplorer/importwizard.py:517 msgid "Preview" msgstr "Aperçu" #: spyder/widgets/variableexplorer/importwizard.py:521 msgid "Variable Name" msgstr "Nom de variable" #: spyder/widgets/variableexplorer/importwizard.py:544 msgid "Done" msgstr "Terminer" #: spyder/widgets/variableexplorer/importwizard.py:582 msgid "" "Unable to proceed to next step

Please check your entries." "

Error message:
%s" msgstr "" "Impossible de passer à l'étape suivante

Merci de vérifier " "votre saisie.

Message d'erreur :
%s" #: spyder/widgets/variableexplorer/namespacebrowser.py:181 #: spyder/widgets/variableexplorer/namespacebrowser.py:385 msgid "Import data" msgstr "Importer des données" #: spyder/widgets/variableexplorer/namespacebrowser.py:184 #: spyder/widgets/variableexplorer/namespacebrowser.py:465 #: spyder/widgets/variableexplorer/namespacebrowser.py:479 msgid "Save data" msgstr "Enregistrer les données" #: spyder/widgets/variableexplorer/namespacebrowser.py:189 msgid "Save data as..." msgstr "Enregistrer les données sous..." #: spyder/widgets/variableexplorer/namespacebrowser.py:201 msgid "Exclude references which name starts with an underscore" msgstr "Exclure les références dont le nom commence par un tiret bas" #: spyder/widgets/variableexplorer/namespacebrowser.py:209 msgid "Exclude references which name is uppercase" msgstr "Exclure les références dont le nom s'écrit en lettres capitales" #: spyder/widgets/variableexplorer/namespacebrowser.py:216 msgid "Exclude references which name starts with an uppercase character" msgstr "Exclure les références dont le nom commence par une lettre majuscule" #: spyder/widgets/variableexplorer/namespacebrowser.py:224 msgid "" "Exclude references to unsupported data types (i.e. which won't be handled/" "saved correctly)" msgstr "" "Exclure les références dont le type n'est pas supporté par l'espace de " "travail (en particulier, l'enregistrement ne fonctionnera pas)" #: spyder/widgets/variableexplorer/namespacebrowser.py:405 msgid "" "Unsupported file extension '%s'

Would you like to import it " "anyway (by selecting a known file format)?" msgstr "" "Extension de fichier non pris en charge '%s'

Souhaitez-vous " "néanmoins ouvrir ce fichier (en choisissant un format de fichier connu) ?" #: spyder/widgets/variableexplorer/namespacebrowser.py:413 msgid "Open file as:" msgstr "Ouvrir le fichier en tant que :" #: spyder/widgets/variableexplorer/namespacebrowser.py:447 msgid "Unable to load '%s'

Error message:
%s" msgstr "Impossible d'ouvrir '%s'

Message d'erreur :
%s" #: spyder/widgets/variableexplorer/namespacebrowser.py:480 msgid "Unable to save current workspace

Error message:
%s" msgstr "" "Impossible d'enregistrer l'espace de travail

Message d'erreur :" "
%s" #: spyder/widgets/variableexplorer/texteditor.py:74 msgid "Text editor" msgstr "Éditeur de texte" #: spyder/widgets/variableexplorer/utils.py:30 msgid "View and edit DataFrames and Series in the Variable Explorer" msgstr "" "Voir et éditer les Dataframes et les Series dans l'explorateur de variables" #: spyder/widgets/variableexplorer/utils.py:35 msgid "View and edit two and three dimensional arrays in the Variable Explorer" msgstr "" "Voir et éditer Tableaux de deux et trois dimensions dans l'explorateur de " "variables" #: spyder/workers/updates.py:90 spyder/workers/updates.py:92 msgid "Unable to retrieve information." msgstr "Impossible de charger l'information." #: spyder/workers/updates.py:94 msgid "" "Unable to connect to the internet.

Make sure the connection is " "working properly." msgstr "" "Impossible de se connecter à internet.

Vérifiez que votre accès à " "internet fonctionne correctement." #: spyder/workers/updates.py:97 msgid "Unable to check for updates." msgstr "Impossible de vérifier les mises à jour." #~ msgid "At startup, the current working directory is:" #~ msgstr "Au démarrage, le répertoire de travail global est:" #~ msgid "At startup," #~ msgstr "Au démarrage," #~ msgid "At startup, the current working directory will be the specified path" #~ msgstr "" #~ "Au démarrage, le répertoire de travail actuel sera le chemin spécifié" #~ msgid "Reset namespace" #~ msgstr "Réinitialiser l'espace de noms" #~ msgid "Reset IPython namespace" #~ msgstr "Réinitialiser l'espace de noms de la console IPython" #~ msgid "Loading external console..." #~ msgstr "Chargement de la console externe..." #~ msgid "The Python console" #~ msgstr "Console IPython" #~ msgid "" #~ "You can also run your code on a Python console. These consoles are useful " #~ "because they let you run a file in a console dedicated only to it.To " #~ "select this behavior, please press the F6 key.

By pressing " #~ "the button below and then focusing the Variable Explorer, you will notice " #~ "that Python consoles are also connected to that pane, and that the " #~ "Variable Explorer only shows the variables of the currently focused " #~ "console." #~ msgstr "" #~ "Vous pouvez également exécuter votre code dans une console Python. Ces " #~ "consoles sont utiles car elles vous permettent d'exécuter un fichier dans " #~ "une console dédiée uniquement à celui-ci. Pour sélectionner ce " #~ "comportement, appuyez sur la touche F6.

En appuyant sur le " #~ "bouton ci-dessous, puis en retournant sur l'explorateur de variables, " #~ "vous remarquerez que les consoles Python sont également connectées à ce " #~ "volet et que l'explorateur de variables ne montre que les variables de la " #~ "console actuellement sélectionnée." #~ msgid "Sort files according to full path" #~ msgstr "Classer les fichiers suivant leur chemin complet" #~ msgid "&Configure..." #~ msgstr "&Configurer..." #~ msgid "Show TODO/FIXME/XXX/HINT/TIP/@todo comments list" #~ msgstr "" #~ "Afficher la liste des commentaires du type TODO/FIXME/XXX/HINT/TIP/@todo" #~ msgid "Interactive data plotting in the consoles" #~ msgstr "Visualisation interactive de données" #~ msgid "Python console" #~ msgstr "Console Python" #~ msgid "One tab per script" #~ msgstr "Un onglet par script" #~ msgid "Buffer: " #~ msgstr "Tampon : " #~ msgid "Merge process standard output/error channels" #~ msgstr "Fusionner les canaux de sortie et d'erreur du processus" #~ msgid "" #~ "Merging the output channels of the process means that\n" #~ "the standard error won't be written in red anymore,\n" #~ "but this has the effect of speeding up display." #~ msgstr "" #~ "Fusionner les canaux de sortie et d'erreur du processus\n" #~ "signifie que les erreurs ne seront plus affichées en rouge,\n" #~ "mais cela entraînera également une amélioration des performances\n" #~ "d'affichage et une meilleure réactivité de la console." #~ msgid "Colorize standard error channel using ANSI escape codes" #~ msgstr "Coloriser le canal d'erreur standard (codes d'échappement ANSI)" #~ msgid "" #~ "This method is the only way to have colorized standard\n" #~ "error channel when the output channels have been merged." #~ msgstr "" #~ "Cette méthode est le seul moyen de coloriser le canal\n" #~ "d'erreur standard lorsque les canaux de sorties ont été fusionnés." #~ msgid "" #~ "This option will be applied the next time a Python console or a terminal " #~ "is opened." #~ msgstr "" #~ "Cette option sera prise en compte lors de la prochaine ouverture de " #~ "console (interpréteur Python ou terminal)." #~ msgid "Light background (white color)" #~ msgstr "Fond blanc" #~ msgid "PYTHONSTARTUP replacement" #~ msgstr "Substitution de PYTHONSTARTUP" #~ msgid "" #~ "This option will override the PYTHONSTARTUP environment variable which\n" #~ "defines the script to be executed during the Python console startup." #~ msgstr "" #~ "Cette option permet de remplacer le script de démarrage des consoles " #~ "Python défini par la\n" #~ "variable d'environnement PYTHONSTARTUP." #~ msgid "Default PYTHONSTARTUP script" #~ msgstr "Script PYTHONSTARTUP par défaut" #~ msgid "Use the following startup script:" #~ msgstr "Utiliser le script de démarrage suivant :" #~ msgid "Monitor" #~ msgstr "Moniteur" #~ msgid "" #~ "The monitor provides introspection features to console: code completion, " #~ "calltips and variable explorer. Because it relies on several modules, " #~ "disabling the monitor may be useful to accelerate console startup." #~ msgstr "" #~ "Le moniteur fournit à la console des fonctionnalités d'introspection " #~ "telles que la complétion de code, les info-bulles et l'explorateur de " #~ "variables. Parce qu'il nécessite l'import de nombreux modules, désactiver " #~ "le moniteur permet d'accélérer le démarrage de la console." #~ msgid "Enable monitor" #~ msgstr "Activer le moniteur" #~ msgid "Default library" #~ msgstr "Bibliothèque par défaut" #~ msgid "Qt-Python Bindings" #~ msgstr "Sélection de la bibliothèque d'interfaçage Qt" #~ msgid "Library:" #~ msgstr "Module:" #~ msgid "" #~ "This option will act on
libraries such as Matplotlib, guidata or ETS" #~ msgstr "" #~ "Cette option est prise en charge par les bibliothèques telles que " #~ "Matplotlib, guidata ou ETS" #~ msgid "" #~ "Decide which backend to use to display graphics. If unsure, please select " #~ "the Automatic backend.

Note: We support a very " #~ "limited number of backends in our Python consoles. If you prefer to work " #~ "with a different one, please use an IPython console." #~ msgstr "" #~ "Décidez quel backend utiliser pour afficher les graphiques. Si vous " #~ "n'êtes pas sûr, sélectionnez le backend Automatique. " #~ "
Remarque: Nous soutenons un nombre très limité de backends " #~ "dans nos consoles Python. Si vous préférez travailler avec un autre, " #~ "utilisez une console IPython." #~ msgid "None" #~ msgstr "Aucun" #~ msgid "Enthought Tool Suite" #~ msgstr "Enthought Tool Suite" #~ msgid "" #~ "Enthought Tool Suite (ETS) supports PyQt4 (qt4) and wxPython (wx) " #~ "graphical user interfaces." #~ msgstr "" #~ "Le logiciel Enthought Tool Suite (ETS) prend en charge les interfaces " #~ "graphiques PyQt4 (qt4) et wxPython (wx)." #~ msgid "ETS_TOOLKIT:" #~ msgstr "ETS_TOOLKIT:" #~ msgid "External modules" #~ msgstr "Modules externes" #~ msgid "" #~ "No Python console is currently selected to run %s.

Please " #~ "select or open a new Python console and try again." #~ msgstr "" #~ "Aucune console Python n'est actuellement sélectionnée pour exécuter " #~ "%s.

Merci de sélectionner ou d'ouvrir une nouvelle console " #~ "Python et de réessayer." #~ msgid "" #~ "%s is already running in a separate process.\n" #~ "Do you want to kill the process before starting a new one?" #~ msgstr "" #~ "%s est déjà en cours d'exécution dans un processus séparé.\n" #~ "Souhaitez-vous tuer ce processus avant d'en démarrer un autre ?" #~ msgid "Command Window" #~ msgstr "Invite de commandes" #~ msgid "Open a &Python console" #~ msgstr "Ouvrir une console &Python" #~ msgid "Open &command prompt" #~ msgstr "Ouvrir un invite de &commandes" #~ msgid "Open a Windows command prompt" #~ msgstr "Ouvrir un invite de commandes Windows" #~ msgid "Open a &terminal" #~ msgstr "Ouvrir un &terminal" #~ msgid "Open a terminal window" #~ msgstr "Ouvrir un terminal de commandes dans Spyder" #~ msgid "Python Console" #~ msgstr "Console Python" #~ msgid "Light background" #~ msgstr "Fond blanc" #~ msgid "Dark background" #~ msgstr "Fond noir" #~ msgid "Working directory:" #~ msgstr "Répertoire de travail :" #~ msgid "Dedicated Python console" #~ msgstr "Console Python dédiée" #~ msgid "Show warning when killing running process" #~ msgstr "Afficher un avertissement à l'interruption d'un processus" #~ msgid "Run Settings" #~ msgstr "Options d'exécution" #~ msgid "the script directory" #~ msgstr "le répertoire du fichier à exécuter" #~ msgid "Show warning when killing running processes" #~ msgstr "Afficher un avertissement à l'interruption d'un processus" #~ msgid "Autorefresh" #~ msgstr "Rafraîchissement automatique" #~ msgid "Enable autorefresh" #~ msgstr "Activer le rafraîchissement automatique" #~ msgid "Refresh interval: " #~ msgstr "Période de rafraîchissement : " #~ msgid "" #~ "The global working directory is the working directory for newly " #~ "opened consoles (Python/IPython consoles and terminals), for the " #~ "file explorer, for the find in files plugin and for new " #~ "files created in the editor." #~ msgstr "" #~ "Le répertoire de travail global est le répertoire de travail " #~ "utilisé pour les nouvelles consoles (consoles Python/IPython et " #~ "terminaux), pour l'explorateur de fichiers, pour la recherche " #~ "dans les fichiers et pour les fichiers créés dans l'éditeur." #~ msgid "the same as in last session" #~ msgstr "celui utilisé lors de la dernière session" #~ msgid "" #~ "At startup, Spyder will restore the global directory from last session" #~ msgstr "" #~ "Au démarrage, Spyder reprendra le répertoire de travail global de la " #~ "dernière session" #~ msgid "Files are opened from:" #~ msgstr "Les fichiers sont ouverts depuis :" #~ msgid "the current file directory" #~ msgstr "le répertoire du fichier en cours d'édition" #~ msgid "the global working directory" #~ msgstr "le répertoire de travail global" #~ msgid "Files are created in:" #~ msgstr "Les fichiers sont créés dans :" #~ msgid "Change to file base directory" #~ msgstr "Sélectionner le répertoire de base du fichier" #~ msgid "When opening a file" #~ msgstr "Lors de l'ouverture d'un fichier" #~ msgid "When saving a file" #~ msgstr "Lors de l'enregistrement d'un fichier" #~ msgid "Global working directory" #~ msgstr "Répertoire de travail global" #~ msgid "Unable to save script '%s'

Error message:
%s" #~ msgstr "" #~ "Impossible d'enregistrer le script '%s'

Message d'erreur :" #~ "
%s" #~ msgid "Run again this program" #~ msgstr "Exécuter de nouveau ce programme" #~ msgid "Kill" #~ msgstr "Terminer" #~ msgid "Kills the current process, causing it to exit immediately" #~ msgstr "" #~ "Tue le processus, entraînant une sortie brutale et immédiate du programme" #~ msgid "Running..." #~ msgstr "En cours d'exécution..." #~ msgid "Terminated." #~ msgstr "Terminé." #~ msgid "Command line arguments:" #~ msgstr "Arguments en ligne de commande :" #~ msgid "Variables" #~ msgstr "Variables" #~ msgid "Show/hide global variables explorer" #~ msgstr "Afficher/masquer l'explorateur de variables globales" #~ msgid "Terminate" #~ msgstr "Quitter" #~ msgid "" #~ "Attempts to stop the process. The process\n" #~ "may not exit as a result of clicking this\n" #~ "button (it is given the chance to prompt\n" #~ "the user for any unsaved files, etc)." #~ msgstr "" #~ "Tentative de fermeture du processus. Il est possible que\n" #~ "le processus ne s'arrête pas suite à cette tentative,\n" #~ "et propose à l'utilisateur de sauvegarder\n" #~ "les fichiers non-enregistrés, etc..." #~ msgid "Interact" #~ msgstr "Interagir" #~ msgid "Debug" #~ msgstr "Déboguer" #~ msgid "Arguments..." #~ msgstr "Arguments..." #~ msgid "Post Mortem Debug" #~ msgstr "Débogage Post Mortem" #~ msgid "Arguments: %s" #~ msgstr "Arguments : %s" #~ msgid "No argument" #~ msgstr "Aucun argument" #~ msgid "A Python console failed to start!" #~ msgstr "Le démarrage d'une console Python a échoué !" #~ msgid "Process failed to start" #~ msgstr "Le processus n'a pas pu démarrer" #~ msgid "Included filenames pattern" #~ msgstr "Expression des noms de fichier à inclure" #~ msgid "Include:" #~ msgstr "Inclure :" #~ msgid "PYTHONPATH" #~ msgstr "PYTHONPATH" #~ msgid "" #~ "Search in all directories listed in sys.path which are outside the Python " #~ "installation directory" #~ msgstr "" #~ "Rechercher dans tous les répertoires listés dans sys.path qui sont situés " #~ "en dehors du répertoire d'installation de Python" #~ msgid "Hg repository" #~ msgstr "Dépôt Mercurial" #~ msgid "Search in current directory hg repository" #~ msgstr "Rechercher dans le dépôt Mercurial du répertoire courant" #~ msgid "Here:" #~ msgstr "Ici :" #~ msgid "Search recursively in this directory" #~ msgstr "Rechercher de manière récursive dans ce répertoire" #~ msgid "Browse a search directory" #~ msgstr "Sélectionner un répertoire de recherche" #~ msgid "Search canceled" #~ msgstr "Recherche annulée" #~ msgid "interrupted" #~ msgstr "interrompu" #~ msgid "" #~ "Inspecting and setting values while debugging in IPython consoles is not " #~ "supported yet by Spyder." #~ msgstr "" #~ "L'inspection et la définition des valeurs lors du débogage dans les " #~ "consoles IPython n'est pas encore prise en charge par Spyder." #~ msgid "Refresh" #~ msgstr "Rafraîchir" #~ msgid "Refresh periodically" #~ msgstr "Rafraîchir périodiquement" #~ msgid "Python(x,y)" #~ msgstr "Python(x,y)" #~ msgid "Python(x,y) launcher" #~ msgstr "Accueil de Python(x,y)" #~ msgid "Python(x,y) documentation folder" #~ msgstr "Dossier de documentation Python(x,y)" #~ msgid "guidata documentation" #~ msgstr "Documentation de guidata" #~ msgid "guiqwt documentation" #~ msgstr "Documentation de guiqwt" #~ msgid "NumPy documentation" #~ msgstr "Documentation de NumPy" #~ msgid "NumPy reference guide" #~ msgstr "Manuel de référence de NumPy" #~ msgid "NumPy user guide" #~ msgstr "Manuel de l'utilisateur de NumPy" #~ msgid "SciPy documentation" #~ msgstr "Documentation de SciPy" #~ msgid "Show/hide project explorer" #~ msgstr "Afficher/masquer l'explorateur de projets" #~ msgid "?" #~ msgstr "?" #~ msgid "Use %s+T when the console is selected to open a new one" #~ msgstr "" #~ "Quand la console est sélectionnée, utiliser %s+T pour ouvrir une nouvelle " #~ "console" #~ msgid "Edit data in the remote process" #~ msgstr "Éditeurs dans le processus distant" #~ msgid "" #~ "Editors are opened in the remote process for NumPy arrays, PIL images, " #~ "lists, tuples and dictionaries.\n" #~ "This avoids transfering large amount of data between the remote process " #~ "and Spyder (through the socket)." #~ msgstr "" #~ "Les tableaux NumPy, images PIL, listes, tuples et dictionnaires seront " #~ "modifiés dans un éditeur exécuté dans le processus distant.\n" #~ "Cela permet d'éviter de transférer de gros volumes de données entre le " #~ "processus distant et Spyder (à travers le socket)." #~ msgid "Array is empty" #~ msgstr "Ce tableau est vide" #~ msgid "Object %s is not picklable" #~ msgstr "" #~ "L'objet %s n'est pas pris en charge par le protocole de " #~ "sérialisation de Pickle" #~ msgid "Truncate values" #~ msgstr "Tronquer les valeurs" #~ msgid "Reload last session" #~ msgstr "Recharger la session précédente" #~ msgid "Load session..." #~ msgstr "Charger une session..." #~ msgid "Load Spyder session" #~ msgstr "Charger une session Spyder" #, fuzzy #~ msgid "Save session..." #~ msgstr "Enregistrer la session" #~ msgid "Save current session and quit application" #~ msgstr "Enregistrer la session en cours et quitter l'application" #~ msgid "Open session" #~ msgstr "Ouvrir une session" #~ msgid "Spyder sessions" #~ msgstr "Sessions Spyder" #~ msgid "Save session" #~ msgstr "Enregistrer la session" #, fuzzy #~ msgid "Jupyter Qtconsole integration" #~ msgstr "Intégration de la console IPython" #~ msgid "Python executable" #~ msgstr "Exécutable Python" #~ msgid "Trying to kill a kernel?" #~ msgstr "Tentative d'arrêt d'un noyau" #~ msgid "" #~ "You can't close this kernel because it has one or more consoles connected " #~ "to it.

You need to close them instead or you can kill the kernel " #~ "using the second button from right to left." #~ msgstr "" #~ "Le noyau ne peut pas être fermé car au moins une console y est connectée. " #~ "

Veuillez soit fermer toutes les consoles connectées ou appuyer " #~ "sur le second bouton en partant de la droite pour tuer le processus du " #~ "noyau." #~ msgid "Kernel" #~ msgstr "Noyau" #~ msgid "" #~ "Either:
  1. Your IPython frontend and kernel versions are " #~ "incompatible or
  2. You don't have IPython installed in " #~ "your external interpreter.
In any case, we're sorry but we can't " #~ "create a console for you." #~ msgstr "" #~ "
  1. Soit les versions de votre interface IPython et du noyau sont " #~ "incompatibles,
  2. soit IPython n'est pas installé pour " #~ "votre interpréteur externe.
Dans tous les cas nous sommes " #~ "désolés mais nous ne pouvons ouvrir une console pour vous." #~ msgid "Kernel %s" #~ msgstr "Noyau %s" #~ msgid "Open an IPython console" #~ msgstr "Ouvrir une console IPython" #~ msgid "" #~ "The console monitor was disabled: the IPython kernel will be started as " #~ "expected, but an IPython console will have to be connected manually to " #~ "the kernel." #~ msgstr "" #~ "Le moniteur (console) a été désactivé. Par conséquent, le noyau IPython " #~ "sera démarré mais la console IPython devra y être connectée manuellement." #~ msgid "" #~ "UMR excluded modules:\n" #~ "(example: guidata, guiqwt)" #~ msgstr "" #~ "Modules non rechargés par l'UMR :\n" #~ "(exemple: guidata, guiqwt)" #~ msgid "" #~ "This feature requires the Matplotlib library.\n" #~ "It seems you don't have it installed." #~ msgstr "" #~ "Cette fonctionnalité nécessite l'installation du module Matplotlib.\n" #~ "Ce dernier n'est apparemment pas installé." #~ msgid "" #~ "This feature requires the Sympy library.\n" #~ "It seems you don't have it installed." #~ msgstr "" #~ "Cette fonctionnalité nécessite l'installation du module Sympy.\n" #~ "Ce dernier n'est apparemment pas installé." #~ msgid "&Font..." #~ msgstr "&Police..." #~ msgid "Set font style" #~ msgstr "Changer la police d'écriture" #~ msgid "Select a new font" #~ msgstr "Sélectionner une police d'écriture" #~ msgid "" #~ "The kernel failed to start!! That's all we know... Please close this " #~ "console and open a new one." #~ msgstr "" #~ "Le démarrage du noyau a échoué ! C'est malheureusement tout ce que nous " #~ "savons... Merci de fermer cette console et d'en ouvrir une nouvelle." #~ msgid "" #~ "It seems the kernel died unexpectedly. Use 'Restart kernel' to continue " #~ "using this console." #~ msgstr "" #~ "Le noyau a été arrêté de façon inattendue. Redémarrez le noyau pour " #~ "continuer d'utiliser cette console." #~ msgid "Kernel process is either remote or unspecified. Cannot interrupt" #~ msgstr "" #~ "Le processus du noyau est soit distant, soit non spécifié : impossible " #~ "d'arrêter le noyau." #~ msgid "Kernel process is either remote or unspecified. Cannot restart." #~ msgstr "" #~ "Le processus du noyau est soit distant, soit non spécifié : impossible de " #~ "redémarrer le noyau." #~ msgid "its own configuration file" #~ msgstr "son propre fichier de configuration" #~ msgid " and " #~ msgstr " et " #~ msgid "the following projects:
%s" #~ msgstr "les projets suivants :
%s" #~ msgid "Project..." #~ msgstr "Projet..." #~ msgid "Existing Spyder project" #~ msgstr "Projet Spyder existant" #~ msgid "Existing Pydev project" #~ msgstr "Projet Pydev existant" #~ msgid "Close unrelated projects" #~ msgstr "Fermer les projets non associés" #~ msgid "Edit related projects" #~ msgstr "Modifier les projets associés" #~ msgid "Add to PYTHONPATH" #~ msgstr "Ajouter à PYTHONPATH" #~ msgid "Remove from PYTHONPATH" #~ msgstr "Retirer de PYTHONPATH" #~ msgid "Properties" #~ msgstr "Propriétés" #~ msgid "" #~ "The workspace was unable to load or save %s

Please check if you " #~ "have the permission to write the associated configuration files." #~ msgstr "" #~ "L'espace de travail n'est pas parvenu à ouvrir ou enregistrer " #~ "%s

Veuillez vérifier que vous disposez bien des droits d'écriture " #~ "sur les fichiers de configuration associés." #~ msgid "Import directory" #~ msgstr "Importer un répertoire" #~ msgid "" #~ "The following directory is not in workspace:
%s

Do you " #~ "want to continue (and copy the directory to workspace)?" #~ msgstr "" #~ "Le répertoire suivant n'est pas dans l'espace de travail :
%s

Souhaitez-vous continuer (et copier ce répertoire dans l'espace " #~ "de travail) ?" #~ msgid "The project %s is already opened!" #~ msgstr "Le projet %s est déjà ouvert !" #~ msgid "" #~ "The project root path directory is inside the workspace but not as the " #~ "expected tree level. It is not a directory of the workspace:
%s" #~ msgstr "" #~ "Le répertoire racine du projet est bien à l'intérieur de l'espace de " #~ "travail mais pas au niveau d'arborescence attendu. Ce n'est pas un " #~ "répertoire de l'espace de travail :
%s" #~ msgid "A project named %s already exists" #~ msgstr "Un projet nommé %s existe déjà" #~ msgid "" #~ "Invalid project name.

Name must match the following regular " #~ "expression:
%s" #~ msgstr "" #~ "Nom de projet incorrect.

Le nom doit respecter l'expression " #~ "régulière suivante :
%s" #~ msgid "" #~ "The following directory is not empty:
%s

Do you want to " #~ "continue?" #~ msgstr "" #~ "Le répertoire suivant n'est pas vide :
%s

Souhaitez-vous " #~ "néanmoins continuer ?" #~ msgid "New project" #~ msgstr "Nouveau projet" #~ msgid "" #~ "The current workspace has not been configured yet.\n" #~ "Do you want to do this now?" #~ msgstr "" #~ "L'espace de travail n'a pas encore été défini.\n" #~ "Souhaitez-vous le faire maintenant ?" #~ msgid "Import existing project" #~ msgstr "Importer un projet existant" #~ msgid "Select projects to import" #~ msgstr "Sélectionner les projets à importer" #~ msgid "The folder %s does not contain a valid %s project" #~ msgstr "Le dossier %s ne contient pas de projet %s valide" #~ msgid "Import existing Pydev project" #~ msgstr "Importer un projet Pydev" #~ msgid "" #~ "Unable to read Pydev project %s

Error message:
%s" #~ msgstr "" #~ "Impossible d'ouvrir le projet Pydev %s

Message " #~ "d'erreur :
%s" #~ msgid "Select projects which are related to %s" #~ msgstr "Sélectionner les projets à associer à %s" #, fuzzy #~ msgid "" #~ "Statistics on source files only:
(Python, Cython, IPython, Enaml,C/C+" #~ "+, Fortran)

%s files.
%s lines of code." #~ msgstr "" #~ "Statistique sur les fichiers source uniquement:
(Python, C/C++, " #~ "Fortran)

%s fichiers.
%s lignes de code." #~ msgid "Select an existing workspace directory, or create a new one" #~ msgstr "Sélectionner un espace de travail existant, ou en créer un nouveau" #~ msgid "" #~ "What is the workspace?

A Spyder workspace is " #~ "a directory on your filesystem that contains Spyder projects and ." #~ "spyderworkspace configuration file.

A Spyder project is " #~ "a directory with source code (and other related files) and a " #~ "configuration file (named .spyderproject) with project settings " #~ "(PYTHONPATH, linked projects, ...).
" #~ msgstr "" #~ "Qu'est-ce que l'espace de travail ?

L'espace de " #~ "travail Spyder est un répertoire de votre système de fichiers qui " #~ "contient les projets Spyder et le fichier de configuration ." #~ "spyderworkspace.

Un projet Spyder est un répertoire " #~ "contenant du code source (et d'autres fichiers) ainsi qu'un fichier de " #~ "configuration (nommé .spyderproject) dans lequel sont stockés les " #~ "réglages du projet (PYTHONPATH, projets liés, ...).
" #~ msgid "This is the current workspace directory" #~ msgstr "Ceci est l'espace de travail actif" #~ msgid "" #~ "The following directory is not a Spyder workspace:
%s

Do you " #~ "want to create a new workspace in this directory?" #~ msgstr "" #~ "Le répertoire suivant n'est pas un espace de travail Spyder :
%s

Souhaitez-vous créer un nouvel espace de travail dans ce " #~ "répertoire ?" #~ msgid "Unable to retrieve data.

Error message:
%s" #~ msgstr "" #~ "Impossible d'accéder aux données

Message d'erreur :
%s" #~ msgid "Matched parentheses:" #~ msgstr "Parenthèse fermée :" #~ msgid "Unmatched parentheses:" #~ msgstr "Parenthèse non fermée :" #~ msgid "Set shell font style" #~ msgstr "Changer la police d'écriture de la console" #~ msgid "Text and margin font style" #~ msgstr "Police d'écriture du texte et de la marge" #~ msgid "tab" #~ msgstr "tabulation" #~ msgid "Breakpoints" #~ msgstr "Points d'arrêt" #~ msgid "Exit" #~ msgstr "Sortir" #~ msgid "Exit Debug" #~ msgstr "Quitter le débogage" #~ msgid "Rich text help on the Object Inspector" #~ msgstr "Texte enrichi dans l'inspecteur d'objets" #~ msgid "Object inspector" #~ msgstr "Inspecteur d'objets" #~ msgid "Preferences > Object Inspector" #~ msgstr "Préférences > Inspecteur d'objets" #~ msgid "Set as current console's working directory" #~ msgstr "Changer le répertoire de travail de la console actuelle" #~ msgid "Save session and quit..." #~ msgstr "Enregistrer la session et quitter..." #~ msgid "Loading object inspector..." #~ msgstr "Chargement de l'inspecteur d'objet..." #, fuzzy #~ msgid "The Object Inspector" #~ msgstr "Inspecteur d'objets" #~ msgid "(Experimental) Editor's code completion, go-to-definition and help" #~ msgstr "(Expérimental) : autocomplétion, aller à la définition, aide." #~ msgid "" #~ "This path is incorrect.\n" #~ "Enter a correct directory path,\n" #~ "then press enter to validate" #~ msgstr "" #~ "Ce chemin d'accès n'est pas valide :\n" #~ "veuillez entrer un chemin d'accès correct,\n" #~ "puis appuyer sur Entrée pour le valider" #~ msgid "Save Python script" #~ msgstr "Enregistrer le script Python" #~ msgid "PyQt" #~ msgstr "PyQt" #~ msgid "API selection for QString and QVariant objects:" #~ msgstr "Sélection de l'API des objets QString et QVariant :" #~ msgid "API #1" #~ msgstr "API n°1" #~ msgid "API #2" #~ msgstr "API n°2" #~ msgid "Default API" #~ msgstr "API par défaut" #~ msgid "" #~ "PyQt API #1 is the default
API for Python 2. PyQt API #2 is the " #~ "default API for Python 3 and is compatible with PySide." #~ msgstr "" #~ "L'API n°1 de PyQt est l'API par défaut pour Python 2. L'API n°2 est l'API " #~ "par défaut pour Python 3 : c'est l'API qui est compatible avec PySide." #~ msgid "Ignore API change errors (sip.setapi)" #~ msgstr "Ignorer les erreurs de changement d'API (sip.setapi)" #~ msgid "" #~ "Enabling this option will ignore
errors when changing PyQt API. As " #~ "PyQt does not support dynamic API changes, it is strongly recommended to " #~ "use this feature wisely, e.g. for debugging purpose." #~ msgstr "" #~ "L'activation de cette option permet d'ignorer les erreurs liées aux " #~ "changements\n" #~ "d'API de PyQt. Vu que PyQt ne prend pas en charge le changement " #~ "dynamique\n" #~ " d'API, il est fortement recommandé d'utiliser cette fonctionnalité " #~ "exceptionnellement,\n" #~ "par exemple pour du débogage." #~ msgid "Matplotlib" #~ msgstr "Matplotlib" #~ msgid "GUI backend:" #~ msgstr "Backend graphique :" #~ msgid "" #~ "Set the GUI toolkit used by
Matplotlib to show figures (default: " #~ "Qt4Agg)" #~ msgstr "" #~ "Spécifie la bibliothèque d'interfaces graphiques à utiliser pour " #~ "l'affichage des figures Matplotlib (par défaut : Qt4Agg)" #~ msgid "Mod1" #~ msgstr "Mod1" #~ msgid "Mod2" #~ msgstr "Mod2" #~ msgid "Mod3" #~ msgstr "Mod3" #, fuzzy #~ msgid "The Internal Console" #~ msgstr "Console interne" #~ msgid "File list management" #~ msgstr "Gestionnaire de fichiers" #~ msgid "Filter:" #~ msgstr "Filtre :" #~ msgid "(press Enter to edit file)" #~ msgstr "(appuyer sur Entrée pour modifier le fichier)" #~ msgid "&Edit file" #~ msgstr "Modifi&er le fichier" #~ msgid "&Close file" #~ msgstr "&Fermer le fichier" #~ msgid "Hint: press Alt to show accelerators" #~ msgstr "Astuce : la touche Alt affiche les accélérateurs" #~ msgid "Vertical dockwidget tabs" #~ msgstr "Onglets distribués verticalement" #~ msgid "Custom dockwidget margin:" #~ msgstr "Marges personnalisées :" #~ msgid "" #~ "Note: add analysis:ignore in a comment to ignore code/style " #~ "analysis warnings. For more informations on style guide for Python code, " #~ "please refer to the %s page." #~ msgstr "" #~ "Note: ajouter analysis:ignore dans un commentaire pour " #~ "ignorer les résultats de l'analyse de code ou de style. Pour plus " #~ "d'informations sur les recommandations officielles de style d'écriture " #~ "avec le langage Python, veuillez visiter la page de la %s." #~ msgid "Style analysis" #~ msgstr "Analyse de style" #~ msgid "Qt (PyQt/PySide)" #~ msgstr "Qt (PyQt/PySide)" #~ msgid "Use a completion widget" #~ msgstr "Utiliser un widget de complétion de code" #~ msgid "Use a widget instead of plain text output for tab completion" #~ msgstr "Utiliser un widget de complétion au lieu d'une liste en texte brut" #~ msgid "Switch to/from layout %d" #~ msgstr "Basculer vers/depuis la disposition %d" #~ msgid "Set layout %d" #~ msgstr "Définir la disposition %d" #~ msgid "" #~ "%s will be closed.\n" #~ "Do you want to kill the associated kernel and all of its clients?" #~ msgstr "" #~ "%s va être fermé.\n" #~ "Souhaitez-vous fermer également le noyau associé et tous ses autres " #~ "clients ?" #~ msgid "Install Spyder's input hook for Qt" #~ msgstr "Installer le \"input hook\" de Spyder pour Qt" #~ msgid "" #~ "PyQt installs an input hook that allows
creating and interacting with " #~ "Qt widgets in an interactive console without blocking it. On Windows " #~ "platforms, it is strongly recommended to replace it by Spyder's. " #~ "Regarding PySide, note that it does not install an input hook, so it is " #~ "required to enable this feature in order to be able to manipulate PySide/" #~ "Qtobjects interactively." #~ msgstr "" #~ "PyQt installe un \"input hook\", mécanisme permettant d'interagir avec " #~ "des widgets Qt dans une console Python sans bloquer cette dernière. Sous " #~ "Windows, il est fortement conseillé de le remplacer par celui de Spyder. " #~ "Concernant PySide, aucun \"input hook\" n'étant implémenté, il est " #~ "également recommandé d'activer cette option pour pouvoir manipuler des " #~ "objets Qt de manière interactive." #~ msgid "Could not open ssh tunnel\n" #~ msgstr "Impossible d'ouvrir un tunnel ssh\n" #~ msgid "Mismatch between kernel and frontend" #~ msgstr "Incompatibilité entre le noyau et l'interface" #~ msgid "" #~ "Your IPython frontend and kernel versions are incompatible!!

We're sorry but we can't create an IPython console for you." #~ msgstr "" #~ "Les versions d'IPython de votre noyau et de l'interface sont " #~ "incompatibles !

Nous sommes désolés, mais nous ne pouvons " #~ "pas vous ouvrir une console IPython." #~ msgid "Always edit in-place" #~ msgstr "Édition en ligne pour tous les types" #~ msgid "Show collection contents" #~ msgstr "Afficher le contenu des séquences" #~ msgid "" #~ "Resizing cells of a table of such size could take a long time.\n" #~ "Do you want to continue anyway?" #~ msgstr "" #~ "Redimensionner les cellules d'un tableau d'une telle taille peut prendre " #~ "du temps.\n" #~ "Souhaitez-vous néanmoins continuer ?" #~ msgid "Interrupt kernel" #~ msgstr "Interrompre le noyau" #~ msgid "Run &selection" #~ msgstr "Exécuter la &sélection" #~ msgid "Patch Matplotlib figures" #~ msgstr "Patcher les figures Matplotlib" #~ msgid "" #~ "Patching Matplotlib library will add a button to customize figure options " #~ "(Qt4Agg only) and fix some issues." #~ msgstr "" #~ "Appliquer un patch à la bibliothèque Matplotlib permet d'ajouter un " #~ "bouton (au backend Qt4Agg) pour modifier les options des courbes et " #~ "images affichées et de corriger quelques bogues." #~ msgid "(for example: kernel-3764.json, or simply 3764)" #~ msgstr "(exemple: `kernel-3764.json`, ou simplement `3764`)" #~ msgid "Provide an IPython kernel connection file:" #~ msgstr "Fichier de connexion du noyau IPython :" #~ msgid "Interpreter" #~ msgstr "Interpréteur" #~ msgid "Dedicated Python interpreter" #~ msgstr "Interpréteur Python dédié" #~ msgid "Open Python interpreter here" #~ msgstr "Ouvrir un interpréteur Python ici" #~ msgid "Import as array" #~ msgstr "Importer en tant que tableau" #~ msgid "(not installed)" #~ msgstr "(non installé)" #~ msgid "Show single completion" #~ msgstr "Afficher les listes de complétion avec un choix unique" #~ msgid "Open a Python interpreter at startup" #~ msgstr "Ouvrir un interpréteur Python au démarrage" #~ msgid "Open an IPython console at startup" #~ msgstr "Ouvrir une console IPython au démarrage" #~ msgid "Close current plugin" #~ msgstr "Fermer la fenêtre courante" #~ msgid "Windows" #~ msgstr "Fenêtres" #, fuzzy #~ msgid "Plugins" #~ msgstr " lignes" #~ msgid "Web resources" #~ msgstr "Ressources en ligne" #, fuzzy #~ msgid "Qt help" #~ msgstr "Aide Qt" #, fuzzy #~ msgid "IPython help" #~ msgstr "Aide Python :" #~ msgid "Balloon tips" #~ msgstr "Info-bulles" #~ msgid "Close current dockwidget" #~ msgstr "Fermer le panneau actif" #~ msgid "IPython Help" #~ msgstr "Aide IPython" #~ msgid "Windows and toolbars" #~ msgstr "Fenêtres et barres d'outils" #~ msgid "Automatic notification to object inspector" #~ msgstr "Notification automatique à l'inspecteur d'objets" #~ msgid "" #~ "If this option is enabled, object inspector\n" #~ "will automatically show informations on functions\n" #~ "entered in editor (this is triggered when entering\n" #~ "a left parenthesis after a valid function name)" #~ msgstr "" #~ "Si cette option est activée, l'inspecteur d'objet\n" #~ "affichera automatiquement des informations\n" #~ "sur les fonctions saisies dans l'éditeur\n" #~ "(le mécanisme est déclenché par la saisie d'une\n" #~ "parenthèse gauche après un nom valide de fonction)" #~ msgid "Create a new Python script" #~ msgstr "Créer un nouveau script Python" #~ msgid "Open text file" #~ msgstr "Ouvrir un fichier texte" #~ msgid "" #~ "Run current cell \n" #~ "(see Editor documentation \n" #~ "for more details on cells)" #~ msgstr "" #~ "Exécuter la cellule en cours d'édition\n" #~ "(voir la documentation de l'Editeur, pour plus de détails sur les " #~ "cellules)" #~ msgid "" #~ "If this option is enabled, object inspector\n" #~ "will automatically show informations on functions\n" #~ "entered in console (this is triggered when entering\n" #~ "a left parenthesis after a valid function name)" #~ msgstr "" #~ "Si cette option est activée, l'inspecteur d'objet affichera " #~ "automatiquement des informations sur les fonctions saisies dans la " #~ "console (le mécanisme est déclenché par la saisie d'une parenthèse gauche " #~ "après un nom valide de fonction)" #~ msgid "Open a Python &interpreter" #~ msgstr "Ouvrir un &interpréteur Python" #~ msgid "
Installed version: %s" #~ msgstr "
Version installée: %s" #~ msgid "" #~ "Unable to open IPython console because no supported IPython version was " #~ "found.

Supported IPython versions: %s" #~ msgstr "" #~ "Impossible d'ouvrir une console IPython car aucune version prise en " #~ "charge n'est installée.

Versions IPython prises en charge: " #~ "%s" #~ msgid "&Interpreters" #~ msgstr "&Interpréteurs" #~ msgid "Open Spyder path manager" #~ msgstr "Ouvre le gestionnaire de chemin d'accès de Spyder" #~ msgid "Qt Assistant" #~ msgstr "Qt Assistant (documentation Qt)" #~ msgid "Maximize current plugin to fit the whole application window" #~ msgstr "" #~ "Agrandir la fenêtre courante sur toute la surface de la fenêtre principale" #~ msgid "" #~ "Restore current plugin to its original size and position within the " #~ "application window" #~ msgstr "" #~ "Réduire la fenêtre courante à sa taille et position d'origine au sein de " #~ "la fenêtre principale" #~ msgid "" #~ "Run current block \n" #~ "(see Editor section in documentation \n" #~ "for more details on blocks) \n" #~ "and advance to the next block" #~ msgstr "" #~ "Exécuter le bloc (voir la section 'Editor' de la documentation) \n" #~ "et avancer jusqu'au bloc suivant" #~ msgid "Version" #~ msgstr "Version" #~ msgid "Status" #~ msgstr "Etat" #~ msgid "" #~ "This feature requires the pywin32 module.\n" #~ "It seems you don't have it installed." #~ msgstr "" #~ "Cette fonctionnalité nécessite l'installation du module pywin32.\n" #~ "Ce dernier n'est apparemment pas installé." #~ msgid "Step Over" #~ msgstr "Pas en avant" #~ msgid "" #~ "Run selection or current \n" #~ "block of lines" #~ msgstr "Exécuter la sélection ou le bloc de lignes" #~ msgid "Debug current script in selected console" #~ msgstr "Déboguer le script courant dans la console sélectionnée" #~ msgid "Debug Step Over" #~ msgstr "Pas en avant (débogage)" #~ msgid "Debug Continue" #~ msgstr "Continuer (débogage)" #~ msgid "Debug Step Into" #~ msgstr "Pas vers l'intérieur (débogage)" #~ msgid "Debug Step Return" #~ msgstr "Pas vers l'extérieur (débogage)" #~ msgid "" #~ "Run selected script in\n" #~ "current console" #~ msgstr "Exécuter le script sélectionné dans la console courante" #~ msgid "Edit Run settings" #~ msgstr "Modifier les options d'exécution" #~ msgid "" #~ "Run again last script in current\n" #~ "console with the same options" #~ msgstr "" #~ "Exécuter de nouveau le dernier script dans la console courante avec les " #~ "mêmes options" #~ msgid "" #~ "Run selected text or current block\n" #~ "of lines inside current console" #~ msgstr "" #~ "Exécuter le texte sélectionné ou le bloc de lignes \n" #~ "dans l'interpréteur de la console courante" #~ msgid "Run active script in a new Python interpreter" #~ msgstr "Exécuter le script actuel dans un nouvel interpréteur Python" #~ msgid "" #~ "Debug current script in external console\n" #~ "(external console is executed in a separate process)" #~ msgstr "" #~ "Déboguer le script en cours d'édition dans la console externe\n" #~ "(la console externe est exécutée dans un processus séparé)" #~ msgid "Edit run configurations" #~ msgstr "Modifier les configurations d'exécution des scripts récents" #~ msgid "Run %s" #~ msgstr "Exécution de %s" #~ msgid "Run configurations" #~ msgstr "Configurations d'exécution" #~ msgid "Type \"copyright\", \"credits\" or \"license\" for more information." #~ msgstr "" #~ "Type \"copyright\", \"credits\" or \"license\" for more information." #~ msgid "Start an IPython kernel at startup" #~ msgstr "Démarrer un noyau IPython au démarrage" #~ msgid "This option is not available for IPython versions prior to v0.12." #~ msgstr "" #~ "Cette option est désactivée pour les versions de IPython antérieures à " #~ "v0.12." #, fuzzy #~ msgid "Format: " #~ msgstr "Format" #, fuzzy #~ msgid " Source" #~ msgstr "Source" #~ msgid "Open &interpreter" #~ msgstr "Ouvrir un &interpréteur" #~ msgid "Start a new IPython kernel" #~ msgstr "Démarrer un nouveau noyau IPython" #~ msgid "Client" #~ msgstr "Client" #~ msgid "New IPython client..." #~ msgstr "Nouveau client IPython..." #~ msgid "Qt" #~ msgstr "Qt" #~ msgid "OS X" #~ msgstr "OS X" #~ msgid "Gtk" #~ msgstr "Gtk" #~ msgid "Wx" #~ msgstr "Wx" #~ msgid "Tkinter" #~ msgstr "Tkinter" #~ msgid "IPython kernels" #~ msgstr "Noyaux IPython" #~ msgid "" #~ "Note:
IPython >=v0.12 is not installed on this computer." #~ msgstr "" #~ "Note :
IPython >=v0.12 n'est pas installé sur cet " #~ "ordinateur." #~ msgid "Set the appropriate IPython color option" #~ msgstr "Utiliser le réglage de couleur IPython approprié" #~ msgid "Open an IPython interpreter at startup" #~ msgstr "Ouvrir un interpréteur IPython au démarrage" #~ msgid "" #~ "This option is not available for IPython\n" #~ "versions which are not fully supported\n" #~ "through Spyder's console (i.e. IPython v0.11+)." #~ msgstr "" #~ "Cette option est désactivée pour les versions de IPython\n" #~ "qui ne sont entièrement prises en charge par Spyder\n" #~ "à travers la console (i.e. IPython v0.11+)." #~ msgid "IPython interpreter command line options" #~ msgstr "IPython : options en ligne de commande" #~ msgid "Open an IPython interpreter" #~ msgstr "Ouvrir un interpréteur IPython" #~ msgid "Open IPython here" #~ msgstr "Ouvrir IPython ici" #~ msgid "Please install the %s tool named '%s'" #~ msgstr "Merci d'installer l'outil %s appelé '%s'" #~ msgid "Replace PyQt input hook by Spyder's" #~ msgstr "Remplacer le \"input hook\" de PyQt par celui de Spyder" #~ msgid "What is the workspace?" #~ msgstr "Qu'est-ce que l'espace de travail ?" #~ msgid "" #~ "A Spyder project is a folder with source code files (and any other kind " #~ "of related files) and a configuration file (named .spyderproject) " #~ "which stores the project settings (PYTHONPATH, related projects, ...)." #~ "

The workspace is a directory, which contains Spyder projects " #~ "(top level subdirectories) and a configuration file (named ." #~ "spyderworkspace). " #~ msgstr "" #~ "Un projet Spyder est un répertoire contenant des fichiers source (et tout " #~ "autre type de fichier) et un fichier de configuration (nommé ." #~ "spyderproject) qui stocke les paramètres du projet (PYTHONPATH, " #~ "projets associés, etc.).

L'espace de travail est un répertoire " #~ "contenant des projets Spyder (sous-répertoires uniquement) et un " #~ "fichier de configuration (nommé .spyderworkspace)." #~ msgid "Matplotlib backend (default: Qt4Agg):" #~ msgstr "Backend Matplotlib (valeur par défaut: Qt4Agg) :" #~ msgid "ETS_TOOLKIT (default value: qt4):" #~ msgstr "ETS_TOOLKIT (valeur par défaut: qt4) :" #~ msgid "&Interact" #~ msgstr "&Interagir" #~ msgid "" #~ "The project explorer shows a tree view of projects: the root of this tree " #~ "is called the workspace.

Each project is associated to a simple " #~ "source code folder containing a configuration file (named ." #~ "spyderproject) which stores the project settings (PYTHONPATH, related " #~ "projects, ...). The workspace is also associated to a folder containing a " #~ "configuration file (named .spyderworkspace) and the folders " #~ "associated to its projects.

In other words, the workspace is " #~ "nothing but a list of projects whose associated folder share the same " #~ "parent directory." #~ msgstr "" #~ "L'explorateur de projet affiche une arborescence de projets dont la " #~ "racine est appelée l'espace de travail.

Chaque projet est associé " #~ "à un simple dossier de code source contenant un fichier de configuration " #~ "(nommé .spyderproject) qui stocke les paramètres du projet " #~ "(PYTHONPATH, projets associés, etc.). L'espace de travail est aussi " #~ "associé à un dossier qui contient un fichier de configuration (nommé ." #~ "spyderworkspace) et tous les dossiers associés à ses projets." #~ "

En d'autres termes, l'espace de travail est simplement une liste " #~ "de projets dont les dossiers associés ont le même répertoire parent." #~ msgid "Create a new workspace directory" #~ msgstr "Créer un nouvel espace de travail" #~ msgid "New folder..." #~ msgstr "Nouveau répertoire..." #~ msgid "New file..." #~ msgstr "Nouveau fichier..." #~ msgid "Unable to delete selected file

Error message:
%s" #~ msgstr "" #~ "Impossible de supprimer le fichier sélectionné

Message " #~ "d'erreur :
%s" #~ msgid "Unable to rename selected file

Error message:
%s" #~ msgstr "" #~ "Impossible de renommer le fichier sélectionné

Message " #~ "d'erreur :
%s" #~ msgid "Folder name" #~ msgstr "Nom du répertoire" #~ msgid "Select project root path" #~ msgstr "Sélectionner la racine du projet" #~ msgid "Edit filename filter" #~ msgstr "Modifier le filtre des types de fichier affichés" #~ msgid "regular expressions" #~ msgstr "expressions régulières" #~ msgid "global patterns" #~ msgstr "syntaxe globale" #~ msgid "Include" #~ msgstr "Inclure" #~ msgid "Exclude" #~ msgstr "Exclure" #~ msgid "Warning:" #~ msgstr "Attention :" #~ msgid "" #~ "%s is not properly installed
(opening a terminal and typing " #~ "\"%s script.py\" do not work)" #~ msgstr "" #~ "%s n'est pas installé correctement
(l'exécution dans un " #~ "terminal de \"%s script.py\" ne fonctionne pas)" #~ msgid "More informations on style guide for Python code: %s." #~ msgstr "" #~ "Pour plus d'informations sur les recommandations de style d'écriture du " #~ "langage Python : %s." #~ msgid "unknown" #~ msgstr "inconnu" #~ msgid "Startup script:" #~ msgstr "Script de démarrage :" #~ msgid "Print" #~ msgstr "Impression" #~ msgid "Unable to print document '%s'" #~ msgstr "Impossible d'imprimer le document '%s'" #~ msgid "Co&mment" #~ msgstr "Co&mmenter" #~ msgid "&Uncomment" #~ msgstr "&Décommenter" #~ msgid "Uncomment current line or selection" #~ msgstr "Décommenter la sélection ou la ligne en cours d'édition" #~ msgid "Please install matplotlib." #~ msgstr "Merci d'installer matplotlib." #~ msgid "" #~ "Remote editing for NumPy arrays, PIL images, lists, tuples and " #~ "dictionaries" #~ msgstr "" #~ "Les tableaux NumPy, images PIL, listes, tuples et dictionnaires seront " #~ "modifiés dans un éditeur exécuté dans le processus distant" #~ msgid "" #~ "Editors are opened in the remote process for NumPy arrays, PIL images, " #~ "lists, tuples and dictionaries" #~ msgstr "" #~ "Les tableaux NumPy, images PIL, listes, tuples et dictionnaires seront " #~ "modifiés dans un éditeur exécuté dans le processus distant" #~ msgid "Open..." #~ msgstr "Ouvrir..." #~ msgid "Close" #~ msgstr "Fermer" #~ msgid "Add block comment" #~ msgstr "Ajouter un bloc de commentaires" #~ msgid "Remove block comment" #~ msgstr "Supprimer un bloc de commentaires" #~ msgid "Save all" #~ msgstr "Enregistrer tout" #~ msgid "Print..." #~ msgstr "Imprimer..." #~ msgid "Close file" #~ msgstr "Fermer le fichier" #~ msgid "Show TODO/FIXME/XXX comments list" #~ msgstr "Afficher la liste des commentaires du type TODO/FIXME/XXX" #~ msgid "Configure..." #~ msgstr "Configurer..." #~ msgid "Previous file" #~ msgstr "Fichier précédent" #~ msgid "Next file" #~ msgstr "Fichier suivant" #~ msgid "Revert" #~ msgstr "Réinitialiser" #~ msgid "Add &block comment around current line or selection" #~ msgstr "" #~ "Ajouter un &bloc de commentaires autour de la sélection ou de la ligne en " #~ "cours d'édition" #~ msgid "Tasks (TODO, FIXME, XXX)" #~ msgstr "Tâches (TODO, FIXME, XXX)" #~ msgid "" #~ "IPython interpreter command line options:\n" #~ "(Qt4 support: -q4thread)\n" #~ "(Qt4 and matplotlib support: -q4thread -pylab)" #~ msgstr "" #~ "Options en ligne de commande de IPython :\n" #~ "(support Qt4 : -q4thread)\n" #~ "(support Qt4 et matplotlib : -q4thread -pylab)" #~ msgid "" #~ "PyQt installs an input hook that processes events when an interactive " #~ "interpreter is waiting for user input, thus allowing to interact with " #~ "widgets without blocking the Python shell. Unfortunately, this is not " #~ "working well on Windows platforms." #~ msgstr "" #~ "PyQt installe un mécanisme (\"input hook\") qui permet d'interagir avec " #~ "des widgets dans un interpréteur Python sans bloquer ce dernier. " #~ "Malheureusement, ce mécanisme ne fonctionne pas parfaitement sous Windows." #~ msgid "Replace text" #~ msgstr "Remplacer" #~ msgid "Find next" #~ msgstr "Rechercher le suivant" #~ msgid "Find previous" #~ msgstr "Rechercher le précédent" #~ msgid "Edit filename filter..." #~ msgstr "Modifier le filtre des types de fichier affichés" spyder-3.2.6/spyder/pil_patch.py0000664000175000017500000000435013026261006017443 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Patching PIL (Python Imaging Library) to avoid triggering the error: AccessInit: hash collision: 3 for both 1 and 1 This error is occuring because of a bug in the PIL import mechanism. How to reproduce this bug in a standard Python interpreter outside Spyder? By importing PIL by two different mechanisms Example on Windows: =============================================================================== C:\Python27\Lib\site-packages>python Python 2.7.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import Image >>> from PIL import Image AccessInit: hash collision: 3 for both 1 and 1 =============================================================================== Another example on Windows (actually that's the same, but this is the exact case encountered with Spyder when the global working directory is the site-packages directory): =============================================================================== C:\Python27\Lib\site-packages>python Python 2.7.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import scipy >>> from pylab import * AccessInit: hash collision: 3 for both 1 and 1 =============================================================================== The solution to this fix is the following patch: =============================================================================== C:\Python27\Lib\site-packages>python Python 2.7.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit (Intel)] on win 32 Type "help", "copyright", "credits" or "license" for more information. >>> import Image >>> import PIL >>> PIL.Image = Image >>> from PIL import Image >>> =============================================================================== """ try: # For Pillow compatibility from PIL import Image import PIL PIL.Image = Image except ImportError: # For PIL import Image import PIL PIL.Image = Image spyder-3.2.6/spyder/plugins/0000775000175000017500000000000013225025007016605 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/plugins/variableexplorer.py0000664000175000017500000001640213224740762022543 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Variable Explorer Plugin""" # Third party imports from qtpy.QtCore import Signal, Slot from qtpy.QtWidgets import QGroupBox, QStackedWidget, QVBoxLayout, QWidget # Local imports from spyder.config.base import _ from spyder.plugins import SpyderPluginMixin from spyder.plugins.configdialog import PluginConfigPage from spyder.utils import icon_manager as ima from spyder.widgets.variableexplorer.namespacebrowser import NamespaceBrowser from spyder.widgets.variableexplorer.utils import REMOTE_SETTINGS class VariableExplorerConfigPage(PluginConfigPage): def setup_page(self): filter_group = QGroupBox(_("Filter")) filter_data = [ ('exclude_private', _("Exclude private references")), ('exclude_capitalized', _("Exclude capitalized references")), ('exclude_uppercase', _("Exclude all-uppercase references")), ('exclude_unsupported', _("Exclude unsupported data types")), ] filter_boxes = [self.create_checkbox(text, option) for option, text in filter_data] display_group = QGroupBox(_("Display")) display_data = [('minmax', _("Show arrays min/max"), '')] display_boxes = [self.create_checkbox(text, option, tip=tip) for option, text, tip in display_data] filter_layout = QVBoxLayout() for box in filter_boxes: filter_layout.addWidget(box) filter_group.setLayout(filter_layout) display_layout = QVBoxLayout() for box in display_boxes: display_layout.addWidget(box) display_group.setLayout(display_layout) vlayout = QVBoxLayout() vlayout.addWidget(filter_group) vlayout.addWidget(display_group) vlayout.addStretch(1) self.setLayout(vlayout) class VariableExplorer(QWidget, SpyderPluginMixin): """ Variable Explorer Plugin """ CONF_SECTION = 'variable_explorer' CONFIGWIDGET_CLASS = VariableExplorerConfigPage sig_option_changed = Signal(str, object) def __init__(self, parent): QWidget.__init__(self, parent) SpyderPluginMixin.__init__(self, parent) # Widgets self.stack = QStackedWidget(self) self.shellwidgets = {} # Layout layout = QVBoxLayout() layout.addWidget(self.stack) self.setLayout(layout) # Initialize plugin self.initialize_plugin() def get_settings(self): """ Retrieve all Variable Explorer configuration settings. Specifically, return the settings in CONF_SECTION with keys in REMOTE_SETTINGS, and the setting 'dataframe_format'. Returns: dict: settings """ settings = {} for name in REMOTE_SETTINGS: settings[name] = self.get_option(name) # dataframe_format is stored without percent sign in config # to avoid interference with ConfigParser's interpolation name = 'dataframe_format' settings[name] = '%{0}'.format(self.get_option(name)) return settings @Slot(str, object) def change_option(self, option_name, new_value): """ Change a config option. This function is called if sig_option_changed is received. If the option changed is the dataframe format, then the leading '%' character is stripped (because it can't be stored in the user config). Then, the signal is emitted again, so that the new value is saved in the user config. """ if option_name == 'dataframe_format': assert new_value.startswith('%') new_value = new_value[1:] self.sig_option_changed.emit(option_name, new_value) # ----- Stack accesors ---------------------------------------------------- def set_current_widget(self, nsb): self.stack.setCurrentWidget(nsb) def current_widget(self): return self.stack.currentWidget() def count(self): return self.stack.count() def remove_widget(self, nsb): self.stack.removeWidget(nsb) def add_widget(self, nsb): self.stack.addWidget(nsb) # ----- Public API -------------------------------------------------------- def add_shellwidget(self, shellwidget): """ Register shell with variable explorer. This function opens a new NamespaceBrowser for browsing the variables in the shell. """ shellwidget_id = id(shellwidget) if shellwidget_id not in self.shellwidgets: nsb = NamespaceBrowser(self) nsb.set_shellwidget(shellwidget) nsb.setup(**self.get_settings()) nsb.sig_option_changed.connect(self.change_option) self.add_widget(nsb) self.shellwidgets[shellwidget_id] = nsb self.set_shellwidget_from_id(shellwidget_id) return nsb def remove_shellwidget(self, shellwidget_id): # If shellwidget_id is not in self.shellwidgets, it simply means # that shell was not a Python-based console (it was a terminal) if shellwidget_id in self.shellwidgets: nsb = self.shellwidgets.pop(shellwidget_id) self.remove_widget(nsb) nsb.close() def set_shellwidget_from_id(self, shellwidget_id): if shellwidget_id in self.shellwidgets: nsb = self.shellwidgets[shellwidget_id] self.set_current_widget(nsb) def import_data(self, fname): """Import data in current namespace""" if self.count(): nsb = self.current_widget() nsb.refresh_table() nsb.import_data(filenames=fname) if self.dockwidget and not self.ismaximized: self.dockwidget.setVisible(True) self.dockwidget.raise_() #------ SpyderPluginWidget API --------------------------------------------- def get_plugin_title(self): """Return widget title""" return _('Variable explorer') def get_plugin_icon(self): """Return plugin icon""" return ima.icon('dictedit') def get_focus_widget(self): """ Return the widget to give focus to when this plugin's dockwidget is raised on top-level """ return self.current_widget() def closing_plugin(self, cancelable=False): """Perform actions before parent main window is closed""" return True def refresh_plugin(self): """Refresh widget""" pass def get_plugin_actions(self): """Return a list of actions related to plugin""" return [] def register_plugin(self): """Register plugin in Spyder's main window""" self.main.add_dockwidget(self) def apply_plugin_settings(self, options): """Apply configuration file's plugin settings""" for nsb in list(self.shellwidgets.values()): nsb.setup(**self.get_settings()) spyder-3.2.6/spyder/plugins/maininterpreter.py0000664000175000017500000002535313224121062022374 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Shortcut management""" # Standard library imports from __future__ import print_function import os import os.path as osp import sys # Third party imports from qtpy.QtWidgets import (QButtonGroup, QGroupBox, QInputDialog, QLabel, QLineEdit, QMessageBox, QPushButton, QVBoxLayout) # Local imports from spyder.config.base import _ from spyder.plugins.configdialog import GeneralConfigPage from spyder.py3compat import PY2, is_text_string, to_text_string from spyder.utils import icon_manager as ima from spyder.utils.misc import get_python_executable from spyder.utils import programs class MainInterpreterConfigPage(GeneralConfigPage): CONF_SECTION = "main_interpreter" NAME = _("Python interpreter") ICON = ima.icon('python') def __init__(self, parent, main): GeneralConfigPage.__init__(self, parent, main) self.cus_exec_radio = None self.pyexec_edit = None # Python executable selection (initializing default values as well) executable = self.get_option('executable', get_python_executable()) if self.get_option('default'): executable = get_python_executable() if not osp.isfile(executable): # This is absolutely necessary, in case the Python interpreter # executable has been moved since last Spyder execution (following # a Python distribution upgrade for example) self.set_option('executable', get_python_executable()) elif executable.endswith('pythonw.exe'): # That should not be necessary because this case is already taken # care of by the `get_python_executable` function but, this was # implemented too late, so we have to fix it here too, in case # the Python executable has already been set with pythonw.exe: self.set_option('executable', executable.replace("pythonw.exe", "python.exe")) def initialize(self): GeneralConfigPage.initialize(self) self.pyexec_edit.textChanged.connect(self.python_executable_changed) self.cus_exec_radio.toggled.connect(self.python_executable_switched) def setup_page(self): newcb = self.create_checkbox # Python executable Group pyexec_group = QGroupBox(_("Python interpreter")) pyexec_bg = QButtonGroup(pyexec_group) pyexec_label = QLabel(_("Select the Python interpreter for all Spyder " "consoles")) def_exec_radio = self.create_radiobutton( _("Default (i.e. the same as Spyder's)"), 'default', button_group=pyexec_bg) self.cus_exec_radio = self.create_radiobutton( _("Use the following Python interpreter:"), 'custom', button_group=pyexec_bg) if os.name == 'nt': filters = _("Executables")+" (*.exe)" else: filters = None pyexec_file = self.create_browsefile('', 'executable', filters=filters) for le in self.lineedits: if self.lineedits[le][0] == 'executable': self.pyexec_edit = le def_exec_radio.toggled.connect(pyexec_file.setDisabled) self.cus_exec_radio.toggled.connect(pyexec_file.setEnabled) pyexec_layout = QVBoxLayout() pyexec_layout.addWidget(pyexec_label) pyexec_layout.addWidget(def_exec_radio) pyexec_layout.addWidget(self.cus_exec_radio) pyexec_layout.addWidget(pyexec_file) pyexec_group.setLayout(pyexec_layout) # UMR Group umr_group = QGroupBox(_("User Module Reloader (UMR)")) umr_label = QLabel(_("UMR forces Python to reload modules which were " "imported when executing a file in a Python or " "IPython console with the runfile " "function.")) umr_label.setWordWrap(True) umr_enabled_box = newcb(_("Enable UMR"), 'umr/enabled', msg_if_enabled=True, msg_warning=_( "This option will enable the User Module Reloader (UMR) " "in Python/IPython consoles. UMR forces Python to " "reload deeply modules during import when running a " "Python script using the Spyder's builtin function " "runfile." "

1. UMR may require to restart the " "console in which it will be called " "(otherwise only newly imported modules will be " "reloaded when executing files)." "

2. If errors occur when re-running a " "PyQt-based program, please check that the Qt objects " "are properly destroyed (e.g. you may have to use the " "attribute Qt.WA_DeleteOnClose on your main " "window, using the setAttribute method)"), ) umr_verbose_box = newcb(_("Show reloaded modules list"), 'umr/verbose', msg_info=_( "Please note that these changes will " "be applied only to new consoles")) umr_namelist_btn = QPushButton( _("Set UMR excluded (not reloaded) modules")) umr_namelist_btn.clicked.connect(self.set_umr_namelist) umr_layout = QVBoxLayout() umr_layout.addWidget(umr_label) umr_layout.addWidget(umr_enabled_box) umr_layout.addWidget(umr_verbose_box) umr_layout.addWidget(umr_namelist_btn) umr_group.setLayout(umr_layout) vlayout = QVBoxLayout() vlayout.addWidget(pyexec_group) vlayout.addWidget(umr_group) vlayout.addStretch(1) self.setLayout(vlayout) def python_executable_changed(self, pyexec): """Custom Python executable value has been changed""" if not self.cus_exec_radio.isChecked(): return def_pyexec = get_python_executable() if not is_text_string(pyexec): pyexec = to_text_string(pyexec.toUtf8(), 'utf-8') if pyexec == def_pyexec: return if (not programs.is_python_interpreter(pyexec) or not self.warn_python_compatibility(pyexec)): QMessageBox.warning(self, _('Warning'), _("You selected an invalid Python interpreter for the " "console so the previous interpreter will stay. Please " "make sure to select a valid one."), QMessageBox.Ok) self.pyexec_edit.setText(def_pyexec) return def python_executable_switched(self, custom): """Python executable default/custom radio button has been toggled""" if custom: self.python_executable_changed(self.pyexec_edit.text()) def warn_python_compatibility(self, pyexec): if not osp.isfile(pyexec): return spyder_version = sys.version_info[0] try: args = ["-c", "import sys; print(sys.version_info[0])"] proc = programs.run_program(pyexec, args) console_version = int(proc.communicate()[0]) except IOError: console_version = spyder_version except ValueError: return False if spyder_version != console_version: QMessageBox.warning(self, _('Warning'), _("You selected a Python %d interpreter for the console " "but Spyder is running on Python %d!.

" "Although this is possible, we recommend you to install and " "run Spyder directly with your selected interpreter, to avoid " "seeing false warnings and errors due to the incompatible " "syntax between these two Python versions." ) % (console_version, spyder_version), QMessageBox.Ok) return True def set_umr_namelist(self): """Set UMR excluded modules name list""" arguments, valid = QInputDialog.getText(self, _('UMR'), _("Set the list of excluded modules as " "this: numpy, scipy"), QLineEdit.Normal, ", ".join(self.get_option('umr/namelist'))) if valid: arguments = to_text_string(arguments) if arguments: namelist = arguments.replace(' ', '').split(',') fixed_namelist = [] non_ascii_namelist = [] for module_name in namelist: if PY2: if all(ord(c) < 128 for c in module_name): if programs.is_module_installed(module_name): fixed_namelist.append(module_name) else: QMessageBox.warning(self, _('Warning'), _("You are working with Python 2, this means that " "you can not import a module that contains non-" "ascii characters."), QMessageBox.Ok) non_ascii_namelist.append(module_name) elif programs.is_module_installed(module_name): fixed_namelist.append(module_name) invalid = ", ".join(set(namelist)-set(fixed_namelist)- set(non_ascii_namelist)) if invalid: QMessageBox.warning(self, _('UMR'), _("The following modules are not " "installed on your machine:\n%s" ) % invalid, QMessageBox.Ok) QMessageBox.information(self, _('UMR'), _("Please note that these changes will " "be applied only to new Python/IPython " "consoles"), QMessageBox.Ok) else: fixed_namelist = [] self.set_option('umr/namelist', fixed_namelist) def apply_settings(self, options): self.main.apply_settings() spyder-3.2.6/spyder/plugins/layoutdialog.py0000664000175000017500000002741213026261006021662 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Layout dialogs""" # Standard library imports import sys # Third party imports from qtpy.QtCore import QAbstractTableModel, QModelIndex, QSize, Qt from qtpy.compat import from_qvariant, to_qvariant from qtpy.QtWidgets import (QAbstractItemView, QComboBox, QDialog, QDialogButtonBox, QGroupBox, QHBoxLayout, QPushButton, QTableView, QVBoxLayout) # Local imports from spyder.config.base import _ from spyder.py3compat import to_text_string class LayoutModel(QAbstractTableModel): """ """ def __init__(self, parent, order, active): super(LayoutModel, self).__init__(parent) # variables self._parent = parent self.order = order self.active = active self._rows = [] self.set_data(order, active) def set_data(self, order, active): """ """ self._rows = [] self.order = order self.active = active for name in order: if name in active: row = [name, True] else: row = [name, False] self._rows.append(row) def flags(self, index): """Override Qt method""" if not index.isValid(): return Qt.ItemIsEnabled column = index.column() if column in [0]: return Qt.ItemFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEditable) else: return Qt.ItemFlags(Qt.ItemIsEnabled) def data(self, index, role=Qt.DisplayRole): """Override Qt method""" if not index.isValid() or not 0 <= index.row() < len(self._rows): return to_qvariant() row = index.row() column = index.column() name, state = self.row(row) if role == Qt.DisplayRole or role == Qt.EditRole: if column == 0: return to_qvariant(name) elif role == Qt.CheckStateRole: if column == 0: if state: return Qt.Checked else: return Qt.Unchecked if column == 1: return to_qvariant(state) return to_qvariant() def setData(self, index, value, role): """Override Qt method""" row = index.row() name, state = self.row(row) if role == Qt.CheckStateRole: self.set_row(row, [name, not state]) self._parent.setCurrentIndex(index) self._parent.setFocus() self.dataChanged.emit(index, index) return True elif role == Qt.EditRole: self.set_row(row, [from_qvariant(value, to_text_string), state]) self.dataChanged.emit(index, index) return True return True def rowCount(self, index=QModelIndex()): """Override Qt method""" return len(self._rows) def columnCount(self, index=QModelIndex()): """Override Qt method""" return 2 def row(self, rownum): """ """ if self._rows == []: return [None, None] else: return self._rows[rownum] def set_row(self, rownum, value): """ """ self._rows[rownum] = value class LayoutSaveDialog(QDialog): """ """ def __init__(self, parent, order): super(LayoutSaveDialog, self).__init__(parent) # variables self._parent = parent # widgets self.combo_box = QComboBox(self) self.combo_box.addItems(order) self.combo_box.setEditable(True) self.combo_box.clearEditText() self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self) self.button_ok = self.button_box.button(QDialogButtonBox.Ok) self.button_cancel = self.button_box.button(QDialogButtonBox.Cancel) # widget setup self.button_ok.setEnabled(False) self.dialog_size = QSize(300, 100) self.setWindowTitle('Save layout as') self.setModal(True) self.setMinimumSize(self.dialog_size) self.setFixedSize(self.dialog_size) # layouts self.layout = QVBoxLayout() self.layout.addWidget(self.combo_box) self.layout.addWidget(self.button_box) self.setLayout(self.layout) # signals and slots self.button_box.accepted.connect(self.accept) self.button_box.rejected.connect(self.close) self.combo_box.editTextChanged.connect(self.check_text) def check_text(self, text): """Disable empty layout name possibility""" if to_text_string(text) == u'': self.button_ok.setEnabled(False) else: self.button_ok.setEnabled(True) class LayoutSettingsDialog(QDialog): """Layout settings dialog""" def __init__(self, parent, names, order, active): super(LayoutSettingsDialog, self).__init__(parent) # variables self._parent = parent self._selection_model = None self.names = names self.order = order self.active = active # widgets self.button_move_up = QPushButton(_('Move Up')) self.button_move_down = QPushButton(_('Move Down')) self.button_delete = QPushButton(_('Delete Layout')) self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self) self.group_box = QGroupBox(_("Layout Display and Order")) self.table = QTableView(self) self.ok_button = self.button_box.button(QDialogButtonBox.Ok) self.cancel_button = self.button_box.button(QDialogButtonBox.Cancel) self.cancel_button.setDefault(True) self.cancel_button.setAutoDefault(True) # widget setup self.dialog_size = QSize(300, 200) self.setMinimumSize(self.dialog_size) self.setFixedSize(self.dialog_size) self.setWindowTitle('Layout Settings') self.table.setModel(LayoutModel(self.table, order, active)) self.table.setSelectionBehavior(QAbstractItemView.SelectRows) self.table.setSelectionMode(QAbstractItemView.SingleSelection) self.table.verticalHeader().hide() self.table.horizontalHeader().hide() self.table.setAlternatingRowColors(True) self.table.setShowGrid(False) self.table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.table.horizontalHeader().setStretchLastSection(True) self.table.setColumnHidden(1, True) # need to keep a reference for pyside not to segfault! self._selection_model = self.table.selectionModel() # layout buttons_layout = QVBoxLayout() buttons_layout.addWidget(self.button_move_up) buttons_layout.addWidget(self.button_move_down) buttons_layout.addStretch() buttons_layout.addWidget(self.button_delete) group_layout = QHBoxLayout() group_layout.addWidget(self.table) group_layout.addLayout(buttons_layout) self.group_box.setLayout(group_layout) layout = QVBoxLayout() layout.addWidget(self.group_box) layout.addWidget(self.button_box) self.setLayout(layout) # signals and slots self.button_box.accepted.connect(self.accept) self.button_box.rejected.connect(self.close) self.button_delete.clicked.connect(self.delete_layout) self.button_move_up.clicked.connect(lambda: self.move_layout(True)) self.button_move_down.clicked.connect(lambda: self.move_layout(False)) self.table.model().dataChanged.connect( lambda: self.selection_changed(None, None)) self._selection_model.selectionChanged.connect( lambda: self.selection_changed(None, None)) # focus table index = self.table.model().index(0, 0) self.table.setCurrentIndex(index) self.table.setFocus() def delete_layout(self): """ """ names, order, active = self.names, self.order, self.order name = from_qvariant(self.table.selectionModel().currentIndex().data(), to_text_string) if name in names: index = names.index(name) # In case nothing has focus in the table if index != -1: order.remove(name) names[index] = None if name in active: active.remove(name) self.names, self.order, self.active = names, order, active self.table.model().set_data(order, active) index = self.table.model().index(0, 0) self.table.setCurrentIndex(index) self.table.setFocus() self.selection_changed(None, None) if len(order) == 0: self.button_move_up.setDisabled(True) self.button_move_down.setDisabled(True) self.button_delete.setDisabled(True) def move_layout(self, up=True): """ """ names, order, active = self.names, self.order, self.active row = self.table.selectionModel().currentIndex().row() row_new = row if up: row_new -= 1 else: row_new += 1 order[row], order[row_new] = order[row_new], order[row] self.order = order self.table.model().set_data(order, active) index = self.table.model().index(row_new, 0) self.table.setCurrentIndex(index) self.table.setFocus() self.selection_changed(None, None) def selection_changed(self, selection, deselection): """ """ model = self.table.model() index = self.table.currentIndex() row = index.row() order, names, active = self.order, self.names, self.active state = model.row(row)[1] name = model.row(row)[0] # Check if name changed if name not in names: # Did changed if row != -1: # row == -1, means no items left to delete old_name = order[row] order[row] = name names[names.index(old_name)] = name if old_name in active: active[active.index(old_name)] = name # Check if checbox clicked if state: if name not in active: active.append(name) else: if name in active: active.remove(name) self.active = active self.button_move_up.setDisabled(False) self.button_move_down.setDisabled(False) if row == 0: self.button_move_up.setDisabled(True) if row == len(names) - 1: self.button_move_down.setDisabled(True) if len(names) == 0: self.button_move_up.setDisabled(True) self.button_move_down.setDisabled(True) def test(): """Run layout test widget test""" from spyder.utils.qthelpers import qapplication app = qapplication() names = ['test', 'tester', '20', '30', '40'] order = ['test', 'tester', '20', '30', '40'] active = ['test', 'tester'] widget_1 = LayoutSettingsDialog(None, names, order, active) widget_2 = LayoutSaveDialog(None, order) widget_1.show() widget_2.show() sys.exit(app.exec_()) if __name__ == '__main__': test() spyder-3.2.6/spyder/plugins/projects.py0000664000175000017500000004037213224740762021031 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Projects Plugin It handles closing, opening and switching among projetcs and also updating the file tree explorer associated with a project """ # Standard library imports import os.path as osp # Third party imports from qtpy.compat import getexistingdirectory from qtpy.QtCore import Signal, Slot from qtpy.QtWidgets import QMenu, QMessageBox # Local imports from spyder.config.base import _, get_home_dir from spyder.plugins import SpyderPluginMixin from spyder.py3compat import is_text_string from spyder.utils import icon_manager as ima from spyder.utils.qthelpers import add_actions, create_action, MENU_SEPARATOR from spyder.utils.misc import getcwd_or_home from spyder.widgets.projects.explorer import ProjectExplorerWidget from spyder.widgets.projects.projectdialog import ProjectDialog from spyder.widgets.projects import EmptyProject class Projects(ProjectExplorerWidget, SpyderPluginMixin): """Projects plugin""" CONF_SECTION = 'project_explorer' open_interpreter = Signal(str) pythonpath_changed = Signal() # File operations create_module = Signal(str) edit = Signal(str) removed = Signal(str) removed_tree = Signal(str) renamed = Signal(str, str) redirect_stdio = Signal(bool) run = Signal(str) # Project handling sig_project_created = Signal(object, object, object) sig_project_loaded = Signal(object) sig_project_closed = Signal(object) sig_new_file = Signal(str) def __init__(self, parent=None): ProjectExplorerWidget.__init__(self, parent=parent, name_filters=self.get_option('name_filters'), show_all=self.get_option('show_all'), show_hscrollbar=self.get_option('show_hscrollbar')) SpyderPluginMixin.__init__(self, parent) self.recent_projects = self.get_option('recent_projects', default=[]) self.current_active_project = None self.latest_project = None self.editor = None self.workingdirectory = None # Initialize plugin self.initialize_plugin() self.setup_project(self.get_active_project_path()) #------ SpyderPluginWidget API --------------------------------------------- def get_plugin_title(self): """Return widget title""" return _("Project explorer") def get_focus_widget(self): """ Return the widget to give focus to when this plugin's dockwidget is raised on top-level """ return self.treewidget def get_plugin_actions(self): """Return a list of actions related to plugin""" self.new_project_action = create_action(self, _("New Project..."), triggered=self.create_new_project) self.open_project_action = create_action(self, _("Open Project..."), triggered=lambda v: self.open_project()) self.close_project_action = create_action(self, _("Close Project"), triggered=self.close_project) self.delete_project_action = create_action(self, _("Delete Project"), triggered=self.delete_project) self.clear_recent_projects_action =\ create_action(self, _("Clear this list"), triggered=self.clear_recent_projects) self.edit_project_preferences_action =\ create_action(self, _("Project Preferences"), triggered=self.edit_project_preferences) self.recent_project_menu = QMenu(_("Recent Projects"), self) explorer_action = self.toggle_view_action self.main.projects_menu_actions += [self.new_project_action, MENU_SEPARATOR, self.open_project_action, self.close_project_action, self.delete_project_action, MENU_SEPARATOR, self.recent_project_menu, explorer_action] self.setup_menu_actions() return [] def register_plugin(self): """Register plugin in Spyder's main window""" self.editor = self.main.editor self.workingdirectory = self.main.workingdirectory self.main.pythonpath_changed() self.main.restore_scrollbar_position.connect( self.restore_scrollbar_position) self.pythonpath_changed.connect(self.main.pythonpath_changed) self.create_module.connect(self.editor.new) self.edit.connect(self.editor.load) self.removed.connect(self.editor.removed) self.removed_tree.connect(self.editor.removed_tree) self.renamed.connect(self.editor.renamed) self.editor.set_projects(self) self.main.add_dockwidget(self) self.sig_open_file.connect(self.main.open_file) self.sig_new_file.connect(lambda x: self.editor.new(text=x)) # New project connections. Order matters! self.sig_project_loaded.connect( lambda v: self.workingdirectory.chdir(v)) self.sig_project_loaded.connect( lambda v: self.main.update_window_title()) self.sig_project_loaded.connect( lambda v: self.editor.setup_open_files()) self.sig_project_loaded.connect(self.update_explorer) self.sig_project_closed[object].connect( lambda v: self.workingdirectory.chdir(self.get_last_working_dir())) self.sig_project_closed.connect( lambda v: self.main.update_window_title()) self.sig_project_closed.connect( lambda v: self.editor.setup_open_files()) self.recent_project_menu.aboutToShow.connect(self.setup_menu_actions) def refresh_plugin(self): """Refresh project explorer widget""" pass def closing_plugin(self, cancelable=False): """Perform actions before parent main window is closed""" self.save_config() self.closing_widget() return True #------ Public API --------------------------------------------------------- def setup_menu_actions(self): """Setup and update the menu actions.""" self.recent_project_menu.clear() self.recent_projects_actions = [] if self.recent_projects: for project in self.recent_projects: if self.is_valid_project(project): name = project.replace(get_home_dir(), '~') action = create_action(self, name, icon = ima.icon('project'), triggered=lambda v, path=project: self.open_project(path=path)) self.recent_projects_actions.append(action) else: self.recent_projects.remove(project) self.recent_projects_actions += [None, self.clear_recent_projects_action] else: self.recent_projects_actions = [self.clear_recent_projects_action] add_actions(self.recent_project_menu, self.recent_projects_actions) self.update_project_actions() def update_project_actions(self): """Update actions of the Projects menu""" if self.recent_projects: self.clear_recent_projects_action.setEnabled(True) else: self.clear_recent_projects_action.setEnabled(False) active = bool(self.get_active_project_path()) self.close_project_action.setEnabled(active) self.delete_project_action.setEnabled(active) self.edit_project_preferences_action.setEnabled(active) def edit_project_preferences(self): """Edit Spyder active project preferences""" from spyder.widgets.projects.configdialog import ProjectPreferences if self.project_active: active_project = self.project_list[0] dlg = ProjectPreferences(self, active_project) # dlg.size_change.connect(self.set_project_prefs_size) # if self.projects_prefs_dialog_size is not None: # dlg.resize(self.projects_prefs_dialog_size) dlg.show() # dlg.check_all_settings() # dlg.pages_widget.currentChanged.connect(self.__preference_page_changed) dlg.exec_() @Slot() def create_new_project(self): """Create new project""" active_project = self.current_active_project dlg = ProjectDialog(self) dlg.sig_project_creation_requested.connect(self._create_project) dlg.sig_project_creation_requested.connect(self.sig_project_created) if dlg.exec_(): pass if active_project is None: self.show_explorer() self.pythonpath_changed.emit() self.restart_consoles() def _create_project(self, path): """Create a new project.""" self.open_project(path=path) self.setup_menu_actions() self.add_to_recent(path) def open_project(self, path=None, restart_consoles=True, save_previous_files=True): """Open the project located in `path`""" if path is None: basedir = get_home_dir() path = getexistingdirectory(parent=self, caption=_("Open project"), basedir=basedir) if not self.is_valid_project(path): if path: QMessageBox.critical(self, _('Error'), _("%s is not a Spyder project!") % path) return else: self.add_to_recent(path) # A project was not open before if self.current_active_project is None: if save_previous_files: self.editor.save_open_files() self.editor.set_option('last_working_dir', getcwd_or_home()) self.show_explorer() else: # we are switching projects self.set_project_filenames(self.editor.get_open_filenames()) self.current_active_project = EmptyProject(path) self.latest_project = EmptyProject(path) self.set_option('current_project_path', self.get_active_project_path()) self.setup_menu_actions() self.sig_project_loaded.emit(path) self.pythonpath_changed.emit() if restart_consoles: self.restart_consoles() def close_project(self): """ Close current project and return to a window without an active project """ if self.current_active_project: path = self.current_active_project.root_path self.set_project_filenames(self.editor.get_open_filenames()) self.current_active_project = None self.set_option('current_project_path', None) self.setup_menu_actions() self.sig_project_closed.emit(path) self.pythonpath_changed.emit() self.dockwidget.close() self.clear() self.restart_consoles() def clear_recent_projects(self): """Clear the list of recent projects""" self.recent_projects = [] self.setup_menu_actions() def get_active_project(self): """Get the active project""" return self.current_active_project def reopen_last_project(self): """ Reopen the active project when Spyder was closed last time, if any """ current_project_path = self.get_option('current_project_path', default=None) # Needs a safer test of project existence! if current_project_path and \ self.is_valid_project(current_project_path): self.open_project(path=current_project_path, restart_consoles=False, save_previous_files=False) self.load_config() def get_project_filenames(self): """Get the list of recent filenames of a project""" recent_files = [] if self.current_active_project: recent_files = self.current_active_project.get_recent_files() elif self.latest_project: recent_files = self.latest_project.get_recent_files() return recent_files def set_project_filenames(self, recent_files): """Set the list of open file names in a project""" if self.current_active_project: self.current_active_project.set_recent_files(recent_files) def get_active_project_path(self): """Get path of the active project""" active_project_path = None if self.current_active_project: active_project_path = self.current_active_project.root_path return active_project_path def get_pythonpath(self, at_start=False): """Get project path as a list to be added to PYTHONPATH""" if at_start: current_path = self.get_option('current_project_path', default=None) else: current_path = self.get_active_project_path() if current_path is None: return [] else: return [current_path] def get_last_working_dir(self): """Get the path of the last working directory""" return self.editor.get_option('last_working_dir', default=getcwd_or_home()) def save_config(self): """Save configuration: opened projects & tree widget state""" self.set_option('recent_projects', self.recent_projects) self.set_option('expanded_state', self.treewidget.get_expanded_state()) self.set_option('scrollbar_position', self.treewidget.get_scrollbar_position()) def load_config(self): """Load configuration: opened projects & tree widget state""" expanded_state = self.get_option('expanded_state', None) # Sometimes the expanded state option may be truncated in .ini file # (for an unknown reason), in this case it would be converted to a # string by 'userconfig': if is_text_string(expanded_state): expanded_state = None if expanded_state is not None: self.treewidget.set_expanded_state(expanded_state) def restore_scrollbar_position(self): """Restoring scrollbar position after main window is visible""" scrollbar_pos = self.get_option('scrollbar_position', None) if scrollbar_pos is not None: self.treewidget.set_scrollbar_position(scrollbar_pos) def update_explorer(self): """Update explorer tree""" self.setup_project(self.get_active_project_path()) def show_explorer(self): """Show the explorer""" if self.dockwidget.isHidden(): self.dockwidget.show() self.dockwidget.raise_() self.dockwidget.update() def restart_consoles(self): """Restart consoles when closing, opening and switching projects""" self.main.ipyconsole.restart() def is_valid_project(self, path): """Check if a directory is a valid Spyder project""" spy_project_dir = osp.join(path, '.spyproject') if osp.isdir(path) and osp.isdir(spy_project_dir): return True else: return False def add_to_recent(self, project): """ Add an entry to recent projetcs We only maintain the list of the 10 most recent projects """ if project not in self.recent_projects: self.recent_projects.insert(0, project) self.recent_projects = self.recent_projects[:10] spyder-3.2.6/spyder/plugins/workingdirectory.py0000664000175000017500000002761713224740762022614 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Working Directory Plugin""" # pylint: disable=C0103 # pylint: disable=R0903 # pylint: disable=R0911 # pylint: disable=R0201 # Standard library imports import os import os.path as osp # Third party imports from qtpy import PYQT5 from qtpy.compat import getexistingdirectory from qtpy.QtCore import QSize, Signal, Slot from qtpy.QtWidgets import (QButtonGroup, QGroupBox, QHBoxLayout, QLabel, QToolBar, QVBoxLayout) # Local imports from spyder.config.base import _, get_conf_path, get_home_dir from spyder.plugins import SpyderPluginMixin from spyder.plugins.configdialog import PluginConfigPage from spyder.py3compat import to_text_string from spyder.utils.misc import getcwd_or_home from spyder.utils import encoding from spyder.utils import icon_manager as ima from spyder.utils.qthelpers import create_action from spyder.widgets.comboboxes import PathComboBox class WorkingDirectoryConfigPage(PluginConfigPage): def setup_page(self): about_label = QLabel(_("The current working directory is " "the working directory for IPython consoles " "and the current directory for the File Explorer.")) about_label.setWordWrap(True) console_group = QGroupBox(_("Console directory")) console_label = QLabel(_("The working directory for new consoles is:")) console_label.setWordWrap(True) console_bg = QButtonGroup(console_group) console_project_radio = self.create_radiobutton( _("The current project directory " "or user home directory " "(if no project is active)"), 'console/use_project_or_home_directory', True, button_group=console_bg) console_cwd_radio = self.create_radiobutton( _("The current working directory"), 'console/use_cwd', False, button_group=console_bg) console_dir_radio = self.create_radiobutton( _("the following directory:"), 'console/use_fixed_directory', False, _("The directory when a new console " "is open will be the specified path"), button_group=console_bg) console_dir_bd = self.create_browsedir("", 'console/fixed_directory', getcwd_or_home()) console_dir_radio.toggled.connect(console_dir_bd.setEnabled) console_project_radio.toggled.connect(console_dir_bd.setDisabled) console_cwd_radio.toggled.connect(console_dir_bd.setDisabled) console_dir_layout = QHBoxLayout() console_dir_layout.addWidget(console_dir_radio) console_dir_layout.addWidget(console_dir_bd) console_layout = QVBoxLayout() console_layout.addWidget(console_label) console_layout.addWidget(console_project_radio) console_layout.addWidget(console_cwd_radio) console_layout.addLayout(console_dir_layout) console_group.setLayout(console_layout) vlayout = QVBoxLayout() vlayout.addWidget(about_label) vlayout.addSpacing(10) vlayout.addWidget(console_group) vlayout.addStretch(1) self.setLayout(vlayout) class WorkingDirectory(QToolBar, SpyderPluginMixin): """ Working directory changer widget """ CONF_SECTION = 'workingdir' CONFIGWIDGET_CLASS = WorkingDirectoryConfigPage LOG_PATH = get_conf_path(CONF_SECTION) sig_option_changed = Signal(str, object) set_previous_enabled = Signal(bool) set_next_enabled = Signal(bool) redirect_stdio = Signal(bool) set_explorer_cwd = Signal(str) refresh_findinfiles = Signal() set_current_console_wd = Signal(str) def __init__(self, parent, workdir=None, **kwds): if PYQT5: super(WorkingDirectory, self).__init__(parent, **kwds) else: QToolBar.__init__(self, parent) SpyderPluginMixin.__init__(self, parent) # Initialize plugin self.initialize_plugin() self.setWindowTitle(self.get_plugin_title()) # Toolbar title self.setObjectName(self.get_plugin_title()) # Used to save Window state # Previous dir action self.history = [] self.histindex = None self.previous_action = create_action(self, "previous", None, ima.icon('previous'), _('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, ima.icon('next'), _('Next'), triggered=self.next_directory) self.addAction(self.next_action) # Enable/disable previous/next actions self.set_previous_enabled.connect(self.previous_action.setEnabled) self.set_next_enabled.connect(self.next_action.setEnabled) # Path combo box adjust = self.get_option('working_dir_adjusttocontents') self.pathedit = PathComboBox(self, adjust_to_contents=adjust) self.pathedit.setToolTip(_("This is the working directory for newly\n" "opened consoles (Python/IPython consoles and\n" "terminals), for the file explorer, for the\n" "find in files plugin and for new files\n" "created in the editor")) self.pathedit.open_dir.connect(self.chdir) self.pathedit.activated[str].connect(self.chdir) self.pathedit.setMaxCount(self.get_option('working_dir_history')) wdhistory = self.load_wdhistory(workdir) if workdir is None: if self.get_option('console/use_project_or_home_directory'): workdir = get_home_dir() else: workdir = self.get_option('console/fixed_directory', default='') if not osp.isdir(workdir): workdir = get_home_dir() self.chdir(workdir) self.pathedit.addItems(wdhistory) self.pathedit.selected_text = self.pathedit.currentText() self.refresh_plugin() self.addWidget(self.pathedit) # Browse action browse_action = create_action(self, "browse", None, ima.icon('DirOpenIcon'), _('Browse a working directory'), triggered=self.select_directory) self.addAction(browse_action) # Parent dir action parent_action = create_action(self, "parent", None, ima.icon('up'), _('Change to parent directory'), triggered=self.parent_directory) self.addAction(parent_action) #------ SpyderPluginWidget API --------------------------------------------- def get_plugin_title(self): """Return widget title""" return _('Current working directory') def get_plugin_icon(self): """Return widget icon""" return ima.icon('DirOpenIcon') def get_plugin_actions(self): """Setup actions""" return (None, None) def register_plugin(self): """Register plugin in Spyder's main window""" self.redirect_stdio.connect(self.main.redirect_internalshell_stdio) self.main.console.shell.refresh.connect(self.refresh_plugin) iconsize = 24 self.setIconSize(QSize(iconsize, iconsize)) self.main.addToolBar(self) def refresh_plugin(self): """Refresh widget""" curdir = getcwd_or_home() self.pathedit.add_text(curdir) self.save_wdhistory() self.set_previous_enabled.emit( self.histindex is not None and self.histindex > 0) self.set_next_enabled.emit(self.histindex is not None and \ self.histindex < len(self.history)-1) def apply_plugin_settings(self, options): """Apply configuration file's plugin settings""" pass def closing_plugin(self, cancelable=False): """Perform actions before parent main window is closed""" return True #------ Public API --------------------------------------------------------- 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 = get_home_dir() wdhistory = [ workdir ] return wdhistory def save_wdhistory(self): """Save history to a text file in user home directory""" text = [ to_text_string( self.pathedit.itemText(index) ) \ for index in range(self.pathedit.count()) ] encoding.writelines(text, self.LOG_PATH) @Slot() def select_directory(self): """Select directory""" self.redirect_stdio.emit(False) directory = getexistingdirectory(self.main, _("Select directory"), getcwd_or_home()) if directory: self.chdir(directory) self.redirect_stdio.emit(True) @Slot() def previous_directory(self): """Back to previous directory""" self.histindex -= 1 self.chdir(directory='', browsing_history=True) @Slot() def next_directory(self): """Return to next directory""" self.histindex += 1 self.chdir(directory='', browsing_history=True) @Slot() def parent_directory(self): """Change working directory to parent directory""" self.chdir(os.path.join(getcwd_or_home(), os.path.pardir)) @Slot(str) @Slot(str, bool) @Slot(str, bool, bool) @Slot(str, bool, bool, bool) def chdir(self, directory, browsing_history=False, refresh_explorer=True, refresh_console=True): """Set directory as working directory""" if directory: directory = osp.abspath(to_text_string(directory)) # Working directory history management 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] self.history.append(directory) self.histindex = len(self.history)-1 # Changing working directory try: os.chdir(directory) if refresh_explorer: self.set_explorer_cwd.emit(directory) if refresh_console: self.set_current_console_wd.emit(directory) self.refresh_findinfiles.emit() except OSError: self.history.pop(self.histindex) self.refresh_plugin() spyder-3.2.6/spyder/plugins/findinfiles.py0000664000175000017500000001716013224740762021471 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Find in Files Plugin""" # pylint: disable=C0103 # pylint: disable=R0903 # pylint: disable=R0911 # pylint: disable=R0201 # Standard library imports import sys # Third party imports from qtpy.QtWidgets import QApplication from qtpy.QtCore import Signal, Slot, Qt from qtpy.QtGui import QKeySequence # Local imports from spyder.config.base import _ from spyder.config.utils import get_edit_extensions from spyder.utils.misc import getcwd_or_home from spyder.utils import icon_manager as ima from spyder.utils.qthelpers import create_action, MENU_SEPARATOR from spyder.widgets.findinfiles import FindInFilesWidget from spyder.plugins import SpyderPluginMixin class FindInFiles(FindInFilesWidget, SpyderPluginMixin): """Find in files DockWidget""" CONF_SECTION = 'find_in_files' sig_option_changed = Signal(str, object) toggle_visibility = Signal(bool) edit_goto = Signal(str, int, str) redirect_stdio = Signal(bool) def __init__(self, parent=None): supported_encodings = self.get_option('supported_encodings') search_path = self.get_option('search_path', None) self.search_text_samples = self.get_option('search_text_samples') search_text = self.get_option('search_text') search_text = [txt for txt in search_text \ if txt not in self.search_text_samples] search_text += self.search_text_samples search_text_regexp = self.get_option('search_text_regexp') exclude = self.get_option('exclude') exclude_idx = self.get_option('exclude_idx', None) exclude_regexp = self.get_option('exclude_regexp') in_python_path = self.get_option('in_python_path') more_options = self.get_option('more_options') case_sensitive = self.get_option('case_sensitive') path_history = self.get_option('path_history', []) FindInFilesWidget.__init__(self, parent, search_text, search_text_regexp, search_path, exclude, exclude_idx, exclude_regexp, supported_encodings, in_python_path, more_options, case_sensitive, path_history) SpyderPluginMixin.__init__(self, parent) # Initialize plugin self.initialize_plugin() self.toggle_visibility.connect(self.toggle) def toggle(self, state): """Toggle widget visibility""" if self.dockwidget: self.dockwidget.setVisible(state) def refreshdir(self): """Refresh search directory""" self.find_options.set_directory(getcwd_or_home()) def set_project_path(self, path): """Refresh current project path""" self.find_options.set_project_path(path) def set_current_opened_file(self, path): """Get path of current opened file in editor""" self.find_options.set_file_path(path) def unset_project_path(self): """Refresh current project path""" self.find_options.disable_project_search() @Slot() def findinfiles_callback(self): """Find in files callback""" widget = QApplication.focusWidget() if not self.ismaximized: self.dockwidget.setVisible(True) self.dockwidget.raise_() text = '' try: if widget.has_selected_text(): text = widget.get_selected_text() except AttributeError: # This is not a text widget deriving from TextEditBaseWidget pass self.set_search_text(text) if text: self.find() #------ SpyderPluginMixin API --------------------------------------------- def switch_to_plugin(self): """Switch to plugin This method is called when pressing plugin's shortcut key""" self.findinfiles_callback() # Necessary at least with PyQt5 on Windows SpyderPluginMixin.switch_to_plugin(self) #------ SpyderPluginWidget API -------------------------------------------- def get_plugin_title(self): """Return widget title""" return _("Find in files") def get_focus_widget(self): """ Return the widget to give focus to when this plugin's dockwidget is raised on top-level """ return self.find_options.search_text def get_plugin_actions(self): """Return a list of actions related to plugin""" return [] def register_plugin(self): """Register plugin in Spyder's main window""" self.get_pythonpath_callback = self.main.get_spyder_pythonpath self.main.add_dockwidget(self) self.edit_goto.connect(self.main.editor.load) self.redirect_stdio.connect(self.main.redirect_internalshell_stdio) self.main.workingdirectory.refresh_findinfiles.connect(self.refreshdir) self.main.projects.sig_project_loaded.connect(self.set_project_path) self.main.projects.sig_project_closed.connect(self.unset_project_path) self.main.editor.open_file_update.connect(self.set_current_opened_file) findinfiles_action = create_action( self, _("&Find in files"), icon=ima.icon('findf'), triggered=self.switch_to_plugin, shortcut=QKeySequence(self.shortcut), context=Qt.WidgetShortcut, tip=_("Search text in multiple files")) self.main.search_menu_actions += [MENU_SEPARATOR, findinfiles_action] self.main.search_toolbar_actions += [MENU_SEPARATOR, findinfiles_action] self.refreshdir() def refresh_plugin(self): """Refresh widget""" pass def closing_plugin(self, cancelable=False): """Perform actions before parent main window is closed""" self.closing_widget() # stop search thread and clean-up options = self.find_options.get_options(all=True) if options is not None: (search_text, text_re, search_path, exclude, exclude_idx, exclude_re, in_python_path, more_options, case_sensitive, path_history) = options hist_limit = 15 search_text = search_text[:hist_limit] search_path = search_path[:hist_limit] exclude = exclude[:hist_limit] path_history = path_history[-hist_limit:] self.set_option('search_text', search_text) self.set_option('search_text_regexp', text_re) self.set_option('search_path', search_path) self.set_option('exclude', exclude) self.set_option('exclude_idx', exclude_idx) self.set_option('exclude_regexp', exclude_re) self.set_option('in_python_path', in_python_path) self.set_option('more_options', more_options) self.set_option('case_sensitive', case_sensitive) self.set_option('path_history', path_history) return True def test(): from spyder.utils.qthelpers import qapplication app = qapplication() widget = FindInFiles() widget.show() sys.exit(app.exec_()) if __name__ == '__main__': test() spyder-3.2.6/spyder/plugins/configdialog.py0000664000175000017500000017651613224740762021637 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Configuration dialog / Preferences. """ # Standard library imports import os.path as osp # Third party imports from qtpy import API from qtpy.compat import (getexistingdirectory, getopenfilename, from_qvariant, to_qvariant) from qtpy.QtCore import QSize, Qt, Signal, Slot, QRegExp from qtpy.QtGui import QColor, QRegExpValidator from qtpy.QtWidgets import (QButtonGroup, QCheckBox, QComboBox, QDialog, QDialogButtonBox, QDoubleSpinBox, QFontComboBox, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLineEdit, QListView, QListWidget, QListWidgetItem, QMessageBox, QPushButton, QRadioButton, QScrollArea, QSpinBox, QSplitter, QStackedWidget, QStyleFactory, QTabWidget, QVBoxLayout, QWidget, QApplication) # Local imports from spyder.config.base import (_, LANGUAGE_CODES, load_lang_conf, running_in_mac_app, save_lang_conf) from spyder.config.gui import get_font, set_font from spyder.config.main import CONF from spyder.config.user import NoDefault from spyder.config.utils import is_gtk_desktop from spyder.py3compat import to_text_string, is_text_string from spyder.utils import icon_manager as ima from spyder.utils import syntaxhighlighters from spyder.utils.misc import getcwd_or_home from spyder.widgets.colors import ColorLayout from spyder.widgets.sourcecode.codeeditor import CodeEditor HDPI_QT_PAGE = "http://doc.qt.io/qt-5/highdpi.html" class ConfigAccessMixin(object): """Namespace for methods that access config storage""" CONF_SECTION = None def set_option(self, option, value): CONF.set(self.CONF_SECTION, option, value) def get_option(self, option, default=NoDefault): return CONF.get(self.CONF_SECTION, option, default) class ConfigPage(QWidget): """Base class for configuration page in Preferences""" # Signals apply_button_enabled = Signal(bool) show_this_page = Signal() def __init__(self, parent, apply_callback=None): QWidget.__init__(self, parent) self.apply_callback = apply_callback self.is_modified = False def initialize(self): """ Initialize configuration page: * setup GUI widgets * load settings and change widgets accordingly """ self.setup_page() self.load_from_conf() def get_name(self): """Return configuration page name""" raise NotImplementedError def get_icon(self): """Return configuration page icon (24x24)""" raise NotImplementedError def setup_page(self): """Setup configuration page widget""" raise NotImplementedError def set_modified(self, state): self.is_modified = state self.apply_button_enabled.emit(state) def is_valid(self): """Return True if all widget contents are valid""" raise NotImplementedError def apply_changes(self): """Apply changes callback""" if self.is_modified: self.save_to_conf() if self.apply_callback is not None: self.apply_callback() # Since the language cannot be retrieved by CONF and the language # is needed before loading CONF, this is an extra method needed to # ensure that when changes are applied, they are copied to a # specific file storing the language value. This only applies to # the main section config. if self.CONF_SECTION == u'main': self._save_lang() for restart_option in self.restart_options: if restart_option in self.changed_options: self.prompt_restart_required() break # Ensure a single popup is displayed self.set_modified(False) def load_from_conf(self): """Load settings from configuration file""" raise NotImplementedError def save_to_conf(self): """Save settings to configuration file""" raise NotImplementedError class ConfigDialog(QDialog): """Spyder configuration ('Preferences') dialog box""" # Signals check_settings = Signal() size_change = Signal(QSize) def __init__(self, parent=None): QDialog.__init__(self, parent) self.main = parent # Widgets self.pages_widget = QStackedWidget() self.contents_widget = QListWidget() self.button_reset = QPushButton(_('Reset to defaults')) bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Apply | QDialogButtonBox.Cancel) self.apply_btn = bbox.button(QDialogButtonBox.Apply) # Widgets setup # Destroying the C++ object right after closing the dialog box, # otherwise it may be garbage-collected in another QThread # (e.g. the editor's analysis thread in Spyder), thus leading to # a segmentation fault on UNIX or an application crash on Windows self.setAttribute(Qt.WA_DeleteOnClose) self.setWindowTitle(_('Preferences')) self.setWindowIcon(ima.icon('configure')) self.contents_widget.setMovement(QListView.Static) self.contents_widget.setSpacing(1) self.contents_widget.setCurrentRow(0) # Layout hsplitter = QSplitter() hsplitter.addWidget(self.contents_widget) hsplitter.addWidget(self.pages_widget) btnlayout = QHBoxLayout() btnlayout.addWidget(self.button_reset) btnlayout.addStretch(1) btnlayout.addWidget(bbox) vlayout = QVBoxLayout() vlayout.addWidget(hsplitter) vlayout.addLayout(btnlayout) self.setLayout(vlayout) # Signals and slots if self.main: self.button_reset.clicked.connect(self.main.reset_spyder) self.pages_widget.currentChanged.connect(self.current_page_changed) self.contents_widget.currentRowChanged.connect( self.pages_widget.setCurrentIndex) bbox.accepted.connect(self.accept) bbox.rejected.connect(self.reject) bbox.clicked.connect(self.button_clicked) # Ensures that the config is present on spyder first run CONF.set('main', 'interface_language', load_lang_conf()) def get_current_index(self): """Return current page index""" return self.contents_widget.currentRow() def set_current_index(self, index): """Set current page index""" self.contents_widget.setCurrentRow(index) def get_page(self, index=None): """Return page widget""" if index is None: widget = self.pages_widget.currentWidget() else: widget = self.pages_widget.widget(index) return widget.widget() @Slot() def accept(self): """Reimplement Qt method""" for index in range(self.pages_widget.count()): configpage = self.get_page(index) if not configpage.is_valid(): return configpage.apply_changes() QDialog.accept(self) def button_clicked(self, button): if button is self.apply_btn: # Apply button was clicked configpage = self.get_page() if not configpage.is_valid(): return configpage.apply_changes() def current_page_changed(self, index): widget = self.get_page(index) self.apply_btn.setVisible(widget.apply_callback is not None) self.apply_btn.setEnabled(widget.is_modified) def add_page(self, widget): self.check_settings.connect(widget.check_settings) widget.show_this_page.connect(lambda row=self.contents_widget.count(): self.contents_widget.setCurrentRow(row)) widget.apply_button_enabled.connect(self.apply_btn.setEnabled) scrollarea = QScrollArea(self) scrollarea.setWidgetResizable(True) scrollarea.setWidget(widget) self.pages_widget.addWidget(scrollarea) item = QListWidgetItem(self.contents_widget) try: item.setIcon(widget.get_icon()) except TypeError: pass item.setText(widget.get_name()) item.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled) item.setSizeHint(QSize(0, 25)) def check_all_settings(self): """This method is called to check all configuration page settings after configuration dialog has been shown""" self.check_settings.emit() def resizeEvent(self, event): """ Reimplement Qt method to be able to save the widget's size from the main application """ QDialog.resizeEvent(self, event) self.size_change.emit(self.size()) class SpyderConfigPage(ConfigPage, ConfigAccessMixin): """Plugin configuration dialog box page widget""" CONF_SECTION = None def __init__(self, parent): ConfigPage.__init__(self, parent, apply_callback=lambda: self.apply_settings(self.changed_options)) self.checkboxes = {} self.radiobuttons = {} self.lineedits = {} self.validate_data = {} self.spinboxes = {} self.comboboxes = {} self.fontboxes = {} self.coloredits = {} self.scedits = {} self.changed_options = set() self.restart_options = dict() # Dict to store name and localized text self.default_button_group = None def apply_settings(self, options): raise NotImplementedError def check_settings(self): """This method is called to check settings after configuration dialog has been shown""" pass def set_modified(self, state): ConfigPage.set_modified(self, state) if not state: self.changed_options = set() def is_valid(self): """Return True if all widget contents are valid""" for lineedit in self.lineedits: if lineedit in self.validate_data and lineedit.isEnabled(): validator, invalid_msg = self.validate_data[lineedit] text = to_text_string(lineedit.text()) if not validator(text): QMessageBox.critical(self, self.get_name(), "%s:
%s" % (invalid_msg, text), QMessageBox.Ok) return False return True def load_from_conf(self): """Load settings from configuration file""" for checkbox, (option, default) in list(self.checkboxes.items()): checkbox.setChecked(self.get_option(option, default)) # QAbstractButton works differently for PySide and PyQt if not API == 'pyside': checkbox.clicked.connect(lambda _foo, opt=option: self.has_been_modified(opt)) else: checkbox.clicked.connect(lambda opt=option: self.has_been_modified(opt)) for radiobutton, (option, default) in list(self.radiobuttons.items()): radiobutton.setChecked(self.get_option(option, default)) radiobutton.toggled.connect(lambda _foo, opt=option: self.has_been_modified(opt)) if radiobutton.restart_required: self.restart_options[option] = radiobutton.label_text for lineedit, (option, default) in list(self.lineedits.items()): lineedit.setText(self.get_option(option, default)) lineedit.textChanged.connect(lambda _foo, opt=option: self.has_been_modified(opt)) if lineedit.restart_required: self.restart_options[option] = lineedit.label_text for spinbox, (option, default) in list(self.spinboxes.items()): spinbox.setValue(self.get_option(option, default)) spinbox.valueChanged.connect(lambda _foo, opt=option: self.has_been_modified(opt)) for combobox, (option, default) in list(self.comboboxes.items()): value = self.get_option(option, default) for index in range(combobox.count()): data = from_qvariant(combobox.itemData(index), to_text_string) # For PyQt API v2, it is necessary to convert `data` to # unicode in case the original type was not a string, like an # integer for example (see qtpy.compat.from_qvariant): if to_text_string(data) == to_text_string(value): break combobox.setCurrentIndex(index) combobox.currentIndexChanged.connect(lambda _foo, opt=option: self.has_been_modified(opt)) if combobox.restart_required: self.restart_options[option] = combobox.label_text for (fontbox, sizebox), option in list(self.fontboxes.items()): font = self.get_font(option) fontbox.setCurrentFont(font) sizebox.setValue(font.pointSize()) if option is None: property = 'plugin_font' else: property = option fontbox.currentIndexChanged.connect(lambda _foo, opt=property: self.has_been_modified(opt)) sizebox.valueChanged.connect(lambda _foo, opt=property: self.has_been_modified(opt)) for clayout, (option, default) in list(self.coloredits.items()): property = to_qvariant(option) edit = clayout.lineedit btn = clayout.colorbtn edit.setText(self.get_option(option, default)) # QAbstractButton works differently for PySide and PyQt if not API == 'pyside': btn.clicked.connect(lambda _foo, opt=option: self.has_been_modified(opt)) else: btn.clicked.connect(lambda opt=option: self.has_been_modified(opt)) edit.textChanged.connect(lambda _foo, opt=option: self.has_been_modified(opt)) for (clayout, cb_bold, cb_italic ), (option, default) in list(self.scedits.items()): edit = clayout.lineedit btn = clayout.colorbtn color, bold, italic = self.get_option(option, default) edit.setText(color) cb_bold.setChecked(bold) cb_italic.setChecked(italic) edit.textChanged.connect(lambda _foo, opt=option: self.has_been_modified(opt)) # QAbstractButton works differently for PySide and PyQt if not API == 'pyside': btn.clicked.connect(lambda _foo, opt=option: self.has_been_modified(opt)) cb_bold.clicked.connect(lambda _foo, opt=option: self.has_been_modified(opt)) cb_italic.clicked.connect(lambda _foo, opt=option: self.has_been_modified(opt)) else: btn.clicked.connect(lambda opt=option: self.has_been_modified(opt)) cb_bold.clicked.connect(lambda opt=option: self.has_been_modified(opt)) cb_italic.clicked.connect(lambda opt=option: self.has_been_modified(opt)) def save_to_conf(self): """Save settings to configuration file""" for checkbox, (option, _default) in list(self.checkboxes.items()): self.set_option(option, checkbox.isChecked()) for radiobutton, (option, _default) in list(self.radiobuttons.items()): self.set_option(option, radiobutton.isChecked()) for lineedit, (option, _default) in list(self.lineedits.items()): self.set_option(option, to_text_string(lineedit.text())) for spinbox, (option, _default) in list(self.spinboxes.items()): self.set_option(option, spinbox.value()) for combobox, (option, _default) in list(self.comboboxes.items()): data = combobox.itemData(combobox.currentIndex()) self.set_option(option, from_qvariant(data, to_text_string)) for (fontbox, sizebox), option in list(self.fontboxes.items()): font = fontbox.currentFont() font.setPointSize(sizebox.value()) self.set_font(font, option) for clayout, (option, _default) in list(self.coloredits.items()): self.set_option(option, to_text_string(clayout.lineedit.text())) for (clayout, cb_bold, cb_italic), (option, _default) in list(self.scedits.items()): color = to_text_string(clayout.lineedit.text()) bold = cb_bold.isChecked() italic = cb_italic.isChecked() self.set_option(option, (color, bold, italic)) @Slot(str) def has_been_modified(self, option): self.set_modified(True) self.changed_options.add(option) def create_checkbox(self, text, option, default=NoDefault, tip=None, msg_warning=None, msg_info=None, msg_if_enabled=False): checkbox = QCheckBox(text) if tip is not None: checkbox.setToolTip(tip) self.checkboxes[checkbox] = (option, default) if msg_warning is not None or msg_info is not None: def show_message(is_checked=False): if is_checked or not msg_if_enabled: if msg_warning is not None: QMessageBox.warning(self, self.get_name(), msg_warning, QMessageBox.Ok) if msg_info is not None: QMessageBox.information(self, self.get_name(), msg_info, QMessageBox.Ok) checkbox.clicked.connect(show_message) return checkbox def create_radiobutton(self, text, option, default=NoDefault, tip=None, msg_warning=None, msg_info=None, msg_if_enabled=False, button_group=None, restart=False): radiobutton = QRadioButton(text) if button_group is None: if self.default_button_group is None: self.default_button_group = QButtonGroup(self) button_group = self.default_button_group button_group.addButton(radiobutton) if tip is not None: radiobutton.setToolTip(tip) self.radiobuttons[radiobutton] = (option, default) if msg_warning is not None or msg_info is not None: def show_message(is_checked): if is_checked or not msg_if_enabled: if msg_warning is not None: QMessageBox.warning(self, self.get_name(), msg_warning, QMessageBox.Ok) if msg_info is not None: QMessageBox.information(self, self.get_name(), msg_info, QMessageBox.Ok) radiobutton.toggled.connect(show_message) radiobutton.restart_required = restart radiobutton.label_text = text return radiobutton def create_lineedit(self, text, option, default=NoDefault, tip=None, alignment=Qt.Vertical, regex=None, restart=False): label = QLabel(text) label.setWordWrap(True) edit = QLineEdit() layout = QVBoxLayout() if alignment == Qt.Vertical else QHBoxLayout() layout.addWidget(label) layout.addWidget(edit) layout.setContentsMargins(0, 0, 0, 0) if tip: edit.setToolTip(tip) if regex: edit.setValidator(QRegExpValidator(QRegExp(regex))) self.lineedits[edit] = (option, default) widget = QWidget(self) widget.label = label widget.textbox = edit widget.setLayout(layout) edit.restart_required = restart edit.label_text = text return widget def create_browsedir(self, text, option, default=NoDefault, tip=None): widget = self.create_lineedit(text, option, default, alignment=Qt.Horizontal) for edit in self.lineedits: if widget.isAncestorOf(edit): break msg = _("Invalid directory path") self.validate_data[edit] = (osp.isdir, msg) browse_btn = QPushButton(ima.icon('DirOpenIcon'), '', self) browse_btn.setToolTip(_("Select directory")) browse_btn.clicked.connect(lambda: self.select_directory(edit)) layout = QHBoxLayout() layout.addWidget(widget) layout.addWidget(browse_btn) layout.setContentsMargins(0, 0, 0, 0) browsedir = QWidget(self) browsedir.setLayout(layout) return browsedir def select_directory(self, edit): """Select directory""" basedir = to_text_string(edit.text()) if not osp.isdir(basedir): basedir = getcwd_or_home() title = _("Select directory") directory = getexistingdirectory(self, title, basedir) if directory: edit.setText(directory) def create_browsefile(self, text, option, default=NoDefault, tip=None, filters=None): widget = self.create_lineedit(text, option, default, alignment=Qt.Horizontal) for edit in self.lineedits: if widget.isAncestorOf(edit): break msg = _('Invalid file path') self.validate_data[edit] = (osp.isfile, msg) browse_btn = QPushButton(ima.icon('FileIcon'), '', self) browse_btn.setToolTip(_("Select file")) browse_btn.clicked.connect(lambda: self.select_file(edit, filters)) layout = QHBoxLayout() layout.addWidget(widget) layout.addWidget(browse_btn) layout.setContentsMargins(0, 0, 0, 0) browsedir = QWidget(self) browsedir.setLayout(layout) return browsedir def select_file(self, edit, filters=None): """Select File""" basedir = osp.dirname(to_text_string(edit.text())) if not osp.isdir(basedir): basedir = getcwd_or_home() if filters is None: filters = _("All files (*)") title = _("Select file") filename, _selfilter = getopenfilename(self, title, basedir, filters) if filename: edit.setText(filename) def create_spinbox(self, prefix, suffix, option, default=NoDefault, min_=None, max_=None, step=None, tip=None): widget = QWidget(self) if prefix: plabel = QLabel(prefix) widget.plabel = plabel else: plabel = None if suffix: slabel = QLabel(suffix) widget.slabel = slabel else: slabel = None if step is not None: if type(step) is int: spinbox = QSpinBox() else: spinbox = QDoubleSpinBox() spinbox.setDecimals(1) spinbox.setSingleStep(step) else: spinbox = QSpinBox() if min_ is not None: spinbox.setMinimum(min_) if max_ is not None: spinbox.setMaximum(max_) if tip is not None: spinbox.setToolTip(tip) self.spinboxes[spinbox] = (option, default) layout = QHBoxLayout() for subwidget in (plabel, spinbox, slabel): if subwidget is not None: layout.addWidget(subwidget) layout.addStretch(1) layout.setContentsMargins(0, 0, 0, 0) widget.spinbox = spinbox widget.setLayout(layout) return widget def create_coloredit(self, text, option, default=NoDefault, tip=None, without_layout=False): label = QLabel(text) clayout = ColorLayout(QColor(Qt.black), self) clayout.lineedit.setMaximumWidth(80) if tip is not None: clayout.setToolTip(tip) self.coloredits[clayout] = (option, default) if without_layout: return label, clayout layout = QHBoxLayout() layout.addWidget(label) layout.addLayout(clayout) layout.addStretch(1) layout.setContentsMargins(0, 0, 0, 0) widget = QWidget(self) widget.setLayout(layout) return widget def create_scedit(self, text, option, default=NoDefault, tip=None, without_layout=False): label = QLabel(text) clayout = ColorLayout(QColor(Qt.black), self) clayout.lineedit.setMaximumWidth(80) if tip is not None: clayout.setToolTip(tip) cb_bold = QCheckBox() cb_bold.setIcon(ima.icon('bold')) cb_bold.setToolTip(_("Bold")) cb_italic = QCheckBox() cb_italic.setIcon(ima.icon('italic')) cb_italic.setToolTip(_("Italic")) self.scedits[(clayout, cb_bold, cb_italic)] = (option, default) if without_layout: return label, clayout, cb_bold, cb_italic layout = QHBoxLayout() layout.addWidget(label) layout.addLayout(clayout) layout.addSpacing(10) layout.addWidget(cb_bold) layout.addWidget(cb_italic) layout.addStretch(1) layout.setContentsMargins(0, 0, 0, 0) widget = QWidget(self) widget.setLayout(layout) return widget def create_combobox(self, text, choices, option, default=NoDefault, tip=None, restart=False): """choices: couples (name, key)""" label = QLabel(text) combobox = QComboBox() if tip is not None: combobox.setToolTip(tip) for name, key in choices: if not (name is None and key is None): combobox.addItem(name, to_qvariant(key)) # Insert separators count = 0 for index, item in enumerate(choices): name, key = item if name is None and key is None: combobox.insertSeparator(index + count) count += 1 self.comboboxes[combobox] = (option, default) layout = QHBoxLayout() layout.addWidget(label) layout.addWidget(combobox) layout.addStretch(1) layout.setContentsMargins(0, 0, 0, 0) widget = QWidget(self) widget.label = label widget.combobox = combobox widget.setLayout(layout) combobox.restart_required = restart combobox.label_text = text return widget def create_fontgroup(self, option=None, text=None, title=None, tip=None, fontfilters=None, without_group=False): """Option=None -> setting plugin font""" if title: fontlabel = QLabel(title) else: fontlabel = QLabel(_("Font: ")) fontbox = QFontComboBox() if fontfilters is not None: fontbox.setFontFilters(fontfilters) sizelabel = QLabel(" "+_("Size: ")) sizebox = QSpinBox() sizebox.setRange(7, 100) self.fontboxes[(fontbox, sizebox)] = option layout = QHBoxLayout() for subwidget in (fontlabel, fontbox, sizelabel, sizebox): layout.addWidget(subwidget) layout.addStretch(1) widget = QWidget(self) widget.fontlabel = fontlabel widget.sizelabel = sizelabel widget.fontbox = fontbox widget.sizebox = sizebox widget.setLayout(layout) if not without_group: if text is None: text = _("Font style") group = QGroupBox(text) group.setLayout(layout) if tip is not None: group.setToolTip(tip) return group else: return widget def create_button(self, text, callback): btn = QPushButton(text) btn.clicked.connect(callback) btn.clicked.connect(lambda checked=False, opt='': self.has_been_modified(opt)) return btn def create_tab(self, *widgets): """Create simple tab widget page: widgets added in a vertical layout""" widget = QWidget() layout = QVBoxLayout() for widg in widgets: layout.addWidget(widg) layout.addStretch(1) widget.setLayout(layout) return widget class PluginConfigPage(SpyderConfigPage): """Plugin configuration dialog box page widget""" def __init__(self, plugin, parent): self.plugin = plugin self.get_option = plugin.get_option self.set_option = plugin.set_option self.get_font = plugin.get_plugin_font self.apply_settings = plugin.apply_plugin_settings SpyderConfigPage.__init__(self, parent) def get_name(self): return self.plugin.get_plugin_title() def get_icon(self): return self.plugin.get_plugin_icon() class GeneralConfigPage(SpyderConfigPage): """Config page that maintains reference to main Spyder window and allows to specify page name and icon declaratively """ CONF_SECTION = None NAME = None # configuration page name, e.g. _("General") ICON = None # name of icon resource (24x24) def __init__(self, parent, main): SpyderConfigPage.__init__(self, parent) self.main = main def get_name(self): """Configuration page name""" return self.NAME def get_icon(self): """Loads page icon named by self.ICON""" return self.ICON def apply_settings(self, options): raise NotImplementedError def prompt_restart_required(self): """Prompt the user with a request to restart.""" restart_opts = self.restart_options changed_opts = self.changed_options options = [restart_opts[o] for o in changed_opts if o in restart_opts] if len(options) == 1: msg_start = _("Spyder needs to restart to change the following " "setting:") else: msg_start = _("Spyder needs to restart to change the following " "settings:") msg_end = _("Do you wish to restart now?") msg_options = u"" for option in options: msg_options += u"
  • {0}
  • ".format(option) msg_title = _("Information") msg = u"{0}
      {1}

    {2}".format(msg_start, msg_options, msg_end) answer = QMessageBox.information(self, msg_title, msg, QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: self.restart() def restart(self): """Restart Spyder.""" self.main.restart() class MainConfigPage(GeneralConfigPage): CONF_SECTION = "main" NAME = _("General") def setup_page(self): self.ICON = ima.icon('genprefs') newcb = self.create_checkbox # --- Interface general_group = QGroupBox(_("General")) languages = LANGUAGE_CODES.items() language_choices = sorted([(val, key) for key, val in languages]) language_combo = self.create_combobox(_('Language'), language_choices, 'interface_language', restart=True) single_instance_box = newcb(_("Use a single instance"), 'single_instance', tip=_("Set this to open external
    " "Python files in an already running " "instance (Requires a restart)")) prompt_box = newcb(_("Prompt when exiting"), 'prompt_on_exit') popup_console_box = newcb(_("Pop up internal console when internal " "errors appear"), 'show_internal_console_if_traceback') check_updates = newcb(_("Check for updates on startup"), 'check_updates_on_startup') # Decide if it's possible to activate or not single instance mode if running_in_mac_app(): self.set_option("single_instance", True) single_instance_box.setEnabled(False) general_layout = QVBoxLayout() general_layout.addWidget(language_combo) general_layout.addWidget(single_instance_box) general_layout.addWidget(prompt_box) general_layout.addWidget(popup_console_box) general_layout.addWidget(check_updates) general_group.setLayout(general_layout) # --- Theme interface_group = QGroupBox(_("Interface")) styles = [str(txt) for txt in list(QStyleFactory.keys())] # Don't offer users the possibility to change to a different # style in Gtk-based desktops # Fixes Issue 2036 if is_gtk_desktop() and ('GTK+' in styles): styles = ['GTK+'] choices = list(zip(styles, [style.lower() for style in styles])) style_combo = self.create_combobox(_('Qt windows style'), choices, 'windows_style', default=self.main.default_style) themes = ['Spyder 2', 'Spyder 3'] icon_choices = list(zip(themes, [theme.lower() for theme in themes])) icons_combo = self.create_combobox(_('Icon theme'), icon_choices, 'icon_theme', restart=True) vertdock_box = newcb(_("Vertical title bars in panes"), 'vertical_dockwidget_titlebars') verttabs_box = newcb(_("Vertical tabs in panes"), 'vertical_tabs') animated_box = newcb(_("Animated toolbars and panes"), 'animated_docks') tear_off_box = newcb(_("Tear off menus"), 'tear_off_menus', tip=_("Set this to detach any
    " "menu from the main window")) margin_box = newcb(_("Custom margin for panes:"), 'use_custom_margin') margin_spin = self.create_spinbox("", _("pixels"), 'custom_margin', 0, 0, 30) margin_box.toggled.connect(margin_spin.spinbox.setEnabled) margin_box.toggled.connect(margin_spin.slabel.setEnabled) margin_spin.spinbox.setEnabled(self.get_option('use_custom_margin')) margin_spin.slabel.setEnabled(self.get_option('use_custom_margin')) cursor_box = newcb(_("Cursor blinking:"), 'use_custom_cursor_blinking') cursor_spin = self.create_spinbox("", _("ms"), 'custom_cursor_blinking', default = QApplication.cursorFlashTime(), min_=0, max_=5000, step=100) cursor_box.toggled.connect(cursor_spin.spinbox.setEnabled) cursor_box.toggled.connect(cursor_spin.slabel.setEnabled) cursor_spin.spinbox.setEnabled( self.get_option('use_custom_cursor_blinking')) cursor_spin.slabel.setEnabled( self.get_option('use_custom_cursor_blinking')) margins_cursor_layout = QGridLayout() margins_cursor_layout.addWidget(margin_box, 0, 0) margins_cursor_layout.addWidget(margin_spin.spinbox, 0, 1) margins_cursor_layout.addWidget(margin_spin.slabel, 0, 2) margins_cursor_layout.addWidget(cursor_box, 1, 0) margins_cursor_layout.addWidget(cursor_spin.spinbox, 1, 1) margins_cursor_layout.addWidget(cursor_spin.slabel, 1, 2) margins_cursor_layout.setColumnStretch(2, 100) # Layout interface comboboxes_layout = QHBoxLayout() cbs_layout = QGridLayout() cbs_layout.addWidget(style_combo.label, 0, 0) cbs_layout.addWidget(style_combo.combobox, 0, 1) cbs_layout.addWidget(icons_combo.label, 1, 0) cbs_layout.addWidget(icons_combo.combobox, 1, 1) comboboxes_layout.addLayout(cbs_layout) comboboxes_layout.addStretch(1) interface_layout = QVBoxLayout() interface_layout.addLayout(comboboxes_layout) interface_layout.addWidget(vertdock_box) interface_layout.addWidget(verttabs_box) interface_layout.addWidget(animated_box) interface_layout.addWidget(tear_off_box) interface_layout.addLayout(margins_cursor_layout) interface_group.setLayout(interface_layout) # --- Status bar sbar_group = QGroupBox(_("Status bar")) show_status_bar = newcb(_("Show status bar"), 'show_status_bar') memory_box = newcb(_("Show memory usage every"), 'memory_usage/enable', tip=self.main.mem_status.toolTip()) memory_spin = self.create_spinbox("", _(" ms"), 'memory_usage/timeout', min_=100, max_=1000000, step=100) memory_box.toggled.connect(memory_spin.setEnabled) memory_spin.setEnabled(self.get_option('memory_usage/enable')) memory_box.setEnabled(self.main.mem_status.is_supported()) memory_spin.setEnabled(self.main.mem_status.is_supported()) cpu_box = newcb(_("Show CPU usage every"), 'cpu_usage/enable', tip=self.main.cpu_status.toolTip()) cpu_spin = self.create_spinbox("", _(" ms"), 'cpu_usage/timeout', min_=100, max_=1000000, step=100) cpu_box.toggled.connect(cpu_spin.setEnabled) cpu_spin.setEnabled(self.get_option('cpu_usage/enable')) cpu_box.setEnabled(self.main.cpu_status.is_supported()) cpu_spin.setEnabled(self.main.cpu_status.is_supported()) status_bar_o = self.get_option('show_status_bar') show_status_bar.toggled.connect(memory_box.setEnabled) show_status_bar.toggled.connect(memory_spin.setEnabled) show_status_bar.toggled.connect(cpu_box.setEnabled) show_status_bar.toggled.connect(cpu_spin.setEnabled) memory_box.setEnabled(status_bar_o) memory_spin.setEnabled(status_bar_o) cpu_box.setEnabled(status_bar_o) cpu_spin.setEnabled(status_bar_o) # Layout status bar cpu_memory_layout = QGridLayout() cpu_memory_layout.addWidget(memory_box, 0, 0) cpu_memory_layout.addWidget(memory_spin, 0, 1) cpu_memory_layout.addWidget(cpu_box, 1, 0) cpu_memory_layout.addWidget(cpu_spin, 1, 1) sbar_layout = QVBoxLayout() sbar_layout.addWidget(show_status_bar) sbar_layout.addLayout(cpu_memory_layout) sbar_group.setLayout(sbar_layout) # --- Screen resolution Group (hidpi) screen_resolution_group = QGroupBox(_("Screen resolution")) screen_resolution_bg = QButtonGroup(screen_resolution_group) screen_resolution_label = QLabel(_("Configuration for high DPI " "screens

    " "Please see " "{0}<> " "for more information about " "these options (in " "English).").format(HDPI_QT_PAGE)) screen_resolution_label.setWordWrap(True) normal_radio = self.create_radiobutton( _("Normal"), 'normal_screen_resolution', button_group=screen_resolution_bg) auto_scale_radio = self.create_radiobutton( _("Enable auto high DPI scaling"), 'high_dpi_scaling', button_group=screen_resolution_bg, tip=_("Set this for high DPI displays"), restart=True) custom_scaling_radio = self.create_radiobutton( _("Set a custom high DPI scaling"), 'high_dpi_custom_scale_factor', button_group=screen_resolution_bg, tip=_("Set this for high DPI displays when " "auto scaling does not work"), restart=True) custom_scaling_edit = self.create_lineedit("", 'high_dpi_custom_scale_factors', tip=_("Enter values for different screens " "separated by semicolons ';', " "float values are supported"), alignment=Qt.Horizontal, regex="[0-9]+(?:\.[0-9]*)(;[0-9]+(?:\.[0-9]*))*", restart=True) normal_radio.toggled.connect(custom_scaling_edit.setDisabled) auto_scale_radio.toggled.connect(custom_scaling_edit.setDisabled) custom_scaling_radio.toggled.connect(custom_scaling_edit.setEnabled) # Layout Screen resolution screen_resolution_layout = QVBoxLayout() screen_resolution_layout.addWidget(screen_resolution_label) screen_resolution_inner_layout = QGridLayout() screen_resolution_inner_layout.addWidget(normal_radio, 0, 0) screen_resolution_inner_layout.addWidget(auto_scale_radio, 1, 0) screen_resolution_inner_layout.addWidget(custom_scaling_radio, 2, 0) screen_resolution_inner_layout.addWidget(custom_scaling_edit, 2, 1) screen_resolution_layout.addLayout(screen_resolution_inner_layout) screen_resolution_group.setLayout(screen_resolution_layout) # --- Theme and fonts plain_text_font = self.create_fontgroup( option='font', title=_("Plain text font"), fontfilters=QFontComboBox.MonospacedFonts, without_group=True) rich_text_font = self.create_fontgroup( option='rich_font', title=_("Rich text font"), without_group=True) fonts_group = QGroupBox(_("Fonts")) fonts_layout = QGridLayout() fonts_layout.addWidget(plain_text_font.fontlabel, 0, 0) fonts_layout.addWidget(plain_text_font.fontbox, 0, 1) fonts_layout.addWidget(plain_text_font.sizelabel, 0, 2) fonts_layout.addWidget(plain_text_font.sizebox, 0, 3) fonts_layout.addWidget(rich_text_font.fontlabel, 1, 0) fonts_layout.addWidget(rich_text_font.fontbox, 1, 1) fonts_layout.addWidget(rich_text_font.sizelabel, 1, 2) fonts_layout.addWidget(rich_text_font.sizebox, 1, 3) fonts_group.setLayout(fonts_layout) tabs = QTabWidget() tabs.addTab(self.create_tab(fonts_group, screen_resolution_group, interface_group), _("Appearance")) tabs.addTab(self.create_tab(general_group, sbar_group), _("Advanced Settings")) vlayout = QVBoxLayout() vlayout.addWidget(tabs) self.setLayout(vlayout) def get_font(self, option): """Return global font used in Spyder.""" return get_font(option=option) def set_font(self, font, option): """Set global font used in Spyder.""" # Update fonts in all plugins set_font(font, option=option) plugins = self.main.widgetlist + self.main.thirdparty_plugins for plugin in plugins: plugin.update_font() def apply_settings(self, options): self.main.apply_settings() def _save_lang(self): """ Get selected language setting and save to language configuration file. """ for combobox, (option, _default) in list(self.comboboxes.items()): if option == 'interface_language': data = combobox.itemData(combobox.currentIndex()) value = from_qvariant(data, to_text_string) break save_lang_conf(value) self.set_option('interface_language', value) class ColorSchemeConfigPage(GeneralConfigPage): CONF_SECTION = "color_schemes" NAME = _("Syntax coloring") def setup_page(self): self.ICON = ima.icon('eyedropper') names = self.get_option("names") try: names.pop(names.index(u'Custom')) except ValueError: pass custom_names = self.get_option("custom_names", []) # Widgets about_label = QLabel(_("Here you can select the color scheme used in " "the Editor and all other Spyder plugins.

    " "You can also edit the color schemes provided " "by Spyder or create your own ones by using " "the options provided below.
    ")) edit_button = QPushButton(_("Edit selected")) create_button = QPushButton(_("Create new scheme")) self.delete_button = QPushButton(_("Delete")) self.preview_editor = CodeEditor(self) self.stacked_widget = QStackedWidget(self) self.reset_button = QPushButton(_("Reset")) self.scheme_editor_dialog = SchemeEditor(parent=self, stack=self.stacked_widget) # Widget setup self.scheme_choices_dict = {} about_label.setWordWrap(True) schemes_combobox_widget = self.create_combobox(_('Scheme:'), [('', '')], 'selected') self.schemes_combobox = schemes_combobox_widget.combobox # Layouts vlayout = QVBoxLayout() manage_layout = QVBoxLayout() manage_layout.addWidget(about_label) combo_layout = QHBoxLayout() combo_layout.addWidget(schemes_combobox_widget.label) combo_layout.addWidget(schemes_combobox_widget.combobox) buttons_layout = QVBoxLayout() buttons_layout.addLayout(combo_layout) buttons_layout.addWidget(edit_button) buttons_layout.addWidget(self.reset_button) buttons_layout.addWidget(self.delete_button) buttons_layout.addStretch(1) buttons_layout.addWidget(create_button) preview_layout = QVBoxLayout() preview_layout.addWidget(self.preview_editor) buttons_preview_layout = QHBoxLayout() buttons_preview_layout.addLayout(buttons_layout) buttons_preview_layout.addLayout(preview_layout) manage_layout.addLayout(buttons_preview_layout) manage_group = QGroupBox(_("Manage color schemes")) manage_group.setLayout(manage_layout) vlayout.addWidget(manage_group) self.setLayout(vlayout) # Signals and slots create_button.clicked.connect(self.create_new_scheme) edit_button.clicked.connect(self.edit_scheme) self.reset_button.clicked.connect(self.reset_to_default) self.delete_button.clicked.connect(self.delete_scheme) self.schemes_combobox.currentIndexChanged.connect(self.update_preview) self.schemes_combobox.currentIndexChanged.connect(self.update_buttons) # Setup for name in names: self.scheme_editor_dialog.add_color_scheme_stack(name) for name in custom_names: self.scheme_editor_dialog.add_color_scheme_stack(name, custom=True) self.update_combobox() self.update_preview() def apply_settings(self, options): self.set_option('selected', self.current_scheme) self.main.editor.apply_plugin_settings(['color_scheme_name']) if self.main.ipyconsole is not None: self.main.ipyconsole.apply_plugin_settings(['color_scheme_name']) if self.main.historylog is not None: self.main.historylog.apply_plugin_settings(['color_scheme_name']) if self.main.help is not None: self.main.help.apply_plugin_settings(['color_scheme_name']) self.update_combobox() self.update_preview() # Helpers # ------------------------------------------------------------------------- @property def current_scheme_name(self): return self.schemes_combobox.currentText() @property def current_scheme(self): return self.scheme_choices_dict[self.current_scheme_name] @property def current_scheme_index(self): return self.schemes_combobox.currentIndex() def update_combobox(self): """Recreates the combobox contents.""" index = self.current_scheme_index self.schemes_combobox.blockSignals(True) names = self.get_option("names") try: names.pop(names.index(u'Custom')) except ValueError: pass custom_names = self.get_option("custom_names", []) # Useful for retrieving the actual data for n in names + custom_names: self.scheme_choices_dict[self.get_option('{0}/name'.format(n))] = n if custom_names: choices = names + [None] + custom_names else: choices = names combobox = self.schemes_combobox combobox.clear() for name in choices: if name is None: continue combobox.addItem(self.get_option('{0}/name'.format(name)), name) if custom_names: combobox.insertSeparator(len(names)) self.schemes_combobox.blockSignals(False) self.schemes_combobox.setCurrentIndex(index) def update_buttons(self): """Updates the enable status of delete and reset buttons.""" current_scheme = self.current_scheme names = self.get_option("names") try: names.pop(names.index(u'Custom')) except ValueError: pass delete_enabled = current_scheme not in names self.delete_button.setEnabled(delete_enabled) self.reset_button.setEnabled(not delete_enabled) def update_preview(self, index=None, scheme_name=None): """ Update the color scheme of the preview editor and adds text. Note ---- 'index' is needed, because this is triggered by a signal that sends the selected index. """ text = ('"""A string"""\n\n' '# A comment\n\n' '# %% A cell\n\n' 'class Foo(object):\n' ' def __init__(self):\n' ' bar = 42\n' ' print(bar)\n' ) show_blanks = CONF.get('editor', 'blank_spaces') if scheme_name is None: scheme_name = self.current_scheme self.preview_editor.setup_editor(linenumbers=True, markers=True, tab_mode=False, font=get_font(), show_blanks=show_blanks, color_scheme=scheme_name) self.preview_editor.set_text(text) self.preview_editor.set_language('Python') # Actions # ------------------------------------------------------------------------- def create_new_scheme(self): """Creates a new color scheme with a custom name.""" names = self.get_option('names') custom_names = self.get_option('custom_names', []) # Get the available number this new color scheme counter = len(custom_names) - 1 custom_index = [int(n.split('-')[-1]) for n in custom_names] for i in range(len(custom_names)): if custom_index[i] != i: counter = i - 1 break custom_name = "custom-{0}".format(counter+1) # Add the config settings, based on the current one. custom_names.append(custom_name) self.set_option('custom_names', custom_names) for key in syntaxhighlighters.COLOR_SCHEME_KEYS: name = "{0}/{1}".format(custom_name, key) default_name = "{0}/{1}".format(self.current_scheme, key) option = self.get_option(default_name) self.set_option(name, option) self.set_option('{0}/name'.format(custom_name), custom_name) # Now they need to be loaded! how to make a partial load_from_conf? dlg = self.scheme_editor_dialog dlg.add_color_scheme_stack(custom_name, custom=True) dlg.set_scheme(custom_name) self.load_from_conf() if dlg.exec_(): # This is needed to have the custom name updated on the combobox name = dlg.get_scheme_name() self.set_option('{0}/name'.format(custom_name), name) # The +1 is needed because of the separator in the combobox index = (names + custom_names).index(custom_name) + 1 self.update_combobox() self.schemes_combobox.setCurrentIndex(index) else: # Delete the config .... custom_names.remove(custom_name) self.set_option('custom_names', custom_names) dlg.delete_color_scheme_stack(custom_name) def edit_scheme(self): """Edit current scheme.""" dlg = self.scheme_editor_dialog dlg.set_scheme(self.current_scheme) if dlg.exec_(): # Update temp scheme to reflect instant edits on the preview temporal_color_scheme = dlg.get_edited_color_scheme() for key in temporal_color_scheme: option = "temp/{0}".format(key) value = temporal_color_scheme[key] self.set_option(option, value) self.update_preview(scheme_name='temp') def delete_scheme(self): """Deletes the currently selected custom color scheme.""" scheme_name = self.current_scheme answer = QMessageBox.warning(self, _("Warning"), _("Are you sure you want to delete " "this scheme?"), QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: # Put the combobox in Spyder by default, when deleting a scheme names = self.get_option('names') self.set_scheme('spyder') self.schemes_combobox.setCurrentIndex(names.index('spyder')) self.set_option('selected', 'spyder') # Delete from custom_names custom_names = self.get_option('custom_names', []) if scheme_name in custom_names: custom_names.remove(scheme_name) self.set_option('custom_names', custom_names) # Delete config options for key in syntaxhighlighters.COLOR_SCHEME_KEYS: option = "{0}/{1}".format(scheme_name, key) CONF.remove_option(self.CONF_SECTION, option) CONF.remove_option(self.CONF_SECTION, "{0}/name".format(scheme_name)) self.update_combobox() self.update_preview() def set_scheme(self, scheme_name): """ Set the current stack in the dialog to the scheme with 'scheme_name'. """ dlg = self.scheme_editor_dialog dlg.set_scheme(scheme_name) @Slot() def reset_to_default(self): """Restore initial values for default color schemes.""" # Checks that this is indeed a default scheme scheme = self.current_scheme names = self.get_option('names') if scheme in names: for key in syntaxhighlighters.COLOR_SCHEME_KEYS: option = "{0}/{1}".format(scheme, key) value = CONF.get_default(self.CONF_SECTION, option) self.set_option(option, value) self.load_from_conf() class SchemeEditor(QDialog): """A color scheme editor dialog.""" def __init__(self, parent=None, stack=None): super(SchemeEditor, self).__init__(parent) self.parent = parent self.stack = stack self.order = [] # Uses scheme names # Needed for self.get_edited_color_scheme() self.widgets = {} self.scheme_name_textbox = {} self.last_edited_color_scheme = None self.last_used_scheme = None # Widgets bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) # Layout layout = QVBoxLayout() layout.addWidget(self.stack) layout.addWidget(bbox) self.setLayout(layout) # Signals bbox.accepted.connect(self.accept) bbox.accepted.connect(self.get_edited_color_scheme) bbox.rejected.connect(self.reject) # Helpers # ------------------------------------------------------------------------- def set_scheme(self, scheme_name): """Set the current stack by 'scheme_name'.""" self.stack.setCurrentIndex(self.order.index(scheme_name)) self.last_used_scheme = scheme_name def get_scheme_name(self): """ Returns the edited scheme name, needed to update the combobox on scheme creation. """ return self.scheme_name_textbox[self.last_used_scheme].text() def get_edited_color_scheme(self): """ Get the values of the last edited color scheme to be used in an instant preview in the preview editor, without using `apply`. """ color_scheme = {} scheme_name = self.last_used_scheme for key in self.widgets[scheme_name]: items = self.widgets[scheme_name][key] if len(items) == 1: # ColorLayout value = items[0].text() else: # ColorLayout + checkboxes value = (items[0].text(), items[1].isChecked(), items[2].isChecked()) color_scheme[key] = value return color_scheme # Actions # ------------------------------------------------------------------------- def add_color_scheme_stack(self, scheme_name, custom=False): """Add a stack for a given scheme and connects the CONF values.""" color_scheme_groups = [ (_('Text'), ["normal", "comment", "string", "number", "keyword", "builtin", "definition", "instance", ]), (_('Highlight'), ["currentcell", "currentline", "occurrence", "matched_p", "unmatched_p", "ctrlclick"]), (_('Background'), ["background", "sideareas"]) ] parent = self.parent line_edit = parent.create_lineedit(_("Scheme name:"), '{0}/name'.format(scheme_name)) self.widgets[scheme_name] = {} # Widget setup line_edit.label.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.setWindowTitle(_('Color scheme editor')) # Layout name_layout = QHBoxLayout() name_layout.addWidget(line_edit.label) name_layout.addWidget(line_edit.textbox) self.scheme_name_textbox[scheme_name] = line_edit.textbox if not custom: line_edit.textbox.setDisabled(True) cs_layout = QVBoxLayout() cs_layout.addLayout(name_layout) h_layout = QHBoxLayout() v_layout = QVBoxLayout() for index, item in enumerate(color_scheme_groups): group_name, keys = item group_layout = QGridLayout() for row, key in enumerate(keys): option = "{0}/{1}".format(scheme_name, key) value = self.parent.get_option(option) name = syntaxhighlighters.COLOR_SCHEME_KEYS[key] if is_text_string(value): label, clayout = parent.create_coloredit( name, option, without_layout=True, ) label.setAlignment(Qt.AlignRight | Qt.AlignVCenter) group_layout.addWidget(label, row+1, 0) group_layout.addLayout(clayout, row+1, 1) # Needed to update temp scheme to obtain instant preview self.widgets[scheme_name][key] = [clayout] else: label, clayout, cb_bold, cb_italic = parent.create_scedit( name, option, without_layout=True, ) label.setAlignment(Qt.AlignRight | Qt.AlignVCenter) group_layout.addWidget(label, row+1, 0) group_layout.addLayout(clayout, row+1, 1) group_layout.addWidget(cb_bold, row+1, 2) group_layout.addWidget(cb_italic, row+1, 3) # Needed to update temp scheme to obtain instant preview self.widgets[scheme_name][key] = [clayout, cb_bold, cb_italic] group_box = QGroupBox(group_name) group_box.setLayout(group_layout) if index == 0: h_layout.addWidget(group_box) else: v_layout.addWidget(group_box) h_layout.addLayout(v_layout) cs_layout.addLayout(h_layout) stackitem = QWidget() stackitem.setLayout(cs_layout) self.stack.addWidget(stackitem) self.order.append(scheme_name) def delete_color_scheme_stack(self, scheme_name): """Remove stack widget by 'scheme_name'.""" self.set_scheme(scheme_name) widget = self.stack.currentWidget() self.stack.removeWidget(widget) index = self.order.index(scheme_name) self.order.pop(index) spyder-3.2.6/spyder/plugins/onlinehelp.py0000664000175000017500000000630713224740762021335 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Online Help Plugin""" # Standard library imports import os.path as osp # Third party imports from qtpy.QtCore import Signal # Local imports from spyder.config.base import _, get_conf_path from spyder.plugins import SpyderPluginMixin from spyder.py3compat import to_text_string from spyder.widgets.pydocgui import PydocBrowser class OnlineHelp(PydocBrowser, SpyderPluginMixin): """ Online Help Plugin """ sig_option_changed = Signal(str, object) CONF_SECTION = 'onlinehelp' LOG_PATH = get_conf_path(CONF_SECTION) def __init__(self, parent): self.main = parent PydocBrowser.__init__(self, parent) SpyderPluginMixin.__init__(self, parent) # Initialize plugin self.initialize_plugin() self.register_widget_shortcuts(self.find_widget) self.webview.set_zoom_factor(self.get_option('zoom_factor')) self.url_combo.setMaxCount(self.get_option('max_history_entries')) self.url_combo.addItems( self.load_history() ) #------ Public API --------------------------------------------------------- def load_history(self, obj=None): """Load history from a text file in user home directory""" if osp.isfile(self.LOG_PATH): history = [line.replace('\n', '') for line in open(self.LOG_PATH, 'r').readlines()] else: history = [] return history def save_history(self): """Save history to a text file in user home directory""" open(self.LOG_PATH, 'w').write("\n".join( \ [to_text_string(self.url_combo.itemText(index)) for index in range(self.url_combo.count())] )) #------ SpyderPluginMixin API --------------------------------------------- def visibility_changed(self, enable): """DockWidget visibility has changed""" SpyderPluginMixin.visibility_changed(self, enable) if enable and not self.is_server_running(): self.initialize() #------ SpyderPluginWidget API --------------------------------------------- def get_plugin_title(self): """Return widget title""" return _('Online help') def get_focus_widget(self): """ Return the widget to give focus to when this plugin's dockwidget is raised on top-level """ self.url_combo.lineEdit().selectAll() return self.url_combo def closing_plugin(self, cancelable=False): """Perform actions before parent main window is closed""" self.save_history() self.set_option('zoom_factor', self.webview.get_zoom_factor()) return True def refresh_plugin(self): """Refresh widget""" pass def get_plugin_actions(self): """Return a list of actions related to plugin""" return [] def register_plugin(self): """Register plugin in Spyder's main window""" self.main.add_dockwidget(self) spyder-3.2.6/spyder/plugins/outlineexplorer.py0000664000175000017500000001051513224740762022434 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Outline Explorer Plugin Data for outline are provided by method .get_outlineexplorer_data() of highlighter of assigned editor. For example, for Python files code editor uses highlighter spyder.utils.syntaxhighlighters.PythonSH """ # Third party imports from qtpy.QtCore import Signal # Local imports from spyder.config.base import _ from spyder.plugins import SpyderPluginMixin from spyder.py3compat import is_text_string from spyder.utils import icon_manager as ima from spyder.widgets.editortools import OutlineExplorerWidget class OutlineExplorer(OutlineExplorerWidget, SpyderPluginMixin): CONF_SECTION = 'outline_explorer' sig_option_changed = Signal(str, object) def __init__(self, parent=None, fullpath_sorting=True): show_fullpath = self.get_option('show_fullpath') show_all_files = self.get_option('show_all_files') show_comments = self.get_option('show_comments') OutlineExplorerWidget.__init__(self, parent=parent, show_fullpath=show_fullpath, fullpath_sorting=fullpath_sorting, show_all_files=show_all_files, show_comments=show_comments) SpyderPluginMixin.__init__(self, parent) # Initialize plugin self.initialize_plugin() self.treewidget.header().hide() self.load_config() #------ SpyderPluginWidget API --------------------------------------------- def get_plugin_title(self): """Return widget title""" return _("Outline") def get_plugin_icon(self): """Return widget icon""" return ima.icon('outline_explorer') def get_focus_widget(self): """ Return the widget to give focus to when this plugin's dockwidget is raised on top-level """ return self.treewidget def get_plugin_actions(self): """Return a list of actions related to plugin""" return [] def register_plugin(self): """Register plugin in Spyder's main window""" self.main.restore_scrollbar_position.connect( self.restore_scrollbar_position) self.main.add_dockwidget(self) def refresh_plugin(self): """Refresh project explorer widget""" pass def closing_plugin(self, cancelable=False): """Perform actions before parent main window is closed""" self.save_config() return True #------ SpyderPluginMixin API --------------------------------------------- def visibility_changed(self, enable): """DockWidget visibility has changed""" SpyderPluginMixin.visibility_changed(self, enable) if enable: self.outlineexplorer_is_visible.emit() #------ Public API --------------------------------------------------------- def restore_scrollbar_position(self): """Restoring scrollbar position after main window is visible""" scrollbar_pos = self.get_option('scrollbar_position', None) if scrollbar_pos is not None: self.treewidget.set_scrollbar_position(scrollbar_pos) def save_config(self): """Save configuration: tree widget state""" for option, value in list(self.get_options().items()): self.set_option(option, value) self.set_option('expanded_state', self.treewidget.get_expanded_state()) self.set_option('scrollbar_position', self.treewidget.get_scrollbar_position()) def load_config(self): """Load configuration: tree widget state""" expanded_state = self.get_option('expanded_state', None) # Sometimes the expanded state option may be truncated in .ini file # (for an unknown reason), in this case it would be converted to a # string by 'userconfig': if is_text_string(expanded_state): expanded_state = None if expanded_state is not None: self.treewidget.set_expanded_state(expanded_state) spyder-3.2.6/spyder/plugins/editor.py0000664000175000017500000037110013224740762020462 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Editor Plugin""" # pylint: disable=C0103 # pylint: disable=R0903 # pylint: disable=R0911 # pylint: disable=R0201 # Standard library imports import os import os.path as osp import re import time # Third party imports from qtpy import API, PYQT5 from qtpy.compat import from_qvariant, getopenfilenames, to_qvariant from qtpy.QtCore import QByteArray, Qt, Signal, Slot from qtpy.QtGui import QKeySequence from qtpy.QtPrintSupport import QAbstractPrintDialog, QPrintDialog, QPrinter from qtpy.QtWidgets import (QAction, QActionGroup, QApplication, QDialog, QFileDialog, QGridLayout, QGroupBox, QHBoxLayout, QInputDialog, QLabel, QMenu, QSplitter, QTabWidget, QToolBar, QVBoxLayout, QWidget) # Local imports from spyder import dependencies from spyder.config.base import _, get_conf_path, PYTEST from spyder.config.main import (CONF, RUN_CELL_SHORTCUT, RUN_CELL_AND_ADVANCE_SHORTCUT) from spyder.config.utils import (get_edit_filetypes, get_edit_filters, get_filter) from spyder.py3compat import PY2, qbytearray_to_str, to_text_string from spyder.utils import codeanalysis, encoding, programs, sourcecode from spyder.utils import icon_manager as ima from spyder.utils.introspection.manager import IntrospectionManager from spyder.utils.qthelpers import create_action, add_actions, MENU_SEPARATOR from spyder.utils.misc import getcwd_or_home from spyder.widgets.findreplace import FindReplace from spyder.widgets.editor import (EditorMainWindow, EditorSplitter, EditorStack, Printer) from spyder.widgets.sourcecode.codeeditor import CodeEditor from spyder.widgets.status import (CursorPositionStatus, EncodingStatus, EOLStatus, ReadWriteStatus) from spyder.plugins import SpyderPluginWidget from spyder.plugins.configdialog import PluginConfigPage from spyder.plugins.runconfig import (ALWAYS_OPEN_FIRST_RUN_OPTION, get_run_configuration, RunConfigDialog, RunConfigOneDialog) # Dependencies NBCONVERT_REQVER = ">=4.0" dependencies.add("nbconvert", _("Manipulate Jupyter notebooks on the Editor"), required_version=NBCONVERT_REQVER) def _load_all_breakpoints(): bp_dict = CONF.get('run', 'breakpoints', {}) for filename in list(bp_dict.keys()): if not osp.isfile(filename): bp_dict.pop(filename) return bp_dict def load_breakpoints(filename): breakpoints = _load_all_breakpoints().get(filename, []) if breakpoints and isinstance(breakpoints[0], int): # Old breakpoints format breakpoints = [(lineno, None) for lineno in breakpoints] return breakpoints def save_breakpoints(filename, breakpoints): if not osp.isfile(filename): return bp_dict = _load_all_breakpoints() bp_dict[filename] = breakpoints CONF.set('run', 'breakpoints', bp_dict) def clear_all_breakpoints(): CONF.set('run', 'breakpoints', {}) def clear_breakpoint(filename, lineno): breakpoints = load_breakpoints(filename) if breakpoints: for breakpoint in breakpoints[:]: if breakpoint[0] == lineno: breakpoints.remove(breakpoint) save_breakpoints(filename, breakpoints) WINPDB_PATH = programs.find_program('winpdb') class EditorConfigPage(PluginConfigPage): def get_name(self): return _("Editor") def get_icon(self): return ima.icon('edit') def setup_page(self): template_btn = self.create_button(_("Edit template for new modules"), self.plugin.edit_template) interface_group = QGroupBox(_("Interface")) newcb = self.create_checkbox showtabbar_box = newcb(_("Show tab bar"), 'show_tab_bar') interface_layout = QVBoxLayout() interface_layout.addWidget(showtabbar_box) interface_group.setLayout(interface_layout) display_group = QGroupBox(_("Source code")) linenumbers_box = newcb(_("Show line numbers"), 'line_numbers') blanks_box = newcb(_("Show blank spaces"), 'blank_spaces') edgeline_box = newcb(_("Show vertical line after"), 'edge_line') edgeline_spin = self.create_spinbox("", _("characters"), 'edge_line_column', 79, 1, 500) edgeline_box.toggled.connect(edgeline_spin.spinbox.setEnabled) edgeline_box.toggled.connect(edgeline_spin.slabel.setEnabled) edgeline_spin.spinbox.setEnabled(self.get_option('edge_line')) edgeline_spin.slabel.setEnabled(self.get_option('edge_line')) currentline_box = newcb(_("Highlight current line"), 'highlight_current_line') currentcell_box = newcb(_("Highlight current cell"), 'highlight_current_cell') occurrence_box = newcb(_("Highlight occurrences after"), 'occurrence_highlighting') occurrence_spin = self.create_spinbox("", _(" ms"), 'occurrence_highlighting/timeout', min_=100, max_=1000000, step=100) occurrence_box.toggled.connect(occurrence_spin.spinbox.setEnabled) occurrence_box.toggled.connect(occurrence_spin.slabel.setEnabled) occurrence_spin.spinbox.setEnabled( self.get_option('occurrence_highlighting')) occurrence_spin.slabel.setEnabled( self.get_option('occurrence_highlighting')) wrap_mode_box = newcb(_("Wrap lines"), 'wrap') display_layout = QGridLayout() display_layout.addWidget(linenumbers_box, 0, 0) display_layout.addWidget(blanks_box, 1, 0) display_layout.addWidget(edgeline_box, 2, 0) display_layout.addWidget(edgeline_spin.spinbox, 2, 1) display_layout.addWidget(edgeline_spin.slabel, 2, 2) display_layout.addWidget(currentline_box, 3, 0) display_layout.addWidget(currentcell_box, 4, 0) display_layout.addWidget(occurrence_box, 5, 0) display_layout.addWidget(occurrence_spin.spinbox, 5, 1) display_layout.addWidget(occurrence_spin.slabel, 5, 2) display_layout.addWidget(wrap_mode_box, 6, 0) display_h_layout = QHBoxLayout() display_h_layout.addLayout(display_layout) display_h_layout.addStretch(1) display_group.setLayout(display_h_layout) run_group = QGroupBox(_("Run")) saveall_box = newcb(_("Save all files before running script"), 'save_all_before_run') run_selection_group = QGroupBox(_("Run selection")) focus_box = newcb(_("Maintain focus in the Editor after running cells " "or selections"), 'focus_to_editor') introspection_group = QGroupBox(_("Introspection")) rope_is_installed = programs.is_module_installed('rope') if rope_is_installed: completion_box = newcb(_("Automatic code completion"), 'codecompletion/auto') case_comp_box = newcb(_("Case sensitive code completion"), 'codecompletion/case_sensitive') comp_enter_box = newcb(_("Enter key selects completion"), 'codecompletion/enter_key') calltips_box = newcb(_("Display balloon tips"), 'calltips') gotodef_box = newcb(_("Link to object definition"), 'go_to_definition', tip=_("If this option is enabled, clicking on an object\n" "name (left-click + Ctrl key) will go this object\n" "definition (if resolved).")) else: rope_label = QLabel(_("Warning:
    " "The Python module rope is not " "installed on this computer: calltips, " "code completion and go-to-definition " "features won't be available.")) rope_label.setWordWrap(True) sourcecode_group = QGroupBox(_("Source code")) closepar_box = newcb(_("Automatic insertion of parentheses, braces " "and brackets"), 'close_parentheses') close_quotes_box = newcb(_("Automatic insertion of closing quotes"), 'close_quotes') add_colons_box = newcb(_("Automatic insertion of colons after 'for', " "'if', 'def', etc"), 'add_colons') autounindent_box = newcb(_("Automatic indentation after 'else', " "'elif', etc."), 'auto_unindent') indent_chars_box = self.create_combobox(_("Indentation characters: "), ((_("2 spaces"), '* *'), (_("3 spaces"), '* *'), (_("4 spaces"), '* *'), (_("5 spaces"), '* *'), (_("6 spaces"), '* *'), (_("7 spaces"), '* *'), (_("8 spaces"), '* *'), (_("Tabulations"), '*\t*')), 'indent_chars') tabwidth_spin = self.create_spinbox(_("Tab stop width:"), _("spaces"), 'tab_stop_width_spaces', 4, 1, 8, 1) def enable_tabwidth_spin(index): if index == 7: # Tabulations tabwidth_spin.plabel.setEnabled(True) tabwidth_spin.spinbox.setEnabled(True) else: tabwidth_spin.plabel.setEnabled(False) tabwidth_spin.spinbox.setEnabled(False) indent_chars_box.combobox.currentIndexChanged.connect(enable_tabwidth_spin) tab_mode_box = newcb(_("Tab always indent"), 'tab_always_indent', default=False, tip=_("If enabled, pressing Tab will always indent,\n" "even when the cursor is not at the beginning\n" "of a line (when this option is enabled, code\n" "completion may be triggered using the alternate\n" "shortcut: Ctrl+Space)")) ibackspace_box = newcb(_("Intelligent backspace"), 'intelligent_backspace', default=True) removetrail_box = newcb(_("Automatically remove trailing spaces " "when saving files"), 'always_remove_trailing_spaces', default=False) analysis_group = QGroupBox(_("Analysis")) pep_url = 'PEP8' pep8_label = QLabel(_("(Refer to the {} page)").format(pep_url)) pep8_label.setOpenExternalLinks(True) is_pyflakes = codeanalysis.is_pyflakes_installed() is_pep8 = codeanalysis.get_checker_executable( 'pycodestyle') is not None pyflakes_box = newcb(_("Real-time code analysis"), 'code_analysis/pyflakes', default=True, tip=_("

    If enabled, Python source code will be analyzed " "using pyflakes, lines containing errors or " "warnings will be highlighted.

    " "

    Note: add analysis:ignore in " "a comment to ignore code analysis " "warnings.

    ")) pyflakes_box.setEnabled(is_pyflakes) if not is_pyflakes: pyflakes_box.setToolTip(_("Code analysis requires pyflakes %s+") % codeanalysis.PYFLAKES_REQVER) pep8_box = newcb(_("Real-time code style analysis"), 'code_analysis/pep8', default=False, tip=_("

    If enabled, Python source code will be analyzed " "using pycodestyle, lines that are not following PEP8 " "style guide will be highlighted.

    " "

    Note: add analysis:ignore in " "a comment to ignore style analysis " "warnings.

    ")) pep8_box.setEnabled(is_pep8) todolist_box = newcb(_("Code annotations (TODO, FIXME, XXX, HINT, TIP," " @todo, HACK, BUG, OPTIMIZE, !!!, ???)"), 'todo_list', default=True) realtime_radio = self.create_radiobutton( _("Perform analysis when " "saving file and every"), 'realtime_analysis', True) saveonly_radio = self.create_radiobutton( _("Perform analysis only " "when saving file"), 'onsave_analysis') af_spin = self.create_spinbox("", _(" ms"), 'realtime_analysis/timeout', min_=100, max_=1000000, step=100) af_layout = QHBoxLayout() af_layout.addWidget(realtime_radio) af_layout.addWidget(af_spin) run_layout = QVBoxLayout() run_layout.addWidget(saveall_box) run_group.setLayout(run_layout) run_selection_layout = QVBoxLayout() run_selection_layout.addWidget(focus_box) run_selection_group.setLayout(run_selection_layout) introspection_layout = QVBoxLayout() if rope_is_installed: introspection_layout.addWidget(calltips_box) introspection_layout.addWidget(completion_box) introspection_layout.addWidget(case_comp_box) introspection_layout.addWidget(comp_enter_box) introspection_layout.addWidget(gotodef_box) else: introspection_layout.addWidget(rope_label) introspection_group.setLayout(introspection_layout) analysis_layout = QVBoxLayout() analysis_layout.addWidget(pyflakes_box) analysis_pep_layout = QHBoxLayout() analysis_pep_layout.addWidget(pep8_box) analysis_pep_layout.addWidget(pep8_label) analysis_layout.addLayout(analysis_pep_layout) analysis_layout.addWidget(todolist_box) analysis_layout.addLayout(af_layout) analysis_layout.addWidget(saveonly_radio) analysis_group.setLayout(analysis_layout) sourcecode_layout = QVBoxLayout() sourcecode_layout.addWidget(closepar_box) sourcecode_layout.addWidget(autounindent_box) sourcecode_layout.addWidget(add_colons_box) sourcecode_layout.addWidget(close_quotes_box) indent_tab_layout = QHBoxLayout() indent_tab_grid_layout = QGridLayout() indent_tab_grid_layout.addWidget(indent_chars_box.label, 0, 0) indent_tab_grid_layout.addWidget(indent_chars_box.combobox, 0, 1) indent_tab_grid_layout.addWidget(tabwidth_spin.plabel, 1, 0) indent_tab_grid_layout.addWidget(tabwidth_spin.spinbox, 1, 1) indent_tab_grid_layout.addWidget(tabwidth_spin.slabel, 1, 2) indent_tab_layout.addLayout(indent_tab_grid_layout) indent_tab_layout.addStretch(1) sourcecode_layout.addLayout(indent_tab_layout) sourcecode_layout.addWidget(tab_mode_box) sourcecode_layout.addWidget(ibackspace_box) sourcecode_layout.addWidget(removetrail_box) sourcecode_group.setLayout(sourcecode_layout) eol_group = QGroupBox(_("End-of-line characters")) eol_label = QLabel(_("When opening a text file containing " "mixed end-of-line characters (this may " "raise syntax errors in the consoles " "on Windows platforms), Spyder may fix the " "file automatically.")) eol_label.setWordWrap(True) check_eol_box = newcb(_("Fix automatically and show warning " "message box"), 'check_eol_chars', default=True) eol_layout = QVBoxLayout() eol_layout.addWidget(eol_label) eol_layout.addWidget(check_eol_box) eol_group.setLayout(eol_layout) tabs = QTabWidget() tabs.addTab(self.create_tab(interface_group, display_group), _("Display")) tabs.addTab(self.create_tab(introspection_group, analysis_group), _("Code Introspection/Analysis")) tabs.addTab(self.create_tab(template_btn, run_group, run_selection_group, sourcecode_group, eol_group), _("Advanced settings")) vlayout = QVBoxLayout() vlayout.addWidget(tabs) self.setLayout(vlayout) class Editor(SpyderPluginWidget): """ Multi-file Editor widget """ CONF_SECTION = 'editor' CONFIGWIDGET_CLASS = EditorConfigPage TEMPFILE_PATH = get_conf_path('temp.py') TEMPLATE_PATH = get_conf_path('template.py') DISABLE_ACTIONS_WHEN_HIDDEN = False # SpyderPluginWidget class attribute # Signals run_in_current_ipyclient = Signal(str, str, str, bool, bool, bool, bool) exec_in_extconsole = Signal(str, bool) redirect_stdio = Signal(bool) open_dir = Signal(str) breakpoints_saved = Signal() run_in_current_extconsole = Signal(str, str, str, bool, bool) open_file_update = Signal(str) def __init__(self, parent, ignore_last_opened_files=False): if PYQT5: SpyderPluginWidget.__init__(self, parent, main=parent) else: SpyderPluginWidget.__init__(self, parent) self.__set_eol_chars = True # Creating template if it doesn't already exist if not osp.isfile(self.TEMPLATE_PATH): if os.name == "nt": shebang = [] else: shebang = ['#!/usr/bin/env python' + ('2' if PY2 else '3')] header = shebang + [ '# -*- coding: utf-8 -*-', '"""', 'Created on %(date)s', '', '@author: %(username)s', '"""', ''] encoding.write(os.linesep.join(header), self.TEMPLATE_PATH, 'utf-8') self.projects = None self.outlineexplorer = None self.help = None self.editorstacks = None self.editorwindows = None self.editorwindows_to_be_created = None self.file_dependent_actions = [] self.pythonfile_dependent_actions = [] self.dock_toolbar_actions = None self.edit_menu_actions = None #XXX: find another way to notify Spyder # (see spyder.py: 'update_edit_menu' method) self.search_menu_actions = None #XXX: same thing ('update_search_menu') self.stack_menu_actions = None # Initialize plugin self.initialize_plugin() # Configuration dialog size self.dialog_size = None statusbar = self.main.statusBar() self.readwrite_status = ReadWriteStatus(self, statusbar) self.eol_status = EOLStatus(self, statusbar) self.encoding_status = EncodingStatus(self, statusbar) self.cursorpos_status = CursorPositionStatus(self, statusbar) layout = QVBoxLayout() self.dock_toolbar = QToolBar(self) add_actions(self.dock_toolbar, self.dock_toolbar_actions) layout.addWidget(self.dock_toolbar) self.last_edit_cursor_pos = None self.cursor_pos_history = [] self.cursor_pos_index = None self.__ignore_cursor_position = True self.editorstacks = [] self.last_focus_editorstack = {} self.editorwindows = [] self.editorwindows_to_be_created = [] self.toolbar_list = None self.menu_list = None # Don't start IntrospectionManager when running tests because # it consumes a lot of memory if PYTEST and not os.environ.get('SPY_TEST_USE_INTROSPECTION'): try: from unittest.mock import Mock except ImportError: from mock import Mock # Python 2 self.introspector = Mock() else: self.introspector = IntrospectionManager( extra_path=self.main.get_spyder_pythonpath()) # Setup new windows: self.main.all_actions_defined.connect(self.setup_other_windows) # Change module completions when PYTHONPATH changes self.main.sig_pythonpath_changed.connect(self.set_path) # Find widget self.find_widget = FindReplace(self, enable_replace=True) self.find_widget.hide() self.find_widget.visibility_changed.connect( lambda vs: self.rehighlight_cells()) self.register_widget_shortcuts(self.find_widget) # Tabbed editor widget + Find/Replace widget editor_widgets = QWidget(self) editor_layout = QVBoxLayout() editor_layout.setContentsMargins(0, 0, 0, 0) editor_widgets.setLayout(editor_layout) self.editorsplitter = EditorSplitter(self, self, self.stack_menu_actions, first=True) editor_layout.addWidget(self.editorsplitter) editor_layout.addWidget(self.find_widget) # Splitter: editor widgets (see above) + outline explorer self.splitter = QSplitter(self) self.splitter.setContentsMargins(0, 0, 0, 0) self.splitter.addWidget(editor_widgets) self.splitter.setStretchFactor(0, 5) self.splitter.setStretchFactor(1, 1) layout.addWidget(self.splitter) self.setLayout(layout) self.setFocusPolicy(Qt.ClickFocus) # Editor's splitter state state = self.get_option('splitter_state', None) if state is not None: self.splitter.restoreState( QByteArray().fromHex( str(state).encode('utf-8')) ) self.recent_files = self.get_option('recent_files', []) self.untitled_num = 0 # Parameters of last file execution: self.__last_ic_exec = None # internal console self.__last_ec_exec = None # external console # File types and filters used by the Open dialog self.edit_filetypes = None self.edit_filters = None self.__ignore_cursor_position = False current_editor = self.get_current_editor() if current_editor is not None: filename = self.get_current_filename() position = current_editor.get_position('cursor') self.add_cursor_position_to_history(filename, position) self.update_cursorpos_actions() self.set_path() def set_projects(self, projects): self.projects = projects @Slot() def show_hide_projects(self): if self.projects is not None: dw = self.projects.dockwidget if dw.isVisible(): dw.hide() else: dw.show() dw.raise_() self.switch_to_plugin() def set_outlineexplorer(self, outlineexplorer): self.outlineexplorer = outlineexplorer for editorstack in self.editorstacks: editorstack.set_outlineexplorer(self.outlineexplorer) self.editorstacks[0].initialize_outlineexplorer() self.outlineexplorer.edit_goto.connect( lambda filenames, goto, word: self.load(filenames=filenames, goto=goto, word=word, editorwindow=self)) self.outlineexplorer.edit.connect( lambda filenames: self.load(filenames=filenames, editorwindow=self)) def set_help(self, help_plugin): self.help = help_plugin for editorstack in self.editorstacks: editorstack.set_help(self.help) #------ Private API -------------------------------------------------------- def restore_scrollbar_position(self): """Restoring scrollbar position after main window is visible""" # Widget is now visible, we may center cursor on top level editor: try: self.get_current_editor().centerCursor() except AttributeError: pass #------ SpyderPluginWidget API --------------------------------------------- def get_plugin_title(self): """Return widget title""" title = _('Editor') if self.dockwidget: filename = self.get_current_filename() if self.dockwidget.dock_tabbar: if filename and self.dockwidget.dock_tabbar.count() < 2: title += ' - ' + to_text_string(filename) else: title += ' - ' + to_text_string(filename) return title def get_plugin_icon(self): """Return widget icon.""" return ima.icon('edit') def get_focus_widget(self): """ Return the widget to give focus to. This happens when plugin's dockwidget is raised on top-level. """ return self.get_current_editor() def visibility_changed(self, enable): """DockWidget visibility has changed""" SpyderPluginWidget.visibility_changed(self, enable) if self.dockwidget.isWindow(): self.dock_toolbar.show() else: self.dock_toolbar.hide() if enable: self.refresh_plugin() self.update_plugin_title.emit() def refresh_plugin(self): """Refresh editor plugin""" editorstack = self.get_current_editorstack() editorstack.refresh() self.refresh_save_all_action() def closing_plugin(self, cancelable=False): """Perform actions before parent main window is closed""" state = self.splitter.saveState() self.set_option('splitter_state', qbytearray_to_str(state)) filenames = [] editorstack = self.editorstacks[0] active_project_path = None if self.projects is not None: active_project_path = self.projects.get_active_project_path() if not active_project_path: self.set_open_filenames() else: self.projects.set_project_filenames( [finfo.filename for finfo in editorstack.data]) self.set_option('layout_settings', self.editorsplitter.get_layout_settings()) self.set_option('windows_layout_settings', [win.get_layout_settings() for win in self.editorwindows]) # self.set_option('filenames', filenames) self.set_option('recent_files', self.recent_files) try: if not editorstack.save_if_changed(cancelable) and cancelable: return False else: for win in self.editorwindows[:]: win.close() return True except IndexError: return True def get_plugin_actions(self): """Return a list of actions related to plugin""" # ---- File menu and toolbar ---- self.new_action = create_action( self, _("&New file..."), icon=ima.icon('filenew'), tip=_("New file"), triggered=self.new, context=Qt.WidgetShortcut ) self.register_shortcut(self.new_action, context="Editor", name="New file", add_sc_to_tip=True) self.open_last_closed_action = create_action( self, _("O&pen last closed"), tip=_("Open last closed"), triggered=self.open_last_closed ) self.register_shortcut(self.open_last_closed_action, context="Editor", name="Open last closed") self.open_action = create_action(self, _("&Open..."), icon=ima.icon('fileopen'), tip=_("Open file"), triggered=self.load, context=Qt.WidgetShortcut) self.register_shortcut(self.open_action, context="Editor", name="Open file", add_sc_to_tip=True) self.revert_action = create_action(self, _("&Revert"), icon=ima.icon('revert'), tip=_("Revert file from disk"), triggered=self.revert) self.save_action = create_action(self, _("&Save"), icon=ima.icon('filesave'), tip=_("Save file"), triggered=self.save, context=Qt.WidgetShortcut) self.register_shortcut(self.save_action, context="Editor", name="Save file", add_sc_to_tip=True) self.save_all_action = create_action(self, _("Sav&e all"), icon=ima.icon('save_all'), tip=_("Save all files"), triggered=self.save_all, context=Qt.WidgetShortcut) self.register_shortcut(self.save_all_action, context="Editor", name="Save all", add_sc_to_tip=True) save_as_action = create_action(self, _("Save &as..."), None, ima.icon('filesaveas'), tip=_("Save current file as..."), triggered=self.save_as, context=Qt.WidgetShortcut) self.register_shortcut(save_as_action, "Editor", "Save As") save_copy_as_action = create_action(self, _("Save copy as..."), None, ima.icon('filesaveas'), _("Save copy of current file as..."), triggered=self.save_copy_as) print_preview_action = create_action(self, _("Print preview..."), tip=_("Print preview..."), triggered=self.print_preview) self.print_action = create_action(self, _("&Print..."), icon=ima.icon('print'), tip=_("Print current file..."), triggered=self.print_file) # Shortcut for close_action is defined in widgets/editor.py self.close_action = create_action(self, _("&Close"), icon=ima.icon('fileclose'), tip=_("Close current file"), triggered=self.close_file) self.close_all_action = create_action(self, _("C&lose all"), icon=ima.icon('filecloseall'), tip=_("Close all opened files"), triggered=self.close_all_files, context=Qt.WidgetShortcut) self.register_shortcut(self.close_all_action, context="Editor", name="Close all") # ---- Find menu and toolbar ---- _text = _("&Find text") find_action = create_action(self, _text, icon=ima.icon('find'), tip=_text, triggered=self.find, context=Qt.WidgetShortcut) self.register_shortcut(find_action, context="_", name="Find text", add_sc_to_tip=True) find_next_action = create_action(self, _("Find &next"), icon=ima.icon('findnext'), triggered=self.find_next, context=Qt.WidgetShortcut) self.register_shortcut(find_next_action, context="_", name="Find next") find_previous_action = create_action(self, _("Find &previous"), icon=ima.icon('findprevious'), triggered=self.find_previous, context=Qt.WidgetShortcut) self.register_shortcut(find_previous_action, context="_", name="Find previous") _text = _("&Replace text") replace_action = create_action(self, _text, icon=ima.icon('replace'), tip=_text, triggered=self.replace, context=Qt.WidgetShortcut) self.register_shortcut(replace_action, context="_", name="Replace text") # ---- Debug menu and toolbar ---- set_clear_breakpoint_action = create_action(self, _("Set/Clear breakpoint"), icon=ima.icon('breakpoint_big'), triggered=self.set_or_clear_breakpoint, context=Qt.WidgetShortcut) self.register_shortcut(set_clear_breakpoint_action, context="Editor", name="Breakpoint") set_cond_breakpoint_action = create_action(self, _("Set/Edit conditional breakpoint"), icon=ima.icon('breakpoint_cond_big'), triggered=self.set_or_edit_conditional_breakpoint, context=Qt.WidgetShortcut) self.register_shortcut(set_cond_breakpoint_action, context="Editor", name="Conditional breakpoint") clear_all_breakpoints_action = create_action(self, _('Clear breakpoints in all files'), triggered=self.clear_all_breakpoints) self.winpdb_action = create_action(self, _("Debug with winpdb"), triggered=self.run_winpdb) self.winpdb_action.setEnabled(WINPDB_PATH is not None and PY2) # --- Debug toolbar --- debug_action = create_action(self, _("&Debug"), icon=ima.icon('debug'), tip=_("Debug file"), triggered=self.debug_file) self.register_shortcut(debug_action, context="_", name="Debug", add_sc_to_tip=True) debug_next_action = create_action(self, _("Step"), icon=ima.icon('arrow-step-over'), tip=_("Run current line"), triggered=lambda: self.debug_command("next")) self.register_shortcut(debug_next_action, "_", "Debug Step Over", add_sc_to_tip=True) debug_continue_action = create_action(self, _("Continue"), icon=ima.icon('arrow-continue'), tip=_("Continue execution until next breakpoint"), triggered=lambda: self.debug_command("continue")) self.register_shortcut(debug_continue_action, "_", "Debug Continue", add_sc_to_tip=True) debug_step_action = create_action(self, _("Step Into"), icon=ima.icon('arrow-step-in'), tip=_("Step into function or method of current line"), triggered=lambda: self.debug_command("step")) self.register_shortcut(debug_step_action, "_", "Debug Step Into", add_sc_to_tip=True) debug_return_action = create_action(self, _("Step Return"), icon=ima.icon('arrow-step-out'), tip=_("Run until current function or method returns"), triggered=lambda: self.debug_command("return")) self.register_shortcut(debug_return_action, "_", "Debug Step Return", add_sc_to_tip=True) debug_exit_action = create_action(self, _("Stop"), icon=ima.icon('stop_debug'), tip=_("Stop debugging"), triggered=lambda: self.debug_command("exit")) self.register_shortcut(debug_exit_action, "_", "Debug Exit", add_sc_to_tip=True) # --- Run toolbar --- run_action = create_action(self, _("&Run"), icon=ima.icon('run'), tip=_("Run file"), triggered=self.run_file) self.register_shortcut(run_action, context="_", name="Run", add_sc_to_tip=True) configure_action = create_action(self, _("&Configuration per file..."), icon=ima.icon('run_settings'), tip=_("Run settings"), menurole=QAction.NoRole, triggered=self.edit_run_configurations) self.register_shortcut(configure_action, context="_", name="Configure", add_sc_to_tip=True) re_run_action = create_action(self, _("Re-run &last script"), icon=ima.icon('run_again'), tip=_("Run again last file"), triggered=self.re_run_file) self.register_shortcut(re_run_action, context="_", name="Re-run last script", add_sc_to_tip=True) run_selected_action = create_action(self, _("Run &selection or " "current line"), icon=ima.icon('run_selection'), tip=_("Run selection or " "current line"), triggered=self.run_selection, context=Qt.WidgetShortcut) self.register_shortcut(run_selected_action, context="Editor", name="Run selection", add_sc_to_tip=True) run_cell_action = create_action(self, _("Run cell"), icon=ima.icon('run_cell'), shortcut=QKeySequence(RUN_CELL_SHORTCUT), tip=_("Run current cell (Ctrl+Enter)\n" "[Use #%% to create cells]"), triggered=self.run_cell, context=Qt.WidgetShortcut) run_cell_advance_action = create_action(self, _("Run cell and advance"), icon=ima.icon('run_cell_advance'), shortcut=QKeySequence(RUN_CELL_AND_ADVANCE_SHORTCUT), tip=_("Run current cell and go to the next one " "(Shift+Enter)"), triggered=self.run_cell_and_advance, context=Qt.WidgetShortcut) re_run_last_cell_action = create_action(self, _("Re-run last cell"), tip=_("Re run last cell "), triggered=self.re_run_last_cell, context=Qt.WidgetShortcut) self.register_shortcut(re_run_last_cell_action, context="Editor", name='re-run last cell', add_sc_to_tip=True) # --- Source code Toolbar --- self.todo_list_action = create_action(self, _("Show todo list"), icon=ima.icon('todo_list'), tip=_("Show comments list (TODO/FIXME/XXX/HINT/TIP/@todo/" "HACK/BUG/OPTIMIZE/!!!/???)"), triggered=self.go_to_next_todo) self.todo_menu = QMenu(self) self.todo_list_action.setMenu(self.todo_menu) self.todo_menu.aboutToShow.connect(self.update_todo_menu) self.warning_list_action = create_action(self, _("Show warning/error list"), icon=ima.icon('wng_list'), tip=_("Show code analysis warnings/errors"), triggered=self.go_to_next_warning) self.warning_menu = QMenu(self) self.warning_list_action.setMenu(self.warning_menu) self.warning_menu.aboutToShow.connect(self.update_warning_menu) self.previous_warning_action = create_action(self, _("Previous warning/error"), icon=ima.icon('prev_wng'), tip=_("Go to previous code analysis warning/error"), triggered=self.go_to_previous_warning) self.next_warning_action = create_action(self, _("Next warning/error"), icon=ima.icon('next_wng'), tip=_("Go to next code analysis warning/error"), triggered=self.go_to_next_warning) self.previous_edit_cursor_action = create_action(self, _("Last edit location"), icon=ima.icon('last_edit_location'), tip=_("Go to last edit location"), triggered=self.go_to_last_edit_location, context=Qt.WidgetShortcut) self.register_shortcut(self.previous_edit_cursor_action, context="Editor", name="Last edit location", add_sc_to_tip=True) self.previous_cursor_action = create_action(self, _("Previous cursor position"), icon=ima.icon('prev_cursor'), tip=_("Go to previous cursor position"), triggered=self.go_to_previous_cursor_position, context=Qt.WidgetShortcut) self.register_shortcut(self.previous_cursor_action, context="Editor", name="Previous cursor position", add_sc_to_tip=True) self.next_cursor_action = create_action(self, _("Next cursor position"), icon=ima.icon('next_cursor'), tip=_("Go to next cursor position"), triggered=self.go_to_next_cursor_position, context=Qt.WidgetShortcut) self.register_shortcut(self.next_cursor_action, context="Editor", name="Next cursor position", add_sc_to_tip=True) # --- Edit Toolbar --- self.toggle_comment_action = create_action(self, _("Comment")+"/"+_("Uncomment"), icon=ima.icon('comment'), tip=_("Comment current line or selection"), triggered=self.toggle_comment, context=Qt.WidgetShortcut) self.register_shortcut(self.toggle_comment_action, context="Editor", name="Toggle comment") blockcomment_action = create_action(self, _("Add &block comment"), tip=_("Add block comment around " "current line or selection"), triggered=self.blockcomment, context=Qt.WidgetShortcut) self.register_shortcut(blockcomment_action, context="Editor", name="Blockcomment") unblockcomment_action = create_action(self, _("R&emove block comment"), tip = _("Remove comment block around " "current line or selection"), triggered=self.unblockcomment, context=Qt.WidgetShortcut) self.register_shortcut(unblockcomment_action, context="Editor", name="Unblockcomment") # ---------------------------------------------------------------------- # The following action shortcuts are hard-coded in CodeEditor # keyPressEvent handler (the shortcut is here only to inform user): # (context=Qt.WidgetShortcut -> disable shortcut for other widgets) self.indent_action = create_action(self, _("Indent"), "Tab", icon=ima.icon('indent'), tip=_("Indent current line or selection"), triggered=self.indent, context=Qt.WidgetShortcut) self.unindent_action = create_action(self, _("Unindent"), "Shift+Tab", icon=ima.icon('unindent'), tip=_("Unindent current line or selection"), triggered=self.unindent, context=Qt.WidgetShortcut) self.text_uppercase_action = create_action(self, _("Toggle Uppercase"), tip=_("Change to uppercase current line or selection"), triggered=self.text_uppercase, context=Qt.WidgetShortcut) self.register_shortcut(self.text_uppercase_action, context="Editor", name="transform to uppercase") self.text_lowercase_action = create_action(self, _("Toggle Lowercase"), tip=_("Change to lowercase current line or selection"), triggered=self.text_lowercase, context=Qt.WidgetShortcut) self.register_shortcut(self.text_lowercase_action, context="Editor", name="transform to lowercase") # ---------------------------------------------------------------------- self.win_eol_action = create_action(self, _("Carriage return and line feed (Windows)"), toggled=lambda checked: self.toggle_eol_chars('nt', checked)) self.linux_eol_action = create_action(self, _("Line feed (UNIX)"), toggled=lambda checked: self.toggle_eol_chars('posix', checked)) self.mac_eol_action = create_action(self, _("Carriage return (Mac)"), toggled=lambda checked: self.toggle_eol_chars('mac', checked)) eol_action_group = QActionGroup(self) eol_actions = (self.win_eol_action, self.linux_eol_action, self.mac_eol_action) add_actions(eol_action_group, eol_actions) eol_menu = QMenu(_("Convert end-of-line characters"), self) add_actions(eol_menu, eol_actions) trailingspaces_action = create_action(self, _("Remove trailing spaces"), triggered=self.remove_trailing_spaces) self.showblanks_action = create_action(self, _("Show blank spaces"), toggled=self.toggle_show_blanks) fixindentation_action = create_action(self, _("Fix indentation"), tip=_("Replace tab characters by space characters"), triggered=self.fix_indentation) gotoline_action = create_action(self, _("Go to line..."), icon=ima.icon('gotoline'), triggered=self.go_to_line, context=Qt.WidgetShortcut) self.register_shortcut(gotoline_action, context="Editor", name="Go to line") workdir_action = create_action(self, _("Set console working directory"), icon=ima.icon('DirOpenIcon'), tip=_("Set current console (and file explorer) working " "directory to current script directory"), triggered=self.__set_workdir) self.max_recent_action = create_action(self, _("Maximum number of recent files..."), triggered=self.change_max_recent_files) self.clear_recent_action = create_action(self, _("Clear this list"), tip=_("Clear recent files list"), triggered=self.clear_recent_files) # ---- File menu/toolbar construction ---- self.recent_file_menu = QMenu(_("Open &recent"), self) self.recent_file_menu.aboutToShow.connect(self.update_recent_file_menu) file_menu_actions = [self.new_action, MENU_SEPARATOR, self.open_action, self.open_last_closed_action, self.recent_file_menu, MENU_SEPARATOR, MENU_SEPARATOR, self.save_action, self.save_all_action, save_as_action, save_copy_as_action, self.revert_action, MENU_SEPARATOR, print_preview_action, self.print_action, MENU_SEPARATOR, self.close_action, self.close_all_action, MENU_SEPARATOR] self.main.file_menu_actions += file_menu_actions file_toolbar_actions = ([self.new_action, self.open_action, self.save_action, self.save_all_action] + self.main.file_toolbar_actions) self.main.file_toolbar_actions = file_toolbar_actions # ---- Find menu/toolbar construction ---- self.main.search_menu_actions = [find_action, find_next_action, find_previous_action, replace_action] self.main.search_toolbar_actions = [find_action, find_next_action, replace_action] # ---- Edit menu/toolbar construction ---- self.edit_menu_actions = [self.toggle_comment_action, blockcomment_action, unblockcomment_action, self.indent_action, self.unindent_action, self.text_uppercase_action, self.text_lowercase_action] self.main.edit_menu_actions += [MENU_SEPARATOR] + self.edit_menu_actions edit_toolbar_actions = [self.toggle_comment_action, self.unindent_action, self.indent_action] self.main.edit_toolbar_actions += edit_toolbar_actions # ---- Search menu/toolbar construction ---- self.search_menu_actions = [gotoline_action] self.main.search_menu_actions += self.search_menu_actions self.main.search_toolbar_actions += [gotoline_action] # ---- Run menu/toolbar construction ---- run_menu_actions = [run_action, run_cell_action, run_cell_advance_action, re_run_last_cell_action, MENU_SEPARATOR, run_selected_action, re_run_action, configure_action, MENU_SEPARATOR] self.main.run_menu_actions += run_menu_actions run_toolbar_actions = [run_action, run_cell_action, run_cell_advance_action, run_selected_action, re_run_action] self.main.run_toolbar_actions += run_toolbar_actions # ---- Debug menu/toolbar construction ---- # NOTE: 'list_breakpoints' is used by the breakpoints # plugin to add its "List breakpoints" action to this # menu debug_menu_actions = [debug_action, debug_next_action, debug_step_action, debug_return_action, debug_continue_action, debug_exit_action, MENU_SEPARATOR, set_clear_breakpoint_action, set_cond_breakpoint_action, clear_all_breakpoints_action, 'list_breakpoints', MENU_SEPARATOR, self.winpdb_action] self.main.debug_menu_actions += debug_menu_actions debug_toolbar_actions = [debug_action, debug_next_action, debug_step_action, debug_return_action, debug_continue_action, debug_exit_action] self.main.debug_toolbar_actions += debug_toolbar_actions # ---- Source menu/toolbar construction ---- source_menu_actions = [eol_menu, self.showblanks_action, trailingspaces_action, fixindentation_action, MENU_SEPARATOR, self.todo_list_action, self.warning_list_action, self.previous_warning_action, self.next_warning_action, MENU_SEPARATOR, self.previous_edit_cursor_action, self.previous_cursor_action, self.next_cursor_action] self.main.source_menu_actions += source_menu_actions source_toolbar_actions = [self.todo_list_action, self.warning_list_action, self.previous_warning_action, self.next_warning_action, MENU_SEPARATOR, self.previous_edit_cursor_action, self.previous_cursor_action, self.next_cursor_action] self.main.source_toolbar_actions += source_toolbar_actions # ---- Dock widget and file dependent actions ---- self.dock_toolbar_actions = (file_toolbar_actions + [MENU_SEPARATOR] + source_toolbar_actions + [MENU_SEPARATOR] + run_toolbar_actions + [MENU_SEPARATOR] + debug_toolbar_actions + [MENU_SEPARATOR] + edit_toolbar_actions) self.pythonfile_dependent_actions = [run_action, configure_action, set_clear_breakpoint_action, set_cond_breakpoint_action, debug_action, run_selected_action, run_cell_action, run_cell_advance_action, re_run_last_cell_action, blockcomment_action, unblockcomment_action, self.winpdb_action] self.cythonfile_compatible_actions = [run_action, configure_action] self.file_dependent_actions = self.pythonfile_dependent_actions + \ [self.save_action, save_as_action, save_copy_as_action, print_preview_action, self.print_action, self.save_all_action, gotoline_action, workdir_action, self.close_action, self.close_all_action, self.toggle_comment_action, self.revert_action, self.indent_action, self.unindent_action] self.stack_menu_actions = [gotoline_action, workdir_action] return self.file_dependent_actions def register_plugin(self): """Register plugin in Spyder's main window""" self.main.restore_scrollbar_position.connect( self.restore_scrollbar_position) self.main.console.edit_goto.connect(self.load) self.exec_in_extconsole.connect(self.main.execute_in_external_console) self.redirect_stdio.connect(self.main.redirect_internalshell_stdio) self.open_dir.connect(self.main.workingdirectory.chdir) self.set_help(self.main.help) if self.main.outlineexplorer is not None: self.set_outlineexplorer(self.main.outlineexplorer) editorstack = self.get_current_editorstack() if not editorstack.data: self.__load_temp_file() self.main.add_dockwidget(self) self.main.add_to_fileswitcher(self, editorstack.tabs, editorstack.data, ima.icon('TextFileIcon')) def update_font(self): """Update font from Preferences""" font = self.get_plugin_font() color_scheme = self.get_color_scheme() for editorstack in self.editorstacks: editorstack.set_default_font(font, color_scheme) completion_size = CONF.get('main', 'completion/size') for finfo in editorstack.data: comp_widget = finfo.editor.completion_widget comp_widget.setup_appearance(completion_size, font) #------ Focus tabwidget def __get_focus_editorstack(self): fwidget = QApplication.focusWidget() if isinstance(fwidget, EditorStack): return fwidget else: for editorstack in self.editorstacks: if editorstack.isAncestorOf(fwidget): return editorstack def set_last_focus_editorstack(self, editorwindow, editorstack): self.last_focus_editorstack[editorwindow] = editorstack self.last_focus_editorstack[None] = editorstack # very last editorstack def get_last_focus_editorstack(self, editorwindow=None): return self.last_focus_editorstack[editorwindow] def remove_last_focus_editorstack(self, editorstack): for editorwindow, widget in list(self.last_focus_editorstack.items()): if widget is editorstack: self.last_focus_editorstack[editorwindow] = None def save_focus_editorstack(self): editorstack = self.__get_focus_editorstack() if editorstack is not None: for win in [self]+self.editorwindows: if win.isAncestorOf(editorstack): self.set_last_focus_editorstack(win, editorstack) # ------ Handling editorstacks def register_editorstack(self, editorstack): self.editorstacks.append(editorstack) self.register_widget_shortcuts(editorstack) if len(self.editorstacks) > 1 and self.main is not None: # The first editostack is registered automatically with Spyder's # main window through the `register_plugin` method. Only additional # editors added by splitting need to be registered. # See Issue #5057. self.main.fileswitcher.sig_goto_file.connect( editorstack.set_stack_index) if self.isAncestorOf(editorstack): # editorstack is a child of the Editor plugin self.set_last_focus_editorstack(self, editorstack) editorstack.set_closable( len(self.editorstacks) > 1 ) if self.outlineexplorer is not None: editorstack.set_outlineexplorer(self.outlineexplorer) editorstack.set_find_widget(self.find_widget) editorstack.reset_statusbar.connect(self.readwrite_status.hide) editorstack.reset_statusbar.connect(self.encoding_status.hide) editorstack.reset_statusbar.connect(self.cursorpos_status.hide) editorstack.readonly_changed.connect( self.readwrite_status.readonly_changed) editorstack.encoding_changed.connect( self.encoding_status.encoding_changed) editorstack.sig_editor_cursor_position_changed.connect( self.cursorpos_status.cursor_position_changed) editorstack.sig_refresh_eol_chars.connect(self.eol_status.eol_changed) editorstack.set_help(self.help) editorstack.set_io_actions(self.new_action, self.open_action, self.save_action, self.revert_action) editorstack.set_tempfile_path(self.TEMPFILE_PATH) editorstack.set_introspector(self.introspector) settings = ( ('set_pyflakes_enabled', 'code_analysis/pyflakes'), ('set_pep8_enabled', 'code_analysis/pep8'), ('set_todolist_enabled', 'todo_list'), ('set_realtime_analysis_enabled', 'realtime_analysis'), ('set_realtime_analysis_timeout', 'realtime_analysis/timeout'), ('set_blanks_enabled', 'blank_spaces'), ('set_linenumbers_enabled', 'line_numbers'), ('set_edgeline_enabled', 'edge_line'), ('set_edgeline_column', 'edge_line_column'), ('set_codecompletion_auto_enabled', 'codecompletion/auto'), ('set_codecompletion_case_enabled', 'codecompletion/case_sensitive'), ('set_codecompletion_enter_enabled', 'codecompletion/enter_key'), ('set_calltips_enabled', 'calltips'), ('set_go_to_definition_enabled', 'go_to_definition'), ('set_focus_to_editor', 'focus_to_editor'), ('set_close_parentheses_enabled', 'close_parentheses'), ('set_close_quotes_enabled', 'close_quotes'), ('set_add_colons_enabled', 'add_colons'), ('set_auto_unindent_enabled', 'auto_unindent'), ('set_indent_chars', 'indent_chars'), ('set_tab_stop_width_spaces', 'tab_stop_width_spaces'), ('set_wrap_enabled', 'wrap'), ('set_tabmode_enabled', 'tab_always_indent'), ('set_intelligent_backspace_enabled', 'intelligent_backspace'), ('set_highlight_current_line_enabled', 'highlight_current_line'), ('set_highlight_current_cell_enabled', 'highlight_current_cell'), ('set_occurrence_highlighting_enabled', 'occurrence_highlighting'), ('set_occurrence_highlighting_timeout', 'occurrence_highlighting/timeout'), ('set_checkeolchars_enabled', 'check_eol_chars'), ('set_fullpath_sorting_enabled', 'fullpath_sorting'), ('set_tabbar_visible', 'show_tab_bar'), ('set_always_remove_trailing_spaces', 'always_remove_trailing_spaces'), ) for method, setting in settings: getattr(editorstack, method)(self.get_option(setting)) editorstack.set_help_enabled(CONF.get('help', 'connect/editor')) color_scheme = self.get_color_scheme() editorstack.set_default_font(self.get_plugin_font(), color_scheme) editorstack.starting_long_process.connect(self.starting_long_process) editorstack.ending_long_process.connect(self.ending_long_process) # Redirect signals editorstack.redirect_stdio.connect( lambda state: self.redirect_stdio.emit(state)) editorstack.exec_in_extconsole.connect( lambda text, option: self.exec_in_extconsole.emit(text, option)) editorstack.update_plugin_title.connect( lambda: self.update_plugin_title.emit()) editorstack.editor_focus_changed.connect(self.save_focus_editorstack) editorstack.editor_focus_changed.connect(self.set_editorstack_for_introspection) editorstack.editor_focus_changed.connect(self.main.plugin_focus_changed) editorstack.zoom_in.connect(lambda: self.zoom(1)) editorstack.zoom_out.connect(lambda: self.zoom(-1)) editorstack.zoom_reset.connect(lambda: self.zoom(0)) editorstack.sig_new_file.connect(lambda s: self.new(text=s)) editorstack.sig_new_file[()].connect(self.new) editorstack.sig_close_file.connect(self.close_file_in_all_editorstacks) editorstack.file_saved.connect(self.file_saved_in_editorstack) editorstack.file_renamed_in_data.connect( self.file_renamed_in_data_in_editorstack) editorstack.create_new_window.connect(self.create_new_window) editorstack.opened_files_list_changed.connect( self.opened_files_list_changed) editorstack.analysis_results_changed.connect( self.analysis_results_changed) editorstack.todo_results_changed.connect(self.todo_results_changed) editorstack.update_code_analysis_actions.connect( self.update_code_analysis_actions) editorstack.update_code_analysis_actions.connect( self.update_todo_actions) editorstack.refresh_file_dependent_actions.connect( self.refresh_file_dependent_actions) editorstack.refresh_save_all_action.connect(self.refresh_save_all_action) editorstack.sig_refresh_eol_chars.connect(self.refresh_eol_chars) editorstack.save_breakpoints.connect(self.save_breakpoints) editorstack.text_changed_at.connect(self.text_changed_at) editorstack.current_file_changed.connect(self.current_file_changed) editorstack.plugin_load.connect(self.load) editorstack.plugin_load[()].connect(self.load) editorstack.edit_goto.connect(self.load) editorstack.sig_save_as.connect(self.save_as) editorstack.sig_prev_edit_pos.connect(self.go_to_last_edit_location) editorstack.sig_prev_cursor.connect(self.go_to_previous_cursor_position) editorstack.sig_next_cursor.connect(self.go_to_next_cursor_position) def unregister_editorstack(self, editorstack): """Removing editorstack only if it's not the last remaining""" self.remove_last_focus_editorstack(editorstack) if len(self.editorstacks) > 1: index = self.editorstacks.index(editorstack) self.editorstacks.pop(index) return True else: # editorstack was not removed! return False def clone_editorstack(self, editorstack): editorstack.clone_from(self.editorstacks[0]) for finfo in editorstack.data: self.register_widget_shortcuts(finfo.editor) @Slot(str, str) def close_file_in_all_editorstacks(self, editorstack_id_str, filename): for editorstack in self.editorstacks: if str(id(editorstack)) != editorstack_id_str: editorstack.blockSignals(True) index = editorstack.get_index_from_filename(filename) editorstack.close_file(index, force=True) editorstack.blockSignals(False) @Slot(str, str, str) def file_saved_in_editorstack(self, editorstack_id_str, original_filename, filename): """A file was saved in editorstack, this notifies others""" for editorstack in self.editorstacks: if str(id(editorstack)) != editorstack_id_str: editorstack.file_saved_in_other_editorstack(original_filename, filename) @Slot(str, str, str) def file_renamed_in_data_in_editorstack(self, editorstack_id_str, original_filename, filename): """A file was renamed in data in editorstack, this notifies others""" for editorstack in self.editorstacks: if str(id(editorstack)) != editorstack_id_str: editorstack.rename_in_data(original_filename, filename) def set_editorstack_for_introspection(self): """ Set the current editorstack to be used by the IntrospectionManager instance """ editorstack = self.__get_focus_editorstack() if editorstack is not None: self.introspector.set_editor_widget(editorstack) # Disconnect active signals try: self.introspector.send_to_help.disconnect() self.introspector.edit_goto.disconnect() except TypeError: pass # Reconnect signals again self.introspector.send_to_help.connect(editorstack.send_to_help) self.introspector.edit_goto.connect( lambda fname, lineno, name: editorstack.edit_goto.emit(fname, lineno, name)) #------ Handling editor windows def setup_other_windows(self): """Setup toolbars and menus for 'New window' instances""" self.toolbar_list = ((_("File toolbar"), "file_toolbar", self.main.file_toolbar_actions), (_("Search toolbar"), "search_toolbar", self.main.search_menu_actions), (_("Source toolbar"), "source_toolbar", self.main.source_toolbar_actions), (_("Run toolbar"), "run_toolbar", self.main.run_toolbar_actions), (_("Debug toolbar"), "debug_toolbar", self.main.debug_toolbar_actions), (_("Edit toolbar"), "edit_toolbar", self.main.edit_toolbar_actions)) self.menu_list = ((_("&File"), self.main.file_menu_actions), (_("&Edit"), self.main.edit_menu_actions), (_("&Search"), self.main.search_menu_actions), (_("Sour&ce"), self.main.source_menu_actions), (_("&Run"), self.main.run_menu_actions), (_("&Tools"), self.main.tools_menu_actions), (_("&View"), []), (_("&Help"), self.main.help_menu_actions)) # Create pending new windows: for layout_settings in self.editorwindows_to_be_created: win = self.create_new_window() win.set_layout_settings(layout_settings) def create_new_window(self): oe_options = self.outlineexplorer.get_options() fullpath_sorting=self.get_option('fullpath_sorting', True), window = EditorMainWindow(self, self.stack_menu_actions, self.toolbar_list, self.menu_list, show_fullpath=oe_options['show_fullpath'], fullpath_sorting=fullpath_sorting, show_all_files=oe_options['show_all_files'], show_comments=oe_options['show_comments']) window.add_toolbars_to_menu("&View", window.get_toolbars()) window.load_toolbars() window.resize(self.size()) window.show() self.register_editorwindow(window) window.destroyed.connect(lambda: self.unregister_editorwindow(window)) return window def register_editorwindow(self, window): self.editorwindows.append(window) def unregister_editorwindow(self, window): self.editorwindows.pop(self.editorwindows.index(window)) #------ Accessors def get_filenames(self): return [finfo.filename for finfo in self.editorstacks[0].data] def get_filename_index(self, filename): return self.editorstacks[0].has_filename(filename) def get_current_editorstack(self, editorwindow=None): if self.editorstacks is not None: if len(self.editorstacks) == 1: editorstack = self.editorstacks[0] else: editorstack = self.__get_focus_editorstack() if editorstack is None or editorwindow is not None: editorstack = self.get_last_focus_editorstack(editorwindow) if editorstack is None: editorstack = self.editorstacks[0] return editorstack def get_current_editor(self): editorstack = self.get_current_editorstack() if editorstack is not None: return editorstack.get_current_editor() def get_current_finfo(self): editorstack = self.get_current_editorstack() if editorstack is not None: return editorstack.get_current_finfo() def get_current_filename(self): editorstack = self.get_current_editorstack() if editorstack is not None: return editorstack.get_current_filename() def is_file_opened(self, filename=None): return self.editorstacks[0].is_file_opened(filename) def set_current_filename(self, filename, editorwindow=None): """Set focus to *filename* if this file has been opened Return the editor instance associated to *filename*""" editorstack = self.get_current_editorstack(editorwindow) return editorstack.set_current_filename(filename) def set_path(self): for finfo in self.editorstacks[0].data: finfo.path = self.main.get_spyder_pythonpath() if self.introspector: self.introspector.change_extra_path( self.main.get_spyder_pythonpath()) #------ FileSwitcher API def get_current_tab_manager(self): """Get the widget with the TabWidget attribute.""" return self.get_current_editorstack() #------ Refresh methods def refresh_file_dependent_actions(self): """Enable/disable file dependent actions (only if dockwidget is visible)""" if self.dockwidget and self.dockwidget.isVisible(): enable = self.get_current_editor() is not None for action in self.file_dependent_actions: action.setEnabled(enable) def refresh_save_all_action(self): """Enable 'Save All' if there are files to be saved""" editorstack = self.get_current_editorstack() if editorstack: state = any(finfo.editor.document().isModified() or finfo.newly_created for finfo in editorstack.data) self.save_all_action.setEnabled(state) def update_warning_menu(self): """Update warning list menu""" editorstack = self.get_current_editorstack() check_results = editorstack.get_analysis_results() self.warning_menu.clear() filename = self.get_current_filename() for message, line_number in check_results: error = 'syntax' in message text = message[:1].upper()+message[1:] icon = ima.icon('error') if error else ima.icon('warning') # QAction.triggered works differently for PySide and PyQt if not API == 'pyside': slot = lambda _checked, _l=line_number: self.load(filename, goto=_l) else: slot = lambda _l=line_number: self.load(filename, goto=_l) action = create_action(self, text=text, icon=icon, triggered=slot) self.warning_menu.addAction(action) def analysis_results_changed(self): """ Synchronize analysis results between editorstacks Refresh analysis navigation buttons """ editorstack = self.get_current_editorstack() results = editorstack.get_analysis_results() index = editorstack.get_stack_index() if index != -1: filename = editorstack.data[index].filename for other_editorstack in self.editorstacks: if other_editorstack is not editorstack: other_editorstack.set_analysis_results(filename, results) self.update_code_analysis_actions() def update_todo_menu(self): """Update todo list menu""" editorstack = self.get_current_editorstack() results = editorstack.get_todo_results() self.todo_menu.clear() filename = self.get_current_filename() for text, line0 in results: icon = ima.icon('todo') # QAction.triggered works differently for PySide and PyQt if not API == 'pyside': slot = lambda _checked, _l=line0: self.load(filename, goto=_l) else: slot = lambda _l=line0: self.load(filename, goto=_l) action = create_action(self, text=text, icon=icon, triggered=slot) self.todo_menu.addAction(action) self.update_todo_actions() def todo_results_changed(self): """ Synchronize todo results between editorstacks Refresh todo list navigation buttons """ editorstack = self.get_current_editorstack() results = editorstack.get_todo_results() index = editorstack.get_stack_index() if index != -1: filename = editorstack.data[index].filename for other_editorstack in self.editorstacks: if other_editorstack is not editorstack: other_editorstack.set_todo_results(filename, results) self.update_todo_actions() def refresh_eol_chars(self, os_name): os_name = to_text_string(os_name) self.__set_eol_chars = False if os_name == 'nt': self.win_eol_action.setChecked(True) elif os_name == 'posix': self.linux_eol_action.setChecked(True) else: self.mac_eol_action.setChecked(True) self.__set_eol_chars = True #------ Slots def opened_files_list_changed(self): """ Opened files list has changed: --> open/close file action --> modification ('*' added to title) --> current edited file has changed """ # Refresh Python file dependent actions: editor = self.get_current_editor() if editor: python_enable = editor.is_python() cython_enable = python_enable or ( programs.is_module_installed('Cython') and editor.is_cython()) for action in self.pythonfile_dependent_actions: if action in self.cythonfile_compatible_actions: enable = cython_enable else: enable = python_enable if action is self.winpdb_action: action.setEnabled(enable and WINPDB_PATH is not None) else: action.setEnabled(enable) self.open_file_update.emit(self.get_current_filename()) def update_code_analysis_actions(self): editorstack = self.get_current_editorstack() results = editorstack.get_analysis_results() # Update code analysis buttons state = (self.get_option('code_analysis/pyflakes') \ or self.get_option('code_analysis/pep8')) \ and results is not None and len(results) for action in (self.warning_list_action, self.previous_warning_action, self.next_warning_action): action.setEnabled(state) def update_todo_actions(self): editorstack = self.get_current_editorstack() results = editorstack.get_todo_results() state = self.get_option('todo_list') \ and results is not None and len(results) self.todo_list_action.setEnabled(state) def rehighlight_cells(self): """Rehighlight cells of current editor""" editor = self.get_current_editor() editor.rehighlight_cells() QApplication.processEvents() #------ Breakpoints def save_breakpoints(self, filename, breakpoints): filename = to_text_string(filename) breakpoints = to_text_string(breakpoints) filename = osp.normpath(osp.abspath(filename)) if breakpoints: breakpoints = eval(breakpoints) else: breakpoints = [] save_breakpoints(filename, breakpoints) self.breakpoints_saved.emit() #------ File I/O def __load_temp_file(self): """Load temporary file from a text file in user home directory""" if not osp.isfile(self.TEMPFILE_PATH): # Creating temporary file default = ['# -*- coding: utf-8 -*-', '"""', _("Spyder Editor"), '', _("This is a temporary script file."), '"""', '', ''] text = os.linesep.join([encoding.to_unicode(qstr) for qstr in default]) encoding.write(to_text_string(text), self.TEMPFILE_PATH, 'utf-8') self.load(self.TEMPFILE_PATH) @Slot() def __set_workdir(self): """Set current script directory as working directory""" fname = self.get_current_filename() if fname is not None: directory = osp.dirname(osp.abspath(fname)) self.open_dir.emit(directory) def __add_recent_file(self, fname): """Add to recent file list""" if fname is None: return if fname in self.recent_files: self.recent_files.remove(fname) self.recent_files.insert(0, fname) if len(self.recent_files) > self.get_option('max_recent_files'): self.recent_files.pop(-1) def _clone_file_everywhere(self, finfo): """Clone file (*src_editor* widget) in all editorstacks Cloning from the first editorstack in which every single new editor is created (when loading or creating a new file)""" for editorstack in self.editorstacks[1:]: editor = editorstack.clone_editor_from(finfo, set_current=False) self.register_widget_shortcuts(editor) @Slot() @Slot(str) def new(self, fname=None, editorstack=None, text=None): """ Create a new file - Untitled fname=None --> fname will be 'untitledXX.py' but do not create file fname= --> create file """ # If no text is provided, create default content if text is None: default_content = True text, enc = encoding.read(self.TEMPLATE_PATH) enc_match = re.search('-*- coding: ?([a-z0-9A-Z\-]*) -*-', text) if enc_match: enc = enc_match.group(1) # Initialize template variables # Windows username = encoding.to_unicode_from_fs(os.environ.get('USERNAME', '')) # Linux, Mac OS X if not username: username = encoding.to_unicode_from_fs(os.environ.get('USER', '-')) VARS = { 'date': time.ctime(), 'username': username, } try: text = text % VARS except: pass else: default_content = False enc = encoding.read(self.TEMPLATE_PATH)[1] create_fname = lambda n: to_text_string(_("untitled")) + ("%d.py" % n) # Creating editor widget if editorstack is None: current_es = self.get_current_editorstack() else: current_es = editorstack created_from_here = fname is None if created_from_here: while True: fname = create_fname(self.untitled_num) self.untitled_num += 1 if not osp.isfile(fname): break basedir = getcwd_or_home() if self.main.projects.get_active_project() is not None: basedir = self.main.projects.get_active_project_path() else: c_fname = self.get_current_filename() if c_fname is not None and c_fname != self.TEMPFILE_PATH: basedir = osp.dirname(c_fname) fname = osp.abspath(osp.join(basedir, fname)) else: # QString when triggered by a Qt signal fname = osp.abspath(to_text_string(fname)) index = current_es.has_filename(fname) if index is not None and not current_es.close_file(index): return # Creating the editor widget in the first editorstack (the one that # can't be destroyed), then cloning this editor widget in all other # editorstacks: finfo = self.editorstacks[0].new(fname, enc, text, default_content) finfo.path = self.main.get_spyder_pythonpath() self._clone_file_everywhere(finfo) current_editor = current_es.set_current_filename(finfo.filename) self.register_widget_shortcuts(current_editor) if not created_from_here: self.save(force=True) def edit_template(self): """Edit new file template""" self.load(self.TEMPLATE_PATH) def update_recent_file_menu(self): """Update recent file menu""" recent_files = [] for fname in self.recent_files: if self.is_file_opened(fname) is None and osp.isfile(fname): recent_files.append(fname) self.recent_file_menu.clear() if recent_files: for fname in recent_files: action = create_action(self, fname, icon=ima.icon('FileIcon'), triggered=self.load) action.setData(to_qvariant(fname)) self.recent_file_menu.addAction(action) self.clear_recent_action.setEnabled(len(recent_files) > 0) add_actions(self.recent_file_menu, (None, self.max_recent_action, self.clear_recent_action)) @Slot() def clear_recent_files(self): """Clear recent files list""" self.recent_files = [] @Slot() def change_max_recent_files(self): "Change max recent files entries""" editorstack = self.get_current_editorstack() mrf, valid = QInputDialog.getInt(editorstack, _('Editor'), _('Maximum number of recent files'), self.get_option('max_recent_files'), 1, 35) if valid: self.set_option('max_recent_files', mrf) @Slot() @Slot(str) @Slot(str, int, str) @Slot(str, int, str, object) def load(self, filenames=None, goto=None, word='', editorwindow=None, processevents=True): """ Load a text file editorwindow: load in this editorwindow (useful when clicking on outline explorer with multiple editor windows) processevents: determines if processEvents() should be called at the end of this method (set to False to prevent keyboard events from creeping through to the editor during debugging) """ editor0 = self.get_current_editor() if editor0 is not None: position0 = editor0.get_position('cursor') filename0 = self.get_current_filename() else: position0, filename0 = None, None if not filenames: # Recent files action action = self.sender() if isinstance(action, QAction): filenames = from_qvariant(action.data(), to_text_string) if not filenames: basedir = getcwd_or_home() if self.edit_filetypes is None: self.edit_filetypes = get_edit_filetypes() if self.edit_filters is None: self.edit_filters = get_edit_filters() c_fname = self.get_current_filename() if c_fname is not None and c_fname != self.TEMPFILE_PATH: basedir = osp.dirname(c_fname) self.redirect_stdio.emit(False) parent_widget = self.get_current_editorstack() if filename0 is not None: selectedfilter = get_filter(self.edit_filetypes, osp.splitext(filename0)[1]) else: selectedfilter = '' if not PYTEST: filenames, _sf = getopenfilenames( parent_widget, _("Open file"), basedir, self.edit_filters, selectedfilter=selectedfilter, options=QFileDialog.HideNameFilterDetails) else: # Use a Qt (i.e. scriptable) dialog for pytest dialog = QFileDialog(parent_widget, _("Open file"), options=QFileDialog.DontUseNativeDialog) if dialog.exec_(): filenames = dialog.selectedFiles() self.redirect_stdio.emit(True) if filenames: filenames = [osp.normpath(fname) for fname in filenames] else: return focus_widget = QApplication.focusWidget() if self.editorwindows and not self.dockwidget.isVisible(): # We override the editorwindow variable to force a focus on # the editor window instead of the hidden editor dockwidget. # See PR #5742. if editorwindow not in self.editorwindows: editorwindow = self.editorwindows[0] editorwindow.setFocus() editorwindow.raise_() elif (self.dockwidget and not self.ismaximized and not self.dockwidget.isAncestorOf(focus_widget) and not isinstance(focus_widget, CodeEditor)): self.dockwidget.setVisible(True) self.dockwidget.setFocus() self.dockwidget.raise_() def _convert(fname): fname = osp.abspath(encoding.to_unicode_from_fs(fname)) if os.name == 'nt' and len(fname) >= 2 and fname[1] == ':': fname = fname[0].upper()+fname[1:] return fname if hasattr(filenames, 'replaceInStrings'): # This is a QStringList instance (PyQt API #1), converting to list: filenames = list(filenames) if not isinstance(filenames, list): filenames = [_convert(filenames)] else: filenames = [_convert(fname) for fname in list(filenames)] if isinstance(goto, int): goto = [goto] elif goto is not None and len(goto) != len(filenames): goto = None for index, filename in enumerate(filenames): # -- Do not open an already opened file current_editor = self.set_current_filename(filename, editorwindow) if current_editor is None: # -- Not a valid filename: if not osp.isfile(filename): continue # -- current_es = self.get_current_editorstack(editorwindow) # Creating the editor widget in the first editorstack (the one # that can't be destroyed), then cloning this editor widget in # all other editorstacks: finfo = self.editorstacks[0].load(filename, set_current=False) finfo.path = self.main.get_spyder_pythonpath() self._clone_file_everywhere(finfo) current_editor = current_es.set_current_filename(filename) current_editor.set_breakpoints(load_breakpoints(filename)) self.register_widget_shortcuts(current_editor) current_es.analyze_script() self.__add_recent_file(filename) if goto is not None: # 'word' is assumed to be None as well current_editor.go_to_line(goto[index], word=word) position = current_editor.get_position('cursor') self.cursor_moved(filename0, position0, filename, position) current_editor.clearFocus() current_editor.setFocus() current_editor.window().raise_() if processevents: QApplication.processEvents() @Slot() def print_file(self): """Print current file""" editor = self.get_current_editor() filename = self.get_current_filename() printer = Printer(mode=QPrinter.HighResolution, header_font=self.get_plugin_font('printer_header')) printDialog = QPrintDialog(printer, editor) if editor.has_selected_text(): printDialog.setOption(QAbstractPrintDialog.PrintSelection, True) self.redirect_stdio.emit(False) answer = printDialog.exec_() self.redirect_stdio.emit(True) if answer == QDialog.Accepted: self.starting_long_process(_("Printing...")) printer.setDocName(filename) editor.print_(printer) self.ending_long_process() @Slot() def print_preview(self): """Print preview for current file""" from qtpy.QtPrintSupport import QPrintPreviewDialog editor = self.get_current_editor() printer = Printer(mode=QPrinter.HighResolution, header_font=self.get_plugin_font('printer_header')) preview = QPrintPreviewDialog(printer, self) preview.setWindowFlags(Qt.Window) preview.paintRequested.connect(lambda printer: editor.print_(printer)) self.redirect_stdio.emit(False) preview.exec_() self.redirect_stdio.emit(True) @Slot() def close_file(self): """Close current file""" editorstack = self.get_current_editorstack() editorstack.close_file() @Slot() def close_all_files(self): """Close all opened scripts""" self.editorstacks[0].close_all_files() @Slot() def save(self, index=None, force=False): """Save file""" editorstack = self.get_current_editorstack() return editorstack.save(index=index, force=force) @Slot() def save_as(self): """Save *as* the currently edited file""" editorstack = self.get_current_editorstack() if editorstack.save_as(): fname = editorstack.get_current_filename() self.__add_recent_file(fname) @Slot() def save_copy_as(self): """Save *copy as* the currently edited file""" editorstack = self.get_current_editorstack() editorstack.save_copy_as() @Slot() def save_all(self): """Save all opened files""" self.get_current_editorstack().save_all() @Slot() def revert(self): """Revert the currently edited file from disk""" editorstack = self.get_current_editorstack() editorstack.revert() @Slot() def find(self): """Find slot""" editorstack = self.get_current_editorstack() editorstack.find_widget.show() editorstack.find_widget.search_text.setFocus() @Slot() def find_next(self): """Fnd next slot""" editorstack = self.get_current_editorstack() editorstack.find_widget.find_next() @Slot() def find_previous(self): """Find previous slot""" editorstack = self.get_current_editorstack() editorstack.find_widget.find_previous() @Slot() def replace(self): """Replace slot""" editorstack = self.get_current_editorstack() editorstack.find_widget.show_replace() def open_last_closed(self): """ Reopens the last closed tab.""" editorstack = self.get_current_editorstack() last_closed_files = editorstack.get_last_closed_files() if (len(last_closed_files) > 0): file_to_open = last_closed_files[0] last_closed_files.remove(file_to_open) editorstack.set_last_closed_files(last_closed_files) self.load(file_to_open) #------ Explorer widget def close_file_from_name(self, filename): """Close file from its name""" filename = osp.abspath(to_text_string(filename)) index = self.editorstacks[0].has_filename(filename) if index is not None: self.editorstacks[0].close_file(index) def removed(self, filename): """File was removed in file explorer widget or in project explorer""" self.close_file_from_name(filename) def removed_tree(self, dirname): """Directory was removed in project explorer widget""" dirname = osp.abspath(to_text_string(dirname)) for fname in self.get_filenames(): if osp.abspath(fname).startswith(dirname): self.close_file_from_name(fname) def renamed(self, source, dest): """File was renamed in file explorer widget or in project explorer""" filename = osp.abspath(to_text_string(source)) index = self.editorstacks[0].has_filename(filename) if index is not None: for editorstack in self.editorstacks: editorstack.rename_in_data(filename, new_filename=to_text_string(dest)) #------ Source code @Slot() def indent(self): """Indent current line or selection""" editor = self.get_current_editor() if editor is not None: editor.indent() @Slot() def unindent(self): """Unindent current line or selection""" editor = self.get_current_editor() if editor is not None: editor.unindent() @Slot() def text_uppercase (self): """Change current line or selection to uppercase.""" editor = self.get_current_editor() if editor is not None: editor.transform_to_uppercase() @Slot() def text_lowercase(self): """Change current line or selection to lowercase.""" editor = self.get_current_editor() if editor is not None: editor.transform_to_lowercase() @Slot() def toggle_comment(self): """Comment current line or selection""" editor = self.get_current_editor() if editor is not None: editor.toggle_comment() @Slot() def blockcomment(self): """Block comment current line or selection""" editor = self.get_current_editor() if editor is not None: editor.blockcomment() @Slot() def unblockcomment(self): """Un-block comment current line or selection""" editor = self.get_current_editor() if editor is not None: editor.unblockcomment() @Slot() def go_to_next_todo(self): editor = self.get_current_editor() position = editor.go_to_next_todo() filename = self.get_current_filename() self.add_cursor_position_to_history(filename, position) @Slot() def go_to_next_warning(self): editor = self.get_current_editor() position = editor.go_to_next_warning() filename = self.get_current_filename() self.add_cursor_position_to_history(filename, position) @Slot() def go_to_previous_warning(self): editor = self.get_current_editor() position = editor.go_to_previous_warning() filename = self.get_current_filename() self.add_cursor_position_to_history(filename, position) @Slot() def run_winpdb(self): """Run winpdb to debug current file""" if self.save(): fname = self.get_current_filename() runconf = get_run_configuration(fname) if runconf is None: args = [] wdir = None else: args = runconf.get_arguments().split() wdir = runconf.get_working_directory() # Handle the case where wdir comes back as an empty string # when the working directory dialog checkbox is unchecked. # (subprocess "cwd" default is None, so empty str # must be changed to None in this case.) programs.run_program(WINPDB_PATH, [fname] + args, cwd=wdir or None) def toggle_eol_chars(self, os_name, checked): if checked: editor = self.get_current_editor() if self.__set_eol_chars: editor.set_eol_chars(sourcecode.get_eol_chars_from_os_name(os_name)) @Slot(bool) def toggle_show_blanks(self, checked): editor = self.get_current_editor() editor.set_blanks_enabled(checked) @Slot() def remove_trailing_spaces(self): editorstack = self.get_current_editorstack() editorstack.remove_trailing_spaces() @Slot() def fix_indentation(self): editorstack = self.get_current_editorstack() editorstack.fix_indentation() #------ Cursor position history management def update_cursorpos_actions(self): self.previous_edit_cursor_action.setEnabled( self.last_edit_cursor_pos is not None) self.previous_cursor_action.setEnabled( self.cursor_pos_index is not None and self.cursor_pos_index > 0) self.next_cursor_action.setEnabled(self.cursor_pos_index is not None \ and self.cursor_pos_index < len(self.cursor_pos_history)-1) def add_cursor_position_to_history(self, filename, position, fc=False): if self.__ignore_cursor_position: return for index, (fname, pos) in enumerate(self.cursor_pos_history[:]): if fname == filename: if pos == position or pos == 0: if fc: self.cursor_pos_history[index] = (filename, position) self.cursor_pos_index = index self.update_cursorpos_actions() return else: if self.cursor_pos_index >= index: self.cursor_pos_index -= 1 self.cursor_pos_history.pop(index) break if self.cursor_pos_index is not None: self.cursor_pos_history = \ self.cursor_pos_history[:self.cursor_pos_index+1] self.cursor_pos_history.append((filename, position)) self.cursor_pos_index = len(self.cursor_pos_history)-1 self.update_cursorpos_actions() def cursor_moved(self, filename0, position0, filename1, position1): """Cursor was just moved: 'go to'""" if position0 is not None: self.add_cursor_position_to_history(filename0, position0) self.add_cursor_position_to_history(filename1, position1) def text_changed_at(self, filename, position): self.last_edit_cursor_pos = (to_text_string(filename), position) def current_file_changed(self, filename, position): self.add_cursor_position_to_history(to_text_string(filename), position, fc=True) @Slot() def go_to_last_edit_location(self): if self.last_edit_cursor_pos is not None: filename, position = self.last_edit_cursor_pos if not osp.isfile(filename): self.last_edit_cursor_pos = None return else: self.load(filename) editor = self.get_current_editor() if position < editor.document().characterCount(): editor.set_cursor_position(position) def __move_cursor_position(self, index_move): if self.cursor_pos_index is None: return filename, _position = self.cursor_pos_history[self.cursor_pos_index] self.cursor_pos_history[self.cursor_pos_index] = ( filename, self.get_current_editor().get_position('cursor') ) self.__ignore_cursor_position = True old_index = self.cursor_pos_index self.cursor_pos_index = min([ len(self.cursor_pos_history)-1, max([0, self.cursor_pos_index+index_move]) ]) filename, position = self.cursor_pos_history[self.cursor_pos_index] if not osp.isfile(filename): self.cursor_pos_history.pop(self.cursor_pos_index) if self.cursor_pos_index < old_index: old_index -= 1 self.cursor_pos_index = old_index else: self.load(filename) editor = self.get_current_editor() if position < editor.document().characterCount(): editor.set_cursor_position(position) self.__ignore_cursor_position = False self.update_cursorpos_actions() @Slot() def go_to_previous_cursor_position(self): self.__move_cursor_position(-1) @Slot() def go_to_next_cursor_position(self): self.__move_cursor_position(1) @Slot() def go_to_line(self, line=None): """Open 'go to line' dialog""" editorstack = self.get_current_editorstack() if editorstack is not None: editorstack.go_to_line(line) @Slot() def set_or_clear_breakpoint(self): """Set/Clear breakpoint""" editorstack = self.get_current_editorstack() if editorstack is not None: editorstack.set_or_clear_breakpoint() @Slot() def set_or_edit_conditional_breakpoint(self): """Set/Edit conditional breakpoint""" editorstack = self.get_current_editorstack() if editorstack is not None: editorstack.set_or_edit_conditional_breakpoint() @Slot() def clear_all_breakpoints(self): """Clear breakpoints in all files""" clear_all_breakpoints() self.breakpoints_saved.emit() editorstack = self.get_current_editorstack() if editorstack is not None: for data in editorstack.data: data.editor.clear_breakpoints() self.refresh_plugin() def clear_breakpoint(self, filename, lineno): """Remove a single breakpoint""" clear_breakpoint(filename, lineno) self.breakpoints_saved.emit() editorstack = self.get_current_editorstack() if editorstack is not None: index = self.is_file_opened(filename) if index is not None: editorstack.data[index].editor.add_remove_breakpoint(lineno) def debug_command(self, command): """Debug actions""" self.main.ipyconsole.write_to_stdin(command) focus_widget = self.main.ipyconsole.get_focus_widget() if focus_widget: focus_widget.setFocus() #------ Run Python script @Slot() def edit_run_configurations(self): dialog = RunConfigDialog(self) dialog.size_change.connect(lambda s: self.set_dialog_size(s)) if self.dialog_size is not None: dialog.resize(self.dialog_size) fname = osp.abspath(self.get_current_filename()) dialog.setup(fname) if dialog.exec_(): fname = dialog.file_to_run if fname is not None: self.load(fname) self.run_file() @Slot() def run_file(self, debug=False): """Run script inside current interpreter or in a new one""" editorstack = self.get_current_editorstack() if editorstack.save(): editor = self.get_current_editor() fname = osp.abspath(self.get_current_filename()) # Escape single and double quotes in fname (Fixes Issue 2158) fname = fname.replace("'", r"\'") fname = fname.replace('"', r'\"') runconf = get_run_configuration(fname) if runconf is None: dialog = RunConfigOneDialog(self) dialog.size_change.connect(lambda s: self.set_dialog_size(s)) if self.dialog_size is not None: dialog.resize(self.dialog_size) dialog.setup(fname) if CONF.get('run', 'open_at_least_once', not PYTEST): # Open Run Config dialog at least once: the first time # a script is ever run in Spyder, so that the user may # see it at least once and be conscious that it exists show_dlg = True CONF.set('run', 'open_at_least_once', False) else: # Open Run Config dialog only # if ALWAYS_OPEN_FIRST_RUN_OPTION option is enabled show_dlg = CONF.get('run', ALWAYS_OPEN_FIRST_RUN_OPTION) if show_dlg and not dialog.exec_(): return runconf = dialog.get_configuration() args = runconf.get_arguments() python_args = runconf.get_python_arguments() interact = runconf.interact post_mortem = runconf.post_mortem current = runconf.current systerm = runconf.systerm clear_namespace = runconf.clear_namespace if runconf.file_dir: wdir = osp.dirname(fname) elif runconf.cw_dir: wdir = '' elif osp.isdir(runconf.dir): wdir = runconf.dir else: wdir = '' python = True # Note: in the future, it may be useful to run # something in a terminal instead of a Python interp. self.__last_ec_exec = (fname, wdir, args, interact, debug, python, python_args, current, systerm, post_mortem, clear_namespace) self.re_run_file() if not interact and not debug: # If external console dockwidget is hidden, it will be # raised in top-level and so focus will be given to the # current external shell automatically # (see SpyderPluginWidget.visibility_changed method) editor.setFocus() def set_dialog_size(self, size): self.dialog_size = size @Slot() def debug_file(self): """Debug current script""" self.run_file(debug=True) @Slot() def re_run_file(self): """Re-run last script""" if self.get_option('save_all_before_run'): self.save_all() if self.__last_ec_exec is None: return (fname, wdir, args, interact, debug, python, python_args, current, systerm, post_mortem, clear_namespace) = self.__last_ec_exec if not systerm: self.run_in_current_ipyclient.emit(fname, wdir, args, debug, post_mortem, current, clear_namespace) else: self.main.open_external_console(fname, wdir, args, interact, debug, python, python_args, systerm, post_mortem) @Slot() def run_selection(self): """Run selection or current line in external console""" editorstack = self.get_current_editorstack() editorstack.run_selection() @Slot() def run_cell(self): """Run current cell""" editorstack = self.get_current_editorstack() editorstack.run_cell() @Slot() def run_cell_and_advance(self): """Run current cell and advance to the next one""" editorstack = self.get_current_editorstack() editorstack.run_cell_and_advance() @Slot() def re_run_last_cell(self): """Run last executed cell.""" editorstack = self.get_current_editorstack() editorstack.re_run_last_cell() #------ Zoom in/out/reset def zoom(self, factor): """Zoom in/out/reset""" editor = self.get_current_editorstack().get_current_editor() if factor == 0: font = self.get_plugin_font() editor.set_font(font) else: font = editor.font() size = font.pointSize() + factor if size > 0: font.setPointSize(size) editor.set_font(font) editor.update_tab_stop_width_spaces() #------ Options def apply_plugin_settings(self, options): """Apply configuration file's plugin settings""" # toggle_fullpath_sorting if self.editorstacks is not None: # --- syntax highlight and text rendering settings color_scheme_n = 'color_scheme_name' color_scheme_o = self.get_color_scheme() currentline_n = 'highlight_current_line' currentline_o = self.get_option(currentline_n) currentcell_n = 'highlight_current_cell' currentcell_o = self.get_option(currentcell_n) occurrence_n = 'occurrence_highlighting' occurrence_o = self.get_option(occurrence_n) occurrence_timeout_n = 'occurrence_highlighting/timeout' occurrence_timeout_o = self.get_option(occurrence_timeout_n) focus_to_editor_n = 'focus_to_editor' focus_to_editor_o = self.get_option(focus_to_editor_n) for editorstack in self.editorstacks: if color_scheme_n in options: editorstack.set_color_scheme(color_scheme_o) if currentline_n in options: editorstack.set_highlight_current_line_enabled( currentline_o) if currentcell_n in options: editorstack.set_highlight_current_cell_enabled( currentcell_o) if occurrence_n in options: editorstack.set_occurrence_highlighting_enabled(occurrence_o) if occurrence_timeout_n in options: editorstack.set_occurrence_highlighting_timeout( occurrence_timeout_o) if focus_to_editor_n in options: editorstack.set_focus_to_editor(focus_to_editor_o) # --- everything else fpsorting_n = 'fullpath_sorting' fpsorting_o = self.get_option(fpsorting_n) tabbar_n = 'show_tab_bar' tabbar_o = self.get_option(tabbar_n) linenb_n = 'line_numbers' linenb_o = self.get_option(linenb_n) blanks_n = 'blank_spaces' blanks_o = self.get_option(blanks_n) edgeline_n = 'edge_line' edgeline_o = self.get_option(edgeline_n) edgelinecol_n = 'edge_line_column' edgelinecol_o = self.get_option(edgelinecol_n) wrap_n = 'wrap' wrap_o = self.get_option(wrap_n) tabindent_n = 'tab_always_indent' tabindent_o = self.get_option(tabindent_n) ibackspace_n = 'intelligent_backspace' ibackspace_o = self.get_option(ibackspace_n) removetrail_n = 'always_remove_trailing_spaces' removetrail_o = self.get_option(removetrail_n) autocomp_n = 'codecompletion/auto' autocomp_o = self.get_option(autocomp_n) case_comp_n = 'codecompletion/case_sensitive' case_comp_o = self.get_option(case_comp_n) enter_key_n = 'codecompletion/enter_key' enter_key_o = self.get_option(enter_key_n) calltips_n = 'calltips' calltips_o = self.get_option(calltips_n) gotodef_n = 'go_to_definition' gotodef_o = self.get_option(gotodef_n) closepar_n = 'close_parentheses' closepar_o = self.get_option(closepar_n) close_quotes_n = 'close_quotes' close_quotes_o = self.get_option(close_quotes_n) add_colons_n = 'add_colons' add_colons_o = self.get_option(add_colons_n) autounindent_n = 'auto_unindent' autounindent_o = self.get_option(autounindent_n) indent_chars_n = 'indent_chars' indent_chars_o = self.get_option(indent_chars_n) tab_stop_width_spaces_n = 'tab_stop_width_spaces' tab_stop_width_spaces_o = self.get_option(tab_stop_width_spaces_n) help_n = 'connect_to_oi' help_o = CONF.get('help', 'connect/editor') todo_n = 'todo_list' todo_o = self.get_option(todo_n) pyflakes_n = 'code_analysis/pyflakes' pyflakes_o = self.get_option(pyflakes_n) pep8_n = 'code_analysis/pep8' pep8_o = self.get_option(pep8_n) rt_analysis_n = 'realtime_analysis' rt_analysis_o = self.get_option(rt_analysis_n) rta_timeout_n = 'realtime_analysis/timeout' rta_timeout_o = self.get_option(rta_timeout_n) finfo = self.get_current_finfo() if fpsorting_n in options: if self.outlineexplorer is not None: self.outlineexplorer.set_fullpath_sorting(fpsorting_o) for window in self.editorwindows: window.editorwidget.outlineexplorer.set_fullpath_sorting( fpsorting_o) for editorstack in self.editorstacks: if fpsorting_n in options: editorstack.set_fullpath_sorting_enabled(fpsorting_o) if tabbar_n in options: editorstack.set_tabbar_visible(tabbar_o) if linenb_n in options: editorstack.set_linenumbers_enabled(linenb_o, current_finfo=finfo) if blanks_n in options: editorstack.set_blanks_enabled(blanks_o) self.showblanks_action.setChecked(blanks_o) if edgeline_n in options: editorstack.set_edgeline_enabled(edgeline_o) if edgelinecol_n in options: editorstack.set_edgeline_column(edgelinecol_o) if wrap_n in options: editorstack.set_wrap_enabled(wrap_o) if tabindent_n in options: editorstack.set_tabmode_enabled(tabindent_o) if ibackspace_n in options: editorstack.set_intelligent_backspace_enabled(ibackspace_o) if removetrail_n in options: editorstack.set_always_remove_trailing_spaces(removetrail_o) if autocomp_n in options: editorstack.set_codecompletion_auto_enabled(autocomp_o) if case_comp_n in options: editorstack.set_codecompletion_case_enabled(case_comp_o) if enter_key_n in options: editorstack.set_codecompletion_enter_enabled(enter_key_o) if calltips_n in options: editorstack.set_calltips_enabled(calltips_o) if gotodef_n in options: editorstack.set_go_to_definition_enabled(gotodef_o) if closepar_n in options: editorstack.set_close_parentheses_enabled(closepar_o) if close_quotes_n in options: editorstack.set_close_quotes_enabled(close_quotes_o) if add_colons_n in options: editorstack.set_add_colons_enabled(add_colons_o) if autounindent_n in options: editorstack.set_auto_unindent_enabled(autounindent_o) if indent_chars_n in options: editorstack.set_indent_chars(indent_chars_o) if tab_stop_width_spaces_n in options: editorstack.set_tab_stop_width_spaces(tab_stop_width_spaces_o) if help_n in options: editorstack.set_help_enabled(help_o) if todo_n in options: editorstack.set_todolist_enabled(todo_o, current_finfo=finfo) if pyflakes_n in options: editorstack.set_pyflakes_enabled(pyflakes_o, current_finfo=finfo) if pep8_n in options: editorstack.set_pep8_enabled(pep8_o, current_finfo=finfo) if rt_analysis_n in options: editorstack.set_realtime_analysis_enabled(rt_analysis_o) if rta_timeout_n in options: editorstack.set_realtime_analysis_timeout(rta_timeout_o) # We must update the current editor after the others: # (otherwise, code analysis buttons state would correspond to the # last editor instead of showing the one of the current editor) if finfo is not None: if todo_n in options and todo_o: finfo.run_todo_finder() if pyflakes_n in options or pep8_n in options: finfo.run_code_analysis(pyflakes_o, pep8_o) # --- Open files def get_open_filenames(self): """Get the list of open files in the current stack""" editorstack = self.editorstacks[0] filenames = [] filenames += [finfo.filename for finfo in editorstack.data] return filenames def set_open_filenames(self): """ Set the recent opened files on editor based on active project. If no project is active, then editor filenames are saved, otherwise the opened filenames are stored in the project config info. """ if self.projects is not None: if not self.projects.get_active_project(): filenames = self.get_open_filenames() self.set_option('filenames', filenames) def setup_open_files(self): """Open the list of saved files per project""" self.set_create_new_file_if_empty(False) active_project_path = None if self.projects is not None: active_project_path = self.projects.get_active_project_path() if active_project_path: filenames = self.projects.get_project_filenames() else: filenames = self.get_option('filenames', default=[]) self.close_all_files() if filenames and any([osp.isfile(f) for f in filenames]): self.load(filenames) layout = self.get_option('layout_settings', None) if layout is not None: self.editorsplitter.set_layout_settings(layout) win_layout = self.get_option('windows_layout_settings', None) if win_layout: for layout_settings in win_layout: self.editorwindows_to_be_created.append(layout_settings) self.set_last_focus_editorstack(self, self.editorstacks[0]) else: self.__load_temp_file() self.set_create_new_file_if_empty(True) def save_open_files(self): """Save the list of open files""" self.set_option('filenames', self.get_open_filenames()) def set_create_new_file_if_empty(self, value): """Change the value of create_new_file_if_empty""" for editorstack in self.editorstacks: editorstack.create_new_file_if_empty = value spyder-3.2.6/spyder/plugins/tests/0000775000175000017500000000000013225025007017747 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/plugins/tests/test_layoutdialog.py0000664000175000017500000000261013156676663024103 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for layoutdialog.py """ # Test library imports import pytest # Local imports from spyder.plugins.layoutdialog import LayoutSettingsDialog, LayoutSaveDialog @pytest.fixture def setup_layout_settings_dialog(qtbot, parent, names, order, active): """Set up LayoutSettingsDialog.""" widget = LayoutSettingsDialog(parent, names, order, active) qtbot.addWidget(widget) return widget @pytest.fixture def setup_layout_save_dialog(qtbot, parent, order): """Set up LayoutSaveDialog.""" widget = LayoutSaveDialog(parent, order) qtbot.addWidget(widget) return widget def test_layout_settings_dialog(qtbot): """Run layout settings dialog.""" names = ['test', 'tester', '20', '30', '40'] order = ['test', 'tester', '20', '30', '40'] active = ['test', 'tester'] layout_settings_dlg = setup_layout_settings_dialog(qtbot, None, names, order, active) layout_settings_dlg.show() assert layout_settings_dlg def test_layout_save_dialog(qtbot): """Run layout save dialog.""" order = ['test', 'tester', '20', '30', '40'] layout_save_dlg = setup_layout_save_dialog(qtbot, None, order) layout_save_dlg.show() assert layout_save_dlg if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/plugins/tests/test_findinfiles.py0000664000175000017500000000204413211142272023651 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Copyright © Spyder Project Contributors # # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) # ----------------------------------------------------------------------------- """Test scripts for `findinfiles` plugin.""" # Standard library imports import re # 3rd party imports import pytest # Local imports from spyder.config.main import EXCLUDE_PATTERNS def check_regex(patterns): """ Check that regular expression patterns provided by compiling them. Return a list of booleans for each of the provided patterns. """ checks = [] for pattern in patterns: try: re.compile(pattern) is_valid = True except re.error: is_valid = False checks.append(is_valid) return checks def test_exclude_patterns_are_valid_regex(): checks = check_regex(EXCLUDE_PATTERNS) assert all(checks) if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/plugins/tests/test_editor_introspection.py0000664000175000017500000000570513224740762025650 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """Tests for the Editor plugin.""" # Standard library imports import os import os.path as osp # Third party imports import pytest try: from unittest.mock import Mock except ImportError: from mock import Mock # Python 2 from qtpy import PYQT4 from qtpy.QtWidgets import QWidget, QApplication from qtpy.QtCore import Qt # Local imports from spyder.utils.introspection.jedi_plugin import JEDI_010 from spyder.utils.qthelpers import qapplication from spyder.py3compat import PY2 # Location of this file LOCATION = osp.realpath(osp.join(os.getcwd(), osp.dirname(__file__))) @pytest.fixture def setup_editor(qtbot, monkeypatch): """Set up the Editor plugin.""" app = qapplication() os.environ['SPY_TEST_USE_INTROSPECTION'] = 'True' monkeypatch.setattr('spyder.dependencies', Mock()) from spyder.plugins.editor import Editor monkeypatch.setattr('spyder.plugins.editor.add_actions', Mock()) class MainMock(QWidget): def __getattr__(self, attr): if attr.endswith('actions'): return [] else: return Mock() def get_spyder_pythonpath(*args): return [] editor = Editor(MainMock()) qtbot.addWidget(editor) editor.show() editor.new(fname="test.py", text="") editor.introspector.set_editor_widget(editor.editorstacks[0]) yield editor, qtbot # teardown os.environ['SPY_TEST_USE_INTROSPECTION'] = 'False' editor.introspector.plugin_manager.close() @pytest.mark.skipif(os.environ.get('CI', None) is not None, reason="It makes other tests to segfault in our CIs") @pytest.mark.skipif(not JEDI_010, reason="This feature is only supported in jedy >= 0.10") def test_introspection(setup_editor): """Validate changing path in introspection plugins.""" editor, qtbot = setup_editor code_editor = editor.get_focus_widget() completion = code_editor.completion_widget # Set cursor to start code_editor.go_to_line(1) # Complete fr --> from qtbot.keyClicks(code_editor, 'fr') qtbot.wait(20000) # press tab and get completions with qtbot.waitSignal(completion.sig_show_completions, timeout=10000) as sig: qtbot.keyPress(code_editor, Qt.Key_Tab) assert "from" in sig.args[0] # enter should accept first completion qtbot.keyPress(completion, Qt.Key_Enter, delay=1000) assert code_editor.toPlainText() == 'from\n' # Modify PYTHONPATH editor.introspector.change_extra_path([LOCATION]) qtbot.wait(10000) # Type 'from test' and try to get completion with qtbot.waitSignal(completion.sig_show_completions, timeout=10000) as sig: qtbot.keyClicks(code_editor, ' test_') qtbot.keyPress(code_editor, Qt.Key_Tab) assert "test_editor_introspection" in sig.args[0] spyder-3.2.6/spyder/plugins/tests/test_ipythonconsole.py0000664000175000017500000006353613224462407024462 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # import codecs import os import os.path as osp import shutil import tempfile from textwrap import dedent import cloudpickle from flaky import flaky from pygments.token import Name import pytest from qtpy import PYQT4, PYQT5, PYQT_VERSION from qtpy.QtCore import Qt, QTimer from qtpy.QtWidgets import QApplication from spyder.config.gui import get_color_scheme from spyder.config.main import CONF from spyder.py3compat import PY2, PY3 from spyder.plugins.ipythonconsole import (IPythonConsole, KernelConnectionDialog) from spyder.utils.environ import listdict2envdict from spyder.utils.ipython.style import create_style_class from spyder.utils.programs import TEMPDIR from spyder.utils.test import close_message_box from spyder.widgets.variableexplorer.collectionseditor import CollectionsEditor #============================================================================== # Constants #============================================================================== SHELL_TIMEOUT = 20000 PYQT_WHEEL = PYQT_VERSION > '5.6' TEMP_DIRECTORY = tempfile.gettempdir() NON_ASCII_DIR = osp.join(TEMP_DIRECTORY, u'測試', u'اختبار') #============================================================================== # Utillity Functions #============================================================================== def open_client_from_connection_info(connection_info, qtbot): top_level_widgets = QApplication.topLevelWidgets() for w in top_level_widgets: if isinstance(w, KernelConnectionDialog): w.cf.setText(connection_info) qtbot.keyClick(w, Qt.Key_Enter) def get_console_font_color(syntax_style): styles = create_style_class(syntax_style).styles font_color = styles[Name] return font_color def get_console_background_color(style_sheet): background_color = style_sheet.split('background-color:')[1] background_color = background_color.split(';')[0] return background_color #============================================================================== # Qt Test Fixtures #============================================================================== @pytest.fixture def ipyconsole(request): """IPython console fixture.""" # Tests assume inline backend CONF.set('ipython_console', 'pylab/backend', 0) # Test the console with a non-ascii temp dir non_ascii_dir = request.node.get_marker('non_ascii_dir') if non_ascii_dir: test_dir = NON_ASCII_DIR else: test_dir = TEMPDIR # Instruct the console to not use a stderr file no_stderr_file = request.node.get_marker('no_stderr_file') if no_stderr_file: test_no_stderr = True else: test_no_stderr = False auto_backend = request.node.get_marker('auto_backend') if auto_backend: CONF.set('ipython_console', 'pylab/backend', 1) # Create the console and a new client console = IPythonConsole(parent=None, testing=True, test_dir=test_dir, test_no_stderr=test_no_stderr) console.create_new_client() def close_console(): console.closing_plugin() console.close() request.addfinalizer(close_console) console.show() return console #============================================================================== # Tests #============================================================================== @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.auto_backend @pytest.mark.skipif(os.name == 'nt' or PYQT4, reason="It times out sometimes on Windows and it's not needed in PyQt4") def test_auto_backend(ipyconsole, qtbot): """Test that the automatic backend is working correctly.""" # Wait until the window is fully up shell = ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # This is here to generate further errors with qtbot.waitSignal(shell.executed): shell.execute("%matplotlib qt5") # Assert there are no errors in the console control = ipyconsole.get_focus_widget() assert 'NOTE' not in control.toPlainText() assert 'Error' not in control.toPlainText() @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt', reason="It times out sometimes on Windows") def test_tab_rename_for_slaves(ipyconsole, qtbot): """Test slave clients are renamed correctly.""" # Wait until the window is fully up shell = ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) cf = ipyconsole.get_current_client().connection_file ipyconsole._create_client_for_kernel(cf, None, None, None) qtbot.wait(1000) # Rename slave ipyconsole.rename_tabs_after_change('foo') # Assert both clients have the same name assert 'foo' in ipyconsole.get_clients()[0].get_name() assert 'foo' in ipyconsole.get_clients()[1].get_name() @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt', reason="It times out sometimes on Windows") def test_no_repeated_tabs_name(ipyconsole, qtbot): """Test that tabs can't have repeated given names.""" # Rename first client ipyconsole.rename_tabs_after_change('foo') # Create a new client and try to rename it ipyconsole.create_new_client() ipyconsole.rename_tabs_after_change('foo') # Assert the rename didn't take place client_name = ipyconsole.get_current_client().get_name() assert '2' in client_name @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt', reason="It times out sometimes on Windows") def test_tabs_preserve_name_after_move(ipyconsole, qtbot): """Test that tabs preserve their names after they are moved.""" # Create a new client ipyconsole.create_new_client() # Move tabs ipyconsole.tabwidget.tabBar().moveTab(0, 1) # Assert the second client is in the first position client_name = ipyconsole.get_clients()[0].get_name() assert '2' in client_name @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt', reason="It times out sometimes on Windows") def test_conf_env_vars(ipyconsole, qtbot): """Test that kernels have env vars set by our kernel spec.""" # Wait until the window is fully up shell = ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Get a CONF env var with qtbot.waitSignal(shell.executed): shell.execute("import os; a = os.environ.get('SPY_SYMPY_O')") # Assert we get the assigned value correctly assert shell.get_value('a') == 'False' @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt', reason="It times out sometimes on Windows") @pytest.mark.no_stderr_file def test_no_stderr_file(ipyconsole, qtbot): """Test that consoles can run without an stderr.""" # Wait until the window is fully up shell = ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Execute a simple assignment with qtbot.waitSignal(shell.executed): shell.execute('a = 1') # Assert we get the assigned value correctly assert shell.get_value('a') == 1 @pytest.mark.slow @pytest.mark.non_ascii_dir @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt', reason="It times out sometimes on Windows") def test_non_ascii_stderr_file(ipyconsole, qtbot): """Test the creation of a console with a stderr file in a non-ascii dir.""" # Wait until the window is fully up shell = ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Execute a simple assignment with qtbot.waitSignal(shell.executed): shell.execute('a = 1') # Assert we get the assigned value assert shell.get_value('a') == 1 @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt', reason="It times out sometimes on Windows") def test_console_import_namespace(ipyconsole, qtbot): """Test an import of the form 'from foo import *'.""" # Wait until the window is fully up shell = ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Import numpy with qtbot.waitSignal(shell.executed): shell.execute('from numpy import *') # Assert we get the e value correctly assert shell.get_value('e') == 2.718281828459045 @pytest.mark.slow @flaky(max_runs=3) def test_console_disambiguation(ipyconsole, qtbot): """Test the disambiguation of dedicated consoles.""" # Create directories and file for TEMP_DIRECTORY/a/b/c.py # and TEMP_DIRECTORY/a/d/c.py dir_b = osp.join(TEMP_DIRECTORY, 'a', 'b') filename_b = osp.join(dir_b, 'c.py') if not osp.isdir(dir_b): os.makedirs(dir_b) if not osp.isfile(filename_b): file_c = open(filename_b, 'w+') file_c.close() dir_d = osp.join(TEMP_DIRECTORY, 'a', 'd') filename_d = osp.join(dir_d, 'c.py') if not osp.isdir(dir_d): os.makedirs(dir_d) if not osp.isfile(filename_d): file_e = open(filename_d, 'w+') file_e.close() # Create new client and assert name without disambiguation ipyconsole.create_client_for_file(filename_b) client = ipyconsole.get_current_client() assert client.get_name() == 'c.py/A' # Create new client and assert name with disambiguation ipyconsole.create_client_for_file(filename_d) client = ipyconsole.get_current_client() assert client.get_name() == 'c.py - d/A' ipyconsole.tabwidget.setCurrentIndex(1) client = ipyconsole.get_current_client() assert client.get_name() == 'c.py - b/A' @pytest.mark.slow @flaky(max_runs=3) def test_console_coloring(ipyconsole, qtbot): config_options = ipyconsole.config_options() syntax_style = config_options.JupyterWidget.syntax_style style_sheet = config_options.JupyterWidget.style_sheet console_font_color = get_console_font_color(syntax_style) console_background_color = get_console_background_color(style_sheet) selected_color_scheme = CONF.get('color_schemes', 'selected') color_scheme = get_color_scheme(selected_color_scheme) editor_background_color = color_scheme['background'] editor_font_color = color_scheme['normal'][0] console_background_color = console_background_color.replace("'", "") editor_background_color = editor_background_color.replace("'", "") console_font_color = console_font_color.replace("'", "") editor_font_color = editor_font_color.replace("'", "") assert console_background_color.strip() == editor_background_color.strip() assert console_font_color.strip() == editor_font_color.strip() @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt', reason="It doesn't work on Windows") def test_get_env(ipyconsole, qtbot): """Test that showing env var contents is working as expected.""" shell = ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Add a new entry to os.environ with qtbot.waitSignal(shell.executed): shell.execute("import os; os.environ['FOO'] = 'bar'" ) # Ask for os.environ contents with qtbot.waitSignal(shell.sig_show_env): shell.get_env() # Get env contents from the generated widget top_level_widgets = QApplication.topLevelWidgets() for w in top_level_widgets: if isinstance(w, CollectionsEditor): env_contents = w.get_value() qtbot.keyClick(w, Qt.Key_Enter) # Assert that our added entry is part of os.environ env_contents = listdict2envdict(env_contents) assert env_contents['FOO'] == 'bar' @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt', reason="It doesn't work on Windows") def test_get_syspath(ipyconsole, qtbot): """Test that showing sys.path contents is working as expected.""" shell = ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Add a new entry to sys.path with qtbot.waitSignal(shell.executed): tmp_dir = tempfile.mkdtemp() shell.execute("import sys, tempfile; sys.path.append('%s')" % tmp_dir) # Ask for sys.path contents with qtbot.waitSignal(shell.sig_show_syspath): shell.get_syspath() # Get sys.path contents from the generated widget top_level_widgets = QApplication.topLevelWidgets() for w in top_level_widgets: if isinstance(w, CollectionsEditor): syspath_contents = w.get_value() qtbot.keyClick(w, Qt.Key_Enter) # Assert that our added entry is part of sys.path assert tmp_dir in syspath_contents # Remove temporary directory try: os.rmdir(tmp_dir) except: pass @pytest.mark.slow @flaky(max_runs=10) @pytest.mark.skipif(os.name == 'nt', reason="It doesn't work on Windows") def test_browse_history_dbg(ipyconsole, qtbot): """Test that browsing command history is working while debugging.""" shell = ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Give focus to the widget that's going to receive clicks control = ipyconsole.get_focus_widget() control.setFocus() # Generate a traceback and enter debugging mode with qtbot.waitSignal(shell.executed): shell.execute('1/0') shell.execute('%debug') qtbot.wait(1000) # Enter an expression qtbot.keyClicks(control, '!aa = 10') qtbot.keyClick(control, Qt.Key_Enter) # Clear console (for some reason using shell.clear_console # doesn't work here) shell.reset(clear=True) qtbot.wait(1000) # Press Up arrow button and assert we get the last # introduced command qtbot.keyClick(control, Qt.Key_Up) assert '!aa = 10' in control.toPlainText() @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt' or PY2, reason="It times out sometimes on Windows and doesn't work on PY2") def test_unicode_vars(ipyconsole, qtbot): """ Test that the Variable Explorer Works with unicode variables. """ # Wait until the window is fully up shell = ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Set value for a Unicode variable with qtbot.waitSignal(shell.executed): shell.execute('д = 10') # Assert we get its value correctly assert shell.get_value('д') == 10 # Change its value and verify shell.set_value('д', [cloudpickle.dumps(20, protocol=2)]) qtbot.wait(1000) assert shell.get_value('д') == 20 @pytest.mark.slow @flaky(max_runs=3) def test_read_stderr(ipyconsole, qtbot): """ Test the read operation of the stderr file of the kernel """ shell = ipyconsole.get_current_shellwidget() client = ipyconsole.get_current_client() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Set contents of the stderr file of the kernel content = 'Test text' stderr_file = client.stderr_file codecs.open(stderr_file, 'w', 'cp437').write(content) # Assert that content is correct assert content == client._read_stderr() @flaky(max_runs=10) @pytest.mark.no_xvfb @pytest.mark.skipif(os.environ.get('CI', None) is not None, reason="It times out in our CIs") def test_values_dbg(ipyconsole, qtbot): """ Test that getting, setting, copying and removing values is working while debugging. """ shell = ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Give focus to the widget that's going to receive clicks control = ipyconsole.get_focus_widget() control.setFocus() # Generate a traceback and enter debugging mode with qtbot.waitSignal(shell.executed): shell.execute('1/0') shell.execute('%debug') qtbot.wait(1000) # Get value qtbot.keyClicks(control, '!aa = 10') qtbot.keyClick(control, Qt.Key_Enter) qtbot.wait(1000) assert shell.get_value('aa') == 10 # Set value shell.set_value('aa', [cloudpickle.dumps(20, protocol=2)]) qtbot.wait(1000) assert shell.get_value('aa') == 20 # Copy value shell.copy_value('aa', 'bb') qtbot.wait(1000) assert shell.get_value('bb') == 20 # Rmoeve value shell.remove_value('aa') qtbot.wait(1000) qtbot.keyClicks(control, '!aa') qtbot.keyClick(control, Qt.Key_Enter) qtbot.wait(1000) assert "*** NameError: name 'aa' is not defined" in control.toPlainText() @pytest.mark.slow @flaky(max_runs=10) @pytest.mark.skipif(os.name == 'nt', reason="It doesn't work on Windows") def test_plot_magic_dbg(ipyconsole, qtbot): """Test our plot magic while debugging""" shell = ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Give focus to the widget that's going to receive clicks control = ipyconsole.get_focus_widget() control.setFocus() # Import Matplotlib with qtbot.waitSignal(shell.executed): shell.execute('import matplotlib.pyplot as plt') # Generate a traceback and enter debugging mode with qtbot.waitSignal(shell.executed): shell.execute('1/0') shell.execute('%debug') qtbot.wait(1000) # Test reset magic qtbot.keyClicks(control, '%plot plt.plot(range(10))') qtbot.keyClick(control, Qt.Key_Enter) qtbot.wait(1000) # Assert that there's a plot in the console assert shell._control.toHtml().count('img src') == 1 @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt', reason="It times out on Windows") def test_run_doctest(ipyconsole, qtbot): """ Test that doctests can be run without problems """ shell = ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) code = dedent(''' def add(x, y): """ >>> add(1, 2) 3 >>> add(5.1, 2.2) 7.3 """ return x + y ''') # Run code with qtbot.waitSignal(shell.executed): shell.execute(code) # Import doctest with qtbot.waitSignal(shell.executed): shell.execute('import doctest') # Run doctest with qtbot.waitSignal(shell.executed): shell.execute('doctest.testmod()') # Assert that doctests were run correctly assert "TestResults(failed=0, attempted=2)" in shell._control.toPlainText() @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt' or (PY2 and PYQT5) or PYQT4, reason="It times out frequently") def test_mpl_backend_change(ipyconsole, qtbot): """ Test that Matplotlib backend is changed correctly when using the %matplotlib magic """ shell = ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Import Matplotlib with qtbot.waitSignal(shell.executed): shell.execute('import matplotlib.pyplot as plt') # Generate a plot with qtbot.waitSignal(shell.executed): shell.execute('plt.plot(range(10))') # Change backends with qtbot.waitSignal(shell.executed): shell.execute('%matplotlib tk') # Generate another plot with qtbot.waitSignal(shell.executed): shell.execute('plt.plot(range(10))') # Assert that there's a single inline plot in the console assert shell._control.toHtml().count('img src') == 1 @flaky(max_runs=10) @pytest.mark.skipif(os.environ.get('CI', None) is not None or PYQT5, reason="It fails frequently in PyQt5 and our CIs") def test_ctrl_c_dbg(ipyconsole, qtbot): """ Test that Ctrl+C works while debugging """ shell = ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Give focus to the widget that's going to receive clicks control = ipyconsole.get_focus_widget() control.setFocus() # Generate a traceback and enter debugging mode with qtbot.waitSignal(shell.executed): shell.execute('1/0') shell.execute('%debug') qtbot.wait(1000) # Test Ctrl+C qtbot.keyClick(control, Qt.Key_C, modifier=Qt.ControlModifier) qtbot.wait(2000) assert 'For copying text while debugging, use Ctrl+Shift+C' in control.toPlainText() @pytest.mark.slow @flaky(max_runs=10) @pytest.mark.skipif(os.name == 'nt', reason="It doesn't work on Windows") def test_clear_and_reset_magics_dbg(ipyconsole, qtbot): """ Test that clear and reset magics are working while debugging """ shell = ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Give focus to the widget that's going to receive clicks control = ipyconsole.get_focus_widget() control.setFocus() # Generate a traceback and enter debugging mode with qtbot.waitSignal(shell.executed): shell.execute('1/0') shell.execute('%debug') qtbot.wait(1000) # Test clear magic shell.clear_console() qtbot.wait(1000) assert '\nipdb> ' == control.toPlainText() # Test reset magic qtbot.keyClicks(control, '!bb = 10') qtbot.keyClick(control, Qt.Key_Enter) qtbot.wait(500) assert shell.get_value('bb') == 10 shell.reset_namespace(warning=False, silent=True) qtbot.wait(1000) qtbot.keyClicks(control, '!bb') qtbot.keyClick(control, Qt.Key_Enter) qtbot.wait(500) assert "*** NameError: name 'bb' is not defined" in control.toPlainText() @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt', reason="It times out on Windows") def test_restart_kernel(ipyconsole, qtbot): """ Test that kernel is restarted correctly """ shell = ipyconsole.get_current_shellwidget() client = ipyconsole.get_current_client() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Do an assignment to verify that it's not there after restarting with qtbot.waitSignal(shell.executed): shell.execute('a = 10') # Restart kernel and wait until it's up again shell._prompt_html = None QTimer.singleShot(1000, lambda: close_message_box(qtbot)) client.restart_kernel() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) assert not shell.is_defined('a') @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt', reason="It times out on Windows") def test_load_kernel_file_from_id(ipyconsole, qtbot): """ Test that a new client is created using its id """ shell = ipyconsole.get_current_shellwidget() client = ipyconsole.get_current_client() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) connection_file = osp.basename(client.connection_file) id_ = connection_file.split('kernel-')[-1].split('.json')[0] QTimer.singleShot(2000, lambda: open_client_from_connection_info( id_, qtbot)) ipyconsole.create_client_for_kernel() qtbot.wait(1000) new_client = ipyconsole.get_clients()[1] assert new_client.id_ == dict(int_id='1', str_id='B') @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt' or (PY3 and PYQT4), reason="It segfaults frequently") def test_load_kernel_file_from_location(ipyconsole, qtbot): """ Test that a new client is created using a connection file placed in a different location from jupyter_runtime_dir """ shell = ipyconsole.get_current_shellwidget() client = ipyconsole.get_current_client() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) connection_file = osp.join(tempfile.gettempdir(), osp.basename(client.connection_file)) shutil.copy2(client.connection_file, connection_file) QTimer.singleShot(2000, lambda: open_client_from_connection_info( connection_file, qtbot)) ipyconsole.create_client_for_kernel() qtbot.wait(1000) assert len(ipyconsole.get_clients()) == 2 @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt' or PYQT4, reason="It segfaults frequently") def test_load_kernel_file(ipyconsole, qtbot): """ Test that a new client is created using the connection file of an existing client """ shell = ipyconsole.get_current_shellwidget() client = ipyconsole.get_current_client() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) QTimer.singleShot(2000, lambda: open_client_from_connection_info( client.connection_file, qtbot)) ipyconsole.create_client_for_kernel() qtbot.wait(1000) new_client = ipyconsole.get_clients()[1] new_shell = new_client.shellwidget with qtbot.waitSignal(new_shell.executed): new_shell.execute('a = 10') assert new_client.id_ == dict(int_id='1', str_id='B') assert shell.get_value('a') == new_shell.get_value('a') @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt', reason="It times out on Windows") def test_sys_argv_clear(ipyconsole, qtbot): """Test that sys.argv is cleared up correctly""" shell = ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) with qtbot.waitSignal(shell.executed): shell.execute('import sys; A = sys.argv') argv = shell.get_value("A") assert argv == [''] if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/plugins/tests/test_shorcuts.py0000664000175000017500000000131413156676663023260 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for shortcuts.py """ import os # Test library imports import pytest # Local imports from spyder.plugins.shortcuts import ShortcutsTable @pytest.fixture def setup_shorcuts(qtbot): """Set up shortcuts.""" widget = ShortcutsTable() qtbot.addWidget(widget) return widget @pytest.mark.skipif(not os.name == 'nt', reason="It segfaults too much on Linux") def test_shortcuts(qtbot): """Run shortcuts table.""" shortcuts = setup_shorcuts(qtbot) shortcuts.show() shortcuts.check_shortcuts() assert shortcuts if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/plugins/tests/test_variableexplorer.py0000664000175000017500000000203713156676663024757 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License """ Tests for variableexplorer.py """ import pytest from spyder.utils.qthelpers import qapplication from spyder.plugins.variableexplorer import VariableExplorer def test_get_settings(monkeypatch): def mock_get_option(self, option): if option == 'remote1': return 'remote1val' if option == 'remote2': return 'remote2val' if option == 'dataframe_format': return '3d' monkeypatch.setattr(VariableExplorer, 'CONF_SECTION', 'sect') monkeypatch.setattr('spyder.plugins.variableexplorer.REMOTE_SETTINGS', ['remote1', 'remote2']) monkeypatch.setattr(VariableExplorer, 'get_option', mock_get_option) app = qapplication() settings = VariableExplorer(None).get_settings() expected = {'remote1': 'remote1val', 'remote2': 'remote2val', 'dataframe_format': '%3d'} assert settings == expected if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/plugins/tests/__init__.py0000664000175000017500000000050213156676663022104 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Copyright (c) Spyder Project Contributors # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Tests.""" spyder-3.2.6/spyder/plugins/explorer.py0000664000175000017500000000730013224740762021032 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Files and Directories Explorer Plugin""" # pylint: disable=C0103 # pylint: disable=R0903 # pylint: disable=R0911 # pylint: disable=R0201 # Standard library imports import os.path as osp # Third party imports from qtpy.QtCore import Signal # Local imports from spyder.config.base import _ from spyder.plugins import SpyderPluginMixin from spyder.py3compat import to_text_string from spyder.widgets.explorer import ExplorerWidget class Explorer(ExplorerWidget, SpyderPluginMixin): """File and Directories Explorer DockWidget""" CONF_SECTION = 'explorer' open_interpreter = Signal(str) edit = Signal(str) removed = Signal(str) removed_tree = Signal(str) renamed = Signal(str, str) create_module = Signal(str) run = Signal(str) open_dir = Signal(str) def __init__(self, parent=None): ExplorerWidget.__init__(self, parent=parent, name_filters=self.get_option('name_filters'), show_all=self.get_option('show_all'), show_icontext=self.get_option('show_icontext')) SpyderPluginMixin.__init__(self, parent) # Initialize plugin self.initialize_plugin() #------ SpyderPluginWidget API --------------------------------------------- def get_plugin_title(self): """Return widget title""" return _("File explorer") def get_focus_widget(self): """ Return the widget to give focus to when this plugin's dockwidget is raised on top-level """ return self.treewidget def get_plugin_actions(self): """Return a list of actions related to plugin""" return [] 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.removed_tree.connect(self.main.editor.removed_tree) self.renamed.connect(self.main.editor.renamed) self.main.editor.open_dir.connect(self.chdir) self.create_module.connect(self.main.editor.new) # 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, refresh_console=True)) self.sig_open_file.connect(self.main.open_file) self.sig_new_file.connect(lambda t: self.main.editor.new(text=t)) def refresh_plugin(self, new_path=None, force_current=True): """Refresh explorer widget""" self.treewidget.update_history(new_path) self.treewidget.refresh(new_path, force_current=force_current) def closing_plugin(self, cancelable=False): """Perform actions before parent main window is closed""" return True #------ Public API --------------------------------------------------------- def chdir(self, directory): """Set working directory""" self.treewidget.chdir(directory) spyder-3.2.6/spyder/plugins/history.py0000664000175000017500000002425413224740762020702 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Console History Plugin""" # Standard library imports import os.path as osp import sys # Third party imports from qtpy import PYQT5 from qtpy.QtCore import Signal, Slot from qtpy.QtWidgets import (QGroupBox, QHBoxLayout, QInputDialog, QMenu, QToolButton, QVBoxLayout, QWidget) # Local imports from spyder.utils import encoding from spyder.config.base import _ from spyder.plugins import SpyderPluginWidget from spyder.plugins.configdialog import PluginConfigPage from spyder.py3compat import is_text_string, to_text_string from spyder.utils import icon_manager as ima from spyder.utils.qthelpers import (add_actions, create_action, create_toolbutton) from spyder.widgets.tabs import Tabs from spyder.widgets.sourcecode import codeeditor from spyder.widgets.findreplace import FindReplace class HistoryConfigPage(PluginConfigPage): def get_icon(self): return ima.icon('history') def setup_page(self): settings_group = QGroupBox(_("Settings")) hist_spin = self.create_spinbox( _("History depth: "), _(" entries"), 'max_entries', min_=10, max_=10000, step=10, tip=_("Set maximum line count")) sourcecode_group = QGroupBox(_("Source code")) wrap_mode_box = self.create_checkbox(_("Wrap lines"), 'wrap') go_to_eof_box = self.create_checkbox( _("Scroll automatically to last entry"), 'go_to_eof') settings_layout = QVBoxLayout() settings_layout.addWidget(hist_spin) settings_group.setLayout(settings_layout) sourcecode_layout = QVBoxLayout() sourcecode_layout.addWidget(wrap_mode_box) sourcecode_layout.addWidget(go_to_eof_box) sourcecode_group.setLayout(sourcecode_layout) vlayout = QVBoxLayout() vlayout.addWidget(settings_group) vlayout.addWidget(sourcecode_group) vlayout.addStretch(1) self.setLayout(vlayout) class HistoryLog(SpyderPluginWidget): """ History log widget """ CONF_SECTION = 'historylog' CONFIGWIDGET_CLASS = HistoryConfigPage focus_changed = Signal() def __init__(self, parent): self.tabwidget = None self.menu_actions = None self.dockviewer = None self.wrap_action = None self.editors = [] self.filenames = [] if PYQT5: SpyderPluginWidget.__init__(self, parent, main = parent) else: SpyderPluginWidget.__init__(self, parent) # Initialize plugin self.initialize_plugin() layout = QVBoxLayout() self.tabwidget = Tabs(self, self.menu_actions) self.tabwidget.currentChanged.connect(self.refresh_plugin) self.tabwidget.move_data.connect(self.move_tab) if sys.platform == 'darwin': tab_container = QWidget() tab_container.setObjectName('tab-container') tab_layout = QHBoxLayout(tab_container) tab_layout.setContentsMargins(0, 0, 0, 0) tab_layout.addWidget(self.tabwidget) layout.addWidget(tab_container) else: layout.addWidget(self.tabwidget) # Menu as corner widget options_button = create_toolbutton(self, text=_('Options'), icon=ima.icon('tooloptions')) options_button.setPopupMode(QToolButton.InstantPopup) menu = QMenu(self) add_actions(menu, self.menu_actions) options_button.setMenu(menu) self.tabwidget.setCornerWidget(options_button) # Find/replace widget self.find_widget = FindReplace(self) self.find_widget.hide() self.register_widget_shortcuts(self.find_widget) layout.addWidget(self.find_widget) self.setLayout(layout) #------ SpyderPluginWidget API --------------------------------------------- def get_plugin_title(self): """Return widget title""" return _('History log') def get_plugin_icon(self): """Return widget icon""" return ima.icon('history') def get_focus_widget(self): """ Return the widget to give focus to when this plugin's dockwidget is raised on top-level """ return self.tabwidget.currentWidget() def closing_plugin(self, cancelable=False): """Perform actions before parent main window is closed""" return True def refresh_plugin(self): """Refresh tabwidget""" if self.tabwidget.count(): editor = self.tabwidget.currentWidget() else: editor = None self.find_widget.set_editor(editor) def get_plugin_actions(self): """Return a list of actions related to plugin""" history_action = create_action(self, _("History..."), None, ima.icon('history'), _("Set history maximum entries"), triggered=self.change_history_depth) self.wrap_action = create_action(self, _("Wrap lines"), toggled=self.toggle_wrap_mode) self.wrap_action.setChecked( self.get_option('wrap') ) self.menu_actions = [history_action, self.wrap_action] return self.menu_actions def on_first_registration(self): """Action to be performed on first plugin registration""" self.main.tabify_plugins(self.main.ipyconsole, self) def register_plugin(self): """Register plugin in Spyder's main window""" self.focus_changed.connect(self.main.plugin_focus_changed) self.main.add_dockwidget(self) # self.main.console.set_historylog(self) self.main.console.shell.refresh.connect(self.refresh_plugin) def update_font(self): """Update font from Preferences""" color_scheme = self.get_color_scheme() font = self.get_plugin_font() for editor in self.editors: editor.set_font(font, color_scheme) def apply_plugin_settings(self, options): """Apply configuration file's plugin settings""" color_scheme_n = 'color_scheme_name' color_scheme_o = self.get_color_scheme() font_n = 'plugin_font' font_o = self.get_plugin_font() wrap_n = 'wrap' wrap_o = self.get_option(wrap_n) self.wrap_action.setChecked(wrap_o) for editor in self.editors: if font_n in options: scs = color_scheme_o if color_scheme_n in options else None editor.set_font(font_o, scs) elif color_scheme_n in options: editor.set_color_scheme(color_scheme_o) if wrap_n in options: editor.toggle_wrap_mode(wrap_o) #------ Private API -------------------------------------------------------- def move_tab(self, index_from, index_to): """ Move tab (tabs themselves have already been moved by the tabwidget) """ filename = self.filenames.pop(index_from) editor = self.editors.pop(index_from) self.filenames.insert(index_to, filename) self.editors.insert(index_to, editor) #------ Public API --------------------------------------------------------- def add_history(self, filename): """ Add new history tab Slot for add_history signal emitted by shell instance """ filename = encoding.to_unicode_from_fs(filename) if filename in self.filenames: return editor = codeeditor.CodeEditor(self) if osp.splitext(filename)[1] == '.py': language = 'py' else: language = 'bat' editor.setup_editor(linenumbers=False, language=language, scrollflagarea=False) editor.focus_changed.connect(lambda: self.focus_changed.emit()) editor.setReadOnly(True) color_scheme = self.get_color_scheme() editor.set_font( self.get_plugin_font(), color_scheme ) editor.toggle_wrap_mode( self.get_option('wrap') ) text, _ = encoding.read(filename) editor.set_text(text) editor.set_cursor_position('eof') self.editors.append(editor) self.filenames.append(filename) index = self.tabwidget.addTab(editor, osp.basename(filename)) self.find_widget.set_editor(editor) self.tabwidget.setTabToolTip(index, filename) self.tabwidget.setCurrentIndex(index) 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) @Slot() def change_history_depth(self): "Change history max entries""" depth, valid = QInputDialog.getInt(self, _('History'), _('Maximum entries'), self.get_option('max_entries'), 10, 10000) if valid: self.set_option('max_entries', depth) @Slot(bool) def toggle_wrap_mode(self, checked): """Toggle wrap mode""" if self.tabwidget is None: return for editor in self.editors: editor.toggle_wrap_mode(checked) self.set_option('wrap', checked) spyder-3.2.6/spyder/plugins/shortcuts.py0000664000175000017500000010206113224121062021212 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Shortcut management""" # Standard library imports from __future__ import print_function import os import re import sys # Third party imports from qtpy import PYQT5 from qtpy.compat import from_qvariant, to_qvariant from qtpy.QtCore import (QAbstractTableModel, QModelIndex, QRegExp, QSortFilterProxyModel, Qt, Slot) from qtpy.QtGui import (QKeySequence, QRegExpValidator) from qtpy.QtWidgets import (QAbstractItemView, QApplication, QDialog, QDialogButtonBox, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QMessageBox, QPushButton, QSpacerItem, QTableView, QVBoxLayout) # Local imports from spyder.config.base import _, debug_print from spyder.config.gui import (get_shortcut, iter_shortcuts, reset_shortcuts, set_shortcut) from spyder.plugins.configdialog import GeneralConfigPage from spyder.utils import icon_manager as ima from spyder.utils.qthelpers import get_std_icon from spyder.utils.stringmatching import get_search_scores, get_search_regex from spyder.widgets.helperwidgets import HTMLDelegate from spyder.widgets.helperwidgets import HelperToolButton MODIFIERS = {Qt.Key_Shift: Qt.SHIFT, Qt.Key_Control: Qt.CTRL, Qt.Key_Alt: Qt.ALT, Qt.Key_Meta: Qt.META} # Valid shortcut keys SINGLE_KEYS = ["F{}".format(_i) for _i in range(1, 36)] + ["Delete", "Escape"] KEYSTRINGS = ["Tab", "Backtab", "Backspace", "Return", "Enter", "Pause", "Print", "Clear", "Home", "End", "Left", "Up", "Right", "Down", "PageUp", "PageDown"] + \ ["Space", "Exclam", "QuoteDbl", "NumberSign", "Dollar", "Percent", "Ampersand", "Apostrophe", "ParenLeft", "ParenRight", "Asterisk", "Plus", "Comma", "Minus", "Period", "Slash"] + \ [str(_i) for _i in range(10)] + \ ["Colon", "Semicolon", "Less", "Equal", "Greater", "Question", "At"] + [chr(_i) for _i in range(65, 91)] + \ ["BracketLeft", "Backslash", "BracketRight", "Underscore", "Control", "Alt", "Shift", "Meta"] VALID_SINGLE_KEYS = [getattr(Qt, 'Key_{0}'.format(k)) for k in SINGLE_KEYS] VALID_KEYS = [getattr(Qt, 'Key_{0}'.format(k)) for k in KEYSTRINGS+SINGLE_KEYS] # Valid finder chars. To be improved VALID_ACCENT_CHARS = "ÁÉÍOÚáéíúóàèìòùÀÈÌÒÙâêîôûÂÊÎÔÛäëïöüÄËÏÖÜñÑ" VALID_FINDER_CHARS = "[A-Za-z\s{0}]".format(VALID_ACCENT_CHARS) BLACKLIST = { 'Shift+Del': _('Currently used to delete lines on editor/Cut a word'), 'Shift+Ins': _('Currently used to paste a word') } if os.name == 'nt': BLACKLIST['Alt+Backspace'] = _('We cannot support this ' 'shortcut on Windows') BLACKLIST['Shift'] = _('Shortcuts that use Shift and another key' ' are unsupported') class CustomLineEdit(QLineEdit): """QLineEdit that filters its key press and release events.""" def __init__(self, parent): super(CustomLineEdit, self).__init__(parent) self.setReadOnly(True) self.setFocusPolicy(Qt.NoFocus) def keyPressEvent(self, e): """Qt Override""" self.parent().keyPressEvent(e) def keyReleaseEvent(self, e): """Qt Override""" self.parent().keyReleaseEvent(e) class ShortcutFinder(QLineEdit): """Textbox for filtering listed shortcuts in the table.""" def __init__(self, parent, callback=None): super(ShortcutFinder, self).__init__(parent) self._parent = parent # Widget setup regex = QRegExp(VALID_FINDER_CHARS + "{100}") self.setValidator(QRegExpValidator(regex)) # Signals if callback: self.textChanged.connect(callback) def set_text(self, text): """Set the filter text.""" text = text.strip() new_text = self.text() + text self.setText(new_text) def keyPressEvent(self, event): """Qt Override.""" key = event.key() if key in [Qt.Key_Up]: self._parent.previous_row() elif key in [Qt.Key_Down]: self._parent.next_row() elif key in [Qt.Key_Enter, Qt.Key_Return]: self._parent.show_editor() else: super(ShortcutFinder, self).keyPressEvent(event) # Error codes for the shortcut editor dialog (NO_WARNING, SEQUENCE_LENGTH, SEQUENCE_CONFLICT, INVALID_KEY, IN_BLACKLIST, SHIFT_BLACKLIST) = [0, 1, 2, 3, 4, 5] class ShortcutEditor(QDialog): """A dialog for entering key sequences.""" def __init__(self, parent, context, name, sequence, shortcuts): super(ShortcutEditor, self).__init__(parent) self._parent = parent self.context = context self.npressed = 0 self.keys = set() self.key_modifiers = set() self.key_non_modifiers = list() self.key_text = list() self.sequence = sequence self.new_sequence = None self.edit_state = True self.shortcuts = shortcuts # Widgets self.label_info = QLabel() self.label_info.setText(_("Press the new shortcut and select 'Ok': \n" "(Press 'Tab' once to switch focus between the shortcut entry \n" "and the buttons below it)")) self.label_current_sequence = QLabel(_("Current shortcut:")) self.text_current_sequence = QLabel(sequence) self.label_new_sequence = QLabel(_("New shortcut:")) self.text_new_sequence = CustomLineEdit(self) self.text_new_sequence.setPlaceholderText(sequence) self.helper_button = HelperToolButton() self.helper_button.hide() self.label_warning = QLabel() self.label_warning.hide() bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.button_ok = bbox.button(QDialogButtonBox.Ok) self.button_cancel = bbox.button(QDialogButtonBox.Cancel) # Setup widgets self.setWindowTitle(_('Shortcut: {0}').format(name)) self.button_ok.setFocusPolicy(Qt.NoFocus) self.button_ok.setEnabled(False) self.button_cancel.setFocusPolicy(Qt.NoFocus) self.helper_button.setToolTip('') self.helper_button.setFocusPolicy(Qt.NoFocus) style = """ QToolButton { margin:1px; border: 0px solid grey; padding:0px; border-radius: 0px; }""" self.helper_button.setStyleSheet(style) self.text_new_sequence.setFocusPolicy(Qt.NoFocus) self.label_warning.setFocusPolicy(Qt.NoFocus) # Layout spacing = 5 layout_sequence = QGridLayout() layout_sequence.addWidget(self.label_info, 0, 0, 1, 3) layout_sequence.addItem(QSpacerItem(spacing, spacing), 1, 0, 1, 2) layout_sequence.addWidget(self.label_current_sequence, 2, 0) layout_sequence.addWidget(self.text_current_sequence, 2, 2) layout_sequence.addWidget(self.label_new_sequence, 3, 0) layout_sequence.addWidget(self.helper_button, 3, 1) layout_sequence.addWidget(self.text_new_sequence, 3, 2) layout_sequence.addWidget(self.label_warning, 4, 2, 1, 2) layout = QVBoxLayout() layout.addLayout(layout_sequence) layout.addSpacing(spacing) layout.addWidget(bbox) self.setLayout(layout) # Signals bbox.accepted.connect(self.accept) bbox.rejected.connect(self.reject) @Slot() def reject(self): """Slot for rejected signal.""" # Added for issue #5426. Due to the focusPolicy of Qt.NoFocus for the # buttons, if the cancel button was clicked without first setting focus # to the button, it would cause a seg fault crash. self.button_cancel.setFocus() super().reject() @Slot() def accept(self): """Slot for accepted signal.""" # Added for issue #5426. Due to the focusPolicy of Qt.NoFocus for the # buttons, if the ok button was clicked without first setting focus to # the button, it would cause a seg fault crash. self.button_ok.setFocus() super().accept() def keyPressEvent(self, e): """Qt override.""" key = e.key() # Check if valid keys if key not in VALID_KEYS: self.invalid_key_flag = True return self.npressed += 1 self.key_non_modifiers.append(key) self.key_modifiers.add(key) self.key_text.append(e.text()) self.invalid_key_flag = False debug_print('key {0}, npressed: {1}'.format(key, self.npressed)) if key == Qt.Key_unknown: return # The user clicked just and only the special keys # Ctrl, Shift, Alt, Meta. if (key == Qt.Key_Control or key == Qt.Key_Shift or key == Qt.Key_Alt or key == Qt.Key_Meta): return modifiers = e.modifiers() if modifiers & Qt.ShiftModifier: key += Qt.SHIFT if modifiers & Qt.ControlModifier: key += Qt.CTRL if sys.platform == 'darwin': self.npressed -= 1 debug_print('decrementing') if modifiers & Qt.AltModifier: key += Qt.ALT if modifiers & Qt.MetaModifier: key += Qt.META self.keys.add(key) def toggle_state(self): """Switch between shortcut entry and Accept/Cancel shortcut mode.""" self.edit_state = not self.edit_state if not self.edit_state: self.text_new_sequence.setEnabled(False) if self.button_ok.isEnabled(): self.button_ok.setFocus() else: self.button_cancel.setFocus() else: self.text_new_sequence.setEnabled(True) self.text_new_sequence.setFocus() def nonedit_keyrelease(self, e): """Key release event for non-edit state.""" key = e.key() if key in [Qt.Key_Escape]: self.close() return if key in [Qt.Key_Left, Qt.Key_Right, Qt.Key_Up, Qt.Key_Down]: if self.button_ok.hasFocus(): self.button_cancel.setFocus() else: self.button_ok.setFocus() def keyReleaseEvent(self, e): """Qt override.""" self.npressed -= 1 if self.npressed <= 0: key = e.key() if len(self.keys) == 1 and key == Qt.Key_Tab: self.toggle_state() return if len(self.keys) == 1 and key == Qt.Key_Escape: self.set_sequence('') self.label_warning.setText(_("Please introduce a different " "shortcut")) if len(self.keys) == 1 and key in [Qt.Key_Return, Qt.Key_Enter]: self.toggle_state() return if not self.edit_state: self.nonedit_keyrelease(e) else: debug_print('keys: {}'.format(self.keys)) if self.keys and key != Qt.Key_Escape: self.validate_sequence() self.keys = set() self.key_modifiers = set() self.key_non_modifiers = list() self.key_text = list() self.npressed = 0 def check_conflicts(self): """Check shortcuts for conflicts.""" conflicts = [] for index, shortcut in enumerate(self.shortcuts): sequence = str(shortcut.key) if sequence == self.new_sequence and \ (shortcut.context == self.context or shortcut.context == '_' or self.context == '_'): conflicts.append(shortcut) return conflicts def update_warning(self, warning_type=NO_WARNING, conflicts=[]): """Update warning label to reflect conflict status of new shortcut""" if warning_type == NO_WARNING: warn = False tip = 'This shortcut is correct!' elif warning_type == SEQUENCE_CONFLICT: template = '{0}{1}' tip_title = _('The new shortcut conflicts with:') + '
    ' tip_body = '' for s in conflicts: tip_body += ' - {0}: {1}
    '.format(s.context, s.name) tip_body = tip_body[:-4] # Removing last
    tip = template.format(tip_title, tip_body) warn = True elif warning_type == IN_BLACKLIST: template = '{0}{1}' tip_title = _('Forbidden key sequence!') + '
    ' tip_body = '' use = BLACKLIST[self.new_sequence] if use is not None: tip_body = use tip = template.format(tip_title, tip_body) warn = True elif warning_type == SHIFT_BLACKLIST: template = '{0}{1}' tip_title = _('Forbidden key sequence!') + '
    ' tip_body = '' use = BLACKLIST['Shift'] if use is not None: tip_body = use tip = template.format(tip_title, tip_body) warn = True elif warning_type == SEQUENCE_LENGTH: # Sequences with 5 keysequences (i.e. Ctrl+1, Ctrl+2, Ctrl+3, # Ctrl+4, Ctrl+5) are invalid template = '{0}' tip = _('A compound sequence can have {break} a maximum of ' '4 subsequences.{break}').format(**{'break': '
    '}) warn = True elif warning_type == INVALID_KEY: template = '{0}' tip = _('Invalid key entered') + '
    ' warn = True self.helper_button.show() if warn: self.label_warning.show() self.helper_button.setIcon(get_std_icon('MessageBoxWarning')) self.button_ok.setEnabled(False) else: self.helper_button.setIcon(get_std_icon('DialogApplyButton')) self.label_warning.setText(tip) def set_sequence(self, sequence): """Set the new shortcut and update buttons.""" if not sequence or self.sequence == sequence: self.button_ok.setEnabled(False) different_sequence = False else: self.button_ok.setEnabled(True) different_sequence = True if sys.platform == 'darwin': if 'Meta+Ctrl' in sequence: shown_sequence = sequence.replace('Meta+Ctrl', 'Ctrl+Cmd') elif 'Ctrl+Meta' in sequence: shown_sequence = sequence.replace('Ctrl+Meta', 'Cmd+Ctrl') elif 'Ctrl' in sequence: shown_sequence = sequence.replace('Ctrl', 'Cmd') elif 'Meta' in sequence: shown_sequence = sequence.replace('Meta', 'Ctrl') else: shown_sequence = sequence else: shown_sequence = sequence self.text_new_sequence.setText(shown_sequence) self.new_sequence = sequence conflicts = self.check_conflicts() blacklist = self.new_sequence in BLACKLIST individual_keys = self.new_sequence.split('+') if conflicts and different_sequence: warning_type = SEQUENCE_CONFLICT elif blacklist: warning_type = IN_BLACKLIST elif len(individual_keys) == 2 and individual_keys[0] == 'Shift': warning_type = SHIFT_BLACKLIST else: warning_type = NO_WARNING self.update_warning(warning_type=warning_type, conflicts=conflicts) def validate_sequence(self): """Provide additional checks for accepting or rejecting shortcuts.""" if self.invalid_key_flag: self.update_warning(warning_type=INVALID_KEY) return for mod in MODIFIERS: non_mod = set(self.key_non_modifiers) non_mod.discard(mod) if mod in self.key_non_modifiers: self.key_non_modifiers.remove(mod) self.key_modifiers = self.key_modifiers - non_mod while u'' in self.key_text: self.key_text.remove(u'') self.key_text = [k.upper() for k in self.key_text] # Fix Backtab, Tab issue if Qt.Key_Backtab in self.key_non_modifiers: idx = self.key_non_modifiers.index(Qt.Key_Backtab) self.key_non_modifiers[idx] = Qt.Key_Tab if len(self.key_modifiers) == 0: # Filter single key allowed if self.key_non_modifiers[0] not in VALID_SINGLE_KEYS: return # Filter elif len(self.key_non_modifiers) > 1: return # QKeySequence accepts a maximum of 4 different sequences if len(self.keys) > 4: # Update warning self.update_warning(warning_type=SEQUENCE_LENGTH) return keys = [] for i in range(len(self.keys)): key_seq = 0 for m in self.key_modifiers: key_seq += MODIFIERS[m] key_seq += self.key_non_modifiers[i] keys.append(key_seq) sequence = QKeySequence(*keys) self.set_sequence(sequence.toString()) class Shortcut(object): """Shortcut convenience class for holding shortcut context, name, original ordering index, key sequence for the shortcut and localized text. """ def __init__(self, context, name, key=None): self.index = 0 # Sorted index. Populated when loading shortcuts self.context = context self.name = name self.key = key def __str__(self): return "{0}/{1}: {2}".format(self.context, self.name, self.key) def load(self): self.key = get_shortcut(self.context, self.name) def save(self): set_shortcut(self.context, self.name, self.key) CONTEXT, NAME, SEQUENCE, SEARCH_SCORE = [0, 1, 2, 3] class ShortcutsModel(QAbstractTableModel): def __init__(self, parent): QAbstractTableModel.__init__(self) self._parent = parent self.shortcuts = [] self.scores = [] self.rich_text = [] self.normal_text = [] self.letters = '' self.label = QLabel() self.widths = [] # Needed to compensate for the HTMLDelegate color selection unawarness palette = parent.palette() self.text_color = palette.text().color().name() self.text_color_highlight = palette.highlightedText().color().name() def current_index(self): """Get the currently selected index in the parent table view.""" i = self._parent.proxy_model.mapToSource(self._parent.currentIndex()) return i def sortByName(self): """Qt Override.""" self.shortcuts = sorted(self.shortcuts, key=lambda x: x.context+'/'+x.name) self.reset() def flags(self, index): """Qt Override.""" if not index.isValid(): return Qt.ItemIsEnabled return Qt.ItemFlags(QAbstractTableModel.flags(self, index)) def data(self, index, role=Qt.DisplayRole): """Qt Override.""" row = index.row() if not index.isValid() or not (0 <= row < len(self.shortcuts)): return to_qvariant() shortcut = self.shortcuts[row] key = shortcut.key column = index.column() if role == Qt.DisplayRole: if column == CONTEXT: return to_qvariant(shortcut.context) elif column == NAME: color = self.text_color if self._parent == QApplication.focusWidget(): if self.current_index().row() == row: color = self.text_color_highlight else: color = self.text_color text = self.rich_text[row] text = '

    {1}

    '.format(color, text) return to_qvariant(text) elif column == SEQUENCE: text = QKeySequence(key).toString(QKeySequence.NativeText) return to_qvariant(text) elif column == SEARCH_SCORE: # Treating search scores as a table column simplifies the # sorting once a score for a specific string in the finder # has been defined. This column however should always remain # hidden. return to_qvariant(self.scores[row]) elif role == Qt.TextAlignmentRole: return to_qvariant(int(Qt.AlignHCenter | Qt.AlignVCenter)) return to_qvariant() def headerData(self, section, orientation, role=Qt.DisplayRole): """Qt Override.""" if role == Qt.TextAlignmentRole: if orientation == Qt.Horizontal: return to_qvariant(int(Qt.AlignHCenter | Qt.AlignVCenter)) return to_qvariant(int(Qt.AlignRight | Qt.AlignVCenter)) if role != Qt.DisplayRole: return to_qvariant() if orientation == Qt.Horizontal: if section == CONTEXT: return to_qvariant(_("Context")) elif section == NAME: return to_qvariant(_("Name")) elif section == SEQUENCE: return to_qvariant(_("Shortcut")) elif section == SEARCH_SCORE: return to_qvariant(_("Score")) return to_qvariant() def rowCount(self, index=QModelIndex()): """Qt Override.""" return len(self.shortcuts) def columnCount(self, index=QModelIndex()): """Qt Override.""" return 4 def setData(self, index, value, role=Qt.EditRole): """Qt Override.""" if index.isValid() and 0 <= index.row() < len(self.shortcuts): shortcut = self.shortcuts[index.row()] column = index.column() text = from_qvariant(value, str) if column == SEQUENCE: shortcut.key = text self.dataChanged.emit(index, index) return True return False def update_search_letters(self, text): """Update search letters with text input in search box.""" self.letters = text names = [shortcut.name for shortcut in self.shortcuts] results = get_search_scores(text, names, template='{0}') self.normal_text, self.rich_text, self.scores = zip(*results) self.reset() def update_active_row(self): """Update active row to update color in selected text.""" self.data(self.current_index()) def row(self, row_num): """Get row based on model index. Needed for the custom proxy model.""" return self.shortcuts[row_num] def reset(self): """"Reset model to take into account new search letters.""" self.beginResetModel() self.endResetModel() class CustomSortFilterProxy(QSortFilterProxyModel): """Custom column filter based on regex.""" def __init__(self, parent=None): super(CustomSortFilterProxy, self).__init__(parent) self._parent = parent self.pattern = re.compile(u'') def set_filter(self, text): """Set regular expression for filter.""" self.pattern = get_search_regex(text) if self.pattern: self._parent.setSortingEnabled(False) else: self._parent.setSortingEnabled(True) self.invalidateFilter() def filterAcceptsRow(self, row_num, parent): """Qt override. Reimplemented from base class to allow the use of custom filtering. """ model = self.sourceModel() name = model.row(row_num).name r = re.search(self.pattern, name) if r is None: return False else: return True class ShortcutsTable(QTableView): def __init__(self, parent=None): QTableView.__init__(self, parent) self._parent = parent self.finder = None self.source_model = ShortcutsModel(self) self.proxy_model = CustomSortFilterProxy(self) self.last_regex = '' self.proxy_model.setSourceModel(self.source_model) self.proxy_model.setDynamicSortFilter(True) self.proxy_model.setFilterKeyColumn(NAME) self.proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive) self.setModel(self.proxy_model) self.hideColumn(SEARCH_SCORE) self.setItemDelegateForColumn(NAME, HTMLDelegate(self, margin=9)) self.setSelectionBehavior(QAbstractItemView.SelectRows) self.setSelectionMode(QAbstractItemView.SingleSelection) self.setSortingEnabled(True) self.setEditTriggers(QAbstractItemView.AllEditTriggers) self.selectionModel().selectionChanged.connect(self.selection) self.verticalHeader().hide() self.load_shortcuts() def focusOutEvent(self, e): """Qt Override.""" self.source_model.update_active_row() super(ShortcutsTable, self).focusOutEvent(e) def focusInEvent(self, e): """Qt Override.""" super(ShortcutsTable, self).focusInEvent(e) self.selectRow(self.currentIndex().row()) def selection(self, index): """Update selected row.""" self.update() self.isActiveWindow() def adjust_cells(self): """Adjust column size based on contents.""" self.resizeRowsToContents() self.resizeColumnsToContents() fm = self.horizontalHeader().fontMetrics() names = [fm.width(s.name + ' '*9) for s in self.source_model.shortcuts] self.setColumnWidth(NAME, max(names)) self.horizontalHeader().setStretchLastSection(True) def load_shortcuts(self): """Load shortcuts and assign to table model.""" shortcuts = [] for context, name, keystr in iter_shortcuts(): shortcut = Shortcut(context, name, keystr) shortcuts.append(shortcut) shortcuts = sorted(shortcuts, key=lambda x: x.context+x.name) # Store the original order of shortcuts for i, shortcut in enumerate(shortcuts): shortcut.index = i self.source_model.shortcuts = shortcuts self.source_model.scores = [0]*len(shortcuts) self.source_model.rich_text = [s.name for s in shortcuts] self.source_model.reset() self.adjust_cells() self.sortByColumn(CONTEXT, Qt.AscendingOrder) def check_shortcuts(self): """Check shortcuts for conflicts.""" conflicts = [] for index, sh1 in enumerate(self.source_model.shortcuts): if index == len(self.source_model.shortcuts)-1: break for sh2 in self.source_model.shortcuts[index+1:]: if sh2 is sh1: continue if str(sh2.key) == str(sh1.key) \ and (sh1.context == sh2.context or sh1.context == '_' or sh2.context == '_'): conflicts.append((sh1, sh2)) if conflicts: self.parent().show_this_page.emit() cstr = "\n".join(['%s <---> %s' % (sh1, sh2) for sh1, sh2 in conflicts]) QMessageBox.warning(self, _("Conflicts"), _("The following conflicts have been " "detected:")+"\n"+cstr, QMessageBox.Ok) def save_shortcuts(self): """Save shortcuts from table model.""" self.check_shortcuts() for shortcut in self.source_model.shortcuts: shortcut.save() def show_editor(self): """Create, setup and display the shortcut editor dialog.""" index = self.proxy_model.mapToSource(self.currentIndex()) row, column = index.row(), index.column() shortcuts = self.source_model.shortcuts context = shortcuts[row].context name = shortcuts[row].name sequence_index = self.source_model.index(row, SEQUENCE) sequence = sequence_index.data() dialog = ShortcutEditor(self, context, name, sequence, shortcuts) if dialog.exec_(): new_sequence = dialog.new_sequence self.source_model.setData(sequence_index, new_sequence) def set_regex(self, regex=None, reset=False): """Update the regex text for the shortcut finder.""" if reset: text = '' else: text = self.finder.text().replace(' ', '').lower() self.proxy_model.set_filter(text) self.source_model.update_search_letters(text) self.sortByColumn(SEARCH_SCORE, Qt.AscendingOrder) if self.last_regex != regex: self.selectRow(0) self.last_regex = regex def next_row(self): """Move to next row from currently selected row.""" row = self.currentIndex().row() rows = self.proxy_model.rowCount() if row + 1 == rows: row = -1 self.selectRow(row + 1) def previous_row(self): """Move to previous row from currently selected row.""" row = self.currentIndex().row() rows = self.proxy_model.rowCount() if row == 0: row = rows self.selectRow(row - 1) def keyPressEvent(self, event): """Qt Override.""" key = event.key() if key in [Qt.Key_Enter, Qt.Key_Return]: self.show_editor() elif key in [Qt.Key_Tab]: self.finder.setFocus() elif key in [Qt.Key_Backtab]: self.parent().reset_btn.setFocus() elif key in [Qt.Key_Up, Qt.Key_Down, Qt.Key_Left, Qt.Key_Right]: super(ShortcutsTable, self).keyPressEvent(event) elif key not in [Qt.Key_Escape, Qt.Key_Space]: text = event.text() if text: if re.search(VALID_FINDER_CHARS, text) is not None: self.finder.setFocus() self.finder.set_text(text) elif key in [Qt.Key_Escape]: self.finder.keyPressEvent(event) def mouseDoubleClickEvent(self, event): """Qt Override.""" self.show_editor() class ShortcutsConfigPage(GeneralConfigPage): CONF_SECTION = "shortcuts" NAME = _("Keyboard shortcuts") ICON = ima.icon('keyboard') def setup_page(self): # Widgets self.table = ShortcutsTable(self) self.finder = ShortcutFinder(self.table, self.table.set_regex) self.table.finder = self.finder self.label_finder = QLabel(_('Search: ')) self.reset_btn = QPushButton(_("Reset to default values")) # Layout hlayout = QHBoxLayout() vlayout = QVBoxLayout() hlayout.addWidget(self.label_finder) hlayout.addWidget(self.finder) vlayout.addWidget(self.table) vlayout.addLayout(hlayout) vlayout.addWidget(self.reset_btn) self.setLayout(vlayout) self.setTabOrder(self.table, self.finder) self.setTabOrder(self.finder, self.reset_btn) # Signals and slots if PYQT5: # Qt5 'dataChanged' has 3 parameters self.table.proxy_model.dataChanged.connect( lambda i1, i2, roles, opt='': self.has_been_modified(opt)) else: self.table.proxy_model.dataChanged.connect( lambda i1, i2, opt='': self.has_been_modified(opt)) self.reset_btn.clicked.connect(self.reset_to_default) def check_settings(self): self.table.check_shortcuts() def reset_to_default(self): """Reset to default values of the shortcuts making a confirmation.""" reset = QMessageBox.warning(self, _("Shortcuts reset"), _("Do you want to reset " "to default values?"), QMessageBox.Yes | QMessageBox.No) if reset == QMessageBox.No: return reset_shortcuts() self.main.apply_shortcuts() self.table.load_shortcuts() self.load_from_conf() self.set_modified(False) def apply_settings(self, options): self.table.save_shortcuts() self.main.apply_shortcuts() def test(): from spyder.utils.qthelpers import qapplication app = qapplication() table = ShortcutsTable() table.show() app.exec_() print([str(s) for s in table.source_model.shortcuts]) # spyder: test-skip table.check_shortcuts() if __name__ == '__main__': test() spyder-3.2.6/spyder/plugins/ipythonconsole.py0000664000175000017500000022553513224740762022263 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ IPython Console plugin based on QtConsole """ # pylint: disable=C0103 # pylint: disable=R0903 # pylint: disable=R0911 # pylint: disable=R0201 # Standard library imports import atexit import codecs import os import os.path as osp import uuid import sys # Third party imports from jupyter_client.connect import find_connection_file from jupyter_core.paths import jupyter_config_dir, jupyter_runtime_dir from qtconsole.client import QtKernelClient from qtconsole.manager import QtKernelManager from qtpy import PYQT5 from qtpy.compat import getopenfilename from qtpy.QtCore import Qt, Signal, Slot from qtpy.QtWidgets import (QApplication, QCheckBox, QDialog, QDialogButtonBox, QFormLayout, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLineEdit, QMessageBox, QPushButton, QTabWidget, QVBoxLayout, QWidget) from traitlets.config.loader import Config, load_pyconfig_files from zmq.ssh import tunnel as zmqtunnel try: import pexpect except ImportError: pexpect = None # Local imports from spyder import dependencies from spyder.config.base import (_, DEV, get_conf_path, get_home_dir, get_module_path) from spyder.config.main import CONF from spyder.plugins import SpyderPluginWidget from spyder.plugins.configdialog import PluginConfigPage from spyder.py3compat import is_string, PY2, to_text_string from spyder.utils.ipython.kernelspec import SpyderKernelSpec from spyder.utils.ipython.style import create_qss_style from spyder.utils.qthelpers import create_action, MENU_SEPARATOR from spyder.utils import icon_manager as ima from spyder.utils import programs, sourcecode from spyder.utils.programs import TEMPDIR from spyder.utils.misc import get_error_match, remove_backslashes from spyder.widgets.findreplace import FindReplace from spyder.widgets.ipythonconsole import ClientWidget from spyder.widgets.tabs import Tabs # Dependencies SYMPY_REQVER = '>=0.7.3' dependencies.add("sympy", _("Symbolic mathematics in the IPython Console"), required_version=SYMPY_REQVER, optional=True) CYTHON_REQVER = '>=0.21' dependencies.add("cython", _("Run Cython files in the IPython Console"), required_version=CYTHON_REQVER, optional=True) QTCONSOLE_REQVER = ">=4.2.0" dependencies.add("qtconsole", _("Integrate the IPython console"), required_version=QTCONSOLE_REQVER) IPYTHON_REQVER = ">=4.0;<6.0" if PY2 else ">=4.0" dependencies.add("IPython", _("IPython interactive python environment"), required_version=IPYTHON_REQVER) #------------------------------------------------------------------------------ # Existing kernels #------------------------------------------------------------------------------ # Replacing pyzmq openssh_tunnel method to work around the issue # https://github.com/zeromq/pyzmq/issues/589 which was solved in pyzmq # https://github.com/zeromq/pyzmq/pull/615 def _stop_tunnel(cmd): pexpect.run(cmd) def openssh_tunnel(self, lport, rport, server, remoteip='127.0.0.1', keyfile=None, password=None, timeout=0.4): if pexpect is None: raise ImportError("pexpect unavailable, use paramiko_tunnel") ssh="ssh " if keyfile: ssh += "-i " + keyfile if ':' in server: server, port = server.split(':') ssh += " -p %s" % port cmd = "%s -O check %s" % (ssh, server) (output, exitstatus) = pexpect.run(cmd, withexitstatus=True) if not exitstatus: pid = int(output[output.find("(pid=")+5:output.find(")")]) cmd = "%s -O forward -L 127.0.0.1:%i:%s:%i %s" % ( ssh, lport, remoteip, rport, server) (output, exitstatus) = pexpect.run(cmd, withexitstatus=True) if not exitstatus: atexit.register(_stop_tunnel, cmd.replace("-O forward", "-O cancel", 1)) return pid cmd = "%s -f -S none -L 127.0.0.1:%i:%s:%i %s sleep %i" % ( ssh, lport, remoteip, rport, server, timeout) # pop SSH_ASKPASS from env env = os.environ.copy() env.pop('SSH_ASKPASS', None) ssh_newkey = 'Are you sure you want to continue connecting' tunnel = pexpect.spawn(cmd, env=env) failed = False while True: try: i = tunnel.expect([ssh_newkey, '[Pp]assword:'], timeout=.1) if i==0: host = server.split('@')[-1] question = _("The authenticity of host %s can't be " "established. Are you sure you want to continue " "connecting?") % host reply = QMessageBox.question(self, _('Warning'), question, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: tunnel.sendline('yes') continue else: tunnel.sendline('no') raise RuntimeError( _("The authenticity of the host can't be established")) if i==1 and password is not None: tunnel.sendline(password) except pexpect.TIMEOUT: continue except pexpect.EOF: if tunnel.exitstatus: raise RuntimeError(_("Tunnel '%s' failed to start") % cmd) else: return tunnel.pid else: if failed or password is None: raise RuntimeError(_("Could not connect to remote host")) # TODO: Use this block when pyzmq bug #620 is fixed # # Prompt a passphrase dialog to the user for a second attempt # password, ok = QInputDialog.getText(self, _('Password'), # _('Enter password for: ') + server, # echo=QLineEdit.Password) # if ok is False: # raise RuntimeError('Could not connect to remote host.') tunnel.sendline(password) failed = True class KernelConnectionDialog(QDialog): """Dialog to connect to existing kernels (either local or remote)""" def __init__(self, parent=None): super(KernelConnectionDialog, self).__init__(parent) self.setWindowTitle(_('Connect to an existing kernel')) main_label = QLabel(_("Please enter the connection info of the kernel " "you want to connect to. For that you can " "either select its JSON connection file using " "the Browse button, or write directly " "its id, in case it's a local kernel (for " "example kernel-3764.json or just " "3764).")) main_label.setWordWrap(True) main_label.setAlignment(Qt.AlignJustify) # connection file cf_label = QLabel(_('Connection info:')) self.cf = QLineEdit() self.cf.setPlaceholderText(_('Path to connection file or kernel id')) self.cf.setMinimumWidth(250) cf_open_btn = QPushButton(_('Browse')) cf_open_btn.clicked.connect(self.select_connection_file) cf_layout = QHBoxLayout() cf_layout.addWidget(cf_label) cf_layout.addWidget(self.cf) cf_layout.addWidget(cf_open_btn) # remote kernel checkbox self.rm_cb = QCheckBox(_('This is a remote kernel')) # ssh connection self.hn = QLineEdit() self.hn.setPlaceholderText(_('username@hostname:port')) self.kf = QLineEdit() self.kf.setPlaceholderText(_('Path to ssh key file')) kf_open_btn = QPushButton(_('Browse')) kf_open_btn.clicked.connect(self.select_ssh_key) kf_layout = QHBoxLayout() kf_layout.addWidget(self.kf) kf_layout.addWidget(kf_open_btn) self.pw = QLineEdit() self.pw.setPlaceholderText(_('Password or ssh key passphrase')) self.pw.setEchoMode(QLineEdit.Password) ssh_form = QFormLayout() ssh_form.addRow(_('Host name'), self.hn) ssh_form.addRow(_('Ssh key'), kf_layout) ssh_form.addRow(_('Password'), self.pw) # Ok and Cancel buttons self.accept_btns = QDialogButtonBox( QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self) self.accept_btns.accepted.connect(self.accept) self.accept_btns.rejected.connect(self.reject) # Dialog layout layout = QVBoxLayout(self) layout.addWidget(main_label) layout.addLayout(cf_layout) layout.addWidget(self.rm_cb) layout.addLayout(ssh_form) layout.addWidget(self.accept_btns) # remote kernel checkbox enables the ssh_connection_form def ssh_set_enabled(state): for wid in [self.hn, self.kf, kf_open_btn, self.pw]: wid.setEnabled(state) for i in range(ssh_form.rowCount()): ssh_form.itemAt(2 * i).widget().setEnabled(state) ssh_set_enabled(self.rm_cb.checkState()) self.rm_cb.stateChanged.connect(ssh_set_enabled) def select_connection_file(self): cf = getopenfilename(self, _('Open connection file'), jupyter_runtime_dir(), '*.json;;*.*')[0] self.cf.setText(cf) def select_ssh_key(self): kf = getopenfilename(self, _('Select ssh key'), get_home_dir(), '*.pem;;*.*')[0] self.kf.setText(kf) @staticmethod def get_connection_parameters(parent=None, dialog=None): if not dialog: dialog = KernelConnectionDialog(parent) result = dialog.exec_() is_remote = bool(dialog.rm_cb.checkState()) accepted = result == QDialog.Accepted if is_remote: falsy_to_none = lambda arg: arg if arg else None return (dialog.cf.text(), # connection file falsy_to_none(dialog.hn.text()), # host name falsy_to_none(dialog.kf.text()), # ssh key file falsy_to_none(dialog.pw.text()), # ssh password accepted) # ok else: path = dialog.cf.text() _dir, filename = osp.dirname(path), osp.basename(path) if _dir == '' and not filename.endswith('.json'): path = osp.join(jupyter_runtime_dir(), 'kernel-'+path+'.json') return (path, None, None, None, accepted) #------------------------------------------------------------------------------ # Config page #------------------------------------------------------------------------------ class IPythonConsoleConfigPage(PluginConfigPage): def __init__(self, plugin, parent): PluginConfigPage.__init__(self, plugin, parent) self.get_name = lambda: _("IPython console") def setup_page(self): newcb = self.create_checkbox # Interface Group interface_group = QGroupBox(_("Interface")) banner_box = newcb(_("Display initial banner"), 'show_banner', tip=_("This option lets you hide the message shown at\n" "the top of the console when it's opened.")) pager_box = newcb(_("Use a pager to display additional text inside " "the console"), 'use_pager', tip=_("Useful if you don't want to fill the " "console with long help or completion texts.\n" "Note: Use the Q key to get out of the " "pager.")) calltips_box = newcb(_("Display balloon tips"), 'show_calltips') ask_box = newcb(_("Ask for confirmation before closing"), 'ask_before_closing') reset_namespace_box = newcb( _("Ask for confirmation before removing all user-defined " "variables"), 'show_reset_namespace_warning', tip=_("This option lets you hide the warning message shown\n" "when resetting the namespace from Spyder.")) show_time_box = newcb(_("Show elapsed time"), 'show_elapsed_time') interface_layout = QVBoxLayout() interface_layout.addWidget(banner_box) interface_layout.addWidget(pager_box) interface_layout.addWidget(calltips_box) interface_layout.addWidget(ask_box) interface_layout.addWidget(reset_namespace_box) interface_layout.addWidget(show_time_box) interface_group.setLayout(interface_layout) comp_group = QGroupBox(_("Completion Type")) comp_label = QLabel(_("Decide what type of completion to use")) comp_label.setWordWrap(True) completers = [(_("Graphical"), 0), (_("Terminal"), 1), (_("Plain"), 2)] comp_box = self.create_combobox(_("Completion:")+" ", completers, 'completion_type') comp_layout = QVBoxLayout() comp_layout.addWidget(comp_label) comp_layout.addWidget(comp_box) comp_group.setLayout(comp_layout) # Source Code Group source_code_group = QGroupBox(_("Source code")) buffer_spin = self.create_spinbox( _("Buffer: "), _(" lines"), 'buffer_size', min_=-1, max_=1000000, step=100, tip=_("Set the maximum number of lines of text shown in the\n" "console before truncation. Specifying -1 disables it\n" "(not recommended!)")) source_code_layout = QVBoxLayout() source_code_layout.addWidget(buffer_spin) source_code_group.setLayout(source_code_layout) # --- Graphics --- # Pylab Group pylab_group = QGroupBox(_("Support for graphics (Matplotlib)")) pylab_box = newcb(_("Activate support"), 'pylab') autoload_pylab_box = newcb(_("Automatically load Pylab and NumPy " "modules"), 'pylab/autoload', tip=_("This lets you load graphics support " "without importing \nthe commands to do " "plots. Useful to work with other\n" "plotting libraries different to " "Matplotlib or to develop \nGUIs with " "Spyder.")) autoload_pylab_box.setEnabled(self.get_option('pylab')) pylab_box.toggled.connect(autoload_pylab_box.setEnabled) pylab_layout = QVBoxLayout() pylab_layout.addWidget(pylab_box) pylab_layout.addWidget(autoload_pylab_box) pylab_group.setLayout(pylab_layout) # Pylab backend Group inline = _("Inline") automatic = _("Automatic") backend_group = QGroupBox(_("Graphics backend")) bend_label = QLabel(_("Decide how graphics are going to be displayed " "in the console. If unsure, please select " "%s to put graphics inside the " "console or %s to interact with " "them (through zooming and panning) in a " "separate window.") % (inline, automatic)) bend_label.setWordWrap(True) backends = [(inline, 0), (automatic, 1), ("Qt5", 2), ("Qt4", 3)] if sys.platform == 'darwin': backends.append( ("OS X", 4) ) if sys.platform.startswith('linux'): backends.append( ("Gtk3", 5) ) backends.append( ("Gtk", 6) ) if PY2: backends.append( ("Wx", 7) ) backends.append( ("Tkinter", 8) ) backends = tuple(backends) backend_box = self.create_combobox( _("Backend:")+" ", backends, 'pylab/backend', default=0, tip=_("This option will be applied the " "next time a console is opened.")) backend_layout = QVBoxLayout() backend_layout.addWidget(bend_label) backend_layout.addWidget(backend_box) backend_group.setLayout(backend_layout) backend_group.setEnabled(self.get_option('pylab')) pylab_box.toggled.connect(backend_group.setEnabled) # Inline backend Group inline_group = QGroupBox(_("Inline backend")) inline_label = QLabel(_("Decide how to render the figures created by " "this backend")) inline_label.setWordWrap(True) formats = (("PNG", 0), ("SVG", 1)) format_box = self.create_combobox(_("Format:")+" ", formats, 'pylab/inline/figure_format', default=0) resolution_spin = self.create_spinbox( _("Resolution:")+" ", " "+_("dpi"), 'pylab/inline/resolution', min_=50, max_=999, step=0.1, tip=_("Only used when the format is PNG. Default is " "72")) width_spin = self.create_spinbox( _("Width:")+" ", " "+_("inches"), 'pylab/inline/width', min_=2, max_=20, step=1, tip=_("Default is 6")) height_spin = self.create_spinbox( _("Height:")+" ", " "+_("inches"), 'pylab/inline/height', min_=1, max_=20, step=1, tip=_("Default is 4")) inline_v_layout = QVBoxLayout() inline_v_layout.addWidget(inline_label) inline_layout = QGridLayout() inline_layout.addWidget(format_box.label, 1, 0) inline_layout.addWidget(format_box.combobox, 1, 1) inline_layout.addWidget(resolution_spin.plabel, 2, 0) inline_layout.addWidget(resolution_spin.spinbox, 2, 1) inline_layout.addWidget(resolution_spin.slabel, 2, 2) inline_layout.addWidget(width_spin.plabel, 3, 0) inline_layout.addWidget(width_spin.spinbox, 3, 1) inline_layout.addWidget(width_spin.slabel, 3, 2) inline_layout.addWidget(height_spin.plabel, 4, 0) inline_layout.addWidget(height_spin.spinbox, 4, 1) inline_layout.addWidget(height_spin.slabel, 4, 2) inline_h_layout = QHBoxLayout() inline_h_layout.addLayout(inline_layout) inline_h_layout.addStretch(1) inline_v_layout.addLayout(inline_h_layout) inline_group.setLayout(inline_v_layout) inline_group.setEnabled(self.get_option('pylab')) pylab_box.toggled.connect(inline_group.setEnabled) # --- Startup --- # Run lines Group run_lines_group = QGroupBox(_("Run code")) run_lines_label = QLabel(_("You can run several lines of code when " "a console is started. Please introduce " "each one separated by commas, for " "example:
    " "import os, import sys")) run_lines_label.setWordWrap(True) run_lines_edit = self.create_lineedit(_("Lines:"), 'startup/run_lines', '', alignment=Qt.Horizontal) run_lines_layout = QVBoxLayout() run_lines_layout.addWidget(run_lines_label) run_lines_layout.addWidget(run_lines_edit) run_lines_group.setLayout(run_lines_layout) # Run file Group run_file_group = QGroupBox(_("Run a file")) run_file_label = QLabel(_("You can also run a whole file at startup " "instead of just some lines (This is " "similar to have a PYTHONSTARTUP file).")) run_file_label.setWordWrap(True) file_radio = newcb(_("Use the following file:"), 'startup/use_run_file', False) run_file_browser = self.create_browsefile('', 'startup/run_file', '') run_file_browser.setEnabled(False) file_radio.toggled.connect(run_file_browser.setEnabled) run_file_layout = QVBoxLayout() run_file_layout.addWidget(run_file_label) run_file_layout.addWidget(file_radio) run_file_layout.addWidget(run_file_browser) run_file_group.setLayout(run_file_layout) # ---- Advanced settings ---- # Greedy completer group greedy_group = QGroupBox(_("Greedy completion")) greedy_label = QLabel(_("Enable Tab completion on elements " "of lists, results of function calls, etc, " "without assigning them to a " "variable.
    " "For example, you can get completions on " "things like li[0].<Tab> or " "ins.meth().<Tab>")) greedy_label.setWordWrap(True) greedy_box = newcb(_("Use the greedy completer"), "greedy_completer", tip="Warning: It can be unsafe because the " "code is actually evaluated when you press " "Tab.") greedy_layout = QVBoxLayout() greedy_layout.addWidget(greedy_label) greedy_layout.addWidget(greedy_box) greedy_group.setLayout(greedy_layout) # Autocall group autocall_group = QGroupBox(_("Autocall")) autocall_label = QLabel(_("Autocall makes IPython automatically call " "any callable object even if you didn't type " "explicit parentheses.
    " "For example, if you type str 43 it " "becomes str(43) automatically.")) autocall_label.setWordWrap(True) smart = _('Smart') full = _('Full') autocall_opts = ((_('Off'), 0), (smart, 1), (full, 2)) autocall_box = self.create_combobox( _("Autocall: "), autocall_opts, 'autocall', default=0, tip=_("On %s mode, Autocall is not applied if " "there are no arguments after the callable. On " "%s mode, all callable objects are " "automatically called (even if no arguments are " "present).") % (smart, full)) autocall_layout = QVBoxLayout() autocall_layout.addWidget(autocall_label) autocall_layout.addWidget(autocall_box) autocall_group.setLayout(autocall_layout) # Sympy group sympy_group = QGroupBox(_("Symbolic Mathematics")) sympy_label = QLabel(_("Perfom symbolic operations in the console " "(e.g. integrals, derivatives, vector calculus, " "etc) and get the outputs in a beautifully " "printed style (it requires the Sympy module).")) sympy_label.setWordWrap(True) sympy_box = newcb(_("Use symbolic math"), "symbolic_math", tip=_("This option loads the Sympy library to work " "with.
    Please refer to its documentation to " "learn how to use it.")) sympy_layout = QVBoxLayout() sympy_layout.addWidget(sympy_label) sympy_layout.addWidget(sympy_box) sympy_group.setLayout(sympy_layout) # Prompts group prompts_group = QGroupBox(_("Prompts")) prompts_label = QLabel(_("Modify how Input and Output prompts are " "shown in the console.")) prompts_label.setWordWrap(True) in_prompt_edit = self.create_lineedit(_("Input prompt:"), 'in_prompt', '', _('Default is
    ' 'In [<span class="in-prompt-number">' '%i</span>]:'), alignment=Qt.Horizontal) out_prompt_edit = self.create_lineedit(_("Output prompt:"), 'out_prompt', '', _('Default is
    ' 'Out[<span class="out-prompt-number">' '%i</span>]:'), alignment=Qt.Horizontal) prompts_layout = QVBoxLayout() prompts_layout.addWidget(prompts_label) prompts_g_layout = QGridLayout() prompts_g_layout.addWidget(in_prompt_edit.label, 0, 0) prompts_g_layout.addWidget(in_prompt_edit.textbox, 0, 1) prompts_g_layout.addWidget(out_prompt_edit.label, 1, 0) prompts_g_layout.addWidget(out_prompt_edit.textbox, 1, 1) prompts_layout.addLayout(prompts_g_layout) prompts_group.setLayout(prompts_layout) # --- Tabs organization --- tabs = QTabWidget() tabs.addTab(self.create_tab(interface_group, comp_group, source_code_group), _("Display")) tabs.addTab(self.create_tab(pylab_group, backend_group, inline_group), _("Graphics")) tabs.addTab(self.create_tab(run_lines_group, run_file_group), _("Startup")) tabs.addTab(self.create_tab(greedy_group, autocall_group, sympy_group, prompts_group), _("Advanced Settings")) vlayout = QVBoxLayout() vlayout.addWidget(tabs) self.setLayout(vlayout) #------------------------------------------------------------------------------ # Plugin widget #------------------------------------------------------------------------------ class IPythonConsole(SpyderPluginWidget): """ IPython Console plugin This is a widget with tabs where each one is a ClientWidget """ CONF_SECTION = 'ipython_console' CONFIGWIDGET_CLASS = IPythonConsoleConfigPage DISABLE_ACTIONS_WHEN_HIDDEN = False # Signals focus_changed = Signal() edit_goto = Signal((str, int, str), (str, int, str, bool)) # Error messages permission_error_msg = _("The directory {} is not writable and it is " "required to create IPython consoles. Please " "make it writable.") def __init__(self, parent, testing=False, test_dir=TEMPDIR, test_no_stderr=False): """Ipython Console constructor.""" if PYQT5: SpyderPluginWidget.__init__(self, parent, main = parent) else: SpyderPluginWidget.__init__(self, parent) self.tabwidget = None self.menu_actions = None self.help = None # Help plugin self.historylog = None # History log plugin self.variableexplorer = None # Variable explorer plugin self.editor = None # Editor plugin self.projects = None # Projects plugin self.master_clients = 0 self.clients = [] self.filenames = [] self.mainwindow_close = False self.create_new_client_if_empty = True # Attrs for testing self.testing = testing self.test_dir = test_dir self.test_no_stderr = test_no_stderr # Initialize plugin if not self.testing: self.initialize_plugin() # Create temp dir on testing to save kernel errors if self.testing: if not osp.isdir(osp.join(test_dir)): os.makedirs(osp.join(test_dir)) layout = QVBoxLayout() self.tabwidget = Tabs(self, self.menu_actions, rename_tabs=True, split_char='/', split_index=0) if hasattr(self.tabwidget, 'setDocumentMode')\ and not sys.platform == 'darwin': # Don't set document mode to true on OSX because it generates # a crash when the console is detached from the main window # Fixes Issue 561 self.tabwidget.setDocumentMode(True) self.tabwidget.currentChanged.connect(self.refresh_plugin) self.tabwidget.tabBar().tabMoved.connect(self.move_tab) self.tabwidget.tabBar().sig_change_name.connect( self.rename_tabs_after_change) self.tabwidget.set_close_function(self.close_client) if sys.platform == 'darwin': tab_container = QWidget() tab_container.setObjectName('tab-container') tab_layout = QHBoxLayout(tab_container) tab_layout.setContentsMargins(0, 0, 0, 0) tab_layout.addWidget(self.tabwidget) layout.addWidget(tab_container) else: layout.addWidget(self.tabwidget) # Find/replace widget self.find_widget = FindReplace(self) self.find_widget.hide() if not self.testing: self.register_widget_shortcuts(self.find_widget) layout.addWidget(self.find_widget) self.setLayout(layout) # Accepting drops self.setAcceptDrops(True) #------ SpyderPluginMixin API --------------------------------------------- def update_font(self): """Update font from Preferences""" font = self.get_plugin_font() for client in self.clients: client.set_font(font) def apply_plugin_settings(self, options): """Apply configuration file's plugin settings""" font_n = 'plugin_font' font_o = self.get_plugin_font() help_n = 'connect_to_oi' help_o = CONF.get('help', 'connect/ipython_console') color_scheme_n = 'color_scheme_name' color_scheme_o = CONF.get('color_schemes', 'selected') show_time_n = 'show_elapsed_time' show_time_o = self.get_option(show_time_n) reset_namespace_n = 'show_reset_namespace_warning' reset_namespace_o = self.get_option(reset_namespace_n) for client in self.clients: control = client.get_control() if font_n in options: client.set_font(font_o) if help_n in options and control is not None: control.set_help_enabled(help_o) if color_scheme_n in options: client.set_color_scheme(color_scheme_o) if show_time_n in options: client.show_time_action.setChecked(show_time_o) client.set_elapsed_time_visible(show_time_o) if reset_namespace_n in options: client.reset_warning = reset_namespace_o def toggle_view(self, checked): """Toggle view""" if checked: self.dockwidget.show() self.dockwidget.raise_() # Start a client in case there are none shown if not self.clients: if self.main.is_setting_up: self.create_new_client(give_focus=False) else: self.create_new_client(give_focus=True) else: self.dockwidget.hide() #------ SpyderPluginWidget API -------------------------------------------- def get_plugin_title(self): """Return widget title""" return _('IPython console') def get_plugin_icon(self): """Return widget icon""" return ima.icon('ipython_console') def get_focus_widget(self): """ Return the widget to give focus to when this plugin's dockwidget is raised on top-level """ client = self.tabwidget.currentWidget() if client is not None: return client.get_control() def closing_plugin(self, cancelable=False): """Perform actions before parent main window is closed""" self.mainwindow_close = True for client in self.clients: client.shutdown() client.close() return True def refresh_plugin(self): """Refresh tabwidget""" client = None if self.tabwidget.count(): # Give focus to the control widget of the selected tab client = self.tabwidget.currentWidget() control = client.get_control() control.setFocus() buttons = [[b, -7] for b in client.get_toolbar_buttons()] buttons = sum(buttons, [])[:-1] widgets = [client.create_time_label()] + buttons else: control = None widgets = [] self.find_widget.set_editor(control) self.tabwidget.set_corner_widgets({Qt.TopRightCorner: widgets}) if client and not self.testing: sw = client.shellwidget self.variableexplorer.set_shellwidget_from_id(id(sw)) self.help.set_shell(sw) self.update_tabs_text() self.update_plugin_title.emit() def get_plugin_actions(self): """Return a list of actions related to plugin.""" create_client_action = create_action( self, _("Open an &IPython console"), icon=ima.icon('ipython_console'), triggered=self.create_new_client, context=Qt.WidgetWithChildrenShortcut) self.register_shortcut(create_client_action, context="ipython_console", name="New tab") restart_action = create_action(self, _("Restart kernel"), icon=ima.icon('restart'), triggered=self.restart_kernel, context=Qt.WidgetWithChildrenShortcut) self.register_shortcut(restart_action, context="ipython_console", name="Restart kernel") connect_to_kernel_action = create_action(self, _("Connect to an existing kernel"), None, None, _("Open a new IPython console connected to an existing kernel"), triggered=self.create_client_for_kernel) rename_tab_action = create_action(self, _("Rename tab"), icon=ima.icon('rename'), triggered=self.tab_name_editor) # Add the action to the 'Consoles' menu on the main window main_consoles_menu = self.main.consoles_menu_actions main_consoles_menu.insert(0, create_client_action) main_consoles_menu += [MENU_SEPARATOR, restart_action, connect_to_kernel_action] # Plugin actions self.menu_actions = [create_client_action, MENU_SEPARATOR, restart_action, connect_to_kernel_action, MENU_SEPARATOR, rename_tab_action] return self.menu_actions def register_plugin(self): """Register plugin in Spyder's main window""" self.main.add_dockwidget(self) self.help = self.main.help self.historylog = self.main.historylog self.variableexplorer = self.main.variableexplorer self.editor = self.main.editor self.explorer = self.main.explorer self.projects = self.main.projects self.focus_changed.connect(self.main.plugin_focus_changed) self.edit_goto.connect(self.editor.load) self.edit_goto[str, int, str, bool].connect( lambda fname, lineno, word, processevents: self.editor.load(fname, lineno, word, processevents=processevents)) self.editor.breakpoints_saved.connect(self.set_spyder_breakpoints) self.editor.run_in_current_ipyclient.connect(self.run_script) self.main.workingdirectory.set_current_console_wd.connect( self.set_current_client_working_directory) self.tabwidget.currentChanged.connect(self.update_working_directory) self.explorer.open_interpreter.connect(self.create_client_from_path) self.explorer.run.connect(lambda fname: self.run_script( fname, osp.dirname(fname), '', False, False, False, True)) self.projects.open_interpreter.connect(self.create_client_from_path) self.projects.run.connect(lambda fname: self.run_script( fname, osp.dirname(fname), '', False, False, False, True)) #------ Public API (for clients) ------------------------------------------ def get_clients(self): """Return clients list""" return [cl for cl in self.clients if isinstance(cl, ClientWidget)] def get_focus_client(self): """Return current client with focus, if any""" widget = QApplication.focusWidget() for client in self.get_clients(): if widget is client or widget is client.get_control(): return client def get_current_client(self): """Return the currently selected client""" client = self.tabwidget.currentWidget() if client is not None: return client def get_current_shellwidget(self): """Return the shellwidget of the current client""" client = self.get_current_client() if client is not None: return client.shellwidget def run_script(self, filename, wdir, args, debug, post_mortem, current_client, clear_variables): """Run script in current or dedicated client""" norm = lambda text: remove_backslashes(to_text_string(text)) # Select client to execute code on it is_new_client = False if current_client: client = self.get_current_client() else: client = self.get_client_for_file(filename) if client is None: self.create_client_for_file(filename) client = self.get_current_client() is_new_client = True if client is not None: # Internal kernels, use runfile if client.get_kernel() 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) if post_mortem: line += ", post_mortem=True" line += ")" else: # External kernels, use %run line = "%run " if debug: line += "-d " line += "\"%s\"" % to_text_string(filename) if args: line += " %s" % norm(args) try: if current_client: self.execute_code(line, current_client, clear_variables) else: if is_new_client: client.shellwidget.silent_execute('%clear') else: client.shellwidget.execute('%clear') client.shellwidget.sig_prompt_ready.connect( lambda: self.execute_code(line, current_client, clear_variables)) except AttributeError: pass 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 %s." "

    Please open a new one and try again." ) % osp.basename(filename), QMessageBox.Ok) def set_current_client_working_directory(self, directory): """Set current client working directory.""" shellwidget = self.get_current_shellwidget() if shellwidget is not None: shellwidget.set_cwd(directory) def set_working_directory(self, dirname): """Set current working directory. In the workingdirectory and explorer plugins. """ if dirname and not self.testing: self.main.workingdirectory.chdir(dirname, refresh_explorer=True, refresh_console=False) def update_working_directory(self): """Update working directory to console cwd.""" shellwidget = self.get_current_shellwidget() if shellwidget is not None: shellwidget.get_cwd() def execute_code(self, lines, current_client=True, clear_variables=False): """Execute code instructions.""" sw = self.get_current_shellwidget() if sw is not None: if sw._reading: pass else: if not current_client: # Clear console and reset namespace for # dedicated clients # See issue 5748 try: sw.sig_prompt_ready.disconnect() except TypeError: pass sw.reset_namespace(warning=False, silent=True) elif current_client and clear_variables: sw.reset_namespace(warning=False, silent=True) sw.execute(to_text_string(lines)) self.activateWindow() self.get_current_client().get_control().setFocus() def write_to_stdin(self, line): sw = self.get_current_shellwidget() if sw is not None: sw.write_to_stdin(line) @Slot() @Slot(bool) @Slot(str) @Slot(bool, str) def create_new_client(self, give_focus=True, filename=''): """Create a new client""" self.master_clients += 1 client_id = dict(int_id=to_text_string(self.master_clients), str_id='A') cf = self._new_connection_file() show_elapsed_time = self.get_option('show_elapsed_time') reset_warning = self.get_option('show_reset_namespace_warning') client = ClientWidget(self, id_=client_id, history_filename=get_conf_path('history.py'), config_options=self.config_options(), additional_options=self.additional_options(), interpreter_versions=self.interpreter_versions(), connection_file=cf, menu_actions=self.menu_actions, show_elapsed_time=show_elapsed_time, reset_warning=reset_warning) if self.testing: client.stderr_dir = self.test_dir self.add_tab(client, name=client.get_name(), filename=filename) if cf is None: error_msg = self.permission_error_msg.format(jupyter_runtime_dir()) client.show_kernel_error(error_msg) return # Check if ipykernel is present in the external interpreter. # Else we won't be able to create a client if not CONF.get('main_interpreter', 'default'): pyexec = CONF.get('main_interpreter', 'executable') has_ipykernel = programs.is_module_installed('ipykernel', interpreter=pyexec) has_cloudpickle = programs.is_module_installed('cloudpickle', interpreter=pyexec) if not (has_ipykernel and has_cloudpickle): client.show_kernel_error(_("Your Python environment or " "installation doesn't " "have the ipykernel and " "cloudpickle modules " "installed on it. Without these modules " "is not possible for Spyder to create a " "console for you.

    " "You can install them by running " "in a system terminal:

    " "pip install ipykernel cloudpickle" "

    " "or

    " "conda install ipykernel cloudpickle")) return self.connect_client_to_kernel(client) if client.shellwidget.kernel_manager is None: return self.register_client(client) @Slot() def create_client_for_kernel(self): """Create a client connected to an existing kernel""" connect_output = KernelConnectionDialog.get_connection_parameters(self) (connection_file, hostname, sshkey, password, ok) = connect_output if not ok: return else: self._create_client_for_kernel(connection_file, hostname, sshkey, password) def connect_client_to_kernel(self, client): """Connect a client to its kernel""" connection_file = client.connection_file if self.test_no_stderr: stderr_file = None else: stderr_file = client.stderr_file km, kc = self.create_kernel_manager_and_kernel_client(connection_file, stderr_file) # An error occurred if this is True if is_string(km) and kc is None: client.shellwidget.kernel_manager = None client.show_kernel_error(km) return kc.started_channels.connect(lambda c=client: self.process_started(c)) kc.stopped_channels.connect(lambda c=client: self.process_finished(c)) kc.start_channels(shell=True, iopub=True) shellwidget = client.shellwidget shellwidget.kernel_manager = km shellwidget.kernel_client = kc def set_editor(self): """Set the editor used by the %edit magic""" python = sys.executable if DEV: spyder_start_directory = get_module_path('spyder') bootstrap_script = osp.join(osp.dirname(spyder_start_directory), 'bootstrap.py') editor = u'{0} {1} --'.format(python, bootstrap_script) else: import1 = "import sys" import2 = "from spyder.app.start import send_args_to_spyder" code = "send_args_to_spyder([sys.argv[-1]])" editor = u"{0} -c '{1}; {2}; {3}'".format(python, import1, import2, code) return to_text_string(editor) def config_options(self): """ Generate a Trailets Config instance for shell widgets using our config system This lets us create each widget with its own config """ # ---- Jupyter config ---- try: full_cfg = load_pyconfig_files(['jupyter_qtconsole_config.py'], jupyter_config_dir()) # From the full config we only select the JupyterWidget section # because the others have no effect here. cfg = Config({'JupyterWidget': full_cfg.JupyterWidget}) except: cfg = Config() # ---- Spyder config ---- spy_cfg = Config() # Make the pager widget a rich one (i.e a QTextEdit) spy_cfg.JupyterWidget.kind = 'rich' # Gui completion widget completion_type_o = self.get_option('completion_type') completions = {0: "droplist", 1: "ncurses", 2: "plain"} spy_cfg.JupyterWidget.gui_completion = completions[completion_type_o] # Pager pager_o = self.get_option('use_pager') if pager_o: spy_cfg.JupyterWidget.paging = 'inside' else: spy_cfg.JupyterWidget.paging = 'none' # Calltips calltips_o = self.get_option('show_calltips') spy_cfg.JupyterWidget.enable_calltips = calltips_o # Buffer size buffer_size_o = self.get_option('buffer_size') spy_cfg.JupyterWidget.buffer_size = buffer_size_o # Prompts in_prompt_o = self.get_option('in_prompt') out_prompt_o = self.get_option('out_prompt') if in_prompt_o: spy_cfg.JupyterWidget.in_prompt = in_prompt_o if out_prompt_o: spy_cfg.JupyterWidget.out_prompt = out_prompt_o # Style color_scheme = CONF.get('color_schemes', 'selected') style_sheet = create_qss_style(color_scheme)[0] spy_cfg.JupyterWidget.style_sheet = style_sheet spy_cfg.JupyterWidget.syntax_style = color_scheme # Editor for %edit if CONF.get('main', 'single_instance'): spy_cfg.JupyterWidget.editor = self.set_editor() # Merge QtConsole and Spyder configs. Spyder prefs will have # prevalence over QtConsole ones cfg._merge(spy_cfg) return cfg def interpreter_versions(self): """Python and IPython versions used by clients""" if CONF.get('main_interpreter', 'default'): from IPython.core import release versions = dict( python_version = sys.version.split("\n")[0].strip(), ipython_version = release.version ) else: import subprocess versions = {} pyexec = CONF.get('main_interpreter', 'executable') py_cmd = "%s -c 'import sys; print(sys.version.split(\"\\n\")[0])'" % \ pyexec ipy_cmd = "%s -c 'import IPython.core.release as r; print(r.version)'" \ % pyexec for cmd in [py_cmd, ipy_cmd]: try: proc = programs.run_shell_command(cmd) output, _err = proc.communicate() except subprocess.CalledProcessError: output = '' output = output.decode().split('\n')[0].strip() if 'IPython' in cmd: versions['ipython_version'] = output else: versions['python_version'] = output return versions def additional_options(self): """ Additional options for shell widgets that are not defined in JupyterWidget config options """ options = dict( pylab=self.get_option('pylab'), autoload_pylab=self.get_option('pylab/autoload'), sympy=self.get_option('symbolic_math'), show_banner=self.get_option('show_banner') ) return options def register_client(self, client, give_focus=True): """Register new client""" client.configure_shellwidget(give_focus=give_focus) # Local vars shellwidget = client.shellwidget control = shellwidget._control page_control = shellwidget._page_control # Create new clients with Ctrl+T shortcut shellwidget.new_client.connect(self.create_new_client) # For tracebacks control.go_to_error.connect(self.go_to_error) shellwidget.sig_pdb_step.connect( lambda fname, lineno, shellwidget=shellwidget: self.pdb_has_stopped(fname, lineno, shellwidget)) # Set shell cwd according to preferences cwd_path = '' if CONF.get('workingdir', 'console/use_project_or_home_directory'): cwd_path = get_home_dir() if (self.projects is not None and self.projects.get_active_project() is not None): cwd_path = self.projects.get_active_project_path() elif CONF.get('workingdir', 'console/use_fixed_directory'): cwd_path = CONF.get('workingdir', 'console/fixed_directory') if osp.isdir(cwd_path) and self.main is not None: shellwidget.set_cwd(cwd_path) if give_focus: # Syncronice cwd with explorer and cwd widget shellwidget.get_cwd() # Connect text widget to Help if self.help is not None: control.set_help(self.help) control.set_help_enabled(CONF.get('help', 'connect/ipython_console')) # Connect client to our history log if self.historylog is not None: self.historylog.add_history(client.history_filename) client.append_to_history.connect(self.historylog.append_to_history) # Set font for client client.set_font( self.get_plugin_font() ) # Connect focus signal to client's control widget control.focus_changed.connect(lambda: self.focus_changed.emit()) shellwidget.sig_change_cwd.connect(self.set_working_directory) # Update the find widget if focus changes between control and # page_control self.find_widget.set_editor(control) if page_control: page_control.focus_changed.connect(lambda: self.focus_changed.emit()) control.visibility_changed.connect(self.refresh_plugin) page_control.visibility_changed.connect(self.refresh_plugin) page_control.show_find_widget.connect(self.find_widget.show) def close_client(self, index=None, client=None, force=False): """Close client tab from index or widget (or close current tab)""" if not self.tabwidget.count(): return if client is not None: index = self.tabwidget.indexOf(client) if index is None and client is None: index = self.tabwidget.currentIndex() if index is not None: client = self.tabwidget.widget(index) # Needed to handle a RuntimeError. See issue 5568. try: # Close client client.stop_button_click_handler() except RuntimeError: pass # Disconnect timer needed to update elapsed time try: client.timer.timeout.disconnect(client.show_time) except (RuntimeError, TypeError): pass # Check if related clients or kernels are opened # and eventually ask before closing them if not self.mainwindow_close and not force: close_all = True if self.get_option('ask_before_closing'): close = QMessageBox.question(self, self.get_plugin_title(), _("Do you want to close this console?"), QMessageBox.Yes | QMessageBox.No) if close == QMessageBox.No: return if len(self.get_related_clients(client)) > 0: close_all = QMessageBox.question(self, self.get_plugin_title(), _("Do you want to close all other consoles connected " "to the same kernel as this one?"), QMessageBox.Yes | QMessageBox.No) client.shutdown() if close_all == QMessageBox.Yes: self.close_related_clients(client) client.close() # Note: client index may have changed after closing related widgets self.tabwidget.removeTab(self.tabwidget.indexOf(client)) self.clients.remove(client) # This is needed to prevent that hanged consoles make reference # to an index that doesn't exist. See issue 4881 try: self.filenames.pop(index) except IndexError: pass self.update_tabs_text() # Create a new client if the console is about to become empty if not self.tabwidget.count() and self.create_new_client_if_empty: self.create_new_client() self.update_plugin_title.emit() def get_client_index_from_id(self, client_id): """Return client index from id""" for index, client in enumerate(self.clients): if id(client) == client_id: return index def get_related_clients(self, client): """ Get all other clients that are connected to the same kernel as `client` """ related_clients = [] for cl in self.get_clients(): if cl.connection_file == client.connection_file and \ cl is not client: related_clients.append(cl) return related_clients def close_related_clients(self, client): """Close all clients related to *client*, except itself""" related_clients = self.get_related_clients(client) for cl in related_clients: self.close_client(client=cl, force=True) def restart(self): """ Restart the console This is needed when we switch projects to update PYTHONPATH and the selected interpreter """ self.master_clients = 0 self.create_new_client_if_empty = False for i in range(len(self.clients)): client = self.clients[-1] try: client.shutdown() except Exception as e: QMessageBox.warning(self, _('Warning'), _("It was not possible to restart the IPython console " "when switching to this project. " "The error was {0}").format(e), QMessageBox.Ok) self.close_client(client=client, force=True) self.create_new_client(give_focus=False) self.create_new_client_if_empty = True def pdb_has_stopped(self, fname, lineno, shellwidget): """Python debugger has just stopped at frame (fname, lineno)""" # This is a unique form of the edit_goto signal that is intended to # prevent keyboard input from accidentally entering the editor # during repeated, rapid entry of debugging commands. self.edit_goto[str, int, str, bool].emit(fname, lineno, '', False) self.activateWindow() shellwidget._control.setFocus() def set_spyder_breakpoints(self): """Set Spyder breakpoints into all clients""" for cl in self.clients: cl.shellwidget.set_spyder_breakpoints() @Slot(str) def create_client_from_path(self, path): """Create a client with its cwd pointing to path.""" self.create_new_client() sw = self.get_current_shellwidget() sw.set_cwd(path) def create_client_for_file(self, filename): """Create a client to execute code related to a file.""" # Create client self.create_new_client(filename=filename) # Don't increase the count of master clients self.master_clients -= 1 # Rename client tab with filename client = self.get_current_client() client.allow_rename = False tab_text = self.disambiguate_fname(filename) self.rename_client_tab(client, tab_text) def get_client_for_file(self, filename): """Get client associated with a given file.""" client = None for idx, cl in enumerate(self.get_clients()): if self.filenames[idx] == filename: self.tabwidget.setCurrentIndex(idx) client = cl break return client def set_elapsed_time(self, client): """Set elapsed time for slave clients.""" related_clients = self.get_related_clients(client) for cl in related_clients: if cl.timer is not None: client.create_time_label() client.t0 = cl.t0 client.timer.timeout.connect(client.show_time) client.timer.start(1000) break #------ Public API (for kernels) ------------------------------------------ def ssh_tunnel(self, *args, **kwargs): if os.name == 'nt': return zmqtunnel.paramiko_tunnel(*args, **kwargs) else: return openssh_tunnel(self, *args, **kwargs) def tunnel_to_kernel(self, connection_info, hostname, sshkey=None, password=None, timeout=10): """ Tunnel connections to a kernel via ssh. Remote ports are specified in the connection info ci. """ lports = zmqtunnel.select_random_ports(4) rports = (connection_info['shell_port'], connection_info['iopub_port'], connection_info['stdin_port'], connection_info['hb_port']) remote_ip = connection_info['ip'] for lp, rp in zip(lports, rports): self.ssh_tunnel(lp, rp, hostname, remote_ip, sshkey, password, timeout) return tuple(lports) def create_kernel_spec(self): """Create a kernel spec for our own kernels""" # Before creating our kernel spec, we always need to # set this value in spyder.ini if not self.testing: CONF.set('main', 'spyder_pythonpath', self.main.get_spyder_pythonpath()) return SpyderKernelSpec() def create_kernel_manager_and_kernel_client(self, connection_file, stderr_file): """Create kernel manager and client.""" # Kernel spec kernel_spec = self.create_kernel_spec() if not kernel_spec.env.get('PYTHONPATH'): error_msg = _("This error was most probably caused by installing " "Spyder in a directory with non-ascii characters " "(i.e. characters with tildes, apostrophes or " "non-latin symbols).

    " "To fix it, please reinstall Spyder in a " "different location.") return (error_msg, None) # Kernel manager kernel_manager = QtKernelManager(connection_file=connection_file, config=None, autorestart=True) kernel_manager._kernel_spec = kernel_spec # Save stderr in a file to read it later in case of errors if stderr_file is not None: stderr = codecs.open(stderr_file, 'w', encoding='utf-8') else: stderr = None kernel_manager.start_kernel(stderr=stderr) # Kernel client kernel_client = kernel_manager.client() # Increase time to detect if a kernel is alive # See Issue 3444 kernel_client.hb_channel.time_to_dead = 18.0 return kernel_manager, kernel_client def restart_kernel(self): """Restart kernel of current client.""" client = self.get_current_client() if client is not None: client.restart_kernel() #------ Public API (for tabs) --------------------------------------------- def add_tab(self, widget, name, filename=''): """Add tab""" self.clients.append(widget) index = self.tabwidget.addTab(widget, name) self.filenames.insert(index, filename) self.tabwidget.setCurrentIndex(index) if self.dockwidget and not self.ismaximized: self.dockwidget.setVisible(True) self.dockwidget.raise_() self.activateWindow() widget.get_control().setFocus() self.update_tabs_text() def move_tab(self, index_from, index_to): """ Move tab (tabs themselves have already been moved by the tabwidget) """ filename = self.filenames.pop(index_from) client = self.clients.pop(index_from) self.filenames.insert(index_to, filename) self.clients.insert(index_to, client) self.update_tabs_text() self.update_plugin_title.emit() def disambiguate_fname(self, fname): """Generate a file name without ambiguation.""" files_path_list = [filename for filename in self.filenames if filename] return sourcecode.disambiguate_fname(files_path_list, fname) def update_tabs_text(self): """Update the text from the tabs.""" # This is needed to prevent that hanged consoles make reference # to an index that doesn't exist. See issue 4881 try: for index, fname in enumerate(self.filenames): client = self.clients[index] if fname: self.rename_client_tab(client, self.disambiguate_fname(fname)) else: self.rename_client_tab(client, None) except IndexError: pass def rename_client_tab(self, client, given_name): """Rename client's tab""" index = self.get_client_index_from_id(id(client)) if given_name is not None: client.given_name = given_name self.tabwidget.setTabText(index, client.get_name()) def rename_tabs_after_change(self, given_name): """Rename tabs after a change in name.""" client = self.get_current_client() # Prevent renames that want to assign the same name of # a previous tab repeated = False for cl in self.get_clients(): if id(client) != id(cl) and given_name == cl.given_name: repeated = True break # Rename current client tab to add str_id if client.allow_rename and not u'/' in given_name and not repeated: self.rename_client_tab(client, given_name) else: self.rename_client_tab(client, None) # Rename related clients if client.allow_rename and not u'/' in given_name and not repeated: for cl in self.get_related_clients(client): self.rename_client_tab(cl, given_name) def tab_name_editor(self): """Trigger the tab name editor.""" index = self.tabwidget.currentIndex() self.tabwidget.tabBar().tab_name_editor.edit_tab(index) #------ Public API (for help) --------------------------------------------- def go_to_error(self, text): """Go to error if relevant""" match = get_error_match(to_text_string(text)) if match: fname, lnb = match.groups() self.edit_goto.emit(osp.abspath(fname), int(lnb), '') @Slot() def show_intro(self): """Show intro to IPython help""" from IPython.core.usage import interactive_usage self.help.show_rich_text(interactive_usage) @Slot() def show_guiref(self): """Show qtconsole help""" from qtconsole.usage import gui_reference self.help.show_rich_text(gui_reference, collapse=True) @Slot() def show_quickref(self): """Show IPython Cheat Sheet""" from IPython.core.usage import quick_reference self.help.show_plain_text(quick_reference) #------ Private API ------------------------------------------------------- def _new_connection_file(self): """ Generate a new connection file Taken from jupyter_client/console_app.py Licensed under the BSD license """ # Check if jupyter_runtime_dir exists (Spyder addition) if not osp.isdir(jupyter_runtime_dir()): try: os.makedirs(jupyter_runtime_dir()) except (IOError, OSError): return None cf = '' while not cf: ident = str(uuid.uuid4()).split('-')[-1] cf = os.path.join(jupyter_runtime_dir(), 'kernel-%s.json' % ident) cf = cf if not os.path.exists(cf) else '' return cf def process_started(self, client): if self.help is not None: self.help.set_shell(client.shellwidget) if self.variableexplorer is not None: self.variableexplorer.add_shellwidget(client.shellwidget) def process_finished(self, client): if self.variableexplorer is not None: self.variableexplorer.remove_shellwidget(id(client.shellwidget)) def connect_external_kernel(self, shellwidget): """ Connect an external kernel to the Variable Explorer and Help, if it is a Spyder kernel. """ sw = shellwidget kc = shellwidget.kernel_client if self.help is not None: self.help.set_shell(sw) if self.variableexplorer is not None: self.variableexplorer.add_shellwidget(sw) sw.set_namespace_view_settings() sw.refresh_namespacebrowser() kc.stopped_channels.connect(lambda : self.variableexplorer.remove_shellwidget(id(sw))) def _create_client_for_kernel(self, connection_file, hostname, sshkey, password): # Verifying if the connection file exists try: cf_path = osp.dirname(connection_file) cf_filename = osp.basename(connection_file) # To change a possible empty string to None cf_path = cf_path if cf_path else None connection_file = find_connection_file(filename=cf_filename, path=cf_path) except (IOError, UnboundLocalError): QMessageBox.critical(self, _('IPython'), _("Unable to connect to " "%s") % connection_file) return # Getting the master id that corresponds to the client # (i.e. the i in i/A) master_id = None given_name = None external_kernel = False slave_ord = ord('A') - 1 kernel_manager = None for cl in self.get_clients(): if connection_file in cl.connection_file: if cl.get_kernel() is not None: kernel_manager = cl.get_kernel() connection_file = cl.connection_file if master_id is None: master_id = cl.id_['int_id'] given_name = cl.given_name new_slave_ord = ord(cl.id_['str_id']) if new_slave_ord > slave_ord: slave_ord = new_slave_ord # If we couldn't find a client with the same connection file, # it means this is a new master client if master_id is None: self.master_clients += 1 master_id = to_text_string(self.master_clients) external_kernel = True # Set full client name client_id = dict(int_id=master_id, str_id=chr(slave_ord + 1)) # Creating the client show_elapsed_time = self.get_option('show_elapsed_time') reset_warning = self.get_option('show_reset_namespace_warning') client = ClientWidget(self, id_=client_id, given_name=given_name, history_filename=get_conf_path('history.py'), config_options=self.config_options(), additional_options=self.additional_options(), interpreter_versions=self.interpreter_versions(), connection_file=connection_file, menu_actions=self.menu_actions, hostname=hostname, external_kernel=external_kernel, slave=True, show_elapsed_time=show_elapsed_time, reset_warning=reset_warning) # Create kernel client kernel_client = QtKernelClient(connection_file=connection_file) kernel_client.load_connection_file() if hostname is not None: try: connection_info = dict(ip = kernel_client.ip, shell_port = kernel_client.shell_port, iopub_port = kernel_client.iopub_port, stdin_port = kernel_client.stdin_port, hb_port = kernel_client.hb_port) newports = self.tunnel_to_kernel(connection_info, hostname, sshkey, password) (kernel_client.shell_port, kernel_client.iopub_port, kernel_client.stdin_port, kernel_client.hb_port) = newports except Exception as e: QMessageBox.critical(self, _('Connection error'), _("Could not open ssh tunnel. The " "error was:\n\n") + to_text_string(e)) return # Assign kernel manager and client to shellwidget client.shellwidget.kernel_client = kernel_client client.shellwidget.kernel_manager = kernel_manager kernel_client.start_channels() if external_kernel: client.shellwidget.sig_is_spykernel.connect( self.connect_external_kernel) client.shellwidget.is_spyder_kernel() # Set elapsed time, if possible if not external_kernel: self.set_elapsed_time(client) # Adding a new tab for the client self.add_tab(client, name=client.get_name()) # Register client self.register_client(client) spyder-3.2.6/spyder/plugins/console.py0000664000175000017500000003734613224740762020651 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Internal Console Plugin""" # pylint: disable=C0103 # pylint: disable=R0903 # pylint: disable=R0911 # pylint: disable=R0201 # Standard library imports import os import os.path as osp import sys # Third party imports from qtpy import PYQT5 from qtpy.compat import getopenfilename from qtpy.QtCore import Signal, Slot, Qt from qtpy.QtWidgets import (QInputDialog, QLineEdit, QMenu, QVBoxLayout, QMessageBox) # Local imports from spyder.config.base import _, debug_print from spyder.config.main import CONF from spyder.utils import icon_manager as ima from spyder.utils.environ import EnvDialog from spyder.utils.misc import (get_error_match, remove_backslashes, getcwd_or_home) from spyder.utils.qthelpers import (add_actions, create_action, DialogManager, mimedata2url) from spyder.widgets.internalshell import InternalShell from spyder.widgets.findreplace import FindReplace from spyder.widgets.variableexplorer.collectionseditor import CollectionsEditor from spyder.plugins import SpyderPluginWidget from spyder.py3compat import to_text_string class Console(SpyderPluginWidget): """ Console widget """ CONF_SECTION = 'internal_console' focus_changed = Signal() redirect_stdio = Signal(bool) edit_goto = Signal(str, int, str) def __init__(self, parent=None, namespace=None, commands=[], message=None, exitfunc=None, profile=False, multithreaded=False): if PYQT5: SpyderPluginWidget.__init__(self, parent, main = parent) else: SpyderPluginWidget.__init__(self, parent) debug_print(" ..internal console: initializing") self.dialog_manager = DialogManager() # Shell light_background = self.get_option('light_background') self.shell = InternalShell(parent, namespace, commands, message, self.get_option('max_line_count'), self.get_plugin_font(), exitfunc, profile, multithreaded, light_background=light_background) self.shell.status.connect(lambda msg: self.show_message.emit(msg, 0)) self.shell.go_to_error.connect(self.go_to_error) self.shell.focus_changed.connect(lambda: self.focus_changed.emit()) # Redirecting some signals: self.shell.redirect_stdio.connect(lambda state: self.redirect_stdio.emit(state)) # Initialize plugin self.initialize_plugin() # Find/replace widget self.find_widget = FindReplace(self) self.find_widget.set_editor(self.shell) self.find_widget.hide() self.register_widget_shortcuts(self.find_widget) # Main layout layout = QVBoxLayout() layout.addWidget(self.shell) layout.addWidget(self.find_widget) self.setLayout(layout) # Parameters self.shell.toggle_wrap_mode(self.get_option('wrap')) # Accepting drops self.setAcceptDrops(True) # Traceback MessageBox self.msgbox_traceback= None self.error_traceback = "" #------ Private API -------------------------------------------------------- def set_historylog(self, historylog): """Bind historylog instance to this console Not used anymore since v2.0""" historylog.add_history(self.shell.history_filename) self.shell.append_to_history.connect(historylog.append_to_history) def set_help(self, help_plugin): """Bind help instance to this console""" self.shell.help = help_plugin #------ SpyderPluginWidget API --------------------------------------------- def get_plugin_title(self): """Return widget title""" return _('Internal console') def get_focus_widget(self): """ Return the widget to give focus to when this plugin's dockwidget is raised on top-level """ return self.shell def update_font(self): """Update font from Preferences""" font = self.get_plugin_font() self.shell.set_font(font) def closing_plugin(self, cancelable=False): """Perform actions before parent main window is closed""" self.dialog_manager.close_all() self.shell.exit_interpreter() return True def refresh_plugin(self): pass def get_plugin_actions(self): """Return a list of actions related to plugin""" quit_action = create_action(self, _("&Quit"), icon=ima.icon('exit'), tip=_("Quit"), triggered=self.quit) self.register_shortcut(quit_action, "_", "Quit", "Ctrl+Q") run_action = create_action(self, _("&Run..."), None, ima.icon('run_small'), _("Run a Python script"), triggered=self.run_script) environ_action = create_action(self, _("Environment variables..."), icon=ima.icon('environ'), tip=_("Show and edit environment variables" " (for current session)"), triggered=self.show_env) syspath_action = create_action(self, _("Show sys.path contents..."), icon=ima.icon('syspath'), tip=_("Show (read-only) sys.path"), triggered=self.show_syspath) buffer_action = create_action(self, _("Buffer..."), None, tip=_("Set maximum line count"), triggered=self.change_max_line_count) exteditor_action = create_action(self, _("External editor path..."), None, None, _("Set external editor executable path"), triggered=self.change_exteditor) wrap_action = create_action(self, _("Wrap lines"), toggled=self.toggle_wrap_mode) wrap_action.setChecked(self.get_option('wrap')) calltips_action = create_action(self, _("Display balloon tips"), toggled=self.toggle_calltips) calltips_action.setChecked(self.get_option('calltips')) codecompletion_action = create_action(self, _("Automatic code completion"), toggled=self.toggle_codecompletion) codecompletion_action.setChecked(self.get_option('codecompletion/auto')) codecompenter_action = create_action(self, _("Enter key selects completion"), toggled=self.toggle_codecompletion_enter) codecompenter_action.setChecked(self.get_option( 'codecompletion/enter_key')) option_menu = QMenu(_('Internal console settings'), self) option_menu.setIcon(ima.icon('tooloptions')) add_actions(option_menu, (buffer_action, wrap_action, calltips_action, codecompletion_action, codecompenter_action, exteditor_action)) plugin_actions = [None, run_action, environ_action, syspath_action, option_menu, None, quit_action] # Add actions to context menu add_actions(self.shell.menu, plugin_actions) return plugin_actions def register_plugin(self): """Register plugin in Spyder's main window""" self.focus_changed.connect(self.main.plugin_focus_changed) self.main.add_dockwidget(self) # Connecting the following signal once the dockwidget has been created: self.shell.exception_occurred.connect(self.exception_occurred) def exception_occurred(self, text, is_traceback): """Exception ocurred in the internal console. Show a QMessageBox or the internal console to warn the user""" # Skip errors without traceback if not is_traceback and self.msgbox_traceback is None: return if CONF.get('main', 'show_internal_console_if_traceback', False): self.dockwidget.show() self.dockwidget.raise_() else: if self.msgbox_traceback is None: self.msgbox_traceback = QMessageBox( QMessageBox.Critical, _('Error'), _("Spyder has encountered a problem.
    " "Sorry for the inconvenience." "

    " "You can automatically submit this error to our Github " "issues tracker.

    " "Note: You need a Github account for that."), QMessageBox.Ok, parent=self) self.submit_btn = self.msgbox_traceback.addButton( _('Submit to Github'), QMessageBox.YesRole) self.submit_btn.pressed.connect(self.press_submit_btn) self.msgbox_traceback.setWindowModality(Qt.NonModal) self.error_traceback = "" self.msgbox_traceback.show() self.msgbox_traceback.finished.connect(self.close_msg) self.msgbox_traceback.setDetailedText(' ') # open show details (iterate over all buttons and click it) for button in self.msgbox_traceback.buttons(): if (self.msgbox_traceback.buttonRole(button) == QMessageBox.ActionRole): button.click() break self.error_traceback += text self.msgbox_traceback.setDetailedText(self.error_traceback) def close_msg(self): self.msgbox_traceback = None def press_submit_btn(self): self.main.report_issue(self.error_traceback) self.msgbox_traceback = None #------ Public API --------------------------------------------------------- @Slot() def quit(self): """Quit mainwindow""" self.main.close() @Slot() def show_env(self): """Show environment variables""" self.dialog_manager.show(EnvDialog()) @Slot() def show_syspath(self): """Show sys.path""" editor = CollectionsEditor() editor.setup(sys.path, title="sys.path", readonly=True, width=600, icon=ima.icon('syspath')) self.dialog_manager.show(editor) @Slot() def run_script(self, filename=None, silent=False, set_focus=False, args=None): """Run a Python script""" if filename is None: self.shell.interpreter.restore_stds() filename, _selfilter = getopenfilename( self, _("Run Python script"), getcwd_or_home(), _("Python scripts")+" (*.py ; *.pyw ; *.ipy)") self.shell.interpreter.redirect_stds() if filename: os.chdir( osp.dirname(filename) ) filename = osp.basename(filename) else: return debug_print(args) filename = osp.abspath(filename) rbs = remove_backslashes command = "runfile('%s', args='%s')" % (rbs(filename), rbs(args)) if set_focus: self.shell.setFocus() if self.dockwidget and not self.ismaximized: self.dockwidget.setVisible(True) self.dockwidget.raise_() self.shell.write(command+'\n') self.shell.run_command(command) def go_to_error(self, text): """Go to error if relevant""" match = get_error_match(to_text_string(text)) if match: fname, lnb = match.groups() self.edit_script(fname, int(lnb)) def edit_script(self, filename=None, goto=-1): """Edit script""" # Called from InternalShell if not hasattr(self, 'main') \ or not hasattr(self.main, 'editor'): self.shell.external_editor(filename, goto) return if filename is not None: self.edit_goto.emit(osp.abspath(filename), goto, '') def execute_lines(self, lines): """Execute lines and give focus to shell""" self.shell.execute_lines(to_text_string(lines)) self.shell.setFocus() @Slot() def change_max_line_count(self): "Change maximum line count""" mlc, valid = QInputDialog.getInt(self, _('Buffer'), _('Maximum line count'), self.get_option('max_line_count'), 0, 1000000) if valid: self.shell.setMaximumBlockCount(mlc) self.set_option('max_line_count', mlc) @Slot() def change_exteditor(self): """Change external editor path""" path, valid = QInputDialog.getText(self, _('External editor'), _('External editor executable path:'), QLineEdit.Normal, self.get_option('external_editor/path')) if valid: self.set_option('external_editor/path', to_text_string(path)) @Slot(bool) def toggle_wrap_mode(self, checked): """Toggle wrap mode""" self.shell.toggle_wrap_mode(checked) self.set_option('wrap', checked) @Slot(bool) def toggle_calltips(self, checked): """Toggle calltips""" self.shell.set_calltips(checked) self.set_option('calltips', checked) @Slot(bool) def toggle_codecompletion(self, checked): """Toggle automatic code completion""" self.shell.set_codecompletion_auto(checked) self.set_option('codecompletion/auto', checked) @Slot(bool) def toggle_codecompletion_enter(self, checked): """Toggle Enter key for code completion""" self.shell.set_codecompletion_enter(checked) self.set_option('codecompletion/enter_key', checked) #----Drag and drop def dragEnterEvent(self, event): """Reimplement Qt method Inform Qt about the types of data that the widget accepts""" source = event.mimeData() if source.hasUrls(): if mimedata2url(source): event.acceptProposedAction() else: event.ignore() elif source.hasText(): event.acceptProposedAction() def dropEvent(self, event): """Reimplement Qt method Unpack dropped data and handle it""" source = event.mimeData() if source.hasUrls(): pathlist = mimedata2url(source) self.shell.drop_pathlist(pathlist) elif source.hasText(): lines = to_text_string(source.text()) self.shell.set_cursor_position('eof') self.shell.execute_lines(lines) event.acceptProposedAction() spyder-3.2.6/spyder/plugins/help.py0000664000175000017500000011027213224740762020125 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Help Plugin""" # Standard library imports import re import os.path as osp import socket import sys # Third party imports from qtpy import PYQT5 from qtpy.QtCore import QThread, QUrl, Signal, Slot from qtpy.QtWidgets import (QActionGroup, QComboBox, QGroupBox, QHBoxLayout, QLabel, QLineEdit, QMenu, QMessageBox, QSizePolicy, QToolButton, QVBoxLayout, QWidget) from qtpy.QtWebEngineWidgets import QWebEnginePage, WEBENGINE # Local imports from spyder import dependencies from spyder.config.base import _, get_conf_path, get_module_source_path from spyder.config.fonts import DEFAULT_SMALL_DELTA from spyder.plugins import SpyderPluginWidget from spyder.plugins.configdialog import PluginConfigPage from spyder.py3compat import get_meth_class_inst, to_text_string from spyder.utils import icon_manager as ima from spyder.utils import programs from spyder.utils.help.sphinxify import (CSS_PATH, generate_context, sphinxify, usage, warning) from spyder.utils.qthelpers import (add_actions, create_action, create_toolbutton, create_plugin_layout) from spyder.widgets.browser import FrameWebView from spyder.widgets.comboboxes import EditableComboBox from spyder.widgets.findreplace import FindReplace from spyder.widgets.sourcecode import codeeditor # Sphinx dependency dependencies.add("sphinx", _("Show help for objects in the Editor and " "Consoles in a dedicated pane"), required_version='>=0.6.6') class ObjectComboBox(EditableComboBox): """ QComboBox handling object names """ # Signals valid = Signal(bool, bool) def __init__(self, parent): EditableComboBox.__init__(self, parent) self.help = parent self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.tips = {True: '', False: ''} 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 validate_current_text(self): self.validate(self.currentText()) def validate(self, qstr, editing=True): """Reimplemented to avoid formatting actions""" valid = self.is_valid(qstr) if self.hasFocus() and valid is not None: if editing: # Combo box text is being modified: invalidate the entry self.show_tip(self.tips[valid]) self.valid.emit(False, False) else: # A new item has just been selected if valid: self.selected() else: self.valid.emit(False, False) class HelpConfigPage(PluginConfigPage): def setup_page(self): # Connections group connections_group = QGroupBox(_("Automatic connections")) connections_label = QLabel(_("This pane can automatically " "show an object's help information after " "a left parenthesis is written next to it. " "Below you can decide to which plugin " "you want to connect it to turn on this " "feature.")) connections_label.setWordWrap(True) editor_box = self.create_checkbox(_("Editor"), 'connect/editor') rope_installed = programs.is_module_installed('rope') jedi_installed = programs.is_module_installed('jedi', '>=0.8.1') editor_box.setEnabled(rope_installed or jedi_installed) if not rope_installed and not jedi_installed: editor_tip = _("This feature requires the Rope or Jedi libraries.\n" "It seems you don't have either installed.") editor_box.setToolTip(editor_tip) ipython_box = self.create_checkbox(_("IPython Console"), 'connect/ipython_console') connections_layout = QVBoxLayout() connections_layout.addWidget(connections_label) connections_layout.addWidget(editor_box) connections_layout.addWidget(ipython_box) connections_group.setLayout(connections_layout) # Features group features_group = QGroupBox(_("Additional features")) math_box = self.create_checkbox(_("Render mathematical equations"), 'math') req_sphinx = programs.is_module_installed('sphinx', '>=1.1') math_box.setEnabled(req_sphinx) if not req_sphinx: sphinx_ver = programs.get_module_version('sphinx') sphinx_tip = _("This feature requires Sphinx 1.1 or superior.") sphinx_tip += "\n" + _("Sphinx %s is currently installed.") % sphinx_ver math_box.setToolTip(sphinx_tip) features_layout = QVBoxLayout() features_layout.addWidget(math_box) features_group.setLayout(features_layout) # Source code group sourcecode_group = QGroupBox(_("Source code")) wrap_mode_box = self.create_checkbox(_("Wrap lines"), 'wrap') sourcecode_layout = QVBoxLayout() sourcecode_layout.addWidget(wrap_mode_box) sourcecode_group.setLayout(sourcecode_layout) # Final layout vlayout = QVBoxLayout() vlayout.addWidget(connections_group) vlayout.addWidget(features_group) vlayout.addWidget(sourcecode_group) vlayout.addStretch(1) self.setLayout(vlayout) class RichText(QWidget): """ WebView widget with find dialog """ def __init__(self, parent): QWidget.__init__(self, parent) self.webview = FrameWebView(self) self.find_widget = FindReplace(self) self.find_widget.set_editor(self.webview.web_widget) self.find_widget.hide() layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.webview) layout.addWidget(self.find_widget) self.setLayout(layout) def set_font(self, font, fixed_font=None): """Set font""" self.webview.set_font(font, fixed_font=fixed_font) def set_html(self, html_text, base_url): """Set html text""" self.webview.setHtml(html_text, base_url) def clear(self): self.set_html('', self.webview.url()) class PlainText(QWidget): """ Read-only editor widget with find dialog """ # Signals focus_changed = Signal() def __init__(self, parent): QWidget.__init__(self, parent) self.editor = None # Read-only editor self.editor = codeeditor.CodeEditor(self) self.editor.setup_editor(linenumbers=False, language='py', scrollflagarea=False, edge_line=False) self.editor.focus_changed.connect(lambda: self.focus_changed.emit()) self.editor.setReadOnly(True) # Find/replace widget self.find_widget = FindReplace(self) self.find_widget.set_editor(self.editor) self.find_widget.hide() layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.editor) layout.addWidget(self.find_widget) self.setLayout(layout) def set_font(self, font, color_scheme=None): """Set font""" self.editor.set_font(font, color_scheme=color_scheme) def set_color_scheme(self, color_scheme): """Set color scheme""" self.editor.set_color_scheme(color_scheme) def set_text(self, text, is_code): self.editor.set_highlight_current_line(is_code) self.editor.set_occurrence_highlighting(is_code) if is_code: self.editor.set_language('py') else: self.editor.set_language(None) self.editor.set_text(text) self.editor.set_cursor_position('sof') def clear(self): self.editor.clear() class SphinxThread(QThread): """ A worker thread for handling rich text rendering. Parameters ---------- doc : str or dict A string containing a raw rst text or a dict containing the doc string components to be rendered. See spyder.utils.dochelpers.getdoc for description. context : dict A dict containing the substitution variables for the layout template html_text_no_doc : unicode Text to be rendered if doc string cannot be extracted. math_option : bool Use LaTeX math rendering. """ # Signals error_msg = Signal(str) html_ready = Signal(str) def __init__(self, html_text_no_doc=''): super(SphinxThread, self).__init__() self.doc = None self.context = None self.html_text_no_doc = html_text_no_doc self.math_option = False def render(self, doc, context=None, math_option=False, img_path=''): """Start thread to render a given documentation""" # If the thread is already running wait for it to finish before # starting it again. if self.wait(): self.doc = doc self.context = context self.math_option = math_option self.img_path = img_path # This causes run() to be executed in separate thread self.start() 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'] == '' and \ any([doc['name'], doc['argspec'], doc['note']]): msg = _("No further documentation available") html_text += '
    ' html_text += '
    %s
    ' % msg 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) class Help(SpyderPluginWidget): """ Docstrings viewer widget """ CONF_SECTION = 'help' CONFIGWIDGET_CLASS = HelpConfigPage LOG_PATH = get_conf_path(CONF_SECTION) FONT_SIZE_DELTA = DEFAULT_SMALL_DELTA # Signals focus_changed = Signal() def __init__(self, parent): if PYQT5: SpyderPluginWidget.__init__(self, parent, main = parent) else: SpyderPluginWidget.__init__(self, parent) self.internal_shell = None # Initialize plugin self.initialize_plugin() self.no_doc_string = _("No documentation available") self._last_console_cb = None self._last_editor_cb = None self.plain_text = PlainText(self) self.rich_text = RichText(self) color_scheme = self.get_color_scheme() self.set_plain_text_font(self.get_plugin_font(), color_scheme) self.plain_text.editor.toggle_wrap_mode(self.get_option('wrap')) # Add entries to read-only editor context-menu self.wrap_action = create_action(self, _("Wrap lines"), toggled=self.toggle_wrap_mode) self.wrap_action.setChecked(self.get_option('wrap')) self.plain_text.editor.readonly_menu.addSeparator() add_actions(self.plain_text.editor.readonly_menu, (self.wrap_action,)) self.set_rich_text_font(self.get_plugin_font('rich_text')) self.shell = None # locked = disable link with Console self.locked = False self._last_texts = [None, None] self._last_editor_doc = None # Object name layout_edit = QHBoxLayout() layout_edit.setContentsMargins(0, 0, 0, 0) txt = _("Source") if sys.platform == 'darwin': source_label = QLabel(" " + txt) else: source_label = QLabel(txt) layout_edit.addWidget(source_label) self.source_combo = QComboBox(self) self.source_combo.addItems([_("Console"), _("Editor")]) self.source_combo.currentIndexChanged.connect(self.source_changed) if (not programs.is_module_installed('rope') and not programs.is_module_installed('jedi', '>=0.8.1')): self.source_combo.hide() source_label.hide() layout_edit.addWidget(self.source_combo) layout_edit.addSpacing(10) layout_edit.addWidget(QLabel(_("Object"))) self.combo = ObjectComboBox(self) layout_edit.addWidget(self.combo) self.object_edit = QLineEdit(self) self.object_edit.setReadOnly(True) layout_edit.addWidget(self.object_edit) self.combo.setMaxCount(self.get_option('max_history_entries')) self.combo.addItems( self.load_history() ) self.combo.setItemText(0, '') self.combo.valid.connect(lambda valid: self.force_refresh()) # Plain text docstring option self.docstring = True self.rich_help = self.get_option('rich_mode', True) self.plain_text_action = create_action(self, _("Plain Text"), toggled=self.toggle_plain_text) # Source code option self.show_source_action = create_action(self, _("Show Source"), toggled=self.toggle_show_source) # Rich text option self.rich_text_action = create_action(self, _("Rich Text"), toggled=self.toggle_rich_text) # Add the help actions to an exclusive QActionGroup help_actions = QActionGroup(self) help_actions.setExclusive(True) help_actions.addAction(self.plain_text_action) help_actions.addAction(self.rich_text_action) # Automatic import option self.auto_import_action = create_action(self, _("Automatic import"), toggled=self.toggle_auto_import) auto_import_state = self.get_option('automatic_import') self.auto_import_action.setChecked(auto_import_state) # Lock checkbox self.locked_button = create_toolbutton(self, triggered=self.toggle_locked) layout_edit.addWidget(self.locked_button) self._update_lock_icon() # Option menu options_button = create_toolbutton(self, text=_('Options'), icon=ima.icon('tooloptions')) options_button.setPopupMode(QToolButton.InstantPopup) menu = QMenu(self) add_actions(menu, [self.rich_text_action, self.plain_text_action, self.show_source_action, None, self.auto_import_action]) options_button.setMenu(menu) layout_edit.addWidget(options_button) if self.rich_help: self.switch_to_rich_text() else: self.switch_to_plain_text() self.plain_text_action.setChecked(not self.rich_help) self.rich_text_action.setChecked(self.rich_help) self.source_changed() # Main layout layout = create_plugin_layout(layout_edit) # we have two main widgets, but only one of them is shown at a time layout.addWidget(self.plain_text) layout.addWidget(self.rich_text) self.setLayout(layout) # Add worker thread for handling rich text rendering self._sphinx_thread = SphinxThread( html_text_no_doc=warning(self.no_doc_string)) self._sphinx_thread.html_ready.connect( self._on_sphinx_thread_html_ready) self._sphinx_thread.error_msg.connect(self._on_sphinx_thread_error_msg) # Handle internal and external links view = self.rich_text.webview if not WEBENGINE: view.page().setLinkDelegationPolicy(QWebEnginePage.DelegateAllLinks) view.linkClicked.connect(self.handle_link_clicks) self._starting_up = True #------ SpyderPluginWidget API --------------------------------------------- def on_first_registration(self): """Action to be performed on first plugin registration""" self.main.tabify_plugins(self.main.variableexplorer, self) def get_plugin_title(self): """Return widget title""" return _('Help') def get_plugin_icon(self): """Return widget icon""" return ima.icon('help') 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 get_plugin_actions(self): """Return a list of actions related to plugin""" return [] def register_plugin(self): """Register plugin in Spyder's main window""" self.focus_changed.connect(self.main.plugin_focus_changed) self.main.add_dockwidget(self) self.main.console.set_help(self) self.internal_shell = self.main.console.shell def closing_plugin(self, cancelable=False): """Perform actions before parent main window is closed""" return True def refresh_plugin(self): """Refresh widget""" if self._starting_up: self._starting_up = False self.switch_to_rich_text() self.show_intro_message() def update_font(self): """Update font from Preferences""" color_scheme = self.get_color_scheme() font = self.get_plugin_font() rich_font = self.get_plugin_font(rich_text=True) self.set_plain_text_font(font, color_scheme=color_scheme) self.set_rich_text_font(rich_font) def apply_plugin_settings(self, options): """Apply configuration file's plugin settings""" color_scheme_n = 'color_scheme_name' color_scheme_o = self.get_color_scheme() connect_n = 'connect_to_oi' wrap_n = 'wrap' wrap_o = self.get_option(wrap_n) self.wrap_action.setChecked(wrap_o) math_n = 'math' math_o = self.get_option(math_n) if color_scheme_n in options: self.set_plain_text_color_scheme(color_scheme_o) if wrap_n in options: self.toggle_wrap_mode(wrap_o) if math_n in options: self.toggle_math_mode(math_o) # To make auto-connection changes take place instantly self.main.editor.apply_plugin_settings(options=[connect_n]) self.main.ipyconsole.apply_plugin_settings(options=[connect_n]) #------ Public API (related to Help's source) ------------------------- def source_is_console(self): """Return True if source is Console""" return self.source_combo.currentIndex() == 0 def switch_to_editor_source(self): self.source_combo.setCurrentIndex(1) def switch_to_console_source(self): self.source_combo.setCurrentIndex(0) def source_changed(self, index=None): if self.source_is_console(): # Console self.combo.show() self.object_edit.hide() self.show_source_action.setEnabled(True) self.auto_import_action.setEnabled(True) else: # Editor self.combo.hide() self.object_edit.show() self.show_source_action.setDisabled(True) self.auto_import_action.setDisabled(True) self.restore_text() def save_text(self, callback): if self.source_is_console(): self._last_console_cb = callback else: self._last_editor_cb = callback def restore_text(self): if self.source_is_console(): cb = self._last_console_cb else: cb = self._last_editor_cb if cb is None: if self.is_plain_text_mode(): self.plain_text.clear() else: self.rich_text.clear() else: func = cb[0] args = cb[1:] func(*args) if get_meth_class_inst(func) is self.rich_text: self.switch_to_rich_text() else: self.switch_to_plain_text() #------ Public API (related to rich/plain text widgets) -------------------- @property def find_widget(self): if self.plain_text.isVisible(): return self.plain_text.find_widget else: return self.rich_text.find_widget def set_rich_text_font(self, font): """Set rich text mode font""" self.rich_text.set_font(font, fixed_font=self.get_plugin_font()) def set_plain_text_font(self, font, color_scheme=None): """Set plain text mode font""" self.plain_text.set_font(font, color_scheme=color_scheme) def set_plain_text_color_scheme(self, color_scheme): """Set plain text mode color scheme""" self.plain_text.set_color_scheme(color_scheme) @Slot(bool) def toggle_wrap_mode(self, checked): """Toggle wrap mode""" self.plain_text.editor.toggle_wrap_mode(checked) self.set_option('wrap', checked) def toggle_math_mode(self, checked): """Toggle math mode""" self.set_option('math', checked) def is_plain_text_mode(self): """Return True if plain text mode is active""" return self.plain_text.isVisible() def is_rich_text_mode(self): """Return True if rich text mode is active""" return self.rich_text.isVisible() def switch_to_plain_text(self): """Switch to plain text mode""" self.rich_help = False self.plain_text.show() self.rich_text.hide() self.plain_text_action.setChecked(True) def switch_to_rich_text(self): """Switch to rich text mode""" self.rich_help = True self.plain_text.hide() self.rich_text.show() self.rich_text_action.setChecked(True) self.show_source_action.setChecked(False) def set_plain_text(self, text, is_code): """Set plain text docs""" # text is coming from utils.dochelpers.getdoc if type(text) is dict: name = text['name'] if name: rst_title = ''.join(['='*len(name), '\n', name, '\n', '='*len(name), '\n\n']) else: rst_title = '' if text['argspec']: definition = ''.join(['Definition: ', name, text['argspec'], '\n']) else: definition = '' if text['note']: note = ''.join(['Type: ', text['note'], '\n\n----\n\n']) else: note = '' full_text = ''.join([rst_title, definition, note, text['docstring']]) else: full_text = text self.plain_text.set_text(full_text, is_code) self.save_text([self.plain_text.set_text, full_text, is_code]) def set_rich_text_html(self, html_text, base_url): """Set rich text""" self.rich_text.set_html(html_text, base_url) self.save_text([self.rich_text.set_html, html_text, base_url]) def show_intro_message(self): intro_message = _("Here you can get help of any object by pressing " "%s in front of it, either on the Editor or the " "Console.%s" "Help can also be shown automatically after writing " "a left parenthesis next to an object. You can " "activate this behavior in %s.") prefs = _("Preferences > Help") if sys.platform == 'darwin': shortcut = "Cmd+I" else: shortcut = "Ctrl+I" if self.is_rich_text_mode(): title = _("Usage") tutorial_message = _("New to Spyder? Read our") tutorial = _("tutorial") intro_message = intro_message % (""+shortcut+"", "

    ", ""+prefs+"") self.set_rich_text_html(usage(title, intro_message, tutorial_message, tutorial), QUrl.fromLocalFile(CSS_PATH)) else: install_sphinx = "\n\n%s" % _("Please consider installing Sphinx " "to get documentation rendered in " "rich text.") intro_message = intro_message % (shortcut, "\n\n", prefs) intro_message += install_sphinx self.set_plain_text(intro_message, is_code=False) def show_rich_text(self, text, collapse=False, img_path=''): """Show text in rich mode""" self.visibility_changed(True) self.raise_() self.switch_to_rich_text() context = generate_context(collapse=collapse, img_path=img_path) self.render_sphinx_doc(text, context) def show_plain_text(self, text): """Show text in plain mode""" self.visibility_changed(True) self.raise_() self.switch_to_plain_text() self.set_plain_text(text, is_code=False) @Slot() def show_tutorial(self): tutorial_path = get_module_source_path('spyder.utils.help') tutorial = osp.join(tutorial_path, 'tutorial.rst') text = open(tutorial).read() self.show_rich_text(text, collapse=True) def handle_link_clicks(self, url): url = to_text_string(url.toString()) if url == "spy://tutorial": self.show_tutorial() elif url.startswith('http'): programs.start_file(url) else: self.rich_text.webview.load(QUrl(url)) #------ Public API --------------------------------------------------------- def force_refresh(self): if self.source_is_console(): self.set_object_text(None, force_refresh=True) elif self._last_editor_doc is not None: self.set_editor_doc(self._last_editor_doc, force_refresh=True) 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 set_editor_doc(self, doc, force_refresh=False): """ Use the help plugin to show docstring dictionary computed with introspection plugin from the Editor plugin """ if (self.locked and not force_refresh): return self.switch_to_editor_source() self._last_editor_doc = doc self.object_edit.setText(doc['obj_text']) if self.rich_help: self.render_sphinx_doc(doc) else: self.set_plain_text(doc, is_code=False) if self.dockwidget is not None: self.dockwidget.blockSignals(True) self.__eventually_raise_help(doc['docstring'], force=force_refresh) if self.dockwidget is not None: self.dockwidget.blockSignals(False) def __eventually_raise_help(self, text, force=False): index = self.source_combo.currentIndex() if hasattr(self.main, 'tabifiedDockWidgets'): # 'QMainWindow.tabifiedDockWidgets' was introduced in PyQt 4.5 if self.dockwidget and (force or self.dockwidget.isVisible()) \ and not self.ismaximized \ and (force or text != self._last_texts[index]): dockwidgets = self.main.tabifiedDockWidgets(self.dockwidget) if self.main.console.dockwidget not in dockwidgets and \ (hasattr(self.main, 'ipyconsole') and \ self.main.ipyconsole.dockwidget not in dockwidgets): self.dockwidget.show() self.dockwidget.raise_() self._last_texts[index] = text def load_history(self, obj=None): """Load history from a text file in user home directory""" if osp.isfile(self.LOG_PATH): history = [line.replace('\n', '') for line in open(self.LOG_PATH, 'r').readlines()] else: history = [] return history def save_history(self): """Save history to a text file in user home directory""" open(self.LOG_PATH, 'w').write("\n".join( \ [to_text_string(self.combo.itemText(index)) for index in range(self.combo.count())] )) @Slot(bool) def toggle_plain_text(self, checked): """Toggle plain text docstring""" if checked: self.docstring = checked self.switch_to_plain_text() self.force_refresh() self.set_option('rich_mode', not checked) @Slot(bool) def toggle_show_source(self, checked): """Toggle show source code""" if checked: self.switch_to_plain_text() self.docstring = not checked self.force_refresh() self.set_option('rich_mode', not checked) @Slot(bool) def toggle_rich_text(self, checked): """Toggle between sphinxified docstrings or plain ones""" if checked: self.docstring = not checked self.switch_to_rich_text() self.set_option('rich_mode', checked) @Slot(bool) def toggle_auto_import(self, checked): """Toggle automatic import feature""" self.combo.validate_current_text() self.set_option('automatic_import', checked) self.force_refresh() @Slot() 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 = ima.icon('lock') if self.locked else ima.icon('lock_open') self.locked_button.setIcon(icon) tip = _("Unlock") if self.locked else _("Lock") self.locked_button.setToolTip(tip) def set_shell(self, shell): """Bind to shell""" self.shell = shell def get_shell(self): """ Return shell which is currently bound to Help, or another running shell if it has been terminated """ if (not hasattr(self.shell, 'get_doc') or (hasattr(self.shell, 'is_running') and not self.shell.is_running())): self.shell = None if self.main.ipyconsole is not None: shell = self.main.ipyconsole.get_current_shellwidget() if shell is not None and shell.kernel_client is not None: self.shell = shell if self.shell is None: self.shell = self.internal_shell return self.shell def render_sphinx_doc(self, doc, context=None): """Transform doc string dictionary to HTML and show it""" # Math rendering option could have changed fname = self.parent().parent().editor.get_current_filename() dname = osp.dirname(fname) self._sphinx_thread.render(doc, context, self.get_option('math'), dname) def _on_sphinx_thread_html_ready(self, html_text): """Set our sphinx documentation based on thread result""" self._sphinx_thread.wait() self.set_rich_text_html(html_text, QUrl.fromLocalFile(CSS_PATH)) def _on_sphinx_thread_error_msg(self, error_msg): """ Display error message on Sphinx rich text failure""" self._sphinx_thread.wait() self.plain_text_action.setChecked(True) sphinx_ver = programs.get_module_version('sphinx') QMessageBox.critical(self, _('Help'), _("The following error occured when calling " "Sphinx %s.
    Incompatible Sphinx " "version or doc string decoding failed." "

    Error message:
    %s" ) % (sphinx_ver, error_msg)) def show_help(self, obj_text, ignore_unknown=False): """Show help""" shell = self.get_shell() if shell is None: return obj_text = to_text_string(obj_text) if not shell.is_defined(obj_text): if self.get_option('automatic_import') and \ self.internal_shell.is_defined(obj_text, force_import=True): shell = self.internal_shell else: shell = None doc = None source_text = None if shell is not None: doc = shell.get_doc(obj_text) source_text = shell.get_source(obj_text) is_code = False if self.rich_help: self.render_sphinx_doc(doc) return doc is not None elif self.docstring: hlp_text = doc if hlp_text is None: hlp_text = source_text if hlp_text is None: hlp_text = self.no_doc_string if ignore_unknown: return False else: hlp_text = source_text if hlp_text is None: hlp_text = doc if hlp_text is None: hlp_text = _("No source code available.") if ignore_unknown: return False else: is_code = True self.set_plain_text(hlp_text, is_code=is_code) return True spyder-3.2.6/spyder/plugins/runconfig.py0000664000175000017500000005555113224121062021161 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Run configurations related dialogs and widgets and data models""" # Standard library imports import os.path as osp # Third party imports from qtpy.compat import getexistingdirectory from qtpy.QtCore import QSize, Qt, Signal, Slot from qtpy.QtWidgets import (QButtonGroup, QCheckBox, QComboBox, QDialog, QDialogButtonBox, QFrame, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLineEdit, QMessageBox, QPushButton, QRadioButton, QSizePolicy, QStackedWidget, QVBoxLayout, QWidget) # Local imports from spyder.config.base import _ from spyder.config.main import CONF from spyder.plugins.configdialog import GeneralConfigPage from spyder.py3compat import to_text_string from spyder.utils import icon_manager as ima from spyder.utils.misc import getcwd_or_home CURRENT_INTERPRETER = _("Execute in current console") DEDICATED_INTERPRETER = _("Execute in a dedicated console") SYSTERM_INTERPRETER = _("Execute in an external system terminal") CURRENT_INTERPRETER_OPTION = 'default/interpreter/current' DEDICATED_INTERPRETER_OPTION = 'default/interpreter/dedicated' SYSTERM_INTERPRETER_OPTION = 'default/interpreter/systerm' WDIR_USE_SCRIPT_DIR_OPTION = 'default/wdir/use_script_directory' WDIR_USE_CWD_DIR_OPTION = 'default/wdir/use_cwd_directory' WDIR_USE_FIXED_DIR_OPTION = 'default/wdir/use_fixed_directory' WDIR_FIXED_DIR_OPTION = 'default/wdir/fixed_directory' ALWAYS_OPEN_FIRST_RUN = _("Always show %s on a first file run") ALWAYS_OPEN_FIRST_RUN_OPTION = 'open_on_firstrun' CLEAR_ALL_VARIABLES = _("Remove all variables before execution") POST_MORTEM = _("Directly enter debugging when errors appear") INTERACT = _("Interact with the Python console after execution") FILE_DIR = _("The directory of the file being executed") CW_DIR = _("The current working directory") FIXED_DIR = _("The following directory:") class RunConfiguration(object): """Run configuration""" def __init__(self, fname=None): self.args = None self.args_enabled = None self.wdir = None self.wdir_enabled = None self.current = None self.systerm = None self.interact = None self.post_mortem = None self.python_args = None self.python_args_enabled = None self.clear_namespace = None self.file_dir = None self.cw_dir = None self.fixed_dir = None self.dir = None self.set(CONF.get('run', 'defaultconfiguration', default={})) def set(self, options): self.args = options.get('args', '') self.args_enabled = options.get('args/enabled', False) self.current = options.get('current', CONF.get('run', CURRENT_INTERPRETER_OPTION, True)) self.systerm = options.get('systerm', CONF.get('run', SYSTERM_INTERPRETER_OPTION, False)) self.interact = options.get('interact', CONF.get('run', 'interact', False)) self.post_mortem = options.get('post_mortem', CONF.get('run', 'post_mortem', False)) self.python_args = options.get('python_args', '') self.python_args_enabled = options.get('python_args/enabled', False) self.clear_namespace = options.get('clear_namespace', CONF.get('run', 'clear_namespace', False)) self.file_dir = options.get('file_dir', CONF.get('run', WDIR_USE_SCRIPT_DIR_OPTION, True)) self.cw_dir = options.get('cw_dir', CONF.get('run', WDIR_USE_CWD_DIR_OPTION, False)) self.fixed_dir = options.get('fixed_dir', CONF.get('run', WDIR_USE_FIXED_DIR_OPTION, False)) self.dir = options.get('dir', '') def get(self): return { 'args/enabled': self.args_enabled, 'args': self.args, 'workdir/enabled': self.wdir_enabled, 'workdir': self.wdir, 'current': self.current, 'systerm': self.systerm, 'interact': self.interact, 'post_mortem': self.post_mortem, 'python_args/enabled': self.python_args_enabled, 'python_args': self.python_args, 'clear_namespace': self.clear_namespace, 'file_dir': self.file_dir, 'cw_dir': self.cw_dir, 'fixed_dir': self.fixed_dir, 'dir': self.dir } def get_working_directory(self): return self.dir def get_arguments(self): if self.args_enabled: return self.args else: return '' def get_python_arguments(self): if self.python_args_enabled: return self.python_args else: return '' def _get_run_configurations(): history_count = CONF.get('run', 'history', 20) try: return [(filename, options) for filename, options in CONF.get('run', 'configurations', []) if osp.isfile(filename)][:history_count] except ValueError: CONF.set('run', 'configurations', []) return [] def _set_run_configurations(configurations): history_count = CONF.get('run', 'history', 20) CONF.set('run', 'configurations', configurations[:history_count]) def get_run_configuration(fname): """Return script *fname* run configuration""" configurations = _get_run_configurations() for filename, options in configurations: if fname == filename: runconf = RunConfiguration() runconf.set(options) return runconf class RunConfigOptions(QWidget): """Run configuration options""" def __init__(self, parent=None): QWidget.__init__(self, parent) self.dir = None self.runconf = RunConfiguration() firstrun_o = CONF.get('run', ALWAYS_OPEN_FIRST_RUN_OPTION, False) # --- Interpreter --- interpreter_group = QGroupBox(_("Console")) interpreter_layout = QVBoxLayout() interpreter_group.setLayout(interpreter_layout) self.current_radio = QRadioButton(CURRENT_INTERPRETER) interpreter_layout.addWidget(self.current_radio) self.dedicated_radio = QRadioButton(DEDICATED_INTERPRETER) interpreter_layout.addWidget(self.dedicated_radio) self.systerm_radio = QRadioButton(SYSTERM_INTERPRETER) interpreter_layout.addWidget(self.systerm_radio) # --- General settings ---- common_group = QGroupBox(_("General settings")) common_layout = QGridLayout() common_group.setLayout(common_layout) self.clear_var_cb = QCheckBox(CLEAR_ALL_VARIABLES) common_layout.addWidget(self.clear_var_cb, 0, 0) self.post_mortem_cb = QCheckBox(POST_MORTEM) common_layout.addWidget(self.post_mortem_cb, 1, 0) self.clo_cb = QCheckBox(_("Command line options:")) common_layout.addWidget(self.clo_cb, 2, 0) self.clo_edit = QLineEdit() self.clo_cb.toggled.connect(self.clo_edit.setEnabled) self.clo_edit.setEnabled(False) common_layout.addWidget(self.clo_edit, 2, 1) # --- Working directory --- wdir_group = QGroupBox(_("Working Directory settings")) wdir_layout = QVBoxLayout() wdir_group.setLayout(wdir_layout) self.file_dir_radio = QRadioButton(FILE_DIR) wdir_layout.addWidget(self.file_dir_radio) self.cwd_radio = QRadioButton(CW_DIR) wdir_layout.addWidget(self.cwd_radio) fixed_dir_layout = QHBoxLayout() self.fixed_dir_radio = QRadioButton(FIXED_DIR) fixed_dir_layout.addWidget(self.fixed_dir_radio) self.wd_edit = QLineEdit() self.fixed_dir_radio.toggled.connect(self.wd_edit.setEnabled) self.wd_edit.setEnabled(False) fixed_dir_layout.addWidget(self.wd_edit) browse_btn = QPushButton(ima.icon('DirOpenIcon'), '', self) browse_btn.setToolTip(_("Select directory")) browse_btn.clicked.connect(self.select_directory) fixed_dir_layout.addWidget(browse_btn) wdir_layout.addLayout(fixed_dir_layout) # --- System terminal --- external_group = QGroupBox(_("External system terminal")) external_group.setDisabled(True) self.systerm_radio.toggled.connect(external_group.setEnabled) external_layout = QGridLayout() external_group.setLayout(external_layout) self.interact_cb = QCheckBox(INTERACT) external_layout.addWidget(self.interact_cb, 1, 0, 1, -1) self.pclo_cb = QCheckBox(_("Command line options:")) external_layout.addWidget(self.pclo_cb, 3, 0) self.pclo_edit = QLineEdit() self.pclo_cb.toggled.connect(self.pclo_edit.setEnabled) self.pclo_edit.setEnabled(False) self.pclo_edit.setToolTip(_("-u is added to the " "other options you set here")) external_layout.addWidget(self.pclo_edit, 3, 1) # Checkbox to preserve the old behavior, i.e. always open the dialog # on first run hline = QFrame() hline.setFrameShape(QFrame.HLine) hline.setFrameShadow(QFrame.Sunken) self.firstrun_cb = QCheckBox(ALWAYS_OPEN_FIRST_RUN % _("this dialog")) self.firstrun_cb.clicked.connect(self.set_firstrun_o) self.firstrun_cb.setChecked(firstrun_o) layout = QVBoxLayout() layout.addWidget(interpreter_group) layout.addWidget(common_group) layout.addWidget(wdir_group) layout.addWidget(external_group) layout.addWidget(hline) layout.addWidget(self.firstrun_cb) self.setLayout(layout) def select_directory(self): """Select directory""" basedir = to_text_string(self.wd_edit.text()) if not osp.isdir(basedir): basedir = getcwd_or_home() directory = getexistingdirectory(self, _("Select directory"), basedir) if directory: self.wd_edit.setText(directory) self.dir = directory def set(self, options): self.runconf.set(options) self.clo_cb.setChecked(self.runconf.args_enabled) self.clo_edit.setText(self.runconf.args) if self.runconf.current: self.current_radio.setChecked(True) elif self.runconf.systerm: self.systerm_radio.setChecked(True) else: self.dedicated_radio.setChecked(True) self.interact_cb.setChecked(self.runconf.interact) self.post_mortem_cb.setChecked(self.runconf.post_mortem) self.pclo_cb.setChecked(self.runconf.python_args_enabled) self.pclo_edit.setText(self.runconf.python_args) self.clear_var_cb.setChecked(self.runconf.clear_namespace) self.file_dir_radio.setChecked(self.runconf.file_dir) self.cwd_radio.setChecked(self.runconf.cw_dir) self.fixed_dir_radio.setChecked(self.runconf.fixed_dir) self.dir = self.runconf.dir self.wd_edit.setText(self.dir) def get(self): self.runconf.args_enabled = self.clo_cb.isChecked() self.runconf.args = to_text_string(self.clo_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.post_mortem = self.post_mortem_cb.isChecked() self.runconf.python_args_enabled = self.pclo_cb.isChecked() self.runconf.python_args = to_text_string(self.pclo_edit.text()) self.runconf.clear_namespace = self.clear_var_cb.isChecked() self.runconf.file_dir = self.file_dir_radio.isChecked() self.runconf.cw_dir = self.cwd_radio.isChecked() self.runconf.fixed_dir = self.fixed_dir_radio.isChecked() self.runconf.dir = self.wd_edit.text() return self.runconf.get() def is_valid(self): wdir = to_text_string(self.wd_edit.text()) if not self.fixed_dir_radio.isChecked() or osp.isdir(wdir): return True else: QMessageBox.critical(self, _("Run configuration"), _("The following working directory is " "not valid:
    %s") % wdir) return False def set_firstrun_o(self): CONF.set('run', ALWAYS_OPEN_FIRST_RUN_OPTION, self.firstrun_cb.isChecked()) class BaseRunConfigDialog(QDialog): """Run configuration dialog box, base widget""" size_change = Signal(QSize) def __init__(self, parent=None): QDialog.__init__(self, parent) # Destroying the C++ object right after closing the dialog box, # otherwise it may be garbage-collected in another QThread # (e.g. the editor's analysis thread in Spyder), thus leading to # a segmentation fault on UNIX or an application crash on Windows self.setAttribute(Qt.WA_DeleteOnClose) self.setWindowIcon(ima.icon('run_settings')) layout = QVBoxLayout() self.setLayout(layout) def add_widgets(self, *widgets_or_spacings): """Add widgets/spacing to dialog vertical layout""" layout = self.layout() for widget_or_spacing in widgets_or_spacings: if isinstance(widget_or_spacing, int): layout.addSpacing(widget_or_spacing) else: layout.addWidget(widget_or_spacing) def add_button_box(self, stdbtns): """Create dialog button box and add it to the dialog layout""" bbox = QDialogButtonBox(stdbtns) run_btn = bbox.addButton(_("Run"), QDialogButtonBox.AcceptRole) run_btn.clicked.connect(self.run_btn_clicked) bbox.accepted.connect(self.accept) bbox.rejected.connect(self.reject) btnlayout = QHBoxLayout() btnlayout.addStretch(1) btnlayout.addWidget(bbox) self.layout().addLayout(btnlayout) def resizeEvent(self, event): """ Reimplement Qt method to be able to save the widget's size from the main application """ QDialog.resizeEvent(self, event) self.size_change.emit(self.size()) def run_btn_clicked(self): """Run button was just clicked""" pass def setup(self, fname): """Setup Run Configuration dialog with filename *fname*""" raise NotImplementedError class RunConfigOneDialog(BaseRunConfigDialog): """Run configuration dialog box: single file version""" def __init__(self, parent=None): BaseRunConfigDialog.__init__(self, parent) self.filename = None self.runconfigoptions = None def setup(self, fname): """Setup Run Configuration dialog with filename *fname*""" self.filename = fname self.runconfigoptions = RunConfigOptions(self) self.runconfigoptions.set(RunConfiguration(fname).get()) self.add_widgets(self.runconfigoptions) self.add_button_box(QDialogButtonBox.Cancel) self.setWindowTitle(_("Run settings for %s") % osp.basename(fname)) @Slot() def accept(self): """Reimplement Qt method""" if not self.runconfigoptions.is_valid(): return configurations = _get_run_configurations() configurations.insert(0, (self.filename, self.runconfigoptions.get())) _set_run_configurations(configurations) QDialog.accept(self) def get_configuration(self): # It is import to avoid accessing Qt C++ object as it has probably # already been destroyed, due to the Qt.WA_DeleteOnClose attribute return self.runconfigoptions.runconf class RunConfigDialog(BaseRunConfigDialog): """Run configuration dialog box: multiple file version""" def __init__(self, parent=None): BaseRunConfigDialog.__init__(self, parent) self.file_to_run = None self.combo = None self.stack = None def run_btn_clicked(self): """Run button was just clicked""" self.file_to_run = to_text_string(self.combo.currentText()) def setup(self, fname): """Setup Run Configuration dialog with filename *fname*""" combo_label = QLabel(_("Select a run configuration:")) self.combo = QComboBox() self.combo.setMaxVisibleItems(20) self.combo.setSizeAdjustPolicy(QComboBox.AdjustToMinimumContentsLength) self.combo.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.stack = QStackedWidget() configurations = _get_run_configurations() for index, (filename, options) in enumerate(configurations): if fname == filename: break else: # There is no run configuration for script *fname*: # creating a temporary configuration that will be kept only if # dialog changes are accepted by the user configurations.insert(0, (fname, RunConfiguration(fname).get())) index = 0 for filename, options in configurations: widget = RunConfigOptions(self) widget.set(options) self.combo.addItem(filename) self.stack.addWidget(widget) self.combo.currentIndexChanged.connect(self.stack.setCurrentIndex) self.combo.setCurrentIndex(index) self.add_widgets(combo_label, self.combo, 10, self.stack) self.add_button_box(QDialogButtonBox.Ok|QDialogButtonBox.Cancel) self.setWindowTitle(_("Run configuration per file")) def accept(self): """Reimplement Qt method""" configurations = [] for index in range(self.stack.count()): filename = to_text_string(self.combo.itemText(index)) runconfigoptions = self.stack.widget(index) if index == self.stack.currentIndex() and\ not runconfigoptions.is_valid(): return options = runconfigoptions.get() configurations.append( (filename, options) ) _set_run_configurations(configurations) QDialog.accept(self) class RunConfigPage(GeneralConfigPage): """Default Run Settings configuration page""" CONF_SECTION = "run" NAME = _("Run") ICON = ima.icon('run') def setup_page(self): about_label = QLabel(_("The following are the default options for " "running files.These options may be overriden " "using the Configuration per file entry " "of the Run menu.")) about_label.setWordWrap(True) interpreter_group = QGroupBox(_("Console")) interpreter_bg = QButtonGroup(interpreter_group) self.current_radio = self.create_radiobutton(CURRENT_INTERPRETER, CURRENT_INTERPRETER_OPTION, True, button_group=interpreter_bg) self.dedicated_radio = self.create_radiobutton(DEDICATED_INTERPRETER, DEDICATED_INTERPRETER_OPTION, False, button_group=interpreter_bg) self.systerm_radio = self.create_radiobutton(SYSTERM_INTERPRETER, SYSTERM_INTERPRETER_OPTION, False, button_group=interpreter_bg) interpreter_layout = QVBoxLayout() interpreter_group.setLayout(interpreter_layout) interpreter_layout.addWidget(self.current_radio) interpreter_layout.addWidget(self.dedicated_radio) interpreter_layout.addWidget(self.systerm_radio) general_group = QGroupBox(_("General settings")) post_mortem = self.create_checkbox(POST_MORTEM, 'post_mortem', False) clear_variables = self.create_checkbox(CLEAR_ALL_VARIABLES, 'clear_namespace', False) general_layout = QVBoxLayout() general_layout.addWidget(clear_variables) general_layout.addWidget(post_mortem) general_group.setLayout(general_layout) wdir_group = QGroupBox(_("Working Directory settings")) wdir_bg = QButtonGroup(wdir_group) wdir_label = QLabel(_("Default working directory is:")) wdir_label.setWordWrap(True) dirname_radio = self.create_radiobutton( FILE_DIR, WDIR_USE_SCRIPT_DIR_OPTION, True, button_group=wdir_bg) cwd_radio = self.create_radiobutton( CW_DIR, WDIR_USE_CWD_DIR_OPTION, False, button_group=wdir_bg) thisdir_radio = self.create_radiobutton( FIXED_DIR, WDIR_USE_FIXED_DIR_OPTION, False, button_group=wdir_bg) thisdir_bd = self.create_browsedir("", WDIR_FIXED_DIR_OPTION, getcwd_or_home()) thisdir_radio.toggled.connect(thisdir_bd.setEnabled) dirname_radio.toggled.connect(thisdir_bd.setDisabled) cwd_radio.toggled.connect(thisdir_bd.setDisabled) thisdir_layout = QHBoxLayout() thisdir_layout.addWidget(thisdir_radio) thisdir_layout.addWidget(thisdir_bd) wdir_layout = QVBoxLayout() wdir_layout.addWidget(wdir_label) wdir_layout.addWidget(dirname_radio) wdir_layout.addWidget(cwd_radio) wdir_layout.addLayout(thisdir_layout) wdir_group.setLayout(wdir_layout) external_group = QGroupBox(_("External system terminal")) interact_after = self.create_checkbox(INTERACT, 'interact', False) external_layout = QVBoxLayout() external_layout.addWidget(interact_after) external_group.setLayout(external_layout) firstrun_cb = self.create_checkbox( ALWAYS_OPEN_FIRST_RUN % _("Run Settings dialog"), ALWAYS_OPEN_FIRST_RUN_OPTION, False) vlayout = QVBoxLayout() vlayout.addWidget(about_label) vlayout.addSpacing(10) vlayout.addWidget(interpreter_group) vlayout.addWidget(general_group) vlayout.addWidget(wdir_group) vlayout.addWidget(external_group) vlayout.addWidget(firstrun_cb) vlayout.addStretch(1) self.setLayout(vlayout) def apply_settings(self, options): pass spyder-3.2.6/spyder/plugins/__init__.py0000664000175000017500000005605013224740762020737 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ spyder.plugins ============== Here, 'plugins' are widgets designed specifically for Spyder These plugins inherit the following classes (SpyderPluginMixin & SpyderPluginWidget) """ # pylint: disable=C0103 # pylint: disable=R0903 # pylint: disable=R0911 # pylint: disable=R0201 # Standard library imports import inspect import os # Third party imports from qtpy import PYQT5 from qtpy.QtCore import QEvent, QObject, QPoint, Qt, Signal from qtpy.QtGui import QCursor, QKeySequence from qtpy.QtWidgets import (QApplication, QDockWidget, QMainWindow, QShortcut, QTabBar, QWidget, QMessageBox) # Local imports from spyder.config.base import _ from spyder.config.gui import get_color_scheme, get_font from spyder.config.main import CONF from spyder.config.user import NoDefault from spyder.py3compat import configparser, is_text_string from spyder.utils import icon_manager as ima from spyder.utils.qthelpers import create_action, toggle_actions class TabFilter(QObject): """ Filter event attached to each QTabBar that holds 2 or more dockwidgets in charge of handling tab rearangement. This filter also holds the methods needed for the detection of a drag and the movement of tabs. """ def __init__(self, dock_tabbar, main): QObject.__init__(self) self.dock_tabbar = dock_tabbar self.main = main self.moving = False self.from_index = None self.to_index = None # Helper methods def _get_plugin(self, index): """Get plugin reference based on tab index.""" for plugin in self.main.widgetlist: tab_text = self.dock_tabbar.tabText(index).replace('&', '') if plugin.get_plugin_title() == tab_text: return plugin def _get_plugins(self): """ Get a list of all plugin references in the QTabBar to which this event filter is attached. """ plugins = [] for index in range(self.dock_tabbar.count()): plugin = self._get_plugin(index) plugins.append(plugin) return plugins def _fix_cursor(self, from_index, to_index): """Fix mouse cursor position to adjust for different tab sizes.""" # The direction is +1 (moving to the right) or -1 (moving to the left) direction = abs(to_index - from_index)/(to_index - from_index) tab_width = self.dock_tabbar.tabRect(to_index).width() tab_x_min = self.dock_tabbar.tabRect(to_index).x() tab_x_max = tab_x_min + tab_width previous_width = self.dock_tabbar.tabRect(to_index - direction).width() delta = previous_width - tab_width if delta > 0: delta = delta * direction else: delta = 0 cursor = QCursor() pos = self.dock_tabbar.mapFromGlobal(cursor.pos()) x, y = pos.x(), pos.y() if x < tab_x_min or x > tab_x_max: new_pos = self.dock_tabbar.mapToGlobal(QPoint(x + delta, y)) cursor.setPos(new_pos) def eventFilter(self, obj, event): """Filter mouse press events. Events that are captured and not propagated return True. Events that are not captured and are propagated return False. """ event_type = event.type() if event_type == QEvent.MouseButtonPress: self.tab_pressed(event) return False if event_type == QEvent.MouseMove: self.tab_moved(event) return True if event_type == QEvent.MouseButtonRelease: self.tab_released(event) return True return False def tab_pressed(self, event): """Method called when a tab from a QTabBar has been pressed.""" self.from_index = self.dock_tabbar.tabAt(event.pos()) self.dock_tabbar.setCurrentIndex(self.from_index) if event.button() == Qt.RightButton: if self.from_index == -1: self.show_nontab_menu(event) else: self.show_tab_menu(event) def tab_moved(self, event): """Method called when a tab from a QTabBar has been moved.""" # If the left button isn't pressed anymore then return if not event.buttons() & Qt.LeftButton: self.to_index = None return self.to_index = self.dock_tabbar.tabAt(event.pos()) if not self.moving and self.from_index != -1 and self.to_index != -1: QApplication.setOverrideCursor(Qt.ClosedHandCursor) self.moving = True if self.to_index == -1: self.to_index = self.from_index from_index, to_index = self.from_index, self.to_index if from_index != to_index and from_index != -1 and to_index != -1: self.move_tab(from_index, to_index) self._fix_cursor(from_index, to_index) self.from_index = to_index def tab_released(self, event): """Method called when a tab from a QTabBar has been released.""" QApplication.restoreOverrideCursor() self.moving = False def move_tab(self, from_index, to_index): """Move a tab from a given index to a given index position.""" plugins = self._get_plugins() from_plugin = self._get_plugin(from_index) to_plugin = self._get_plugin(to_index) from_idx = plugins.index(from_plugin) to_idx = plugins.index(to_plugin) plugins[from_idx], plugins[to_idx] = plugins[to_idx], plugins[from_idx] for i in range(len(plugins)-1): self.main.tabify_plugins(plugins[i], plugins[i+1]) from_plugin.dockwidget.raise_() def show_tab_menu(self, event): """Show the context menu assigned to tabs.""" self.show_nontab_menu(event) def show_nontab_menu(self, event): """Show the context menu assigned to nontabs section.""" menu = self.main.createPopupMenu() menu.exec_(self.dock_tabbar.mapToGlobal(event.pos())) class SpyderDockWidget(QDockWidget): """Subclass to override needed methods""" plugin_closed = Signal() def __init__(self, title, parent): super(SpyderDockWidget, self).__init__(title, parent) # Needed for the installation of the event filter self.title = title self.main = parent self.dock_tabbar = None # To track dockwidget changes the filter is installed when dockwidget # visibility changes. This installs the filter on startup and also # on dockwidgets that are undocked and then docked to a new location. self.visibilityChanged.connect(self.install_tab_event_filter) def closeEvent(self, event): """ Reimplement Qt method to send a signal on close so that "Panes" main window menu can be updated correctly """ self.plugin_closed.emit() def install_tab_event_filter(self, value): """ Install an event filter to capture mouse events in the tabs of a QTabBar holding tabified dockwidgets. """ dock_tabbar = None tabbars = self.main.findChildren(QTabBar) for tabbar in tabbars: for tab in range(tabbar.count()): title = tabbar.tabText(tab) if title == self.title: dock_tabbar = tabbar break if dock_tabbar is not None: self.dock_tabbar = dock_tabbar # Install filter only once per QTabBar if getattr(self.dock_tabbar, 'filter', None) is None: self.dock_tabbar.filter = TabFilter(self.dock_tabbar, self.main) self.dock_tabbar.installEventFilter(self.dock_tabbar.filter) class SpyderPluginMixin(object): """ Useful methods to bind widgets to the main window See SpyderPluginWidget class for required widget interface Signals: * sig_option_changed Example: plugin.sig_option_changed.emit('show_all', checked) * show_message * update_plugin_title """ CONF_SECTION = None CONFIGWIDGET_CLASS = None FONT_SIZE_DELTA = 0 RICH_FONT_SIZE_DELTA = 0 IMG_PATH = 'images' ALLOWED_AREAS = Qt.AllDockWidgetAreas LOCATION = Qt.LeftDockWidgetArea FEATURES = QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetFloatable DISABLE_ACTIONS_WHEN_HIDDEN = True # Signals sig_option_changed = None show_message = None update_plugin_title = None def __init__(self, main=None, **kwds): """Bind widget to a QMainWindow instance""" super(SpyderPluginMixin, self).__init__(**kwds) assert self.CONF_SECTION is not None self.PLUGIN_PATH = os.path.dirname(inspect.getfile(self.__class__)) self.main = main self.default_margins = None self.plugin_actions = None self.dockwidget = None self.mainwindow = None self.ismaximized = False self.isvisible = False # NOTE: Don't use the default option of CONF.get to assign a # None shortcut to plugins that don't have one. That will mess # the creation of our Keyboard Shortcuts prefs page try: self.shortcut = CONF.get('shortcuts', '_/switch to %s' % \ self.CONF_SECTION) except configparser.NoOptionError: self.shortcut = None # We decided to create our own toggle action instead of using # the one that comes with dockwidget because it's not possible # to raise and focus the plugin with it. self.toggle_view_action = None def initialize_plugin(self): """Initialize plugin: connect signals, setup actions, ...""" self.create_toggle_view_action() self.plugin_actions = self.get_plugin_actions() if self.show_message is not None: self.show_message.connect(self.__show_message) if self.update_plugin_title is not None: self.update_plugin_title.connect(self.__update_plugin_title) if self.sig_option_changed is not None: self.sig_option_changed.connect(self.set_option) self.setWindowTitle(self.get_plugin_title()) def on_first_registration(self): """Action to be performed on first plugin registration""" # Was written to handle the very first plugin position in Spyder's # main window layout, but this could also be used for other things # (see for example the IPython console plugin for which this method # had to be written to handle the fact that this plugin was # introduced between v2.1 and v2.2) raise NotImplementedError def initialize_plugin_in_mainwindow_layout(self): """If this is the first time the plugin is shown, perform actions to initialize plugin position in Spyder's window layout""" if self.get_option('first_time', True): try: self.on_first_registration() except NotImplementedError: return self.set_option('first_time', False) def update_margins(self): layout = self.layout() if self.default_margins is None: self.default_margins = layout.getContentsMargins() if CONF.get('main', 'use_custom_margin'): margin = CONF.get('main', 'custom_margin') layout.setContentsMargins(*[margin]*4) else: layout.setContentsMargins(*self.default_margins) def __update_plugin_title(self): """Update plugin title, i.e. dockwidget or mainwindow title""" if self.dockwidget is not None: win = self.dockwidget elif self.mainwindow is not None: win = self.mainwindow else: return win.setWindowTitle(self.get_plugin_title()) def create_dockwidget(self): """Add to parent QMainWindow as a dock widget""" # This is not clear yet why the following do not work... # (see Issue #880) ## # Using Qt.Window window flags solves Issue #880 (detached dockwidgets ## # are not painted after restarting Spyder and restoring their hexstate) ## # but it does not work with PyQt <=v4.7 (dockwidgets can't be docked) ## # or non-Windows platforms (lot of warnings are printed out) ## # (so in those cases, we use the default window flags: Qt.Widget): ## flags = Qt.Widget if is_old_pyqt or os.name != 'nt' else Qt.Window dock = SpyderDockWidget(self.get_plugin_title(), self.main)#, flags) dock.setObjectName(self.__class__.__name__+"_dw") dock.setAllowedAreas(self.ALLOWED_AREAS) dock.setFeatures(self.FEATURES) dock.setWidget(self) self.update_margins() dock.visibilityChanged.connect(self.visibility_changed) dock.plugin_closed.connect(self.plugin_closed) self.dockwidget = dock if self.shortcut is not None: sc = QShortcut(QKeySequence(self.shortcut), self.main, self.switch_to_plugin) self.register_shortcut(sc, "_", "Switch to %s" % self.CONF_SECTION) return (dock, self.LOCATION) def create_mainwindow(self): """ Create a QMainWindow instance containing this plugin Note: this method is currently not used """ self.mainwindow = mainwindow = QMainWindow() mainwindow.setAttribute(Qt.WA_DeleteOnClose) icon = self.get_plugin_icon() if is_text_string(icon): icon = self.get_icon(icon) mainwindow.setWindowIcon(icon) mainwindow.setWindowTitle(self.get_plugin_title()) mainwindow.setCentralWidget(self) self.refresh_plugin() return mainwindow def create_configwidget(self, parent): """Create configuration dialog box page widget""" if self.CONFIGWIDGET_CLASS is not None: configwidget = self.CONFIGWIDGET_CLASS(self, parent) configwidget.initialize() return configwidget def apply_plugin_settings(self, options): """Apply configuration file's plugin settings""" raise NotImplementedError def register_shortcut(self, qaction_or_qshortcut, context, name, add_sc_to_tip=False): """ Register QAction or QShortcut to Spyder main application if add_sc_to_tip is True, the shortcut is added to the action's tooltip """ self.main.register_shortcut(qaction_or_qshortcut, context, name, add_sc_to_tip) def register_widget_shortcuts(self, widget): """ Register widget shortcuts widget interface must have a method called 'get_shortcut_data' """ for qshortcut, context, name in widget.get_shortcut_data(): self.register_shortcut(qshortcut, context, name) def switch_to_plugin(self): """Switch to plugin This method is called when pressing plugin's shortcut key""" if not self.ismaximized: self.dockwidget.show() if not self.toggle_view_action.isChecked(): self.toggle_view_action.setChecked(True) self.visibility_changed(True) def visibility_changed(self, enable): """DockWidget visibility has changed""" if enable: self.dockwidget.raise_() widget = self.get_focus_widget() if widget is not None: widget.setFocus() visible = self.dockwidget.isVisible() or self.ismaximized if self.DISABLE_ACTIONS_WHEN_HIDDEN: toggle_actions(self.plugin_actions, visible) self.isvisible = enable and visible if self.isvisible: self.refresh_plugin() # To give focus to the plugin's widget def plugin_closed(self): """DockWidget was closed""" self.toggle_view_action.setChecked(False) def set_option(self, option, value): """ Set a plugin option in configuration file Use a SIGNAL to call it, e.g.: plugin.sig_option_changed.emit('show_all', checked) """ CONF.set(self.CONF_SECTION, str(option), value) def get_option(self, option, default=NoDefault): """Get a plugin option from configuration file""" return CONF.get(self.CONF_SECTION, option, default) def get_plugin_font(self, rich_text=False): """ Return plugin font option. All plugins in Spyder use a global font. This is a convenience method in case some plugins will have a delta size based on the default size. """ if rich_text: option = 'rich_font' font_size_delta = self.RICH_FONT_SIZE_DELTA else: option = 'font' font_size_delta = self.FONT_SIZE_DELTA return get_font(option=option, font_size_delta=font_size_delta) def set_plugin_font(self): """ Set plugin font option. Note: All plugins in Spyder use a global font. To define a different size, the plugin must define a 'FONT_SIZE_DELTA' class variable. """ raise Exception("Plugins font is based on the general settings, " "and cannot be set directly on the plugin." "This method is deprecated.") def update_font(self): """ This has to be reimplemented by plugins that need to adjust their fonts """ pass def __show_message(self, message, timeout=0): """Show message in main window's status bar""" self.main.statusBar().showMessage(message, timeout) def starting_long_process(self, message): """ Showing message in main window's status bar and changing mouse cursor to Qt.WaitCursor """ self.__show_message(message) QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() def ending_long_process(self, message=""): """ Clearing main window's status bar and restoring mouse cursor """ QApplication.restoreOverrideCursor() self.__show_message(message, timeout=2000) QApplication.processEvents() def get_color_scheme(self): """Get current color scheme""" return get_color_scheme(CONF.get('color_schemes', 'selected')) def create_toggle_view_action(self): """Associate a toggle view action with each plugin""" title = self.get_plugin_title() if self.CONF_SECTION == 'editor': title = _('Editor') if self.shortcut is not None: action = create_action(self, title, toggled=lambda checked: self.toggle_view(checked), shortcut=QKeySequence(self.shortcut), context=Qt.WidgetShortcut) else: action = create_action(self, title, toggled=lambda checked: self.toggle_view(checked)) self.toggle_view_action = action def toggle_view(self, checked): """Toggle view""" if not self.dockwidget: return if checked: self.dockwidget.show() self.dockwidget.raise_() else: self.dockwidget.hide() class SpyderPluginWidget(QWidget, SpyderPluginMixin): """ Spyder base widget class Spyder's widgets either inherit this class or reimplement its interface """ sig_option_changed = Signal(str, object) show_message = Signal(str, int) update_plugin_title = Signal() if PYQT5: def __init__(self, parent, **kwds): check_compatibility, message = self.check_compatibility() super(SpyderPluginWidget, self).__init__(parent, **kwds) if not check_compatibility: self.show_compatibility_message(message) else: def __init__(self, parent): check_compatibility, message = self.check_compatibility() QWidget.__init__(self, parent) SpyderPluginMixin.__init__(self, parent) if not check_compatibility: self.show_compatibility_message(message) def get_plugin_title(self): """ Return plugin title Note: after some thinking, it appears that using a method is more flexible here than using a class attribute """ raise NotImplementedError def get_plugin_icon(self): """ Return plugin icon (QIcon instance) Note: this is required for plugins creating a main window (see SpyderPluginMixin.create_mainwindow) and for configuration dialog widgets creation """ return ima.icon('outline_explorer') def get_focus_widget(self): """ Return the widget to give focus to when this plugin's dockwidget is raised on top-level """ pass def closing_plugin(self, cancelable=False): """ Perform actions before parent main window is closed Return True or False whether the plugin may be closed immediately or not Note: returned value is ignored if *cancelable* is False """ return True def refresh_plugin(self): """Refresh widget""" raise NotImplementedError def get_plugin_actions(self): """ Return a list of actions related to plugin Note: these actions will be enabled when plugin's dockwidget is visible and they will be disabled when it's hidden """ raise NotImplementedError def register_plugin(self): """Register plugin in Spyder's main window""" raise NotImplementedError def check_compatibility(self): """ This method can be implemented to check compatibility of a plugin for a given condition. `message` should give information in case of non compatibility: For example: 'This plugin does not work with Qt4' """ message = '' valid = True return valid, message def show_compatibility_message(self, message): """Show compatibility message.""" messageBox = QMessageBox(self) messageBox.setWindowModality(Qt.NonModal) messageBox.setAttribute(Qt.WA_DeleteOnClose) messageBox.setWindowTitle('Compatibility Check') messageBox.setText(message) messageBox.setStandardButtons(QMessageBox.Ok) messageBox.show() spyder-3.2.6/spyder/py3compat.py0000664000175000017500000001711113224121062017413 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ spyder.py3compat ---------------- Transitional module providing compatibility functions intended to help migrating from Python 2 to Python 3. This module should be fully compatible with: * Python >=v2.6 * Python 3 """ from __future__ import print_function import operator import os import sys PY2 = sys.version[0] == '2' PY3 = sys.version[0] == '3' #============================================================================== # Data types #============================================================================== if PY2: # Python 2 TEXT_TYPES = (str, unicode) INT_TYPES = (int, long) else: # Python 3 TEXT_TYPES = (str,) INT_TYPES = (int,) NUMERIC_TYPES = tuple(list(INT_TYPES) + [float, complex]) #============================================================================== # Renamed/Reorganized modules #============================================================================== if PY2: # Python 2 import __builtin__ as builtins import ConfigParser as configparser try: import _winreg as winreg except ImportError: pass from sys import maxint as maxsize try: import CStringIO as io except ImportError: import StringIO as io try: import cPickle as pickle except ImportError: import pickle from UserDict import DictMixin as MutableMapping import thread as _thread import repr as reprlib import Queue else: # Python 3 import builtins import configparser try: import winreg except ImportError: pass from sys import maxsize import io import pickle from collections import MutableMapping import _thread import reprlib import queue as Queue #============================================================================== # Strings #============================================================================== def is_type_text_string(obj): """Return True if `obj` is type text string, False if it is anything else, like an instance of a class that extends the basestring class.""" if PY2: # Python 2 return type(obj) in [str, unicode] else: # Python 3 return type(obj) in [str, bytes] def is_text_string(obj): """Return True if `obj` is a text string, False if it is anything else, like binary data (Python 3) or QString (Python 2, PyQt API #1)""" if PY2: # Python 2 return isinstance(obj, basestring) else: # Python 3 return isinstance(obj, str) def is_binary_string(obj): """Return True if `obj` is a binary string, False if it is anything else""" if PY2: # Python 2 return isinstance(obj, str) else: # Python 3 return isinstance(obj, bytes) def is_string(obj): """Return True if `obj` is a text or binary Python string object, False if it is anything else, like a QString (Python 2, PyQt API #1)""" return is_text_string(obj) or is_binary_string(obj) def is_unicode(obj): """Return True if `obj` is unicode""" if PY2: # Python 2 return isinstance(obj, unicode) else: # Python 3 return isinstance(obj, str) def to_text_string(obj, encoding=None): """Convert `obj` to (unicode) text string""" if PY2: # Python 2 if encoding is None: return unicode(obj) else: return unicode(obj, encoding) else: # Python 3 if encoding is None: return str(obj) elif isinstance(obj, str): # In case this function is not used properly, this could happen return obj else: return str(obj, encoding) def to_binary_string(obj, encoding=None): """Convert `obj` to binary string (bytes in Python 3, str in Python 2)""" if PY2: # Python 2 if encoding is None: return str(obj) else: return obj.encode(encoding) else: # Python 3 return bytes(obj, 'utf-8' if encoding is None else encoding) #============================================================================== # Function attributes #============================================================================== def get_func_code(func): """Return function code object""" if PY2: # Python 2 return func.func_code else: # Python 3 return func.__code__ def get_func_name(func): """Return function name""" if PY2: # Python 2 return func.func_name else: # Python 3 return func.__name__ def get_func_defaults(func): """Return function default argument values""" if PY2: # Python 2 return func.func_defaults else: # Python 3 return func.__defaults__ #============================================================================== # Special method attributes #============================================================================== def get_meth_func(obj): """Return method function object""" if PY2: # Python 2 return obj.im_func else: # Python 3 return obj.__func__ def get_meth_class_inst(obj): """Return method class instance""" if PY2: # Python 2 return obj.im_self else: # Python 3 return obj.__self__ def get_meth_class(obj): """Return method class""" if PY2: # Python 2 return obj.im_class else: # Python 3 return obj.__self__.__class__ #============================================================================== # Misc. #============================================================================== if PY2: # Python 2 input = raw_input getcwd = os.getcwdu cmp = cmp import string str_lower = string.lower from itertools import izip_longest as zip_longest else: # Python 3 input = input getcwd = os.getcwd def cmp(a, b): return (a > b) - (a < b) str_lower = str.lower from itertools import zip_longest def qbytearray_to_str(qba): """Convert QByteArray object to str in a way compatible with Python 2/3""" return str(bytes(qba.toHex().data()).decode()) # ============================================================================= # Dict funcs # ============================================================================= if PY3: def iterkeys(d, **kw): return iter(d.keys(**kw)) def itervalues(d, **kw): return iter(d.values(**kw)) def iteritems(d, **kw): return iter(d.items(**kw)) def iterlists(d, **kw): return iter(d.lists(**kw)) viewkeys = operator.methodcaller("keys") viewvalues = operator.methodcaller("values") viewitems = operator.methodcaller("items") else: def iterkeys(d, **kw): return d.iterkeys(**kw) def itervalues(d, **kw): return d.itervalues(**kw) def iteritems(d, **kw): return d.iteritems(**kw) def iterlists(d, **kw): return d.iterlists(**kw) viewkeys = operator.methodcaller("viewkeys") viewvalues = operator.methodcaller("viewvalues") viewitems = operator.methodcaller("viewitems") if __name__ == '__main__': pass spyder-3.2.6/spyder/otherplugins.py0000664000175000017500000001005413224121062020216 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Spyder third-party plugins configuration management """ import os import os.path as osp import sys import traceback # Local imports from spyder.config.base import get_conf_path from spyder.py3compat import PY2 if PY2: import imp else: import importlib USER_PLUGIN_DIR = "plugins" PLUGIN_PREFIX = "spyder_" IO_PREFIX = PLUGIN_PREFIX + "io_" def get_spyderplugins_mods(io=False): """Import modules from plugins package and return the list""" # Create user directory user_plugin_path = osp.join(get_conf_path(), USER_PLUGIN_DIR) if not osp.isdir(user_plugin_path): os.makedirs(user_plugin_path) modlist, modnames = [], [] # The user plugins directory is given the priority when looking for modules for plugin_path in [user_plugin_path] + sys.path: _get_spyderplugins(plugin_path, io, modnames, modlist) return modlist def _get_spyderplugins(plugin_path, is_io, modnames, modlist): """Scan the directory `plugin_path` for plugin packages and loads them.""" if not osp.isdir(plugin_path): return for name in os.listdir(plugin_path): # This is needed in order to register the spyder_io_hdf5 plugin. # See issue 4487 # Is this a Spyder plugin? if not name.startswith(PLUGIN_PREFIX): continue # Ensure right type of plugin if is_io != name.startswith(IO_PREFIX): continue # Skip names that end in certain suffixes forbidden_suffixes = ['dist-info', 'egg.info', 'egg-info', 'egg-link'] if any([name.endswith(s) for s in forbidden_suffixes]): continue # Import the plugin _import_plugin(name, plugin_path, modnames, modlist) def _import_plugin(module_name, plugin_path, modnames, modlist): """Import the plugin `module_name` from `plugin_path`, add it to `modlist` and adds its name to `modnames`. """ if module_name in modnames: return try: # First add a mock module with the LOCALEPATH attribute so that the # helper method can find the locale on import mock = _ModuleMock() mock.LOCALEPATH = osp.join(plugin_path, module_name, 'locale') sys.modules[module_name] = mock if osp.isdir(osp.join(plugin_path, module_name)): module = _import_module_from_path(module_name, plugin_path) else: module = None # Then restore the actual loaded module instead of the mock if module: sys.modules[module_name] = module modlist.append(module) modnames.append(module_name) except Exception: sys.stderr.write("ERROR: 3rd party plugin import failed for " "`{0}`\n".format(module_name)) traceback.print_exc(file=sys.stderr) def _import_module_from_path(module_name, plugin_path): """Imports `module_name` from `plugin_path`. Return None if no module is found. """ module = None if PY2: info = imp.find_module(module_name, [plugin_path]) if info: module = imp.load_module(module_name, *info) elif sys.version_info[0:2] <= (3, 3): loader = importlib.machinery.PathFinder.find_module( module_name, [plugin_path]) if loader: module = loader.load_module(module_name) else: # Python 3.4+ spec = importlib.machinery.PathFinder.find_spec( module_name, [plugin_path]) if spec: module = spec.loader.load_module(module_name) return module class _ModuleMock(): """This mock module is added to sys.modules on plugin load to add the location of the LOCALEDATA so that the module loads succesfully. Once loaded the module is replaced by the actual loaded module object. """ pass spyder-3.2.6/spyder/tests/0000775000175000017500000000000013225025007016266 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/tests/test_dont_use.py0000664000175000017500000000362413156676663021553 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) import os import re import codecs import pytest root_path = os.path.realpath(os.path.join(os.getcwd(), 'spyder')) @pytest.mark.parametrize("pattern,exclude_patterns,message", [ ("isinstance\(.*,.*str\)", ['py3compat.py'], ("Don't use builtin isinstance() function," "use spyder.py3compat.is_text_string() instead")), (r"^[\s\#]*\bprint\(((?!file=).)*\)", ['.*test.*', 'example.py', 'binaryornot'], ("Don't use print() functions, ", "for debuging you could use debug_print instead")), (r"^[\s\#]*\bprint\s+(?!>>)((?!#).)*", ['.*test.*'], ("Don't use print __builtin__, ", "for debuging you could use debug_print instead")), ]) def test_dont_use(pattern, exclude_patterns, message): """ This test is used for discouraged using of some expresions that could introduce errors, and encourage use spyder function instead. If you want to skip some line from this test just use: # spyder: test-skip """ pattern = re.compile(pattern + "((?!# spyder: test-skip)\s)*$") found = 0 for dir_name, _, file_list in os.walk(root_path): for fname in file_list: exclude = any([re.search(ex, fname) for ex in exclude_patterns]) exclude = exclude or any([re.search(ex, dir_name) for ex in exclude_patterns]) if fname.endswith('.py') and not exclude: file = os.path.join(dir_name, fname) with codecs.open(file, encoding="utf-8") as f: for i, line in enumerate(f): for match in re.finditer(pattern, line): print("{}\nline:{}, {}".format(file, i + 1, line)) found += 1 assert found == 0, "{}\n{} errors found".format(message, found) spyder-3.2.6/spyder/tests/__init__.py0000664000175000017500000000050213156676663020423 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Copyright (c) Spyder Project Contributors # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Tests.""" spyder-3.2.6/spyder/images/0000775000175000017500000000000013225025007016371 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/images/qt.png0000664000175000017500000000341513026261006017526 0ustar carloscarlos00000000000000PNG  IHDR szz cHRMz&u0`:pQ<bKGDIDATXý{XYdz>.6m$ 2ݦ biH5]uq)R&,6Ii ᑄ],Z )T3559eI"{}~sy?~{Р{Ҁ>ЎiTb@p~AO`=u xS>4ȹr ANVEv,o`WO9i#o9k #o:7[_A@cIM J?Z{M#xYLAvl]N?qɾpmƐdӤ[@4+_y$DHGcF#31'Ӏig9&mmJs󄘞<x"Wj8};o$/W&9ϰ@X#^3 C R#-ʰxC;Q hPɱp25%Շ~ؘ·)k0s#"RI5ߖZ#.c ~ZP5ηRUoH~FJЁ{|ft, *BD$`~,4<¼<IIKXë$5Ȏ"NZKA`J^kؠ2ЊL0y0X/ߌf]f̖+lu̵\v"ܙe ӰqW$+XulЇuw XFLf}{Bج̸@6hUʀ"yPDNc}'$ԦU0qP-qeklj!KLZ4~Eokii766>~.?+}ABҌԐׇpp9.g044C8 n݇M[M mP\.\56panlujiCeXS[Ϸ+m Zq~+`/&۰ sMrS\KOYն` j=\+btFJNos5@Mkyw͌el{0Wj,CNcWuXGUXD!a{̹OtyhievD'n(/! J")}URb\ y`;w|1㽣=\ AO;{`JqJ-W,Sa` lW#lM >~:@pB OG ^灒*p29nL[K%OhFiCj;L/ws"T*e(PC9{LhAt,+.?Ga8{[;:J)3S݁;w\ -@;|.}5]NTt(gy.huuu}QCms^_bOpsss!w{A d2BdKt3 :f5H?'vR=:;$e9@d]Lz"L m It' /3mם{Q҇NdtvP\.Zc>?d >艫^sss>JgK$$uh"&N5X,nS8Gm>k_]/ lIENDB`spyder-3.2.6/spyder/images/splash.svg0000664000175000017500000102763613224740762020436 0ustar carloscarlos00000000000000 image/svg+xml spyder 3 spyder-3.2.6/spyder/images/qtlinguist.png0000664000175000017500000000344713026261006021312 0ustar carloscarlos00000000000000PNG  IHDR szz cHRMz&u0`:pQ<bKGDIDATX{Pyc;:,KJsڡXk~EThRڐ.8sBD˸˭Ūoyu#vߙ|~=UR>Lz\-vXS^? 4]bR@)5jN/JI9f!t 4<`Ҝe+GcE"j"U *؁}8øqeIo|J 1LqvOaU!r7EӮ՛ 2Wt2.1`7H'HR'&\4LLėCbYrJDŸʙ R(암LG<#8e >ghPif{`ww)%SPro,]; r:(ۇKWfm  8 U"u2B1}OX)eA(8y+ē$u,cb"w%]9uO&n?9>7jJ.oyeհgM)5Q[G19dc!q*l^@Dhd/p)ais4}n ڪ;8Y6.#DË%ςȞ {C)NjO8]8 :^zpNC“l ,ضeV9roBYO,MF2gM&34#HJS[h՛{ȱXQmdMU$G5zxsa'bYxv[>+މ8SGM1잺L=͇oՖÞ"U*0M؊Oʾ?m|<;=aE+; *X,½xwcS0y*^St\;ӷSZn%vU-8a -$٤Ol.Z-Jn@g*8#j.ҹע! pl4v (NJ^NCC]zl^v9:,mύ9!}0v3*߬nU8l B;k؀>:% & ŌYRHMsDG{Pr9&XDhhH8mZYў*H?׵<{aۏоk2W'>Ʉ"rhO5d=y!Z4c奏9w^ t7#۪xpDɂ}<=꘹ mm\-8V&ͪlE5Xx`<{il|4j]8GFnmg~.ׄPwL6|:8qtS,댇V6%Թ.tia.#L!bJt ~4#&/臩aWϊQM]Nb't$=#bQd99̽pyF!Bptu})Kl>E&^kk'=%hnb}T1D4xj830kޣNfEOHIA̷"CGKQuZ)$er@75@k?IENDB`spyder-3.2.6/spyder/images/pythonpath.png0000664000175000017500000000245713026261006021305 0ustar carloscarlos00000000000000PNG  IHDRw= cHRMz&u0`:pQ<bKGDIDATHǵ]l33]{lCG`(7D ~BPTrEzEP+JAABHH.?U%_D%Xv:&z;3|_/VvT8W9yGSA6 rƐ^gǍg4 ?!)滻Fٰ/̀Bwx{Oxk>ӵ5{{Bd{1VS .G߭ql*pı@nğ+7Ք喐 CCdo3V3]'-.8XT@ UD+jbn)pNq "J uWy6џbadtcϽRJ +ڋumH^_ =}`nim1S JjթɅdr!'O1(VX86Oj^7F/iΛC9ik DA2~vW ~cH}UvD *-X Mmđ$%j9(oXMj}/5zCdԒ3<4@q@>CV[RsDX[n~68?䟾bm'B+D|C%Tj)zm:536WەI4uBbU8QRZlئ󽽥A*oTފ vFQ-pzfOrrݡlA~|Yo Mq(%L<e X箱(?>Y xё+ғ\)6\ xᥗ=t9)6s(>yoarcOd=z/6sK= ~=- *lp _5}IENDB`spyder-3.2.6/spyder/images/spyder.png0000664000175000017500000001051713026261006020411 0ustar carloscarlos00000000000000PNG  IHDRddpT cHRMz&u0`:pQ< pHYs 1 1yWBbKGDIDATx] NȬ%SJRk*rMsI!ɔH 2dhC5=^w~q}9g ׵ow;{|aݓA$ ++{ffwNȃ7o|܋0>%2RnV%8Yh6222%Bhe20C@H"?-B\I??`lP 'N@Ȅ|]0!r/4}W8WKY4kܠ[n5^n)*&c}ec>߿?؀G} Ķl"C9\G S٤IVvmɀ(R6q S&3޽{={>xIcr!vF4s>7nd|駺vYvW_}eD_aMzo2://YS2^uvE]˾fݺuF$r΄ L![^=㻝;wzJȂ te 4Aډ'H9 LBngtNDEEe>&&F79^ѱcG1x`ݵHYVP'aÆ߶moPP/ٵk?f+?Vc@J߰ DG4Ǐ&[@pO>DNjjT_&:ahׯ_g۷ xѺkGA~y];ϷmddPDVqp(Ք}Co]%ۀ%56mڔ]p_S 9BSӧaÆ}& ጭСCm&}TL )BCUT7o,:u5Bvءݻח_~ifehPGJ!@ɓ'O*+j | Ž=׬YcDA%D=׉:l2u (zi.Z}=jDqB`2[vcǎu,i曊}ĉlʕB˗V`h@ʏA!niΚ5琵i܂?3ib'|F8(:ɢlݺ_n]o>֦ME[9s&۸qr&aV-[ns1ja!Du:%ӧo9@]$VA{G-k1~?:C4o\1@?~b駟YܸqCu]"=s7g:Bg(>B~!I&)>mq lٲe( 톶3gXe'{M6)gא!C _dx2tu ?t?)v`N rkOJOG⊺j6viՊNٳgS*uh8\ajh+,]!Ç IoaP&EḓP~f@~#;#=nBĴ 2Ȯ# PIBaMj{Ѯ)jBn@F >$(dڴi *wpA2Ij[Qj"wŊiAd{O Ӛڳ"fQ|XF3"l$ڶնڻM2~00wAƙeY)d"%bqYeؐdI?Mhq$:])dT)6!D/m lT~^J7I0%6Ǥn+ RϷȚ5kX֯_ۢ@"k=(N I'Wqu"ݴ4%#pai2<;9v($:YRbi˳"Pqqq9tS2JfYM*˼ Y@`RȨQ/2DxMDR|G[XYSIw] ޯ'w. 4:1#܊Q)!huV ^2A=t #o[DIf`e_ j7c^ȋV9IM|I0 ђbH+δqcG#mWy ɠħrDѓ IJ|V2*iWҒǘ_VUKՏg.,P:&Xy[,֭́[]2NR:AVXJJ0_%)%#HO'B'd{쵷P0;6DbŔAgVQJQ+P_DLEU`b^?[14!E EO|&%mm2<ɤ2Vhw0Q'/ȐUvZSf?ɐ2P'F@l+U5xUa(Iԓ ! 9H2dup>|XIP"Gl7!e˖F}o@| SS2Ν1::Z*1My&mRKwqݠE$SLvٳJ$ oFwc?rݡ<|NL2>e[!2TӊJ32ƌ#!Lˑ%KbpB-1"N !9LH|ahHڑt/!D1KiǰR0aTD#b~}NʱcrZm%+)|,|ށ~ *&b4sw U xv$Q2- %>V>7Ӟ懶?Ds)v^ hu^!Ф#ש#͹잲9Me {@2ƚO1[̾,L}٤3B2OnnFIE@2ɴ~vF!a2 [`3DȮJTJue^pQ%AV[_Sb5Χ1Wwkb/?kw;ee#K2BI"`,\6UaC]}_JP9*[ \(b9.H6(<w`UD쥉yڃm4}1*$?|AHG!-_ܬZ4p.}4|jC@S֖"=vȌ녠`^=/_p YIDIaːt(*\54&s2Hk/EBi!GbϽ`(;d Sߩ Wx>3: Aw_k==^zߢRjw \oJNi>)&oQ)sʄfWK;zq4Brv)O;e.[v$tsd|[ƽjc-H+v59|5vAjnu8t憁ۤ$H%_̠'gT_/yJ Ay o^d T2YOH)|/;>r c٦$:ӒUR iذvaE {/P>z1sb_E)'R$ ai+Èn<7ZpwkCGWIÜ9^p !3dwy?wEО3ʭsTW՟ɽֿ#z?"nط_jKXXVU0oy BH䱳q *D2<|$&:-\F4knk#"DPj` Zu6 =+dFr*mư 'BS~kC#_C/42IENDB`spyder-3.2.6/spyder/images/italic.png0000664000175000017500000000027213026261006020345 0ustar carloscarlos00000000000000PNG  IHDR7 cHRMz&u0`:pQ<bKGD̿GIDAT(c`|@?80t#s0x3lů@!7f4 ovB> 3g@ i^IENDB`spyder-3.2.6/spyder/images/chevron-left.png0000664000175000017500000000032113026261006021467 0ustar carloscarlos00000000000000PNG  IHDR w&IDATx}1qoed{5q D@չ:&C8nfZTy7y3Q/IT G\ F C,18æ)N#Ŷ/(5|dbWk&2TaC b2p0ZpIENDB`spyder-3.2.6/spyder/images/filetypes/0000775000175000017500000000000013225025007020375 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/images/filetypes/pot.png0000664000175000017500000000167013026261006021711 0ustar carloscarlos00000000000000PNG  IHDR(-SgAMA7 cHRMz&u0`:pQ<:PLTEnananananananam`nanai]fZbWnana]SYOnaSJnanaMFIBnaC=na>9na95m`5~1j^2z/fZ2z/aV]S2z/2z/WNRIMF2z/2z/GAC=?:2z/2z/:6734}12z/2z/2z/2z/꺾ŴŰ׽צ،ίϵ֢ԡΪđɇׇɯսzﵬݍׄ˵ߔ篵ޘ뵧ﱩɍgsނqzБȈ쳢⛍ꝷngvMe]l~sۥ؁mw忧]`ئ?wFjPYlc}slѐ^^zѯmĴ_W{gZ鰐ԃܿV\CCRbveآגޠpƄШ\WJGWeytiqnm[NXfxgZܦvיy~¼j`hY{gp讠}xx̀ڠzfś³þҰ~ :9tRNS=H bKGDLoIDATW1JCQg^>w%E܀ ,d 6b*2,҈-(i"Oi sg ߭oAF^ e|?_WݩCPUg4}MŹʼn#D)ϙ ԕ堵^`^krf~Wt3zGuE IENDB`spyder-3.2.6/spyder/images/filetypes/bat.png0000664000175000017500000000112113026261006021644 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FPLTEffg333``aߓ???SSS"""234UUU]]]Ƈ'''xyy]]]芊xyzJJK񻼾^_` ijkWWWvwy 9mp9tRNSp/pGg&EOg΀4somlf4'7&)&gbKGDH pHYs  IDATM@gv7vw 0ce& My}$AY(!Rꎢ`bqe4DLt>`2Yr`%|v%\S%NQi4z3v\xCƓ Vj fdEIENDB`spyder-3.2.6/spyder/images/filetypes/cl.png0000664000175000017500000000054113026261006021501 0ustar carloscarlos00000000000000PNG  IHDR7 cHRMR@}y<s߯IENDB`spyder-3.2.6/spyder/images/filetypes/properties.png0000664000175000017500000000074013026261006023300 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FPLTEYtRNS@fbKGDH pHYs  IDATAJP?P1.t/ŕ  5iByD@/$n*dUhIlG [(LPMŅs>+##-(緊:Z00tizRB) 6m^x= ^&INQ zV,xBܰ"r[+ 2- 6&vygC-x<S#5֗&2p`h>(80$,faT[u@gk}u~IENDB`spyder-3.2.6/spyder/images/filetypes/tar.png0000664000175000017500000000116713026261006021676 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_F}PLTE۴ؽ}ڹq׳lĉԮƉ}}φɃҸwҳrήnհpҊߺzܹ{XXSUƣbʭl˪i̫kO}BiV-KؿVY\^A~f3p[,}?жDJMOx8zb+m/}8ŗ}Iv{9ttpiddddddH\ddddddDO~aMdddddd@~v?ddddddA 6Nʧ{f !o-蚍SɺyM˼`͹|;ӼWf?ۑI ^ ףKƃTTbKGD IDAT=KB@{EGA>C(P$" --AE B R!@HZ1n-# 0N@xĹ!~/0pP%vhp?`޲ Eڪ:sC5/`6MͮjV0Q=[|jܝǻUmX5Nz] ؗPU Kՙ0M2Kd5AųGIENDB`spyder-3.2.6/spyder/images/filetypes/cfg.png0000664000175000017500000000074013026261006021643 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FPLTEYtRNS@fbKGDH pHYs  IDATAJP?P1.t/ŕ  5iByD@/$n*dUhIlG [(LPMŅs>+##-(緊:Z00tizRK> *4t334H.?2"3`04&CbKGDf |dIDATW]ʡAaw|gC%h6c3&$BRw!*`Gs,IENDB`spyder-3.2.6/spyder/images/filetypes/zip.png0000664000175000017500000000116713026261006021712 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_F}PLTE۴ؽ}ڹq׳lĉԮƉ}}φɃҸwҳrήnհpҊߺzܹ{XXSUƣbʭl˪i̫kO}BiV-KؿVY\^A~f3p[,}?жDJMOx8zb+m/}8ŗ}Iv{9ttpiddddddH\ddddddDO~aMdddddd@~v?ddddddA 6Nʧ{f !o-蚍SɺyM˼`͹|;ӼWf?ۑI ^ ףKƃTTbKGD IDAT=KB@{EGA>C(P$" --AE B R!@HZ1n-# 0N@xĹ!~/0pP%vhp?`޲ Eڪ:sC5/`6MͮjV0Q=[|jܝǻUmX5Nz] ؗPU Kՙ0M2Kd5AųGIENDB`spyder-3.2.6/spyder/images/filetypes/rej.png0000664000175000017500000000034513026261006021665 0ustar carloscarlos00000000000000PNG  IHDRR cHRMz&u0`:pQ<PLTESiItRNS@fbKGDaf}EIDATc`FA``TRRRRRd`TTRDQ6V26BQqRrQBQ  E R EQ ll jZIENDB`spyder-3.2.6/spyder/images/filetypes/tex.png0000664000175000017500000000077113026261006021710 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FPLTEQNN\YYںHEFEABSPQ<9:ZWX|zzܠ򝛜dabԾjgh~~YVWzxyRtRNS#bKGDH pHYs  IDATJBQ?Y-ZTPAQᢔx͔!Xj BH75J P޵cPHM'~~d2K:8iMֳ}^*IX=P?I/FKVE_}}~@zՂ7\ϱ26 Űh?PBqIENDB`spyder-3.2.6/spyder/images/filetypes/ps.png0000664000175000017500000000103213026261006021521 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FPLTE籲nnn}}}VUVIFFzz{212=:;߹͛OdtRNS#bKGDH pHYs  IDAT.DAgDRlTD4F޻!b+)$T=QB׿q M֭h$9T8ME#Ӳ%yŕ!|y'(sÏEo3;<+##-(緊:Z00tizR~?qAkGiDDDhvftpsqwtCgEc}888cccfffӡ=sAmChEd}Ge}S;;;P_NbgarnEt@nBiEd~Fd}GHIIIKZH[gYli;z=uqv>3CCCI~c`VK@58NNNSaQQiN^{ZѤEoaXMB70JJJNQMHRGMZKjwhaZFFFHHHGGGBBB_QF4JZGGMFPlLMaKRmNPhLS=?EWCFUCKeGI]GNlIJ`F<<<===999555㤇tRNSBCAbKGDaIDAT++Y\1,J-6S&It閛r,/0`>pD_a$Jw|: ן <$l<-ZVq,`zfr~W8:kc.8M8?oG,6PV㭷ĸ"MW.{2$IENDB`spyder-3.2.6/spyder/images/filetypes/jpg.png0000664000175000017500000000077613026261006021675 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_F&PLTE]dbdcefegfhbgkmlnomqrqksyxy{x}~~z}SGqqptcev:DLe`NPV@8+!^gosNSYXkE@V`8?U(2?7QvsMGP1"64#,tPg:1?bM]@C*chBxpx~TdqQQWAQXHjNU5OSBAtRNS@fbKGDH pHYs  8IDATWc` XPE! 3BIK (J@v  ېIENDB`spyder-3.2.6/spyder/images/filetypes/jl.png0000664000175000017500000000127213026261006021512 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz&u0`:pQ<)PLTExx Puqux{}~{yyy{}wz|tyz z{|yMpNr l ZQxWT{Pt Sy^]^WOt IyX]Pv IzQu Sz]XOt OsSzU|PvbtRNS ΦקDtWs6(E +se*tg)35.yA<|bKGDb+< pHYs  IDATNQ@9GRKkqW$/@  M,k@`S XXy汩> 庪o:˩|m䶪^zE{ö6i1Y,~qcWv{= B*Jpl(IENDB`spyder-3.2.6/spyder/images/filetypes/ui.png0000664000175000017500000000174113026261006021523 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz&u0`:pQ<UPLTE8R vRy3L Lq*!uW8R "13&|Kn!1x x*u'!1oh׶hMKFh FCB꭫Ud3B8Ђ,/"2]/&Gk>D)y[6Ca [=Y #3 |W?%6Cc JJLѝS=kb<#34OsKRMKG?PsS[^^VSURDR`g|lebccVI[|nYalwWNr6PsqsKFx{lXiLMr!4NMO0Yc=JB[9n}@z,&426t2u.3CE8FK4|Ns"^p)%l%%+,#$%Lkon96%Wl OeD[JT.tlJR"# YLX.ɀ v zYtRNS?֮zM4ѳ}R)ץECS$kؔԫ6Q"b3@ڬ{ WbKGDzIDATEMP@{?g&ЦaZ:*V0  ) 17`H"~JbsfS,OzVu֙>f u ޑsoPT5n'u]G0wVګ*fPܹ#z?]zj ut߭H/[~zo!4XIENDB`spyder-3.2.6/spyder/images/filetypes/tif.png0000664000175000017500000000077613026261006021677 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_F&PLTE]dbdcefegfhbgkmlnomqrqksyxy{x}~~z}SGqqptcev:DLe`NPV@8+!^gosNSYXkE@V`8?U(2?7QvsMGP1"64#,tPg:1?bM]@C*chBxpx~TdqQQWAQXHjNU5OSBAtRNS@fbKGDH pHYs  8IDATWc` XPE! 3BIK (J@v  ېIENDB`spyder-3.2.6/spyder/images/filetypes/xml.png0000664000175000017500000000114313026261006021702 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_F2PLTE\-+FL2ub77 d`wg?gHo[;Hg㜡+&*P&#'ůjk k,|_6քF)8nd$.L,|G7KSToU!M YD*NlZtZ b&r[Uo!ƬyaoDKYIENDB`spyder-3.2.6/spyder/images/filetypes/log.png0000664000175000017500000000120513026261006021662 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FSPLTE4(( 'WJ q0HKA?䫪$$*aQK+0e69ȱ("5n in%%իD,A"㳰6a=U ݿ$3,)߰UMg! ױ6HEA଩*ntRNS@fbKGDH pHYs  IDAT5J䷒@ } *ؔ42V\,b&&}g@Yq4g1QMfwU)-}VNau!+[mVN]xԥl)~޽}v NY5IENDB`spyder-3.2.6/spyder/images/filetypes/nt.png0000664000175000017500000000112113026261006021517 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FPLTEffg333``aߓ???SSS"""234UUU]]]Ƈ'''xyy]]]芊xyzJJK񻼾^_` ijkWWWvwy 9mp9tRNSp/pGg&EOg΀4somlf4'7&)&gbKGDH pHYs  IDATM@gv7vw 0ce& My}$AY(!Rꎢ`bqe4DLt>`2Yr`%|v%\S%NQi4z3v\xCƓ Vj fdEIENDB`spyder-3.2.6/spyder/images/filetypes/f77.png0000664000175000017500000000053513026261006021511 0ustar carloscarlos00000000000000PNG  IHDR7 cHRMz%u0`:o_FbKGD̿ pHYs  IDAT(m1JD1dX(؈Zو`a{ /T<7-;_bޓ/$L$Qܾ(3pyQ\ͭBjy3EY !J#Nqfj}9r(+F>);Ґ6!Tʣ'} [c(vv{3TƱ6pUŃ!d-؊7>%acbh%BqBB+=*SCؔ 1Dn뾺~P"B 9IENDB`spyder-3.2.6/spyder/images/filetypes/enaml.png0000664000175000017500000000170313026261006022200 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz&u0`:pQ<PLTEdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddJFA{9ttpidddddd_iqx~oaddddddZm{`inpvnefeffezvcjibdddddddddddddddC{s?dddddddddA 6Nʧ{f o-蚍ñѿ|1;ӼWf?ۑI ^ ףKƃhsbKGD6 pHYs  IDAT1(RR2t$) 2(Bd ,6b )%FJ$aQ)dxO$/I$)jO" XʦO-Ihnk^ S92級pc9#xӟ( >+gC]S.%r^O &`˭$1)'s}YPdYU~ښ$e+;o'4IENDB`spyder-3.2.6/spyder/images/filetypes/diff.png0000664000175000017500000000034513026261006022015 0ustar carloscarlos00000000000000PNG  IHDRR cHRMz&u0`:pQ<PLTESiItRNS@fbKGDaf}EIDATc`FA``TRRRRRd`TTRDQ6V26BQqRrQBQ  E R EQ ll jZIENDB`spyder-3.2.6/spyder/images/filetypes/po.png0000664000175000017500000000174413026261006021527 0ustar carloscarlos00000000000000PNG  IHDR(-SgAMA7 cHRMz&u0`:pQ<PLTEnananananananam`nanai]fZbWnana]SYOnaSJnanaMFIBnaC=na>9na95m`5~1j^2z/fZ2z/aV]S2z/2z/WNRIMF2z/2z/GAC=?:2z/2z/:6734}12z/2z/2z/2z/꺾ŴŰ׽צ،ίϵ֢ԡΪđɇׇЦիܐۋ׎ɯսzﵬԜٕmmDŽ˵ߔ篵ޘ뵧ﱩэՋfgq֚sނqzБȈ쳢⛍ꝷnfugvMfMe]l~sۥ؁mw忧]l‹ڸ`ئ?wFjPYlc}slѐ^^SnzѯmĴ_W{gZ鰐ԃܿV\[KCCRbveآגޠpƄШ\WVQJGWeytiqnm[[XNXfxgZܦvיy~¼jie^j`hY{gp讠}xx̀ڠzfś³þҰ~&]9tRNS=H bKGDHzIDATWcdF(b30p2622~ 1T0`| dΈ߲0 03Jx2",L|(L`TaOcd쎿w4Wed\|;- @6<@<֧%IENDB`spyder-3.2.6/spyder/images/filetypes/hpp.png0000664000175000017500000000054413026261006021675 0ustar carloscarlos00000000000000PNG  IHDR7 cHRMz%u0`:o_FbKGD̿ pHYs  IDAT(uѭNCAgړ40LB(  !j$ SYk$|7Hn?,E4w|\l錻LB ,З!JEHCѰV*jAdlȣ 'R%\ԛ}39ǯ—O/<; &N+C#M^cW+!U6u͘OPWaЫM&ZuY::DNIENDB`spyder-3.2.6/spyder/images/filetypes/ini.png0000664000175000017500000000074013026261006021663 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FPLTEYtRNS@fbKGDH pHYs  IDATAJP?P1.t/ŕ  5iByD@/$n*dUhIlG [(LPMŅs>+##-(緊:Z00tizR 9у{DY?I]$ lr" %;y<6\Y*?Oz IENDB`spyder-3.2.6/spyder/images/filetypes/hxx.png0000664000175000017500000000054413026261006021715 0ustar carloscarlos00000000000000PNG  IHDR7 cHRMz%u0`:o_FbKGD̿ pHYs  IDAT(uѭNCAgړ40LB(  !j$ SYk$|7Hn?,E4w|\l錻LB ,З!JEHCѰV*jAdlȣ 'R%\ԛ}39ǯ—O/<; &N+C#M^cW+!U6u͘OPWaЫM&ZuY::DNIENDB`spyder-3.2.6/spyder/images/filetypes/f90.png0000664000175000017500000000053513026261006021504 0ustar carloscarlos00000000000000PNG  IHDR7 cHRMz%u0`:o_FbKGD̿ pHYs  IDAT(m1JD1dX(؈Zو`a{ /T<7-;_bޓ/$L$Qܾ(3pyQ\ͭBjy3EY !J#Nqfj}9r(+F>);Ґ6!Tʣ'} [c(vv{3TƱ6pUŃ!d-؊7>%acbh%BqBB+=*SCؔ 1Dn뾺~P"B 9IENDB`spyder-3.2.6/spyder/images/filetypes/pyw.png0000664000175000017500000000147213026261006021726 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz&u0`:pQ<PLTEĿ񫫫̾G=uKx>~?qAkGiݰCgEc}=sAmChEd}Ge}SEt@nBiEd~Fd}GH;z=uqv>3I~c`VK@58EoaXMB70aZ򷳳_QF4S=?⛭t tRNSoICH_'bKGD LIDATM+ٖAAf"qrX:ڙ_ g@jIRJ’mx] n`-+JlBa  ]bQid Lm\r*$O]"2$4< ,?ty,*)6I5ITM`322_,#"#_)?Z$ +s 9676FK6f9:Qd5'^Sq`Vqu;;9GN5p7NW4??=Vo*#++:pbt.<:;[n0?E,s0j4321j6c'-8855=!8FDUp+($-2.`\}% !#'-+$|&&$l(#j=RtRNSHw? %QʲeT]8/[l i oZEdo/TpQDgNsaqnfyh솽|||zzz}}}~~~FttRNS#bKGDH pHYs  IDAT1Na&Px K;m;X e:SĤB6SbD0A $qFIov,c$'%IFC.IEMס~?l{ynV5m'2xU(nL"?&4IENDB`spyder-3.2.6/spyder/images/filetypes/js.png0000664000175000017500000000103113026261006021512 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz&u0`:pQ<PLTE܆Ո֠RŪ甲T:qvԪ哴yՄֲ%bXZϕwQ@y&a,gXNҤh=y\[3oeً璻f5pdH`wrᗸ^յe|m챺ЙѲ여йF&tRNS@fbKGDHtIDATWu10D;k NW=h t(."(t4ҊPř iNj Us\\m !VtRMb2`8.[? x| 5deIENDB`spyder-3.2.6/spyder/images/filetypes/tgz.png0000664000175000017500000000116713026261006021714 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_F}PLTE۴ؽ}ڹq׳lĉԮƉ}}φɃҸwҳrήnհpҊߺzܹ{XXSUƣbʭl˪i̫kO}BiV-KؿVY\^A~f3p[,}?жDJMOx8zb+m/}8ŗ}Iv~?qAkGiݰCgEc}=sAmChEd}Ge}SEt@nBiEd~Fd}GH;z=uqv>3I~c`VK@58EoaXMB70aZ򷳳_QF4S=?⛭t tRNSoICH_'bKGD LIDATM+ٖAAf"qrX:ڙ_ g@jIRJ’mxB) 6m^x= ^&INQ zV,xBܰ"r[+ 2- 6&vygC-x<S#5֗&2p`h>(80$,faT[u@gk}u~IENDB`spyder-3.2.6/spyder/images/filetypes/pxd.png0000664000175000017500000000163213026261006021700 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz&u0`:pQ<PLTEdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddJFA{9ttpiddddddH\ddddddDO~aMdddddd@~v?ddddddA 6Nʧ{f !o-蚍SɺyM˼`͹|;ӼWf?ۑI ^ ףKƃTTbKGD IDAT=KB@{EGA>C(P$" --AE B R!@HZ1n-# 0N@xĹ!~/0pP%vhp?`޲ Eڪ:sC5/`6MͮjV0Q=[|jܝǻUmX5Nz] ؗPU Kՙ0M2Kd5AųGIENDB`spyder-3.2.6/spyder/images/filetypes/doc.png0000664000175000017500000000121413026261006021646 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FMPLTEٿݴ|_ͥ󕡶\p[fKbd}38U<(=3 !H TȹCTtRNS#bKGDH pHYs  IDAT=APH ,k؅&"f m%! e5`zUH:gQg@>. ny;p0U`ΠTgPJ>Hx\D-[JKz=9\Ӗ osŹIENDB`spyder-3.2.6/spyder/images/filetypes/cmd.png0000664000175000017500000000112113026261006021641 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FPLTEffg333``aߓ???SSS"""234UUU]]]Ƈ'''xyy]]]芊xyzJJK񻼾^_` ijkWWWvwy 9mp9tRNSp/pGg&EOg΀4somlf4'7&)&gbKGDH pHYs  IDATM@gv7vw 0ce& My}$AY(!Rꎢ`bqe4DLt>`2Yr`%|v%\S%NQi4z3v\xCƓ Vj fdEIENDB`spyder-3.2.6/spyder/images/filetypes/patch.png0000664000175000017500000000034513026261006022204 0ustar carloscarlos00000000000000PNG  IHDRR cHRMz&u0`:pQ<PLTESiItRNS@fbKGDaf}EIDATc`FA``TRRRRRd`TTRDQ6V26BQqRrQBQ  E R EQ ll jZIENDB`spyder-3.2.6/spyder/images/filetypes/nsi.png0000664000175000017500000000177313026261006021704 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz&u0`:pQ<PLTE|ſ°몡ͻҤ͉ybuwWԮؓĹӣʣֵϥʽظɼനöܷ޿⾷ܱ٤ıµ[R]Tog[TͿ׼br^ͩ߼ݱԮȭqR}umzŅϢ׷ůңܢͿypPȆѨڼӾظ±̪Ǧ¦_bnh²ɴզޑךտϩŦjƧ۽ղ{Xly˭rXɳlg ȷu DT\ϰL]hس׻ŚHtRNS"=H. >K> *4t334H.?2"3`04&CbKGDf |dIDATW]ʡAaw|gC%h6c3&$BRw!*`Gs,IENDB`spyder-3.2.6/spyder/images/filetypes/inf.png0000664000175000017500000000074013026261006021660 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FPLTEYtRNS@fbKGDH pHYs  IDATAJP?P1.t/ŕ  5iByD@/$n*dUhIlG [(LPMŅs>+##-(緊:Z00tizR);Ґ6!Tʣ'} [c(vv{3TƱ6pUŃ!d-؊7>%acbh%BqBB+=*SCؔ 1Dn뾺~P"B 9IENDB`spyder-3.2.6/spyder/images/filetypes/png.png0000664000175000017500000000077613026261006021701 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_F&PLTE]dbdcefegfhbgkmlnomqrqksyxy{x}~~z}SGqqptcev:DLe`NPV@8+!^gosNSYXkE@V`8?U(2?7QvsMGP1"64#,tPg:1?bM]@C*chBxpx~TdqQQWAQXHjNU5OSBAtRNS@fbKGDH pHYs  8IDATWc` XPE! 3BIK (J@v  ېIENDB`spyder-3.2.6/spyder/images/filetypes/tiff.png0000664000175000017500000000077613026261006022045 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_F&PLTE]dbdcefegfhbgkmlnomqrqksyxy{x}~~z}SGqqptcev:DLe`NPV@8+!^gosNSYXkE@V`8?U(2?7QvsMGP1"64#,tPg:1?bM]@C*chBxpx~TdqQQWAQXHjNU5OSBAtRNS@fbKGDH pHYs  8IDATWc` XPE! 3BIK (J@v  ېIENDB`spyder-3.2.6/spyder/images/filetypes/cxx.png0000664000175000017500000000054413026261006021710 0ustar carloscarlos00000000000000PNG  IHDR7 cHRMz%u0`:o_FbKGD̿ pHYs  IDAT(uѭNCAgړ40LB(  !j$ SYk$|7Hn?,E4w|\l錻LB ,З!JEHCѰV*jAdlȣ 'R%\ԛ}39ǯ—O/<; &N+C#M^cW+!U6u͘OPWaЫM&ZuY::DNIENDB`spyder-3.2.6/spyder/images/filetypes/gif.png0000664000175000017500000000077613026261006021662 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_F&PLTE]dbdcefegfhbgkmlnomqrqksyxy{x}~~z}SGqqptcev:DLe`NPV@8+!^gosNSYXkE@V`8?U(2?7QvsMGP1"64#,tPg:1?bM]@C*chBxpx~TdqQQWAQXHjNU5OSBAtRNS@fbKGDH pHYs  8IDATWc` XPE! 3BIK (J@v  ېIENDB`spyder-3.2.6/spyder/images/filetypes/readme.png0000664000175000017500000000121713026261006022341 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FkPLTEؒޮہsYT{X\Qu'O"I#Lq˞)Q(O"K诰)cRq , (r!^ޯ2TN_hT ,k鯰捡>t|'~e*aLzP|%Y~򨪰ٜʴ𦨬@ ftRNS@fbKGDH pHYs  IDATW} Ag6_HH0P  ɹE9<3yFd|A.h[:@y `J}pPPUh*Գ5 8޹FWUKs2{ef&eS7KaYAIENDB`spyder-3.2.6/spyder/images/filetypes/c.png0000664000175000017500000000055113026261006021326 0ustar carloscarlos00000000000000PNG  IHDR7 cHRMz%u0`:o_FbKGD̿ pHYs  IDAT(mѱJ1_Xpq(:9>oQ&uġ>S聄{ܐ]=|ؐ] fY b9@OFC\I@DRJB.{ ͊ͭ[C=t&ٶSU _vK*C.)YhZ֐E[$PgSف&6_+>%ԝ ;d رTr/e *ٺQ/?Da4IENDB`spyder-3.2.6/spyder/images/filetypes/pdf.png0000664000175000017500000000145313026261006021657 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FPLTEgogmTVOO--IIYYSSEECCzz7722KKPPCCnnJJgiBBqr멻 tRNSwmjq.:bKGDH pHYs  IDATWU= Pg^̏A+##-(緊:Z00tizR*xavbiegem?MQUֲ軺1P=A|w^&&&&&R'T8NtNJAi CauU-_6iY|n^td:OaYw.?vvNhΦj?U櫌ڰ "ɡ&0}sytRNSUoO <92i-V=V_޷PQM˯ٷrŸD  'Q;]  c@ 5 bKGDԶwLIDAT(=J@矝͘ V#IJd46V X7+ckE>&43W#5#a]3xug1U ,%1@2WrmCd<#?I<)Hy 0471DM+k릭\(obU[M{&IR$A${I+jxeRl.VY3Aif,IENDB`spyder-3.2.6/spyder/images/advanced.png0000664000175000017500000000154713026261006020653 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz&u0`:pQ<PLTESSS444jjjvvv{{{rrrLLLGGG䎏hhhڣܓ:::AABOOPeff==>555111```SSSIII}}}vwwkkkTTTPPPbbb```ٷѮ潾⳴IKtRNSJC ohߑJP\Cv~omf䕍angft7bKGDHIDATJ&Ar 'q*\+@ AqEšAAQ[SUp_RC.ҨYټL=yͿ\gWlb OSK2|?mzbu8{ۓ5ԋU>y>rxf`GC[4%mEzd7ozWiArA[[[D *h-hs _u/hfZ!AR9 ~߻† -¡@Qq8ol:Kd5n_Tla,\\|um+po$Ƣm 7*F gwwӝ'%)w3)ObE8׮t\߆/D .BSG!s_P+yn% Eg-C/6^p݀4-ܚWrխ6A|]L}02ŅbH c0j"07 տ51NYJ ?'X11P\0::J4Y}Y`м/c hX[!j^zC>:dѱ><ưz1;:$DL J(C`αIENDB`spyder-3.2.6/spyder/images/tour-spyder-logo.png0000664000175000017500000002010313026261006022326 0ustar carloscarlos00000000000000PNG  IHDR cHRMz&u0`:pQ< pHYs UbKGDIDATx]tT֖N @B!b(‹ &bE`y((b{X XQ쨠 bC @!O}N.2sg2 Z{!L;w˷>0""BD"@H!"F8͉Dr뉲DUhb+C5THt8@Z,beVzkRG+maRdưʭ4Ś+5$NZ{pCUxd&$_#=i!S kmذaBQQ]2wڵZl޼)DH{H3ձ OJ6lx̻C>$L>22x+v+5لohڵk@cwgVV +6?@H.}֭{ׯ>Xq?G>E_}}_=|͂-[~Vv f 7}s!7C'wzȬO?t֦M΄\ OoMyoy:/ h K[o^{B0k ;W>%rvb+*YAfw^^x\0BWZђ€"i111-uU~|\ ]؎f[>uy "uH%c۶mVcG˸S'؂zlۑEEIvS}ت@0ҟw$ʃHމ':}ȝON㮻21{5`ppBwqǎrQF _Ě5kRD,A7 `ԖD&c^~!_Ug  Xe*yR2QuDeơ ?c]uYF!㎐)qȶ0`%8gС87tD QfF/tg())J82{d! &RΝ;A7vX-`KwH6 !Ceu435VM8s[nE:oi ^{{W Hf +^?x p 7-Pf#WJ}QơY( ߖu>Z|~/n2e"2[SSSh@ T1bDM);((&N5cAn@wFK0Y`S/:Ю,^11A ; .pLK\77N3j, YZ D`+P!/hbCt8UW@(E'sA(?o&O ^zIO>ٸK|@}@Bщ '2R GߑlG,iMTUޭ[alw${+Km'I'_b #w'n;g^ EϚvDJ@U#9(+lݾ}ǠS!NlD6JHHhJ1R]YAmS)yˢdt%Ѵ2)g 9sEPpz /yaw믍2XCZS_$F ,bt1 z=z_{O)Gl~ƬbFf X /h?C@ԫaQ4F,p%x@Bן[]أMCT@2 2jJ|(.Ne'?FLU:rtA+ri5Eݻ pM=5joMbx9e~ZW`r#Sڶ!j7B_.␞˻v8ʊr)FG[61CYY/5kڮ(1(]ޭ-S_S!ɪ/s|y@p[徴4`' 6L#=_ƺZ7y7mr3q-<kC^@ڂ;qd7Hދ\YPhPɾTLC72f͚=9U ]&7\nh$e;@n3㍤3Kz_y)Lqt ndDZ?aa]j qhCwMn#%v:9rdl͚2nt`;u2~ x{,]{%Z%!ٵ,dbK.R5)%죶|yGd G[ z܂05U= 8P'dlSǓ 70"@ *!3=eW2)[mtI`X': ̝;WXѡ AWOABֺϽݳbG">waܤ+[I<(Au<$rD1΀A^._\$`c:(+3S)WXEys($9~` ?ku]g碋.2oGl9܈@2iv>'sI93AMvmEYwSWLI"J7үnZ1#D-7n7bfN&[@9BףLXr$s]+J_ 0J2hgh'gԩ>.;ςq"C.napUW9 XV{d\Ul)u\!oRM_)Z<&!2Hn ow =ہ%K/A \GD ߄(UT8+0](fw,CzݟL6e*ıǶA@\@;111a16%\$TꢦU``DԷa~d9=;v5%GgOǝBcA BV"*̥s s%$y$X7aڴi =.!@ D FmvxJjUUDΪf,`x  t'ƍRHyvT)ޭ&Πr_^w1x=eJHA!nI|a$FU 7]zV tL 8I"v?3EF KAe#*A{=H* 9DEWjAdۋr7a4T5 aS0Xw5#{*8Ì,َA"%qn'ZJnc| ` F  @@ SۑbMF-G L@̩[4֮.tC8~P 56jhŰl4\H @@?vJv!4U4: #ÖΜv ZtIp+S9?xe"$ '`+z ժf!O?t*8ؗh8 0EKDk;?lzQw6]PaGf1\j<(єsz1#;L ֈ>_`)%%%wPۑ ʷB$?nA ߺ_=rX 5 :ukDX%v@TϋQ^?*F{ P M$\*uŒFr[om4OPr>v<~ʉ&He )S#1YT@2 C/|w\NWKîQ2sV"7*z Um-@R?)i $m-3qS,è-yN*NViqT ;E.%"Y#PvEɓ qZBf0uLm[NF.^\,L]۠9O슏P X7#<LݢoQ*T@PLg2fr`](7ZZ\xᅮ3Up D;״icê-PI=h=h~"$Iu $GPʎ N '[YP35kJ!@Eog y벥k5M%"g`AXm7tz2c zVN%x^@V6UfMI< Id4EQVۯq@ObS"NH4M427nl 9|W{T94Mݙ*I^`$ -JɂٷH⥐H.F,FR(9(F\{J /^*DVᕘкZSDQ? #NL:@44,<;;!T@0 L9^VpW" 1?JvZ+TBO誱7Pxrr8S̃xқC)(x֩SI8MnnL)䋹}z.\ӑݠ:{@ᚅ+.]pz7`j7s5d' <-80k\ґ)=pZ J>~Iaa#֔>x"?9^ l|Ft6zGm" 5p}vHiciOX&p@~껰q-c>oBZq Kkwyқ'-9Ւݖ6|Q-"29 ҘI\L͛ nI7f$V|,0wd߄)=u҂Ry'NR ve;A[L Ox60O1(,'u P!O$6 BgWvo%\|y 1 2ݜoא(!K"OpKr2-%sxY4-4_@]ӠxH_wjQL7 u6s.F̕yr[i&!B3+-נZ"X7=4V5I G!Y&:3<xt6M -0#g5eMXb[u=66lXpU8Aw5g5gHb4S5˹bܲ,5Æ /(q :DTO]z/AyxaNeZ:V"4$P3Ow- ( M$w1жf53Fsh Nb!d;}$`hhG w bL@3ݑ$Bѹ" UC)ljVyM)&<=N' b1{cn"*v,[카)<%46IV(*C EyX"]!مo`MM ˤ$~9ؗw&d:g1 ?Q_!swHdR>m H`Ȕc2^Q!B !k! -TUHg3E$,Dҍ- FhΏIjKgֳ$/D;©KmlKPS %ͳ u!u 9|Z_7gOza 2v7k)XB;)tNB1`%$U8}]HB_o:N\0=YT -DmDE<[viiUhK9VQTXPI'?-/*s=C)(w#咊Oj#c52.G9oB MIENDB`spyder-3.2.6/spyder/images/none.png0000664000175000017500000000024113026261006020033 0ustar carloscarlos00000000000000PNG  IHDR7 cHRMz&u0`:pQ< pHYs ;ttRNSv8bKGD݊ IDATc 0 HIENDB`spyder-3.2.6/spyder/images/help.png0000664000175000017500000000231713026261006020032 0ustar carloscarlos00000000000000PNG  IHDRw= cHRMz&u0`:pQ<bKGDXIDATHOh\UϽwd&ɤi+5Uj"nDAb®Ԃ.XPIAQ" VPhmkiCLf2d&e{u!5ծ끻{#RJJQbT!@(]Q46}Ht@֧HJ " jx 9p폲ٞb?yc(|`+tQ+@p}ߞ)+] -wSUro=gv+G&ށ0 @q&>>s__=nѕB{c2`UC_<+6ߨ!8 40;fhkejø{8:.ta1CG^;0}j#Ot=,hʲ_FYqtgSFn`? [Udz?UI4+ oõ 0ZN(^}9$bxæ- }΃]Jt.sr ?dj"XB2鬢;c1<4I" }Y. B*Я7YJHJEQ8ne4%4 `!ԠnDIDµ6C “^E+g}.TK0*Uj HP)3m!p=v9F΍1%[vcpz:mXE4 @C(A% BٰlX(_qܰ*bNe_|u~dT,C=X,F-4BhX AE?l|pzFN%9zR;ȎL} mZKKUk+8ǎmW "*$h! $9Pm;)I*9/{׋Ϙ'fOx K)K0- ֒bD3.$ D( $TFE#e+vDss%kGd}q5o Fv]Rmsܤ0#jL 4MsSD,ZEJje)%|RPD-SJ50 ׺Q䆺}2oy;EsIENDB`spyder-3.2.6/spyder/images/winpython.svg0000664000175000017500000003326713026261006021164 0ustar carloscarlos00000000000000 image/svg+xml spyder-3.2.6/spyder/images/chevron-right.png0000664000175000017500000000031213026261006021652 0ustar carloscarlos00000000000000PNG  IHDR Vu\IDATxҽ @'b%$DH!X \4{hg*G~=x>$2\=3gl@:B.P j4j~ cΕn'Q vd 0oN}eHZ_cr7_QIENDB`spyder-3.2.6/spyder/images/browser.png0000664000175000017500000000167313026261006020571 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FOPLTE#xU,bV\cH|#BZ&[55cN8DDE HA=/\(|96YC"|s50f ~|#&*"yevX(iA "q'jxq Q:}dy4~?ara]{]6^7DRtU$l8l5CH5c}Ih|x:p ]]K,psd<yv}hu k7@\.4@jU*7yHPa+GE<&p ~d`9<*tRNSp: FKuGЖGbKGDH pHYs  IDATJBa$ h&4+43 BKKݥIΑ$_"#uXr~ T:{ۃfg$$iQ&@{/T]lEI*UIENDB`spyder-3.2.6/spyder/images/console/0000775000175000017500000000000013225025007020033 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/images/console/loading_sprites.png0000664000175000017500000001103413026261006023726 0ustar carloscarlos00000000000000PNG  IHDR j cHRMz&u0`:pQ<bKGD̿IDAThޅ |SUʣ6`ЩkAlj&[dj%*yXQkD>%CV]t0f\gdZ|a[K(n`J*X@yIngnt9szrϹ5 kkܗjH;XqH Д/4쐐c{^~SzCFr X?plI4ƶ9O6ic9sOK18}:^Fa9Йterx3 _ԯ>roOK(y6lowMO?>);JH{ps|% o1W%(kͩ¥L+s\SV) ?sr24S o@~,i;CG_)HmGdMk:yG]Ϩkn2wZC&PоߧmJsZ~[)xe!# ZiqZ~J{gekN L6e,I= A{il{8m KCYpI,Zl=ߖj"z1ÚN_lmi~ؚlH沈}?UjK7Sz?o:eҦ4t. Zy:`T+߮aF=2uVND-b2N)#oSB ޲B'☼/ͥj!17G.x4fL=-uI$:B?NvZ,A(#q+=ϋ'I.Q= Άx*u'kI (AH̳)pQp8y|x;qyy ,x&$3Iˇ <8-b}Ina.< 8ٝCMF(Cw>QI!=+OnKE`V'2npLO5t7{cڭсI#դ+!j0o9%{wC$䫏#iNI;O)b 7ס4^Xsx so_+-1-)mt}ڴpl5Y+4{{f;3n&lyߦJ|НY΍3OtC/.cOSC^W/N^Ȗx^o6~g![r|+ܴ uf}}n|^Їy?Gѱ{+~?K}c/zkx=~xI| sHwxߏoo㷩:<>3t2[^'6zۏq, %w_S܇wSÄ8~\:oB^Q/umI9ʹ~%q_Opip%j_+)8W FU(_u|,wXswρBO'is۱]*bsԵ=Iq<-߯TX$[xģYPD&Kx$oˆ K"#RFTҬ>::Q|i~iS_T*Ew1U*3O4sҧPoy~[af|*ۚ>4?C~)wFxtISn5|(BL qk)8R?chkG 1C#޲pJkFP+ɟg-)Gj)8pdJ}A4f8Oέ"cx͈B ߄_͇T&ȄStD^qG&"v➼ޣ΁ヮ<޶wFǃWymׇP:WMN3jnpgʟ?~$|fw B |VWA<cyw ey:?l#2 7 f ֨ryAM4yzzug2%+_PZORΑȯUe>~ ^~ma+z +T_qoxQ%7R9uZ Jjy 4]N ]h|ɮ 1.Q7Ni*氚NY_4yA 8٩1ԙi;1z}i8߅=I{y^y}:Oߩ,W y|L׿0 O; A{( |H=~Ep8q@O@{h[`Rzj^7ARX{L\y>MQ7z>蜯z5'WKawC*) U]y.,ۀ>a_D).!\y5ywڏzUy =\Wm)͹J)/MWz ;Vz/84VIp8SEyPU7T- a~Tޖ1ཆ{"S+},l#;a w89Fnm0Y0 ylt9Ig:3:wnXH:g ΐMK\??Z|$oе f9έ +{.~rlgXu6@/svh7u/ #Z~ͰA{婋;X Í@ts]PO1țe:oOp G)؆9߱[~O/п3lc?ӐSޠw~ɼv 8 ,B'xy8W;:C*L_dY&#ߒ=:% K",4/x%8e ng+^AVN7R;a `l)wE8p +kp ~1т_<;J !rfGWf-8܁7DC@Pűkuh(>↊wqH?/?%Tq̃4TuqȻt2&Oj𦈁=1~#nnyrQ;9 fc&G!Ĺ iIyc _Ɠۿ@|Gl-9m1 !裔(.D(s"G)_*x18$R1uxGԺ|>9 }*5_>J0@+Ḕq9[y6G ?ٹEJ, B9TI\-ƻUZ:ho=F< NJ,+w飔FpLBe&Z\cݨόo8 k ]iN.p3'~UQ3hOw<7'i6D Fgú&A3R8q_}X9s|(&DS+hn9 f/\%y< wM3F6l;}Uw-ck a6740r!ͅp߿pcaQNYM3U3l)ٰ5'Ic^1)'}s oy#Ort{'rpd~{i; IENDB`spyder-3.2.6/spyder/images/console/environ.png0000664000175000017500000000073313026261006022224 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz&u0`:pQ<PLTEf̙f1b/]$Hl{f̻cɖ_őZUOJ}yDws?rn:miτڬ6iRAt3fo; tRNSkkǢU!ܯUbKGDIDATW] 0 C=[Iu[^O؎-t6i '":;s)$F>iՂ;]?Oc{#޵mel٢}WWqYuU)DE"Rʺ,xR.k7XIENDB`spyder-3.2.6/spyder/images/console/cmdprompt_t.png0000664000175000017500000000111713026261006023071 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMR@}y<s~5Rr'kD>] |,`JFHc,IVR[c jru%v&p haa\jr<( .+ + * + - . + ( ISS$ ]Tӓ@OKV5-BғCAϓʁ*ֈ&J0,ܗB7#r{B,V{ <0&d9uz+  ~ !)טӌ-$ v!A_hj_B% ~MtRNS4( d |)>!ϰT6lL b{q-)(()*+,+489bubKGDg( pHYs  IDATWcb^>F`!,&` *mDT0= 1;V p`fbB q7v0a(`C& @*䘹9d102Z<̊L,żH(@I yy_IENDB`spyder-3.2.6/spyder/images/console/editclear.png0000664000175000017500000000323613026261006022501 0ustar carloscarlos00000000000000PNG  IHDR szz cHRMz&u0`:pQ< pHYs+bKGDIDATX͕}l]u?{}]ºAY蘤[`K"104J@1?aLedoD ZiVtlk^:n]{ι]Dlk|o~y_9O`m2,ۮsۻcM(v~ m)#gç{1b.XLOO4utT|Y \ JX2ᒇ{{ `fծ@ҋGO`*hS}Ck;4,eIBH}kG=ObYYY21913zt%vsr"M|~lܲ` ΓN8cem0 wwiWҍ{|rs |'vpbdʖxcMϬ[L /au]s- uMF:ˁC7_=zS=p|6uxF*ez#osůrBwM-YpF4 f.?L']U^&n@_]!<>!6::Ym%$ 7~Ϻ+{ygN=0cxSw."8dN%APm c{!ysx &/e9l3@|2> (JaDW>u]#?GnycyȩFPXBDV$ג܃mW=}ݽb͉ C'ȒNP^U(rtuZЅuJ mV)5ssdrZd!a*>;g8PZ#hB]u=ph(M4Bc;aKH^&\&`S0U>ĪkJ{O #E8P|A28NE+?KY|%±ǩ6ع0ٵ`(b@vj6բU(Sci8ǵF)m%O|LjhG}Y ߋ@>⯃ A 9ݟ6V7|DKŧn= H]7>B6r.e؛с`1YNΘZ.xݾ"JŬ {&xPIENDB`spyder-3.2.6/spyder/images/console/python.png0000664000175000017500000000132413026261006022062 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz&u0`:pQ<nPLTEZZZ[[[I}@pMs@yAkDfIf?rAlCgEc}Ec|ɢ?|>t@nBiEd~Ge}a\G=u@oBjDeFd}[OP=v?qBktRG@FjEd}`VK@9aZODe\Q?]HIDA'tRNS% !)*#P; (#PbKGD-IDATW5ΡJ+SہAs]\ | 0@apMWI0JIËe ><[0܀}D$x}9?YR; :;6·MP82YQT_TK 97#52Ƕ@@:9y|oy{umCU.4vYcE˜اK"7NX'A=j4#ĉPE 8n+^!pU3^Գ~lpw趬|Ә (s5YMiDCk4-"ִg^NWb5*r |!CBy .IENDB`spyder-3.2.6/spyder/images/console/prompt.png0000664000175000017500000000042513026261006022063 0ustar carloscarlos00000000000000PNG  IHDRX cHRMz&u0`:pQ<?PLTEf1bfc_UDw:m6i3fmtRNS!rbKGD5GIDATI H+aEW^*]eQ%deFV[;kX⓷_wgN T4^shIENDB`spyder-3.2.6/spyder/images/console/run_small.png0000664000175000017500000000112113026261006022530 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMR@}y<s! x\TfH(0I}e%T a1G$"(cʙزŧbQ PJ lK>&!lXI&5I{vֱG@|4-? jC[ fxzLO B~9DOO)RX!V E!A@ Ŋf v2l<]\Q^+ڥ:5k֮QIENDB`spyder-3.2.6/spyder/images/console/ipython_console.png0000664000175000017500000000107313026261006023756 0ustar carloscarlos00000000000000PNG  IHDRl cHRMz&u0`:pQ<PLTE~ws}FV_AR[@QZ?PY?OY>NX=MWY>3: Aw_k==^zߢRjw \oJNi>)&oQ)sʄfWK;zq4Brv)O;e.[v$tsd|[ƽjc-H+v59|5vAjnu8t憁ۤ$H%_̠'gT_/yJ Ay o^d T2YOH)|/;>r c٦$:ӒUR iذvaE {/P>z1sb_E)'R$ ai+Èn<7ZpwkCGWIÜ9^p !3dwy?wEО3ʭsTW՟ɽֿ#z?"nط_jKXXVU0oy BH䱳q *D2<|$&:-\F4knk#"DPj` Zu6 =+dFr*mư 'BS~kC#_C/42IENDB`spyder-3.2.6/spyder/images/projects/0000775000175000017500000000000013225025007020222 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/images/projects/folder.png0000664000175000017500000000140013026261006022176 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz&u0`:pQ<PLTEѭ޵٬դџ͖ɄuĆo%""$!!l%""$!!m%""$!!V$!!͢d*qdh@==ϋ_Z*:!)3 &.ۼڧꚷ׈ڗ愶چy{styuphѡ(GtRNSAj޲#'7F1Z%1%bKGDHIDATWU1 @DCv hFW +=$b#f|02dU} @T tQy&~f\( j2'Q ]Ϫi;I/GJIENDB`spyder-3.2.6/spyder/images/projects/pythonpath.png0000664000175000017500000000154013026261006023126 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMR@}y<s>uejuphW-(4,G=C;?7=510DCQ+*k *":2?7A=f))ef l k h e] a+tRNSAj޲#1%1QugbKGD,q pHYs  ~IDATMa~M,vp [3p-TUSՂG:OUjjZj[]4ճlO-Tм@w~h~j@#ޫ#e -wlk'>-i|?GC|`IENDB`spyder-3.2.6/spyder/images/projects/project.png0000664000175000017500000000134113026261006022375 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz&u0`:pQ<PLTEþ؜ޖهzrzflIT3=-4)% ($,-)% ($40)% ($($ͫ! #D@;ϋ !]I?muntltzkrrrilmHXUs7XHU*F.I(8&=.D+;$6)<- uAtRNSAj޲#'7F1Z%1w1HbKGDB=IDATW]A@Fi7Rٸ:HĂ8TYXLE-{Q 2LHm rH-{Y\$յRGjDuyP&y'p%7;@[FIENDB`spyder-3.2.6/spyder/images/projects/add_to_path.png0000664000175000017500000000147413026261006023204 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FPLTE4c/XKqI֓҄~{|xe(%%ױu5$t v؜pj$4G*4?(/9rr8y6yr+y)xHzH7`72]1:_:.}+,Z*qqeeߚ.d0RHeYwynt{p{p{rcb☼ދ㌺)_,zo|qukxovm_\ㆲކߊ+Z-e 7'/+;695ie쇳߂H9g#{<. e$(]*%f&6p<ъA4tRNS#T=VUC53`At6%4G9:ggc/mymeR(IENDB`spyder-3.2.6/spyder/images/projects/pydev.png0000664000175000017500000000161713026261006022064 0ustar carloscarlos00000000000000PNG  IHDRaM= cHRMz&u0`:pQ<PLTEܺ֫ӧڳʱqppqtplxΝ޽pXjlXim[jp`qkoqrrih|Λvj}hz|gw{bsw]nrPbjYjjpqstn֪orkctw]npYjnUfkP`dBT`m~bofըȆvr{vohӥ{͗fkNjܶldƊժlΚǎuj۷…z޻ݾǎq~ׯذӦƍΜ{mj~͛̚ƌwp۶_v¬rҡkrmݸǾǸ tRNS@fbKGDl C]IDAT(SO(a28%(1)J91E9PvWJɟrruJ-~v^)h>W-(4,G=C;?7=510DCQ+*ڗ愶k *":2?7A=y{f))ef l k h e] styuph4WW:tRNSAj޲'7F1Z%1;bKGD;9lIDATWU1PޓH,@ -% 1cxQ=ŹŜwTRD5!P#{uK7ʪߨ~R *CF]nUQC{_/auSRDA VBa[IENDB`spyder-3.2.6/spyder/images/projects/pp_folder.png0000664000175000017500000000136613026261006022710 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz&u0`:pQ<PLTEѭ޵٬դџ͖ɄuĆo%""$!!l%""$!!m%""$!!V$!!d*qdh@==_Z*:!)3 &.ۼ|UxSrr+y)xHzHڗ愶7`72]1.}+,Z*qq{.d0RHwt{p{pcby+Z-e7'/+;6ieh{<. e$(]*%f&6p<ޒ=tRNSAj޲#'7F1%1rbKGD>IdIDATWU+`Es}` ;@0$f(6! ?nܑ!9U}  W3z( RwD(tQ3sKe9JU} T/z;G PwsH75IENDB`spyder-3.2.6/spyder/images/projects/package.png0000664000175000017500000000146013026261006022324 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz&u0`:pQ<PLTEѭ޵٬դџ͖ɄyvڹouĖ\oj`IlgYDmgYDVjX8}lQd*qdhI;h7|?n2v[);+_Z*:A*O9jR(`I A00!)3 &.ۼڹpڸp۹yѝܹ֧͈ݻxwˁʀ׻vήkմp|ڗ愶uщܶtԬYVX˯giy{ݵiȫk˧fʡQSR\istyϪ`W\řGJIQjuph˨ZTRѻ>ADJIǬq=~:+?tRNSAj޲s1Kb%!}Ճ&1ybKGDHrIDATWʱ 0;?r i(h2CP D$DBndSwk8YM,(`-lf=JmJvYdbW"U푽^ԛO>A{<. e$IǬq=~:(]*%f&6pIdIDATW]!@fVn@B 47Dq J@ Zh˸e3ԕ굃ZBAj#Cx^*&8X[AeEQtr\I Uz ö;HuIENDB`spyder-3.2.6/spyder/images/qtassistant.png0000664000175000017500000000362613026261006021464 0ustar carloscarlos00000000000000PNG  IHDR szz cHRMz&u0`:pQ<bKGDIDATX͗}P-:?dywne%bd0h"+oM2[z'DRGmwYR EB"vY`Y`Xoml)PLo8Z8{θ ҤAR@"#o97Y!0]|DSQ6wg6z.zQ,_1,ABWlKvPWwwP p{4iZ~ p\i,DdJȫiFIE6\GV|e ><g0@ @sOxKbq[K_ӄf+4RwAR݄*t|t˨ǁ췱S$g8L:lB&pyg:tk~XXR n\*WD˄U;GaU@$:c#[!{W 1N `5 Yڢ1Iޫ?CUWƮ u_`([#V-ĪQak~^-TSH [Sy䭑rUy*]ɗ+JqJhJ)'1n5 <KoqՐ53"/աAFҋy$fB)faX{r^GE0Hy "NE)RAΘٷ~BFg]Ìbw qW>p7tŰ$Tu4WSmp;z= R) k5\Υu2zs=3^Ѩi=<鉕?G bSJǒ-4ӋRP;sIȌ ݱ/kF”:UޜζT)$LYt.Wf:W8$:g*+>Gg+1`zwZ'=`Í1铫~\}A机6]J%NVRܞO2#w6|C6>5= Zo:M@mq#Vߛ}&Ho0e38X& |Jթ:y'AXR `<~*>K.}xIyxʇu%AH#SG%ɐ]ـRJ* P6CI\R""#>dЖT;ə |T:$*[ Q@, }z}C ?EԷtƓO# O0%w^u`4FPѿHq?ǂ*IENDB`spyder-3.2.6/spyder/images/set_workdir.png0000664000175000017500000000142013026261006021430 0ustar carloscarlos00000000000000PNG  IHDRa~e cHRMz%u0`:o_FPLTEC^Lg3N!;(CZZZ[[[I}@pMs@yAkDfIf?rAlCgEc}Ec|ɢ?|>t_~PfEd~Ge}a\G=u@o[v`{Fd}[OPLg송QkRG@(C5POj,BY`VK@9:ACYeuUaZODe\Q?]HId*tRNS% !)rv8P; (#PBbKGD- pHYs  d_IDAT*$fN M'}};8*'G)iR{bk`/݇B9F;U#RAb< 4^atPjV:M[TUYeq%fろ^~Uu^<:]}"ϪߓGLka6!gK3%ZIENDB`spyder-3.2.6/spyder/images/spyder.svg0000664000175000017500000003414413026261006020426 0ustar carloscarlos00000000000000 image/svg+xml spyder-3.2.6/spyder/images/qtdesigner.png0000664000175000017500000000335613026261006021253 0ustar carloscarlos00000000000000PNG  IHDR szz cHRMz&u0`:pQ<bKGDwIDATXýwPTWטLO*Q M+5Ib"!Jqe(. "% &A X kM3g޻w T_U3vf }2i)zW>_3M/k dSHJI2=}2 fQrI/I97C) 1T#%5=NZH*HrIvLz94΃5a /=zD^(1 5'f"8{<Ŧ< fY=j~ daL\;AR4kpJ_#ݜƋXLlvܑ6[(XFU%:KR wߕWbyg[B3oZOyLzA9"F~ؔ88Q Li8VϷW C75 `@,`'ؑ)4X 񰩑oK,EٜaP<B][5:VR,0n6~<6CmÓEkAH=e09nfb 4~RKLiYꅕ]vA2;~ (v xsS@YC f#氾+`l?:caP_ `!ST#Pfo 3YAXMd/~{rr 5)Mv .|;z@hjnDpbLie@{`p/*ԡ͎h. r|{&E91V9 ?3X_|A4C't n۱᝻H@6vS\_2&A_Wކ5\Q||xo] FCdV>pi[;ܮ(:\Tˇh4G\& B?p򊋘p0ĠpgLAb:l\l(9(51: hPqu-N\$UummpnPJ8˘⺖Ze8+.-j5v8%a\ŷ4h+ujds%nj>Td\[B'@\+-pnOC5B tZ8ŵ?~l({,aɈq*P\SCD4xqqU\\؟>. 1u_ÌLXxJFu\ܤ[MȘ'gwI{$r]H>1e]S|atK.O" +@kks+_Qb0 u V})hU==hrV/Y{y;.[=pT4gG0wxs9ty5Vt: @:qtn?r|,P ]>)p%4ma%7S 87 J<]$KIPM禷jUjb &Pnо| `P.@- ɘ>n*vS4ܺ IДŵwS|$z;G.WDvNQ!67QPꓒS yo~jz=_y] IENDB`spyder-3.2.6/spyder/images/upper_lower.png0000664000175000017500000000052313026261006021442 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMR@}y<sacBd(NE5W[xB1U&K;,OUq0RD<\=%HNk*L!D8X7W8W*L!CIf'AHd6AHd)'"!.N!CJf걺 3A^8Ѣۈ#%GLh䭶-N<ݿ壯))LNj㰸ٷߵ$H!E߾桮/0RQmⲻݷ㷿{ڒ堭6Ws嫶;=_@c9]:^;^=_=btRNS/bKGD;9l pHYs  IDAT(ca`ddd@gbXgaL0YxvC 02`8 D1 &̀&  Fx(ΈM.Q u:or[ { `:X""l׆J#-5c u7-Ag ݹ $ƹX=Xχ.q ,P+gdʨ+hDN>X{,I(IENDB`spyder-3.2.6/spyder/images/actions/home.png0000664000175000017500000000157513026261006021477 0ustar carloscarlos00000000000000PNG  IHDR(-SgAMAܲ cHRMz&u0`:pQ<"PLTEIGGIKHGGHBBEDEF8<:MV!#w%&W{)J !~2Cr$qrz>*|TXVTQLLMOTuG|nϻRtRNSmM,|F)x{@WNU % 9bKGDHIDAT=*&A2d0I % ,Š(h P򞪊RUw~RՠuTZGup^&lo&m3+-Kޅ1plX%غZ4qd}zx "-m-IENDB`spyder-3.2.6/spyder/images/actions/replace.png0000664000175000017500000000216013026261006022151 0ustar carloscarlos00000000000000PNG  IHDRש cHRMz&u0`:pQ<PLTE  xxyB@AtsuGDE%%%z{{RRTMLMQQQXXYHHHIIIHGIFFG\[]KKMKKLKLMfghSSVTTWgfiZY[534NOP>=>GFIVVYZZ\PPRBCDﹹ\]^867/-.\Z\EDESSTpop;:;523UUWXXZppqOLPYR\plq+()CACdeg111YY[423][]TOU^VaWTYooo[[[0#1?EMUFLlblTTUcdfCCDijl[Y[>%AFLW!`T&ZB;BRRRK"NVoP'VkBBBYYYǂVVXYNY38RNC7CVVVA*BS[W+]rmfmAE|GanGu>9=<;<:7;?6@TNTXXX퉉d`dB7C?7@<9Dn4%CgLkL"A_a252 N o F4V@ iCPB>8,`cIENDB`spyder-3.2.6/spyder/images/actions/stop.png0000664000175000017500000000073213026261006021526 0ustar carloscarlos00000000000000PNG  IHDR ex cHRMz&u0`:pQ<PLTEAAAA..,,RRTTVVVVUUSSPPRR\\aa``PPTTNNVVEEHHFFKKSS99<<;;BBOO115577337788//JJ --FF""'';;##"",,##++++##""""""GtRNS˲*bKGDF pHYs  aIDATmQ@9HPkqn x MS|>u;:P*2VUo2=2*c/se)/~ '? ǙIENDB`spyder-3.2.6/spyder/images/actions/copywop.png0000664000175000017500000000171313026261006022241 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMR@}y<s?))*GGG677|Ԣ`ƭgȱoʲW]ڣ݀dMqstߑBuⲤWY䚳O~9lzޝmcYm}ᆟKy~ㅠ}tj煞pgǵ];RtRNS: pU3 6|V3 ͖"~θuV72tN1 r^bKGDR `- pHYs  ~IDAT1+pEQ`B7ܠ(%I(f60ٌʯa{ ՐYP|dӖxbhGZ&_M=h;9Usnh9Cv\@Ϝ^^K!mcIENDB`spyder-3.2.6/spyder/images/actions/next.png0000664000175000017500000000135513026261006021521 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMR@}y<s) h%t}869===20000/1+z#|%zp4"% #%!||}}0BRtRNSGQBCAXr1!-.{/w #'%`v=~CI1wsnbKGD} pHYs  ~IDATW]? AqPJ)f&IEƛWaWJϏtz_rtB}b@#g^uCGeG({^pt0xCFag䏼L`,"'nHH9IENDB`spyder-3.2.6/spyder/images/actions/editdelete.png0000664000175000017500000000230213026261006022644 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FPLTEv]r\[30h=q^mtKFDGH-12$73;852 :6=:ZS^YE>s N<y IBy!F2T@^ /K Sij= Up{iaJbanz ta$_g KZwK_%Muvv mF  !2 ,8hp"#(DddF)%z¼ÿnhlfz{vkd84>;kfwoMHHC:4F>E@MF&"$"805.   ~`d w s        2(E5 72NGPH:3,tRNS^s N[e|CX dAgTm Ȑ fש Ȏ9sS}7ܭQSl>RC|Oz:bKGD۶x pHYs  IDATNBQwFr@1BФ& NÇp/Oq ހ`3ٜ`1`p#6` Ʈ>(-vD=CqؗO%bC[LL $Qr#z%(H^΂J *B_m|'W-ə㚅-6 H&M- O{T4ޒe&IENDB`spyder-3.2.6/spyder/images/actions/findf.png0000664000175000017500000000171713026261006021633 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_F4PLTE./0[[Z...###ǽतˤ̬zzy\\];;<,,-;;??)(*867  5/4443LKKʚ777+&,.&/"$"797/'0+&-эGGHPOPnooLKM;;<]]]gfg??@9:;224a`dtsu424,,,778;:=>:<=GIH***=;=99:=>>ZZ[hghHEG$"#344/20EGE>=?mgoa``$$&234>?Anoq523LLKOLO2.4-/AGDLZ?]))(--.89:CEGbdc_M`>DNWR*WX"]nLL,Q+&+LNL?@@FBFH)MEƀMK0McM^=aI-Ls?|ggJmǎ TtRNS% '$ .t;̬_m: xILM\&omf vٷϩ!"֭Ԯ",+-ۭݹ=5/ OapvO D =Dl P , ~)})+-/ / 0 0 2 6 1tRNS[q,*xbKGDH pHYs  IDATMP@w+p"#0 QP"H(}wKp:`'p|GrǺXUG_3 #D(J( ^O% Y^% Ya [_ _b3z< e-Cc1E e *L h %XOi%*y()("m2P\." `ȁ' Zm% Tb3jptRNSOIF?a9OٹrefwbKGDH pHYs  IDATmNBa|I:IGRQ.kBQ6وTIJd$sL>xrnm@SKk;һ3l#:Y{㦠ۋh\_uͺ-x-ZH)Kl YI%AijI.z%hρPa1yPfdW3[IENDB`spyder-3.2.6/spyder/images/actions/auto_reload.png0000664000175000017500000000145513026261006023042 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMR@}y<s4nd!Hsvxzzz{y8$]:{ zRzmgabZLGJ;"pr6g3 bo5&f?&lxYkm ^[rj| qei h_#byOc)&} bI"g(f"^__]N9c) c!S!BBG82w r m ؈'jr{#awqw%Su&J o'B"h):WH*49):G:7%S+2oAE97'D(>)9*5*1@BELtRNS6*e*/. jVq8]5%"۠!-AmDbKGD[t4 pHYs  ~IDATEJa=9Nt P465(5ynAS/<3 D vޥKrv"vVIݎpGv Zd8HʤZJR&XG7Hn&4v~}{AS=W!µG#1IENDB`spyder-3.2.6/spyder/images/actions/cmdprompt.png0000664000175000017500000000132013026261006022540 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FtPLTE񱳳ſ [[[IIIKKKHHHFFFCCCDDD222 aaa---<<<@@@===;;;999888...555+++,,,666777)))///>>>$$$&&&### BBB???EEEJJJXXXVVVccciiimmmpppqqqrrrnnndddԿ$tRNSCRcnsuwwusncSD}bKGDH pHYs  IDATJQ3&A  E[,DQf7ÿ֓>?E* ]E8}AHw ]8J{])7CfٶvMNX0$$|ZڶDA>ƓY#qvIENDB`spyder-3.2.6/spyder/images/actions/arrow-continue.png0000664000175000017500000000253013026261006023513 0ustar carloscarlos00000000000000PNG  IHDR cHRMz&u0`:pQ< pHYs+tIME 3!!!bKGDIDAT8ˍkLWKbm >? aJq 9E&*rQT Ee(!2(E(@)*E,R[K[hBۗ #B9O?^Z. rS!8[3%ʘ%4C[Lr~kH5ֈ Mpq2>nwvetٌ-Բ3Uq~)DcL㹞̱&{"7aU1hCu1)2oĆ7k-  mUZ\M- dɪ𼣽 7Ui/UH@f!e*[R-sb%RD2\Yb:k}}k E>.zZ:+ȣB~j]IN#cprC uZ ӎ9:Cӫ_!BN%R,@;Z Xcw_R $n<_@"'tWnK!Xr Ϭvʉ2$uT"kIH\}Y=$C-: &sU3n;2"v?. &+]VDq],NV#MLu%Pޙ݈U!3&n F5Ѡ~"rӑ;86!+qrySsO48< |r%ΗyKo^Xܟ.®k}_F'.4!-~ꐼ^ۍڍ[++EPX*KΤ<-ѯ; mNMoSۋ_#?H*=HKTT>uNz æ1C8kta`*^\l pp/-T.iy4>LjDp x>[¡NPco'aţl;Il\}~XQS= =}"կ26`V(I3"c9Nղ?`ʕ;] DZ*dHgुΨ:= ϸZfm=](Dir2{>blgB*&iA\vc{s=(q쥏2q:ρw<{2ӫyrazIJUՌޱtuւUTcXۣYՄGMYf#o`כ<~73( w[XS)ե|dWdIENDB`spyder-3.2.6/spyder/images/actions/options_less.png0000664000175000017500000000150113026261006023255 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMR@}y<s>‘XXXed>>ssxUUe==e>>vfkW-(4,G=C;?7=510DCQ+*’k *":2?7A=i‘def))ef l k h e] `+- K.tRNSlbKGDNaq pHYs  ~IDAT]ϱ P FxSAꢈ 99vq(TC)|@P';kAre-PޒftzeY3?I(^#,13 R.KVY]oN"!]+ `-\zɵ9-tIENDB`spyder-3.2.6/spyder/images/actions/show.png0000664000175000017500000000040513026261006021516 0ustar carloscarlos00000000000000PNG  IHDR7 cHRMz%u0`:o_FbKGD̿ pHYs  }IDAT(1` ^V,xscªҴO&cǟC*zR/ոCnT)-;2" 30pXm"PpDo TRgW77D%&r,IENDB`spyder-3.2.6/spyder/images/actions/arrow-step-in.png0000664000175000017500000000132213026261006023244 0ustar carloscarlos00000000000000PNG  IHDRש cHRMz&u0`:pQ<PLTEa|^Z߁o|VzgxRԉjWW]mNwEDfGdC_ޱ=|T5qnFjZNS:y=)c5)`2n.#tRNSP]G .C (Y=F7?  bKGDH pHYsodIDAT1NUQе;bbei8^- !LjuԤA`R#E(@`fbgv5Q7Fw.4ߢTN=1ś>PWI"gG(xcC{@{w]}l,ǏwWu>$I$قda}I[lIvhI:IA' $jn~$/__@&`IENDB`spyder-3.2.6/spyder/images/actions/hist.png0000664000175000017500000000053413026261006021510 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMR@}y<s``gᒐbCR!,1CE -j*(P'RT 2czIENDB`spyder-3.2.6/spyder/images/actions/maximize.png0000664000175000017500000000217713026261006022371 0ustar carloscarlos00000000000000PNG  IHDRw= cHRMz&u0`:pQ< pHYs  bKGDIDAT_hey5m!)va༬aM.MA%?.."(4Z$FCDjAI,fNw}>ϯSphHͦ իW_cl߾]FF^N8p`?;pcK\"!LӀBDlxdpWw D`0YHC4aɢ291Yٔ}\a5WGIB*:@i)w8, fW5T94з0{MUq8&M FFe}NZeZH^`b2hSU2qN$(J{xsOqsT98.WycJ-#n4I<{sϩX##,č\W%knI,-*>xgT-ti2=_`xiZm&MS,CU >B ܷ aL^i4R4Mq&P[,|4Λ\.oyN6JԪ`<1Q c|_8 %bTj%%IXX.qbbqyhY$3bn@ 8%I<8:EƯc2:6 H`anM9|"+^Vhs0Sg\!Qd\ѱ z~mN\bˮ3<}R3ز O' mιh9ͦ9"B`Kqb8y;FHP@˹c d1AD8B'7WYJTc\Pƺy8D "Kݴ*vA2"2sN w! Xkr)¹2m"B`7Cb :2Y>b,.ZQ~ K/ytEuTMRAQnPp.5];ϾH7@52,,(/*1+2-4/60/'h o 1#SA`QfT^OQIBA=;=;@ACBJFPH=0p h     ~ r y  )66n z %"*/%'$&$&|^ $:0Rhc^ZnhKFNJb_uq[WoimgRLIE`\ZVd-tRNSBBə쮳񸸮쳒HbKGDkfZIDATm.DQ@ѽ=QШF#*LWDPJ$V(X:<ĺSF}D$eMeGu"K}/F3¾NfuOO@ W4}Ya|{osvQ8fA ԓbsB/[z+:ZIENDB`spyder-3.2.6/spyder/images/actions/arrow-step-over.png0000664000175000017500000000137713026261006023623 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz&u0`:pQ<qPLTE8:=54,0s2%z$z1ln u"w"xdj ZaS YN@@@@:GWLB{B02,"7_tRNS5 yy9̃&&5&&3HHHHHU{bKGDHIDATjQ{g]fJB; Ey0iDa}6Ix?}qyf.Ay7ܒߠ?'$G;:W?Rzr d Ɉ"ji/2IG}^5-,+-`u0rj]F4~Y,qIENDB`spyder-3.2.6/spyder/images/actions/tooloptions.png0000664000175000017500000000142513026261006023132 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FPLTEë›áƪ̡ƪʢĪɡéɤƪ̥ƮУĭΦŭͨĮ̨Į̖몪íí’de>>‘XXXed>>’?>‘de??mit.tRNSlbKGDH pHYs  IDAT]jaw;DRYyVigbΠPZ`g2XDgV3F9QO󱛱xwX@E!_vmn+_*SzR*<1 x$?R+^b_s8M&WIENDB`spyder-3.2.6/spyder/images/actions/collapse.png0000664000175000017500000000122613026261006022342 0ustar carloscarlos00000000000000PNG  IHDR(-SgAMA7 cHRMz&u0`:pQ<APLTEthsgrfbY`XthqeodbY\TsgZRpeYRWPaX_WGB_VD@\TVOHCFBB?XQVOEAC@B?΁φncf\yqwò֞̃silbdZbYxpǍzs~͎їk`aYnj}yrmcИi__WƌÇ^Wmblaj`h^g]]U[SYRWPUNcZ]U[TQKPJNHLGJEd\OJ~yytwq{tMHwshc^ZnhKFNJb_uq[WoimgRLIE`\ZV׽tRNS쮳񸸮bKGDj%bIDAT AQsRL6LՂ~98BmCRQTA} l$ṟ Igx# JWLҘ?fXӊJK캭3>>  TO# O1)o^v\N:/ Uwrv """A<9ZZGEG1*1969  @jjjjjlbbdxu7KKMCBDKJKDDEܴLUVY/-0bce524zz|qru_`a^^`ٰ yo8RSVa_b$ !<<>888$!"fefSRTKIL<;>988?ɣjtRNSAT3! FIY: j4!׍ﶹZB! ;Jı>MI1 bKGDϷ7IDAT=JQ15I:`k.Ah)i$(jc.,J( 8w&@rcI䙼.5>m<4)!D87.!5Vniݵxb:9䶮/T%7ׁ̐_$,_XIENDB`spyder-3.2.6/spyder/images/actions/reload.png0000664000175000017500000000163213026261006022007 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FPLTEf0+%>4nd!Hsvxzzz{y8$]:{ zRzmgabZLGJ;"pr6g3 b!?apgM(o5&fy|||{A?&l+2}&^[rj| '$!0` a!a!^ f" qeiVEhW{murhWRPA h_#byOc);76/4)1$-&} bI"g(f"^__]N9c) c!S!BBG82G``J( ؈'jr{wqw4OIWH 6(9):G:7626.8-7(4#+ oAE97@Bw~wtRNS6*e*/ި. ˾jVq꾄8]꺺5%"۠!-yRbKGDH pHYs  IDAT*d60PlvW,bSB)Pf)\Y}JUU )- }%cw<S+G&Z=-=50Mip=[f70؎WS.RuyU?ϵ"OIENDB`spyder-3.2.6/spyder/images/actions/expand_selection.png0000664000175000017500000000143713026261006024070 0ustar carloscarlos00000000000000PNG  IHDR(-SgAMA7 cHRMz&u0`:pQ<PLTEd[ncdZbYk`RFaYodmci_M?_WYRlao`]R&B`Ob\R_WSv?NHLG&JEHD= ,WPUNIETNthsgrfqef\d[bY`X^Vء֞g_ȍɎ\T֝ђ~~v~ŊZRrfuk̃ӛ{}unjsmYRWPpeɀyunslUNfYjs݂Q2t݃TLރz,cZsl_M3KgbGCaX_W\Dyuc_LGEA_Vzssl^Zd^plD@\T}[TFBqmsnB?ZSXQVOTNRLEAC@B?A>lP$.tRNSBBɳƄʱbKGDoIDATe1NA*ce,m%DCfVJ?E;wZ }:LGhd.ZH6-[.ԉ=ZDH |eB"?7T?ɳ?ՕzoxTGv<$Jhv%<^j a KD[IENDB`spyder-3.2.6/spyder/images/actions/edit.png0000664000175000017500000000133713026261006021470 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_F\PLTEĠssrQPQ@>?~|}eee FFFܰأߜ󳱱ߡб񰰳ċ5tRNS; o[<@CCCCCCCCF8cbKGDH pHYs  IDATMJAE{_W}-$! Sw!n؍8ԉADiATT 9F) 1-@BR8VۘsFFB] sRAߧUog@Vu^)zXrF֮z\~9nW>s]_KO>C맷?',+BIENDB`spyder-3.2.6/spyder/images/actions/editcut.png0000664000175000017500000000172213026261006022202 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FPLTE"!! 444*((ggg! &''%&&&$$021455-*+000aaa(%'CCCAAABBBDCC---&&&///111333 #"!HGG  GGGHHH433  (((/./___IHIMMMLKK***9::AAA=?@?>>666popxwgii&$$ig.,,0..311!!:9: %#$311%#$%$%   ԐlmnytRNS_YA A kwM>yF5*tzzO׹ ZvW>?g,_sh1a}bKGDߌ pHYs  IDAT1J" 5+CsECIݢC44DCGlh 3`%C=Ɏ`&υtx7}> 1&3kZt<(W@ @ŒBgi'pS14J3I$p2$I \I$I.9N[(VASxIENDB`spyder-3.2.6/spyder/images/actions/2downarrow.png0000664000175000017500000000160713026261006022647 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz&u0`:pQ< PLTE[#}yuropnmkhf8k1xAv [U r \x%wue]WU `l)={#|nmAIx T9mf iW`xq `}! a b g jo lozo ~,y qo dnG|uTOMLLQTVXT|*>zrq$rC2~ut! J){W&%w#!VM:>{wr!(C3}r+L$w*Ku#7@z'F2%N7:|ң=RtRNS% UNW@{x)F|,Mm:bKGDHIDAT?*[(2(A()J$}pO)QD) @@f{l_`фU&ο.=ni쟁 X{Z嫚:cgmKjsN=Z߈RzN+U pRպwUj*UՖU"_S$IENDB`spyder-3.2.6/spyder/images/actions/window_fullscreen.png0000664000175000017500000000045313026261006024272 0ustar carloscarlos00000000000000PNG  IHDRY cHRMz&u0`:pQ<*PLTEnnnqntRNS@fbKGD a pHYs  aIDATc`@HAH Q9p`qGP+44 q\"'́q """!!'t%}9?<===968+z1/0002>#|%zp4%"# !%}|}|aTQtRNSGQBCA¼U!׌1-{χ.wȁ/v`%'$#~=CI1XbKGD|Ѷ _ pHYs  ~IDATu;AQ@ѽϹI$YhT~Õh$3UZ? B'WCR`ޤ*0rIUSsb5uB/v`ڷSL̥zbm:<@4I)*hTo!C!IENDB`spyder-3.2.6/spyder/images/actions/editcopy.png0000664000175000017500000000151613026261006022362 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FPLTE;;:wwwvvv000eegPPP:::LLLDDEMMLTTUMMM***xxykkk墣NNM444ݡNNNǟRRRAA@&&&bbbfffUUUlllqrtLMNTUU@@A%%%?>?))*GGG677ǵGPtRNS: pU3 Þ|V3 ͖"~θuV72tN1 ݝdhbKGDH pHYs  IDAT1+"JQJ E1JR)bp% 0H既TsWU *g@U/,;UX3;*^O UƈyUѦSUmK&>hh o5:Kw\u4r >IENDB`spyder-3.2.6/spyder/images/actions/magnifier.png0000664000175000017500000000133613026261006022503 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FGPLTEhhmEGH::=BBCeejcejWWX+-0((-@??bcgPRWB@B23;WXZ778PPUJKOEHSHO_222rxbj557sx}000--.psz222]][HHJx}zzZ[[ ...mopMOP]]_moozz{^\dtRNS%9 이5Ў ɐĵ +b!ˮ Ͱs|bKGDH pHYs  IDAT?G[ti }5"!pqͭM nK騥BUXo UUQUU@ZGh6U;Uh;A[ϫFph+xkѥp2"U7eIENDB`spyder-3.2.6/spyder/images/actions/edit_add.png0000664000175000017500000000143613026261006022300 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FPLTE;r>:q=?yBFGGJ@yC8m;7n:4f83i75j84f76h:;q>;l?:e>5f93f7-Y1b_QP3b86k95j94j87m;:q=9z:h^YR@yA1{1C~C0v1@@7v8 <1>y?7h:6h:8m<>lA;g?>jA:f>:f?;q>9x:2254:{;MMeakhRR_\r|ed^]ympg\[d`xk_XUtaR95E=[Vmiif`NN?SP[W_\eb='bRp`VD=/;.G7**(A:*)"@733+<8?tRNS#,,***##",***LL***,"",***LL**,##***,,#h 7xbKGDi+9 pHYs  {IDATWcdFd ZD0 F$f F^6G >3uH?(oˈ 0011V^< ²$ 4``8( .jY WqIENDB`spyder-3.2.6/spyder/images/actions/zoom_out.png0000664000175000017500000000150513026261006022413 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FPLTEhhmEGH::=BBCeejcejWWX+-0((-@??bcgPRWB@B23;WXZ778PPUJKOEHSHO_222rxbj557sx}000--.psz222!g`]][f^lzzZ[[fb... k !l!h#k&m'n(mQ)nmop4tfwtt0qUyQsMOP]]_Kf"}j@mooYUXzz{:&ktRNS%9 이5Ў ɐĵ +b@ˮ ͰibKGDH pHYs  IDAT* JbPXH.,6彔*ɭd!e00UUx$U*+~h*scx*.4nΪ2Z58-Í[ec^jsa^o0ycU= śYZG5t\H@E=U@LPZ]5"ZGR? UYĂ&  ~߿<;3-)&66ֲ763+PUQV! -/ַ̻9:PTOS<>ټϊʅtRNSﳓ`bKGDH pHYs  IDAT=@{/Ht0g0[͞΋=hѠ9b PAQ (7鄠$Ti$5geH\]\zP9E@u8ye8sy P1Aԩ;DIENDB`spyder-3.2.6/spyder/images/actions/plot.png0000664000175000017500000000057613026261006021525 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FZPLTELDeLDeiSr>>̀*+ xdtRNS4&bKGDH pHYs  #uIDAT]0E*_&jvMN)m?SJy. 8%\wZ: rE;`uqƊ{$ 2Rahcwrhγ5^~'+߾^ SLIENDB`spyder-3.2.6/spyder/images/actions/browse_tab.png0000664000175000017500000000146313026261006022672 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz&u0`:pQ<PLTE666111001000..0...333 lllggi iiieeg YYZrssSSSOOOꜜ晙㘘ίܬctRNS.8ECppppDD &TDbKGDHIDAT1@w%4j:ԛɑ0r>cL"By= ĎљH RSYCc[EZBdN`X,YV4$6.ӠY9ok@R ү7 XOIENDB`spyder-3.2.6/spyder/images/actions/stop_debug.png0000664000175000017500000000210213026261006022665 0ustar carloscarlos00000000000000PNG  IHDRW? cHRMz&u0`:pQ<PLTEggferrb`|^zZ}uX{mWTwgSQtbNq[MIgRHF_HBU>A?L4?~<{B+;{9x9$7t3332/.,+*)'&%%#,6t5q5p4q4p4pdbbc]^[}~\YvvwYU}mnopligedcrVRxfhie_TNHEB@?RTNufbVJECDCRPLtWHCBBAONH\9;::9FKED.//9GC8!#"+E@})B>x Ay;u>v:q@{./Y>eZdWӭKՑy"c1^x l77u%pL1}1t e\(_qᴝNVn8Z>z>Z!x%jIENDB`spyder-3.2.6/spyder/images/actions/rename.png0000664000175000017500000000101513026261006022003 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FPLTEfff+f8tRNS4hbKGDH pHYs  d_}IDAT 07in>O"HqJ"5KZMF Ԙ1(1( ~\굺)%O)A+LE1A/q1vCw8) =_t)Tv}EQUxIENDB`spyder-3.2.6/spyder/images/actions/edit24.png0000664000175000017500000000140113026261006021626 0ustar carloscarlos00000000000000PNG  IHDRש cHRMz&u0`:pQ<\PLTEĠssrQPQ@>?~|}eee FFFܰأߜ󳱱ߡб񰰳ċew5tRNS; o[<@CCCCCCCCF8cbKGD6G pHYs  IDATMJA~]-'AD q.©sADb[}F $Vi34ww`iP+dws?TL:+pQu. kW )h)|l㔽QRfo#eTD24]zIe^?,HAԃ^6W_`"zԽ`6;$ҍ$aK,Ž-IENDB`spyder-3.2.6/spyder/images/actions/imshow.png0000664000175000017500000000077613026261006022057 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_F&PLTE]dbdcefegfhbgkmlnomqrqksyxy{x}~~z}SGqqptcev:DLe`NPV@8+!^gosNSYXkE@V`8?U(2?7QvsMGP1"64#,tPg:1?bM]@C*chBxpx~TdqQQWAQXHjNU5OSBAtRNS@fbKGDH pHYs  8IDATWc` XPE! 3BIK (J@v  ېIENDB`spyder-3.2.6/spyder/images/actions/filter.png0000664000175000017500000000204413026261006022024 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_F[PLTE~abr ,)>T=VUC53`At6%4G9:ggc/mymeR(IENDB`spyder-3.2.6/spyder/images/actions/1downarrow.png0000664000175000017500000000121413026261006022640 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz&u0`:pQ<\PLTE g e g e c ` ^ \ Y V SQMKJCv wBvvdRwoX]O f Y dH{f e]# h g Z l br+~&l u n iLY!$$#!|&(*+)7T!}w o n.I{sr';?ut"(H1wv+N#'J!s<>#TJX12tRNSê8EBdI@HGxbKGDHtIDATcd@0" 20##8 Pik0;#'`[dw1> (00ޕBݡSw@r'vƫH \DyIB{IENDB`spyder-3.2.6/spyder/images/actions/options_more.png0000664000175000017500000000155413026261006023261 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMR@}y<s>{xVTUySrr‘XXX8y6yred>>+y)xHzH7`72]1:_:.}+,Z*qqee.d0RHeYwynt{p{p{rcb’)_,zo|qukxovm_\‘de+Z-e 7'/+;695ieH9g#{<. e$(]*%f&6pɂc6!܏BAԆK#]ZSzDb5e5Bk7J%{g1=+_ jpFNuf{lӂfo0p%^dւlQ>,se p3qrofT?@&nv Iuk.`9U {(>=A<6tRNS ` PϿ`@ ￯ᅬ`ppP00@އbKGDH pHYs  ~IDATWMν Aq`Af,*ܫK0WP(sM/ޘBN}A^}2AݍHkY/_4]KݞvL7F` Cz:yas!,]$vtU ~(fPIENDB`spyder-3.2.6/spyder/images/actions/restore.png0000664000175000017500000000071013026261006022220 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz&u0`:pQ<PLTEUUOOJJGGAA8899::11%n%11 i ++!|!oz{_wjp U UURRmmMMiiGG~~AAvv\\::UUoobb33gg,,__??YY%%77{wI!^\tRNS@@@Y!YÐM@SYwtbKGD70G{IDATm@!iJ-ʬ5`؅:Hk>$ƨx>>ı TO#   :/\Nvo^1)O wrvU 9691*1GEGZZA<9"""  bbdjjljjj@DDEKJKCBDKKMxu7^^`_`aqruzz|524bce/-0UVYLܴOPRMMP98<<;>KILSRTfef$!"888<<>$ !a_bRSVyo8ٰ __atuvMMM,*+*()VR8?-ҫjtRNS3TA !:YIF 4j!رJ; !BZ>ϱI˔M1~bKGDϷ7IDAT(Sѽ+dpRv6)`+eJ[$%dAbʟbP0ù$ yy$x,&?{p!:)s8&t+q~:/ܦk*޹".\Jr#YSPjCXonl`c&^e`VoڭFRhv$Td(vgqZ[11`{^a'*81{E}IENDB`spyder-3.2.6/spyder/images/actions/zoom_in.png0000664000175000017500000000150513026261006022212 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FPLTEhhmEGH::=BBCeejcejWWX+-0((-@??bcgPRWB@B23;WXZ778PPUJKOEHSHO_222rxbj557sx}000--.psz222!g`]][f^lzzZ[[fb... k !l!h#k&m'n(mQ)nmop4tfwtt0qUyQsMOP]]_Kfj@mooYXzz{4:RktRNS%9 이5Ў ɐĵ +b@ˮ ͰibKGDH pHYs  IDATM=KBQň*rkQ?A A 5($Pq)D:#`a̜lȢ&/C]-؛Q{]d0 x>֌Ls'_>rhX'xiyul /*8ձצʬ0yMGReݕoX.)' IENDB`spyder-3.2.6/spyder/images/actions/check.png0000664000175000017500000000201313026261006021610 0ustar carloscarlos00000000000000PNG  IHDRש cHRMz&u0`:pQ<RPLTE } .(=6h ,% ]T *# OH *"QC  ( UU ) )!EI  -%FH}93 /(JRvE@:.KET r7-KF]s&y g v}s 2" {F6~ZJ$&#}o5''#($F8zrƿּtoұ׻qkD; sںohC9 D:߸oeD8 ȼpgI> "ulSG%.)إߺآڣ{q[O1":+.$[Q~uߥܗݗwcV=.F76+6(aUߔFBĄzj]H9RB=36'RD‖掓Lj~rfRC\LF33B \b-uk@j3A  _xcP0w9#c8VQH`6aX1&#ħ0GcLq7r 1C{cHq3z1ԯnj Ƣ~"*q+(;E9ąIENDB`spyder-3.2.6/spyder/images/actions/redo.png0000664000175000017500000000200713026261006021467 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_F.PLTE:.SBN>C0B1B0B0D2RBM=K;UDTCTCUD>J:aQ_O_OaQhXH8 9-K;H8i]eVfXI9F6g\`RdX_SgZaSF6aTh\cU[ B/  nB    {aK9z8)]K O?n_ 9 K=kZc6)?2^L.(  }L:wg!t+%2-4/0+${@ U  E/< F L S Z ] ^ ] [ V 2/0;08/+/"n_4(o ]E(v9, L 0 A/L<QtRNS0PP7ē??KMqоMigbKGDPnL pHYs  IDATU.Ca|=o.vaNtXl6 nC&Qhi,&&#x^:d%gr_;o@).U4d h,lbgU}lyeEƓt|P=92v*mhwﶨTB>n_IENDB`spyder-3.2.6/spyder/images/actions/eraser.png0000664000175000017500000000133113026261006022016 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FMPLTE˽SS!%% I@=A?>6!<@@9䑑E??{{@@^^㎎||^^^^65뙑88훑[[22~~}} MMDL":tRNS~ۂ|IH|F~DGEIHFMǃbKGDn"Q pHYs  d_IDATAK`O]C0QNJ0 L1. /"/"1#cdaJUI(:'1Y,71l*KLMLKJHK9.Y) $ Y I \^ t,!/"R> rm-}&SB+x$/y)bRK=!UiZPA"iXI< `O6A9;42*(!"u h'PA" =1 08RtRNS!♟ԄvY,8:bKGDQG pHYs  IDATJa[N@ zQmhlh8Q(Zzƣ78r_↶ nxw?LJ.F识vvjX+Q%Xl+':+`p?E)kO'P‚ ~3d) +0!*1IENDB`spyder-3.2.6/spyder/images/actions/hide.png0000664000175000017500000000041513026261006021450 0ustar carloscarlos00000000000000PNG  IHDR7 cHRMz%u0`:o_FbKGD̿ pHYs  IDAT(͐0 E2 hSRg\ (#%ρ r&ĕ4naqR(<)* E3SP>w 0'Y1;@>6~?xW,4m'IENDB`spyder-3.2.6/spyder/images/actions/configure.png0000664000175000017500000000262513026261006022525 0ustar carloscarlos00000000000000PNG  IHDRw= cHRMz&u0`:pQ<bKGDIDATHK Pu"0`O@Q$ZzR(dzb*(E Bf<(ZO<T2Ħ4E}޷n}Dco-#KK{ɞH&ՊtIЎlz<a LzN`mnnnS^^.ry'YB=zk@3n lΟh~B3ؓ#7'W^JOގ‚/y_)HV^*R?Ix9[2PeEvww u5ؒ)^NՃͨCIq~?#C׬@_DNS\V\ƛHٰw۴hnE}P 'aS͖ ؔs凋x\|rOlfhj޽&OWԸ:8hj-V +a(cׇz= ww_$g֝?7UPHz"Ua5F|+~b9Z׬FlU(Ns% 31Spۀ"Am::ⲗ~+i8Sk_1(t N9;^11hCʽ/]0{4z(> 1i:63Jl.3c+ > 8NlqaR۷1Y]BT(/w@gFУ (>9ޙ,qdUWvNr{]eʰs }^ڂ|=,/jdkΒ8ʐg쳷9ooo܀h"do0U =ŷ _=z8-kЄK$VF$`[^$]./+srő#ׇ͛M%ኰSvQλ}~.D߃xf8WڜmdT+]\P;f :kjݞ+cq5/PLQU ;R6n(W܅H\K`%~[b4[>%OOt1*xD͸1:Sl00a` U,N+g) LLMH=/y 7%"*%zI*4̄&JLYHŸ$R?H|LEA"H`$? g5TH[0&b ǯ̈́gDdDE" nn~IENDB`spyder-3.2.6/spyder/images/actions/window_nofullscreen.png0000664000175000017500000000127713026261006024634 0ustar carloscarlos00000000000000PNG  IHDRש cHRMz&u0`:pQ<ePLTEnnn͍ukˆ̋yɀukpeUNslunƉђ{ӛ̃ukrfWPYRsmnj}uleԔ~ђ֝sgZRŊ~~vjbqe֞ءth\TɎȍg_rf^V`XbYd[f\RLTNVOXQZSA>B?C@EAFB[T}\TB?snqm`Yslzs_VD@pld^^Zc\tnsl_WaXEALGc_yua]qjNjcZGCSOgbd_{„nj[UEtRNS@fbKGDhQ pHYs  IDAT(ϵ=N@FߋkkQ܀:"ŀLRػJU3zI M;]S+rnQ c .qY]-K+;$VWohӚ<`%0~\A?f Nu<04̡cl_$LI<6zJ|M] xIENDB`spyder-3.2.6/spyder/images/actions/special_paste.png0000664000175000017500000000141113026261006023350 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FtPLTECe6 wJ"wI tFV0tDrCsDj;W&e6ƧW&e6s;e6+e5'((555444334d5333e5d5[+ j;k<j;h8 x`344e\@jjmgghhhi\\\ʳʸĦzwuywtھ–j_-׻hY]׷e1oӴв74ͯS{Iˬ|JɨƦsDq@ám@j=_/}nzC6tRNSeB¿įY4zzzz`zWĸ)0\bKGDH pHYs  ~IDATJE{gތ6m*Zm?#EEh-JF]i'L{/.> e?][\Y\?.R6Fvɼ$h;|P[{!AXhT#%x !@HB@8f@R\.o!H0`Op6Z-PIENDB`spyder-3.2.6/spyder/images/actions/expand.png0000664000175000017500000000123713026261006022021 0ustar carloscarlos00000000000000PNG  IHDR(-SgAMA7 cHRMz&u0`:pQ<JPLTEd[ncdZbYk`aYodmci__WYRlaj`h^[S_W]UPJNHLGYROJJEHDWPMHWPUNIETNthsgrfqef\d[bY`X^Vء֞g_ȍɎ\T֝ђ~~v~ŊZRrfuk̃ӛ{}unjsmYRWPpeɀyunslUNcZslqjd_gbGCaX_Wtna]yuc_LGEA_Vzssl^Zd^plD@\T}[TFBqmsnB?ZSXQVOTNRLEAC@B?A>EdtRNS񸳮쳸`XbKGDmIDATJA@{gݙ ;>M!|W[HiEV@FE[ XD@>BW)ol@CB'0xt8z͚B[.Dk%k $jX[MY:IENDB`spyder-3.2.6/spyder/images/actions/exit.png0000664000175000017500000000167013026261006021514 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz&u0`:pQ<CPLTEVP\p7gp7hQ ]VW,Mtryw0PW'R-2/3'QY#Xw4v1WVDFCDV :U 8Q 9K 9>K9Ig fq=m7*s(- %*s!0p48,1!/o9|B]tssrAZ:}KB]bqbqC^L_PfX0"IAibngNF/" ;32) 祡ᐌ70矛 "魪2, up@9 /'.' ?9rnxtA:$#@9vr{B<ꢞ&&衞>7쨥rlrl餡 "2),$.!91_W^W4,%H:xC5tf=tRNS'ab'##;uL m=]0+Gh1J$I1Ii$ d-IENDB`spyder-3.2.6/spyder/images/actions/lock_open.png0000664000175000017500000000060213026261006022506 0ustar carloscarlos00000000000000PNG  IHDR7 cHRMz%u0`:o_F pHYs  bKGD̿IDAT-N\Q}c P]DkЃfH&.B sB=<Bw&DH<3JӛffBHs»Qͤ+1hhشAx55ԕ54  2K5SZ:,/FSQ'&[Ox]*RCMh4{֌ғ?0Mh IENDB`spyder-3.2.6/spyder/images/actions/arrow-step-out.png0000664000175000017500000000075013026261006023451 0ustar carloscarlos00000000000000PNG  IHDRש cHRMz&u0`:pQ<PLTEzܹRVڻZ߼z^arfuq}hrpvNmW߃GSD=|OHd5qnFjZOS:y=)c5)`2nv "tRNSv8bKGD- pHYs(JIDAT(S[@w5$PBL]^}ϼ30#E@"怔 P G֘  :b3t%Js@2aώ%l^U u}ȿ5QGZ#IiB";Ir$)Y(WUOu6sIENDB`spyder-3.2.6/spyder/images/actions/find.png0000664000175000017500000000221613026261006021460 0ustar carloscarlos00000000000000PNG  IHDRw= cHRMz&u0`:pQ<bKGDIDATH_L[u[hӖRm]+n--P(MtrSʟ gCP'n,enŠLԄ`\osfYt1?x؃3SLLMN~=9s.#@J|'Jc3Emԧ rd9[x3++ㆰ`w|>Me68Cww_G9_ n0 s ELSfj,E˽h"?6 c8~Y+(7F r9~4щP_S#;^`aqjB`=hmiC$VMӰ&H6h!U8sţF~ċR~u%h z,-`ށ422Ue=#Yub[sG -`D>B+)FP# a$CtCbv}+vs\)/*tGp *zSPA$:E4R{X"%eTRp5~ xB  }iqxWt+p:0D2읮=O|QQ%w"\Èq~U5 22B8 O#$aQTle;sNTj0*n:Խq$ uI_Ƶ`} CȒJ u>=0^;Wa]aer)))!kX,N%]OMMՒ)ks-#7-ؾCf s/D* XJ?] O:eN30M[.:tf$KjFmUJ+U-Z}G$]$EBzzJo%M233sM(.;4L"IENDB`spyder-3.2.6/spyder/images/actions/editpaste.png0000664000175000017500000000177213026261006022530 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FPLTEtLk8s[?=89:=hefgbmGjf\wPuHl;tIǒg2]+]/\`0\^-yQ[*^G,26?889:::Z(򚚛Y'X&W%~V$~U"}T!}T!vLxP|S |R |R uI|lPSNBz|z{{aaaٰ{aVخźŹŹ˿Ƚy]|Lѩe}LzGjCd@b;a=kHkCͣ{•g}{ysr͝tvxD]꛾șp_8Q@O[YlR{TE;UragQ}I`{h~\azFl[# !~j\vEm:b-s`ZtCsBf.xZvPh=eu[b!yyRN8W#YIENDB`spyder-3.2.6/spyder/images/editor/indent.png0000664000175000017500000000066713026261006021657 0ustar carloscarlos00000000000000PNG  IHDRj cHRMz%u0`:o_F~PLTELDeLDe``TnK,raaٱFTtRNS; :bKGDf |d pHYs  ~IDAT1JCQ95,lAd Jaekc$L{([Y p+(e\AqD/IAvl~/$f^T7( 9`|2(6g 3p5gIENDB`spyder-3.2.6/spyder/images/editor/private2.png0000664000175000017500000000065413026261006022126 0ustar carloscarlos00000000000000PNG  IHDR a cHRMz&u0`:pQ<PLTE~}z{vvhhaaLLL`_LLLZZ]^LLLLLLΪ```ݞrq󣣹uu~~lmhissꗖΌ΃||vuߙΐ͑qq獍_^S utRNSYYh n!/bKGD8hIDATM; PEs{Av6V))\@jD PJ2@x7XY]n*R.t*ɘE81y"зm/yx#@'ЇIENDB`spyder-3.2.6/spyder/images/editor/breakpoint_cond_small.png0000664000175000017500000000146313026261006024722 0ustar carloscarlos00000000000000PNG  IHDR( cHRMz&u0`:pQ<PLTEપڏ>>GGyyԍ㶶ԁAAZZڑuueejjeegghhccAAсcc\\\\֓XXNN>>yyDD((GG33 EEGG**EEyyɓ88ƛ‚ \\ڶtt$$͈ AAcc==PP@@SSRRDD@@II??VVՖ漼ݢ__GGPP>>OOদrr..<<8877׏RR22HH00""mmݪ ,,DD ެͯ%%((22''JJ %%ӓԔ&& $$ 44--"",,CC""((!!GGQBtRNS*~cqqccq*+UɫbKGDU3 pHYs+IDATM Aa=|[! Pdy~R,ghnduY+RfPMK.vwx-I喝>m<=:HѲ8lp)~7iy7߀ލ-@u%K%Яq!jIENDB`spyder-3.2.6/spyder/images/editor/private1.png0000664000175000017500000000065713026261006022130 0ustar carloscarlos00000000000000PNG  IHDR a cHRMz&u0`:pQ<PLTExxvrn҃_xXBBByVBBBpQyTBBBBBBx˺ﻢʹ```ݯj򸝸{t{ފdߝ~qfo魐͘͞ߠyߡ}ܑmެٌ̡͡i椆}VBG|tRNSYYh n!/bKGD9@hIDATM; PEs{AV%)\" rUlៀL $ i $gXեKExt׶;sZ:DzJ2f6zdLd @"A IENDB`spyder-3.2.6/spyder/images/editor/debug.png0000664000175000017500000000264213026261006021457 0ustar carloscarlos00000000000000PNG  IHDRu cHRMz&u0`:pQ< pHYs+tIME 0&hybKGDIDAT8uU[lU^ZMV)ZH xD4)&$cc jW„'qvؚ5Z4m۶׶tDK5V==V7rG+-{d";Jp]_] <`8L w,EV$*L#0xu(W  RwL&pQbU{w,9s, LfќSN^̌QR;ƈx&C ޾Q, V1ZVhA6Mb8%ޝ%^ESKһEh` BŲ1`2k~:H?,-ĨulK~JTy[VYIa %W?:`, atURXQN}iEIu ZT@8# { D `}fKks7*Il|ADسi^l\ {We >9"r :ԁ;]y獕 +;*9χ4.DT!KkaTr*;RyGkCS\M|}BrqW2 ne4xEufs.;Nf!˹u MQ.'A~0د|i՟/z?ypb3s20^]ڲa>9-6ǯm:ο{w4Α[":ŕۡq͋LJu6} >|^pkHQ'KSw[nUړ/, < ܸVubj_UølK͂Xo}-~ϻ yߐG(|?xnL|w; cVQ: .sՉ\6C۔d痼ĩ 8{`rESjaٵT*G<wjSn?8yE@s| :7*0COR,X+:GcF }g5!Pv,<T5fmKYsh&>5}{7ҖHZYv٦XH PV3BYԳѼQ ͹G™U)frNSG+Yٱ0لq CQA,{.z'~+&Ҷ4LɺAt0~C;P(㩿Hϥ@:>=I>"=A W[@02f Ȩ;ȧ>%,yo]k?$;%Vq{sCecd|'Dq>[;;!A8JDl@ Z>vIENDB`spyder-3.2.6/spyder/images/editor/warning.png0000664000175000017500000000076013026261006022035 0ustar carloscarlos00000000000000PNG  IHDR a cHRMz&u0`:pQ<PLTEv r{miv a^omWfOM^GWSQOMKIGEBAŋבWʚÎEV׃NuT5ʛċ0Zpid !ҎܞӅӃԇHO(tRNSU֌~5*SH ~k*Ä<bKGDJ ]IDATцB@9DDZF_!s.ID47I tғզbֺMUnY6tj^򳯨Yj:³IENDB`spyder-3.2.6/spyder/images/editor/attribute.png0000664000175000017500000000102613026261006022367 0ustar carloscarlos00000000000000PNG  IHDR a cHRMz&u0`:pQ<PLTE  FR LO.6 U4/e,ǝà<{|2*u n ytRNS7e1c334aibKGDOnfAI pHYs%%IR$qIDATAJPo .'B/_pMWE"#g$A*4?kHk :a|Lմya }CَJx̭s$9#;I-IENDB`spyder-3.2.6/spyder/images/editor/module.png0000664000175000017500000000132713026261006021655 0ustar carloscarlos00000000000000PNG  IHDR a cHRMz&u0`:pQ<PLTE߿ =-?RUSN@3ܢ::1Sw=s_3M5:1N_NG7<`KNDSDQCK@@AŽ8>;5u6{\+|0>7HJ>A8'<8:BBA>:83Å YmN8زL($Ԝ,':.o>19.(/'rOЅ'"=,t"Ջ !,@858cG˧?tRNS(I}}H(*oq+*rs*M܃WV4~8~7 7\\7t5GbKGDoG pHYs%%IR$UIDATcd`o@ςŒz`s@,ɨUu)\a&.8 7Q1^bXYY1jvvVF$E =LIENDB`spyder-3.2.6/spyder/images/editor/breakpoint_big.png0000664000175000017500000000250313026261006023344 0ustar carloscarlos00000000000000PNG  IHDRĴl; cHRMz&u0`:pQ< pHYs  tIME /&ŏbKGDIDAT8OiLTW_ۘ/%nYa@0-&.T\ *jc?T 18V:mma @ڲBiAIp?FCM3{wEܣ-%EC.ﱱY:-)itgm6-5%&xkgZ5Gf?kex_p;VCyAoffA˩Sd v<[}TP=lӧ7r(H@ΔM&0ޗKJ"GJ Mj}.sp.}C18-DGSsTof29|199~ccߔ3gX8joFMϜ1 j`BG_8H7&dރ5bX Yg\uA;w#yEqfx6|={\/nH-bſmUԶeGC-. f1S>EK>L۶Q,"^,7l~SH=B~~[jb VRɓ^ը1<9t6 = 5kTGܟ?rͣsޜ9tol "CHgTT"#/ #2bhժUߟ>H^Tajg 2gT?jeDs`^2\IFl[A3P!2.išv|e#jg@,6 hFrAA t 3. %K[3bq%KF\eSLiўkFT ,갾d Wv@gN[Bao &…Ԁpk7=H7H-_>YjA d|dB1`vL* rqV&,Y{P?6XKRSif Y[m^Ѹܳ` #;+CK~raU/dEt mJ5븮T:PNsص/q2CfJ&ŋmEyyN4mܽߧ8 ؙ*oݢŠ ocegoɿv{j6edx]߽+uZa^Uk2}#^Wz; Gpb<IENDB`spyder-3.2.6/spyder/images/editor/run_cell.png0000664000175000017500000000171613026261006022175 0ustar carloscarlos00000000000000PNG  IHDR cHRMz&u0`:pQ<PLTESSSDDDBBB<UDDOfJJ [ NFFeQ::m ^ aaab$v&___n pi]]] }jZZZ  WWWs WWWvwVVVQQQLLL---VVVQQQRRRJJJcctttRNS5{ !i -Rk:GED=F bKGDH pHYs?eIDATU1JA矬1?h?G}IENDB`spyder-3.2.6/spyder/images/editor/error.png0000664000175000017500000000070213026261006021515 0ustar carloscarlos00000000000000PNG  IHDR agAMA7 cHRMz&u0`:pQ<PLTEkc~a|`bz_x_v]s\p[옉gnZlYo_eiXgWl]eVbU}瑅aT_S풉쒈]Rg\f[}琄ퟕ厃tRNS@fbKGD hVmIDAT1 PEћ73!/€vv  tjwh=?2-TeguzVf_-">W;_"m?El> [? :4qIENDB`spyder-3.2.6/spyder/images/editor/outline_explorer.png0000664000175000017500000000140713026261006023766 0ustar carloscarlos00000000000000PNG  IHDRש cHRMz&u0`:pQ<PLTErm}m|n}fwctbr]o\n`qeuj{m|{t|u|uu~xudsapbo_o[l~[k}[k~\l~]m^n_o`petrڽѶ̳ʩæưȷͻbNdGJ'H&0*K::_Dz;sI}0ldz[[?d?D}Nc3Kٶ(tRNSy~Y@bKGD:N IDAT(ύjAD_%H[.~!$ET$zquRiL5 HN4Q5&Ω]= 5`:o`iS*ýFR6L<ʺimU#i ߙrfQ1l?edďWM޳u895/[=8W.MR%(n:&|\^\IENDB`spyder-3.2.6/spyder/images/editor/file.png0000664000175000017500000000040513026261006021303 0ustar carloscarlos00000000000000PNG  IHDR7 cHRMz&u0`:pQ<bKGD̿IDAT(uQ! D߰$A{DPBa2^B7`>4]4;t;-N-ĀFtRNS 2DHI3)8<;91"64, &5.#E iT0%-ma$/*l(e`WGCMJ!+|VbKGDb+< pHYs m[IDAT8k[0&CBB#Q`9;Ɋ"kz>b7 ezp<a# K1(I8Cp}? 7.$SKvҙl.O<ۻC(3+* ڪOE.%uX/$' _ޭQP#w ϡY򶨢 b}ݦ3A"4]a ["zA.x|t [+IٷMS1jȘ<;|$v11VSFWkuL)zݸ&ф c'u$^0]Ibesyi@_@ ;IENDB`spyder-3.2.6/spyder/images/editor/function.png0000664000175000017500000000062313026261006022213 0ustar carloscarlos00000000000000PNG  IHDR a cHRMz&u0`:pQ<PLTEqu*GMQQQB%S]Q/QJ X_mP*ǩ-@V \8AӋf2EEQٶ~ٻLl%@ڇA+Ϯ]]{ ;pi&rn@(93cc4g"̙T:gȒ8@0 Gv#n\,Wuj%K$2ԓ&Q_EEP'.X=y2d *=cN5U\I"LlCЁ|,lyٔ)t[>r)k {@hB9iͣJE6S0Hڌf_B k Q׾{75B'=tXG C7m}Z&Puu8e R<&nV*] P04Z`z&TBqCVYB*:6Y,Л\*7?k,hA4!P?,(j6υ4a# ↞Q|~ּ/7.iÂV 1<Ǿ6.\:&f9Rz&>c CherC2f#2u+)7BlOl| ?&t.2^%mcp-.##Bx;u8<*HD|lu+AZytyȧ\Tt"Iy y}74+W>`͵vDuVP`1R6cp6xIENDB`spyder-3.2.6/spyder/images/editor/prev_cursor.png0000664000175000017500000000165213026261006022742 0ustar carloscarlos00000000000000PNG  IHDRש cHRMz&u0`:pQ<PLTEfffcdfadg0,w4%k<&o T Y Y Y VE>IwV  \b$j'jf;j?|pDm4zkmm ]\\\]  ||} 'k ^ ] ]W w+tRNSqqrל}:wSMReֵ ֲOBbKGD+$IDAT(SuнJAYc2 66!y3AME Xm,|!cQP $u-ǝ<JyYM 3binaXsHiK0mMÎcg~vM4„ƚEWF w~<ȠSJ'E޼,K|W&IҭҎDb5|\o܀j$]<ӔP0e5 7$[w/4k\IENDB`spyder-3.2.6/spyder/images/editor/breakpoint_small.png0000664000175000017500000000102413026261006023710 0ustar carloscarlos00000000000000PNG  IHDR E5N cHRMz&u0`:pQ<PLTEiiee88C55QQiiee88eeiimUUQQt//t^^FF22;;BB22[[HHooff``eennHH__RR\\DDQQ11aaBBCCDDVV0099AA5577.. 00==33,,0055++,,//((--11..))**))44&&##$$~$$c~tRNSgg&ggggg bKGDT pHYs  gIDATMA@{i3R{}[i2kzT}<>BBVWU !  "{"$m$LMKyf?@>./.ޗFGF]][~|3tRNS n*s #E4a F_ !EqmCf3,i}6[ 6o;=X6Kָ>*}fi7*_xMe7,nIENDB`spyder-3.2.6/spyder/images/editor/uncomment.png0000664000175000017500000000151013026261006022367 0ustar carloscarlos00000000000000PNG  IHDR D cHRMz&u0`:pQ<PLTE??LLL``챜ڴ·췪4a4YY__VVKKEEKKBB6g6>>;t;4]4-N-G?tRNS 3DHI264"19;<8) ,N!#.5& O-%0*/$E(CGW +?]bKGD[t4 pHYs mVIDAT8V@q0P! 1RJ+2Vv?H .fq)(^A B JbIpRNAIB<+OLv-d#_5E=M$#%@2#[:veQr8h|.1vf) }h-!=vAiOz:fdSI`Vg]-Z/_S  K@]T^UbYwkGlJ6d86f89g:.c0)'>/&o2/j8.h69h<6b= #C3:pB#*L<,($PA=tRNS~ᴼyy4bKGDHIDATJ`y&c+y9utڵRGAj 4ִDi+"^}pFg33~!1E+*D9k`tpLpEK 8i&jdYN:/4TXEAT s—mpΩLsmp'Ww\[BGj i,]uO@YOJn}"٩,IENDB`spyder-3.2.6/spyder/images/editor/refactor.png0000664000175000017500000000061413026261006022173 0ustar carloscarlos00000000000000PNG  IHDR a cHRMz&u0`:pQ<PLTECC::KK@@ cc%%PP\\uuGG## rr33!!Y. tRNSeͩ.bKGDH pHYs 0`IDATA A/%xI\ѱTIdZ|Z[PY֘[}Wo 8^6l` t椐c\HgP2 $ %[_IENDB`spyder-3.2.6/spyder/images/editor/prev_wng.png0000664000175000017500000000164213026261006022217 0ustar carloscarlos00000000000000PNG  IHDRש cHRMz&u0`:pQ<PLTE8(::!*,+0'/}$gvއ%uhxSdbS ZK340,w4%k<&o T Y Y Y VE>IwV  \b$j'jf;j?|pDm4zŋבWʚÎEV׃mNuT5ʛċ0Zpid !ҎܞӅӃԇTRPNLJHFC ]\\\]  ||} 'k ^ ] ]W <EtRNS*˾_M ދ| Mvqqrל}:wSMReֵ ֲ{\_bKGDP6IDAT(caX،I0:*lSgt >F1t &ᷨ"l@wyF PsT VFAFq-: U uBL-R#V `j[ $t@`bD09 ($q9, g``8Ŝ85#ITgMgde`8CLL& \%x" 7IENDB`spyder-3.2.6/spyder/images/editor/outline_explorer_vis.png0000664000175000017500000000202613026261006024645 0ustar carloscarlos00000000000000PNG  IHDRש cHRMz&u0`:pQ<CPLTErm|j{iyfweucs`q]o\n_pbrctn}m|m}retap`p`o_o^n^m]m\l~[k~[k}[l~_obodsuɷ;οꁊۗވS6R2D4;RO{׮Bx7qj;wUqP㢉sGc6̾˾IJ͚ðۭͪ*98tRNS~y_UbKGDPnLIDATJB*)a9BZZ"h)(BQGG84<6Y^wVi\+wn -M̭1P"W%lI4bO-%$e c#Hv"g-I2}w',rA nշ}`E)[ t![ :$6j&cDyw_(Ɖ&;8OB=rcs.!!])7+:4/?6!)IENDB`spyder-3.2.6/spyder/images/editor/fromcursor.png0000664000175000017500000000070013026261006022563 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMR@}y<s9P0&E"3s!@ƩddL ]M{kv8ѲI"%(ʏjlPUU\=U_Q٦ΨJ(/g1Fac 3 (Dm~rbG<6j|-\L!_<މymX&k64[j cLPcyRݗt/sGųˍkS77g;?amo̙nsiuG0fťlcЯq+5!yf*΂`GS3/Oe2x1bCs7KS G(3k~ 3(ًh7M#LX;B47?mٙ2BC9#o2FڮmZ|oW6skf483cSaAtWX\p}J)r|`= Ύ-OLX<13p$~OGR@i j"0jGnWРq=K÷fN0;:r ds5ra-04[Zi0\ rE!M(%UE#ײܯx.xz뫌޿4VtNoDs8&Hrl``PO(!anS'7?_W>9ڍaT Ϋj~)TTpl`TH^HD+ #Jf#'ߨ#лgF\0lp[Ux9kxƜ$\3m+փzBh҄G['gUw/,MJ@p 2F(S65NJ5KMx2ArSM=5lCr4ˮXbkkB E!vXÈ(t\3zvn" Ԉ;Wuo6đ J`[>x渎Q^7>m7t@-nh@ٝC-x:\Gdu Dk \t\4_ƭn!eEPQ^lN/0KJ$e ]b*G|;]M+UiO=IncZo/qY2٩ "p7c4_3'=>8t%o>ey64+MZ|TC!?ӓ+PN -aĘIENDB`spyder-3.2.6/spyder/images/editor/unindent.png0000664000175000017500000000067413026261006022220 0ustar carloscarlos00000000000000PNG  IHDRj cHRMz%u0`:o_FPLTELDeLDeLDe'n8z'nK9zc ZT&nٱ-(tRNSa#bKGD L pHYs  ~IDATWm0Eь6(hE)*J\i~<>0F#FI}sj7Fșų yX =B,W5층ސNbIENDB`spyder-3.2.6/spyder/images/editor/highlight.png0000664000175000017500000000110513026261006022331 0ustar carloscarlos00000000000000PNG  IHDR(-SgAMA7 cHRMz&u0`:pQ< PLTEZZZZQJ;ummm___NNN<<<)))".O,`ߴ!Y%X P PKK}tJΓ ݘՎ;;;;;;<;;"wwwmmm___NNN<<<)))#Lꑹ玹w׋䈪ߞ^ƗZQ܊ VwZ`lfܟHٳ@'1L,tRNS**uuuuuu_ K QZfNϢ'bKGDHtIDATW 0D_B>AAš)do{!dʈmT_B^zI~R:QvzeGD:,"lT/"j(4 @ثzp7_1R^IENDB`spyder-3.2.6/spyder/images/editor/run_selection.png0000664000175000017500000000177313026261006023246 0ustar carloscarlos00000000000000PNG  IHDR cHRMz&u0`:pQ<PLTESSSDDDBBB<UDDOfJJ [ NFFeQ::m ^ aaab$v&___n pi]]] }jZZZ  WWWs WWWvwVVVQQQLLL---VVVQQQRRRJJJcctttRNS5{ !i -Rk:GED=F bKGDH pHYsIDATU=JCA;s&"7`;l-,=XYf܁(8s&yI XA,S9fd33 I'hG4w)&~eژ+Nul ƲNlm,ΝlBy, ԺR|5guSuHe33#2j EIaBa.K `@m< mD|(3>ۗĒ>;%7IENDB`spyder-3.2.6/spyder/images/editor/next_cursor.png0000664000175000017500000000165513026261006022747 0ustar carloscarlos00000000000000PNG  IHDRש cHRMz&u0`:pQ<PLTEfffadgcdf,w0%k4>E V Y Y Y T&o<wI V \'j$jb;f?|jDp4zmkmm]\\\]   }||W ] ] ^'k ?5#+tRNSqq:}rSwMRe ֲ.bKGD+$IDAT(uJ@KJ7,\UQ^ܸDbE%J i\$10ϜfN@©<hBUr)a_afА5ڝnݧ禟aVhvIq ,`@Vj`rUQAol9P:rh_*'y|3]B([.&a'#R}-ǫ}BqJ-P/@8WIENDB`spyder-3.2.6/spyder/images/editor/versplit.png0000664000175000017500000000202513026261006022234 0ustar carloscarlos00000000000000PNG  IHDRש cHRMz&u0`:pQ<PLTErm|j{iyfweucs`q]o\n_pbrctn}m|m}x{t{u||uHeM;a@>mBuXdx~retap`p`o_o^n^m]m\l~[k~[k}[l~_o,T:!^1bodsu2H?%U# S*q#NտһϷͳʰȬƩæůݶkpY|YRuR_|anr¾½=iA܋ߕݒ=dA=kAmf~v~;e@=nAvn{rwSI`Vg]-Z/_S  K@]T^UbYwkGlJ6d86f89g:.c0)'>/&o2/j8.h69h<̾Ȼŵ®ȷʻ6b= #C3:pB#*L<,($PA{>Y"<摢9VQTĕUbH1q(ZA5, n 9N55ռ:䨷' gFX8??NYyk)g|71X&wSIENDB`spyder-3.2.6/spyder/images/editor/close_panel.png0000664000175000017500000000210313026261006022645 0ustar carloscarlos00000000000000PNG  IHDRש cHRMz&u0`:pQ<PLTEttuuOOOOONML3/0-;6A:=86/3,5140/+++qAAPP.+43.*-*-*-*-*,*,)/,#% #" &#:98,).,rm|j{iyfweucs`q]o\n_pbrctn}m|m}x{t{u||uux~retap`p`o_o^n^m]m\l~[k~[k}[l~_obodsuտһϷͳʰȬƩæůݶb33400-<7A;>9604,6251/,+,pABi,, >6RIUNNFKFMIROXT\YnMLx,,c  #,&0)5-933/YV.,#% "" &#DBctRNS~yTbKGDbZqIDATu=NQ@{PgI k$P L4b1h`9⾠QBYG]m+wЍ8`@&r\بheȌcAG#Ȥ:ѪDVEs*>jZ#SʏŽL 3;l-Ė;ufcVzt9i w&`/IENDB`spyder-3.2.6/spyder/images/editor/gotoline.png0000664000175000017500000000061713026261006022211 0ustar carloscarlos00000000000000PNG  IHDRa~e cHRMz&u0`:pQ<iPLTEz=1ȁ= pwFM@rbXtRNSeB/sXM&8Lǿ!;yZo6XbKGD"]e\IDATWe]  JCŴ @p̙ݝg F4*$ji{s w@FPm7[Ux*! Q ~M7GwKQ#G +FM<IENDB`spyder-3.2.6/spyder/images/editor/selectall.png0000664000175000017500000000230513026261006022335 0ustar carloscarlos00000000000000PNG  IHDR D cHRMz&u0`:pQ<%PLTE݈yyw؂~{x{vrupnpkjlggiedfbbe`ac_`b^mojwzt|y뤻ӯݤңҲ򅜴뇛ӼݣѢѨֱ씫ð쫾ԫӪӵ޻ꥼԥӬߵ޵衸Р戛墹Сϩז䟶䕕肂!0ttRNSMUPZZX[_dhlortvwi`\bKGD- pHYs+IDAT8O}ѽkq~1AMMuJqN.>P77 gRPTpRHI>6$!s`Y}@'cV  ;d 1^#0fMV1P aڬT6B%I&YI;%_10uT,dXT~3W%ހ'`VP_])zu͕Dֲ9u巒WQet ?Ḃ')^ X&/e0]Z$h 03~\eJ>{ѶB)N9 6w L}ק,rT䶬<N:T/ߊ@:<@q\~L!EIENDB`spyder-3.2.6/spyder/images/editor/no_match.png0000664000175000017500000000024113026261006022152 0ustar carloscarlos00000000000000PNG  IHDR ~aJ cHRMz&u0`:pQ<tRNSv8bKGD݊ pHYs IDATc` $.qIENDB`spyder-3.2.6/spyder/images/editor/run.png0000664000175000017500000000154613026261006021177 0ustar carloscarlos00000000000000PNG  IHDRj cHRMz&u0`:pQ<PLTE\OPGGNNL@PJTdd[M\ddfNd]]QmXOs77` ` y5w5#r$k} O 't(#v%`n n wu e vt w {  y z )) ӛHHljLJ\\yyuuiiddggjjYYRRVVYY\\(u(JJAADDHHKKNNRR33;;003377::==@@CC44(())((((++//2255 vgXufx N%GtRNS/4wթFxL`{q<r?O[H/bKGDH pHYsaa0UIDATmб 0r58TpꠛO cA Et.$TgwF; d{=5bp)1rYIwV  \b$j'jf;j?|pDm4z2f]kmm ]\\\]  ||} 'k ^ ] ]W +tRNSqqrל}:wSMReֵ ֲOBbKGD+$IDAT(m.Cq߷AZV QcXhDbeIA.ArR ih3d.$ d9IB.C80fBRCJK^ &Y'E0]^MDHf͆)rԿdpDےּN 2}uavҊ!ޭ x A 4&Sgcf+ѰWkn*;׽J*UwZ97RNIENDB`spyder-3.2.6/spyder/images/editor/cell.png0000664000175000017500000000032113026261006021300 0ustar carloscarlos00000000000000PNG  IHDR [A cHRMz&u0`:pQ<PLTEnnn땕33Y0utRNS@fbKGDhQ7IDAT0-0 Ygu׌#нNPDd +IENDB`spyder-3.2.6/spyder/images/editor/horsplit.png0000664000175000017500000000222513026261006022232 0ustar carloscarlos00000000000000PNG  IHDRש cHRMz&u0`:pQ<PLTErm|j{iyfweucs`q]o\n_pbrctn}m|m}XuhHeL:a?>mAXdretap`p`o_o^n^m]m\l~[k~[k}[l~_o*S7 ^/bodsu2H?%U# S*q#Nyɷ;ο𤫸ŵŷȹkpY|YRuR_|anr˽=iA܋ߕݒ=dA̻=kAmf~v~;e@˻=nAvn{rwSI`Vg]-Z/_S  K@]T^UbYwkGlJ6d86f89g:.c0)'>/&o2/j8.h69h<̪6b= #C3:pB#*L<,($PAqBtRNS~y梞(bKGDHIDAT=JCA=s$d Bc%V p+H/{p+-D&ϣ@鼎iGTbÍی =s_Kf )) + `(!M%iDʭ51*-^F9Q-OPo [us{8\d\yYl3n~fqE0iĚcps6r RZOIENDB`spyder-3.2.6/spyder/images/editor/next_wng.png0000664000175000017500000000165013026261006022220 0ustar carloscarlos00000000000000PNG  IHDRש cHRMz&u0`:pQ<PLTE8(::!*,+0'/}$gvއ%uhxSdbS ZK43,w0%k4>E V Y Y Y T&o<wI V \'j$jb;f?|jDp4zmŋבWʚÎEV׃mNuT5ʛċ0Zpid !ҎܞӅӃԇTRPNLJHFC]\\\]   }||W ] ] ^'k ~EtRNS*˾_M ދ| Mvqq:}rSwMRe ֲbKGDP6IDAT(c` 021#8L& 3v fG&&N,\,LLN̼psa >FF 8f0 {8#[TDXXYY=`vg($&*&τj;# y ya Q.A>@ ./##TvE3RL@Ap23r3Bs HpF)K2ؤ12<`23<bM N8  :~ IENDB`spyder-3.2.6/spyder/images/editor/convention.png0000664000175000017500000000063213026261006022550 0ustar carloscarlos00000000000000PNG  IHDR a cHRMz&u0`:pQ<PLTE=======? Dگ7g@ǓحNZāHX68!Cb5R6 0Q#@5"? ?n7&G=b!@+Q%G1\(M5d8k <*OJ9m2_=LZNAz'KJC~8kHPE2[+&I#C [nj{j|Xs[v`zxf[v[uSmBhBivBjBi?e'Y(\2fDrV*_r(^([!P{ Dw=n(7q:;v0a'<pB^Z5 zbKGDJ pHYs  ~IDATE1  lIQJR )LF Q"jYe`e(J(d0$! K"!y$%ߌpL!@#BeCt<]8D@{aA%銟{5RVBRRXJ1s}]#BtIENDB`spyder-3.2.6/spyder/images/bold.png0000664000175000017500000000026513026261006020022 0ustar carloscarlos00000000000000PNG  IHDR7 cHRMz&u0`:pQ<bKGD̿BIDAT(c`L@?&V i;L4)5``fϊ 000MA9IENDB`spyder-3.2.6/spyder/images/file/0000775000175000017500000000000013225025007017310 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/images/file/print.png0000664000175000017500000000221513026261006021152 0ustar carloscarlos00000000000000PNG  IHDRש cHRMz&u0`:pQ<PLTE```qqq ʡUUV;;;778_``ĵ[\\sttopp}~~eefVVVPPQEEEOOOCCC???HIHKLKKLKDEDMNMGHG<<>><==:;/,-BBB޾===GFGMLNNLONMOONPPNQPOQPORPPRKIK>>>̵GGGHHIؾ7QtRNS^c̿@;;4Isu<ּ#<&Y>mP~`}]+~ݽVkgmKbKGDHIDAT(;JCQE׺~,Z,lM9hkc3r6 ,A/%ZaPEw;HXs?"@[<ՈlNӗRǪzG-Av:rbq)7{.e`HY).j~-Մ m[ZF5׽WL.[De%քNvsDnrv0v+l+;?>%C4IENDB`spyder-3.2.6/spyder/images/file/filesaveas.png0000664000175000017500000000245613026261006022147 0ustar carloscarlos00000000000000PNG  IHDRw= cHRMz&u0`:pQ<bKGDIDATHO]U}Ki/[-UJԑ)5?9hu`H8G^6O s^{98R=:YZۨ*==K۶Nc (XX|c̊U ?T6Oyͳo_];T.[(YǞ}Ǚ B(Eb!F%#FT 7n - XC@Y#Ab((=P@A d ( D@DHӔrqIA@/$GBOs m<Ŭ(hD} kuN|>͛{A$! a-ATԚ@! !xf$ ׹$"aɠ @@+sM9{vZc]eJQ((`ڕ0li;s淬!:mm*gŅim`2uB>91(kJzՎ; (kj4H\oC 4Ǿdn|+ilvT9G-.FIX,C{|i8~ًP(8kEC$M\.sv9hJ[ҋyak>Di1Y s2(J(*gR}{xrijSCΝgGJ*`Y T %<믽_8qff.R,QX^^&M14 #"{bs9}کSJeHxISo94ͦ?bc_Jō ֛LNLp1:;;iii{%O%$!MS4%I"fݵJ֮CLNNǘRhD $IB ϒ(99>>p}Tj59Z6''P|.O>[wcX|zYbT5}{}Z'|Zvt[R9[m:c5&kLj&gϞ+fWNTUUM<LMo_1 cLS@pMUmc_/X[c^ܾKQ S: wp]!i2)6߸@pIENDB`spyder-3.2.6/spyder/images/file/filesave.png0000664000175000017500000000200513026261006021611 0ustar carloscarlos00000000000000PNG  IHDRw= cHRMz&u0`:pQ<bKGDIDATHǝ͋U꩞qBfHFB1AĿ½KW]s#B\(.? !J4a4wWST+x9doi3gΝ}LzJ;k!Ds~:1|ȉ<ܼy'=.]zݳo*Q˗^[eפPopslanƒ;I3!V8b9/ @+=pNΙS>4cf Q+t}"k>d@Uq#kAMI1T3V0ǃ}Rr&g]l2;pH+[4TzmΟqA>; .߿]XJSH!äPea88"hD"aK1"c2V1bfErNojyYMH G0#ebcX9 l{Wx u渦{D JׯߡUxEEhzDKren>y|;4M;!{@I!U8mQUeڶ{fiD3[))R܎jb:4`@'D'ڶTIh,E>0)%#wM3X(4gef+Qyp;dʹf~AJ&|'/%quӇ"u93/Qmx襋7^qFՈѨZ,"ܻC)1̜d8xYu]{z2qٓbB) MYvwsηڶV"U3ی!l9 !LDd""`Kl:woDÜ01aq@6\ èʒlIENDB`spyder-3.2.6/spyder/images/file/filecloseall.png0000664000175000017500000000054513026261006022460 0ustar carloscarlos00000000000000PNG  IHDR(-SgAMA7 cHRMz&u0`:pQ<rPLTE4BRz6Wv1Qq|6DVyomr*5ATpPm&1?Gb~OkNjD^z\wZya~^y[yWrSoj]zWrfUpTqSqEdDcu!tRNSdc?FI QAbKGD%8IDATWc`  ~A)6 I@-# 0210)F6F83F kǪ(ъIENDB`spyder-3.2.6/spyder/images/file/save_all.png0000664000175000017500000000271513026261006021611 0ustar carloscarlos00000000000000PNG  IHDRw= cHRMz&u0`:pQ<bKGDVIDATHǝˏ\Guϙx왉 c,LHV% $X0 +6(A@"F,0!q&I4'v^qOO?{T"9#]UΧ}{ᯜ87NիFf$ vxyUNaVVxϳMk,[}h޽{ߝ;ǿMɜLu+8*+8@UՈ8Dxɧ1} hل0x!`"۵րKƵ~` UJ"I@DpsFS_旿5G~}.ʢ"C)E- ]~p4ִt+W6jpwq4C񱟮G ~xωS1o,|"#D C@=d׻#Q(JPj0FmΫ,"V $ʢbZ *IX4js#MS# Y`1;]\$Qe NnJ{O EhZ[fLk1BŤҥW"9q""wE ( ]?q=GUU8H"ڔI1!xL&%шxh\0{H$O0dyy7 ^cj&BN CUUX[#a?ZTTBLPَ\J)r nuԕxa:%UUcdZcP5"bDI3V={nXrR3g9t| \pA)E7v\>zcǏ- [[uuSBls$>|~/e] Sn-1}};Sm`X+N<`C&* KS*IENDB`spyder-3.2.6/spyder/images/file/filenew.png0000664000175000017500000000051213026261006021445 0ustar carloscarlos00000000000000PNG  IHDRJ~s cHRMz&u0`:pQ<bKGD̿IDAT8˕0&>>xhvuIG:>`ط_y- / P(™{Ip@0KXs%`OH1շ&!xka , j^ES `]ՠ`@yk 1mY}** `7#Ft㳎Q?;&fc[CvsT)ll.IENDB`spyder-3.2.6/spyder/images/file/fileopen.png0000664000175000017500000000237413026261006021625 0ustar carloscarlos00000000000000PNG  IHDRש cHRMz&u0`:pQ<PLTEެXXXNNNKKKJJJHHHFFFDDDCCCBBB???<<<|wwwzdbbx(%%(%%WTTu(%%(%%(%%(%%!WUUr(%%(%%(%%!VTTq(%%(%%(%%!USSd(%%!USSƚ]I/}(y(%%!WUU֪mgd:Xspp v(%%%"":77̸;Uyc%6I(%%%""uss >Y_&,5)+1(')洿ᦽ菾呿ૻǯ쌻㎻㍻সƪ鋸ኸॷƨ臵އ݈ߤŨ牴܀$ɹutRNS5[r0@Ru0SRRRRRRRRQ[9O\&)$g 73q@B{о.Nߖ^q+dn5ap @+ dl  ebKGDHIDAT(Se?/CaGjqcАHL,*&B /  Cgf'dS%Rý,9ȕYaŜQL?DF$ᵸb.I#Ks F.[ycY?Ւ.<-E)V5/xqVTׁlTK7T4lFKx\MVZZu_7`P@?T6'57^P 2*x`-H֮IENDB`spyder-3.2.6/spyder/images/file/fileimport.png0000664000175000017500000000410513026261006022170 0ustar carloscarlos00000000000000PNG  IHDR szz cHRMz&u0`:pQ<bKGDIDATXÍk]Uq޹wm)ePl DPQ!Z#|1Z)-!UQ?b J0|DJ!ЖBȔ)әL>c{vng=^{})[{x'MdAnz}TI\C,w. 6 v9`GPyz){ptzsT-(.R +x4v-漼|N/G{}  ) PphYqgx3.SK5\nݜgcC>\GBYH%*J(%֭#"<Ä]) MSRJ5_{1aWs 'P^hJZFa5Sqr~jf0&(' 8 [@zBSRhM\P!VA$(&˒4Kꑓ`|~* (%wE))Σ Me{3x Cp L7j(m(T5FEK觟~>`ֵ@&%`%p4X,L0 Bl @7^ -l W JҘ7xhQA<B;S LGLk.7LBJ:UrYbV8^8I$ù̥41cҠNPnA[7VM\j,%=M&pYN%\HTx80iԿ挾c0Y;Ai^uky]9|xР4$Y.)wcWm{JyR"g\I9'S\7sDd:X= g jpR`K/DG$]q%iPֽLe$4PAА!v\u,MJJi2MK/?mS{E)}}ey]g/?ڋVapU) y1Dž) N Tg( 2`MZBJ<ۿ08:qWWPjӬhn~> g/?c#| y-Q* pI@fTkUzlE~ V~+R{A)R,MQQĞ <{O#cC;$$8(+j^'H3\ cL xd#^vh& 3Y6(mXs^|1WV02:* y&Q`UW% -yʀ./bOv}ހjlUF7Ə]=NwǛAL6RBxBMicFhǗvqێUZ!nZeq7]xl"ҨA'ci4ʊS䟿×?^9{Jݜ3kBSNʼ6ݣqq/.AOS|u5z "x;BD~f*nx7T&8x`x H\y ~|j>s+V_?L1/3?s7>㝿8qlyw#j@~^lxus m.̎s W-F.:.~ `Ra8soR ׻9=Gi821KMek64s9f1lݺu y9'X3I׽v_Ƿ| PVЦE,pkTROI(hsC.$rs[-hA)TjfD!jBmc}MIENDB`spyder-3.2.6/spyder/images/file/fileclose.png0000664000175000017500000000226413026261006021767 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FPLTE7Pi.CZ2MkIhHgQp^}VuXw^~;Sl!-6?`<\{^}Qq0Op6Wx -7<]|]|Rr2Qs]| )%'5H$6#5 /E9]1Qs^{Xubb\{`ZyCbc\{]|[zGfKkYw;Wv ;Ic>]{=[zPj ?Rbv6Wv1Qq[k.9BU[c}6Tt-LkyV`jGWjh~YwPog}AUj%"! .'.)EVtLj.K *GfF]vH_x,Ii=]}NgOh;Z{4UuNgMe-KjE`{WpSkF`{XrdWxTtTllcE`|dSrQpZqJdaCdUoeZyYx\tUoJiUuYsngYtXwեԆЪВ֠twchwby`widwq_|[zHhKjca~JjXwXvNnB`?_?_~Cb8Wv;Zy7VuSq[x>]}=[z=\|=\{=]{\zEeGfLlb~gMmIhFe^{[xMlSrYxnmZyRr\yTnRrWwaxycWvSsUob}q}nb|tm]tRNS&+)NF52VO;LhbUnh3D,!0&,>BbOKbN\-R?teEb{:8aaJJMՒʒ|Ec{줺WG}?pQtegtyP夁RArAjTAwwOĶy[xfiqgZcǡkkJUUa՚\\ccXMM|cU""FFiiޒBB{\xxRV||TppKY-\3bKGD)Ԏ6IDATMA7aDF@ t@NtUBbY5z*UtFh `xn1$%6=S_m}b;ZѴ]6U%;Zsnj\]_<{z+xjs`T (.Fќ1IENDB`spyder-3.2.6/spyder/images/dictedit.png0000664000175000017500000000126513026261006020674 0ustar carloscarlos00000000000000PNG  IHDR DgAMA7 cHRMz&u0`:pQ<PLTE~{|z{zzyyywxxuwwtvvsuurttq}}|ssrookmmillhkkgjjfiieiifmmkxxxooliighhehhfhhdggcdd`eeaYYTXXSVVQXXT\\[m%vKtRNSk%&($i}jbKGDYIDAT8͓JaEϙo@VR)؈`?F0NR*Ad,"Hݭĩnq s R k3'UVI~ pHLJ(&1{:`ɛ lH9ox1Æ5_,sAA9 ƅ/r6'fjZP삻2];Ηw7. .p+}IENDB`spyder-3.2.6/spyder/images/vcs_commit.png0000664000175000017500000000113613026261006021243 0ustar carloscarlos00000000000000PNG  IHDR(-SgAMA7 cHRMz&u0`:pQ<PLTEWNRJVMIAUL?8TK:~4j_g\SK=79}3j_f\_URJ<68|2i^f[ZQVMQI;57{1eZ:46z1\S:~45y0SK9}35x/IB8|24w.@97{13v.6z12u-mci_lbтz`Wj`ρaX@9~ymh^}|_Vy΀g\|y]TcYvk҄zj`mcxx\SZQmc{vvZRQId[w~tYQG@\TWO=7e!S,tRNSy{CeA?O}ejt47kY=FWj mզg.׵f@`?}7h8IENDB`spyder-3.2.6/spyder/images/options.svg0000664000175000017500000001113213026261006020603 0ustar carloscarlos00000000000000 image/svg+xml spyder-3.2.6/spyder/images/font.png0000664000175000017500000000146313026261006020051 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz%u0`:o_FPLTE555LLLjjjfffeeedddWWW666EEEJJJDDDIIIGGGCCC[[[gggBBBgggAAAeeeddd```@@@]]]ZZZ???WWWVVV???QQQ///ZZZWVVWWVVVUTTSPPPRRQRRRQQPPOONNN999­xDUkanCRjw5G_,>WΠ3C[N[onxXdwKVjWbucn괸YexO[nݎx:tRNS<]uqqsm=MTLSQLeqLoLoooLooLopNq$Vw.bKGDH pHYs  IDATUM+Q~sμVj"OkvֶW, Ju9` oyğ+K D$?A:. hD|Zʴ6LצnD!lc A9AwB#igc{P>ܷۛ1AVm={\_g+f!D#0J0 1!(`,,DA#3>pL1sfً==u}ѮVwv;"s{s=\L˻$GqI+poTBEM  Vl#sඪj͝ %mKth:fcZ 'lhȎNc9Y E线:򑑩ՙq1OfWozC'a4{^b:`yT!>"ٕ &KtoXt,x#yG2E3D/{c@RaAoNF;WM-hz2]/X\Lh$`R<3F'.bM8~`- 68x/⃃ĥl'RC\Í?#qS"_`@$xpsڑ/POMس'4̏@ /S9N*Rӡf; F$ԸT";ii7 g(^l( t#El8OC:V݊p ,\e?;mےpx1v+'z.$}Tp˪¢Wt蔢qjXi$-jk$ķ_pIvi:i.\sP)TQQpIFk> @ZP3IENDB`spyder-3.2.6/spyder/images/vcs_browse.png0000664000175000017500000000125013026261006021251 0ustar carloscarlos00000000000000PNG  IHDR(-SgAMA7 cHRMz&u0`:pQ<wPLTEQqząoQqĔal+JɘbIj'T{zzyvusrpolɒfzcy`X^ڠ\~޴Z|sXzo鞽TunSsl󙣲wvhda_\~ayȫ暹ߗӸ޹P,tRNSkXeXƓibKGDHIDAT]@@{'#۳d@=Q5PCDL>Fh9|S[6f.SJ?R}ռ(q  OJh#dJ %Wǹ#"y_:GD2*ѪUl~v^J2ŖxIENDB`spyder-3.2.6/spyder/images/keyboard.png0000664000175000017500000000252313026261006020701 0ustar carloscarlos00000000000000PNG  IHDRw= cHRMz&u0`:pQ<bKGDIDATHU}PuB)bj+."$_3S(-[bԁgGIj(™(' x`m c{}<߾I䀋s|_? t8~(|^yቌ{m$tYV/s4 Y }s9"Y\笹Vf=q#~tӨ`-cl"aVNTQ5 a: Șu z"QRnKDܞ)'5ct-Q a0!H|7x UnBy'˴РЂ ւT5WKFH0"IBp_6-NJ'^V0Mê9עGZܼOQ((QjR0a$QvB4o{،)ZjcT^*jL:.A[Eo͵ HR:mܘGKx.|hǜN((_oЬAPfUV8eۢ1V~A_ܦAS8}^fh{763K%SG[45*ݘ)6P)V 7ɔ5ci$^DߧJu]}B >3: Aw_k==^zߢRjw \oJNi>)&oQ)sʄfWK;zq4Brv)O;e.[v$tsd|[ƽjc-H+v59|5vAjnu8t憁ۤ$H%_̠'gT_/yJ Ay o^d T2YOH)|/;>r c٦$:ӒUR iذvaE {/P>z1sb_E)'R$ ai+Èn<7ZpwkCGWIÜ9^p !3dwy?wEО3ʭsTW՟ɽֿ#z?"nط_jKXXVU0oy BH䱳q *D2<|$&:-\F4knk#"DPj` Zu6 =+dFr*mư 'BS~kC#_C/42IENDB`spyder-3.2.6/spyder/images/arrow.png0000664000175000017500000000044113026261006020230 0ustar carloscarlos00000000000000PNG  IHDRa~e cHRMz&u0`:pQ<EPLTEUUEE jUUNNEE99yy--ddVV!!HH~FFw.%8tRNS!tbKGD|ѨJIDAT@0v{SUY4 ~-#V"'B-jHF-J!4&Bk7;4ꜗIENDB`spyder-3.2.6/spyder/app/0000775000175000017500000000000013225025007015704 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/app/mainwindow.py0000664000175000017500000040744313224740762020461 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Spyder, the Scientific PYthon Development EnviRonment ===================================================== Developped and maintained by the Spyder Project Contributors Copyright © Spyder Project Contributors Licensed under the terms of the MIT License (see spyder/__init__.py for details) """ # ============================================================================= # Stdlib imports # ============================================================================= from __future__ import print_function import atexit import errno import os import os.path as osp import re import shutil import signal import socket import subprocess import sys import threading import traceback #============================================================================== # Keeping a reference to the original sys.exit before patching it #============================================================================== ORIGINAL_SYS_EXIT = sys.exit #============================================================================== # Check requirements #============================================================================== from spyder import requirements requirements.check_path() requirements.check_qt() #============================================================================== # Windows only: support for hiding console window when started with python.exe #============================================================================== set_attached_console_visible = None is_attached_console_visible = None set_windows_appusermodelid = None if os.name == 'nt': from spyder.utils.windows import (set_attached_console_visible, is_attached_console_visible, set_windows_appusermodelid) #============================================================================== # Workaround: importing rope.base.project here, otherwise this module can't # be imported if Spyder was executed from another folder than spyder #============================================================================== try: import rope.base.project # analysis:ignore except ImportError: pass #============================================================================== # Qt imports #============================================================================== from qtpy import API, PYQT5 from qtpy.compat import from_qvariant from qtpy.QtCore import (QByteArray, QCoreApplication, QPoint, QSize, Qt, QThread, QTimer, QUrl, Signal, Slot) from qtpy.QtGui import QColor, QDesktopServices, QIcon, QKeySequence, QPixmap from qtpy.QtWidgets import (QAction, QApplication, QDockWidget, QMainWindow, QMenu, QMessageBox, QShortcut, QSplashScreen, QStyleFactory) # Avoid a "Cannot mix incompatible Qt library" error on Windows platforms # when PySide is selected by the QT_API environment variable and when PyQt4 # is also installed (or any other Qt-based application prepending a directory # containing incompatible Qt DLLs versions in PATH): from qtpy import QtSvg # analysis:ignore # Avoid a bug in Qt: https://bugreports.qt.io/browse/QTBUG-46720 from qtpy import QtWebEngineWidgets # analysis:ignore # To catch font errors in QtAwesome from qtawesome.iconic_font import FontError #============================================================================== # Proper high DPI scaling is available in Qt >= 5.6.0. This attibute must # be set before creating the application. #============================================================================== from spyder.config.main import CONF if hasattr(Qt, 'AA_EnableHighDpiScaling'): QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling, CONF.get('main', 'high_dpi_scaling')) #============================================================================== # Create our QApplication instance here because it's needed to render the # splash screen created below #============================================================================== from spyder.utils.qthelpers import qapplication, MENU_SEPARATOR from spyder.config.base import get_image_path MAIN_APP = qapplication() if PYQT5: APP_ICON = QIcon(get_image_path("spyder.svg")) else: APP_ICON = QIcon(get_image_path("spyder.png")) MAIN_APP.setWindowIcon(APP_ICON) #============================================================================== # Create splash screen out of MainWindow to reduce perceived startup time. #============================================================================== from spyder.config.base import _, get_image_path, DEV, PYTEST if not PYTEST: SPLASH = QSplashScreen(QPixmap(get_image_path('splash.svg'))) SPLASH_FONT = SPLASH.font() SPLASH_FONT.setPixelSize(10) SPLASH.setFont(SPLASH_FONT) SPLASH.show() SPLASH.showMessage(_("Initializing..."), Qt.AlignBottom | Qt.AlignCenter | Qt.AlignAbsolute, QColor(Qt.white)) QApplication.processEvents() else: SPLASH = None #============================================================================== # Local utility imports #============================================================================== from spyder import __version__, __project_url__, __forum_url__, get_versions from spyder.config.base import (get_conf_path, get_module_data_path, get_module_source_path, STDERR, DEBUG, debug_print, MAC_APP_NAME, get_home_dir, running_in_mac_app, get_module_path, reset_config_files) from spyder.config.main import OPEN_FILES_PORT from spyder.config.utils import IMPORT_EXT, is_gtk_desktop from spyder.app.cli_options import get_options from spyder import dependencies from spyder.py3compat import (is_text_string, to_text_string, PY3, qbytearray_to_str, configparser as cp) from spyder.utils import encoding, programs from spyder.utils import icon_manager as ima from spyder.utils.introspection import module_completion from spyder.utils.programs import is_module_installed from spyder.utils.misc import select_port, getcwd_or_home from spyder.widgets.fileswitcher import FileSwitcher #============================================================================== # Local gui imports #============================================================================== # NOTE: Move (if possible) import's of widgets and plugins exactly where they # are needed in MainWindow to speed up perceived startup time (i.e. the time # from clicking the Spyder icon to showing the splash screen). try: from spyder.utils.environ import WinUserEnvDialog except ImportError: WinUserEnvDialog = None # analysis:ignore from spyder.utils.qthelpers import (create_action, add_actions, get_icon, add_shortcut_to_tooltip, create_module_bookmark_actions, create_program_action, DialogManager, create_python_script_action, file_uri) from spyder.config.gui import get_shortcut from spyder.otherplugins import get_spyderplugins_mods from spyder.app import tour #============================================================================== # Get the cwd before initializing WorkingDirectory, which sets it to the one # used in the last session #============================================================================== CWD = getcwd_or_home() #============================================================================== # Spyder's main window widgets utilities #============================================================================== def get_python_doc_path(): """ Return Python documentation path (Windows: return the PythonXX.chm path if available) """ if os.name == 'nt': doc_path = osp.join(sys.prefix, "Doc") if not osp.isdir(doc_path): return python_chm = [path for path in os.listdir(doc_path) if re.match(r"(?i)Python[0-9]{3,6}.chm", path)] if python_chm: return file_uri(osp.join(doc_path, python_chm[0])) else: vinf = sys.version_info doc_path = '/usr/share/doc/python%d.%d/html' % (vinf[0], vinf[1]) python_doc = osp.join(doc_path, "index.html") if osp.isfile(python_doc): return file_uri(python_doc) def get_focus_python_shell(): """Extract and return Python shell from widget Return None if *widget* is not a Python shell (e.g. IPython kernel)""" widget = QApplication.focusWidget() from spyder.widgets.shell import PythonShellWidget from spyder.widgets.externalshell.pythonshell import ExternalPythonShell if isinstance(widget, PythonShellWidget): return widget elif isinstance(widget, ExternalPythonShell): return widget.shell #============================================================================== # Main Window #============================================================================== class MainWindow(QMainWindow): """Spyder main window""" DOCKOPTIONS = QMainWindow.AllowTabbedDocks|QMainWindow.AllowNestedDocks CURSORBLINK_OSDEFAULT = QApplication.cursorFlashTime() SPYDER_PATH = get_conf_path('path') SPYDER_NOT_ACTIVE_PATH = get_conf_path('not_active_path') BOOKMARKS = ( ('Python2', "https://docs.python.org/2/index.html", _("Python2 documentation")), ('Python3', "https://docs.python.org/3/index.html", _("Python3 documentation")), ('numpy', "http://docs.scipy.org/doc/", _("Numpy and Scipy documentation")), ('matplotlib', "http://matplotlib.sourceforge.net/contents.html", _("Matplotlib documentation")), ('PyQt4', "http://pyqt.sourceforge.net/Docs/PyQt4/", _("PyQt4 Reference Guide")), ('PyQt4', "http://pyqt.sourceforge.net/Docs/PyQt4/classes.html", _("PyQt4 API Reference")), ('PyQt5', "http://pyqt.sourceforge.net/Docs/PyQt5/", _("PyQt5 Reference Guide")), ('PyQt5', "http://pyqt.sourceforge.net/Docs/PyQt5/class_reference.html", _("PyQt5 API Reference")), ('winpython', "https://winpython.github.io/", _("WinPython")) ) # Signals restore_scrollbar_position = Signal() all_actions_defined = Signal() sig_pythonpath_changed = Signal() sig_open_external_file = Signal(str) sig_resized = Signal("QResizeEvent") # related to interactive tour sig_moved = Signal("QMoveEvent") # related to interactive tour def __init__(self, options=None): QMainWindow.__init__(self) qapp = QApplication.instance() if PYQT5: # Enabling scaling for high dpi qapp.setAttribute(Qt.AA_UseHighDpiPixmaps) self.default_style = str(qapp.style().objectName()) self.dialog_manager = DialogManager() self.init_workdir = options.working_directory self.profile = options.profile self.multithreaded = options.multithreaded self.new_instance = options.new_instance self.open_project = options.open_project self.debug_print("Start of MainWindow constructor") def signal_handler(signum, frame=None): """Handler for signals.""" sys.stdout.write('Handling signal: %s\n' % signum) sys.stdout.flush() QApplication.quit() if os.name == "nt": try: import win32api win32api.SetConsoleCtrlHandler(signal_handler, True) except ImportError: pass else: signal.signal(signal.SIGTERM, signal_handler) if not DEV: # Make spyder quit when presing ctrl+C in the console # In DEV Ctrl+C doesn't quit, because it helps to # capture the traceback when spyder freezes signal.signal(signal.SIGINT, signal_handler) # Use a custom Qt stylesheet if sys.platform == 'darwin': spy_path = get_module_source_path('spyder') img_path = osp.join(spy_path, 'images') mac_style = open(osp.join(spy_path, 'app', 'mac_stylesheet.qss')).read() mac_style = mac_style.replace('$IMAGE_PATH', img_path) self.setStyleSheet(mac_style) # Create our TEMPDIR if not osp.isdir(programs.TEMPDIR): os.mkdir(programs.TEMPDIR) # Shortcut management data self.shortcut_data = [] # Loading Spyder path self.path = [] self.not_active_path = [] self.project_path = [] if osp.isfile(self.SPYDER_PATH): self.path, _x = encoding.readlines(self.SPYDER_PATH) self.path = [name for name in self.path if osp.isdir(name)] if osp.isfile(self.SPYDER_NOT_ACTIVE_PATH): self.not_active_path, _x = \ encoding.readlines(self.SPYDER_NOT_ACTIVE_PATH) self.not_active_path = \ [name for name in self.not_active_path if osp.isdir(name)] self.remove_path_from_sys_path() self.add_path_to_sys_path() # Plugins self.console = None self.workingdirectory = None self.editor = None self.explorer = None self.help = None self.onlinehelp = None self.projects = None self.outlineexplorer = None self.historylog = None self.extconsole = None self.ipyconsole = None self.variableexplorer = None self.findinfiles = None self.thirdparty_plugins = [] # Tour # TODO: Should I consider it a plugin?? or? self.tour = None self.tours_available = None # File switcher self.fileswitcher = None # Check for updates Thread and Worker, refereces needed to prevent # segfaulting self.check_updates_action = None self.thread_updates = None self.worker_updates = None self.give_updates_feedback = True # Preferences from spyder.plugins.configdialog import (MainConfigPage, ColorSchemeConfigPage) from spyder.plugins.shortcuts import ShortcutsConfigPage from spyder.plugins.runconfig import RunConfigPage from spyder.plugins.maininterpreter import MainInterpreterConfigPage self.general_prefs = [MainConfigPage, ShortcutsConfigPage, ColorSchemeConfigPage, MainInterpreterConfigPage, RunConfigPage] self.prefs_index = None self.prefs_dialog_size = None # Quick Layouts and Dialogs from spyder.plugins.layoutdialog import (LayoutSaveDialog, LayoutSettingsDialog) self.dialog_layout_save = LayoutSaveDialog self.dialog_layout_settings = LayoutSettingsDialog # Actions self.lock_dockwidgets_action = None self.show_toolbars_action = None self.close_dockwidget_action = None self.undo_action = None self.redo_action = None self.copy_action = None self.cut_action = None self.paste_action = None self.selectall_action = None self.maximize_action = None self.fullscreen_action = None # Menu bars self.file_menu = None self.file_menu_actions = [] self.edit_menu = None self.edit_menu_actions = [] self.search_menu = None self.search_menu_actions = [] self.source_menu = None self.source_menu_actions = [] self.run_menu = None self.run_menu_actions = [] self.debug_menu = None self.debug_menu_actions = [] self.consoles_menu = None self.consoles_menu_actions = [] self.projects_menu = None self.projects_menu_actions = [] self.tools_menu = None self.tools_menu_actions = [] self.external_tools_menu = None # We must keep a reference to this, # otherwise the external tools menu is lost after leaving setup method self.external_tools_menu_actions = [] self.view_menu = None self.plugins_menu = None self.plugins_menu_actions = [] self.toolbars_menu = None self.help_menu = None self.help_menu_actions = [] # Status bar widgets self.mem_status = None self.cpu_status = None # Toolbars self.visible_toolbars = [] self.toolbarslist = [] self.main_toolbar = None self.main_toolbar_actions = [] self.file_toolbar = None self.file_toolbar_actions = [] self.edit_toolbar = None self.edit_toolbar_actions = [] self.search_toolbar = None self.search_toolbar_actions = [] self.source_toolbar = None self.source_toolbar_actions = [] self.run_toolbar = None self.run_toolbar_actions = [] self.debug_toolbar = None self.debug_toolbar_actions = [] self.layout_toolbar = None self.layout_toolbar_actions = [] # Set Window title and icon if DEV is not None: title = "Spyder %s (Python %s.%s)" % (__version__, sys.version_info[0], sys.version_info[1]) else: title = "Spyder (Python %s.%s)" % (sys.version_info[0], sys.version_info[1]) if DEBUG: title += " [DEBUG MODE %d]" % DEBUG if options.window_title is not None: title += ' -- ' + options.window_title if DEBUG or PYTEST: # Show errors in internal console when developing or testing. CONF.set('main', 'show_internal_console_if_traceback', True) self.base_title = title self.update_window_title() if set_windows_appusermodelid != None: res = set_windows_appusermodelid() debug_print("appusermodelid: " + str(res)) # Setting QTimer if running in travis test_travis = os.environ.get('TEST_CI_APP', None) if test_travis is not None: global MAIN_APP timer_shutdown_time = 30000 self.timer_shutdown = QTimer(self) self.timer_shutdown.timeout.connect(MAIN_APP.quit) self.timer_shutdown.start(timer_shutdown_time) # Showing splash screen self.splash = SPLASH if CONF.get('main', 'current_version', '') != __version__: CONF.set('main', 'current_version', __version__) # Execute here the actions to be performed only once after # each update (there is nothing there for now, but it could # be useful some day...) # List of satellite widgets (registered in add_dockwidget): self.widgetlist = [] # Flags used if closing() is called by the exit() shell command self.already_closed = False self.is_starting_up = True self.is_setting_up = True self.dockwidgets_locked = CONF.get('main', 'panes_locked') self.floating_dockwidgets = [] self.window_size = None self.window_position = None self.state_before_maximizing = None self.current_quick_layout = None self.previous_layout_settings = None # TODO: related to quick layouts self.last_plugin = None self.fullscreen_flag = None # isFullscreen does not work as expected # The following flag remember the maximized state even when # the window is in fullscreen mode: self.maximized_flag = None # To keep track of the last focused widget self.last_focused_widget = None self.previous_focused_widget = None # Server to open external files on a single instance # This is needed in order to handle socket creation problems. # See issue 4132 if os.name == 'nt': try: self.open_files_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP) except OSError as e: self.open_files_server = None QMessageBox.warning(None, "Spyder", _("An error occurred while creating a socket needed " "by Spyder. Please, try to run as an Administrator " "from cmd.exe the following command and then " "restart your computer:

    netsh winsock reset" "
    ")) else: self.open_files_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP) self.apply_settings() self.debug_print("End of MainWindow constructor") def debug_print(self, message): """Debug prints""" debug_print(message) #---- Window setup def create_toolbar(self, title, object_name, iconsize=24): """Create and return toolbar with *title* and *object_name*""" toolbar = self.addToolBar(title) toolbar.setObjectName(object_name) toolbar.setIconSize(QSize(iconsize, iconsize)) self.toolbarslist.append(toolbar) return toolbar def setup(self): """Setup main window""" self.debug_print("*** Start of MainWindow setup ***") self.debug_print(" ..core actions") self.close_dockwidget_action = create_action(self, icon=ima.icon('DialogCloseButton'), text=_("Close current pane"), triggered=self.close_current_dockwidget, context=Qt.ApplicationShortcut) self.register_shortcut(self.close_dockwidget_action, "_", "Close pane") self.lock_dockwidgets_action = create_action(self, _("Lock panes"), toggled=self.toggle_lock_dockwidgets, context=Qt.ApplicationShortcut) self.register_shortcut(self.lock_dockwidgets_action, "_", "Lock unlock panes") # custom layouts shortcuts self.toggle_next_layout_action = create_action(self, _("Use next layout"), triggered=self.toggle_next_layout, context=Qt.ApplicationShortcut) self.toggle_previous_layout_action = create_action(self, _("Use previous layout"), triggered=self.toggle_previous_layout, context=Qt.ApplicationShortcut) self.register_shortcut(self.toggle_next_layout_action, "_", "Use next layout") self.register_shortcut(self.toggle_previous_layout_action, "_", "Use previous layout") # File switcher shortcuts self.file_switcher_action = create_action( self, _('File switcher...'), icon=ima.icon('filelist'), tip=_('Fast switch between files'), triggered=self.open_fileswitcher, context=Qt.ApplicationShortcut) self.register_shortcut(self.file_switcher_action, context="_", name="File switcher") self.symbol_finder_action = create_action( self, _('Symbol finder...'), icon=ima.icon('symbol_find'), tip=_('Fast symbol search in file'), triggered=self.open_symbolfinder, context=Qt.ApplicationShortcut) self.register_shortcut(self.symbol_finder_action, context="_", name="symbol finder", add_sc_to_tip=True) self.file_toolbar_actions = [self.file_switcher_action, self.symbol_finder_action] def create_edit_action(text, tr_text, icon): textseq = text.split(' ') method_name = textseq[0].lower()+"".join(textseq[1:]) action = create_action(self, tr_text, icon=icon, triggered=self.global_callback, data=method_name, context=Qt.WidgetShortcut) self.register_shortcut(action, "Editor", text) return action self.undo_action = create_edit_action('Undo', _('Undo'), ima.icon('undo')) self.redo_action = create_edit_action('Redo', _('Redo'), ima.icon('redo')) self.copy_action = create_edit_action('Copy', _('Copy'), ima.icon('editcopy')) self.cut_action = create_edit_action('Cut', _('Cut'), ima.icon('editcut')) self.paste_action = create_edit_action('Paste', _('Paste'), ima.icon('editpaste')) self.selectall_action = create_edit_action("Select All", _("Select All"), ima.icon('selectall')) self.edit_menu_actions = [self.undo_action, self.redo_action, None, self.cut_action, self.copy_action, self.paste_action, self.selectall_action] namespace = None self.debug_print(" ..toolbars") # File menu/toolbar self.file_menu = self.menuBar().addMenu(_("&File")) self.file_toolbar = self.create_toolbar(_("File toolbar"), "file_toolbar") # Edit menu/toolbar self.edit_menu = self.menuBar().addMenu(_("&Edit")) self.edit_toolbar = self.create_toolbar(_("Edit toolbar"), "edit_toolbar") # Search menu/toolbar self.search_menu = self.menuBar().addMenu(_("&Search")) self.search_toolbar = self.create_toolbar(_("Search toolbar"), "search_toolbar") # Source menu/toolbar self.source_menu = self.menuBar().addMenu(_("Sour&ce")) self.source_toolbar = self.create_toolbar(_("Source toolbar"), "source_toolbar") # Run menu/toolbar self.run_menu = self.menuBar().addMenu(_("&Run")) self.run_toolbar = self.create_toolbar(_("Run toolbar"), "run_toolbar") # Debug menu/toolbar self.debug_menu = self.menuBar().addMenu(_("&Debug")) self.debug_toolbar = self.create_toolbar(_("Debug toolbar"), "debug_toolbar") # Consoles menu/toolbar self.consoles_menu = self.menuBar().addMenu(_("C&onsoles")) # Projects menu self.projects_menu = self.menuBar().addMenu(_("&Projects")) # Tools menu self.tools_menu = self.menuBar().addMenu(_("&Tools")) # View menu self.view_menu = self.menuBar().addMenu(_("&View")) # Help menu self.help_menu = self.menuBar().addMenu(_("&Help")) # Status bar status = self.statusBar() status.setObjectName("StatusBar") status.showMessage(_("Welcome to Spyder!"), 5000) self.debug_print(" ..tools") # Tools + External Tools prefs_action = create_action(self, _("Pre&ferences"), icon=ima.icon('configure'), triggered=self.edit_preferences, context=Qt.ApplicationShortcut) self.register_shortcut(prefs_action, "_", "Preferences", add_sc_to_tip=True) spyder_path_action = create_action(self, _("PYTHONPATH manager"), None, icon=ima.icon('pythonpath'), triggered=self.path_manager_callback, tip=_("Python Path Manager"), menurole=QAction.ApplicationSpecificRole) update_modules_action = create_action(self, _("Update module names list"), triggered=lambda: module_completion.reset(), tip=_("Refresh list of module names " "available in PYTHONPATH")) reset_spyder_action = create_action( self, _("Reset Spyder to factory defaults"), triggered=self.reset_spyder) self.tools_menu_actions = [prefs_action, spyder_path_action] if WinUserEnvDialog is not None: winenv_action = create_action(self, _("Current user environment variables..."), icon='win_env.png', tip=_("Show and edit current user environment " "variables in Windows registry " "(i.e. for all sessions)"), triggered=self.win_env) self.tools_menu_actions.append(winenv_action) self.tools_menu_actions += [reset_spyder_action, MENU_SEPARATOR, update_modules_action] # External Tools submenu self.external_tools_menu = QMenu(_("External Tools")) self.external_tools_menu_actions = [] # WinPython control panel self.wp_action = create_action(self, _("WinPython control panel"), icon=get_icon('winpython.svg'), triggered=lambda: programs.run_python_script('winpython', 'controlpanel')) if os.name == 'nt' and is_module_installed('winpython'): self.external_tools_menu_actions.append(self.wp_action) # Qt-related tools additact = [] for name in ("designer-qt4", "designer"): qtdact = create_program_action(self, _("Qt Designer"), name, 'qtdesigner.png') if qtdact: break for name in ("linguist-qt4", "linguist"): qtlact = create_program_action(self, _("Qt Linguist"), "linguist", 'qtlinguist.png') if qtlact: break args = ['-no-opengl'] if os.name == 'nt' else [] qteact = create_python_script_action(self, _("Qt examples"), 'qt.png', "PyQt4", osp.join("examples", "demos", "qtdemo", "qtdemo"), args) for act in (qtdact, qtlact, qteact): if act: additact.append(act) if additact and is_module_installed('winpython'): self.external_tools_menu_actions += [None] + additact # Guidata and Sift self.debug_print(" ..sift?") gdgq_act = [] # Guidata and Guiqwt don't support PyQt5 yet and they fail # with an AssertionError when imported using those bindings # (see issue 2274) try: from guidata import configtools from guidata import config # analysis:ignore guidata_icon = configtools.get_icon('guidata.svg') guidata_act = create_python_script_action(self, _("guidata examples"), guidata_icon, "guidata", osp.join("tests", "__init__")) gdgq_act += [guidata_act] except (ImportError, AssertionError): pass try: from guidata import configtools from guiqwt import config # analysis:ignore guiqwt_icon = configtools.get_icon('guiqwt.svg') guiqwt_act = create_python_script_action(self, _("guiqwt examples"), guiqwt_icon, "guiqwt", osp.join("tests", "__init__")) if guiqwt_act: gdgq_act += [guiqwt_act] sift_icon = configtools.get_icon('sift.svg') sift_act = create_python_script_action(self, _("Sift"), sift_icon, "guiqwt", osp.join("tests", "sift")) if sift_act: gdgq_act += [sift_act] except (ImportError, AssertionError): pass if gdgq_act: self.external_tools_menu_actions += [None] + gdgq_act # ViTables vitables_act = create_program_action(self, _("ViTables"), "vitables", 'vitables.png') if vitables_act: self.external_tools_menu_actions += [None, vitables_act] # Maximize current plugin self.maximize_action = create_action(self, '', triggered=self.maximize_dockwidget, context=Qt.ApplicationShortcut) self.register_shortcut(self.maximize_action, "_", "Maximize pane") self.__update_maximize_action() # Fullscreen mode self.fullscreen_action = create_action(self, _("Fullscreen mode"), triggered=self.toggle_fullscreen, context=Qt.ApplicationShortcut) self.register_shortcut(self.fullscreen_action, "_", "Fullscreen mode", add_sc_to_tip=True) # Main toolbar self.main_toolbar_actions = [self.maximize_action, self.fullscreen_action, None, prefs_action, spyder_path_action] self.main_toolbar = self.create_toolbar(_("Main toolbar"), "main_toolbar") # Internal console plugin self.debug_print(" ..plugin: internal console") from spyder.plugins.console import Console self.console = Console(self, namespace, exitfunc=self.closing, profile=self.profile, multithreaded=self.multithreaded, message=_("Spyder Internal Console\n\n" "This console is used to report application\n" "internal errors and to inspect Spyder\n" "internals with the following commands:\n" " spy.app, spy.window, dir(spy)\n\n" "Please don't use it to run your code\n\n")) self.console.register_plugin() # Working directory plugin self.debug_print(" ..plugin: working directory") from spyder.plugins.workingdirectory import WorkingDirectory self.workingdirectory = WorkingDirectory(self, self.init_workdir, main=self) self.workingdirectory.register_plugin() self.toolbarslist.append(self.workingdirectory) # Help plugin if CONF.get('help', 'enable'): self.set_splash(_("Loading help...")) from spyder.plugins.help import Help self.help = Help(self) self.help.register_plugin() # Outline explorer widget if CONF.get('outline_explorer', 'enable'): self.set_splash(_("Loading outline explorer...")) from spyder.plugins.outlineexplorer import OutlineExplorer fullpath_sorting = CONF.get('editor', 'fullpath_sorting', True) self.outlineexplorer = OutlineExplorer(self, fullpath_sorting=fullpath_sorting) self.outlineexplorer.register_plugin() # Editor plugin self.set_splash(_("Loading editor...")) from spyder.plugins.editor import Editor self.editor = Editor(self) self.editor.register_plugin() # Populating file menu entries quit_action = create_action(self, _("&Quit"), icon=ima.icon('exit'), tip=_("Quit"), triggered=self.console.quit, context=Qt.ApplicationShortcut) self.register_shortcut(quit_action, "_", "Quit") restart_action = create_action(self, _("&Restart"), icon=ima.icon('restart'), tip=_("Restart"), triggered=self.restart, context=Qt.ApplicationShortcut) self.register_shortcut(restart_action, "_", "Restart") self.file_menu_actions += [self.file_switcher_action, self.symbol_finder_action, None, restart_action, quit_action] self.set_splash("") self.debug_print(" ..widgets") # Explorer if CONF.get('explorer', 'enable'): self.set_splash(_("Loading file explorer...")) from spyder.plugins.explorer import Explorer self.explorer = Explorer(self) self.explorer.register_plugin() # History log widget if CONF.get('historylog', 'enable'): self.set_splash(_("Loading history plugin...")) from spyder.plugins.history import HistoryLog self.historylog = HistoryLog(self) self.historylog.register_plugin() # Online help widget try: # Qt >= v4.4 from spyder.plugins.onlinehelp import OnlineHelp except ImportError: # Qt < v4.4 OnlineHelp = None # analysis:ignore if CONF.get('onlinehelp', 'enable') and OnlineHelp is not None: self.set_splash(_("Loading online help...")) self.onlinehelp = OnlineHelp(self) self.onlinehelp.register_plugin() # Project explorer widget self.set_splash(_("Loading project explorer...")) from spyder.plugins.projects import Projects self.projects = Projects(self) self.projects.register_plugin() self.project_path = self.projects.get_pythonpath(at_start=True) # Find in files if CONF.get('find_in_files', 'enable'): from spyder.plugins.findinfiles import FindInFiles self.findinfiles = FindInFiles(self) self.findinfiles.register_plugin() # Namespace browser self.set_splash(_("Loading namespace browser...")) from spyder.plugins.variableexplorer import VariableExplorer self.variableexplorer = VariableExplorer(self) self.variableexplorer.register_plugin() # IPython console self.set_splash(_("Loading IPython console...")) from spyder.plugins.ipythonconsole import IPythonConsole self.ipyconsole = IPythonConsole(self) self.ipyconsole.register_plugin() self.set_splash(_("Setting up main window...")) # Help menu dep_action = create_action(self, _("Dependencies..."), triggered=self.show_dependencies, icon=ima.icon('advanced')) report_action = create_action(self, _("Report issue..."), icon=ima.icon('bug'), triggered=self.report_issue) support_action = create_action(self, _("Spyder support..."), triggered=self.google_group) self.check_updates_action = create_action(self, _("Check for updates..."), triggered=self.check_updates) # Spyder documentation doc_path = get_module_data_path('spyder', relpath="doc", attr_name='DOCPATH') # * Trying to find the chm doc spyder_doc = osp.join(doc_path, "Spyderdoc.chm") if not osp.isfile(spyder_doc): spyder_doc = osp.join(doc_path, os.pardir, "Spyderdoc.chm") # * Trying to find the html doc if not osp.isfile(spyder_doc): spyder_doc = osp.join(doc_path, "index.html") # * Trying to find the development-version html doc if not osp.isfile(spyder_doc): spyder_doc = osp.join(get_module_source_path('spyder'), os.pardir, 'build', 'lib', 'spyder', 'doc', "index.html") # * If we totally fail, point to our web build if not osp.isfile(spyder_doc): spyder_doc = 'http://pythonhosted.org/spyder' else: spyder_doc = file_uri(spyder_doc) doc_action = create_action(self, _("Spyder documentation"), icon=ima.icon('DialogHelpButton'), triggered=lambda: programs.start_file(spyder_doc)) self.register_shortcut(doc_action, "_", "spyder documentation") if self.help is not None: tut_action = create_action(self, _("Spyder tutorial"), triggered=self.help.show_tutorial) else: tut_action = None shortcuts_action = create_action(self, _("Shortcuts Summary"), shortcut="Meta+F1", triggered=self.show_shortcuts_dialog) #----- Tours self.tour = tour.AnimatedTour(self) self.tours_menu = QMenu(_("Interactive tours")) self.tour_menu_actions = [] # TODO: Only show intro tour for now. When we are close to finish # 3.0, we will finish and show the other tour self.tours_available = tour.get_tours(0) for i, tour_available in enumerate(self.tours_available): self.tours_available[i]['last'] = 0 tour_name = tour_available['name'] def trigger(i=i, self=self): # closure needed! return lambda: self.show_tour(i) temp_action = create_action(self, tour_name, tip="", triggered=trigger()) self.tour_menu_actions += [temp_action] self.tours_menu.addActions(self.tour_menu_actions) self.help_menu_actions = [doc_action, tut_action, shortcuts_action, self.tours_menu, MENU_SEPARATOR, report_action, dep_action, self.check_updates_action, support_action, MENU_SEPARATOR] # Python documentation if get_python_doc_path() is not None: pydoc_act = create_action(self, _("Python documentation"), triggered=lambda: programs.start_file(get_python_doc_path())) self.help_menu_actions.append(pydoc_act) # IPython documentation if self.help is not None: ipython_menu = QMenu(_("IPython documentation"), self) intro_action = create_action(self, _("Intro to IPython"), triggered=self.ipyconsole.show_intro) quickref_action = create_action(self, _("Quick reference"), triggered=self.ipyconsole.show_quickref) guiref_action = create_action(self, _("Console help"), triggered=self.ipyconsole.show_guiref) add_actions(ipython_menu, (intro_action, guiref_action, quickref_action)) self.help_menu_actions.append(ipython_menu) # Windows-only: documentation located in sys.prefix/Doc ipm_actions = [] def add_ipm_action(text, path): """Add installed Python module doc action to help submenu""" # QAction.triggered works differently for PySide and PyQt path = file_uri(path) if not API == 'pyside': slot=lambda _checked, path=path: programs.start_file(path) else: slot=lambda path=path: programs.start_file(path) action = create_action(self, text, icon='%s.png' % osp.splitext(path)[1][1:], triggered=slot) ipm_actions.append(action) sysdocpth = osp.join(sys.prefix, 'Doc') if osp.isdir(sysdocpth): # exists on Windows, except frozen dist. for docfn in os.listdir(sysdocpth): pt = r'([a-zA-Z\_]*)(doc)?(-dev)?(-ref)?(-user)?.(chm|pdf)' match = re.match(pt, docfn) if match is not None: pname = match.groups()[0] if pname not in ('Python', ): add_ipm_action(pname, osp.join(sysdocpth, docfn)) # Installed Python modules submenu (Windows only) if ipm_actions: pymods_menu = QMenu(_("Installed Python modules"), self) add_actions(pymods_menu, ipm_actions) self.help_menu_actions.append(pymods_menu) # Online documentation web_resources = QMenu(_("Online documentation")) webres_actions = create_module_bookmark_actions(self, self.BOOKMARKS) webres_actions.insert(2, None) webres_actions.insert(5, None) webres_actions.insert(8, None) add_actions(web_resources, webres_actions) self.help_menu_actions.append(web_resources) # Qt assistant link if sys.platform.startswith('linux') and not PYQT5: qta_exe = "assistant-qt4" else: qta_exe = "assistant" qta_act = create_program_action(self, _("Qt documentation"), qta_exe) if qta_act: self.help_menu_actions += [qta_act, None] # About Spyder about_action = create_action(self, _("About %s...") % "Spyder", icon=ima.icon('MessageBoxInformation'), triggered=self.about) self.help_menu_actions += [MENU_SEPARATOR, about_action] # Status bar widgets from spyder.widgets.status import MemoryStatus, CPUStatus self.mem_status = MemoryStatus(self, status) self.cpu_status = CPUStatus(self, status) self.apply_statusbar_settings() # Third-party plugins for mod in get_spyderplugins_mods(): try: plugin = mod.PLUGIN_CLASS(self) try: # Not all the plugins have the check_compatibility method # i.e Breakpoints, Profiler, Pylint check = plugin.check_compatibility()[0] except AttributeError: check = True if check: self.thirdparty_plugins.append(plugin) plugin.register_plugin() except Exception as error: print("%s: %s" % (mod, str(error)), file=STDERR) traceback.print_exc(file=STDERR) #----- View # View menu self.plugins_menu = QMenu(_("Panes"), self) self.toolbars_menu = QMenu(_("Toolbars"), self) self.quick_layout_menu = QMenu(_("Window layouts"), self) self.quick_layout_set_menu() self.view_menu.addMenu(self.plugins_menu) # Panes add_actions(self.view_menu, (self.lock_dockwidgets_action, self.close_dockwidget_action, self.maximize_action, MENU_SEPARATOR)) self.show_toolbars_action = create_action(self, _("Show toolbars"), triggered=self.show_toolbars, context=Qt.ApplicationShortcut) self.register_shortcut(self.show_toolbars_action, "_", "Show toolbars") self.view_menu.addMenu(self.toolbars_menu) self.view_menu.addAction(self.show_toolbars_action) add_actions(self.view_menu, (MENU_SEPARATOR, self.quick_layout_menu, self.toggle_previous_layout_action, self.toggle_next_layout_action, MENU_SEPARATOR, self.fullscreen_action)) if set_attached_console_visible is not None: cmd_act = create_action(self, _("Attached console window (debugging)"), toggled=set_attached_console_visible) cmd_act.setChecked(is_attached_console_visible()) add_actions(self.view_menu, (MENU_SEPARATOR, cmd_act)) # Adding external tools action to "Tools" menu if self.external_tools_menu_actions: external_tools_act = create_action(self, _("External Tools")) external_tools_act.setMenu(self.external_tools_menu) self.tools_menu_actions += [None, external_tools_act] # Filling out menu/toolbar entries: add_actions(self.file_menu, self.file_menu_actions) add_actions(self.edit_menu, self.edit_menu_actions) add_actions(self.search_menu, self.search_menu_actions) add_actions(self.source_menu, self.source_menu_actions) add_actions(self.run_menu, self.run_menu_actions) add_actions(self.debug_menu, self.debug_menu_actions) add_actions(self.consoles_menu, self.consoles_menu_actions) add_actions(self.projects_menu, self.projects_menu_actions) add_actions(self.tools_menu, self.tools_menu_actions) add_actions(self.external_tools_menu, self.external_tools_menu_actions) add_actions(self.help_menu, self.help_menu_actions) add_actions(self.main_toolbar, self.main_toolbar_actions) add_actions(self.file_toolbar, self.file_toolbar_actions) add_actions(self.edit_toolbar, self.edit_toolbar_actions) add_actions(self.search_toolbar, self.search_toolbar_actions) add_actions(self.source_toolbar, self.source_toolbar_actions) add_actions(self.debug_toolbar, self.debug_toolbar_actions) add_actions(self.run_toolbar, self.run_toolbar_actions) # Apply all defined shortcuts (plugins + 3rd-party plugins) self.apply_shortcuts() # Emitting the signal notifying plugins that main window menu and # toolbar actions are all defined: self.all_actions_defined.emit() # Window set-up self.debug_print("Setting up window...") self.setup_layout(default=False) # Show and hide shortcuts in menus for Mac. # This is a workaround because we can't disable shortcuts # by setting context=Qt.WidgetShortcut there if sys.platform == 'darwin': for name in ['file', 'edit', 'search', 'source', 'run', 'debug', 'projects', 'tools', 'plugins']: menu_object = getattr(self, name + '_menu') menu_object.aboutToShow.connect( lambda name=name: self.show_shortcuts(name)) menu_object.aboutToHide.connect( lambda name=name: self.hide_shortcuts(name)) if self.splash is not None: self.splash.hide() # Enabling tear off for all menus except help menu if CONF.get('main', 'tear_off_menus'): for child in self.menuBar().children(): if isinstance(child, QMenu) and child != self.help_menu: child.setTearOffEnabled(True) # Menu about to show for child in self.menuBar().children(): if isinstance(child, QMenu): try: child.aboutToShow.connect(self.update_edit_menu) except TypeError: pass self.debug_print("*** End of MainWindow setup ***") self.is_starting_up = False def post_visible_setup(self): """Actions to be performed only after the main window's `show` method was triggered""" self.restore_scrollbar_position.emit() # Remove our temporary dir atexit.register(self.remove_tmpdir) # [Workaround for Issue 880] # QDockWidget objects are not painted if restored as floating # windows, so we must dock them before showing the mainwindow, # then set them again as floating windows here. for widget in self.floating_dockwidgets: widget.setFloating(True) # In MacOS X 10.7 our app is not displayed after initialized (I don't # know why because this doesn't happen when started from the terminal), # so we need to resort to this hack to make it appear. if running_in_mac_app(): idx = __file__.index(MAC_APP_NAME) app_path = __file__[:idx] subprocess.call(['open', app_path + MAC_APP_NAME]) # Server to maintain just one Spyder instance and open files in it if # the user tries to start other instances with # $ spyder foo.py if (CONF.get('main', 'single_instance') and not self.new_instance and self.open_files_server): t = threading.Thread(target=self.start_open_files_server) t.setDaemon(True) t.start() # Connect the window to the signal emmited by the previous server # when it gets a client connected to it self.sig_open_external_file.connect(self.open_external_file) # Create Plugins and toolbars submenus self.create_plugins_menu() self.create_toolbars_menu() # Update toolbar visibility status self.toolbars_visible = CONF.get('main', 'toolbars_visible') self.load_last_visible_toolbars() # Update lock status of dockidgets (panes) self.lock_dockwidgets_action.setChecked(self.dockwidgets_locked) self.apply_panes_settings() # Hide Internal Console so that people don't use it instead of # the External or IPython ones if self.console.dockwidget.isVisible() and DEV is None: self.console.toggle_view_action.setChecked(False) self.console.dockwidget.hide() # Show Help and Consoles by default plugins_to_show = [self.ipyconsole] if self.help is not None: plugins_to_show.append(self.help) for plugin in plugins_to_show: if plugin.dockwidget.isVisible(): plugin.dockwidget.raise_() # Show history file if no console is visible if not self.ipyconsole.isvisible: self.historylog.add_history(get_conf_path('history.py')) if self.open_project: self.projects.open_project(self.open_project) else: # Load last project if a project was active when Spyder # was closed self.projects.reopen_last_project() # If no project is active, load last session if self.projects.get_active_project() is None: self.editor.setup_open_files() # Check for spyder updates if DEV is None and CONF.get('main', 'check_updates_on_startup'): self.give_updates_feedback = False self.check_updates(startup=True) # Show dialog with missing dependencies self.report_missing_dependencies() self.is_setting_up = False def update_window_title(self): """Update main spyder window title based on projects.""" title = self.base_title if self.projects is not None: path = self.projects.get_active_project_path() if path: path = path.replace(get_home_dir(), '~') title = '{0} - {1}'.format(path, title) self.setWindowTitle(title) def report_missing_dependencies(self): """Show a QMessageBox with a list of missing hard dependencies""" missing_deps = dependencies.missing_dependencies() if missing_deps: QMessageBox.critical(self, _('Error'), _("You have missing dependencies!" "

    %s

    " "Please install them to avoid this message." "

    " "Note: Spyder could work without some of these " "dependencies, however to have a smooth experience when " "using Spyder we strongly recommend you to install " "all the listed missing dependencies.

    " "Failing to install these dependencies might result in bugs. " "Please be sure that any found bugs are not the direct " "result of missing dependencies, prior to reporting a new " "issue." ) % missing_deps, QMessageBox.Ok) def load_window_settings(self, prefix, default=False, section='main'): """Load window layout settings from userconfig-based configuration with *prefix*, under *section* default: if True, do not restore inner layout""" get_func = CONF.get_default if default else CONF.get window_size = get_func(section, prefix+'size') prefs_dialog_size = get_func(section, prefix+'prefs_dialog_size') if default: hexstate = None else: hexstate = get_func(section, prefix+'state', None) pos = get_func(section, prefix+'position') # It's necessary to verify if the window/position value is valid # with the current screen. See issue 3748 width = pos[0] height = pos[1] screen_shape = QApplication.desktop().geometry() current_width = screen_shape.width() current_height = screen_shape.height() if current_width < width or current_height < height: pos = CONF.get_default(section, prefix+'position') is_maximized = get_func(section, prefix+'is_maximized') is_fullscreen = get_func(section, prefix+'is_fullscreen') return hexstate, window_size, prefs_dialog_size, pos, is_maximized, \ is_fullscreen def get_window_settings(self): """Return current window settings Symetric to the 'set_window_settings' setter""" window_size = (self.window_size.width(), self.window_size.height()) is_fullscreen = self.isFullScreen() if is_fullscreen: is_maximized = self.maximized_flag else: is_maximized = self.isMaximized() pos = (self.window_position.x(), self.window_position.y()) prefs_dialog_size = (self.prefs_dialog_size.width(), self.prefs_dialog_size.height()) hexstate = qbytearray_to_str(self.saveState()) return (hexstate, window_size, prefs_dialog_size, pos, is_maximized, is_fullscreen) def set_window_settings(self, hexstate, window_size, prefs_dialog_size, pos, is_maximized, is_fullscreen): """Set window settings Symetric to the 'get_window_settings' accessor""" self.setUpdatesEnabled(False) self.window_size = QSize(window_size[0], window_size[1]) # width,height self.prefs_dialog_size = QSize(prefs_dialog_size[0], prefs_dialog_size[1]) # width,height self.window_position = QPoint(pos[0], pos[1]) # x,y self.setWindowState(Qt.WindowNoState) self.resize(self.window_size) self.move(self.window_position) # Window layout if hexstate: self.restoreState( QByteArray().fromHex( str(hexstate).encode('utf-8')) ) # [Workaround for Issue 880] # QDockWidget objects are not painted if restored as floating # windows, so we must dock them before showing the mainwindow. for widget in self.children(): if isinstance(widget, QDockWidget) and widget.isFloating(): self.floating_dockwidgets.append(widget) widget.setFloating(False) # Is fullscreen? if is_fullscreen: self.setWindowState(Qt.WindowFullScreen) self.__update_fullscreen_action() # Is maximized? if is_fullscreen: self.maximized_flag = is_maximized elif is_maximized: self.setWindowState(Qt.WindowMaximized) self.setUpdatesEnabled(True) def save_current_window_settings(self, prefix, section='main', none_state=False): """Save current window settings with *prefix* in the userconfig-based configuration, under *section*""" win_size = self.window_size prefs_size = self.prefs_dialog_size CONF.set(section, prefix+'size', (win_size.width(), win_size.height())) CONF.set(section, prefix+'prefs_dialog_size', (prefs_size.width(), prefs_size.height())) CONF.set(section, prefix+'is_maximized', self.isMaximized()) CONF.set(section, prefix+'is_fullscreen', self.isFullScreen()) pos = self.window_position CONF.set(section, prefix+'position', (pos.x(), pos.y())) self.maximize_dockwidget(restore=True)# Restore non-maximized layout if none_state: CONF.set(section, prefix + 'state', None) else: qba = self.saveState() CONF.set(section, prefix + 'state', qbytearray_to_str(qba)) CONF.set(section, prefix+'statusbar', not self.statusBar().isHidden()) def tabify_plugins(self, first, second): """Tabify plugin dockwigdets""" self.tabifyDockWidget(first.dockwidget, second.dockwidget) # --- Layouts def setup_layout(self, default=False): """Setup window layout""" prefix = 'window' + '/' settings = self.load_window_settings(prefix, default) hexstate = settings[0] self.first_spyder_run = False if hexstate is None: # First Spyder execution: self.setWindowState(Qt.WindowMaximized) self.first_spyder_run = True self.setup_default_layouts('default', settings) # Now that the initial setup is done, copy the window settings, # except for the hexstate in the quick layouts sections for the # default layouts. # Order and name of the default layouts is found in config.py section = 'quick_layouts' get_func = CONF.get_default if default else CONF.get order = get_func(section, 'order') # restore the original defaults if reset layouts is called if default: CONF.set(section, 'active', order) CONF.set(section, 'order', order) CONF.set(section, 'names', order) for index, name, in enumerate(order): prefix = 'layout_{0}/'.format(index) self.save_current_window_settings(prefix, section, none_state=True) # store the initial layout as the default in spyder prefix = 'layout_default/' section = 'quick_layouts' self.save_current_window_settings(prefix, section, none_state=True) self.current_quick_layout = 'default' # Regenerate menu self.quick_layout_set_menu() self.set_window_settings(*settings) for plugin in self.widgetlist: try: plugin.initialize_plugin_in_mainwindow_layout() except Exception as error: print("%s: %s" % (plugin, str(error)), file=STDERR) traceback.print_exc(file=STDERR) def setup_default_layouts(self, index, settings): """Setup default layouts when run for the first time""" self.set_window_settings(*settings) self.setUpdatesEnabled(False) # IMPORTANT: order has to be the same as defined in the config file MATLAB, RSTUDIO, VERTICAL, HORIZONTAL = range(4) # define widgets locally editor = self.editor console_ipy = self.ipyconsole console_int = self.console outline = self.outlineexplorer explorer_project = self.projects explorer_file = self.explorer explorer_variable = self.variableexplorer history = self.historylog finder = self.findinfiles help_plugin = self.help helper = self.onlinehelp plugins = self.thirdparty_plugins global_hidden_widgets = [finder, console_int, explorer_project, helper] + plugins global_hidden_toolbars = [self.source_toolbar, self.edit_toolbar, self.search_toolbar] # Layout definition # layouts are organized by columns, each colum is organized by rows # widths have to add 1.0, height per column have to add 1.0 # Spyder Default Initial Layout s_layout = {'widgets': [ # column 0 [[explorer_project]], # column 1 [[editor]], # column 2 [[outline]], # column 3 [[help_plugin, explorer_variable, helper, explorer_file, finder] + plugins, [console_int, console_ipy, history]] ], 'width fraction': [0.0, # column 0 width 0.55, # column 1 width 0.0, # column 2 width 0.45], # column 3 width 'height fraction': [[1.0], # column 0, row heights [1.0], # column 1, row heights [1.0], # column 2, row heights [0.46, 0.54]], # column 3, row heights 'hidden widgets': [outline], 'hidden toolbars': [], } r_layout = {'widgets': [ # column 0 [[editor], [console_ipy, console_int]], # column 1 [[explorer_variable, history, outline, finder] + plugins, [explorer_file, explorer_project, help_plugin, helper]] ], 'width fraction': [0.55, # column 0 width 0.45], # column 1 width 'height fraction': [[0.55, 0.45], # column 0, row heights [0.55, 0.45]], # column 1, row heights 'hidden widgets': [outline], 'hidden toolbars': [], } # Matlab m_layout = {'widgets': [ # column 0 [[explorer_file, explorer_project], [outline]], # column 1 [[editor], [console_ipy, console_int]], # column 2 [[explorer_variable, finder] + plugins, [history, help_plugin, helper]] ], 'width fraction': [0.20, # column 0 width 0.40, # column 1 width 0.40], # column 2 width 'height fraction': [[0.55, 0.45], # column 0, row heights [0.55, 0.45], # column 1, row heights [0.55, 0.45]], # column 2, row heights 'hidden widgets': [], 'hidden toolbars': [], } # Vertically split v_layout = {'widgets': [ # column 0 [[editor], [console_ipy, console_int, explorer_file, explorer_project, help_plugin, explorer_variable, history, outline, finder, helper] + plugins] ], 'width fraction': [1.0], # column 0 width 'height fraction': [[0.55, 0.45]], # column 0, row heights 'hidden widgets': [outline], 'hidden toolbars': [], } # Horizontally split h_layout = {'widgets': [ # column 0 [[editor]], # column 1 [[console_ipy, console_int, explorer_file, explorer_project, help_plugin, explorer_variable, history, outline, finder, helper] + plugins] ], 'width fraction': [0.55, # column 0 width 0.45], # column 1 width 'height fraction': [[1.0], # column 0, row heights [1.0]], # column 1, row heights 'hidden widgets': [outline], 'hidden toolbars': [] } # Layout selection layouts = {'default': s_layout, RSTUDIO: r_layout, MATLAB: m_layout, VERTICAL: v_layout, HORIZONTAL: h_layout} layout = layouts[index] widgets_layout = layout['widgets'] widgets = [] for column in widgets_layout : for row in column: for widget in row: if widget is not None: widgets.append(widget) # Make every widget visible for widget in widgets: widget.toggle_view(True) action = widget.toggle_view_action action.setChecked(widget.dockwidget.isVisible()) # Set the widgets horizontally for i in range(len(widgets) - 1): first, second = widgets[i], widgets[i+1] if first is not None and second is not None: self.splitDockWidget(first.dockwidget, second.dockwidget, Qt.Horizontal) # Arrange rows vertically for column in widgets_layout : for i in range(len(column) - 1): first_row, second_row = column[i], column[i+1] if first_row is not None and second_row is not None: self.splitDockWidget(first_row[0].dockwidget, second_row[0].dockwidget, Qt.Vertical) # Tabify for column in widgets_layout : for row in column: for i in range(len(row) - 1): first, second = row[i], row[i+1] if first is not None and second is not None: self.tabify_plugins(first, second) # Raise front widget per row row[0].dockwidget.show() row[0].dockwidget.raise_() # Hide toolbars hidden_toolbars = global_hidden_toolbars + layout['hidden toolbars'] for toolbar in hidden_toolbars: if toolbar is not None: toolbar.close() # Hide widgets hidden_widgets = global_hidden_widgets + layout['hidden widgets'] for widget in hidden_widgets: if widget is not None: widget.dockwidget.close() # set the width and height self._layout_widget_info = [] width, height = self.window_size.width(), self.window_size.height() # fix column width # for c in range(len(widgets_layout)): # widget = widgets_layout[c][0][0].dockwidget # min_width, max_width = widget.minimumWidth(), widget.maximumWidth() # info = {'widget': widget, # 'min width': min_width, # 'max width': max_width} # self._layout_widget_info.append(info) # new_width = int(layout['width fraction'][c] * width * 0.95) # widget.setMinimumWidth(new_width) # widget.setMaximumWidth(new_width) # widget.updateGeometry() # fix column height for c, column in enumerate(widgets_layout): for r in range(len(column) - 1): widget = column[r][0] dockwidget = widget.dockwidget dock_min_h = dockwidget.minimumHeight() dock_max_h = dockwidget.maximumHeight() info = {'widget': widget, 'dock min height': dock_min_h, 'dock max height': dock_max_h} self._layout_widget_info.append(info) # The 0.95 factor is to adjust height based on usefull # estimated area in the window new_height = int(layout['height fraction'][c][r]*height*0.95) dockwidget.setMinimumHeight(new_height) dockwidget.setMaximumHeight(new_height) self._custom_layout_timer = QTimer(self) self._custom_layout_timer.timeout.connect(self.layout_fix_timer) self._custom_layout_timer.setSingleShot(True) self._custom_layout_timer.start(5000) def layout_fix_timer(self): """Fixes the height of docks after a new layout is set.""" info = self._layout_widget_info for i in info: dockwidget = i['widget'].dockwidget if 'dock min width' in i: dockwidget.setMinimumWidth(i['dock min width']) dockwidget.setMaximumWidth(i['dock max width']) if 'dock min height' in i: dockwidget.setMinimumHeight(i['dock min height']) dockwidget.setMaximumHeight(i['dock max height']) dockwidget.updateGeometry() self.setUpdatesEnabled(True) @Slot() def toggle_previous_layout(self): """ """ self.toggle_layout('previous') @Slot() def toggle_next_layout(self): """ """ self.toggle_layout('next') def toggle_layout(self, direction='next'): """ """ get = CONF.get names = get('quick_layouts', 'names') order = get('quick_layouts', 'order') active = get('quick_layouts', 'active') if len(active) == 0: return layout_index = ['default'] for name in order: if name in active: layout_index.append(names.index(name)) current_layout = self.current_quick_layout dic = {'next': 1, 'previous': -1} if current_layout is None: # Start from default current_layout = 'default' if current_layout in layout_index: current_index = layout_index.index(current_layout) else: current_index = 0 new_index = (current_index + dic[direction]) % len(layout_index) self.quick_layout_switch(layout_index[new_index]) def quick_layout_set_menu(self): """ """ get = CONF.get names = get('quick_layouts', 'names') order = get('quick_layouts', 'order') active = get('quick_layouts', 'active') ql_actions = [] ql_actions = [create_action(self, _('Spyder Default Layout'), triggered=lambda: self.quick_layout_switch('default'))] for name in order: if name in active: index = names.index(name) # closure required so lambda works with the default parameter def trigger(i=index, self=self): return lambda: self.quick_layout_switch(i) qli_act = create_action(self, name, triggered=trigger()) # closure above replaces the following which stopped working # qli_act = create_action(self, name, triggered=lambda i=index: # self.quick_layout_switch(i) ql_actions += [qli_act] self.ql_save = create_action(self, _("Save current layout"), triggered=lambda: self.quick_layout_save(), context=Qt.ApplicationShortcut) self.ql_preferences = create_action(self, _("Layout preferences"), triggered=lambda: self.quick_layout_settings(), context=Qt.ApplicationShortcut) self.ql_reset = create_action(self, _('Reset to spyder default'), triggered=self.reset_window_layout) self.register_shortcut(self.ql_save, "_", "Save current layout") self.register_shortcut(self.ql_preferences, "_", "Layout preferences") ql_actions += [None] ql_actions += [self.ql_save, self.ql_preferences, self.ql_reset] self.quick_layout_menu.clear() add_actions(self.quick_layout_menu, ql_actions) if len(order) == 0: self.ql_preferences.setEnabled(False) else: self.ql_preferences.setEnabled(True) @Slot() def reset_window_layout(self): """Reset window layout to default""" answer = QMessageBox.warning(self, _("Warning"), _("Window layout will be reset to default settings: " "this affects window position, size and dockwidgets.\n" "Do you want to continue?"), QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: self.setup_layout(default=True) def quick_layout_save(self): """Save layout dialog""" get = CONF.get set_ = CONF.set names = get('quick_layouts', 'names') order = get('quick_layouts', 'order') active = get('quick_layouts', 'active') dlg = self.dialog_layout_save(self, names) if dlg.exec_(): name = dlg.combo_box.currentText() if name in names: answer = QMessageBox.warning(self, _("Warning"), _("Layout %s will be \ overwritten. Do you want to \ continue?") % name, QMessageBox.Yes | QMessageBox.No) index = order.index(name) else: answer = True if None in names: index = names.index(None) names[index] = name else: index = len(names) names.append(name) order.append(name) # Always make active a new layout even if it overwrites an inactive # layout if name not in active: active.append(name) if answer: self.save_current_window_settings('layout_{}/'.format(index), section='quick_layouts') set_('quick_layouts', 'names', names) set_('quick_layouts', 'order', order) set_('quick_layouts', 'active', active) self.quick_layout_set_menu() def quick_layout_settings(self): """Layout settings dialog""" get = CONF.get set_ = CONF.set section = 'quick_layouts' names = get(section, 'names') order = get(section, 'order') active = get(section, 'active') dlg = self.dialog_layout_settings(self, names, order, active) if dlg.exec_(): set_(section, 'names', dlg.names) set_(section, 'order', dlg.order) set_(section, 'active', dlg.active) self.quick_layout_set_menu() def quick_layout_switch(self, index): """Switch to quick layout number *index*""" section = 'quick_layouts' try: settings = self.load_window_settings('layout_{}/'.format(index), section=section) (hexstate, window_size, prefs_dialog_size, pos, is_maximized, is_fullscreen) = settings # The defaults layouts will alwyas be regenerated unless there was # an overwrite, either by rewriting with same name, or by deleting # and then creating a new one if hexstate is None: self.setup_default_layouts(index, settings) except cp.NoOptionError: QMessageBox.critical(self, _("Warning"), _("Quick switch layout #%s has not yet " "been defined.") % str(index)) return # TODO: is there any real use in calling the previous layout # setting? # self.previous_layout_settings = self.get_window_settings() self.set_window_settings(*settings) self.current_quick_layout = index # make sure the flags are correctly set for visible panes for plugin in self.widgetlist: action = plugin.toggle_view_action action.setChecked(plugin.dockwidget.isVisible()) # --- Show/Hide toolbars def _update_show_toolbars_action(self): """Update the text displayed in the menu entry.""" if self.toolbars_visible: text = _("Hide toolbars") tip = _("Hide toolbars") else: text = _("Show toolbars") tip = _("Show toolbars") self.show_toolbars_action.setText(text) self.show_toolbars_action.setToolTip(tip) def save_visible_toolbars(self): """Saves the name of the visible toolbars in the .ini file.""" toolbars = [] for toolbar in self.visible_toolbars: toolbars.append(toolbar.objectName()) CONF.set('main', 'last_visible_toolbars', toolbars) def get_visible_toolbars(self): """Collects the visible toolbars.""" toolbars = [] for toolbar in self.toolbarslist: if toolbar.toggleViewAction().isChecked(): toolbars.append(toolbar) self.visible_toolbars = toolbars def load_last_visible_toolbars(self): """Loads the last visible toolbars from the .ini file.""" toolbars_names = CONF.get('main', 'last_visible_toolbars', default=[]) if toolbars_names: dic = {} for toolbar in self.toolbarslist: dic[toolbar.objectName()] = toolbar toolbars = [] for name in toolbars_names: if name in dic: toolbars.append(dic[name]) self.visible_toolbars = toolbars else: self.get_visible_toolbars() self._update_show_toolbars_action() @Slot() def show_toolbars(self): """Show/Hides toolbars.""" value = not self.toolbars_visible CONF.set('main', 'toolbars_visible', value) if value: self.save_visible_toolbars() else: self.get_visible_toolbars() for toolbar in self.visible_toolbars: toolbar.toggleViewAction().setChecked(value) toolbar.setVisible(value) self.toolbars_visible = value self._update_show_toolbars_action() # --- Other def plugin_focus_changed(self): """Focus has changed from one plugin to another""" self.update_edit_menu() self.update_search_menu() def show_shortcuts(self, menu): """Show action shortcuts in menu""" for element in getattr(self, menu + '_menu_actions'): if element and isinstance(element, QAction): if element._shown_shortcut is not None: element.setShortcut(element._shown_shortcut) def hide_shortcuts(self, menu): """Hide action shortcuts in menu""" for element in getattr(self, menu + '_menu_actions'): if element and isinstance(element, QAction): if element._shown_shortcut is not None: element.setShortcut(QKeySequence()) def get_focus_widget_properties(self): """Get properties of focus widget Returns tuple (widget, properties) where properties is a tuple of booleans: (is_console, not_readonly, readwrite_editor)""" widget = QApplication.focusWidget() from spyder.widgets.shell import ShellBaseWidget from spyder.widgets.editor import TextEditBaseWidget from spyder.widgets.ipythonconsole import ControlWidget # if focused widget isn't valid try the last focused if not isinstance(widget, (ShellBaseWidget, TextEditBaseWidget, ControlWidget)): widget = self.previous_focused_widget textedit_properties = None if isinstance(widget, (ShellBaseWidget, TextEditBaseWidget, ControlWidget)): console = isinstance(widget, (ShellBaseWidget, ControlWidget)) not_readonly = not widget.isReadOnly() readwrite_editor = not_readonly and not console textedit_properties = (console, not_readonly, readwrite_editor) return widget, textedit_properties def update_edit_menu(self): """Update edit menu""" widget, textedit_properties = self.get_focus_widget_properties() if textedit_properties is None: # widget is not an editor/console return #!!! Below this line, widget is expected to be a QPlainTextEdit instance console, not_readonly, readwrite_editor = textedit_properties # Editor has focus and there is no file opened in it if not console and not_readonly and not self.editor.is_file_opened(): return # Disabling all actions to begin with for child in self.edit_menu.actions(): child.setEnabled(False) self.selectall_action.setEnabled(True) # Undo, redo self.undo_action.setEnabled( readwrite_editor \ and widget.document().isUndoAvailable() ) self.redo_action.setEnabled( readwrite_editor \ and widget.document().isRedoAvailable() ) # Copy, cut, paste, delete has_selection = widget.has_selected_text() self.copy_action.setEnabled(has_selection) self.cut_action.setEnabled(has_selection and not_readonly) self.paste_action.setEnabled(not_readonly) # Comment, uncomment, indent, unindent... if not console and not_readonly: # This is the editor and current file is writable for action in self.editor.edit_menu_actions: action.setEnabled(True) def update_search_menu(self): """Update search menu""" if self.menuBar().hasFocus(): return widget, textedit_properties = self.get_focus_widget_properties() for action in self.editor.search_menu_actions: try: action.setEnabled(self.editor.isAncestorOf(widget)) except RuntimeError: pass if textedit_properties is None: # widget is not an editor/console return #!!! Below this line, widget is expected to be a QPlainTextEdit instance _x, _y, readwrite_editor = textedit_properties # Disable the replace action for read-only files self.search_menu_actions[3].setEnabled(readwrite_editor) def create_plugins_menu(self): order = ['editor', 'console', 'ipython_console', 'variable_explorer', 'help', None, 'explorer', 'outline_explorer', 'project_explorer', 'find_in_files', None, 'historylog', 'profiler', 'breakpoints', 'pylint', None, 'onlinehelp', 'internal_console'] for plugin in self.widgetlist: action = plugin.toggle_view_action action.setChecked(plugin.dockwidget.isVisible()) try: name = plugin.CONF_SECTION pos = order.index(name) except ValueError: pos = None if pos is not None: order[pos] = action else: order.append(action) actions = order[:] for action in order: if type(action) is str: actions.remove(action) self.plugins_menu_actions = actions add_actions(self.plugins_menu, actions) def create_toolbars_menu(self): order = ['file_toolbar', 'run_toolbar', 'debug_toolbar', 'main_toolbar', 'Global working directory', None, 'search_toolbar', 'edit_toolbar', 'source_toolbar'] for toolbar in self.toolbarslist: action = toolbar.toggleViewAction() name = toolbar.objectName() try: pos = order.index(name) except ValueError: pos = None if pos is not None: order[pos] = action else: order.append(action) add_actions(self.toolbars_menu, order) def createPopupMenu(self): menu = QMenu('', self) actions = self.help_menu_actions[:3] + \ [None, self.help_menu_actions[-1]] add_actions(menu, actions) return menu def set_splash(self, message): """Set splash message""" if self.splash is None: return if message: self.debug_print(message) self.splash.show() self.splash.showMessage(message, Qt.AlignBottom | Qt.AlignCenter | Qt.AlignAbsolute, QColor(Qt.white)) QApplication.processEvents() def remove_tmpdir(self): """Remove Spyder temporary directory""" if CONF.get('main', 'single_instance') and not self.new_instance: shutil.rmtree(programs.TEMPDIR, ignore_errors=True) def closeEvent(self, event): """closeEvent reimplementation""" if self.closing(True): event.accept() else: event.ignore() def resizeEvent(self, event): """Reimplement Qt method""" if not self.isMaximized() and not self.fullscreen_flag: self.window_size = self.size() QMainWindow.resizeEvent(self, event) # To be used by the tour to be able to resize self.sig_resized.emit(event) def moveEvent(self, event): """Reimplement Qt method""" if not self.isMaximized() and not self.fullscreen_flag: self.window_position = self.pos() QMainWindow.moveEvent(self, event) # To be used by the tour to be able to move self.sig_moved.emit(event) def hideEvent(self, event): """Reimplement Qt method""" try: for plugin in self.widgetlist: if plugin.isAncestorOf(self.last_focused_widget): plugin.visibility_changed(True) QMainWindow.hideEvent(self, event) except RuntimeError: QMainWindow.hideEvent(self, event) def change_last_focused_widget(self, old, now): """To keep track of to the last focused widget""" if (now is None and QApplication.activeWindow() is not None): QApplication.activeWindow().setFocus() self.last_focused_widget = QApplication.focusWidget() elif now is not None: self.last_focused_widget = now self.previous_focused_widget = old def closing(self, cancelable=False): """Exit tasks""" if self.already_closed or self.is_starting_up: return True if cancelable and CONF.get('main', 'prompt_on_exit'): reply = QMessageBox.critical(self, 'Spyder', 'Do you really want to exit?', QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.No: return False prefix = 'window' + '/' self.save_current_window_settings(prefix) if CONF.get('main', 'single_instance') and self.open_files_server: self.open_files_server.close() for plugin in self.thirdparty_plugins: if not plugin.closing_plugin(cancelable): return False for widget in self.widgetlist: if not widget.closing_plugin(cancelable): return False self.dialog_manager.close_all() if self.toolbars_visible: self.save_visible_toolbars() self.already_closed = True return True def add_dockwidget(self, child): """Add QDockWidget and toggleViewAction""" dockwidget, location = child.create_dockwidget() if CONF.get('main', 'vertical_dockwidget_titlebars'): dockwidget.setFeatures(dockwidget.features()| QDockWidget.DockWidgetVerticalTitleBar) self.addDockWidget(location, dockwidget) self.widgetlist.append(child) @Slot() def close_current_dockwidget(self): widget = QApplication.focusWidget() for plugin in self.widgetlist: if plugin.isAncestorOf(widget): plugin.dockwidget.hide() break def toggle_lock_dockwidgets(self, value): """Lock/Unlock dockwidgets""" self.dockwidgets_locked = value self.apply_panes_settings() CONF.set('main', 'panes_locked', value) def __update_maximize_action(self): if self.state_before_maximizing is None: text = _("Maximize current pane") tip = _("Maximize current pane") icon = ima.icon('maximize') else: text = _("Restore current pane") tip = _("Restore pane to its original size") icon = ima.icon('unmaximize') self.maximize_action.setText(text) self.maximize_action.setIcon(icon) self.maximize_action.setToolTip(tip) @Slot() @Slot(bool) def maximize_dockwidget(self, restore=False): """Shortcut: Ctrl+Alt+Shift+M First call: maximize current dockwidget Second call (or restore=True): restore original window layout""" if self.state_before_maximizing is None: if restore: return # Select plugin to maximize self.state_before_maximizing = self.saveState() focus_widget = QApplication.focusWidget() for plugin in self.widgetlist: plugin.dockwidget.hide() if plugin.isAncestorOf(focus_widget): self.last_plugin = plugin # Only plugins that have a dockwidget are part of widgetlist, # so last_plugin can be None after the above "for" cycle. # For example, this happens if, after Spyder has started, focus # is set to the Working directory toolbar (which doesn't have # a dockwidget) and then you press the Maximize button if self.last_plugin is None: # Using the Editor as default plugin to maximize self.last_plugin = self.editor # Maximize last_plugin self.last_plugin.dockwidget.toggleViewAction().setDisabled(True) self.setCentralWidget(self.last_plugin) self.last_plugin.ismaximized = True # Workaround to solve an issue with editor's outline explorer: # (otherwise the whole plugin is hidden and so is the outline explorer # and the latter won't be refreshed if not visible) self.last_plugin.show() self.last_plugin.visibility_changed(True) if self.last_plugin is self.editor: # Automatically show the outline if the editor was maximized: self.addDockWidget(Qt.RightDockWidgetArea, self.outlineexplorer.dockwidget) self.outlineexplorer.dockwidget.show() else: # Restore original layout (before maximizing current dockwidget) self.last_plugin.dockwidget.setWidget(self.last_plugin) self.last_plugin.dockwidget.toggleViewAction().setEnabled(True) self.setCentralWidget(None) self.last_plugin.ismaximized = False self.restoreState(self.state_before_maximizing) self.state_before_maximizing = None self.last_plugin.get_focus_widget().setFocus() self.__update_maximize_action() def __update_fullscreen_action(self): if self.isFullScreen(): icon = ima.icon('window_nofullscreen') else: icon = ima.icon('window_fullscreen') if is_text_string(icon): icon = get_icon(icon) self.fullscreen_action.setIcon(icon) @Slot() def toggle_fullscreen(self): if self.isFullScreen(): self.fullscreen_flag = False self.showNormal() if self.maximized_flag: self.showMaximized() else: self.maximized_flag = self.isMaximized() self.fullscreen_flag = True self.showFullScreen() self.__update_fullscreen_action() def add_to_toolbar(self, toolbar, widget): """Add widget actions to toolbar""" actions = widget.toolbar_actions if actions is not None: add_actions(toolbar, actions) @Slot() def about(self): """About Spyder""" versions = get_versions() # Show Mercurial revision for development version revlink = '' if versions['revision']: rev = versions['revision'] revlink = " (
    Commit: %s)" % (rev, rev) QMessageBox.about(self, _("About %s") % "Spyder", """Spyder %s %s
    The Scientific PYthon Development EnviRonment
    Copyright © The Spyder Project Contributors
    Licensed under the terms of the MIT License

    Created by Pierre Raybaut.
    Developed and maintained by the Spyder Project Contributors.
    Many thanks to all the Spyder beta testers and regular users.

    For bug reports and feature requests, please go to our Github website. For discussions around the project, please go to our Google Group

    This project is part of a larger effort to promote and facilitate the use of Python for scientific and engineering software development. The popular Python distributions Anaconda, WinPython and Python(x,y) also contribute to this plan.

    Python %s %dbits, Qt %s, %s %s on %s

    Most of the icons for the Spyder 2 theme come from the Crystal Project (© 2006-2007 Everaldo Coelho). Other icons for that theme come from Yusuke Kamiyamane (all rights reserved) and from The Oxygen icon theme. """ % (versions['spyder'], revlink, __project_url__, __project_url__, __forum_url__, versions['python'], versions['bitness'], versions['qt'], versions['qt_api'], versions['qt_api_ver'], versions['system'])) @Slot() def show_dependencies(self): """Show Spyder's Dependencies dialog box""" from spyder.widgets.dependencies import DependenciesDialog dlg = DependenciesDialog(None) dlg.set_data(dependencies.DEPENDENCIES) dlg.exec_() @Slot() def report_issue(self, traceback=""): if PY3: from urllib.parse import quote else: from urllib import quote # analysis:ignore versions = get_versions() # Get git revision for development version revision = '' if versions['revision']: revision = versions['revision'] issue_template = """\ ## Description **What steps will reproduce the problem?** 1. 2. 3. **What is the expected output? What do you see instead?** **Please provide any additional information below** %s ## Version and main components * Spyder Version: %s %s * Python Version: %s * Qt Versions: %s, %s %s on %s ## Dependencies ``` %s ``` """ % (traceback, versions['spyder'], revision, versions['python'], versions['qt'], versions['qt_api'], versions['qt_api_ver'], versions['system'], dependencies.status()) url = QUrl("https://github.com/spyder-ide/spyder/issues/new") if PYQT5: from qtpy.QtCore import QUrlQuery query = QUrlQuery() query.addQueryItem("body", quote(issue_template)) url.setQuery(query) else: url.addEncodedQueryItem("body", quote(issue_template)) QDesktopServices.openUrl(url) @Slot() def google_group(self): url = QUrl("http://groups.google.com/group/spyderlib") QDesktopServices.openUrl(url) @Slot() def global_callback(self): """Global callback""" widget = QApplication.focusWidget() action = self.sender() callback = from_qvariant(action.data(), to_text_string) from spyder.widgets.editor import TextEditBaseWidget # if focused widget isn't valid try the last focused^M if not isinstance(widget, TextEditBaseWidget): widget = self.previous_focused_widget if isinstance(widget, TextEditBaseWidget): getattr(widget, callback)() def redirect_internalshell_stdio(self, state): if state: self.console.shell.interpreter.redirect_stds() else: self.console.shell.interpreter.restore_stds() def open_external_console(self, fname, wdir, args, interact, debug, python, python_args, systerm, post_mortem=False): """Open external console""" if systerm: # Running script in an external system terminal try: programs.run_python_script_in_terminal(fname, wdir, args, interact, debug, python_args) except NotImplementedError: QMessageBox.critical(self, _("Run"), _("Running an external system terminal " "is not supported on platform %s." ) % os.name) def execute_in_external_console(self, lines, focus_to_editor): """ Execute lines in IPython console and eventually set focus to the Editor. """ console = self.ipyconsole console.visibility_changed(True) console.raise_() console.execute_code(lines) if focus_to_editor: self.editor.visibility_changed(True) def open_file(self, fname, external=False): """ Open filename with the appropriate application Redirect to the right widget (txt -> editor, spydata -> workspace, ...) or open file outside Spyder (if extension is not supported) """ fname = to_text_string(fname) ext = osp.splitext(fname)[1] if encoding.is_text_file(fname): self.editor.load(fname) elif self.variableexplorer is not None and ext in IMPORT_EXT: self.variableexplorer.import_data(fname) elif not external: fname = file_uri(fname) programs.start_file(fname) def open_external_file(self, fname): """ Open external files that can be handled either by the Editor or the variable explorer inside Spyder. """ fname = encoding.to_unicode_from_fs(fname) if osp.isfile(fname): self.open_file(fname, external=True) elif osp.isfile(osp.join(CWD, fname)): self.open_file(osp.join(CWD, fname), external=True) # ---- PYTHONPATH management, etc. def get_spyder_pythonpath(self): """Return Spyder PYTHONPATH""" active_path = [p for p in self.path if p not in self.not_active_path] return active_path + self.project_path def add_path_to_sys_path(self): """Add Spyder path to sys.path""" for path in reversed(self.get_spyder_pythonpath()): sys.path.insert(1, path) def remove_path_from_sys_path(self): """Remove Spyder path from sys.path""" sys_path = sys.path for path in self.path: while path in sys_path: sys_path.remove(path) @Slot() def path_manager_callback(self): """Spyder path manager""" from spyder.widgets.pathmanager import PathManager self.remove_path_from_sys_path() project_path = self.projects.get_pythonpath() dialog = PathManager(self, self.path, project_path, self.not_active_path, sync=True) dialog.redirect_stdio.connect(self.redirect_internalshell_stdio) dialog.exec_() self.add_path_to_sys_path() encoding.writelines(self.path, self.SPYDER_PATH) # Saving path encoding.writelines(self.not_active_path, self.SPYDER_NOT_ACTIVE_PATH) self.sig_pythonpath_changed.emit() def pythonpath_changed(self): """Projects PYTHONPATH contribution has changed""" self.remove_path_from_sys_path() self.project_path = self.projects.get_pythonpath() self.add_path_to_sys_path() self.sig_pythonpath_changed.emit() @Slot() def win_env(self): """Show Windows current user environment variables""" self.dialog_manager.show(WinUserEnvDialog(self)) #---- Preferences def apply_settings(self): """Apply settings changed in 'Preferences' dialog box""" qapp = QApplication.instance() # Set 'gtk+' as the default theme in Gtk-based desktops # Fixes Issue 2036 if is_gtk_desktop() and ('GTK+' in QStyleFactory.keys()): try: qapp.setStyle('gtk+') except: pass else: style_name = CONF.get('main', 'windows_style', self.default_style) style = QStyleFactory.create(style_name) if style is not None: style.setProperty('name', style_name) qapp.setStyle(style) default = self.DOCKOPTIONS if CONF.get('main', 'vertical_tabs'): default = default|QMainWindow.VerticalTabs if CONF.get('main', 'animated_docks'): default = default|QMainWindow.AnimatedDocks self.setDockOptions(default) self.apply_panes_settings() self.apply_statusbar_settings() if CONF.get('main', 'use_custom_cursor_blinking'): qapp.setCursorFlashTime(CONF.get('main', 'custom_cursor_blinking')) else: qapp.setCursorFlashTime(self.CURSORBLINK_OSDEFAULT) def apply_panes_settings(self): """Update dockwidgets features settings""" # Update toggle action on menu for child in self.widgetlist: features = child.FEATURES if CONF.get('main', 'vertical_dockwidget_titlebars'): features = features | QDockWidget.DockWidgetVerticalTitleBar if not self.dockwidgets_locked: features = features | QDockWidget.DockWidgetMovable child.dockwidget.setFeatures(features) child.update_margins() def apply_statusbar_settings(self): """Update status bar widgets settings""" show_status_bar = CONF.get('main', 'show_status_bar') self.statusBar().setVisible(show_status_bar) if show_status_bar: for widget, name in ((self.mem_status, 'memory_usage'), (self.cpu_status, 'cpu_usage')): if widget is not None: widget.setVisible(CONF.get('main', '%s/enable' % name)) widget.set_interval(CONF.get('main', '%s/timeout' % name)) else: return @Slot() def edit_preferences(self): """Edit Spyder preferences""" from spyder.plugins.configdialog import ConfigDialog dlg = ConfigDialog(self) dlg.size_change.connect(self.set_prefs_size) if self.prefs_dialog_size is not None: dlg.resize(self.prefs_dialog_size) for PrefPageClass in self.general_prefs: widget = PrefPageClass(dlg, main=self) widget.initialize() dlg.add_page(widget) for plugin in [self.workingdirectory, self.editor, self.projects, self.ipyconsole, self.historylog, self.help, self.variableexplorer, self.onlinehelp, self.explorer, self.findinfiles ]+self.thirdparty_plugins: if plugin is not None: try: widget = plugin.create_configwidget(dlg) if widget is not None: dlg.add_page(widget) except Exception: traceback.print_exc(file=sys.stderr) if self.prefs_index is not None: dlg.set_current_index(self.prefs_index) dlg.show() dlg.check_all_settings() dlg.pages_widget.currentChanged.connect(self.__preference_page_changed) dlg.exec_() def __preference_page_changed(self, index): """Preference page index has changed""" self.prefs_index = index def set_prefs_size(self, size): """Save preferences dialog size""" self.prefs_dialog_size = size #---- Shortcuts def register_shortcut(self, qaction_or_qshortcut, context, name, add_sc_to_tip=False): """ Register QAction or QShortcut to Spyder main application, with shortcut (context, name, default) """ self.shortcut_data.append( (qaction_or_qshortcut, context, name, add_sc_to_tip) ) def apply_shortcuts(self): """Apply shortcuts settings to all widgets/plugins""" toberemoved = [] for index, (qobject, context, name, add_sc_to_tip) in enumerate(self.shortcut_data): keyseq = QKeySequence( get_shortcut(context, name) ) try: if isinstance(qobject, QAction): if sys.platform == 'darwin' and \ qobject._shown_shortcut == 'missing': qobject._shown_shortcut = keyseq else: qobject.setShortcut(keyseq) if add_sc_to_tip: add_shortcut_to_tooltip(qobject, context, name) elif isinstance(qobject, QShortcut): qobject.setKey(keyseq) except RuntimeError: # Object has been deleted toberemoved.append(index) for index in sorted(toberemoved, reverse=True): self.shortcut_data.pop(index) @Slot() def show_shortcuts_dialog(self): from spyder.widgets.shortcutssummary import ShortcutsSummaryDialog dlg = ShortcutsSummaryDialog(None) dlg.exec_() # -- Open files server def start_open_files_server(self): self.open_files_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) port = select_port(default_port=OPEN_FILES_PORT) CONF.set('main', 'open_files_port', port) self.open_files_server.bind(('127.0.0.1', port)) self.open_files_server.listen(20) while 1: # 1 is faster than True try: req, dummy = self.open_files_server.accept() except socket.error as e: # See Issue 1275 for details on why errno EINTR is # silently ignored here. eintr = errno.WSAEINTR if os.name == 'nt' else errno.EINTR # To avoid a traceback after closing on Windows if e.args[0] == eintr: continue # handle a connection abort on close error enotsock = (errno.WSAENOTSOCK if os.name == 'nt' else errno.ENOTSOCK) if e.args[0] in [errno.ECONNABORTED, enotsock]: return raise fname = req.recv(1024) fname = fname.decode('utf-8') self.sig_open_external_file.emit(fname) req.sendall(b' ') # ---- Quit and restart, and reset spyder defaults @Slot() def reset_spyder(self): """ Quit and reset Spyder and then Restart application. """ answer = QMessageBox.warning(self, _("Warning"), _("Spyder will restart and reset to default settings:

    " "Do you want to continue?"), QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: self.restart(reset=True) @Slot() def restart(self, reset=False): """ Quit and Restart Spyder application. If reset True it allows to reset spyder on restart. """ # Get start path to use in restart script spyder_start_directory = get_module_path('spyder') restart_script = osp.join(spyder_start_directory, 'app', 'restart.py') # Get any initial argument passed when spyder was started # Note: Variables defined in bootstrap.py and spyder/app/start.py env = os.environ.copy() bootstrap_args = env.pop('SPYDER_BOOTSTRAP_ARGS', None) spyder_args = env.pop('SPYDER_ARGS') # Get current process and python running spyder pid = os.getpid() python = sys.executable # Check if started with bootstrap.py if bootstrap_args is not None: spyder_args = bootstrap_args is_bootstrap = True else: is_bootstrap = False # Pass variables as environment variables (str) to restarter subprocess env['SPYDER_ARGS'] = spyder_args env['SPYDER_PID'] = str(pid) env['SPYDER_IS_BOOTSTRAP'] = str(is_bootstrap) env['SPYDER_RESET'] = str(reset) if DEV: if os.name == 'nt': env['PYTHONPATH'] = ';'.join(sys.path) else: env['PYTHONPATH'] = ':'.join(sys.path) # Build the command and popen arguments depending on the OS if os.name == 'nt': # Hide flashing command prompt startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW shell = False else: startupinfo = None shell = True command = '"{0}" "{1}"' command = command.format(python, restart_script) try: if self.closing(True): subprocess.Popen(command, shell=shell, env=env, startupinfo=startupinfo) self.console.quit() except Exception as error: # If there is an error with subprocess, Spyder should not quit and # the error can be inspected in the internal console print(error) # spyder: test-skip print(command) # spyder: test-skip # ---- Interactive Tours def show_tour(self, index): """ """ frames = self.tours_available[index] self.tour.set_tour(index, frames, self) self.tour.start_tour() # ---- Global File Switcher def open_fileswitcher(self, symbol=False): """Open file list management dialog box.""" if self.fileswitcher is not None and \ self.fileswitcher.is_visible: self.fileswitcher.hide() self.fileswitcher.is_visible = False return if symbol: self.fileswitcher.plugin = self.editor self.fileswitcher.set_search_text('@') else: self.fileswitcher.set_search_text('') self.fileswitcher.show() self.fileswitcher.is_visible = True def open_symbolfinder(self): """Open symbol list management dialog box.""" self.open_fileswitcher(symbol=True) def add_to_fileswitcher(self, plugin, tabs, data, icon): """Add a plugin to the File Switcher.""" if self.fileswitcher is None: self.fileswitcher = FileSwitcher(self, plugin, tabs, data, icon) else: self.fileswitcher.add_plugin(plugin, tabs, data, icon) self.fileswitcher.sig_goto_file.connect( plugin.get_current_tab_manager().set_stack_index) # ---- Check for Spyder Updates def _check_updates_ready(self): """Called by WorkerUpdates when ready""" from spyder.widgets.helperwidgets import MessageCheckBox # feedback` = False is used on startup, so only positive feedback is # given. `feedback` = True is used when after startup (when using the # menu action, and gives feeback if updates are, or are not found. feedback = self.give_updates_feedback # Get results from worker update_available = self.worker_updates.update_available latest_release = self.worker_updates.latest_release error_msg = self.worker_updates.error url_r = 'https://github.com/spyder-ide/spyder/releases' url_i = 'http://pythonhosted.org/spyder/installation.html' # Define the custom QMessageBox box = MessageCheckBox(icon=QMessageBox.Information, parent=self) box.setWindowTitle(_("Spyder updates")) box.set_checkbox_text(_("Check for updates on startup")) box.setStandardButtons(QMessageBox.Ok) box.setDefaultButton(QMessageBox.Ok) # Adjust the checkbox depending on the stored configuration section, option = 'main', 'check_updates_on_startup' check_updates = CONF.get(section, option) box.set_checked(check_updates) if error_msg is not None: msg = error_msg box.setText(msg) box.set_check_visible(False) box.exec_() check_updates = box.is_checked() else: if update_available: anaconda_msg = '' if 'Anaconda' in sys.version or 'conda-forge' in sys.version: anaconda_msg = _("


    IMPORTANT NOTE: It seems " "that you are using Spyder with " "Anaconda/Miniconda. Please " "don't use pip to " "update it as that will probably break " "your installation.

    " "Instead, please wait until new conda " "packages are available and use " "conda to perform the " "update.
    ") msg = _("Spyder %s is available!

    Please use " "your package manager to update Spyder or go to our " "Releases page to download this " "new version.

    If you are not sure how to " "proceed to update Spyder please refer to our " " Installation instructions." "") % (latest_release, url_r, url_i) msg += '
    ' + anaconda_msg box.setText(msg) box.set_check_visible(True) box.exec_() check_updates = box.is_checked() elif feedback: msg = _("Spyder is up to date.") box.setText(msg) box.set_check_visible(False) box.exec_() check_updates = box.is_checked() # Update checkbox based on user interaction CONF.set(section, option, check_updates) # Enable check_updates_action after the thread has finished self.check_updates_action.setDisabled(False) # Provide feeback when clicking menu if check on startup is on self.give_updates_feedback = True @Slot() def check_updates(self, startup=False): """ Check for spyder updates on github releases using a QThread. """ from spyder.workers.updates import WorkerUpdates # Disable check_updates_action while the thread is working self.check_updates_action.setDisabled(True) if self.thread_updates is not None: self.thread_updates.terminate() self.thread_updates = QThread(self) self.worker_updates = WorkerUpdates(self, startup=startup) self.worker_updates.sig_ready.connect(self._check_updates_ready) self.worker_updates.sig_ready.connect(self.thread_updates.quit) self.worker_updates.moveToThread(self.thread_updates) self.thread_updates.started.connect(self.worker_updates.start) self.thread_updates.start() #============================================================================== # Utilities to create the 'main' function #============================================================================== def initialize(): """Initialize Qt, patching sys.exit and eventually setting up ETS""" # This doesn't create our QApplication, just holds a reference to # MAIN_APP, created above to show our splash screen as early as # possible app = qapplication() # --- Set application icon app.setWindowIcon(APP_ICON) #----Monkey patching QApplication class FakeQApplication(QApplication): """Spyder's fake QApplication""" def __init__(self, args): self = app # analysis:ignore @staticmethod def exec_(): """Do nothing because the Qt mainloop is already running""" pass from qtpy import QtWidgets QtWidgets.QApplication = FakeQApplication # ----Monkey patching sys.exit def fake_sys_exit(arg=[]): pass sys.exit = fake_sys_exit # ----Monkey patching sys.excepthook to avoid crashes in PyQt 5.5+ if PYQT5: def spy_excepthook(type_, value, tback): sys.__excepthook__(type_, value, tback) sys.excepthook = spy_excepthook # Removing arguments from sys.argv as in standard Python interpreter sys.argv = [''] # Selecting Qt4 backend for Enthought Tool Suite (if installed) try: from enthought.etsconfig.api import ETSConfig ETSConfig.toolkit = 'qt4' except ImportError: pass return app class Spy(object): """ Inspect Spyder internals Attributes: app Reference to main QApplication object window Reference to spyder.MainWindow widget """ def __init__(self, app, window): self.app = app self.window = window def __dir__(self): return list(self.__dict__.keys()) +\ [x for x in dir(self.__class__) if x[0] != '_'] def versions(self): return get_versions() def run_spyder(app, options, args): """ Create and show Spyder's main window Start QApplication event loop """ #TODO: insert here # Main window main = MainWindow(options) try: main.setup() except BaseException: if main.console is not None: try: main.console.shell.exit_interpreter() except BaseException: pass raise main.show() main.post_visible_setup() if main.console: main.console.shell.interpreter.namespace['spy'] = \ Spy(app=app, window=main) # Open external files passed as args if args: for a in args: main.open_external_file(a) # Don't show icons in menus for Mac if sys.platform == 'darwin': QCoreApplication.setAttribute(Qt.AA_DontShowIconsInMenus, True) # Open external files with our Mac app if running_in_mac_app(): app.sig_open_external_file.connect(main.open_external_file) # To give focus again to the last focused widget after restoring # the window app.focusChanged.connect(main.change_last_focused_widget) if not PYTEST: app.exec_() return main #============================================================================== # Main #============================================================================== def main(): """Main function""" # **** Collect command line options **** # Note regarding Options: # It's important to collect options before monkey patching sys.exit, # otherwise, optparse won't be able to exit if --help option is passed options, args = get_options() if options.show_console: print("(Deprecated) --show console does nothing, now the default " " behavior is to show the console, use --hide-console if you " "want to hide it") if set_attached_console_visible is not None: set_attached_console_visible(not options.hide_console or options.reset_config_files or options.reset_to_defaults or options.optimize or bool(DEBUG)) app = initialize() if options.reset_config_files: # Remove all configuration files! reset_config_files() return elif options.reset_to_defaults: # Reset Spyder settings to defaults CONF.reset_to_defaults(save=True) return elif options.optimize: # Optimize the whole Spyder's source code directory import spyder programs.run_python_script(module="compileall", args=[spyder.__path__[0]], p_args=['-O']) return # Show crash dialog if CONF.get('main', 'crash', False) and not DEV: CONF.set('main', 'crash', False) if SPLASH is not None: SPLASH.hide() QMessageBox.information(None, "Spyder", "Spyder crashed during last session.

    " "If Spyder does not start at all and before submitting a " "bug report, please try to reset settings to defaults by " "running Spyder with the command line option '--reset':
    " "spyder --reset" "

    " "Warning: " "this command will remove all your Spyder configuration files " "located in '%s').

    " "If restoring the default settings does not help, please take " "the time to search for known bugs or " "discussions matching your situation before " "eventually creating a new issue here. " "Your feedback will always be greatly appreciated." "" % (get_conf_path(), __project_url__, __forum_url__, __project_url__)) # Create main window mainwindow = None try: mainwindow = run_spyder(app, options, args) except FontError as fontError: QMessageBox.information(None, "Spyder", "Spyder was unable to load the Spyder 3 " "icon theme. That's why it's going to fallback to the " "theme used in Spyder 2.

    " "For that, please close this window and start Spyder again.") CONF.set('main', 'icon_theme', 'spyder 2') except BaseException: CONF.set('main', 'crash', True) import traceback traceback.print_exc(file=STDERR) traceback.print_exc(file=open('spyder_crash.log', 'w')) if mainwindow is None: # An exception occured if SPLASH is not None: SPLASH.hide() return ORIGINAL_SYS_EXIT() if __name__ == "__main__": main() spyder-3.2.6/spyder/app/tour.py0000664000175000017500000014053513224740762017272 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Spyder interactive tours""" # pylint: disable=C0103 # pylint: disable=R0903 # pylint: disable=R0911 # pylint: disable=R0201 # Standard library imports from __future__ import division import sys # Third party imports from qtpy.QtCore import (QEasingCurve, QPoint, QPropertyAnimation, QRectF, Qt, Signal) from qtpy.QtGui import (QBrush, QColor, QIcon, QPainter, QPainterPath, QPen, QPixmap, QRegion) from qtpy.QtWidgets import (QAction, QApplication, QComboBox, QDialog, QGraphicsOpacityEffect, QHBoxLayout, QLabel, QLayout, QMainWindow, QMenu, QPushButton, QSpacerItem, QToolButton, QVBoxLayout, QWidget) # Local imports from spyder.config.base import _, get_image_path from spyder.py3compat import to_binary_string from spyder.utils.qthelpers import add_actions, create_action # FIXME: Known issues # How to handle if an specific dockwidget does not exists/load, like ipython # on python3.3, should that frame be removed? should it display a warning? class SpyderWidgets(object): """List of supported widgets to highlight/decorate""" # Panes ipython_console = 'ipyconsole' editor = 'editor' editor_line_number_area = 'editor.get_current_editor().linenumberarea' editor_scroll_flag_area = 'editor.get_current_editor().scrollflagarea' file_explorer = 'explorer' help_plugin = 'help' variable_explorer = 'variableexplorer' history_log = "historylog" # Toolbars toolbars = '' toolbars_active = '' toolbar_file = '' toolbar_edit = '' toolbar_run = '' toolbar_debug = '' toolbar_main = '' status_bar = '' menu_bar = '' menu_file = '' menu_edit = '' def get_tours(index=None): """ Get the list of available tours (if index=None), or the your given by index """ return get_tour(index) def get_tour(index): """ This function generates a list of tours. The index argument is used to retrieve a particular tour. If None is passed, it will return the full list of tours. If instead -1 is given, this function will return a test tour To add more tours a new variable needs to be created to hold the list of dicts and the tours variable at the bottom of this function needs to be updated accordingly """ sw = SpyderWidgets qtconsole_link = "http://ipython.org/ipython-doc/stable/interactive/qtconsole.html" # This test should serve as example of keys to use in the tour frame dics test = [{'title': "Welcome to Spyder introduction tour", 'content': "Spyder is an interactive development \ environment. This tip panel supports rich text.
    \
    it also supports image insertion to the right so\ far", 'image': 'tour-spyder-logo.png'}, {'title': "Widget display", 'content': ("This show how a widget is displayed. The tip panel " "is adjusted based on the first widget in the list"), 'widgets': ['button1'], 'decoration': ['button2'], 'interact': True}, {'title': "Widget display", 'content': ("This show how a widget is displayed. The tip panel " "is adjusted based on the first widget in the list"), 'widgets': ['button1'], 'decoration': ['button1'], 'interact': True}, {'title': "Widget display", 'content': ("This show how a widget is displayed. The tip panel " "is adjusted based on the first widget in the list"), 'widgets': ['button1'], 'interact': True}, {'title': "Widget display and highlight", 'content': "This shows how a highlighted widget looks", 'widgets': ['button'], 'decoration': ['button'], 'interact': False}, ] intro = [{'title': _("Welcome to the Introduction tour"), 'content': _("Spyder is a powerful Interactive " "Development Environment (or IDE) for the Python " "programming language.

    " "Here we are going to guide you through its most " "important features.

    " "Please use the arrow keys or click on the buttons " "below to move along the tour."), 'image': 'tour-spyder-logo.png'}, {'title': _("The Editor"), 'content': _("This is the pane where you write Python code before " "evaluating it. You can get automatic suggestions " "and completions while writing, by pressing the " "Tab key next to a given text.

    " "The Editor comes " "with a line number area (highlighted here in red), " "where Spyder shows warnings and syntax errors. They " "can help you to detect potential problems before " "running the code.

    " "You can also set debug breakpoints in the line " "number area, by doing a double click next to " "a non-empty line."), 'widgets': [sw.editor], 'decoration': [sw.editor_line_number_area]}, {'title': _("The IPython console"), 'content': _("This is one of panes where you can run or " "execute the code you wrote on the Editor. To do it " "you need to press the F5 key.

    " "This console comes with several " "useful features that greatly improve your " "programming workflow (like syntax highlighting and " "inline plots). If you want to know more about them, " "please follow this link.

    " "Please click on the button below to run some simple " "code in this console. This will be useful to show " "you other important features.").format( qtconsole_link), 'widgets': [sw.ipython_console], 'run': ["li = list(range(100))", "d = {'a': 1, 'b': 2}"] }, {'title': _("The Variable Explorer"), 'content': _("In this pane you can view and edit the variables " "generated during the execution of a program, or " "those entered directly in one of Spyder " "consoles.

    " "As you can see, the Variable Explorer is showing " "the variables generated during the last step of " "this tour. By doing a double-click on any " "of them, a new window will be opened, where you " "can inspect and modify their contents."), 'widgets': [sw.variable_explorer], 'interact': True}, {'title': _("Help"), 'content': _("This pane displays documentation of the " "functions, classes, methods or modules you are " "currently using in the Editor or the Consoles.

    " "To use it, you need to press Ctrl+I in " "front of an object. If that object has some " "documentation associated with it, it will be " "displayed here."), 'widgets': [sw.help_plugin], 'interact': True}, {'title': _("The File Explorer"), 'content': _("This pane lets you navigate through the directories " "and files present in your computer.

    " "You can also open any of these files with its " "corresponding application, by doing a double " "click on it.

    " "There is one exception to this rule: plain-text " "files will always be opened in the Spyder Editor."), 'widgets': [sw.file_explorer], 'interact': True}, {'title': _("The History Log"), 'content': _("This pane records all commands introduced in " "the Python and IPython consoles."), 'widgets': [sw.history_log], 'interact': True}, ] # ['The run toolbar', # 'Should be short', # ['self.run_toolbar'], None], # ['The debug toolbar', # '', # ['self.debug_toolbar'], None], # ['The main toolbar', # '', # ['self.main_toolbar'], None], # ['The editor', # 'Spyder has differnet bla bla bla', # ['self.editor.dockwidget'], None], # ['The editor', # 'Spyder has differnet bla bla bla', # ['self.outlineexplorer.dockwidget'], None], # # ['The menu bar', # 'Spyder has differnet bla bla bla', # ['self.menuBar()'], None], # # ['The menu bar', # 'Spyder has differnet bla bla bla', # ['self.statusBar()'], None], # # # ['The toolbars!', # 'Spyder has differnet bla bla bla', # ['self.variableexplorer.dockwidget'], None], # ['The toolbars MO!', # 'Spyder has differnet bla bla bla', # ['self.extconsole.dockwidget'], None], # ['The whole window?!', # 'Spyder has differnet bla bla bla', # ['self'], None], # ['Lets try something!', # 'Spyder has differnet bla bla bla', # ['self.extconsole.dockwidget', # 'self.variableexplorer.dockwidget'], None] # # ] feat30 = [{'title': "New features in Spyder 3.0", 'content': _("Spyder is an interactive development " "environment based on bla"), 'image': 'spyder.png'}, {'title': _("Welcome to Spyder introduction tour"), 'content': _("Spyder is an interactive development environment " "based on bla"), 'widgets': ['variableexplorer']}, ] tours = [{'name': _('Introduction tour'), 'tour': intro}, {'name': _('New features in version 3.0'), 'tour': feat30}] if index is None: return tours elif index == -1: return [test] else: return [tours[index]] class FadingDialog(QDialog): """A general fade in/fade out QDialog with some builtin functions""" sig_key_pressed = Signal() def __init__(self, parent, opacity, duration, easing_curve): super(FadingDialog, self).__init__(parent) self.parent = parent self.opacity_min = min(opacity) self.opacity_max = max(opacity) self.duration_fadein = duration[0] self.duration_fadeout = duration[-1] self.easing_curve_in = easing_curve[0] self.easing_curve_out = easing_curve[-1] self.effect = None self.anim = None self._fade_running = False self._funcs_before_fade_in = [] self._funcs_after_fade_in = [] self._funcs_before_fade_out = [] self._funcs_after_fade_out = [] self.setModal(False) def _run(self, funcs): """ """ for func in funcs: func() def _run_before_fade_in(self): """ """ self._run(self._funcs_before_fade_in) def _run_after_fade_in(self): """ """ self._run(self._funcs_after_fade_in) def _run_before_fade_out(self): """ """ self._run(self._funcs_before_fade_out) def _run_after_fade_out(self): """ """ self._run(self._funcs_after_fade_out) def _set_fade_finished(self): """ """ self._fade_running = False def _fade_setup(self): """ """ self._fade_running = True self.effect = QGraphicsOpacityEffect(self) self.setGraphicsEffect(self.effect) self.anim = QPropertyAnimation(self.effect, to_binary_string("opacity")) # --- public api def fade_in(self, on_finished_connect): """ """ self._run_before_fade_in() self._fade_setup() self.show() self.raise_() self.anim.setEasingCurve(self.easing_curve_in) self.anim.setStartValue(self.opacity_min) self.anim.setEndValue(self.opacity_max) self.anim.setDuration(self.duration_fadein) self.anim.finished.connect(on_finished_connect) self.anim.finished.connect(self._set_fade_finished) self.anim.finished.connect(self._run_after_fade_in) self.anim.start() def fade_out(self, on_finished_connect): """ """ self._run_before_fade_out() self._fade_setup() self.anim.setEasingCurve(self.easing_curve_out) self.anim.setStartValue(self.opacity_max) self.anim.setEndValue(self.opacity_min) self.anim.setDuration(self.duration_fadeout) self.anim.finished.connect(on_finished_connect) self.anim.finished.connect(self._set_fade_finished) self.anim.finished.connect(self._run_after_fade_out) self.anim.start() def is_fade_running(self): """ """ return self._fade_running def set_funcs_before_fade_in(self, funcs): """ """ self._funcs_before_fade_in = funcs def set_funcs_after_fade_in(self, funcs): """ """ self._funcs_after_fade_in = funcs def set_funcs_before_fade_out(self, funcs): """ """ self._funcs_before_fade_out = funcs def set_funcs_after_fade_out(self, funcs): """ """ self._funcs_after_fade_out = funcs class FadingCanvas(FadingDialog): """The black semi transparent canvas that covers the application""" def __init__(self, parent, opacity, duration, easing_curve, color, tour=None): """Create a black semi transparent canvas that covers the app.""" super(FadingCanvas, self).__init__(parent, opacity, duration, easing_curve) self.parent = parent self.tour = tour self.color = color # Canvas color self.color_decoration = Qt.red # Decoration color self.stroke_decoration = 2 # width in pixels for decoration self.region_mask = None self.region_subtract = None self.region_decoration = None self.widgets = None # The widget to uncover self.decoration = None # The widget to draw decoration self.interaction_on = False self.path_current = None self.path_subtract = None self.path_full = None self.path_decoration = None # widget setup self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint) self.setAttribute(Qt.WA_TranslucentBackground) self.setAttribute(Qt.WA_TransparentForMouseEvents) self.setModal(False) self.setFocusPolicy(Qt.NoFocus) self.set_funcs_before_fade_in([self.update_canvas]) self.set_funcs_after_fade_out([lambda: self.update_widgets(None), lambda: self.update_decoration(None)]) def set_interaction(self, value): """ """ self.interaction_on = value def update_canvas(self): """ """ w, h = self.parent.size().width(), self.parent.size().height() self.path_full = QPainterPath() self.path_subtract = QPainterPath() self.path_decoration = QPainterPath() self.region_mask = QRegion(0, 0, w, h) self.path_full.addRect(0, 0, w, h) # Add the path if self.widgets is not None: for widget in self.widgets: temp_path = QPainterPath() # if widget is not found... find more general way to handle if widget is not None: widget.raise_() widget.show() geo = widget.frameGeometry() width, height = geo.width(), geo.height() point = widget.mapTo(self.parent, QPoint(0, 0)) x, y = point.x(), point.y() temp_path.addRect(QRectF(x, y, width, height)) temp_region = QRegion(x, y, width, height) if self.interaction_on: self.region_mask = self.region_mask.subtracted(temp_region) self.path_subtract = self.path_subtract.united(temp_path) self.path_current = self.path_full.subtracted(self.path_subtract) else: self.path_current = self.path_full if self.decoration is not None: for widget in self.decoration: temp_path = QPainterPath() widget.raise_() widget.show() geo = widget.frameGeometry() width, height = geo.width(), geo.height() point = widget.mapTo(self.parent, QPoint(0, 0)) x, y = point.x(), point.y() temp_path.addRect(QRectF(x, y, width, height)) temp_region_1 = QRegion(x-1, y-1, width+2, height+2) temp_region_2 = QRegion(x+1, y+1, width-2, height-2) temp_region = temp_region_1.subtracted(temp_region_2) if self.interaction_on: self.region_mask = self.region_mask.united(temp_region) self.path_decoration = self.path_decoration.united(temp_path) else: self.path_decoration.addRect(0, 0, 0, 0) # Add a decoration stroke around widget self.setMask(self.region_mask) self.update() self.repaint() def update_widgets(self, widgets): """ """ self.widgets = widgets def update_decoration(self, widgets): """ """ self.decoration = widgets def paintEvent(self, event): """Override Qt method""" painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) # Decoration painter.fillPath(self.path_current, QBrush(self.color)) painter.strokePath(self.path_decoration, QPen(self.color_decoration, self.stroke_decoration)) # decoration_fill = QColor(self.color_decoration) # decoration_fill.setAlphaF(0.25) # painter.fillPath(self.path_decoration, decoration_fill) def reject(self): """Override Qt method""" if not self.is_fade_running(): key = Qt.Key_Escape self.key_pressed = key self.sig_key_pressed.emit() def mousePressEvent(self, event): """Override Qt method""" pass def focusInEvent(self, event): """Override Qt method.""" # To be used so tips do not appear outside spyder if self.hasFocus(): self.tour.gain_focus() def focusOutEvent(self, event): """Override Qt method.""" # To be used so tips do not appear outside spyder if self.tour.step_current != 0: self.tour.lost_focus() class FadingTipBox(FadingDialog): """ """ def __init__(self, parent, opacity, duration, easing_curve, tour=None): super(FadingTipBox, self).__init__(parent, opacity, duration, easing_curve) self.holder = self.anim # needed for qt to work self.parent = parent self.tour = tour self.frames = None self.color_top = QColor.fromRgb(230, 230, 230) self.color_back = QColor.fromRgb(255, 255, 255) self.offset_shadow = 0 self.fixed_width = 300 self.key_pressed = None self.setAttribute(Qt.WA_TranslucentBackground) self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) self.setModal(False) # Widgets self.button_home = QPushButton("<<") self.button_close = QPushButton("X") self.button_previous = QPushButton(" < ") self.button_end = QPushButton(">>") self.button_next = QPushButton(" > ") self.button_run = QPushButton(_('Run code')) self.button_disable = None self.button_current = QToolButton() self.label_image = QLabel() self.label_title = QLabel() self.combo_title = QComboBox() self.label_current = QLabel() self.label_content = QLabel() self.label_content.setMinimumWidth(self.fixed_width) self.label_content.setMaximumWidth(self.fixed_width) self.label_current.setAlignment(Qt.AlignCenter) self.label_content.setWordWrap(True) self.widgets = [self.label_content, self.label_title, self.label_current, self.combo_title, self.button_close, self.button_run, self.button_next, self.button_previous, self.button_end, self.button_home, self.button_current] arrow = get_image_path('hide.png') self.stylesheet = '''QPushButton { background-color: rgbs(200,200,200,100%); color: rgbs(0,0,0,100%); border-style: outset; border-width: 1px; border-radius: 3px; border-color: rgbs(100,100,100,100%); padding: 2px; } QPushButton:hover { background-color: rgbs(150, 150, 150, 100%); } QPushButton:disabled { background-color: rgbs(230,230,230,100%); color: rgbs(200,200,200,100%); border-color: rgbs(200,200,200,100%); } QComboBox { padding-left: 5px; background-color: rgbs(230,230,230,100%); border-width: 0px; border-radius: 0px; min-height:20px; max-height:20px; } QComboBox::drop-down { subcontrol-origin: padding; subcontrol-position: top left; border-width: 0px; } QComboBox::down-arrow { image: url(''' + arrow + '''); } ''' # Windows fix, slashes should be always in unix-style self.stylesheet = self.stylesheet.replace('\\', '/') self.setFocusPolicy(Qt.StrongFocus) for widget in self.widgets: widget.setFocusPolicy(Qt.NoFocus) widget.setStyleSheet(self.stylesheet) layout_top = QHBoxLayout() layout_top.addWidget(self.combo_title) layout_top.addStretch() layout_top.addWidget(self.button_close) layout_top.addSpacerItem(QSpacerItem(self.offset_shadow, self.offset_shadow)) layout_content = QHBoxLayout() layout_content.addWidget(self.label_content) layout_content.addWidget(self.label_image) layout_content.addSpacerItem(QSpacerItem(5, 5)) layout_run = QHBoxLayout() layout_run.addStretch() layout_run.addWidget(self.button_run) layout_run.addStretch() layout_run.addSpacerItem(QSpacerItem(self.offset_shadow, self.offset_shadow)) layout_navigation = QHBoxLayout() layout_navigation.addWidget(self.button_home) layout_navigation.addWidget(self.button_previous) layout_navigation.addStretch() layout_navigation.addWidget(self.label_current) layout_navigation.addStretch() layout_navigation.addWidget(self.button_next) layout_navigation.addWidget(self.button_end) layout_navigation.addSpacerItem(QSpacerItem(self.offset_shadow, self.offset_shadow)) layout = QVBoxLayout() layout.addLayout(layout_top) layout.addStretch() layout.addSpacerItem(QSpacerItem(15, 15)) layout.addLayout(layout_content) layout.addLayout(layout_run) layout.addStretch() layout.addSpacerItem(QSpacerItem(15, 15)) layout.addLayout(layout_navigation) layout.addSpacerItem(QSpacerItem(self.offset_shadow, self.offset_shadow)) layout.setSizeConstraint(QLayout.SetFixedSize) self.setLayout(layout) self.set_funcs_before_fade_in([self._disable_widgets]) self.set_funcs_after_fade_in([self._enable_widgets, self.setFocus]) self.set_funcs_before_fade_out([self._disable_widgets]) self.setContextMenuPolicy(Qt.CustomContextMenu) # signals and slots # These are defined every time by the AnimatedTour Class def _disable_widgets(self): """ """ for widget in self.widgets: widget.setDisabled(True) def _enable_widgets(self): """ """ self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) for widget in self.widgets: widget.setDisabled(False) if self.button_disable == 'previous': self.button_previous.setDisabled(True) self.button_home.setDisabled(True) elif self.button_disable == 'next': self.button_next.setDisabled(True) self.button_end.setDisabled(True) def set_data(self, title, content, current, image, run, frames=None, step=None): """ """ self.label_title.setText(title) self.combo_title.clear() self.combo_title.addItems(frames) self.combo_title.setCurrentIndex(step) # min_content_len = max([len(f) for f in frames]) # self.combo_title.setMinimumContentsLength(min_content_len) # Fix and try to see how it looks with a combo box self.label_current.setText(current) self.button_current.setText(current) self.label_content.setText(content) self.image = image if image is None: self.label_image.setFixedHeight(1) self.label_image.setFixedWidth(1) else: extension = image.split('.')[-1] self.image = QPixmap(get_image_path(image), extension) self.label_image.setPixmap(self.image) self.label_image.setFixedSize(self.image.size()) if run is None: self.button_run.setVisible(False) else: self.button_run.setDisabled(False) self.button_run.setVisible(True) # Refresh layout self.layout().activate() def set_pos(self, x, y): """ """ self.x = x self.y = y self.move(QPoint(x, y)) def build_paths(self): """ """ geo = self.geometry() radius = 30 shadow = self.offset_shadow x0, y0 = geo.x(), geo.y() width, height = geo.width() - shadow, geo.height() - shadow left, top = 0, 0 right, bottom = width, height self.round_rect_path = QPainterPath() self.round_rect_path.moveTo(right, top + radius) self.round_rect_path.arcTo(right-radius, top, radius, radius, 0.0, 90.0) self.round_rect_path.lineTo(left+radius, top) self.round_rect_path.arcTo(left, top, radius, radius, 90.0, 90.0) self.round_rect_path.lineTo(left, bottom-radius) self.round_rect_path.arcTo(left, bottom-radius, radius, radius, 180.0, 90.0) self.round_rect_path.lineTo(right-radius, bottom) self.round_rect_path.arcTo(right-radius, bottom-radius, radius, radius, 270.0, 90.0) self.round_rect_path.closeSubpath() # Top path header = 36 offset = 2 left, top = offset, offset right = width - (offset) self.top_rect_path = QPainterPath() self.top_rect_path.lineTo(right, top + radius) self.top_rect_path.moveTo(right, top + radius) self.top_rect_path.arcTo(right-radius, top, radius, radius, 0.0, 90.0) self.top_rect_path.lineTo(left+radius, top) self.top_rect_path.arcTo(left, top, radius, radius, 90.0, 90.0) self.top_rect_path.lineTo(left, top + header) self.top_rect_path.lineTo(right, top + header) def paintEvent(self, event): """ """ self.build_paths() painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) painter.fillPath(self.round_rect_path, self.color_back) painter.fillPath(self.top_rect_path, self.color_top) painter.strokePath(self.round_rect_path, QPen(Qt.gray, 1)) # TODO: Build the pointing arrow? def keyReleaseEvent(self, event): """ """ key = event.key() self.key_pressed = key keys = [Qt.Key_Right, Qt.Key_Left, Qt.Key_Down, Qt.Key_Up, Qt.Key_Escape, Qt.Key_PageUp, Qt.Key_PageDown, Qt.Key_Home, Qt.Key_End, Qt.Key_Menu] if key in keys: if not self.is_fade_running(): self.sig_key_pressed.emit() def mousePressEvent(self, event): """override Qt method""" # Raise the main application window on click self.parent.raise_() self.raise_() if event.button() == Qt.RightButton: pass # clicked_widget = self.childAt(event.x(), event.y()) # if clicked_widget == self.label_current: # self.context_menu_requested(event) def focusOutEvent(self, event): """Override Qt method.""" # To be used so tips do not appear outside spyder self.tour.lost_focus() def context_menu_requested(self, event): """ """ pos = QPoint(event.x(), event.y()) menu = QMenu(self) actions = [] action_title = create_action(self, _('Go to step: '), icon=QIcon()) action_title.setDisabled(True) actions.append(action_title) # actions.append(create_action(self, _(': '), icon=QIcon())) add_actions(menu, actions) menu.popup(self.mapToGlobal(pos)) def reject(self): """Qt method to handle escape key event""" if not self.is_fade_running(): key = Qt.Key_Escape self.key_pressed = key self.sig_key_pressed.emit() class AnimatedTour(QWidget): """ """ def __init__(self, parent): QWidget.__init__(self, parent) self.parent = parent # Variables to adjust self.duration_canvas = [666, 666] self.duration_tips = [333, 333] self.opacity_canvas = [0.0, 0.7] self.opacity_tips = [0.0, 1.0] self.color = Qt.black self.easing_curve = [QEasingCurve.Linear] self.current_step = 0 self.step_current = 0 self.steps = 0 self.canvas = None self.tips = None self.frames = None self.spy_window = None self.widgets = None self.dockwidgets = None self.decoration = None self.run = None self.is_tour_set = False self.is_running = False # Widgets self.canvas = FadingCanvas(self.parent, self.opacity_canvas, self.duration_canvas, self.easing_curve, self.color, tour=self) self.tips = FadingTipBox(self.parent, self.opacity_tips, self.duration_tips, self.easing_curve, tour=self) # Widgets setup # Needed to fix issue #2204 self.setAttribute(Qt.WA_TransparentForMouseEvents) # Signals and slots self.tips.button_next.clicked.connect(self.next_step) self.tips.button_previous.clicked.connect(self.previous_step) self.tips.button_close.clicked.connect(self.close_tour) self.tips.button_run.clicked.connect(self.run_code) self.tips.button_home.clicked.connect(self.first_step) self.tips.button_end.clicked.connect(self.last_step) self.tips.button_run.clicked.connect( lambda: self.tips.button_run.setDisabled(True)) self.tips.combo_title.currentIndexChanged.connect(self.go_to_step) # Main window move or resize self.parent.sig_resized.connect(self._resized) self.parent.sig_moved.connect(self._moved) # To capture the arrow keys that allow moving the tour self.tips.sig_key_pressed.connect(self._key_pressed) # To control the focus of tour self.setting_data = False self.hidden = False def _resized(self, event): """ """ if self.is_running: size = event.size() self.canvas.setFixedSize(size) self.canvas.update_canvas() if self.is_tour_set: self._set_data() def _moved(self, event): """ """ if self.is_running: pos = event.pos() self.canvas.move(QPoint(pos.x(), pos.y())) if self.is_tour_set: self._set_data() def _close_canvas(self): """ """ self.tips.hide() self.canvas.fade_out(self.canvas.hide) def _clear_canvas(self): """ """ # TODO: Add option to also make it white... might be usefull? # Make canvas black before transitions self.canvas.update_widgets(None) self.canvas.update_decoration(None) self.canvas.update_canvas() def _move_step(self): """ """ self._set_data() # Show/raise the widget so it is located first! widgets = self.dockwidgets if widgets is not None: widget = widgets[0] if widget is not None: widget.show() widget.raise_() self._locate_tip_box() # Change in canvas only after fadein finishes, for visual aesthetics self.tips.fade_in(self.canvas.update_canvas) self.tips.raise_() def _set_modal(self, value, widgets): """ """ platform = sys.platform.lower() if 'linux' in platform: pass elif 'win' in platform: for widget in widgets: widget.setModal(value) widget.hide() widget.show() elif 'darwin' in platform: pass else: pass def _process_widgets(self, names, spy_window): """ """ widgets = [] dockwidgets = [] for name in names: base = name.split('.')[0] temp = getattr(spy_window, base) # Check if it is the current editor if 'get_current_editor()' in name: temp = temp.get_current_editor() temp = getattr(temp, name.split('.')[-1]) widgets.append(temp) # Check if it is a dockwidget and make the widget a dockwidget # If not return the same widget temp = getattr(temp, 'dockwidget', temp) dockwidgets.append(temp) return widgets, dockwidgets def _set_data(self): """Set data that is displayed in each step of the tour.""" self.setting_data = True step, steps, frames = self.step_current, self.steps, self.frames current = '{0}/{1}'.format(step + 1, steps) frame = frames[step] combobox_frames = [u"{0}. {1}".format(i+1, f['title']) for i, f in enumerate(frames)] title, content, image = '', '', None widgets, dockwidgets, decoration = None, None, None run = None # Check if entry exists in dic and act accordingly if 'title' in frame: title = frame['title'] if 'content' in frame: content = frame['content'] if 'widgets' in frame: widget_names = frames[step]['widgets'] # Get the widgets based on their name widgets, dockwidgets = self._process_widgets(widget_names, self.spy_window) self.widgets = widgets self.dockwidgets = dockwidgets if 'decoration' in frame: widget_names = frames[step]['decoration'] deco, decoration = self._process_widgets(widget_names, self.spy_window) self.decoration = decoration if 'image' in frame: image = frames[step]['image'] if 'interact' in frame: self.canvas.set_interaction(frame['interact']) if frame['interact']: self._set_modal(False, [self.tips]) else: self._set_modal(True, [self.tips]) else: self.canvas.set_interaction(False) self._set_modal(True, [self.tips]) if 'run' in frame: # Asume that the frist widget is the console run = frame['run'] self.run = run self.tips.set_data(title, content, current, image, run, frames=combobox_frames, step=step) self._check_buttons() # Make canvas black when starting a new place of decoration self.canvas.update_widgets(dockwidgets) self.canvas.update_decoration(decoration) self.setting_data = False def _locate_tip_box(self): """ """ dockwidgets = self.dockwidgets # Store the dimensions of the main window geo = self.parent.frameGeometry() x, y, width, height = geo.x(), geo.y(), geo.width(), geo.height() self.width_main = width self.height_main = height self.x_main = x self.y_main = y delta = 20 # Here is the tricky part to define the best position for the # tip widget if dockwidgets is not None: if dockwidgets[0] is not None: geo = dockwidgets[0].geometry() x, y, width, height = geo.x(), geo.y(), geo.width(), geo.height() point = dockwidgets[0].mapToGlobal(QPoint(0, 0)) x_glob, y_glob = point.x(), point.y() # Check if is too tall and put to the side y_fac = (height / self.height_main) * 100 if y_fac > 60: # FIXME: if x < self.tips.width(): x = x_glob + width + delta y = y_glob + height/2 - self.tips.height()/2 else: x = x_glob - self.tips.width() - delta y = y_glob + height/2 - self.tips.height()/2 else: if y < self.tips.height(): x = x_glob + width/2 - self.tips.width()/2 y = y_glob + height + delta else: x = x_glob + width/2 - self.tips.width()/2 y = y_glob - delta - self.tips.height() else: # Center on parent x = self.x_main + self.width_main/2 - self.tips.width()/2 y = self.y_main + self.height_main/2 - self.tips.height()/2 self.tips.set_pos(x, y) def _check_buttons(self): """ """ step, steps = self.step_current, self.steps self.tips.button_disable = None if step == 0: self.tips.button_disable = 'previous' if step == steps - 1: self.tips.button_disable = 'next' def _key_pressed(self): """ """ key = self.tips.key_pressed if ((key == Qt.Key_Right or key == Qt.Key_Down or key == Qt.Key_PageDown) and self.step_current != self.steps - 1): self.next_step() elif ((key == Qt.Key_Left or key == Qt.Key_Up or key == Qt.Key_PageUp) and self.step_current != 0): self.previous_step() elif key == Qt.Key_Escape: self.close_tour() elif key == Qt.Key_Home and self.step_current != 0: self.first_step() elif key == Qt.Key_End and self.step_current != self.steps - 1: self.last_step() elif key == Qt.Key_Menu: pos = self.tips.label_current.pos() self.tips.context_menu_requested(pos) def _hiding(self): self.hidden = True self.tips.hide() # --- public api def run_code(self): """ """ codelines = self.run console = self.widgets[0] for codeline in codelines: console.execute_code(codeline) def set_tour(self, index, frames, spy_window): """ """ self.spy_window = spy_window self.active_tour_index = index self.last_frame_active = frames['last'] self.frames = frames['tour'] self.steps = len(self.frames) self.is_tour_set = True def start_tour(self): """ """ geo = self.parent.geometry() x, y, width, height = geo.x(), geo.y(), geo.width(), geo.height() # self.parent_x = x # self.parent_y = y # self.parent_w = width # self.parent_h = height # FIXME: reset step to last used value # Reset step to begining self.step_current = self.last_frame_active # Adjust the canvas size to match the main window size self.canvas.setFixedSize(width, height) self.canvas.move(QPoint(x, y)) self.canvas.fade_in(self._move_step) self._clear_canvas() self.is_running = True def close_tour(self): """ """ self.tips.fade_out(self._close_canvas) self.canvas.set_interaction(False) self._set_modal(True, [self.tips]) self.canvas.hide() try: # set the last played frame by updating the available tours in # parent. This info will be lost on restart. self.parent.tours_available[self.active_tour_index]['last'] =\ self.step_current except: pass self.is_running = False def hide_tips(self): """Hide tips dialog when the main window loses focus.""" self._clear_canvas() self.tips.fade_out(self._hiding) def unhide_tips(self): """Unhide tips dialog when the main window loses focus.""" self._clear_canvas() self._move_step() self.hidden = False def next_step(self): """ """ self._clear_canvas() self.step_current += 1 self.tips.fade_out(self._move_step) def previous_step(self): """ """ self._clear_canvas() self.step_current -= 1 self.tips.fade_out(self._move_step) def go_to_step(self, number, id_=None): """ """ self._clear_canvas() self.step_current = number self.tips.fade_out(self._move_step) def last_step(self): """ """ self.go_to_step(self.steps - 1) def first_step(self): """ """ self.go_to_step(0) def lost_focus(self): """Confirm if the tour loses focus and hides the tips.""" if (self.is_running and not self.any_has_focus() and not self.setting_data and not self.hidden): self.hide_tips() def gain_focus(self): """Confirm if the tour regains focus and unhides the tips.""" if (self.is_running and self.any_has_focus() and not self.setting_data and self.hidden): self.unhide_tips() def any_has_focus(self): """Returns if tour or any of its components has focus.""" f = (self.hasFocus() or self.parent.hasFocus() or self.tips.hasFocus() or self.canvas.hasFocus()) return f # ---------------------------------------------------------------------------- # Used for testing the functionality class TourTestWindow(QMainWindow): """ """ sig_resized = Signal("QResizeEvent") sig_moved = Signal("QMoveEvent") def __init__(self): super(TourTestWindow, self).__init__() self.setGeometry(300, 100, 400, 600) self.setWindowTitle('Exploring QMainWindow') self.exit = QAction('Exit', self) self.exit.setStatusTip('Exit program') # create the menu bar menubar = self.menuBar() file_ = menubar.addMenu('&File') file_.addAction(self.exit) # create the status bar self.statusBar() # QWidget or its instance needed for box layout self.widget = QWidget(self) self.button = QPushButton('test') self.button1 = QPushButton('1') self.button2 = QPushButton('2') effect = QGraphicsOpacityEffect(self.button2) self.button2.setGraphicsEffect(effect) self.anim = QPropertyAnimation(effect, to_binary_string("opacity")) self.anim.setStartValue(0.01) self.anim.setEndValue(1.0) self.anim.setDuration(500) lay = QVBoxLayout() lay.addWidget(self.button) lay.addStretch() lay.addWidget(self.button1) lay.addWidget(self.button2) self.widget.setLayout(lay) self.setCentralWidget(self.widget) self.button.clicked.connect(self.action1) self.button1.clicked.connect(self.action2) self.tour = AnimatedTour(self) def action1(self): """ """ frames = get_tour('test') index = 0 dic = {'last': 0, 'tour': frames} self.tour.set_tour(index, dic, self) self.tour.start_tour() def action2(self): """ """ self.anim.start() def resizeEvent(self, event): """Reimplement Qt method""" QMainWindow.resizeEvent(self, event) self.sig_resized.emit(event) def moveEvent(self, event): """Reimplement Qt method""" QMainWindow.moveEvent(self, event) self.sig_moved.emit(event) def test(): """ """ app = QApplication([]) win = TourTestWindow() win.show() app.exec_() if __name__ == '__main__': test() spyder-3.2.6/spyder/app/start.py0000664000175000017500000001266413224121062017421 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # Std imports import os import os.path as osp import random import socket import sys import time # To prevent a race condition with ZMQ # See issue 5324 import zmq # This import is needed to fix errors with OpenGL when installed using pip # See issue 3332 try: from OpenGL import GL except: pass # Local imports from spyder.app.cli_options import get_options from spyder.config.base import get_conf_path, running_in_mac_app from spyder.config.main import CONF from spyder.utils.external import lockfile from spyder.py3compat import is_unicode def send_args_to_spyder(args): """ Simple socket client used to send the args passed to the Spyder executable to an already running instance. Args can be Python scripts or files with these extensions: .spydata, .mat, .npy, or .h5, which can be imported by the Variable Explorer. """ port = CONF.get('main', 'open_files_port') # Wait ~50 secs for the server to be up # Taken from http://stackoverflow.com/a/4766598/438386 for _x in range(200): try: for arg in args: client = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP) client.connect(("127.0.0.1", port)) if is_unicode(arg): arg = arg.encode('utf-8') client.send(osp.abspath(arg)) client.close() except socket.error: time.sleep(0.25) continue break def main(): """ Start Spyder application. If single instance mode is turned on (default behavior) and an instance of Spyder is already running, this will just parse and send command line options to the application. """ # Parse command line options options, args = get_options() # Store variable to be used in self.restart (restart spyder instance) os.environ['SPYDER_ARGS'] = str(sys.argv[1:]) #========================================================================== # Proper high DPI scaling is available in Qt >= 5.6.0. This attibute must # be set before creating the application. #========================================================================== if CONF.get('main', 'high_dpi_custom_scale_factor'): factors = str(CONF.get('main', 'high_dpi_custom_scale_factors')) f = list(filter(None, factors.split(';'))) if len(f) == 1: os.environ['QT_SCALE_FACTOR'] = f[0] else: os.environ['QT_SCREEN_SCALE_FACTORS'] = factors else: os.environ['QT_SCALE_FACTOR'] = '' os.environ['QT_SCREEN_SCALE_FACTORS'] = '' # Prevent Spyder from crashing in macOS if locale is not defined if sys.platform == 'darwin': LANG = os.environ.get('LANG') LC_ALL = os.environ.get('LC_ALL') if bool(LANG) and not bool(LC_ALL): LC_ALL = LANG elif not bool(LANG) and bool(LC_ALL): LANG = LC_ALL else: LANG = LC_ALL = 'en_US.UTF-8' os.environ['LANG'] = LANG os.environ['LC_ALL'] = LC_ALL if CONF.get('main', 'single_instance') and not options.new_instance \ and not options.reset_config_files and not running_in_mac_app(): # Minimal delay (0.1-0.2 secs) to avoid that several # instances started at the same time step in their # own foots while trying to create the lock file time.sleep(random.randrange(1000, 2000, 90)/10000.) # Lock file creation lock_file = get_conf_path('spyder.lock') lock = lockfile.FilesystemLock(lock_file) # Try to lock spyder.lock. If it's *possible* to do it, then # there is no previous instance running and we can start a # new one. If *not*, then there is an instance already # running, which is locking that file try: lock_created = lock.lock() except: # If locking fails because of errors in the lockfile # module, try to remove a possibly stale spyder.lock. # This is reported to solve all problems with # lockfile (See issue 2363) try: if os.name == 'nt': if osp.isdir(lock_file): import shutil shutil.rmtree(lock_file, ignore_errors=True) else: if osp.islink(lock_file): os.unlink(lock_file) except: pass # Then start Spyder as usual and *don't* continue # executing this script because it doesn't make # sense from spyder.app import mainwindow mainwindow.main() return if lock_created: # Start a new instance from spyder.app import mainwindow mainwindow.main() else: # Pass args to Spyder or print an informative # message if args: send_args_to_spyder(args) else: print("Spyder is already running. If you want to open a new \n" "instance, please pass to it the --new-instance option") else: from spyder.app import mainwindow mainwindow.main() if __name__ == "__main__": main() spyder-3.2.6/spyder/app/tests/0000775000175000017500000000000013225025007017046 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/app/tests/script_pylint.py0000664000175000017500000000022213224121062022314 0ustar carloscarlos00000000000000#%% # pylint: enable=C0111 # pylint: enable=C0103 # pylint: enable=C0413 a = 10 #%% li = [1, 2, 3] #%% import numpy as np arr = np.array(li) spyder-3.2.6/spyder/app/tests/test_tour.py0000664000175000017500000000104213156676663021474 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for tour.py """ # Test library imports import pytest # Local imports from spyder.app.tour import TourTestWindow @pytest.fixture def setup_tour(qtbot): "Setup the QMainWindow for the tour." tour = TourTestWindow() qtbot.addWidget(tour) return tour def test_tour(qtbot): """Test tour.""" tour = setup_tour(qtbot) tour.show() assert tour if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/app/tests/pyx_script.pyx0000664000175000017500000000046713211142272022022 0ustar carloscarlos00000000000000cpdef int factorial(int x): # Basic example of a cython function, which defines # python-like operations and control flow on defined c types cdef int m = x cdef int i if x <= 1: return 1 else: for i in range(1, x): m = m * i return m a = factorial(10) spyder-3.2.6/spyder/app/tests/script.py0000664000175000017500000000011313156676663020746 0ustar carloscarlos00000000000000#%% a = 10 #%% li = [1, 2, 3] #%% import numpy as np arr = np.array(li) spyder-3.2.6/spyder/app/tests/notebook.ipynb0000664000175000017500000000155213156676663021763 0ustar carloscarlos00000000000000{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "1 + 1" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.2+" } }, "nbformat": 4, "nbformat_minor": 2 } spyder-3.2.6/spyder/app/tests/test_mainwindow.py0000664000175000017500000011763213224740762022660 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for the main window """ import os import os.path as osp from sys import version_info import shutil import tempfile from flaky import flaky from jupyter_client.manager import KernelManager import numpy as np from numpy.testing import assert_array_equal import pytest from qtpy import PYQT4, PYQT5, PYQT_VERSION from qtpy.QtCore import Qt, QTimer from qtpy.QtTest import QTest from qtpy.QtWidgets import QApplication, QFileDialog, QLineEdit from spyder.app.cli_options import get_options from spyder.app.mainwindow import initialize, run_spyder from spyder.config.base import get_home_dir from spyder.config.main import CONF from spyder.plugins.runconfig import RunConfiguration from spyder.py3compat import PY2, to_text_string from spyder.utils.ipython.kernelspec import SpyderKernelSpec from spyder.utils.programs import is_module_installed #============================================================================== # Constants #============================================================================== # Location of this file LOCATION = osp.realpath(osp.join(os.getcwd(), osp.dirname(__file__))) # Time to wait until the IPython console is ready to receive input # (in miliseconds) SHELL_TIMEOUT = 20000 # Need longer EVAL_TIMEOUT, because need to cythonize and C compile ".pyx" file # before import and eval it COMPILE_AND_EVAL_TIMEOUT=30000 # Time to wait for the IPython console to evaluate something (in # miliseconds) EVAL_TIMEOUT = 3000 # Test for PyQt 5 wheels PYQT_WHEEL = PYQT_VERSION > '5.6' # Temporary directory TEMP_DIRECTORY = tempfile.gettempdir() #============================================================================== # Utility functions #============================================================================== def open_file_in_editor(main_window, fname, directory=None): """Open a file using the Editor and its open file dialog""" top_level_widgets = QApplication.topLevelWidgets() for w in top_level_widgets: if isinstance(w, QFileDialog): if directory is not None: w.setDirectory(directory) input_field = w.findChildren(QLineEdit)[0] input_field.setText(fname) QTest.keyClick(w, Qt.Key_Enter) def get_thirdparty_plugin(main_window, plugin_title): """Get a reference to the thirdparty plugin with the title given.""" for plugin in main_window.thirdparty_plugins: if plugin.get_plugin_title() == plugin_title: return plugin def reset_run_code(qtbot, shell, code_editor, nsb): """Reset state after a run code test""" with qtbot.waitSignal(shell.executed): shell.execute('%reset -f') qtbot.waitUntil(lambda: nsb.editor.model.rowCount() == 0, timeout=EVAL_TIMEOUT) code_editor.setFocus() qtbot.keyClick(code_editor, Qt.Key_Home, modifier=Qt.ControlModifier) def start_new_kernel(startup_timeout=60, kernel_name='python', spykernel=False, **kwargs): """Start a new kernel, and return its Manager and Client""" km = KernelManager(kernel_name=kernel_name) if spykernel: km._kernel_spec = SpyderKernelSpec() km.start_kernel(**kwargs) kc = km.client() kc.start_channels() try: kc.wait_for_ready(timeout=startup_timeout) except RuntimeError: kc.stop_channels() km.shutdown_kernel() raise return km, kc #============================================================================== # Fixtures #============================================================================== @pytest.fixture def main_window(request): """Main Window fixture""" # Tests assume inline backend CONF.set('ipython_console', 'pylab/backend', 0) # Check if we need to use introspection in a given test # (it's faster and less memory consuming not to use it!) use_introspection = request.node.get_marker('use_introspection') if use_introspection: os.environ['SPY_TEST_USE_INTROSPECTION'] = 'True' else: try: os.environ.pop('SPY_TEST_USE_INTROSPECTION') except KeyError: pass # Start the window app = initialize() options, args = get_options() window = run_spyder(app, options, args) def close_window(): window.close() request.addfinalizer(close_window) return window #============================================================================== # Tests #============================================================================== # IMPORTANT NOTE: Please leave this test to be the first one here to # avoid possible timeouts in Appveyor @pytest.mark.use_introspection @flaky(max_runs=3) @pytest.mark.skipif(os.environ.get('CI', None) is not None or os.name == 'nt' or PY2, reason="It times out in our CIs, and apparently Windows.") @pytest.mark.timeout(timeout=60, method='thread') def test_calltip(main_window, qtbot): """Hide the calltip in the editor when a matching ')' is found.""" # Load test file text = 'a = [1,2,3]\n(max' main_window.editor.new(fname="test.py", text=text) code_editor = main_window.editor.get_focus_widget() # Set text to start code_editor.set_text(text) code_editor.go_to_line(2) code_editor.move_cursor(5) calltip = code_editor.calltip_widget assert not calltip.isVisible() qtbot.keyPress(code_editor, Qt.Key_ParenLeft, delay=3000) qtbot.keyPress(code_editor, Qt.Key_A, delay=1000) qtbot.waitUntil(lambda: calltip.isVisible(), timeout=1000) qtbot.keyPress(code_editor, Qt.Key_ParenRight, delay=1000) qtbot.keyPress(code_editor, Qt.Key_Space) assert not calltip.isVisible() qtbot.keyPress(code_editor, Qt.Key_ParenRight, delay=1000) qtbot.keyPress(code_editor, Qt.Key_Enter, delay=1000) main_window.editor.close_file() @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt' or PY2 or PYQT4, reason="It fails sometimes") def test_move_to_first_breakpoint(main_window, qtbot): """Test that we move to the first breakpoint if there's one present.""" # Wait until the window is fully up shell = main_window.ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Main variables control = shell._control debug_action = main_window.debug_toolbar_actions[0] debug_button = main_window.debug_toolbar.widgetForAction(debug_action) # Clear all breakpoints main_window.editor.clear_all_breakpoints() # Load test file test_file = osp.join(LOCATION, 'script.py') main_window.editor.load(test_file) code_editor = main_window.editor.get_focus_widget() # Set breakpoint code_editor.add_remove_breakpoint(line_number=10) qtbot.wait(500) # Click the debug button qtbot.mouseClick(debug_button, Qt.LeftButton) qtbot.wait(1000) # Verify that we are at first breakpoint shell.clear_console() qtbot.wait(500) shell.kernel_client.input("list") qtbot.wait(500) assert "1--> 10 arr = np.array(li)" in control.toPlainText() # Exit debugging shell.kernel_client.input("exit") qtbot.wait(500) # Set breakpoint on first line with code code_editor.add_remove_breakpoint(line_number=2) qtbot.wait(500) # Click the debug button qtbot.mouseClick(debug_button, Qt.LeftButton) qtbot.wait(1000) # Verify that we are still on debugging assert shell._reading # Remove breakpoint and close test file main_window.editor.clear_all_breakpoints() main_window.editor.close_file() @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.environ.get('CI', None) is None, reason="It's not meant to be run locally") def test_runconfig_workdir(main_window, qtbot, tmpdir): """Test runconfig workdir options.""" CONF.set('run', 'configurations', []) # ---- Load test file ---- test_file = osp.join(LOCATION, 'script.py') main_window.editor.load(test_file) code_editor = main_window.editor.get_focus_widget() # --- Use cwd for this file --- rc = RunConfiguration().get() rc['file_dir'] = False rc['cw_dir'] = True config_entry = (test_file, rc) CONF.set('run', 'configurations', [config_entry]) # --- Run test file --- shell = main_window.ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) qtbot.keyClick(code_editor, Qt.Key_F5) qtbot.wait(500) # --- Assert we're in cwd after execution --- with qtbot.waitSignal(shell.executed): shell.execute('import os; current_dir = os.getcwd()') assert shell.get_value('current_dir') == get_home_dir() # --- Use fixed execution dir for test file --- temp_dir = str(tmpdir.mkdir("test_dir")) rc['file_dir'] = False rc['cw_dir'] = False rc['fixed_dir'] = True rc['dir'] = temp_dir config_entry = (test_file, rc) CONF.set('run', 'configurations', [config_entry]) # --- Run test file --- shell = main_window.ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) qtbot.keyClick(code_editor, Qt.Key_F5) qtbot.wait(500) # --- Assert we're in fixed dir after execution --- with qtbot.waitSignal(shell.executed): shell.execute('import os; current_dir = os.getcwd()') assert shell.get_value('current_dir') == temp_dir # ---- Closing test file and resetting config ---- main_window.editor.close_file() CONF.set('run', 'configurations', []) @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt' and PY2, reason="It's failing there") def test_dedicated_consoles(main_window, qtbot): """Test running code in dedicated consoles.""" # ---- Load test file ---- test_file = osp.join(LOCATION, 'script.py') main_window.editor.load(test_file) code_editor = main_window.editor.get_focus_widget() # --- Set run options for this file --- rc = RunConfiguration().get() # A dedicated console is used when these two options are False rc['current'] = rc['systerm'] = False config_entry = (test_file, rc) CONF.set('run', 'configurations', [config_entry]) # --- Run test file and assert that we get a dedicated console --- qtbot.keyClick(code_editor, Qt.Key_F5) qtbot.wait(500) shell = main_window.ipyconsole.get_current_shellwidget() control = shell._control qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) nsb = main_window.variableexplorer.get_focus_widget() assert len(main_window.ipyconsole.get_clients()) == 2 assert main_window.ipyconsole.filenames == ['', test_file] assert main_window.ipyconsole.tabwidget.tabText(1) == 'script.py/A' qtbot.wait(500) assert nsb.editor.model.rowCount() == 3 # --- Assert only runfile text is present and there's no banner text --- # See PR #5301 text = control.toPlainText() assert ('runfile' in text) and not ('Python' in text or 'IPython' in text) # --- Clean namespace after re-execution --- with qtbot.waitSignal(shell.executed): shell.execute('zz = -1') qtbot.keyClick(code_editor, Qt.Key_F5) qtbot.wait(500) assert not shell.is_defined('zz') # --- Assert runfile text is present after reruns --- assert 'runfile' in control.toPlainText() # ---- Closing test file and resetting config ---- main_window.editor.close_file() CONF.set('run', 'configurations', []) @pytest.mark.slow @flaky(max_runs=3) def test_connection_to_external_kernel(main_window, qtbot): """Test that only Spyder kernels are connected to the Variable Explorer.""" # Test with a generic kernel km, kc = start_new_kernel() main_window.ipyconsole._create_client_for_kernel(kc.connection_file, None, None, None) shell = main_window.ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) with qtbot.waitSignal(shell.executed): shell.execute('a = 10') # Assert that there are no variables in the variable explorer main_window.variableexplorer.visibility_changed(True) nsb = main_window.variableexplorer.get_focus_widget() qtbot.wait(500) assert nsb.editor.model.rowCount() == 0 # Test with a kernel from Spyder spykm, spykc = start_new_kernel(spykernel=True) main_window.ipyconsole._create_client_for_kernel(spykc.connection_file, None, None, None) shell = main_window.ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) with qtbot.waitSignal(shell.executed): shell.execute('a = 10') # Assert that a variable is visible in the variable explorer main_window.variableexplorer.visibility_changed(True) nsb = main_window.variableexplorer.get_focus_widget() qtbot.wait(500) assert nsb.editor.model.rowCount() == 1 # Shutdown the kernels spykm.shutdown_kernel(now=True) km.shutdown_kernel(now=True) @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt', reason="It times out sometimes on Windows") def test_np_threshold(main_window, qtbot): """Test that setting Numpy threshold doesn't make the Variable Explorer slow.""" # Set Numpy threshold shell = main_window.ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) with qtbot.waitSignal(shell.executed): shell.execute('import numpy as np; np.set_printoptions(threshold=np.nan)') # Create a big Numpy array with qtbot.waitSignal(shell.executed): shell.execute('x = np.random.rand(75000,5)') # Wait a very small time to see the array in the Variable Explorer main_window.variableexplorer.visibility_changed(True) nsb = main_window.variableexplorer.get_focus_widget() qtbot.waitUntil(lambda: nsb.editor.model.rowCount() == 1, timeout=500) # Assert that NumPy threshold remains the same as the one # set by the user with qtbot.waitSignal(shell.executed): shell.execute("t = np.get_printoptions()['threshold']") assert np.isnan(shell.get_value('t')) @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt', reason="It times out sometimes on Windows") def test_change_types_in_varexp(main_window, qtbot): """Test that variable types can't be changed in the Variable Explorer.""" # Create object shell = main_window.ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) with qtbot.waitSignal(shell.executed): shell.execute('a = 10') # Edit object main_window.variableexplorer.visibility_changed(True) nsb = main_window.variableexplorer.get_focus_widget() qtbot.waitUntil(lambda: nsb.editor.model.rowCount() > 0, timeout=EVAL_TIMEOUT) nsb.editor.setFocus() nsb.editor.edit_item() # Try to change types qtbot.keyClicks(QApplication.focusWidget(), "'s'") qtbot.keyClick(QApplication.focusWidget(), Qt.Key_Enter) qtbot.wait(1000) # Assert object remains the same assert shell.get_value('a') == 10 @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.parametrize("test_directory", [u"non_ascii_ñ_í_ç", u"test_dir"]) def test_change_cwd_ipython_console(main_window, qtbot, tmpdir, test_directory): """ Test synchronization with working directory and File Explorer when changing cwd in the IPython console. """ wdir = main_window.workingdirectory treewidget = main_window.explorer.treewidget shell = main_window.ipyconsole.get_current_shellwidget() # Wait until the window is fully up qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Create temp dir temp_dir = to_text_string(tmpdir.mkdir(test_directory)) # Change directory in IPython console using %cd with qtbot.waitSignal(shell.executed): shell.execute(u"%cd {}".format(temp_dir)) qtbot.wait(1000) # Assert that cwd changed in workingdirectory assert osp.normpath(wdir.history[-1]) == osp.normpath(temp_dir) # Assert that cwd changed in explorer assert osp.normpath(treewidget.get_current_folder()) == osp.normpath(temp_dir) @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.parametrize("test_directory", [u"non_ascii_ñ_í_ç", u"test_dir"]) def test_change_cwd_explorer(main_window, qtbot, tmpdir, test_directory): """ Test synchronization with working directory and IPython console when changing directories in the File Explorer. """ wdir = main_window.workingdirectory explorer = main_window.explorer shell = main_window.ipyconsole.get_current_shellwidget() # Wait until the window is fully up qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Create temp directory temp_dir = to_text_string(tmpdir.mkdir(test_directory)) # Change directory in the explorer widget explorer.chdir(temp_dir) qtbot.wait(1000) # Assert that cwd changed in workingdirectory assert osp.normpath(wdir.history[-1]) == osp.normpath(temp_dir) # Assert that cwd changed in IPython console assert osp.normpath(temp_dir) == osp.normpath(shell._cwd) @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt' or not is_module_installed('Cython'), reason="It times out sometimes on Windows and Cython is needed") def test_run_cython_code(main_window, qtbot): """Test all the different ways we have to run Cython code""" # ---- Setup ---- # Wait until the window is fully up shell = main_window.ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Get a reference to the namespace browser widget nsb = main_window.variableexplorer.get_focus_widget() # Get a reference to the code editor widget code_editor = main_window.editor.get_focus_widget() # ---- Run pyx file ---- # Load test file main_window.editor.load(osp.join(LOCATION, 'pyx_script.pyx')) # run file qtbot.keyClick(code_editor, Qt.Key_F5) qtbot.waitUntil(lambda: nsb.editor.model.rowCount() == 1, timeout=COMPILE_AND_EVAL_TIMEOUT) # Verify result assert shell.get_value('a') == 3628800 # Reset and close file reset_run_code(qtbot, shell, code_editor, nsb) main_window.editor.close_file() # ---- Import pyx file ---- # Load test file main_window.editor.load(osp.join(LOCATION, 'pyx_lib_import.py')) # Run file qtbot.keyClick(code_editor, Qt.Key_F5) # Wait until all objects have appeared in the variable explorer qtbot.waitUntil(lambda: nsb.editor.model.rowCount() == 1, timeout=COMPILE_AND_EVAL_TIMEOUT) # Verify result assert shell.get_value('b') == 3628800 # Close file main_window.editor.close_file() @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt', reason="It fails on Windows.") def test_open_notebooks_from_project_explorer(main_window, qtbot): """Test that notebooks are open from the Project explorer.""" projects = main_window.projects editorstack = main_window.editor.get_current_editorstack() # Create a temp project directory project_dir = tempfile.mkdtemp() # Create an empty notebook in the project dir nb = osp.join(LOCATION, 'notebook.ipynb') shutil.copy(nb, osp.join(project_dir, 'notebook.ipynb')) # Create project with qtbot.waitSignal(projects.sig_project_loaded): projects._create_project(project_dir) # Select notebook in the project explorer idx = projects.treewidget.get_index('notebook.ipynb') projects.treewidget.setCurrentIndex(idx) # Prese Enter there qtbot.keyClick(projects.treewidget, Qt.Key_Enter) # Assert that notebook was open assert 'notebook.ipynb' in editorstack.get_current_filename() # Convert notebook to a Python file projects.treewidget.convert_notebook(osp.join(project_dir, 'notebook.ipynb')) # Assert notebook was open assert 'untitled0.py' in editorstack.get_current_filename() # Assert its contents are the expected ones file_text = editorstack.get_current_editor().toPlainText() assert file_text == '\n# coding: utf-8\n\n# In[1]:\n\n\n1 + 1\n\n\n' # Close project projects.close_project() @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt', reason="It times out sometimes on Windows") def test_set_new_breakpoints(main_window, qtbot): """Test that new breakpoints are set in the IPython console.""" # Wait until the window is fully up shell = main_window.ipyconsole.get_current_shellwidget() control = shell._control qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Clear all breakpoints main_window.editor.clear_all_breakpoints() # Load test file test_file = osp.join(LOCATION, 'script.py') main_window.editor.load(test_file) # Click the debug button debug_action = main_window.debug_toolbar_actions[0] debug_button = main_window.debug_toolbar.widgetForAction(debug_action) qtbot.mouseClick(debug_button, Qt.LeftButton) qtbot.wait(1000) # Set a breakpoint code_editor = main_window.editor.get_focus_widget() code_editor.add_remove_breakpoint(line_number=6) qtbot.wait(500) # Verify that the breakpoint was set shell.kernel_client.input("b") qtbot.wait(500) assert "1 breakpoint keep yes at {}:6".format(test_file) in control.toPlainText() # Remove breakpoint and close test file main_window.editor.clear_all_breakpoints() main_window.editor.close_file() @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt', reason="It times out sometimes on Windows") def test_run_code(main_window, qtbot): """Test all the different ways we have to run code""" # ---- Setup ---- # Wait until the window is fully up shell = main_window.ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Load test file main_window.editor.load(osp.join(LOCATION, 'script.py')) # Move to the editor's first line code_editor = main_window.editor.get_focus_widget() code_editor.setFocus() qtbot.keyClick(code_editor, Qt.Key_Home, modifier=Qt.ControlModifier) # Get a reference to the namespace browser widget nsb = main_window.variableexplorer.get_focus_widget() # ---- Run file ---- qtbot.keyClick(code_editor, Qt.Key_F5) # Wait until all objects have appeared in the variable explorer qtbot.waitUntil(lambda: nsb.editor.model.rowCount() == 3, timeout=EVAL_TIMEOUT) # Verify result assert shell.get_value('a') == 10 assert shell.get_value('li') == [1, 2, 3] assert_array_equal(shell.get_value('arr'), np.array([1, 2, 3])) reset_run_code(qtbot, shell, code_editor, nsb) # ---- Run lines ---- # Run the whole file line by line for _ in range(code_editor.blockCount()): qtbot.keyClick(code_editor, Qt.Key_F9) qtbot.wait(100) # Wait until all objects have appeared in the variable explorer qtbot.waitUntil(lambda: nsb.editor.model.rowCount() == 3, timeout=EVAL_TIMEOUT) # Verify result assert shell.get_value('a') == 10 assert shell.get_value('li') == [1, 2, 3] assert_array_equal(shell.get_value('arr'), np.array([1, 2, 3])) reset_run_code(qtbot, shell, code_editor, nsb) # ---- Run cell and advance ---- # Run the three cells present in file for _ in range(3): qtbot.keyClick(code_editor, Qt.Key_Return, modifier=Qt.ShiftModifier) qtbot.wait(100) # Wait until all objects have appeared in the variable explorer qtbot.waitUntil(lambda: nsb.editor.model.rowCount() == 3, timeout=EVAL_TIMEOUT) # Verify result assert shell.get_value('a') == 10 assert shell.get_value('li') == [1, 2, 3] assert_array_equal(shell.get_value('arr'), np.array([1, 2, 3])) reset_run_code(qtbot, shell, code_editor, nsb) # ---- Run cell ---- # Run the first cell in file qtbot.keyClick(code_editor, Qt.Key_Return, modifier=Qt.ControlModifier) # Wait until the object has appeared in the variable explorer qtbot.waitUntil(lambda: nsb.editor.model.rowCount() == 1, timeout=EVAL_TIMEOUT) # Verify result assert shell.get_value('a') == 10 # Press Ctrl+Enter a second time to verify that we're *not* advancing # to the next cell qtbot.keyClick(code_editor, Qt.Key_Return, modifier=Qt.ControlModifier) assert nsb.editor.model.rowCount() == 1 reset_run_code(qtbot, shell, code_editor, nsb) # ---- Re-run last cell ---- # Run the first two cells in file qtbot.keyClick(code_editor, Qt.Key_Return, modifier=Qt.ShiftModifier) qtbot.keyClick(code_editor, Qt.Key_Return, modifier=Qt.ShiftModifier) # Wait until objects have appeared in the variable explorer qtbot.waitUntil(lambda: nsb.editor.model.rowCount() == 2, timeout=EVAL_TIMEOUT) # Clean namespace with qtbot.waitSignal(shell.executed): shell.execute('%reset -f') # Wait until there are no objects in the variable explorer qtbot.waitUntil(lambda: nsb.editor.model.rowCount() == 0, timeout=EVAL_TIMEOUT) # Re-run last cell qtbot.keyClick(code_editor, Qt.Key_Return, modifier=Qt.AltModifier) # Wait until the object has appeared in the variable explorer qtbot.waitUntil(lambda: nsb.editor.model.rowCount() == 1, timeout=EVAL_TIMEOUT) assert shell.get_value('li') == [1, 2, 3] # ---- Closing test file ---- main_window.editor.close_file() @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt' or os.environ.get('CI', None) is None or PYQT5, reason="It times out sometimes on Windows, it's not " "meant to be run outside of a CI and it segfaults " "too frequently in PyQt5") def test_open_files_in_new_editor_window(main_window, qtbot): """ This tests that opening files in a new editor window is working as expected. Test for issue 4085 """ # Set a timer to manipulate the open dialog while it's running QTimer.singleShot(2000, lambda: open_file_in_editor(main_window, 'script.py', directory=LOCATION)) # Create a new editor window # Note: editor.load() uses the current editorstack by default main_window.editor.create_new_window() main_window.editor.load() # Perform the test # Note: There's always one file open in the Editor editorstack = main_window.editor.get_current_editorstack() assert editorstack.get_stack_count() == 2 @pytest.mark.slow @flaky(max_runs=3) def test_close_when_file_is_changed(main_window, qtbot): """Test closing spyder when there is a file with modifications open.""" # Wait until the window is fully up shell = main_window.ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Load test file test_file = osp.join(LOCATION, 'script.py') main_window.editor.load(test_file) editorstack = main_window.editor.get_current_editorstack() editor = editorstack.get_current_editor() editor.document().setModified(True) # Wait for the segfault qtbot.wait(3000) @pytest.mark.slow @flaky(max_runs=3) def test_maximize_minimize_plugins(main_window, qtbot): """Test that the maximize button is working correctly.""" # Set focus to the Editor main_window.editor.get_focus_widget().setFocus() # Click the maximize button max_action = main_window.maximize_action max_button = main_window.main_toolbar.widgetForAction(max_action) qtbot.mouseClick(max_button, Qt.LeftButton) # Verify that the Editor is maximized assert main_window.editor.ismaximized # Verify that the action minimizes the plugin too qtbot.mouseClick(max_button, Qt.LeftButton) assert not main_window.editor.ismaximized @flaky(max_runs=3) @pytest.mark.skipif((os.name == 'nt' or os.environ.get('CI', None) is not None and PYQT_VERSION >= '5.9'), reason="It times out on Windows and segfaults in our CIs with PyQt >= 5.9") def test_issue_4066(main_window, qtbot): """ Test for a segfault when these steps are followed: 1. Open an object present in the Variable Explorer (e.g. a list). 2. Delete that object in its corresponding console while its editor is still opem. 3. Closing that editor by pressing its *Ok* button. """ # Create the object shell = main_window.ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) with qtbot.waitSignal(shell.executed): shell.execute('myobj = [1, 2, 3]') # Open editor associated with that object and get a reference to it nsb = main_window.variableexplorer.get_focus_widget() qtbot.waitUntil(lambda: nsb.editor.model.rowCount() > 0, timeout=EVAL_TIMEOUT) nsb.editor.setFocus() nsb.editor.edit_item() obj_editor_id = list(nsb.editor.delegate._editors.keys())[0] obj_editor = nsb.editor.delegate._editors[obj_editor_id]['editor'] # Move to the IPython console and delete that object main_window.ipyconsole.get_focus_widget().setFocus() with qtbot.waitSignal(shell.executed): shell.execute('del myobj') qtbot.waitUntil(lambda: nsb.editor.model.rowCount() == 0, timeout=EVAL_TIMEOUT) # Close editor ok_widget = obj_editor.bbox.button(obj_editor.bbox.Ok) qtbot.mouseClick(ok_widget, Qt.LeftButton) # Wait for the segfault qtbot.wait(3000) @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt', reason="It times out sometimes on Windows") def test_varexp_edit_inline(main_window, qtbot): """ Test for errors when editing inline values in the Variable Explorer and then moving to another plugin. Note: Errors for this test don't appear related to it but instead they are shown down the road. That's because they are generated by an async C++ RuntimeError. """ # Create object shell = main_window.ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) with qtbot.waitSignal(shell.executed): shell.execute('a = 10') # Edit object main_window.variableexplorer.visibility_changed(True) nsb = main_window.variableexplorer.get_focus_widget() qtbot.waitUntil(lambda: nsb.editor.model.rowCount() > 0, timeout=EVAL_TIMEOUT) nsb.editor.setFocus() nsb.editor.edit_item() # Change focus to IPython console main_window.ipyconsole.get_focus_widget().setFocus() # Wait for the error qtbot.wait(3000) @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt', reason="It times out sometimes on Windows") def test_c_and_n_pdb_commands(main_window, qtbot): """Test that c and n Pdb commands update the Variable Explorer.""" nsb = main_window.variableexplorer.get_focus_widget() # Wait until the window is fully up shell = main_window.ipyconsole.get_current_shellwidget() control = shell._control qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Clear all breakpoints main_window.editor.clear_all_breakpoints() # Load test file test_file = osp.join(LOCATION, 'script.py') main_window.editor.load(test_file) # Click the debug button debug_action = main_window.debug_toolbar_actions[0] debug_button = main_window.debug_toolbar.widgetForAction(debug_action) qtbot.mouseClick(debug_button, Qt.LeftButton) qtbot.wait(1000) # Set a breakpoint code_editor = main_window.editor.get_focus_widget() code_editor.add_remove_breakpoint(line_number=6) qtbot.wait(500) # Verify that c works qtbot.keyClicks(control, 'c') qtbot.keyClick(control, Qt.Key_Enter) qtbot.wait(500) assert nsb.editor.model.rowCount() == 1 # Verify that n works qtbot.keyClicks(control, 'n') qtbot.keyClick(control, Qt.Key_Enter) qtbot.wait(500) assert nsb.editor.model.rowCount() == 2 # Verify that doesn't go to sitecustomize.py with next and stops # the debugging session. qtbot.keyClicks(control, 'n') qtbot.keyClick(control, Qt.Key_Enter) qtbot.wait(500) qtbot.keyClicks(control, 'n') qtbot.keyClick(control, Qt.Key_Enter) qtbot.wait(500) assert nsb.editor.model.rowCount() == 3 qtbot.keyClicks(control, 'n') qtbot.keyClick(control, Qt.Key_Enter) qtbot.wait(500) # Assert that the prompt appear shell.clear_console() assert 'In [2]:' in control.toPlainText() # Remove breakpoint and close test file main_window.editor.clear_all_breakpoints() main_window.editor.close_file() @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt', reason="It times out sometimes on Windows") def test_stop_dbg(main_window, qtbot): """Test that we correctly stop a debugging session.""" nsb = main_window.variableexplorer.get_focus_widget() # Wait until the window is fully up shell = main_window.ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Clear all breakpoints main_window.editor.clear_all_breakpoints() # Load test file test_file = osp.join(LOCATION, 'script.py') main_window.editor.load(test_file) # Click the debug button debug_action = main_window.debug_toolbar_actions[0] debug_button = main_window.debug_toolbar.widgetForAction(debug_action) qtbot.mouseClick(debug_button, Qt.LeftButton) qtbot.wait(1000) # Move to the next line shell.kernel_client.input("n") qtbot.wait(1000) # Stop debugging stop_debug_action = main_window.debug_toolbar_actions[5] stop_debug_button = main_window.debug_toolbar.widgetForAction(stop_debug_action) qtbot.mouseClick(stop_debug_button, Qt.LeftButton) qtbot.wait(1000) # Assert that there is only one entry in the Variable Explorer assert nsb.editor.model.rowCount() == 1 # Remove breakpoint and close test file main_window.editor.clear_all_breakpoints() main_window.editor.close_file() @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt', reason="It times out sometimes on Windows") def test_change_cwd_dbg(main_window, qtbot): """ Test that using the Working directory toolbar is working while debugging. """ # Wait until the window is fully up shell = main_window.ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Give focus to the widget that's going to receive clicks control = main_window.ipyconsole.get_focus_widget() control.setFocus() # Import os to get cwd with qtbot.waitSignal(shell.executed): shell.execute('import os') # Click the debug button debug_action = main_window.debug_toolbar_actions[0] debug_button = main_window.debug_toolbar.widgetForAction(debug_action) qtbot.mouseClick(debug_button, Qt.LeftButton) qtbot.wait(1000) # Set LOCATION as cwd main_window.workingdirectory.chdir(tempfile.gettempdir(), browsing_history=False, refresh_explorer=True) qtbot.wait(1000) # Get cwd in console qtbot.keyClicks(control, 'os.getcwd()') qtbot.keyClick(control, Qt.Key_Enter) qtbot.wait(1000) # Assert cwd is the right one assert tempfile.gettempdir() in control.toPlainText() @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt' or PY2, reason="It times out sometimes") def test_varexp_magic_dbg(main_window, qtbot): """Test that %varexp is working while debugging.""" nsb = main_window.variableexplorer.get_focus_widget() # Wait until the window is fully up shell = main_window.ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Give focus to the widget that's going to receive clicks control = main_window.ipyconsole.get_focus_widget() control.setFocus() # Create an object that can be plotted with qtbot.waitSignal(shell.executed): shell.execute('li = [1, 2, 3]') # Click the debug button debug_action = main_window.debug_toolbar_actions[0] debug_button = main_window.debug_toolbar.widgetForAction(debug_action) qtbot.mouseClick(debug_button, Qt.LeftButton) qtbot.wait(1000) # Generate the plot from the Variable Explorer nsb.plot('li', 'plot') qtbot.wait(1000) # Assert that there's a plot in the console assert shell._control.toHtml().count('img src') == 1 @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(os.environ.get('CI', None) is None, reason="It's not meant to be run outside of a CI") def test_fileswitcher(main_window, qtbot): """Test the use of shorten paths when necessary in the fileswitcher.""" # Load tests files dir_b = osp.join(TEMP_DIRECTORY, 'temp_dir_a', 'temp_b') filename_b = osp.join(dir_b, 'c.py') if not osp.isdir(dir_b): os.makedirs(dir_b) if not osp.isfile(filename_b): file_c = open(filename_b, 'w+') file_c.close() if PYQT5: dir_d = osp.join(TEMP_DIRECTORY, 'temp_dir_a', 'temp_c', 'temp_d', 'temp_e') else: dir_d = osp.join(TEMP_DIRECTORY, 'temp_dir_a', 'temp_c', 'temp_d') dir_e = osp.join(TEMP_DIRECTORY, 'temp_dir_a', 'temp_c', 'temp_dir_f', 'temp_e') filename_e = osp.join(dir_e, 'a.py') if not osp.isdir(dir_e): os.makedirs(dir_e) if not osp.isfile(filename_e): file_e = open(filename_e, 'w+') file_e.close() filename_d = osp.join(dir_d, 'c.py') if not osp.isdir(dir_d): os.makedirs(dir_d) if not osp.isfile(filename_d): file_d = open(filename_d, 'w+') file_d.close() main_window.editor.load(filename_b) main_window.editor.load(filename_d) # Assert that all the path of the file is shown main_window.open_fileswitcher() if os.name == 'nt': item_text = main_window.fileswitcher.list.currentItem().text().replace('\\', '/').lower() dir_d = dir_d.replace('\\', '/').lower() else: item_text = main_window.fileswitcher.list.currentItem().text() assert dir_d in item_text # Resize Main Window to a third of its width size = main_window.window_size main_window.resize(size.width() / 3, size.height()) main_window.open_fileswitcher() # Assert that the path shown in the fileswitcher is shorter if PYQT5: main_window.open_fileswitcher() item_text = main_window.fileswitcher.list.currentItem().text() assert '...' in item_text @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(not PYQT5, reason="It times out.") def test_run_static_code_analysis(main_window, qtbot): """This tests that the Pylint plugin is working as expected.""" # Wait until the window is fully up shell = main_window.ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) # Select the third-party plugin pylint = get_thirdparty_plugin(main_window, "Static code analysis") # Do an analysis test_file = osp.join(LOCATION, 'script_pylint.py') main_window.editor.load(test_file) code_editor = main_window.editor.get_focus_widget() qtbot.keyClick(code_editor, Qt.Key_F8) qtbot.wait(3000) # Perform the test # Check output of the analysis treewidget = pylint.get_focus_widget() qtbot.waitUntil(lambda: treewidget.results is not None, timeout=SHELL_TIMEOUT) result_content = treewidget.results assert result_content['C:'] assert len(result_content['C:']) == 5 # Close the file main_window.editor.close_file() if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/app/tests/__init__.py0000664000175000017500000000050213156676663021203 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Copyright (c) Spyder Project Contributors # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Tests.""" spyder-3.2.6/spyder/app/tests/pyx_lib_import.py0000664000175000017500000000006013211142272022453 0ustar carloscarlos00000000000000import pyx_script b = pyx_script.factorial(10) spyder-3.2.6/spyder/app/restart.py0000664000175000017500000002515613224121062017750 0ustar carloscarlos00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Restart Spyder A helper script that allows to restart (and also reset) Spyder from within the running application. """ # Standard library imports import ast import os import os.path as osp import subprocess import sys import time # Third party imports from qtpy import PYQT5 from qtpy.QtCore import Qt, QTimer from qtpy.QtGui import QColor, QPixmap, QIcon from qtpy.QtWidgets import QApplication, QMessageBox, QSplashScreen, QWidget # Local imports from spyder.config.base import _, get_image_path from spyder.py3compat import to_text_string from spyder.utils.qthelpers import qapplication from spyder.config.main import CONF PY2 = sys.version[0] == '2' IS_WINDOWS = os.name == 'nt' SLEEP_TIME = 0.2 # Seconds for throttling control CLOSE_ERROR, RESET_ERROR, RESTART_ERROR = [1, 2, 3] # Spyder error codes 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 _is_pid_running_on_unix(pid): """Check if a process is running on unix systems based on the pid.""" try: # On unix systems os.kill with a 0 as second argument only pokes the # process (if it exists) and does not kill it os.kill(pid, 0) except OSError: return False else: return True def is_pid_running(pid): """Check if a process is running based on the pid.""" # Select the correct function depending on the OS if os.name == 'nt': return _is_pid_running_on_windows(pid) else: return _is_pid_running_on_unix(pid) class Restarter(QWidget): """Widget in charge of displaying the splash information screen and the error messages. """ def __init__(self): super(Restarter, self).__init__() self.ellipsis = ['', '.', '..', '...', '..', '.'] # Widgets self.timer_ellipsis = QTimer(self) self.splash = QSplashScreen(QPixmap(get_image_path('splash.svg'), 'svg')) # Widget setup self.setVisible(False) font = self.splash.font() font.setPixelSize(10) self.splash.setFont(font) self.splash.show() self.timer_ellipsis.timeout.connect(self.animate_ellipsis) def _show_message(self, text): """Show message on splash screen.""" self.splash.showMessage(text, Qt.AlignBottom | Qt.AlignCenter | Qt.AlignAbsolute, QColor(Qt.white)) def animate_ellipsis(self): """Animate dots at the end of the splash screen message.""" ellipsis = self.ellipsis.pop(0) text = ' '*len(ellipsis) + self.splash_text + ellipsis self.ellipsis.append(ellipsis) self._show_message(text) def set_splash_message(self, text): """Sets the text in the bottom of the Splash screen.""" self.splash_text = text self._show_message(text) self.timer_ellipsis.start(500) def launch_error_message(self, error_type, error=None): """Launch a message box with a predefined error message. Parameters ---------- error_type : int [CLOSE_ERROR, RESET_ERROR, RESTART_ERROR] Possible error codes when restarting/reseting spyder. error : Exception Actual Python exception error caught. """ messages = {CLOSE_ERROR: _("It was not possible to close the previous " "Spyder instance.\nRestart aborted."), RESET_ERROR: _("Spyder could not reset to factory " "defaults.\nRestart aborted."), RESTART_ERROR: _("It was not possible to restart Spyder.\n" "Operation aborted.")} titles = {CLOSE_ERROR: _("Spyder exit error"), RESET_ERROR: _("Spyder reset error"), RESTART_ERROR: _("Spyder restart error")} if error: e = error.__repr__() message = messages[error_type] + "\n\n{0}".format(e) else: message = messages[error_type] title = titles[error_type] self.splash.hide() QMessageBox.warning(self, title, message, QMessageBox.Ok) raise RuntimeError(message) def main(): #========================================================================== # Proper high DPI scaling is available in Qt >= 5.6.0. This attibute must # be set before creating the application. #========================================================================== if CONF.get('main', 'high_dpi_custom_scale_factor'): factors = str(CONF.get('main', 'high_dpi_custom_scale_factors')) f = list(filter(None, factors.split(';'))) if len(f) == 1: os.environ['QT_SCALE_FACTOR'] = f[0] else: os.environ['QT_SCREEN_SCALE_FACTORS'] = factors else: os.environ['QT_SCALE_FACTOR'] = '' os.environ['QT_SCREEN_SCALE_FACTORS'] = '' # Splash screen # ------------------------------------------------------------------------- # Start Qt Splash to inform the user of the current status app = qapplication() restarter = Restarter() if PYQT5: APP_ICON = QIcon(get_image_path("spyder.svg")) else: APP_ICON = QIcon(get_image_path("spyder.png")) app.setWindowIcon(APP_ICON) restarter.set_splash_message(_('Closing Spyder')) # Get variables # Note: Variables defined in app/spyder.py 'restart()' method spyder_args = os.environ.pop('SPYDER_ARGS', None) pid = os.environ.pop('SPYDER_PID', None) is_bootstrap = os.environ.pop('SPYDER_IS_BOOTSTRAP', None) reset = os.environ.pop('SPYDER_RESET', None) # Get the spyder base folder based on this file this_folder = osp.split(osp.dirname(osp.abspath(__file__)))[0] spyder_folder = osp.split(this_folder)[0] if not any([spyder_args, pid, is_bootstrap, reset]): error = "This script can only be called from within a Spyder instance" raise RuntimeError(error) # Variables were stored as string literals in the environment, so to use # them we need to parse them in a safe manner. is_bootstrap = ast.literal_eval(is_bootstrap) pid = ast.literal_eval(pid) args = ast.literal_eval(spyder_args) reset = ast.literal_eval(reset) # Enforce the --new-instance flag when running spyder if '--new-instance' not in args: if is_bootstrap and '--' not in args: args = args + ['--', '--new-instance'] else: args.append('--new-instance') # Create the arguments needed for reseting if '--' in args: args_reset = ['--', '--reset'] else: args_reset = ['--reset'] # Arrange arguments to be passed to the restarter and reset subprocess args = ' '.join(args) args_reset = ' '.join(args_reset) # Get python excutable running this script python = sys.executable # Build the command if is_bootstrap: spyder = osp.join(spyder_folder, 'bootstrap.py') else: spyderdir = osp.join(spyder_folder, 'spyder') spyder = osp.join(spyderdir, 'app', 'start.py') command = '"{0}" "{1}" {2}'.format(python, spyder, args) # Adjust the command and/or arguments to subprocess depending on the OS shell = not IS_WINDOWS # Before launching a new Spyder instance we need to make sure that the # previous one has closed. We wait for a fixed and "reasonable" amount of # time and check, otherwise an error is launched wait_time = 90 if IS_WINDOWS else 30 # Seconds for counter in range(int(wait_time/SLEEP_TIME)): if not is_pid_running(pid): break time.sleep(SLEEP_TIME) # Throttling control QApplication.processEvents() # Needed to refresh the splash else: # The old spyder instance took too long to close and restart aborts restarter.launch_error_message(error_type=CLOSE_ERROR) env = os.environ.copy() # Reset Spyder (if required) # ------------------------------------------------------------------------- if reset: restarter.set_splash_message(_('Resetting Spyder to defaults')) command_reset = '"{0}" "{1}" {2}'.format(python, spyder, args_reset) try: p = subprocess.Popen(command_reset, shell=shell, env=env) except Exception as error: restarter.launch_error_message(error_type=RESET_ERROR, error=error) else: p.communicate() pid_reset = p.pid # Before launching a new Spyder instance we need to make sure that the # reset subprocess has closed. We wait for a fixed and "reasonable" # amount of time and check, otherwise an error is launched. wait_time = 20 # Seconds for counter in range(int(wait_time/SLEEP_TIME)): if not is_pid_running(pid_reset): break time.sleep(SLEEP_TIME) # Throttling control QApplication.processEvents() # Needed to refresh the splash else: # The reset subprocess took too long and it is killed try: p.kill() except OSError as error: restarter.launch_error_message(error_type=RESET_ERROR, error=error) else: restarter.launch_error_message(error_type=RESET_ERROR) # Restart # ------------------------------------------------------------------------- restarter.set_splash_message(_('Restarting')) try: subprocess.Popen(command, shell=shell, env=env) except Exception as error: restarter.launch_error_message(error_type=RESTART_ERROR, error=error) if __name__ == '__main__': main() spyder-3.2.6/spyder/app/mac_stylesheet.qss0000664000175000017500000000617713026261006021460 0ustar carloscarlos00000000000000/* * Qt Stylesheet for MacOS X * Copyright (c) Spyder Project Contributors */ /* ---------------- Dock widget and QSplitter separators --------------- */ QMainWindow::separator { width: 3px; height: 3px; border: 1px solid lightgrey; border-radius: 1px; } QMainWindow::separator:hover { background: darkgrey; } QToolButton { border: none; } QSplitter::handle:horizontal { border: 1px solid darkgrey; width: 2px; } QSplitter::handle:vertical { border: 1px solid darkgrey; height: 2px; } QSplitter::handle:pressed { background: darkgrey; } /* ----------------- Tabs ------------------ */ QWidget#tab-container { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #b1b1b1, stop: 0.07 #b3b3b3, stop: 0.33 #b3b3b3, stop: 0.4 #b0b0b0, stop: 0.47 #b3b3b3, stop: 1.0 #b2b2b2); } QTabWidget::pane#plugin-tab { border-top: 1px solid qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #b1b1b1, stop: 0.07 #b3b3b3, stop: 0.33 #b3b3b3, stop: 0.4 #b0b0b0, stop: 0.47 #b3b3b3, stop: 1.0 #b2b2b2); border-bottom: 0px; border-left: 0px; border-right: 0px; } QTabWidget::tab-bar#plugin-tab { left: 5px; } QTabBar::tab#plugin-tab { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #b1b1b1, stop: 0.07 #b3b3b3, stop: 0.33 #b3b3b3, stop: 0.4 #b0b0b0, stop: 0.47 #b3b3b3, stop: 1.0 #b2b2b2); border: 1px solid #787878; border-top-color: transparent; border-bottom-color: transparent; margin-left: -1px; margin-right: -1px; min-width: 15ex; padding: 3px; } QTabBar::tab:selected#plugin-tab { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #dfdfdf, stop: 0.1 #dddddd, stop: 0.12 #dfdfdf, stop: 0.22 #e0e0e0, stop: 0.33 #dedede, stop: 0.47 #dedede, stop: 0.49 #e0e0e0, stop: 0.59 #dddddd, stop: 0.61 #dfdfdf, stop: 0.73 #dedede, stop: 0.80 #e0e0e0, stop: 1.0 #dedede); border: 1px solid #787878; border-top: 0px; border-top-color: transparent; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; } QTabBar::tab:first#plugin-tab { margin-left: 0; } QTabBar::tab:last#plugin-tab { margin-right: 0; } QTabBar::tab:only-one#plugin-tab { margin: 0; } QTabBar::scroller#plugin-tab { width: 22px; } QTabBar#plugin-tab QToolButton::left-arrow { background: lightgrey; border-right: 1px solid darkgrey; image: url($IMAGE_PATH/chevron-left.png); } QTabBar#plugin-tab QToolButton::right-arrow { background: lightgrey; image: url($IMAGE_PATH/chevron-right.png); } /* ------------------ Dock widgets ------------------- */ QDockWidget::close-button, QDockWidget::float-button { padding: 0px; margin: 2px; } spyder-3.2.6/spyder/app/__init__.py0000664000175000017500000000037413026261006020021 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ spyder.app ========== Modules related to starting and restarting the Spyder application """ spyder-3.2.6/spyder/app/cli_options.py0000664000175000017500000000463313224740762020621 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) import optparse def get_options(): """ Convert options into commands return commands, message """ parser = optparse.OptionParser(usage="spyder [options] files") parser.add_option('--new-instance', action='store_true', default=False, help="Run a new instance of Spyder, even if the single " "instance mode has been turned on (default)") parser.add_option('--defaults', dest="reset_to_defaults", action='store_true', default=False, help="Reset configuration settings to defaults") parser.add_option('--reset', dest="reset_config_files", action='store_true', default=False, help="Remove all configuration files!") parser.add_option('--optimize', action='store_true', default=False, help="Optimize Spyder bytecode (this may require " "administrative privileges)") parser.add_option('-w', '--workdir', dest="working_directory", default=None, help="Default working directory") parser.add_option('--hide-console', action='store_true', default=False, help="Hide parent console window (Windows)") parser.add_option('--show-console', action='store_true', default=False, help="(Deprecated) Does nothing, now the default behavior " "is to show the console") parser.add_option('--multithread', dest="multithreaded", action='store_true', default=False, help="Internal console is executed in another thread " "(separate from main application thread)") parser.add_option('--profile', action='store_true', default=False, help="Profile mode (internal test, " "not related with Python profiling)") parser.add_option('--window-title', type=str, default=None, help="String to show in the main window title") parser.add_option('-p', '--project', default=None, type=str, dest="open_project", help="Path that contains an Spyder project") options, args = parser.parse_args() return options, args spyder-3.2.6/spyder/dependencies.py0000664000175000017500000000710013026261006020122 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Module checking Spyder runtime dependencies""" import os # Local imports from spyder.utils import programs class Dependency(object): """Spyder's dependency version may starts with =, >=, > or < to specify the exact requirement ; multiple conditions may be separated by ';' (e.g. '>=0.13;<1.0')""" OK = 'OK' NOK = 'NOK' def __init__(self, modname, features, required_version, installed_version=None, optional=False): self.modname = modname self.features = features self.required_version = required_version self.optional = optional if installed_version is None: try: self.installed_version = programs.get_module_version(modname) except: # NOTE: Don't add any exception type here! # Modules can fail to import in several ways besides # ImportError self.installed_version = None else: self.installed_version = installed_version def check(self): """Check if dependency is installed""" return programs.is_module_installed(self.modname, self.required_version, self.installed_version) def get_installed_version(self): """Return dependency status (string)""" if self.check(): return '%s (%s)' % (self.installed_version, self.OK) else: return '%s (%s)' % (self.installed_version, self.NOK) def get_status(self): """Return dependency status (string)""" if self.check(): return self.OK else: return self.NOK DEPENDENCIES = [] def add(modname, features, required_version, installed_version=None, optional=False): """Add Spyder dependency""" global DEPENDENCIES for dependency in DEPENDENCIES: if dependency.modname == modname: raise ValueError("Dependency has already been registered: %s"\ % modname) DEPENDENCIES += [Dependency(modname, features, required_version, installed_version, optional)] def check(modname): """Check if required dependency is installed""" for dependency in DEPENDENCIES: if dependency.modname == modname: return dependency.check() else: raise RuntimeError("Unkwown dependency %s" % modname) def status(deps=DEPENDENCIES, linesep=os.linesep): """Return a status of dependencies""" maxwidth = 0 col1 = [] col2 = [] for dependency in deps: title1 = dependency.modname title1 += ' ' + dependency.required_version col1.append(title1) maxwidth = max([maxwidth, len(title1)]) col2.append(dependency.get_installed_version()) text = "" for index in range(len(deps)): text += col1[index].ljust(maxwidth) + ': ' + col2[index] + linesep return text def missing_dependencies(): """Return the status of missing dependencies (if any)""" missing_deps = [] for dependency in DEPENDENCIES: if not dependency.check() and not dependency.optional: missing_deps.append(dependency) if missing_deps: return status(deps=missing_deps, linesep='
    ') else: return "" spyder-3.2.6/spyder/defaults/0000775000175000017500000000000013225025007016733 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/defaults/Readme.txt0000664000175000017500000000165513026261006020700 0ustar carloscarlos00000000000000Copyright (c) Spyder Project Contributors Licensed under the terms of the MIT License (see spyder/__init__.py for details) What is the purpose of this directory? ====================================== The files present here (licensed also MIT) are used to cleanly update user configuration options from Spyder versions previous to 2.3. They way they did an update was by resetting *all* config options to new defaults, which was quite bad from a usability point of view. Now we compare new defaults against a copy of their previous values and only change those that are different in the user config file. This way almost all his/her values remain intact. In particular: * defaults-2.4.0.ini is used to do the update when the previous used version is between 2.1.9 and 2.3.0beta3 * defaults-3.0.0.ini is used when the previous version is 2.3.0beta4 Notes ===== 1. Please don't add more files here, unless you know what you're doing. spyder-3.2.6/spyder/defaults/defaults-2.4.0.ini0000664000175000017500000004347113026261006021713 0ustar carloscarlos00000000000000[main] lightwindow/is_fullscreen = False memory_usage/timeout = 2000 custom_margin = 0 vertical_dockwidget_titlebars = False lightwindow/size = (650, 400) show_internal_console_if_traceback = True memory_usage/enable = True single_instance = True window/is_maximized = False cpu_usage/enable = False lightwindow/is_maximized = False animated_docks = True window/is_fullscreen = False cpu_usage/timeout = 2000 window/size = (1260, 740) open_files_port = 21128 lightwindow/prefs_dialog_size = (745, 411) window/prefs_dialog_size = (745, 411) window/position = (10, 10) lightwindow/position = (30, 30) tear_off_menus = False vertical_tabs = False use_custom_margin = True [quick_layouts] place_holder = [editor_appearance] completion/font/family = ['Monospace', 'DejaVu Sans Mono', 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono', 'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal'] calltips/font/size = 9 calltips/font/family = ['Monospace', 'DejaVu Sans Mono', 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono', 'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal'] cursor/width = 2 calltips/font/italic = False completion/font/size = 9 completion/size = (300, 180) completion/font/bold = False calltips/size = 600 calltips/font/bold = False completion/font/italic = False [shell_appearance] completion/font/family = ['Monospace', 'DejaVu Sans Mono', 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono', 'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal'] calltips/font/size = 9 calltips/font/family = ['Monospace', 'DejaVu Sans Mono', 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono', 'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal'] cursor/width = 2 calltips/font/italic = False completion/font/size = 9 completion/size = (300, 180) completion/font/bold = False calltips/size = 600 calltips/font/bold = False completion/font/italic = False [internal_console] working_dir_adjusttocontents = False external_editor/gotoline = -goto: font/italic = False calltips = True working_dir_history = 30 external_editor/path = SciTE max_line_count = 300 shortcut = None font/family = ['Monospace', 'DejaVu Sans Mono', 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono', 'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal'] codecompletion/enter_key = True font/bold = False font/size = 9 codecompletion/auto = False wrap = True codecompletion/case_sensitive = True light_background = True codecompletion/show_single = False [console] pythonexecutable/default = True colorize_sys_stderr = True umd/enabled = True show_icontext = False calltips = True matplotlib/backend/value = Qt4Agg single_tab = True qt/install_inputhook = True max_line_count = 10000 pythonstartup/default = False font/family = ['Monospace', 'DejaVu Sans Mono', 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono', 'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal'] pyqt/ignore_sip_setapi_errors = False qt/api = default pythonexecutable/custom = False font/size = 9 codecompletion/auto = True wrap = True umd/verbose = True matplotlib/patch = True codecompletion/show_single = False matplotlib/backend/enabled = True monitor/enabled = True pythonstartup/custom = True light_background = True font/italic = False codecompletion/enter_key = True ets_backend = qt4 merge_output_channels = True show_elapsed_time = True pyqt/api_version = 0 shortcut = Ctrl+Shift+C open_python_at_startup = True font/bold = False umd/namelist = ['guidata', 'guiqwt'] codecompletion/case_sensitive = True object_inspector = True [ipython_console] show_calltips = False pylab = True symbolic_math = False pylab/inline/height = 4 open_ipython_at_startup = False out_prompt = autocall = 0 in_prompt = shortcut = None font/bold = False startup/run_lines = startup/run_file = pylab/inline/figure_format = 0 greedy_completer = False pylab/inline/resolution = 72 font/family = ['Monospace', 'DejaVu Sans Mono', 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono', 'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal'] dark_color = False ask_before_closing = True pylab/backend = 0 font/size = 9 light_color = True buffer_size = 10000 show_banner = True font/italic = False pylab/inline/width = 6 use_gui_completion = True use_pager = True startup/use_run_file = False object_inspector = True pylab/autoload = True [variable_explorer] collvalue = False truncate = True exclude_unsupported = True minmax = False exclude_uppercase = True check_all = False exclude_private = True autorefresh = True inplace = False shortcut = Ctrl+Shift+V excluded_names = ['nan', 'inf', 'infty', 'little_endian', 'colorbar_doc', 'typecodes', '__builtins__', '__main__', '__doc__', 'NaN', 'Inf', 'Infinity', 'sctypes', 'rcParams', 'rcParamsDefault', 'sctypeNA', 'typeNA', 'False_', 'True_'] autorefresh/timeout = 2000 exclude_capitalized = False remote_editing = False [editor] wrapflag = True edge_line = True add_colons = True always_remove_trailing_spaces = False auto_unindent = True max_recent_files = 20 onsave_analysis = False wrap = False indent_chars = * * outline_explorer = True show_tab_bar = True shortcut = Ctrl+Shift+E font/family = ['Monospace', 'DejaVu Sans Mono', 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono', 'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal'] codecompletion/auto = True fullpath_sorting = True font/italic = False check_eol_chars = True intelligent_backspace = True realtime_analysis/timeout = 2500 todo_list = True close_quotes = False occurence_highlighting = True object_inspector = True go_to_definition = True tab_stop_width = 40 tab_always_indent = False printer_header/font/bold = False codecompletion/show_single = False printer_header/font/italic = False realtime_analysis = True font/bold = False printer_header/font/family = ['Sans Serif', 'DejaVu Sans', 'Bitstream Vera Sans', 'Bitstream Charter', 'Lucida Grande', 'MS Shell Dlg 2', 'Calibri', 'Verdana', 'Geneva', 'Lucid', 'Arial', 'Helvetica', 'Avant Garde', 'Times', 'sans-serif'] toolbox_panel = True calltips = True highlight_current_line = True font/size = 9 edge_line_column = 79 close_parentheses = True save_all_before_run = True code_analysis/pyflakes = True line_numbers = True codecompletion/enter_key = True code_analysis/pep8 = False printer_header/font/size = 9 codecompletion/case_sensitive = True occurence_highlighting/timeout = 1500 [historylog] max_entries = 100 go_to_eof = True font/bold = False enable = True font/size = 9 font/italic = False wrap = True font/family = ['Monospace', 'DejaVu Sans Mono', 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono', 'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal'] shortcut = Ctrl+Shift+H [inspector] max_history_entries = 20 enable = True font/italic = False rich_text/font/italic = False font/family = ['Monospace', 'DejaVu Sans Mono', 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono', 'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal'] shortcut = Ctrl+Shift+I automatic_import = True connect/ipython_console = False font/bold = False rich_text/font/size = 12 font/size = 9 connect/python_console = False wrap = True connect/editor = False rich_text/font/family = ['Sans Serif', 'DejaVu Sans', 'Bitstream Vera Sans', 'Bitstream Charter', 'Lucida Grande', 'MS Shell Dlg 2', 'Calibri', 'Verdana', 'Geneva', 'Lucid', 'Arial', 'Helvetica', 'Avant Garde', 'Times', 'sans-serif'] rich_text/font/bold = False math = True [onlinehelp] max_history_entries = 20 enable = True zoom_factor = 0.8 shortcut = Ctrl+Shift+D [outline_explorer] show_comments = True show_fullpath = False enable = True shortcut = Ctrl+Shift+O show_all_files = False [project_explorer] show_all = False name_filters = ['*.py', '*.pyw', '*.ipy', '*.pyx', '*.pxd', '*.pxi', '*.c', '*.h', '*.cc', '*.cpp', '*.cxx', '*.h', '*.hh', '*.hpp', '*.hxx', '*.cl', '*.f', '*.for', '*.f77', '*.f90', '*.f95', '*.f2k', '*.pro', '*.m', '*.patch', '*.diff', '*.rej', '*.bat', '*.cmd', '*.txt', '*.txt', '*.rst', '*.po', '*.pot', '*.nsi', '*.nsh', '*.css', '*.htm', '*.html', '*.xml', '*.js', '*.enaml', '*.properties', '*.session', '*.ini', '*.inf', '*.reg', '*.cfg', '*.desktop', '*.txt', '*.png', '*.mat', '*.spydata', '*.tif', '*.jpg', '*.npy', '*.gif', '*.csv', '*.png', '*.ico', '*.svg', 'README', 'INSTALL', 'LICENSE', 'CHANGELOG'] enable = True shortcut = Ctrl+Shift+P show_hscrollbar = True [arrayeditor] font/bold = False font/size = 9 font/family = ['Monospace', 'DejaVu Sans Mono', 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono', 'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal'] font/italic = False [texteditor] font/bold = False font/size = 9 font/family = ['Monospace', 'DejaVu Sans Mono', 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono', 'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal'] font/italic = False [dicteditor] font/bold = False font/size = 9 font/family = ['Monospace', 'DejaVu Sans Mono', 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono', 'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal'] font/italic = False [explorer] enable = True show_hidden = True show_icontext = False wrap = True name_filters = ['*.py', '*.pyw', '*.ipy', '*.pyx', '*.pxd', '*.pxi', '*.c', '*.h', '*.cc', '*.cpp', '*.cxx', '*.h', '*.hh', '*.hpp', '*.hxx', '*.cl', '*.f', '*.for', '*.f77', '*.f90', '*.f95', '*.f2k', '*.pro', '*.m', '*.patch', '*.diff', '*.rej', '*.bat', '*.cmd', '*.txt', '*.txt', '*.rst', '*.po', '*.pot', '*.nsi', '*.nsh', '*.css', '*.htm', '*.html', '*.xml', '*.js', '*.enaml', '*.properties', '*.session', '*.ini', '*.inf', '*.reg', '*.cfg', '*.desktop', '*.txt', '*.png', '*.mat', '*.spydata', '*.tif', '*.jpg', '*.npy', '*.gif', '*.csv', '*.png', '*.ico', '*.svg', 'README', 'INSTALL', 'LICENSE', 'CHANGELOG'] show_all = False shortcut = None show_toolbar = True [find_in_files] enable = True exclude_regexp = True in_python_path = False exclude = ['\\.pyc$|\\.pyo$|\\.orig$|\\.hg|\\.svn|\\bbuild\\b', '\\.pyc$|\\.pyo$|\\.orig$|\\.hg|\\.svn'] search_text_regexp = True more_options = True search_text = [''] supported_encodings = ['utf-8', 'iso-8859-1', 'cp1252'] search_text_samples = ['(^|#)[ ]*(TODO|FIXME|XXX|HINT|TIP)([^#]*)'] shortcut = None include_regexp = True include = ['\\.py$|\\.pyw$|\\.ipy$|\\.pyx$|\\.pxd$|\\.pxi$|\\.c$|\\.h$|\\.cc$|\\.cpp$|\\.cxx$|\\.h$|\\.hh$|\\.hpp$|\\.hxx$|\\.cl$|\\.f$|\\.for$|\\.f77$|\\.f90$|\\.f95$|\\.f2k$|\\.pro$|\\.m$|\\.patch$|\\.diff$|\\.rej$|\\.bat$|\\.cmd$|\\.txt$|\\.txt$|\\.rst$|\\.po$|\\.pot$|\\.nsi$|\\.nsh$|\\.css$|\\.htm$|\\.html$|\\.xml$|\\.js$|\\.enaml$|\\.properties$|\\.session$|\\.ini$|\\.inf$|\\.reg$|\\.cfg$|\\.desktop$|README|INSTALL', '\\.pyw?$|\\.ipy$|\\.txt$|\\.rst$', '.'] [workingdir] working_dir_adjusttocontents = False editor/new/browse_scriptdir = False editor/open/auto_set_to_basedir = False working_dir_history = 20 editor/open/browse_scriptdir = True editor/new/browse_workdir = True editor/open/browse_workdir = False startup/use_last_directory = True editor/save/auto_set_to_basedir = False [shortcuts] editor/duplicate line = Shift+Alt+Up editor/go to next file = Ctrl+Shift+Tab console/clear line = Shift+Escape _/switch to outline_explorer = Ctrl+Shift+O editor/show/hide outline = Ctrl+Alt+O _/fullscreen mode = F11 _/maximize plugin = Ctrl+Alt+Shift+M _/maximize dockwidget = Ctrl+Alt+Shift+M _/close plugin = Shift+Ctrl+F4 _/close dockwidget = Shift+Ctrl+F4 _/switch to inspector = Ctrl+Shift+I profiler/run profiler = F10 editor/move line down = Alt+Down console/clear shell = Ctrl+L pylint/run analysis = F8 _/switch to onlinehelp = Ctrl+Shift+D _/switch to editor = Ctrl+Shift+E editor/code completion = Ctrl+Space _/switch to variable_explorer = Ctrl+Shift+V _/switch to/from layout 3 = Shift+Alt+F3 _/preferences = Ctrl+Alt+Shift+P _/switch to/from layout 1 = Shift+Alt+F1 editor/run selection = F9 _/debug step into = Ctrl+F11 editor/toggle comment = Ctrl+1 editor/go to definition = Ctrl+G editor/show/hide project explorer = Ctrl+Alt+P _/debug step return = Ctrl+Shift+F11 editor/new file = Ctrl+N _/debug step over = Ctrl+F10 editor/save all = Ctrl+Shift+S editor/unblockcomment = Ctrl+5 _/debug exit = Ctrl+Shift+F12 editor/go to previous file = Ctrl+Tab editor/next cursor position = Ctrl+Alt+Right editor/debug = Ctrl+F5 editor/copy line = Shift+Alt+Down editor/file list management = Ctrl+E editor/debug with winpdb = F7 _/quit = Ctrl+Q editor/find next = F3 editor/move line up = Alt+Up console/inspect current object = Ctrl+I editor/find previous = Shift+F3 _/set layout 2 = Ctrl+Shift+Alt+F2 _/set layout 3 = Ctrl+Shift+Alt+F3 _/set layout 1 = Ctrl+Shift+Alt+F1 _/switch to console = Ctrl+Shift+C editor/re-run last script = Ctrl+F6 editor/previous cursor position = Ctrl+Alt+Left _/switch to project_explorer = Ctrl+Shift+P editor/open file = Ctrl+O editor/inspect current object = Ctrl+I editor/last edit location = Ctrl+Alt+Shift+Left editor/print = Ctrl+P editor/configure = F6 editor/breakpoint = F12 editor/find text = Ctrl+F editor/list breakpoints = Ctrl+B editor/run = F5 editor/close all = Ctrl+Shift+W _/debug continue = Ctrl+F12 editor/blockcomment = Ctrl+4 editor/close file = Ctrl+W editor/conditional breakpoint = Shift+F12 _/switch to/from layout 2 = Shift+Alt+F2 editor/replace text = Ctrl+H editor/save file = Ctrl+S editor/go to line = Ctrl+L _/switch to historylog = Ctrl+Shift+H editor/delete line = Ctrl+D [color_schemes] names = ['Emacs', 'IDLE', 'Monokai', 'Pydev', 'Scintilla', 'Spyder', 'Spyder/Dark', 'Zenburn'] monokai/background = #2a2b24 monokai/currentline = #484848 monokai/occurence = #666666 monokai/ctrlclick = #0000ff monokai/sideareas = #2a2b24 monokai/matched_p = #688060 monokai/unmatched_p = #bd6e76 monokai/normal = ('#ddddda', False, False) monokai/keyword = ('#f92672', False, False) monokai/builtin = ('#ae81ff', False, False) monokai/definition = ('#a6e22e', False, False) monokai/comment = ('#75715e', False, True) monokai/string = ('#e6db74', False, False) monokai/number = ('#ae81ff', False, False) monokai/instance = ('#ddddda', False, True) idle/background = #ffffff idle/currentline = #eeffdd idle/occurence = #e8f2fe idle/ctrlclick = #0000ff idle/sideareas = #efefef idle/matched_p = #99ff99 idle/unmatched_p = #ff9999 idle/normal = ('#000000', False, False) idle/keyword = ('#ff7700', True, False) idle/builtin = ('#900090', False, False) idle/definition = ('#0000ff', False, False) idle/comment = ('#dd0000', False, True) idle/string = ('#00aa00', False, False) idle/number = ('#924900', False, False) idle/instance = ('#777777', True, True) emacs/background = #000000 emacs/currentline = #2b2b43 emacs/occurence = #abab67 emacs/ctrlclick = #0000ff emacs/sideareas = #555555 emacs/matched_p = #009800 emacs/unmatched_p = #c80000 emacs/normal = ('#ffffff', False, False) emacs/keyword = ('#3c51e8', False, False) emacs/builtin = ('#900090', False, False) emacs/definition = ('#ff8040', True, False) emacs/comment = ('#005100', False, False) emacs/string = ('#00aa00', False, True) emacs/number = ('#800000', False, False) emacs/instance = ('#ffffff', False, True) zenburn/background = #3f3f3f zenburn/currentline = #333333 zenburn/occurence = #7a738f zenburn/ctrlclick = #0000ff zenburn/sideareas = #3f3f3f zenburn/matched_p = #688060 zenburn/unmatched_p = #bd6e76 zenburn/normal = ('#dcdccc', False, False) zenburn/keyword = ('#dfaf8f', True, False) zenburn/builtin = ('#efef8f', False, False) zenburn/definition = ('#efef8f', False, False) zenburn/comment = ('#7f9f7f', False, True) zenburn/string = ('#cc9393', False, False) zenburn/number = ('#8cd0d3', False, False) zenburn/instance = ('#dcdccc', False, True) spyder/dark/background = #131926 spyder/dark/currentline = #2b2b43 spyder/dark/occurence = #abab67 spyder/dark/ctrlclick = #0000ff spyder/dark/sideareas = #282828 spyder/dark/matched_p = #009800 spyder/dark/unmatched_p = #c80000 spyder/dark/normal = ('#ffffff', False, False) spyder/dark/keyword = ('#558eff', False, False) spyder/dark/builtin = ('#aa00aa', False, False) spyder/dark/definition = ('#ffffff', True, False) spyder/dark/comment = ('#7f7f7f', False, False) spyder/dark/string = ('#11a642', False, True) spyder/dark/number = ('#c80000', False, False) spyder/dark/instance = ('#be5f00', False, True) scintilla/background = #ffffff scintilla/currentline = #eeffdd scintilla/occurence = #ffff99 scintilla/ctrlclick = #0000ff scintilla/sideareas = #efefef scintilla/matched_p = #99ff99 scintilla/unmatched_p = #ff9999 scintilla/normal = ('#000000', False, False) scintilla/keyword = ('#00007f', True, False) scintilla/builtin = ('#000000', False, False) scintilla/definition = ('#007f7f', True, False) scintilla/comment = ('#007f00', False, False) scintilla/string = ('#7f007f', False, False) scintilla/number = ('#007f7f', False, False) scintilla/instance = ('#000000', False, True) pydev/background = #ffffff pydev/currentline = #e8f2fe pydev/occurence = #ffff99 pydev/ctrlclick = #0000ff pydev/sideareas = #efefef pydev/matched_p = #99ff99 pydev/unmatched_p = #ff9999 pydev/normal = ('#000000', False, False) pydev/keyword = ('#0000ff', False, False) pydev/builtin = ('#900090', False, False) pydev/definition = ('#000000', True, False) pydev/comment = ('#c0c0c0', False, False) pydev/string = ('#00aa00', False, True) pydev/number = ('#800000', False, False) pydev/instance = ('#000000', False, True) spyder/background = #ffffff spyder/currentline = #feefff spyder/occurence = #ffff99 spyder/ctrlclick = #0000ff spyder/sideareas = #efefef spyder/matched_p = #99ff99 spyder/unmatched_p = #ff9999 spyder/normal = ('#000000', False, False) spyder/keyword = ('#0000ff', False, False) spyder/builtin = ('#900090', False, False) spyder/definition = ('#000000', True, False) spyder/comment = ('#adadad', False, True) spyder/string = ('#00aa00', False, False) spyder/number = ('#800000', False, False) spyder/instance = ('#924900', False, True) spyder-3.2.6/spyder/defaults/defaults-3.0.0.ini0000664000175000017500000004153613026261006021710 0ustar carloscarlos00000000000000[main] lightwindow/is_fullscreen = False memory_usage/timeout = 2000 custom_margin = 0 vertical_dockwidget_titlebars = False lightwindow/size = (650, 400) show_internal_console_if_traceback = True memory_usage/enable = True single_instance = True window/is_maximized = True cpu_usage/enable = False lightwindow/is_maximized = False animated_docks = True window/is_fullscreen = False cpu_usage/timeout = 2000 window/size = (1260, 740) open_files_port = 21128 lightwindow/prefs_dialog_size = (745, 411) window/prefs_dialog_size = (745, 411) window/position = (10, 10) lightwindow/position = (30, 30) tear_off_menus = False vertical_tabs = False use_custom_margin = True [quick_layouts] place_holder = [editor_appearance] completion/size = (300, 180) cursor/width = 2 [shell_appearance] completion/size = (300, 180) cursor/width = 2 [internal_console] working_dir_adjusttocontents = False external_editor/gotoline = -goto: font/italic = False calltips = True working_dir_history = 30 external_editor/path = SciTE max_line_count = 300 shortcut = None font/family = ['Ubuntu Mono', 'Monospace', 'DejaVu Sans Mono', 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono', 'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal'] codecompletion/enter_key = True font/bold = False font/size = 10 codecompletion/auto = False wrap = True codecompletion/case_sensitive = True light_background = True codecompletion/show_single = False [console] pythonexecutable/default = True colorize_sys_stderr = True umd/enabled = True show_icontext = False calltips = True matplotlib/backend/value = Qt4Agg single_tab = True qt/install_inputhook = True max_line_count = 500 pythonstartup/default = True font/family = ['Ubuntu Mono', 'Monospace', 'DejaVu Sans Mono', 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono', 'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal'] pyqt/ignore_sip_setapi_errors = False qt/api = default pythonexecutable/custom = False font/size = 10 codecompletion/auto = True wrap = True umd/verbose = True matplotlib/patch = True codecompletion/show_single = False matplotlib/backend/enabled = True monitor/enabled = True pythonstartup/custom = False light_background = True font/italic = False codecompletion/enter_key = True ets_backend = qt4 merge_output_channels = True show_elapsed_time = False pyqt/api_version = 0 shortcut = Ctrl+Shift+C open_python_at_startup = True font/bold = False umd/namelist = ['guidata', 'guiqwt'] codecompletion/case_sensitive = True object_inspector = True [ipython_console] show_calltips = True pylab = True symbolic_math = False pylab/inline/height = 4 open_ipython_at_startup = True out_prompt = autocall = 0 in_prompt = shortcut = None font/bold = False startup/run_lines = startup/run_file = pylab/inline/figure_format = 0 greedy_completer = False pylab/inline/resolution = 72 font/family = ['Ubuntu Mono', 'Monospace', 'DejaVu Sans Mono', 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono', 'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal'] dark_color = False ask_before_closing = True pylab/backend = 0 font/size = 10 light_color = True buffer_size = 500 show_banner = True font/italic = False pylab/inline/width = 6 use_gui_completion = True use_pager = True startup/use_run_file = False object_inspector = True pylab/autoload = False [variable_explorer] collvalue = False truncate = True exclude_unsupported = True minmax = False exclude_uppercase = True check_all = False exclude_private = True autorefresh = True inplace = False shortcut = Ctrl+Shift+V excluded_names = ['nan', 'inf', 'infty', 'little_endian', 'colorbar_doc', 'typecodes', '__builtins__', '__main__', '__doc__', 'NaN', 'Inf', 'Infinity', 'sctypes', 'rcParams', 'rcParamsDefault', 'sctypeNA', 'typeNA', 'False_', 'True_'] autorefresh/timeout = 2000 exclude_capitalized = False remote_editing = False [editor] wrapflag = True edge_line = True add_colons = True always_remove_trailing_spaces = False auto_unindent = True max_recent_files = 20 onsave_analysis = False wrap = False indent_chars = * * outline_explorer = True show_tab_bar = True shortcut = Ctrl+Shift+E font/family = ['Ubuntu Mono', 'Monospace', 'DejaVu Sans Mono', 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono', 'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal'] codecompletion/auto = True fullpath_sorting = True font/italic = False check_eol_chars = True intelligent_backspace = True realtime_analysis/timeout = 2500 todo_list = True close_quotes = False occurence_highlighting = True object_inspector = True go_to_definition = True tab_stop_width = 40 tab_always_indent = False printer_header/font/bold = False codecompletion/show_single = False printer_header/font/italic = False realtime_analysis = True font/bold = False printer_header/font/family = ['Ubuntu', 'Sans Serif', 'DejaVu Sans', 'Bitstream Vera Sans', 'Bitstream Charter', 'Lucida Grande', 'MS Shell Dlg 2', 'Calibri', 'Verdana', 'Geneva', 'Lucid', 'Arial', 'Helvetica', 'Avant Garde', 'Times', 'sans-serif'] toolbox_panel = True calltips = True highlight_current_line = True font/size = 10 edge_line_column = 79 close_parentheses = True save_all_before_run = True code_analysis/pyflakes = True line_numbers = True codecompletion/enter_key = True code_analysis/pep8 = False printer_header/font/size = 10 codecompletion/case_sensitive = True occurence_highlighting/timeout = 1500 [historylog] max_entries = 100 go_to_eof = True font/bold = False enable = True font/size = 10 font/italic = False wrap = True font/family = ['Ubuntu Mono', 'Monospace', 'DejaVu Sans Mono', 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono', 'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal'] shortcut = Ctrl+Shift+H [inspector] max_history_entries = 20 enable = True font/italic = False rich_text/font/italic = False font/family = ['Ubuntu Mono', 'Monospace', 'DejaVu Sans Mono', 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono', 'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal'] shortcut = Ctrl+Shift+I automatic_import = True connect/ipython_console = False font/bold = False rich_text/font/size = 13 font/size = 10 connect/python_console = False wrap = True connect/editor = False rich_text/font/family = ['Ubuntu', 'Sans Serif', 'DejaVu Sans', 'Bitstream Vera Sans', 'Bitstream Charter', 'Lucida Grande', 'MS Shell Dlg 2', 'Calibri', 'Verdana', 'Geneva', 'Lucid', 'Arial', 'Helvetica', 'Avant Garde', 'Times', 'sans-serif'] rich_text/font/bold = False math = True [onlinehelp] max_history_entries = 20 enable = True zoom_factor = 0.8 shortcut = Ctrl+Shift+D [outline_explorer] show_comments = True show_fullpath = False enable = True shortcut = Ctrl+Shift+O show_all_files = False [project_explorer] show_all = False name_filters = ['*.py', '*.pyw', '*.ipy', '*.pyx', '*.pxd', '*.pxi', '*.c', '*.h', '*.cc', '*.cpp', '*.cxx', '*.h', '*.hh', '*.hpp', '*.hxx', '*.cl', '*.f', '*.for', '*.f77', '*.f90', '*.f95', '*.f2k', '*.pro', '*.m', '*.jl', '*.patch', '*.diff', '*.rej', '*.bat', '*.cmd', '*.txt', '*.txt', '*.rst', '*.po', '*.pot', '*.nsi', '*.nsh', '*.css', '*.htm', '*.html', '*.xml', '*.js', '*.enaml', '*.properties', '*.session', '*.ini', '*.inf', '*.reg', '*.cfg', '*.desktop', '*.txt', '*.png', '*.mat', '*.spydata', '*.tif', '*.jpg', '*.npy', '*.gif', '*.csv', '*.png', '*.ico', '*.svg', 'README', 'INSTALL', 'LICENSE', 'CHANGELOG'] enable = True shortcut = Ctrl+Shift+P show_hscrollbar = True [arrayeditor] font/bold = False font/size = 10 font/family = ['Ubuntu Mono', 'Monospace', 'DejaVu Sans Mono', 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono', 'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal'] font/italic = False [texteditor] font/bold = False font/size = 10 font/family = ['Ubuntu Mono', 'Monospace', 'DejaVu Sans Mono', 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono', 'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal'] font/italic = False [dicteditor] font/bold = False font/size = 10 font/family = ['Ubuntu Mono', 'Monospace', 'DejaVu Sans Mono', 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono', 'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal'] font/italic = False [explorer] enable = True show_hidden = True show_icontext = False wrap = True name_filters = ['*.py', '*.pyw', '*.ipy', '*.pyx', '*.pxd', '*.pxi', '*.c', '*.h', '*.cc', '*.cpp', '*.cxx', '*.h', '*.hh', '*.hpp', '*.hxx', '*.cl', '*.f', '*.for', '*.f77', '*.f90', '*.f95', '*.f2k', '*.pro', '*.m', '*.jl', '*.patch', '*.diff', '*.rej', '*.bat', '*.cmd', '*.txt', '*.txt', '*.rst', '*.po', '*.pot', '*.nsi', '*.nsh', '*.css', '*.htm', '*.html', '*.xml', '*.js', '*.enaml', '*.properties', '*.session', '*.ini', '*.inf', '*.reg', '*.cfg', '*.desktop', '*.txt', '*.png', '*.mat', '*.spydata', '*.tif', '*.jpg', '*.npy', '*.gif', '*.csv', '*.png', '*.ico', '*.svg', 'README', 'INSTALL', 'LICENSE', 'CHANGELOG'] show_all = False shortcut = None show_toolbar = True [find_in_files] enable = True exclude_regexp = True in_python_path = False exclude = ['\\.pyc$|\\.pyo$|\\.orig$|\\.hg|\\.svn|\\bbuild\\b', '\\.pyc$|\\.pyo$|\\.orig$|\\.hg|\\.svn'] search_text_regexp = True more_options = True search_text = [''] supported_encodings = ['utf-8', 'iso-8859-1', 'cp1252'] search_text_samples = ['(^|#)[ ]*(TODO|FIXME|XXX|HINT|TIP|@todo)([^#]*)'] shortcut = None include_regexp = True include = ['\\.py$|\\.pyw$|\\.ipy$|\\.pyx$|\\.pxd$|\\.pxi$|\\.c$|\\.h$|\\.cc$|\\.cpp$|\\.cxx$|\\.h$|\\.hh$|\\.hpp$|\\.hxx$|\\.cl$|\\.f$|\\.for$|\\.f77$|\\.f90$|\\.f95$|\\.f2k$|\\.pro$|\\.m$|\\.jl$|\\.patch$|\\.diff$|\\.rej$|\\.bat$|\\.cmd$|\\.txt$|\\.txt$|\\.rst$|\\.po$|\\.pot$|\\.nsi$|\\.nsh$|\\.css$|\\.htm$|\\.html$|\\.xml$|\\.js$|\\.enaml$|\\.properties$|\\.session$|\\.ini$|\\.inf$|\\.reg$|\\.cfg$|\\.desktop$|README|INSTALL', '\\.pyw?$|\\.ipy$|\\.txt$|\\.rst$', '.'] [workingdir] working_dir_adjusttocontents = False editor/new/browse_scriptdir = False editor/open/auto_set_to_basedir = False working_dir_history = 20 editor/open/browse_scriptdir = True editor/new/browse_workdir = True editor/open/browse_workdir = False startup/use_last_directory = True editor/save/auto_set_to_basedir = False [shortcuts] editor/duplicate line = Shift+Alt+Up editor/go to next file = Ctrl+Shift+Tab console/clear line = Shift+Escape _/switch to outline_explorer = Ctrl+Shift+O editor/show/hide outline = Ctrl+Alt+O editor/blockcomment = Ctrl+4 _/maximize plugin = Ctrl+Alt+Shift+M _/maximize dockwidget = Ctrl+Alt+Shift+M _/close plugin = Shift+Ctrl+F4 _/close dockwidget = Shift+Ctrl+F4 _/switch to inspector = Ctrl+Shift+I profiler/run profiler = F10 editor/move line down = Alt+Down console/clear shell = Ctrl+L pylint/run analysis = F8 _/switch to onlinehelp = Ctrl+Shift+D _/switch to editor = Ctrl+Shift+E editor/code completion = Ctrl+Space _/switch to variable_explorer = Ctrl+Shift+V _/switch to/from layout 3 = Shift+Alt+F3 _/preferences = Ctrl+Alt+Shift+P _/switch to/from layout 1 = Shift+Alt+F1 editor/run selection = F9 _/debug step into = Ctrl+F11 _/fullscreen mode = F11 editor/toggle comment = Ctrl+1 editor/go to definition = Ctrl+G editor/show/hide project explorer = Ctrl+Alt+P _/debug step return = Ctrl+Shift+F11 editor/new file = Ctrl+N _/debug step over = Ctrl+F10 editor/save all = Ctrl+Shift+S editor/unblockcomment = Ctrl+5 _/debug exit = Ctrl+Shift+F12 editor/go to previous file = Ctrl+Tab editor/next cursor position = Ctrl+Alt+Right editor/debug = Ctrl+F5 editor/copy line = Shift+Alt+Down editor/file list management = Ctrl+E editor/debug with winpdb = F7 _/quit = Ctrl+Q editor/find next = F3 editor/move line up = Alt+Up console/inspect current object = Ctrl+I editor/find previous = Shift+F3 _/set layout 2 = Ctrl+Shift+Alt+F2 _/set layout 3 = Ctrl+Shift+Alt+F3 _/set layout 1 = Ctrl+Shift+Alt+F1 _/switch to console = Ctrl+Shift+C editor/re-run last script = Ctrl+F6 editor/previous cursor position = Ctrl+Alt+Left _/switch to project_explorer = Ctrl+Shift+P editor/open file = Ctrl+O editor/inspect current object = Ctrl+I editor/last edit location = Ctrl+Alt+Shift+Left editor/print = Ctrl+P editor/breakpoint = F12 editor/find text = Ctrl+F editor/list breakpoints = Ctrl+B editor/run = F5 editor/close all = Ctrl+Shift+W _/debug continue = Ctrl+F12 editor/configure = F6 editor/close file = Ctrl+W editor/conditional breakpoint = Shift+F12 _/switch to/from layout 2 = Shift+Alt+F2 editor/replace text = Ctrl+H editor/save file = Ctrl+S editor/go to line = Ctrl+L _/switch to historylog = Ctrl+Shift+H editor/delete line = Ctrl+D [color_schemes] names = ['Emacs', 'IDLE', 'Monokai', 'Pydev', 'Scintilla', 'Spyder', 'Spyder/Dark', 'Zenburn'] monokai/background = #2a2b24 monokai/currentline = #484848 monokai/occurence = #666666 monokai/ctrlclick = #0000ff monokai/sideareas = #2a2b24 monokai/matched_p = #688060 monokai/unmatched_p = #bd6e76 monokai/normal = ('#ddddda', False, False) monokai/keyword = ('#f92672', False, False) monokai/builtin = ('#ae81ff', False, False) monokai/definition = ('#a6e22e', False, False) monokai/comment = ('#75715e', False, True) monokai/string = ('#e6db74', False, False) monokai/number = ('#ae81ff', False, False) monokai/instance = ('#ddddda', False, True) idle/background = #ffffff idle/currentline = #eeffdd idle/occurence = #e8f2fe idle/ctrlclick = #0000ff idle/sideareas = #efefef idle/matched_p = #99ff99 idle/unmatched_p = #ff9999 idle/normal = ('#000000', False, False) idle/keyword = ('#ff7700', True, False) idle/builtin = ('#900090', False, False) idle/definition = ('#0000ff', False, False) idle/comment = ('#dd0000', False, True) idle/string = ('#00aa00', False, False) idle/number = ('#924900', False, False) idle/instance = ('#777777', True, True) emacs/background = #000000 emacs/currentline = #2b2b43 emacs/occurence = #abab67 emacs/ctrlclick = #0000ff emacs/sideareas = #555555 emacs/matched_p = #009800 emacs/unmatched_p = #c80000 emacs/normal = ('#ffffff', False, False) emacs/keyword = ('#3c51e8', False, False) emacs/builtin = ('#900090', False, False) emacs/definition = ('#ff8040', True, False) emacs/comment = ('#005100', False, False) emacs/string = ('#00aa00', False, True) emacs/number = ('#800000', False, False) emacs/instance = ('#ffffff', False, True) zenburn/background = #3f3f3f zenburn/currentline = #333333 zenburn/occurence = #7a738f zenburn/ctrlclick = #0000ff zenburn/sideareas = #3f3f3f zenburn/matched_p = #688060 zenburn/unmatched_p = #bd6e76 zenburn/normal = ('#dcdccc', False, False) zenburn/keyword = ('#dfaf8f', True, False) zenburn/builtin = ('#efef8f', False, False) zenburn/definition = ('#efef8f', False, False) zenburn/comment = ('#7f9f7f', False, True) zenburn/string = ('#cc9393', False, False) zenburn/number = ('#8cd0d3', False, False) zenburn/instance = ('#dcdccc', False, True) spyder/dark/background = #131926 spyder/dark/currentline = #2b2b43 spyder/dark/occurence = #abab67 spyder/dark/ctrlclick = #0000ff spyder/dark/sideareas = #282828 spyder/dark/matched_p = #009800 spyder/dark/unmatched_p = #c80000 spyder/dark/normal = ('#ffffff', False, False) spyder/dark/keyword = ('#558eff', False, False) spyder/dark/builtin = ('#aa00aa', False, False) spyder/dark/definition = ('#ffffff', True, False) spyder/dark/comment = ('#7f7f7f', False, False) spyder/dark/string = ('#11a642', False, True) spyder/dark/number = ('#c80000', False, False) spyder/dark/instance = ('#be5f00', False, True) scintilla/background = #ffffff scintilla/currentline = #eeffdd scintilla/occurence = #ffff99 scintilla/ctrlclick = #0000ff scintilla/sideareas = #efefef scintilla/matched_p = #99ff99 scintilla/unmatched_p = #ff9999 scintilla/normal = ('#000000', False, False) scintilla/keyword = ('#00007f', True, False) scintilla/builtin = ('#000000', False, False) scintilla/definition = ('#007f7f', True, False) scintilla/comment = ('#007f00', False, False) scintilla/string = ('#7f007f', False, False) scintilla/number = ('#007f7f', False, False) scintilla/instance = ('#000000', False, True) pydev/background = #ffffff pydev/currentline = #e8f2fe pydev/occurence = #ffff99 pydev/ctrlclick = #0000ff pydev/sideareas = #efefef pydev/matched_p = #99ff99 pydev/unmatched_p = #ff9999 pydev/normal = ('#000000', False, False) pydev/keyword = ('#0000ff', False, False) pydev/builtin = ('#900090', False, False) pydev/definition = ('#000000', True, False) pydev/comment = ('#c0c0c0', False, False) pydev/string = ('#00aa00', False, True) pydev/number = ('#800000', False, False) pydev/instance = ('#000000', False, True) spyder/background = #ffffff spyder/currentline = #feefff spyder/occurence = #ffff99 spyder/ctrlclick = #0000ff spyder/sideareas = #efefef spyder/matched_p = #99ff99 spyder/unmatched_p = #ff9999 spyder/normal = ('#000000', False, False) spyder/keyword = ('#0000ff', False, False) spyder/builtin = ('#900090', False, False) spyder/definition = ('#000000', True, False) spyder/comment = ('#adadad', False, True) spyder/string = ('#00aa00', False, False) spyder/number = ('#800000', False, False) spyder/instance = ('#924900', False, True) spyder-3.2.6/spyder/widgets/0000775000175000017500000000000013225025007016572 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/widgets/comboboxes.py0000664000175000017500000002612213224121062021304 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Customized combobox widgets.""" # pylint: disable=C0103 # pylint: disable=R0903 # pylint: disable=R0911 # pylint: disable=R0201 # Standard library imports import glob import os import os.path as osp # Third party imports from qtpy.QtCore import QEvent, Qt, QTimer, QUrl, Signal from qtpy.QtGui import QFont from qtpy.QtWidgets import QComboBox, QCompleter, QSizePolicy, QToolTip # Local imports from spyder.config.base import _ from spyder.py3compat import to_text_string from spyder.widgets.helperwidgets import IconLineEdit class BaseComboBox(QComboBox): """Editable combo box base class""" valid = Signal(bool, bool) sig_tab_pressed = Signal(bool) sig_double_tab_pressed = Signal(bool) def __init__(self, parent): QComboBox.__init__(self, parent) self.setEditable(True) self.setCompleter(QCompleter(self)) self.numpress = 0 self.selected_text = self.currentText() # --- Qt overrides def event(self, event): """Qt Override. Filter tab keys and process double tab keys. """ if (event.type() == QEvent.KeyPress) and (event.key() == Qt.Key_Tab): self.sig_tab_pressed.emit(True) self.numpress += 1 if self.numpress == 1: self.presstimer = QTimer.singleShot(400, self.handle_keypress) return True return QComboBox.event(self, event) def keyPressEvent(self, event): """Qt Override. Handle key press events. """ if event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter: if self.add_current_text_if_valid(): self.selected() self.hide_completer() elif event.key() == Qt.Key_Escape: self.set_current_text(self.selected_text) self.hide_completer() else: QComboBox.keyPressEvent(self, event) # --- own methods def handle_keypress(self): """When hitting tab, it handles if single or double tab""" if self.numpress == 2: self.sig_double_tab_pressed.emit(True) self.numpress = 0 def is_valid(self, qstr): """ Return True if string is valid Return None if validation can't be done """ pass def selected(self): """Action to be executed when a valid item has been selected""" self.valid.emit(True, True) def add_text(self, text): """Add text to combo box: add a new item if text is not found in combo box items.""" index = self.findText(text) while index != -1: self.removeItem(index) index = self.findText(text) self.insertItem(0, text) index = self.findText('') if index != -1: self.removeItem(index) self.insertItem(0, '') if text != '': self.setCurrentIndex(1) else: self.setCurrentIndex(0) else: self.setCurrentIndex(0) def set_current_text(self, text): """Sets the text of the QLineEdit of the QComboBox.""" self.lineEdit().setText(to_text_string(text)) def add_current_text(self): """Add current text to combo box history (convenient method)""" text = self.currentText() self.add_text(text) def add_current_text_if_valid(self): """Add current text to combo box history if valid""" valid = self.is_valid(self.currentText()) if valid or valid is None: self.add_current_text() return True else: self.set_current_text(self.selected_text) def hide_completer(self): """Hides the completion widget.""" self.setCompleter(QCompleter([], self)) class PatternComboBox(BaseComboBox): """Search pattern combo box""" def __init__(self, parent, items=None, tip=None, adjust_to_minimum=True): BaseComboBox.__init__(self, parent) if hasattr(self.lineEdit(), 'setClearButtonEnabled'): # only Qt >= 5.2 self.lineEdit().setClearButtonEnabled(True) if adjust_to_minimum: self.setSizeAdjustPolicy(QComboBox.AdjustToMinimumContentsLength) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) if items is not None: self.addItems(items) if tip is not None: self.setToolTip(tip) class EditableComboBox(BaseComboBox): """ Editable combo box + Validate """ def __init__(self, parent): BaseComboBox.__init__(self, parent) self.font = QFont() self.selected_text = self.currentText() # Widget setup self.setSizeAdjustPolicy(QComboBox.AdjustToMinimumContentsLength) # Signals self.editTextChanged.connect(self.validate) self.tips = {True: _("Press enter to validate this entry"), False: _('This entry is incorrect')} def show_tip(self, tip=""): """Show tip""" QToolTip.showText(self.mapToGlobal(self.pos()), tip, self) def selected(self): """Action to be executed when a valid item has been selected""" BaseComboBox.selected(self) self.selected_text = self.currentText() def validate(self, qstr, editing=True): """Validate entered path""" if self.selected_text == qstr and qstr != '': self.valid.emit(True, True) return valid = self.is_valid(qstr) if editing: if valid: self.valid.emit(True, False) else: self.valid.emit(False, False) class PathComboBox(EditableComboBox): """ QComboBox handling path locations """ open_dir = Signal(str) def __init__(self, parent, adjust_to_contents=False): EditableComboBox.__init__(self, parent) # Replace the default lineedit by a custom one with icon display lineedit = IconLineEdit(self) # Widget setup if adjust_to_contents: self.setSizeAdjustPolicy(QComboBox.AdjustToContents) else: self.setSizeAdjustPolicy(QComboBox.AdjustToMinimumContentsLength) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.tips = {True: _("Press enter to validate this path"), False: ''} self.setLineEdit(lineedit) # Signals self.highlighted.connect(self.add_tooltip_to_highlighted_item) self.sig_tab_pressed.connect(self.tab_complete) self.sig_double_tab_pressed.connect(self.double_tab_complete) self.valid.connect(lineedit.update_status) # --- Qt overrides def focusInEvent(self, event): """Handle focus in event restoring to display the status icon.""" show_status = getattr(self.lineEdit(), 'show_status_icon', None) if show_status: show_status() QComboBox.focusInEvent(self, event) def focusOutEvent(self, event): """Handle focus out event restoring the last valid selected path.""" # Calling asynchronously the 'add_current_text' to avoid crash # https://groups.google.com/group/spyderlib/browse_thread/thread/2257abf530e210bd if not self.is_valid(): lineedit = self.lineEdit() QTimer.singleShot(50, lambda: lineedit.setText(self.selected_text)) hide_status = getattr(self.lineEdit(), 'hide_status_icon', None) if hide_status: hide_status() QComboBox.focusOutEvent(self, event) # --- Own methods def _complete_options(self): """Find available completion options.""" text = to_text_string(self.currentText()) opts = glob.glob(text + "*") opts = sorted([opt for opt in opts if osp.isdir(opt)]) self.setCompleter(QCompleter(opts, self)) return opts def double_tab_complete(self): """If several options available a double tab displays options.""" opts = self._complete_options() if len(opts) > 1: self.completer().complete() def tab_complete(self): """ If there is a single option available one tab completes the option. """ opts = self._complete_options() if len(opts) == 1: self.set_current_text(opts[0] + os.sep) self.hide_completer() def is_valid(self, qstr=None): """Return True if string is valid""" if qstr is None: qstr = self.currentText() return osp.isdir(to_text_string(qstr)) def selected(self): """Action to be executed when a valid item has been selected""" self.selected_text = self.currentText() self.valid.emit(True, True) self.open_dir.emit(self.selected_text) def add_current_text(self): """ Add current text to combo box history (convenient method). If path ends in os separator ("\" windows, "/" unix) remove it. """ text = self.currentText() if osp.isdir(text) and text: if text[-1] == os.sep: text = text[:-1] self.add_text(text) def add_tooltip_to_highlighted_item(self, index): """ Add a tooltip showing the full path of the currently highlighted item of the PathComboBox. """ self.setItemData(index, self.itemText(index), Qt.ToolTipRole) class UrlComboBox(PathComboBox): """ QComboBox handling urls """ def __init__(self, parent, adjust_to_contents=False): PathComboBox.__init__(self, parent, adjust_to_contents) self.editTextChanged.disconnect(self.validate) def is_valid(self, qstr=None): """Return True if string is valid""" if qstr is None: qstr = self.currentText() return QUrl(qstr).isValid() def is_module_or_package(path): """Return True if path is a Python module/package""" is_module = osp.isfile(path) and osp.splitext(path)[1] in ('.py', '.pyw') is_package = osp.isdir(path) and osp.isfile(osp.join(path, '__init__.py')) return is_module or is_package class PythonModulesComboBox(PathComboBox): """ QComboBox handling Python modules or packages path (i.e. .py, .pyw files *and* directories containing __init__.py) """ def __init__(self, parent, adjust_to_contents=False): PathComboBox.__init__(self, parent, adjust_to_contents) def is_valid(self, qstr=None): """Return True if string is valid""" if qstr is None: qstr = self.currentText() return is_module_or_package(to_text_string(qstr)) def selected(self): """Action to be executed when a valid item has been selected""" EditableComboBox.selected(self) self.open_dir.emit(self.currentText()) spyder-3.2.6/spyder/widgets/shortcutssummary.py0000664000175000017500000001203713211142273022623 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © 2009- The Spyder Development Team # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Shortcut Summary dialog""" # Standard library imports from operator import itemgetter from itertools import groupby # Third party imports from qtpy.QtCore import Qt from qtpy.QtGui import QFont from qtpy.QtWidgets import (QDialog, QLabel, QGridLayout, QGroupBox, QVBoxLayout, QHBoxLayout, QDesktopWidget, QScrollArea, QWidget) # Local imports from spyder.config.base import _ from spyder.config.gui import iter_shortcuts # Constants MAX_FONT_SIZE = 16 MIN_FONT_SIZE = 8 class ShortcutsSummaryDialog(QDialog): """ Dialog window listing the spyder and plugins shortcuts. It contains all the shortcuts avalaible through iter_shortcuts function The shortcuts are dysplayed in different columns, and grouped by context (global, editor, console...) """ def __init__(self, parent=None): QDialog.__init__(self, parent=parent) self._shortcuts_summary_title = _("Spyder Keyboard ShortCuts") # Calculate font and amount of elements in each column according screen size width, height = self.get_screen_resolution() font_size = height / 80 font_size = max(min(font_size, MAX_FONT_SIZE), MIN_FONT_SIZE) shortcuts_column = (height - 8 * font_size) / (font_size +16) # Widgets style = """ QDialog { margin:0px; padding:0px; border-radius: 2px; }""" self.setStyleSheet(style) font_names = QFont() font_names.setPointSize(font_size) font_names.setBold(True) font_keystr = QFont() font_keystr.setPointSize(font_size) font_title = QFont() font_title.setPointSize(font_size+2) font_title.setBold(True) title_label = QLabel(self._shortcuts_summary_title) title_label.setAlignment(Qt.AlignCenter) title_label.setFont(font_title) # iter over shortcuts and create GroupBox for each context # with shortcuts in a grid columns_layout = QHBoxLayout() added_shortcuts = 0 group = None # group shortcuts by context shortcuts = groupby(sorted(iter_shortcuts()), key=itemgetter(0)) for context, group_shortcuts in shortcuts: for i, (context, name, keystr) in enumerate(group_shortcuts): # start of every column if added_shortcuts == 0: column_layout = QVBoxLayout() # at start of new context add previous context group if i == 0 and added_shortcuts > 0: column_layout.addWidget(group) # create group at start of column or context if added_shortcuts == 0 or i == 0: if context == '_': context = 'Global' group = QGroupBox(context.capitalize()) group.setFont(font_names) group_layout = QGridLayout() group.setLayout(group_layout) # Count space for titles added_shortcuts += 1 # Widgets label_name = QLabel(name.capitalize().replace('_', ' ')) label_name.setFont(font_names) label_keystr = QLabel(keystr) label_keystr.setFont(font_keystr) group_layout.addWidget(label_name, i, 0) group_layout.addWidget(label_keystr, i, 1) added_shortcuts += 1 if added_shortcuts >= shortcuts_column: column_layout.addWidget(group) columns_layout.addLayout(column_layout) added_shortcuts = 0 column_layout.addWidget(group) column_layout.addStretch() # avoid lasts sections to appear too big columns_layout.addLayout(column_layout) # Scroll widget self.scroll_widget = QWidget() self.scroll_widget.setLayout(columns_layout) self.scroll_area = QScrollArea() self.scroll_area.setWidget(self.scroll_widget) # widget setup self.setWindowFlags(Qt.FramelessWindowHint) self.setWindowOpacity(0.95) # layout self._layout = QVBoxLayout() self._layout.addWidget(title_label) self._layout.addWidget(self.scroll_area) self.setLayout(self._layout) self.setGeometry(0, 0, width, height) def get_screen_resolution(self): """Return the screen resolution of the primary screen.""" widget = QDesktopWidget() geometry = widget.availableGeometry(widget.primaryScreen()) return geometry.width(), geometry.height() def test(): # pragma: no cover from spyder.utils.qthelpers import qapplication app = qapplication() dlg_shortcuts = ShortcutsSummaryDialog(None) dlg_shortcuts.show() app.exec_() if __name__ == "__main__": # pragma: no cover test() spyder-3.2.6/spyder/widgets/waitingspinner.py0000664000175000017500000001642513211142273022215 0ustar carloscarlos00000000000000""" The MIT License (MIT) Copyright (c) 2012-2014 Alexander Turkin Copyright (c) 2014 William Hallatt Copyright (c) 2015 Jacob Dawid Copyright (c) 2016 Luca Weiss Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ import math from qtpy.QtCore import * from qtpy.QtGui import * from qtpy.QtWidgets import * class QWaitingSpinner(QWidget): def __init__(self, parent, centerOnParent=True, disableParentWhenSpinning=False, modality=Qt.NonModal): # super().__init__(parent) QWidget.__init__(self, parent) self._centerOnParent = centerOnParent self._disableParentWhenSpinning = disableParentWhenSpinning # WAS IN initialize() self._color = QColor(Qt.black) self._roundness = 100.0 self._minimumTrailOpacity = 3.14159265358979323846 self._trailFadePercentage = 80.0 self._revolutionsPerSecond = 1.57079632679489661923 self._numberOfLines = 20 self._lineLength = 10 self._lineWidth = 2 self._innerRadius = 10 self._currentCounter = 0 self._isSpinning = False self._timer = QTimer(self) self._timer.timeout.connect(self.rotate) self.updateSize() self.updateTimer() self.hide() # END initialize() self.setWindowModality(modality) self.setAttribute(Qt.WA_TranslucentBackground) def paintEvent(self, QPaintEvent): self.updatePosition() painter = QPainter(self) painter.fillRect(self.rect(), Qt.transparent) painter.setRenderHint(QPainter.Antialiasing, True) if self._currentCounter >= self._numberOfLines: self._currentCounter = 0 painter.setPen(Qt.NoPen) for i in range(0, self._numberOfLines): painter.save() painter.translate(self._innerRadius + self._lineLength, self._innerRadius + self._lineLength) rotateAngle = float(360 * i) / float(self._numberOfLines) painter.rotate(rotateAngle) painter.translate(self._innerRadius, 0) distance = self.lineCountDistanceFromPrimary(i, self._currentCounter, self._numberOfLines) color = self.currentLineColor(distance, self._numberOfLines, self._trailFadePercentage, self._minimumTrailOpacity, self._color) painter.setBrush(color) painter.drawRoundedRect(QRect(0, -self._lineWidth / 2, self._lineLength, self._lineWidth), self._roundness, self._roundness, Qt.RelativeSize) painter.restore() def start(self): self.updatePosition() self._isSpinning = True self.show() if self.parentWidget and self._disableParentWhenSpinning: self.parentWidget().setEnabled(False) if not self._timer.isActive(): self._timer.start() self._currentCounter = 0 def stop(self): self._isSpinning = False self.hide() if self.parentWidget() and self._disableParentWhenSpinning: self.parentWidget().setEnabled(True) if self._timer.isActive(): self._timer.stop() self._currentCounter = 0 def setNumberOfLines(self, lines): self._numberOfLines = lines self._currentCounter = 0 self.updateTimer() def setLineLength(self, length): self._lineLength = length self.updateSize() def setLineWidth(self, width): self._lineWidth = width self.updateSize() def setInnerRadius(self, radius): self._innerRadius = radius self.updateSize() def color(self): return self._color def roundness(self): return self._roundness def minimumTrailOpacity(self): return self._minimumTrailOpacity def trailFadePercentage(self): return self._trailFadePercentage def revolutionsPersSecond(self): return self._revolutionsPerSecond def numberOfLines(self): return self._numberOfLines def lineLength(self): return self._lineLength def lineWidth(self): return self._lineWidth def innerRadius(self): return self._innerRadius def isSpinning(self): return self._isSpinning def setRoundness(self, roundness): self._roundness = max(0.0, min(100.0, roundness)) def setColor(self, color=Qt.black): self._color = QColor(color) def setRevolutionsPerSecond(self, revolutionsPerSecond): self._revolutionsPerSecond = revolutionsPerSecond self.updateTimer() def setTrailFadePercentage(self, trail): self._trailFadePercentage = trail def setMinimumTrailOpacity(self, minimumTrailOpacity): self._minimumTrailOpacity = minimumTrailOpacity def rotate(self): self._currentCounter += 1 if self._currentCounter >= self._numberOfLines: self._currentCounter = 0 self.update() def updateSize(self): size = (self._innerRadius + self._lineLength) * 2 self.setFixedSize(size, size) def updateTimer(self): self._timer.setInterval(1000 / (self._numberOfLines * self._revolutionsPerSecond)) def updatePosition(self): if self.parentWidget() and self._centerOnParent: self.move(self.parentWidget().width() / 2 - self.width() / 2, self.parentWidget().height() / 2 - self.height() / 2) def lineCountDistanceFromPrimary(self, current, primary, totalNrOfLines): distance = primary - current if distance < 0: distance += totalNrOfLines return distance def currentLineColor(self, countDistance, totalNrOfLines, trailFadePerc, minOpacity, colorinput): color = QColor(colorinput) if countDistance == 0: return color minAlphaF = minOpacity / 100.0 distanceThreshold = int(math.ceil((totalNrOfLines - 1) * trailFadePerc / 100.0)) if countDistance > distanceThreshold: color.setAlphaF(minAlphaF) else: alphaDiff = color.alphaF() - minAlphaF gradient = alphaDiff / float(distanceThreshold + 1) resultAlpha = color.alphaF() - gradient * countDistance # If alpha is out of bounds, clip it. resultAlpha = min(1.0, max(0.0, resultAlpha)) color.setAlphaF(resultAlpha) return color spyder-3.2.6/spyder/widgets/browser.py0000664000175000017500000003131413224740762020644 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Simple web browser widget""" # Standard library imports import re import sre_constants import sys # Third party imports from qtpy.QtCore import QUrl, Signal, Slot from qtpy.QtWidgets import (QFrame, QHBoxLayout, QLabel, QProgressBar, QMenu, QVBoxLayout, QWidget) from qtpy.QtWebEngineWidgets import (QWebEnginePage, QWebEngineSettings, QWebEngineView, WEBENGINE) from qtpy.QtGui import QFontInfo # Local imports from spyder.config.base import _, DEV from spyder.py3compat import is_text_string, to_text_string from spyder.utils.qthelpers import (action2button, add_actions, create_action, create_toolbutton, create_plugin_layout) from spyder.utils import icon_manager as ima from spyder.widgets.comboboxes import UrlComboBox from spyder.widgets.findreplace import FindReplace class WebPage(QWebEnginePage): """ Web page subclass to manage hyperlinks for WebEngine Note: This can't be used for WebKit because the acceptNavigationRequest method has a different functionality for it. """ linkClicked = Signal(QUrl) def acceptNavigationRequest(self, url, navigation_type, isMainFrame): """ Overloaded method to handle links ourselves """ if navigation_type == QWebEnginePage.NavigationTypeLinkClicked: self.linkClicked.emit(url) return False return True class WebView(QWebEngineView): """Web view""" def __init__(self, parent): QWebEngineView.__init__(self, parent) self.zoom_factor = 1. self.zoom_out_action = create_action(self, _("Zoom out"), icon=ima.icon('zoom_out'), triggered=self.zoom_out) self.zoom_in_action = create_action(self, _("Zoom in"), icon=ima.icon('zoom_in'), triggered=self.zoom_in) if WEBENGINE: web_page = WebPage(self) self.setPage(web_page) self.source_text = '' def find_text(self, text, changed=True, forward=True, case=False, words=False, regexp=False): """Find text""" if not WEBENGINE: findflag = QWebEnginePage.FindWrapsAroundDocument else: findflag = 0 if not forward: findflag = findflag | QWebEnginePage.FindBackward if case: findflag = findflag | QWebEnginePage.FindCaseSensitively return self.findText(text, QWebEnginePage.FindFlags(findflag)) def get_selected_text(self): """Return text selected by current text cursor""" return self.selectedText() def set_source_text(self, source_text): """Set source text of the page. Callback for QWebEngineView.""" self.source_text = source_text def get_number_matches(self, pattern, source_text='', case=False): """Get the number of matches for the searched text.""" pattern = to_text_string(pattern) if not pattern: return 0 if not source_text: if WEBENGINE: self.page().toPlainText(self.set_source_text) source_text = to_text_string(self.source_text) else: source_text = to_text_string( self.page().mainFrame().toPlainText()) try: if case: regobj = re.compile(pattern) else: regobj = re.compile(pattern, re.IGNORECASE) except sre_constants.error: return number_matches = 0 for match in regobj.finditer(source_text): number_matches += 1 return number_matches def set_font(self, font, fixed_font=None): font = QFontInfo(font) settings = self.page().settings() for fontfamily in (settings.StandardFont, settings.SerifFont, settings.SansSerifFont, settings.CursiveFont, settings.FantasyFont): settings.setFontFamily(fontfamily, font.family()) if fixed_font is not None: settings.setFontFamily(settings.FixedFont, fixed_font.family()) size = font.pixelSize() settings.setFontSize(settings.DefaultFontSize, size) settings.setFontSize(settings.DefaultFixedFontSize, size) def apply_zoom_factor(self): """Apply zoom factor""" if hasattr(self, 'setZoomFactor'): # Assuming Qt >=v4.5 self.setZoomFactor(self.zoom_factor) else: # Qt v4.4 self.setTextSizeMultiplier(self.zoom_factor) def set_zoom_factor(self, zoom_factor): """Set zoom factor""" self.zoom_factor = zoom_factor self.apply_zoom_factor() def get_zoom_factor(self): """Return zoom factor""" return self.zoom_factor @Slot() def zoom_out(self): """Zoom out""" self.zoom_factor = max(.1, self.zoom_factor-.1) self.apply_zoom_factor() @Slot() def zoom_in(self): """Zoom in""" self.zoom_factor += .1 self.apply_zoom_factor() #------ QWebEngineView API ------------------------------------------------------- def createWindow(self, webwindowtype): import webbrowser webbrowser.open(to_text_string(self.url().toString())) def contextMenuEvent(self, event): menu = QMenu(self) actions = [self.pageAction(QWebEnginePage.Back), self.pageAction(QWebEnginePage.Forward), None, self.pageAction(QWebEnginePage.SelectAll), self.pageAction(QWebEnginePage.Copy), None, self.zoom_in_action, self.zoom_out_action] if DEV and not WEBENGINE: settings = self.page().settings() settings.setAttribute(QWebEngineSettings.DeveloperExtrasEnabled, True) actions += [None, self.pageAction(QWebEnginePage.InspectElement)] add_actions(menu, actions) menu.popup(event.globalPos()) event.accept() def setHtml(self, html, baseUrl=QUrl()): """ Reimplement Qt method to prevent WebEngine to steal focus when setting html on the page Solution taken from https://bugreports.qt.io/browse/QTBUG-52999 """ if WEBENGINE: self.setEnabled(False) super(WebView, self).setHtml(html, baseUrl) self.setEnabled(True) else: super(WebView, self).setHtml(html, baseUrl) class WebBrowser(QWidget): """ Web browser widget """ def __init__(self, parent=None): QWidget.__init__(self, parent) self.home_url = None self.webview = WebView(self) self.webview.loadFinished.connect(self.load_finished) self.webview.titleChanged.connect(self.setWindowTitle) self.webview.urlChanged.connect(self.url_changed) home_button = create_toolbutton(self, icon=ima.icon('home'), tip=_("Home"), triggered=self.go_home) zoom_out_button = action2button(self.webview.zoom_out_action) zoom_in_button = action2button(self.webview.zoom_in_action) pageact2btn = lambda prop: action2button(self.webview.pageAction(prop), parent=self.webview) refresh_button = pageact2btn(QWebEnginePage.Reload) stop_button = pageact2btn(QWebEnginePage.Stop) previous_button = pageact2btn(QWebEnginePage.Back) next_button = pageact2btn(QWebEnginePage.Forward) stop_button.setEnabled(False) self.webview.loadStarted.connect(lambda: stop_button.setEnabled(True)) self.webview.loadFinished.connect(lambda: stop_button.setEnabled(False)) progressbar = QProgressBar(self) progressbar.setTextVisible(False) progressbar.hide() self.webview.loadStarted.connect(progressbar.show) self.webview.loadProgress.connect(progressbar.setValue) self.webview.loadFinished.connect(lambda _state: progressbar.hide()) label = QLabel(self.get_label()) self.url_combo = UrlComboBox(self) self.url_combo.valid.connect(self.url_combo_activated) if not WEBENGINE: self.webview.iconChanged.connect(self.icon_changed) self.find_widget = FindReplace(self) self.find_widget.set_editor(self.webview) self.find_widget.hide() find_button = create_toolbutton(self, icon=ima.icon('find'), tip=_("Find text"), toggled=self.toggle_find_widget) self.find_widget.visibility_changed.connect(find_button.setChecked) hlayout = QHBoxLayout() for widget in (previous_button, next_button, home_button, find_button, label, self.url_combo, zoom_out_button, zoom_in_button, refresh_button, progressbar, stop_button): hlayout.addWidget(widget) layout = create_plugin_layout(hlayout) layout.addWidget(self.webview) layout.addWidget(self.find_widget) self.setLayout(layout) def get_label(self): """Return address label text""" return _("Address:") def set_home_url(self, text): """Set home URL""" self.home_url = QUrl(text) def set_url(self, url): """Set current URL""" self.url_changed(url) self.go_to(url) def go_to(self, url_or_text): """Go to page *address*""" if is_text_string(url_or_text): url = QUrl(url_or_text) else: url = url_or_text self.webview.load(url) @Slot() def go_home(self): """Go to home page""" if self.home_url is not None: self.set_url(self.home_url) def text_to_url(self, text): """Convert text address into QUrl object""" return QUrl(text) def url_combo_activated(self, valid): """Load URL from combo box first item""" text = to_text_string(self.url_combo.currentText()) self.go_to(self.text_to_url(text)) def load_finished(self, ok): if not ok: self.webview.setHtml(_("Unable to load page")) def url_to_text(self, url): """Convert QUrl object to displayed text in combo box""" return url.toString() def url_changed(self, url): """Displayed URL has changed -> updating URL combo box""" self.url_combo.add_text(self.url_to_text(url)) def icon_changed(self): self.url_combo.setItemIcon(self.url_combo.currentIndex(), self.webview.icon()) self.setWindowIcon(self.webview.icon()) @Slot(bool) def toggle_find_widget(self, state): if state: self.find_widget.show() else: self.find_widget.hide() class FrameWebView(QFrame): """ Framed QWebEngineView for UI consistency in Spyder. """ linkClicked = Signal(QUrl) def __init__(self, parent): QFrame.__init__(self, parent) self._webview = WebView(self) layout = QHBoxLayout() layout.addWidget(self._webview) layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) self.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) if WEBENGINE: self._webview.page().linkClicked.connect(self.linkClicked) else: self._webview.linkClicked.connect(self.linkClicked) def __getattr__(self, name): return getattr(self._webview, name) @property def web_widget(self): return self._webview def test(): """Run web browser""" from spyder.utils.qthelpers import qapplication app = qapplication(test_time=8) widget = WebBrowser() widget.show() widget.set_home_url('http://www.google.com/') widget.go_home() sys.exit(app.exec_()) if __name__ == '__main__': test() spyder-3.2.6/spyder/widgets/ipythonconsole/0000775000175000017500000000000013225025007021647 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/widgets/ipythonconsole/client.py0000664000175000017500000005734613224740762023531 0ustar carloscarlos00000000000000# -*- coding:utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Client widget for the IPython Console This is the widget used on all its tabs """ # Standard library imports from __future__ import absolute_import # Fix for Issue 1356 import codecs import os import os.path as osp from string import Template from threading import Thread from time import ctime, time, strftime, gmtime # Third party imports (qtpy) from qtpy.QtCore import QUrl, QTimer, Signal, Slot from qtpy.QtGui import QKeySequence from qtpy.QtWidgets import (QHBoxLayout, QLabel, QMenu, QMessageBox, QToolButton, QVBoxLayout, QWidget) # Local imports from spyder.config.base import _, get_image_path, get_module_source_path from spyder.config.gui import get_font, get_shortcut from spyder.utils import icon_manager as ima from spyder.utils import sourcecode from spyder.utils.encoding import get_coding from spyder.utils.environ import RemoteEnvDialog from spyder.utils.ipython.style import create_qss_style from spyder.utils.programs import TEMPDIR from spyder.utils.qthelpers import (add_actions, create_action, create_toolbutton, DialogManager, MENU_SEPARATOR) from spyder.py3compat import to_text_string from spyder.widgets.browser import WebView from spyder.widgets.ipythonconsole import ShellWidget from spyder.widgets.mixins import SaveHistoryMixin from spyder.widgets.variableexplorer.collectionseditor import CollectionsEditor #----------------------------------------------------------------------------- # Templates #----------------------------------------------------------------------------- # Using the same css file from the Help plugin for now. Maybe # later it'll be a good idea to create a new one. UTILS_PATH = get_module_source_path('spyder', 'utils') CSS_PATH = osp.join(UTILS_PATH, 'help', 'static', 'css') TEMPLATES_PATH = osp.join(UTILS_PATH, 'ipython', 'templates') BLANK = open(osp.join(TEMPLATES_PATH, 'blank.html')).read() LOADING = open(osp.join(TEMPLATES_PATH, 'loading.html')).read() KERNEL_ERROR = open(osp.join(TEMPLATES_PATH, 'kernel_error.html')).read() #----------------------------------------------------------------------------- # Auxiliary functions #----------------------------------------------------------------------------- def background(f): """ Call a function in a simple thread, to prevent blocking Taken from the Jupyter Qtconsole project """ t = Thread(target=f) t.start() return t #----------------------------------------------------------------------------- # Client widget #----------------------------------------------------------------------------- class ClientWidget(QWidget, SaveHistoryMixin): """ Client widget for the IPython Console This is a widget composed of a shell widget and a WebView info widget to print different messages there. """ SEPARATOR = '{0}## ---({1})---'.format(os.linesep*2, ctime()) INITHISTORY = ['# -*- coding: utf-8 -*-', '# *** Spyder Python Console History Log ***',] append_to_history = Signal(str, str) def __init__(self, plugin, id_, history_filename, config_options, additional_options, interpreter_versions, connection_file=None, hostname=None, menu_actions=None, slave=False, external_kernel=False, given_name=None, show_elapsed_time=False, reset_warning=True): super(ClientWidget, self).__init__(plugin) SaveHistoryMixin.__init__(self, history_filename) # --- Init attrs self.id_ = id_ self.connection_file = connection_file self.hostname = hostname self.menu_actions = menu_actions self.slave = slave self.external_kernel = external_kernel self.given_name = given_name self.show_elapsed_time = show_elapsed_time self.reset_warning = reset_warning # --- Other attrs self.options_button = None self.stop_button = None self.reset_button = None self.stop_icon = ima.icon('stop') self.history = [] self.allow_rename = True self.stderr_dir = None # --- Widgets self.shellwidget = ShellWidget(config=config_options, ipyclient=self, additional_options=additional_options, interpreter_versions=interpreter_versions, external_kernel=external_kernel, local_kernel=True) self.infowidget = WebView(self) self.set_infowidget_font() self.loading_page = self._create_loading_page() self._show_loading_page() # Elapsed time self.time_label = None self.t0 = None self.timer = QTimer(self) # --- Layout vlayout = QVBoxLayout() toolbar_buttons = self.get_toolbar_buttons() hlayout = QHBoxLayout() hlayout.addWidget(self.create_time_label()) hlayout.addStretch(0) for button in toolbar_buttons: hlayout.addWidget(button) vlayout.addLayout(hlayout) vlayout.setContentsMargins(0, 0, 0, 0) vlayout.addWidget(self.shellwidget) vlayout.addWidget(self.infowidget) self.setLayout(vlayout) # --- Exit function self.exit_callback = lambda: plugin.close_client(client=self) # --- Dialog manager self.dialog_manager = DialogManager() # Show timer self.update_time_label_visibility() #------ Public API -------------------------------------------------------- @property def kernel_id(self): """Get kernel id""" if self.connection_file is not None: json_file = osp.basename(self.connection_file) return json_file.split('.json')[0] @property def stderr_file(self): """Filename to save kernel stderr output.""" stderr_file = None if self.connection_file is not None: stderr_file = self.kernel_id + '.stderr' if self.stderr_dir is not None: stderr_file = osp.join(self.stderr_dir, stderr_file) else: try: if not osp.isdir(TEMPDIR): os.makedirs(TEMPDIR) stderr_file = osp.join(TEMPDIR, stderr_file) except (IOError, OSError): stderr_file = None return stderr_file def configure_shellwidget(self, give_focus=True): """Configure shellwidget after kernel is started""" if give_focus: self.get_control().setFocus() # Set exit callback self.shellwidget.set_exit_callback() # To save history self.shellwidget.executing.connect(self.add_to_history) # For Mayavi to run correctly self.shellwidget.executing.connect( self.shellwidget.set_backend_for_mayavi) # To update history after execution self.shellwidget.executed.connect(self.update_history) # To update the Variable Explorer after execution self.shellwidget.executed.connect( self.shellwidget.refresh_namespacebrowser) # To enable the stop button when executing a process self.shellwidget.executing.connect(self.enable_stop_button) # To disable the stop button after execution stopped self.shellwidget.executed.connect(self.disable_stop_button) # To show kernel restarted/died messages self.shellwidget.sig_kernel_restarted.connect( self.kernel_restarted_message) # To correctly change Matplotlib backend interactively self.shellwidget.executing.connect( self.shellwidget.change_mpl_backend) # To show env and sys.path contents self.shellwidget.sig_show_syspath.connect(self.show_syspath) self.shellwidget.sig_show_env.connect(self.show_env) # To sync with working directory toolbar self.shellwidget.executed.connect(self.shellwidget.get_cwd) # To apply style if not create_qss_style(self.shellwidget.syntax_style)[1]: self.shellwidget.silent_execute("%colors linux") else: self.shellwidget.silent_execute("%colors lightbg") # To hide the loading page self.shellwidget.sig_prompt_ready.connect(self._hide_loading_page) # Show possible errors when setting Matplotlib backend self.shellwidget.sig_prompt_ready.connect( self._show_mpl_backend_errors) def enable_stop_button(self): self.stop_button.setEnabled(True) def disable_stop_button(self): self.stop_button.setDisabled(True) @Slot() def stop_button_click_handler(self): """Method to handle what to do when the stop button is pressed""" self.stop_button.setDisabled(True) # Interrupt computations or stop debugging if not self.shellwidget._reading: self.interrupt_kernel() else: self.shellwidget.write_to_stdin('exit') def show_kernel_error(self, error): """Show kernel initialization errors in infowidget.""" # Replace end of line chars with
    eol = sourcecode.get_eol_chars(error) if eol: error = error.replace(eol, '
    ') # Don't break lines in hyphens # From http://stackoverflow.com/q/7691569/438386 error = error.replace('-', '‑') # Create error page message = _("An error ocurred while starting the kernel") kernel_error_template = Template(KERNEL_ERROR) page = kernel_error_template.substitute(css_path=CSS_PATH, message=message, error=error) # Show error self.infowidget.setHtml(page) self.shellwidget.hide() self.infowidget.show() def get_name(self): """Return client name""" if self.given_name is None: # Name according to host if self.hostname is None: name = _("Console") else: name = self.hostname # Adding id to name client_id = self.id_['int_id'] + u'/' + self.id_['str_id'] name = name + u' ' + client_id else: name = self.given_name + u'/' + self.id_['str_id'] return name def get_control(self): """Return the text widget (or similar) to give focus to""" # page_control is the widget used for paging page_control = self.shellwidget._page_control if page_control and page_control.isVisible(): return page_control else: return self.shellwidget._control def get_kernel(self): """Get kernel associated with this client""" return self.shellwidget.kernel_manager def get_options_menu(self): """Return options menu""" reset_action = create_action(self, _("Remove all variables"), icon=ima.icon('editdelete'), triggered=self.reset_namespace) self.show_time_action = create_action(self, _("Show elapsed time"), toggled=self.set_elapsed_time_visible) env_action = create_action( self, _("Show environment variables"), icon=ima.icon('environ'), triggered=self.shellwidget.get_env ) syspath_action = create_action( self, _("Show sys.path contents"), icon=ima.icon('syspath'), triggered=self.shellwidget.get_syspath ) self.show_time_action.setChecked(self.show_elapsed_time) additional_actions = [reset_action, MENU_SEPARATOR, env_action, syspath_action, self.show_time_action] if self.menu_actions is not None: return self.menu_actions + additional_actions else: return additional_actions def get_toolbar_buttons(self): """Return toolbar buttons list.""" buttons = [] # Code to add the stop button if self.stop_button is None: self.stop_button = create_toolbutton( self, text=_("Stop"), icon=self.stop_icon, tip=_("Stop the current command")) self.disable_stop_button() # set click event handler self.stop_button.clicked.connect(self.stop_button_click_handler) if self.stop_button is not None: buttons.append(self.stop_button) # Reset namespace button if self.reset_button is None: self.reset_button = create_toolbutton( self, text=_("Remove"), icon=ima.icon('editdelete'), tip=_("Remove all variables"), triggered=self.reset_namespace) if self.reset_button is not None: buttons.append(self.reset_button) if self.options_button is None: options = self.get_options_menu() if options: self.options_button = create_toolbutton(self, text=_('Options'), icon=ima.icon('tooloptions')) self.options_button.setPopupMode(QToolButton.InstantPopup) menu = QMenu(self) add_actions(menu, options) self.options_button.setMenu(menu) if self.options_button is not None: buttons.append(self.options_button) return buttons def add_actions_to_context_menu(self, menu): """Add actions to IPython widget context menu""" inspect_action = create_action(self, _("Inspect current object"), QKeySequence(get_shortcut('console', 'inspect current object')), icon=ima.icon('MessageBoxInformation'), triggered=self.inspect_object) clear_line_action = create_action(self, _("Clear line or block"), QKeySequence(get_shortcut( 'console', 'clear line')), triggered=self.clear_line) reset_namespace_action = create_action(self, _("Remove all variables"), QKeySequence(get_shortcut( 'ipython_console', 'reset namespace')), icon=ima.icon('editdelete'), triggered=self.reset_namespace) clear_console_action = create_action(self, _("Clear console"), QKeySequence(get_shortcut('console', 'clear shell')), triggered=self.clear_console) quit_action = create_action(self, _("&Quit"), icon=ima.icon('exit'), triggered=self.exit_callback) add_actions(menu, (None, inspect_action, clear_line_action, clear_console_action, reset_namespace_action, None, quit_action)) return menu def set_font(self, font): """Set IPython widget's font""" self.shellwidget._control.setFont(font) self.shellwidget.font = font def set_infowidget_font(self): """Set font for infowidget""" font = get_font(option='rich_font') self.infowidget.set_font(font) def set_color_scheme(self, color_scheme): """Set IPython color scheme.""" self.shellwidget.set_color_scheme(color_scheme) def shutdown(self): """Shutdown kernel""" if self.get_kernel() is not None and not self.slave: self.shellwidget.kernel_manager.shutdown_kernel() if self.shellwidget.kernel_client is not None: background(self.shellwidget.kernel_client.stop_channels) def interrupt_kernel(self): """Interrupt the associanted Spyder kernel if it's running""" self.shellwidget.request_interrupt_kernel() @Slot() def restart_kernel(self): """ Restart the associanted kernel Took this code from the qtconsole project Licensed under the BSD license """ sw = self.shellwidget message = _('Are you sure you want to restart the kernel?') buttons = QMessageBox.Yes | QMessageBox.No result = QMessageBox.question(self, _('Restart kernel?'), message, buttons) if result == QMessageBox.Yes: if sw.kernel_manager: if self.infowidget.isVisible(): self.infowidget.hide() sw.show() try: sw.kernel_manager.restart_kernel() except RuntimeError as e: sw._append_plain_text( _('Error restarting kernel: %s\n') % e, before_prompt=True ) else: sw.reset(clear=True) sw._append_html(_("
    Restarting kernel...\n

    "), before_prompt=False) else: sw._append_plain_text( _('Cannot restart a kernel not started by Spyder\n'), before_prompt=True ) @Slot(str) def kernel_restarted_message(self, msg): """Show kernel restarted/died messages.""" try: stderr = codecs.open(self.stderr_file, 'r', encoding='utf-8').read() except UnicodeDecodeError: # This is needed since the stderr file could be encoded # in something different to utf-8. # See issue 4191 try: stderr = self._read_stderr() except: stderr = None except (OSError, IOError): stderr = None if stderr: self.show_kernel_error('%s' % stderr) else: self.shellwidget._append_html("
    %s

    " % msg, before_prompt=False) @Slot() def inspect_object(self): """Show how to inspect an object with our Help plugin""" self.shellwidget._control.inspect_current_object() @Slot() def clear_line(self): """Clear a console line""" self.shellwidget._keyboard_quit() @Slot() def clear_console(self): """Clear the whole console""" self.shellwidget.clear_console() @Slot() def reset_namespace(self): """Resets the namespace by removing all names defined by the user""" self.shellwidget.reset_namespace(warning=self.reset_warning, message=True) def update_history(self): self.history = self.shellwidget._history @Slot(object) def show_syspath(self, syspath): """Show sys.path contents.""" if syspath is not None: editor = CollectionsEditor() editor.setup(syspath, title="sys.path contents", readonly=True, width=600, icon=ima.icon('syspath')) self.dialog_manager.show(editor) else: return @Slot(object) def show_env(self, env): """Show environment variables.""" self.dialog_manager.show(RemoteEnvDialog(env)) def create_time_label(self): """Create elapsed time label widget (if necessary) and return it""" if self.time_label is None: self.time_label = QLabel() return self.time_label def show_time(self, end=False): """Text to show in time_label.""" if self.time_label is None: return elapsed_time = time() - self.t0 if elapsed_time > 24 * 3600: # More than a day...! fmt = "%d %H:%M:%S" else: fmt = "%H:%M:%S" if end: color = "#AAAAAA" else: color = "#AA6655" text = "%s" \ "" % (color, strftime(fmt, gmtime(elapsed_time))) self.time_label.setText(text) def update_time_label_visibility(self): """Update elapsed time visibility.""" self.time_label.setVisible(self.show_elapsed_time) @Slot(bool) def set_elapsed_time_visible(self, state): """Slot to show/hide elapsed time label.""" self.show_elapsed_time = state if self.time_label is not None: self.time_label.setVisible(state) #------ Private API ------------------------------------------------------- def _create_loading_page(self): """Create html page to show while the kernel is starting""" loading_template = Template(LOADING) loading_img = get_image_path('loading_sprites.png') if os.name == 'nt': loading_img = loading_img.replace('\\', '/') message = _("Connecting to kernel...") page = loading_template.substitute(css_path=CSS_PATH, loading_img=loading_img, message=message) return page def _show_loading_page(self): """Show animation while the kernel is loading.""" self.shellwidget.hide() self.infowidget.show() self.infowidget.setHtml(self.loading_page, QUrl.fromLocalFile(CSS_PATH)) def _hide_loading_page(self): """Hide animation shown while the kernel is loading.""" self.infowidget.hide() self.shellwidget.show() self.infowidget.setHtml(BLANK) self.shellwidget.sig_prompt_ready.disconnect(self._hide_loading_page) def _read_stderr(self): """Read the stderr file of the kernel.""" stderr_text = open(self.stderr_file, 'rb').read() encoding = get_coding(stderr_text) stderr = to_text_string(stderr_text, encoding) return stderr def _show_mpl_backend_errors(self): """ Show possible errors when setting the selected Matplotlib backend. """ if not self.external_kernel: self.shellwidget.silent_execute( "get_ipython().kernel._show_mpl_backend_errors()") self.shellwidget.sig_prompt_ready.disconnect( self._show_mpl_backend_errors) spyder-3.2.6/spyder/widgets/ipythonconsole/namespacebrowser.py0000664000175000017500000002157413224121062025567 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Widget that handle communications between the IPython Console and the Variable Explorer """ from time import time from qtpy.QtCore import QEventLoop from qtpy.QtWidgets import QMessageBox import cloudpickle from qtconsole.rich_jupyter_widget import RichJupyterWidget from spyder.config.base import _, debug_print from spyder.py3compat import PY2, to_text_string class NamepaceBrowserWidget(RichJupyterWidget): """ Widget with the necessary attributes and methods to handle communications between the IPython Console and the Variable Explorer """ # Reference to the nsb widget connected to this client namespacebrowser = None # To save the replies of kernel method executions (except # getting values of variables) _kernel_methods = {} # To save values and messages returned by the kernel _kernel_value = None _kernel_is_starting = True # --- Public API -------------------------------------------------- def set_namespacebrowser(self, namespacebrowser): """Set namespace browser widget""" self.namespacebrowser = namespacebrowser self.configure_namespacebrowser() def configure_namespacebrowser(self): """Configure associated namespace browser widget""" # Update namespace view self.sig_namespace_view.connect(lambda data: self.namespacebrowser.process_remote_view(data)) # Update properties of variables self.sig_var_properties.connect(lambda data: self.namespacebrowser.set_var_properties(data)) def refresh_namespacebrowser(self): """Refresh namespace browser""" if self.namespacebrowser: self.silent_exec_method( 'get_ipython().kernel.get_namespace_view()') self.silent_exec_method( 'get_ipython().kernel.get_var_properties()') def set_namespace_view_settings(self): """Set the namespace view settings""" settings = to_text_string(self.namespacebrowser.get_view_settings()) code = u"get_ipython().kernel.namespace_view_settings = %s" % settings self.silent_execute(code) def get_value(self, name): """Ask kernel for a value""" code = u"get_ipython().kernel.get_value('%s')" % name if self._reading: method = self.kernel_client.input code = u'!' + code else: method = self.silent_execute # Wait until the kernel returns the value wait_loop = QEventLoop() self.sig_got_reply.connect(wait_loop.quit) method(code) wait_loop.exec_() # Remove loop connection and loop self.sig_got_reply.disconnect(wait_loop.quit) wait_loop = None # Handle exceptions if self._kernel_value is None: if self._kernel_reply: msg = self._kernel_reply[:] self._kernel_reply = None raise ValueError(msg) return self._kernel_value def set_value(self, name, value): """Set value for a variable""" value = to_text_string(value) code = u"get_ipython().kernel.set_value('%s', %s, %s)" % (name, value, PY2) if self._reading: self.kernel_client.input(u'!' + code) else: self.silent_execute(code) def remove_value(self, name): """Remove a variable""" code = u"get_ipython().kernel.remove_value('%s')" % name if self._reading: self.kernel_client.input(u'!' + code) else: self.silent_execute(code) def copy_value(self, orig_name, new_name): """Copy a variable""" code = u"get_ipython().kernel.copy_value('%s', '%s')" % (orig_name, new_name) if self._reading: self.kernel_client.input(u'!' + code) else: self.silent_execute(code) def load_data(self, filename, ext): if self._reading: message = _("Loading this kind of data while debugging is not " "supported.") QMessageBox.warning(self, _("Warning"), message) return # Wait until the kernel tries to load the file wait_loop = QEventLoop() self.sig_got_reply.connect(wait_loop.quit) self.silent_exec_method( r"get_ipython().kernel.load_data('%s', '%s')" % (filename, ext)) wait_loop.exec_() # Remove loop connection and loop self.sig_got_reply.disconnect(wait_loop.quit) wait_loop = None return self._kernel_reply def save_namespace(self, filename): if self._reading: message = _("Saving data while debugging is not supported.") QMessageBox.warning(self, _("Warning"), message) return # Wait until the kernel tries to save the file wait_loop = QEventLoop() self.sig_got_reply.connect(wait_loop.quit) self.silent_exec_method(r"get_ipython().kernel.save_namespace('%s')" % filename) wait_loop.exec_() # Remove loop connection and loop self.sig_got_reply.disconnect(wait_loop.quit) wait_loop = None return self._kernel_reply # ---- Private API (defined by us) ------------------------------ def _handle_spyder_msg(self, msg): """ Handle internal spyder messages """ spyder_msg_type = msg['content'].get('spyder_msg_type') if spyder_msg_type == 'data': # Deserialize data try: if PY2: value = cloudpickle.loads(msg['buffers'][0]) else: value = cloudpickle.loads(bytes(msg['buffers'][0])) except Exception as msg: self._kernel_value = None self._kernel_reply = repr(msg) else: self._kernel_value = value self.sig_got_reply.emit() return elif spyder_msg_type == 'pdb_state': pdb_state = msg['content']['pdb_state'] if pdb_state is not None and isinstance(pdb_state, dict): self.refresh_from_pdb(pdb_state) elif spyder_msg_type == 'pdb_continue': # Run Pdb continue to get to the first breakpoint # Fixes 2034 self.write_to_stdin('continue') else: debug_print("No such spyder message type: %s" % spyder_msg_type) # ---- Private API (overrode by us) ---------------------------- def _handle_execute_reply(self, msg): """ Reimplemented to handle communications between Spyder and the kernel """ msg_id = msg['parent_header']['msg_id'] info = self._request_info['execute'].get(msg_id) # unset reading flag, because if execute finished, raw_input can't # still be pending. self._reading = False # Refresh namespacebrowser after the kernel starts running exec_count = msg['content'].get('execution_count', '') if exec_count == 0 and self._kernel_is_starting: if self.namespacebrowser is not None: self.set_namespace_view_settings() self.refresh_namespacebrowser() self._kernel_is_starting = False self.ipyclient.t0 = time() # Handle silent execution of kernel methods if info and info.kind == 'silent_exec_method' and not self._hidden: self.handle_exec_method(msg) self._request_info['execute'].pop(msg_id) else: super(NamepaceBrowserWidget, self)._handle_execute_reply(msg) def _handle_status(self, msg): """ Reimplemented to refresh the namespacebrowser after kernel restarts """ state = msg['content'].get('execution_state', '') msg_type = msg['parent_header'].get('msg_type', '') if state == 'starting': # This is needed to show the time a kernel # has been alive in each console. self.ipyclient.t0 = time() self.ipyclient.timer.timeout.connect(self.ipyclient.show_time) self.ipyclient.timer.start(1000) # This handles restarts when the kernel dies # unexpectedly if not self._kernel_is_starting: self._kernel_is_starting = True elif state == 'idle' and msg_type == 'shutdown_request': # This handles restarts asked by the user if self.namespacebrowser is not None: self.set_namespace_view_settings() self.refresh_namespacebrowser() self.ipyclient.t0 = time() else: super(NamepaceBrowserWidget, self)._handle_status(msg) spyder-3.2.6/spyder/widgets/ipythonconsole/debugging.py0000664000175000017500000000762413224121062024162 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Widget that handles communications between a console in debugging mode and Spyder """ import ast from qtpy.QtCore import Qt from qtconsole.rich_jupyter_widget import RichJupyterWidget class DebuggingWidget(RichJupyterWidget): """ Widget with the necessary attributes and methods to handle communications between a console in debugging mode and Spyder """ # --- Public API -------------------------------------------------- def write_to_stdin(self, line): """Send raw characters to the IPython kernel through stdin""" self.kernel_client.input(line) def set_spyder_breakpoints(self): """Set Spyder breakpoints into a debugging session""" if self._reading: self.kernel_client.input( "!get_ipython().kernel._set_spyder_breakpoints()") def dbg_exec_magic(self, magic, args=''): """Run an IPython magic while debugging.""" code = "!get_ipython().kernel.shell.run_line_magic('{}', '{}')".format( magic, args) self.kernel_client.input(code) def refresh_from_pdb(self, pdb_state): """ Refresh Variable Explorer and Editor from a Pdb session, after running any pdb command. See publish_pdb_state in utils/ipython/spyder_kernel.py and notify_spyder in utils/site/sitecustomize.py and """ if 'step' in pdb_state and 'fname' in pdb_state['step']: fname = pdb_state['step']['fname'] lineno = pdb_state['step']['lineno'] self.sig_pdb_step.emit(fname, lineno) if 'namespace_view' in pdb_state: self.sig_namespace_view.emit(ast.literal_eval( pdb_state['namespace_view'])) if 'var_properties' in pdb_state: self.sig_var_properties.emit(ast.literal_eval( pdb_state['var_properties'])) # ---- Private API (overrode by us) ---------------------------- def _handle_input_request(self, msg): """Save history and add a %plot magic.""" if self._hidden: raise RuntimeError('Request for raw input during hidden execution.') # Make sure that all output from the SUB channel has been processed # before entering readline mode. self.kernel_client.iopub_channel.flush() def callback(line): # Save history to browse it later self._control.history.append(line) # This is the Spyder addition: add a %plot magic to display # plots while debugging if line.startswith('%plot '): line = line.split()[-1] code = "__spy_code__ = get_ipython().run_cell('%s')" % line self.kernel_client.input(code) else: self.kernel_client.input(line) if self._reading: self._reading = False self._readline(msg['content']['prompt'], callback=callback, password=msg['content']['password']) def _event_filter_console_keypress(self, event): """Handle Key_Up/Key_Down while debugging.""" key = event.key() if self._reading: self._control.current_prompt_pos = self._prompt_pos if key == Qt.Key_Up: self._control.browse_history(backward=True) return True elif key == Qt.Key_Down: self._control.browse_history(backward=False) return True elif key in (Qt.Key_Return, Qt.Key_Enter): self._control.reset_search_pos() return super(DebuggingWidget, self)._event_filter_console_keypress(event) else: return super(DebuggingWidget, self)._event_filter_console_keypress(event) spyder-3.2.6/spyder/widgets/ipythonconsole/help.py0000664000175000017500000001061713211142273023156 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Widget that handles communications between the IPython Console and the Help plugin """ from __future__ import absolute_import import re from qtpy.QtCore import QEventLoop from qtconsole.ansi_code_processor import ANSI_OR_SPECIAL_PATTERN from qtconsole.rich_jupyter_widget import RichJupyterWidget from spyder.config.base import _ from spyder.py3compat import PY3 from spyder.utils.dochelpers import getargspecfromtext, getsignaturefromtext class HelpWidget(RichJupyterWidget): """ Widget with the necessary attributes and methods to handle communications between the IPython Console and the Help plugin """ def clean_invalid_var_chars(self, var): """ Replace invalid variable chars in a string by underscores Taken from http://stackoverflow.com/a/3305731/438386 """ return re.sub('\W|^(?=\d)', '_', var) def get_signature(self, content): """Get signature from inspect reply content""" data = content.get('data', {}) text = data.get('text/plain', '') if text: text = ANSI_OR_SPECIAL_PATTERN.sub('', text) self._control.current_prompt_pos = self._prompt_pos line = self._control.get_current_line_to_cursor() name = line[:-1].split('(')[-1] # Take last token after a ( name = name.split('.')[-1] # Then take last token after a . # Clean name from invalid chars try: name = self.clean_invalid_var_chars(name).split('_')[-1] except: pass argspec = getargspecfromtext(text) if argspec: # This covers cases like np.abs, whose docstring is # the same as np.absolute and because of that a proper # signature can't be obtained correctly signature = name + argspec else: signature = getsignaturefromtext(text, name) return signature else: return '' def is_defined(self, objtxt, force_import=False): """Return True if object is defined""" if self._reading: return wait_loop = QEventLoop() self.sig_got_reply.connect(wait_loop.quit) self.silent_exec_method( "get_ipython().kernel.is_defined('%s', force_import=%s)" % (objtxt, force_import)) wait_loop.exec_() # Remove loop connection and loop self.sig_got_reply.disconnect(wait_loop.quit) wait_loop = None return self._kernel_reply def get_doc(self, objtxt): """Get object documentation dictionary""" if self._reading: return wait_loop = QEventLoop() self.sig_got_reply.connect(wait_loop.quit) self.silent_exec_method("get_ipython().kernel.get_doc('%s')" % objtxt) wait_loop.exec_() # Remove loop connection and loop self.sig_got_reply.disconnect(wait_loop.quit) wait_loop = None return self._kernel_reply def get_source(self, objtxt): """Get object source""" if self._reading: return wait_loop = QEventLoop() self.sig_got_reply.connect(wait_loop.quit) self.silent_exec_method("get_ipython().kernel.get_source('%s')" % objtxt) wait_loop.exec_() # Remove loop connection and loop self.sig_got_reply.disconnect(wait_loop.quit) wait_loop = None return self._kernel_reply #---- Private methods (overrode by us) --------------------------------- def _handle_inspect_reply(self, rep): """ Reimplement call tips to only show signatures, using the same style from our Editor and External Console too """ cursor = self._get_cursor() info = self._request_info.get('call_tip') if info and info.id == rep['parent_header']['msg_id'] and \ info.pos == cursor.position(): content = rep['content'] if content.get('status') == 'ok' and content.get('found', False): signature = self.get_signature(content) if signature: self._control.show_calltip(_("Arguments"), signature, signature=True, color='#2D62FF') spyder-3.2.6/spyder/widgets/ipythonconsole/shell.py0000664000175000017500000004634313224721400023341 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Shell Widget for the IPython Console """ import ast import os import uuid from qtpy.QtCore import Signal from qtpy.QtWidgets import QMessageBox from spyder.config.main import CONF from spyder.config.base import _ from spyder.config.gui import config_shortcut from spyder.py3compat import PY2, to_text_string from spyder.utils import encoding from spyder.utils import programs from spyder.utils import syntaxhighlighters as sh from spyder.utils.ipython.style import create_qss_style, create_style_class from spyder.widgets.helperwidgets import MessageCheckBox from spyder.widgets.ipythonconsole import (ControlWidget, DebuggingWidget, HelpWidget, NamepaceBrowserWidget, PageControlWidget) class ShellWidget(NamepaceBrowserWidget, HelpWidget, DebuggingWidget): """ Shell widget for the IPython Console This is the widget in charge of executing code """ # NOTE: Signals can't be assigned separately to each widget # That's why we define all needed signals here. # For NamepaceBrowserWidget sig_namespace_view = Signal(object) sig_var_properties = Signal(object) sig_show_syspath = Signal(object) sig_show_env = Signal(object) # For DebuggingWidget sig_pdb_step = Signal(str, int) # For ShellWidget focus_changed = Signal() new_client = Signal() sig_got_reply = Signal() sig_is_spykernel = Signal(object) sig_kernel_restarted = Signal(str) sig_prompt_ready = Signal() # For global working directory sig_change_cwd = Signal(str) def __init__(self, ipyclient, additional_options, interpreter_versions, external_kernel, *args, **kw): # To override the Qt widget used by RichJupyterWidget self.custom_control = ControlWidget self.custom_page_control = PageControlWidget super(ShellWidget, self).__init__(*args, **kw) self.ipyclient = ipyclient self.additional_options = additional_options self.interpreter_versions = interpreter_versions self.external_kernel = external_kernel self._cwd = '' # Keyboard shortcuts self.shortcuts = self.create_shortcuts() # To save kernel replies in silent execution self._kernel_reply = None # Set the color of the matched parentheses here since the qtconsole # uses a hard-coded value that is not modified when the color scheme is # set in the qtconsole constructor. See issue #4806. self.set_bracket_matcher_color_scheme(self.syntax_style) #---- Public API ---------------------------------------------------------- def set_exit_callback(self): """Set exit callback for this shell.""" self.exit_requested.connect(self.ipyclient.exit_callback) def is_running(self): if self.kernel_client is not None and \ self.kernel_client.channels_running: return True else: return False def is_spyder_kernel(self): """Determine if the kernel is from Spyder.""" code = u"getattr(get_ipython().kernel, 'set_value', False)" if self._reading: return else: self.silent_exec_method(code) def set_cwd(self, dirname): """Set shell current working directory.""" # Replace single for double backslashes on Windows if os.name == 'nt': dirname = dirname.replace(u"\\", u"\\\\") if not self.external_kernel: code = u"get_ipython().kernel.set_cwd(u'{}')".format(dirname) if self._reading: self.kernel_client.input(u'!' + code) else: self.silent_execute(code) self._cwd = dirname def get_cwd(self): """Update current working directory. Retrieve the cwd and emit a signal connected to the working directory widget. (see: handle_exec_method()) """ code = u"get_ipython().kernel.get_cwd()" if self._reading: return else: self.silent_exec_method(code) def set_bracket_matcher_color_scheme(self, color_scheme): """Set color scheme for matched parentheses.""" bsh = sh.BaseSH(parent=self, color_scheme=color_scheme) mpcolor = bsh.get_matched_p_color() self._bracket_matcher.format.setBackground(mpcolor) def set_color_scheme(self, color_scheme): """Set color scheme of the shell.""" self.set_bracket_matcher_color_scheme(color_scheme) self.style_sheet, dark_color = create_qss_style(color_scheme) self.syntax_style = color_scheme self._style_sheet_changed() self._syntax_style_changed() self.reset(clear=True) if not dark_color: self.silent_execute("%colors linux") else: self.silent_execute("%colors lightbg") def get_syspath(self): """Ask the kernel for sys.path contents.""" code = u"get_ipython().kernel.get_syspath()" if self._reading: return else: self.silent_exec_method(code) def get_env(self): """Ask the kernel for environment variables.""" code = u"get_ipython().kernel.get_env()" if self._reading: return else: self.silent_exec_method(code) # --- To handle the banner def long_banner(self): """Banner for IPython widgets with pylab message""" # Default banner try: from IPython.core.usage import quick_guide except Exception: quick_guide = '' banner_parts = [ 'Python %s\n' % self.interpreter_versions['python_version'], 'Type "copyright", "credits" or "license" for more information.\n\n', 'IPython %s -- An enhanced Interactive Python.\n' % \ self.interpreter_versions['ipython_version'], quick_guide ] banner = ''.join(banner_parts) # Pylab additions pylab_o = self.additional_options['pylab'] autoload_pylab_o = self.additional_options['autoload_pylab'] mpl_installed = programs.is_module_installed('matplotlib') if mpl_installed and (pylab_o and autoload_pylab_o): pylab_message = ("\nPopulating the interactive namespace from " "numpy and matplotlib\n") banner = banner + pylab_message # Sympy additions sympy_o = self.additional_options['sympy'] if sympy_o: lines = """ These commands were executed: >>> from __future__ import division >>> from sympy import * >>> x, y, z, t = symbols('x y z t') >>> k, m, n = symbols('k m n', integer=True) >>> f, g, h = symbols('f g h', cls=Function) """ banner = banner + lines if (pylab_o and sympy_o): lines = """ Warning: pylab (numpy and matplotlib) and symbolic math (sympy) are both enabled at the same time. Some pylab functions are going to be overrided by the sympy module (e.g. plot) """ banner = banner + lines return banner def short_banner(self): """Short banner with Python and QtConsole versions""" banner = 'Python %s -- IPython %s' % ( self.interpreter_versions['python_version'], self.interpreter_versions['ipython_version']) return banner # --- To define additional shortcuts def clear_console(self): if self._reading: self.dbg_exec_magic('clear') else: self.execute("%clear") def _reset_namespace(self): warning = CONF.get('ipython_console', 'show_reset_namespace_warning') self.reset_namespace(silent=True, warning=warning) def reset_namespace(self, warning=False, silent=True, message=False): """Reset the namespace by removing all names defined by the user.""" reset_str = _("Remove all variables") warn_str = _("All user-defined variables will be removed. " "Are you sure you want to proceed?") if warning: box = MessageCheckBox(icon=QMessageBox.Warning, parent=self) box.setWindowTitle(reset_str) box.set_checkbox_text(_("Don't show again.")) box.setStandardButtons(QMessageBox.Yes | QMessageBox.No) box.setDefaultButton(QMessageBox.Yes) box.set_checked(False) box.set_check_visible(True) box.setText(warn_str) answer = box.exec_() # Update checkbox based on user interaction CONF.set('ipython_console', 'show_reset_namespace_warning', not box.is_checked()) if answer != QMessageBox.Yes: return try: if self._reading: self.dbg_exec_magic('reset', '-f') else: if silent: if message: self.reset() self._append_html(_("

    Removing all variables..." "\n
    "), before_prompt=False) self.silent_execute("%reset -f") self.refresh_namespacebrowser() else: self.execute("%reset -f") if not self.external_kernel: self.silent_execute( 'get_ipython().kernel.close_all_mpl_figures()') except AttributeError: pass def create_shortcuts(self): """Create shortcuts for ipyconsole.""" inspect = config_shortcut(self._control.inspect_current_object, context='Console', name='Inspect current object', parent=self) clear_console = config_shortcut(self.clear_console, context='Console', name='Clear shell', parent=self) restart_kernel = config_shortcut(self.ipyclient.restart_kernel, context='ipython_console', name='Restart kernel', parent=self) new_tab = config_shortcut(lambda: self.new_client.emit(), context='ipython_console', name='new tab', parent=self) reset_namespace = config_shortcut(lambda: self._reset_namespace(), context='ipython_console', name='reset namespace', parent=self) array_inline = config_shortcut(self._control.enter_array_inline, context='array_builder', name='enter array inline', parent=self) array_table = config_shortcut(self._control.enter_array_table, context='array_builder', name='enter array table', parent=self) clear_line = config_shortcut(self.ipyclient.clear_line, context='console', name='clear line', parent=self) return [inspect, clear_console, restart_kernel, new_tab, reset_namespace, array_inline, array_table, clear_line] # --- To communicate with the kernel def silent_execute(self, code): """Execute code in the kernel without increasing the prompt""" try: self.kernel_client.execute(to_text_string(code), silent=True) except AttributeError: pass def silent_exec_method(self, code): """Silently execute a kernel method and save its reply The methods passed here **don't** involve getting the value of a variable but instead replies that can be handled by ast.literal_eval. To get a value see `get_value` Parameters ---------- code : string Code that contains the kernel method as part of its string See Also -------- handle_exec_method : Method that deals with the reply Note ---- This is based on the _silent_exec_callback method of RichJupyterWidget. Therefore this is licensed BSD """ # Generate uuid, which would be used as an indication of whether or # not the unique request originated from here local_uuid = to_text_string(uuid.uuid1()) code = to_text_string(code) if self.kernel_client is None: return msg_id = self.kernel_client.execute('', silent=True, user_expressions={ local_uuid:code }) self._kernel_methods[local_uuid] = code self._request_info['execute'][msg_id] = self._ExecutionRequest(msg_id, 'silent_exec_method') def handle_exec_method(self, msg): """ Handle data returned by silent executions of kernel methods This is based on the _handle_exec_callback of RichJupyterWidget. Therefore this is licensed BSD. """ user_exp = msg['content'].get('user_expressions') if not user_exp: return for expression in user_exp: if expression in self._kernel_methods: # Process kernel reply method = self._kernel_methods[expression] reply = user_exp[expression] data = reply.get('data') if 'get_namespace_view' in method: if data is not None and 'text/plain' in data: literal = ast.literal_eval(data['text/plain']) view = ast.literal_eval(literal) else: view = None self.sig_namespace_view.emit(view) elif 'get_var_properties' in method: if data is not None and 'text/plain' in data: literal = ast.literal_eval(data['text/plain']) properties = ast.literal_eval(literal) else: properties = None self.sig_var_properties.emit(properties) elif 'get_cwd' in method: if data is not None and 'text/plain' in data: self._cwd = ast.literal_eval(data['text/plain']) if PY2: self._cwd = encoding.to_unicode_from_fs(self._cwd) else: self._cwd = '' self.sig_change_cwd.emit(self._cwd) elif 'get_syspath' in method: if data is not None and 'text/plain' in data: syspath = ast.literal_eval(data['text/plain']) else: syspath = None self.sig_show_syspath.emit(syspath) elif 'get_env' in method: if data is not None and 'text/plain' in data: env = ast.literal_eval(data['text/plain']) else: env = None self.sig_show_env.emit(env) elif 'getattr' in method: if data is not None and 'text/plain' in data: is_spyder_kernel = data['text/plain'] if 'SpyderKernel' in is_spyder_kernel: self.sig_is_spykernel.emit(self) else: if data is not None and 'text/plain' in data: self._kernel_reply = ast.literal_eval(data['text/plain']) else: self._kernel_reply = None self.sig_got_reply.emit() # Remove method after being processed self._kernel_methods.pop(expression) def set_backend_for_mayavi(self, command): """ Mayavi plots require the Qt backend, so we try to detect if one is generated to change backends """ calling_mayavi = False lines = command.splitlines() for l in lines: if not l.startswith('#'): if 'import mayavi' in l or 'from mayavi' in l: calling_mayavi = True break if calling_mayavi: message = _("Changing backend to Qt for Mayavi") self._append_plain_text(message + '\n') self.silent_execute("%gui inline\n%gui qt") def change_mpl_backend(self, command): """ If the user is trying to change Matplotlib backends with %matplotlib, send the same command again to the kernel to correctly change it. Fixes issue 4002 """ if command.startswith('%matplotlib') and \ len(command.splitlines()) == 1: if not 'inline' in command: self.silent_execute(command) #---- Private methods (overrode by us) --------------------------------- def _handle_error(self, msg): """ Reimplemented to reset the prompt if the error comes after the reply """ self._process_execute_error(msg) self._show_interpreter_prompt() def _context_menu_make(self, pos): """Reimplement the IPython context menu""" menu = super(ShellWidget, self)._context_menu_make(pos) return self.ipyclient.add_actions_to_context_menu(menu) def _banner_default(self): """ Reimplement banner creation to let the user decide if he wants a banner or not """ # Don't change banner for external kernels if self.external_kernel: return '' show_banner_o = self.additional_options['show_banner'] if show_banner_o: return self.long_banner() else: return self.short_banner() def _kernel_restarted_message(self, died=True): msg = _("Kernel died, restarting") if died else _("Kernel restarting") self.sig_kernel_restarted.emit(msg) def _syntax_style_changed(self): """Refresh the highlighting with the current syntax style by class.""" if self._highlighter is None: # ignore premature calls return if self.syntax_style: self._highlighter._style = create_style_class(self.syntax_style) self._highlighter._clear_caches() else: self._highlighter.set_style_sheet(self.style_sheet) def _prompt_started_hook(self): """Emit a signal when the prompt is ready.""" if not self._reading: self._highlighter.highlighting_on = True self.sig_prompt_ready.emit() #---- Qt methods ---------------------------------------------------------- def focusInEvent(self, event): """Reimplement Qt method to send focus change notification""" self.focus_changed.emit() return super(ShellWidget, self).focusInEvent(event) def focusOutEvent(self, event): """Reimplement Qt method to send focus change notification""" self.focus_changed.emit() return super(ShellWidget, self).focusOutEvent(event) spyder-3.2.6/spyder/widgets/ipythonconsole/__init__.py0000664000175000017500000000077213026261006023766 0ustar carloscarlos00000000000000# -*- coding:utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Widgets for the IPython Console """ from .control import ControlWidget, PageControlWidget from .debugging import DebuggingWidget from .help import HelpWidget from .namespacebrowser import NamepaceBrowserWidget # ShellWidget contains the other widgets and ClientWidget # contains it from .shell import ShellWidget from .client import ClientWidget spyder-3.2.6/spyder/widgets/ipythonconsole/control.py0000664000175000017500000000756613211142273023717 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Control widgets used by ShellWidget""" from qtpy.QtCore import Qt, Signal from qtpy.QtWidgets import QTextEdit from spyder.utils.qthelpers import restore_keyevent from spyder.widgets.calltip import CallTipWidget from spyder.widgets.mixins import (BaseEditMixin, GetHelpMixin, TracebackLinksMixin, BrowseHistoryMixin) class ControlWidget(TracebackLinksMixin, GetHelpMixin, BrowseHistoryMixin, QTextEdit, BaseEditMixin): """ Subclass of QTextEdit with features from Spyder's mixins to use as the control widget for IPython widgets """ QT_CLASS = QTextEdit visibility_changed = Signal(bool) go_to_error = Signal(str) focus_changed = Signal() def __init__(self, parent=None): QTextEdit.__init__(self, parent) BaseEditMixin.__init__(self) TracebackLinksMixin.__init__(self) GetHelpMixin.__init__(self) BrowseHistoryMixin.__init__(self) self.calltip_widget = CallTipWidget(self, hide_timer_on=False) self.found_results = [] # To not use Spyder calltips obtained through the monitor self.calltips = False def showEvent(self, event): """Reimplement Qt Method""" self.visibility_changed.emit(True) def _key_paren_left(self, text): """ Action for '(' """ self.current_prompt_pos = self.parentWidget()._prompt_pos if self.get_current_line_to_cursor(): last_obj = self.get_last_obj() if last_obj and not last_obj.isdigit(): self.show_object_info(last_obj) self.insert_text(text) def keyPressEvent(self, event): """Reimplement Qt Method - Basic keypress event handler""" event, text, key, ctrl, shift = restore_keyevent(event) if key == Qt.Key_ParenLeft and not self.has_selected_text() \ and self.help_enabled and not self.parent()._reading: self._key_paren_left(text) else: # Let the parent widget handle the key press event QTextEdit.keyPressEvent(self, event) def focusInEvent(self, event): """Reimplement Qt method to send focus change notification""" self.focus_changed.emit() return super(ControlWidget, self).focusInEvent(event) def focusOutEvent(self, event): """Reimplement Qt method to send focus change notification""" self.focus_changed.emit() return super(ControlWidget, self).focusOutEvent(event) class PageControlWidget(QTextEdit, BaseEditMixin): """ Subclass of QTextEdit with features from Spyder's mixins.BaseEditMixin to use as the paging widget for IPython widgets """ QT_CLASS = QTextEdit visibility_changed = Signal(bool) show_find_widget = Signal() focus_changed = Signal() def __init__(self, parent=None): QTextEdit.__init__(self, parent) BaseEditMixin.__init__(self) self.found_results = [] def showEvent(self, event): """Reimplement Qt Method""" self.visibility_changed.emit(True) def keyPressEvent(self, event): """Reimplement Qt Method - Basic keypress event handler""" event, text, key, ctrl, shift = restore_keyevent(event) if key == Qt.Key_Slash and self.isVisible(): self.show_find_widget.emit() def focusInEvent(self, event): """Reimplement Qt method to send focus change notification""" self.focus_changed.emit() return super(PageControlWidget, self).focusInEvent(event) def focusOutEvent(self, event): """Reimplement Qt method to send focus change notification""" self.focus_changed.emit() return super(PageControlWidget, self).focusOutEvent(event) spyder-3.2.6/spyder/widgets/findinfiles.py0000664000175000017500000010464613224740762021464 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Find in files widget""" # pylint: disable=C0103 # pylint: disable=R0903 # pylint: disable=R0911 # pylint: disable=R0201 # Standard library imports from __future__ import with_statement, print_function import fnmatch import os import os.path as osp import re import sys import math import traceback # Third party imports from qtpy.compat import getexistingdirectory from qtpy.QtGui import QAbstractTextDocumentLayout, QTextDocument from qtpy.QtCore import QMutex, QMutexLocker, Qt, QThread, Signal, Slot, QSize from qtpy.QtWidgets import (QHBoxLayout, QLabel, QListWidget, QSizePolicy, QTreeWidgetItem, QVBoxLayout, QWidget, QStyledItemDelegate, QStyleOptionViewItem, QApplication, QStyle, QListWidgetItem) # Local imports from spyder.config.base import _ from spyder.py3compat import to_text_string from spyder.utils import icon_manager as ima from spyder.utils.encoding import is_text_file from spyder.utils.misc import getcwd_or_home from spyder.widgets.comboboxes import PatternComboBox from spyder.widgets.onecolumntree import OneColumnTree from spyder.utils.qthelpers import create_toolbutton, get_icon from spyder.config.gui import get_font from spyder.widgets.waitingspinner import QWaitingSpinner ON = 'on' OFF = 'off' CWD = 0 PROJECT = 1 FILE_PATH = 2 EXTERNAL_PATH = 4 MAX_PATH_LENGTH = 60 MAX_PATH_HISTORY = 15 def truncate_path(text): ellipsis = '...' part_len = (MAX_PATH_LENGTH - len(ellipsis)) / 2.0 left_text = text[:int(math.ceil(part_len))] right_text = text[-int(math.floor(part_len)):] return left_text + ellipsis + right_text class SearchThread(QThread): """Find in files search thread""" sig_finished = Signal(bool) sig_current_file = Signal(str) sig_current_folder = Signal(str) sig_file_match = Signal(tuple, int) sig_out_print = Signal(object) def __init__(self, parent): QThread.__init__(self, parent) self.mutex = QMutex() self.stopped = None self.results = None self.pathlist = None self.total_matches = None self.error_flag = None self.rootpath = None self.python_path = None self.hg_manifest = None self.exclude = None self.texts = None self.text_re = None self.completed = None self.case_sensitive = True self.get_pythonpath_callback = None self.results = {} self.total_matches = 0 self.is_file = False def initialize(self, path, is_file, exclude, texts, text_re, case_sensitive): self.rootpath = path self.python_path = False self.hg_manifest = False self.exclude = re.compile(exclude) self.texts = texts self.text_re = text_re self.is_file = is_file self.stopped = False self.completed = False self.case_sensitive = case_sensitive def run(self): try: self.filenames = [] if self.is_file: self.find_string_in_file(self.rootpath) else: self.find_files_in_path(self.rootpath) except Exception: # Important note: we have to handle unexpected exceptions by # ourselves because they won't be catched by the main thread # (known QThread limitation/bug) traceback.print_exc() self.error_flag = _("Unexpected error: see internal console") self.stop() self.sig_finished.emit(self.completed) def stop(self): with QMutexLocker(self.mutex): self.stopped = True def find_files_in_path(self, path): if self.pathlist is None: self.pathlist = [] self.pathlist.append(path) for path, dirs, files in os.walk(path): with QMutexLocker(self.mutex): if self.stopped: return False try: for d in dirs[:]: dirname = os.path.join(path, d) if re.search(self.exclude, dirname + os.sep): dirs.remove(d) for f in files: filename = os.path.join(path, f) if re.search(self.exclude, filename): continue if is_text_file(filename): self.find_string_in_file(filename) except re.error: self.error_flag = _("invalid regular expression") return False return True def find_string_in_file(self, fname): self.error_flag = False self.sig_current_file.emit(fname) try: for lineno, line in enumerate(open(fname, 'rb')): for text, enc in self.texts: line_search = line if not self.case_sensitive: line_search = line_search.lower() if self.text_re: found = re.search(text, line_search) if found is not None: break else: found = line_search.find(text) if found > -1: break try: line_dec = line.decode(enc) except UnicodeDecodeError: line_dec = line if not self.case_sensitive: line = line.lower() if self.text_re: for match in re.finditer(text, line): self.total_matches += 1 self.sig_file_match.emit((osp.abspath(fname), lineno + 1, match.start(), match.end(), line_dec), self.total_matches) else: found = line.find(text) while found > -1: self.total_matches += 1 self.sig_file_match.emit((osp.abspath(fname), lineno + 1, found, found + len(text), line_dec), self.total_matches) for text, enc in self.texts: found = line.find(text, found + 1) if found > -1: break except IOError as xxx_todo_changeme: (_errno, _strerror) = xxx_todo_changeme.args self.error_flag = _("permission denied errors were encountered") self.completed = True def get_results(self): return self.results, self.pathlist, self.total_matches, self.error_flag class ExternalPathItem(QListWidgetItem): def __init__(self, parent, path): self.path = path QListWidgetItem.__init__(self, self.__repr__(), parent) def __repr__(self): if len(self.path) > MAX_PATH_LENGTH: return truncate_path(self.path) return self.path def __str__(self): return self.__repr__() def __unicode__(self): return self.__repr__() class FindOptions(QWidget): """Find widget with options""" REGEX_INVALID = "background-color:rgb(255, 175, 90);" find = Signal() stop = Signal() def __init__(self, parent, search_text, search_text_regexp, search_path, exclude, exclude_idx, exclude_regexp, supported_encodings, in_python_path, more_options, case_sensitive, external_path_history): QWidget.__init__(self, parent) if search_path is None: search_path = getcwd_or_home() self.path = '' self.project_path = None self.file_path = None self.external_path = None self.external_path_history = external_path_history if not isinstance(search_text, (list, tuple)): search_text = [search_text] if not isinstance(search_path, (list, tuple)): search_path = [search_path] if not isinstance(exclude, (list, tuple)): exclude = [exclude] if not isinstance(external_path_history, (list, tuple)): external_path_history = [external_path_history] self.supported_encodings = supported_encodings # Layout 1 hlayout1 = QHBoxLayout() self.search_text = PatternComboBox(self, search_text, _("Search pattern")) self.edit_regexp = create_toolbutton(self, icon=ima.icon('advanced'), tip=_('Regular expression')) self.case_button = create_toolbutton(self, icon=get_icon("upper_lower.png"), tip=_("Case Sensitive")) self.case_button.setCheckable(True) self.case_button.setChecked(case_sensitive) self.edit_regexp.setCheckable(True) self.edit_regexp.setChecked(search_text_regexp) self.more_widgets = () self.more_options = create_toolbutton(self, toggled=self.toggle_more_options) self.more_options.setCheckable(True) self.more_options.setChecked(more_options) self.ok_button = create_toolbutton(self, text=_("Search"), icon=ima.icon('find'), triggered=lambda: self.find.emit(), tip=_("Start search"), text_beside_icon=True) self.ok_button.clicked.connect(self.update_combos) self.stop_button = create_toolbutton(self, text=_("Stop"), icon=ima.icon('editclear'), triggered=lambda: self.stop.emit(), tip=_("Stop search"), text_beside_icon=True) self.stop_button.setEnabled(False) for widget in [self.search_text, self.edit_regexp, self.case_button, self.ok_button, self.stop_button, self.more_options]: hlayout1.addWidget(widget) # Layout 2 hlayout2 = QHBoxLayout() self.exclude_pattern = PatternComboBox(self, exclude, _("Excluded filenames pattern")) if exclude_idx is not None and exclude_idx >= 0 \ and exclude_idx < self.exclude_pattern.count(): self.exclude_pattern.setCurrentIndex(exclude_idx) self.exclude_regexp = create_toolbutton(self, icon=ima.icon('advanced'), tip=_('Regular expression')) self.exclude_regexp.setCheckable(True) self.exclude_regexp.setChecked(exclude_regexp) exclude_label = QLabel(_("Exclude:")) exclude_label.setBuddy(self.exclude_pattern) for widget in [exclude_label, self.exclude_pattern, self.exclude_regexp]: hlayout2.addWidget(widget) # Layout 3 hlayout3 = QHBoxLayout() search_on_label = QLabel(_("Search in:")) self.path_selection_combo = PatternComboBox(self, exclude, _('Search directory')) self.path_selection_combo.setEditable(False) self.path_selection_contents = QListWidget(self.path_selection_combo) self.path_selection_contents.hide() self.path_selection_combo.setModel( self.path_selection_contents.model()) self.path_selection_contents.addItem(_("Current working directory")) item = self.path_selection_contents.item(0) item.setToolTip(_("Search in all files and " "directories present on the" "current Spyder path")) self.path_selection_contents.addItem(_("Project")) item = self.path_selection_contents.item(1) item.setToolTip(_("Search in all files and " "directories present on the" "current project path " "(If opened)")) item.setFlags(item.flags() & ~Qt.ItemIsEnabled) self.path_selection_contents.addItem(_("File").replace('&', '')) item = self.path_selection_contents.item(2) item.setToolTip(_("Search in current opened file")) self.path_selection_contents.addItem(_("Select other directory")) item = self.path_selection_contents.item(3) item.setToolTip(_("Search in other folder present on the file system")) self.path_selection_combo.insertSeparator(3) self.path_selection_combo.insertSeparator(5) for path in external_path_history: item = ExternalPathItem(None, path) self.path_selection_contents.addItem(item) self.path_selection_combo.currentIndexChanged.connect( self.path_selection_changed) hlayout3.addWidget(search_on_label) hlayout3.addWidget(self.path_selection_combo) self.search_text.valid.connect(lambda valid: self.find.emit()) self.exclude_pattern.valid.connect(lambda valid: self.find.emit()) vlayout = QVBoxLayout() vlayout.setContentsMargins(0, 0, 0, 0) vlayout.addLayout(hlayout1) vlayout.addLayout(hlayout2) vlayout.addLayout(hlayout3) self.more_widgets = (hlayout2,) self.toggle_more_options(more_options) self.setLayout(vlayout) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum) @Slot(bool) def toggle_more_options(self, state): for layout in self.more_widgets: for index in range(layout.count()): if state and self.isVisible() or not state: layout.itemAt(index).widget().setVisible(state) if state: icon = ima.icon('options_less') tip = _('Hide advanced options') else: icon = ima.icon('options_more') tip = _('Show advanced options') self.more_options.setIcon(icon) self.more_options.setToolTip(tip) @Slot() def path_selection_changed(self): idx = self.path_selection_combo.currentIndex() if idx == EXTERNAL_PATH: external_path = self.select_directory() if len(external_path) > 0: item = ExternalPathItem(None, external_path) self.path_selection_contents.addItem(item) total_items = (self.path_selection_combo.count() - MAX_PATH_HISTORY) for i in range(6, total_items): self.path_selection_contents.takeItem(i) self.path_selection_combo.setCurrentIndex( self.path_selection_combo.count() - 1) else: self.path_selection_combo.setCurrentIndex(CWD) elif idx > EXTERNAL_PATH: item = self.path_selection_contents.item(idx) self.external_path = item.path def update_combos(self): self.search_text.lineEdit().returnPressed.emit() self.exclude_pattern.lineEdit().returnPressed.emit() def set_search_text(self, text): if text: self.search_text.add_text(text) self.search_text.lineEdit().selectAll() self.search_text.setFocus() def get_options(self, all=False): # Getting options self.search_text.lineEdit().setStyleSheet("") self.exclude_pattern.lineEdit().setStyleSheet("") utext = to_text_string(self.search_text.currentText()) if not utext: return try: texts = [(utext.encode('utf-8'), 'utf-8')] except UnicodeEncodeError: texts = [] for enc in self.supported_encodings: try: texts.append((utext.encode(enc), enc)) except UnicodeDecodeError: pass text_re = self.edit_regexp.isChecked() exclude = to_text_string(self.exclude_pattern.currentText()) exclude_re = self.exclude_regexp.isChecked() case_sensitive = self.case_button.isChecked() python_path = False if not case_sensitive: texts = [(text[0].lower(), text[1]) for text in texts] file_search = False selection_idx = self.path_selection_combo.currentIndex() if selection_idx == CWD: path = self.path elif selection_idx == PROJECT: path = self.project_path elif selection_idx == FILE_PATH: path = self.file_path file_search = True else: path = self.external_path # Finding text occurrences if not exclude_re: exclude = fnmatch.translate(exclude) else: try: exclude = re.compile(exclude) except Exception: exclude_edit = self.exclude_pattern.lineEdit() exclude_edit.setStyleSheet(self.REGEX_INVALID) return None if text_re: try: texts = [(re.compile(x[0]), x[1]) for x in texts] except Exception: self.search_text.lineEdit().setStyleSheet(self.REGEX_INVALID) return None if all: search_text = [to_text_string(self.search_text.itemText(index)) for index in range(self.search_text.count())] exclude = [to_text_string(self.exclude_pattern.itemText(index)) for index in range(self.exclude_pattern.count())] path_history = [to_text_string( self.path_selection_contents.item(index)) for index in range( 6, self.path_selection_combo.count())] exclude_idx = self.exclude_pattern.currentIndex() more_options = self.more_options.isChecked() return (search_text, text_re, [], exclude, exclude_idx, exclude_re, python_path, more_options, case_sensitive, path_history) else: return (path, file_search, exclude, texts, text_re, case_sensitive) @Slot() def select_directory(self): """Select directory""" self.parent().redirect_stdio.emit(False) directory = getexistingdirectory(self, _("Select directory"), self.path) if directory: directory = to_text_string(osp.abspath(to_text_string(directory))) self.parent().redirect_stdio.emit(True) return directory def set_directory(self, directory): self.path = to_text_string(osp.abspath(to_text_string(directory))) def set_project_path(self, path): self.project_path = to_text_string(osp.abspath(to_text_string(path))) item = self.path_selection_contents.item(PROJECT) item.setFlags(item.flags() | Qt.ItemIsEnabled) def disable_project_search(self): item = self.path_selection_contents.item(PROJECT) item.setFlags(item.flags() & ~Qt.ItemIsEnabled) self.project_path = None def set_file_path(self, path): self.file_path = path def keyPressEvent(self, event): """Reimplemented to handle key events""" ctrl = event.modifiers() & Qt.ControlModifier shift = event.modifiers() & Qt.ShiftModifier if event.key() in (Qt.Key_Enter, Qt.Key_Return): self.find.emit() elif event.key() == Qt.Key_F and ctrl and shift: # Toggle find widgets self.parent().toggle_visibility.emit(not self.isVisible()) else: QWidget.keyPressEvent(self, event) class LineMatchItem(QTreeWidgetItem): def __init__(self, parent, lineno, colno, match): self.lineno = lineno self.colno = colno self.match = match QTreeWidgetItem.__init__(self, parent, [self.__repr__()], QTreeWidgetItem.Type) def __repr__(self): match = to_text_string(self.match).rstrip() font = get_font() _str = to_text_string("{1} ({2}): " "{3}") return _str.format(font.family(), self.lineno, self.colno, match) def __unicode__(self): return self.__repr__() def __str__(self): return self.__repr__() def __lt__(self, x): return self.lineno < x.lineno def __ge__(self, x): return self.lineno >= x.lineno class FileMatchItem(QTreeWidgetItem): def __init__(self, parent, filename, sorting): self.sorting = sorting self.filename = osp.basename(filename) title_format = to_text_string('{0}
    ' '{1}' '') title = (title_format.format(osp.basename(filename), osp.dirname(filename))) QTreeWidgetItem.__init__(self, parent, [title], QTreeWidgetItem.Type) self.setToolTip(0, filename) def __lt__(self, x): if self.sorting['status'] == ON: return self.filename < x.filename else: return False def __ge__(self, x): if self.sorting['status'] == ON: return self.filename >= x.filename else: return False class ItemDelegate(QStyledItemDelegate): def __init__(self, parent): QStyledItemDelegate.__init__(self, parent) def paint(self, painter, option, index): options = QStyleOptionViewItem(option) self.initStyleOption(options, index) style = (QApplication.style() if options.widget is None else options.widget.style()) doc = QTextDocument() doc.setDocumentMargin(0) doc.setHtml(options.text) options.text = "" style.drawControl(QStyle.CE_ItemViewItem, options, painter) ctx = QAbstractTextDocumentLayout.PaintContext() textRect = style.subElementRect(QStyle.SE_ItemViewItemText, options) painter.save() painter.translate(textRect.topLeft()) painter.setClipRect(textRect.translated(-textRect.topLeft())) doc.documentLayout().draw(painter, ctx) painter.restore() def sizeHint(self, option, index): options = QStyleOptionViewItem(option) self.initStyleOption(options, index) doc = QTextDocument() doc.setHtml(options.text) doc.setTextWidth(options.rect.width()) return QSize(doc.idealWidth(), doc.size().height()) class ResultsBrowser(OneColumnTree): def __init__(self, parent): OneColumnTree.__init__(self, parent) self.search_text = None self.results = None self.total_matches = None self.error_flag = None self.completed = None self.sorting = {} self.data = None self.files = None self.set_title('') self.set_sorting(OFF) self.setSortingEnabled(False) self.root_items = None self.sortByColumn(0, Qt.AscendingOrder) self.setItemDelegate(ItemDelegate(self)) self.setUniformRowHeights(False) self.header().sectionClicked.connect(self.sort_section) def activated(self, item): """Double-click event""" itemdata = self.data.get(id(self.currentItem())) if itemdata is not None: filename, lineno, colno = itemdata self.parent().edit_goto.emit(filename, lineno, self.search_text) def set_sorting(self, flag): """Enable result sorting after search is complete.""" self.sorting['status'] = flag self.header().setSectionsClickable(flag == ON) @Slot(int) def sort_section(self, idx): self.setSortingEnabled(True) def clicked(self, item): """Click event""" self.activated(item) def clear_title(self, search_text): self.clear() self.setSortingEnabled(False) self.num_files = 0 self.data = {} self.files = {} self.set_sorting(OFF) self.search_text = search_text title = "'%s' - " % search_text text = _('String not found') self.set_title(title + text) def truncate_result(self, line, start, end): ellipsis = '...' max_line_length = 80 max_num_char_fragment = 40 html_escape_table = { "&": "&", '"': """, "'": "'", ">": ">", "<": "<", } def html_escape(text): """Produce entities within text.""" return "".join(html_escape_table.get(c, c) for c in text) line = to_text_string(line) left, match, right = line[:start], line[start:end], line[end:] if len(line) > max_line_length: offset = (len(line) - len(match)) // 2 left = left.split(' ') num_left_words = len(left) if num_left_words == 1: left = left[0] if len(left) > max_num_char_fragment: left = ellipsis + left[-offset:] left = [left] right = right.split(' ') num_right_words = len(right) if num_right_words == 1: right = right[0] if len(right) > max_num_char_fragment: right = right[:offset] + ellipsis right = [right] left = left[-4:] right = right[:4] if len(left) < num_left_words: left = [ellipsis] + left if len(right) < num_right_words: right = right + [ellipsis] left = ' '.join(left) right = ' '.join(right) if len(left) > max_num_char_fragment: left = ellipsis + left[-30:] if len(right) > max_num_char_fragment: right = right[:30] + ellipsis line_match_format = to_text_string('{0}{1}{2}') left = html_escape(left) right = html_escape(right) match = html_escape(match) trunc_line = line_match_format.format(left, match, right) return trunc_line @Slot(tuple, int) def append_result(self, results, num_matches): """Real-time update of search results""" filename, lineno, colno, match_end, line = results if filename not in self.files: file_item = FileMatchItem(self, filename, self.sorting) file_item.setExpanded(True) self.files[filename] = file_item self.num_files += 1 search_text = self.search_text title = "'%s' - " % search_text nb_files = self.num_files if nb_files == 0: text = _('String not found') else: text_matches = _('matches in') text_files = _('file') if nb_files > 1: text_files += 's' text = "%d %s %d %s" % (num_matches, text_matches, nb_files, text_files) self.set_title(title + text) file_item = self.files[filename] line = self.truncate_result(line, colno, match_end) item = LineMatchItem(file_item, lineno, colno, line) self.data[id(item)] = (filename, lineno, colno) class FileProgressBar(QWidget): """Simple progress spinner with a label""" def __init__(self, parent): QWidget.__init__(self, parent) self.status_text = QLabel(self) self.spinner = QWaitingSpinner(self, centerOnParent=False) self.spinner.setNumberOfLines(12) self.spinner.setInnerRadius(2) layout = QHBoxLayout() layout.addWidget(self.spinner) layout.addWidget(self.status_text) self.setLayout(layout) @Slot(str) def set_label_path(self, path, folder=False): text = truncate_path(path) if not folder: status_str = _(u' Scanning: {0}').format(text) else: status_str = _(u' Searching for files in folder: {0}').format(text) self.status_text.setText(status_str) def reset(self): self.status_text.setText(_(" Searching for files...")) def showEvent(self, event): """Override show event to start waiting spinner.""" QWidget.showEvent(self, event) self.spinner.start() def hideEvent(self, event): """Override hide event to stop waiting spinner.""" QWidget.hideEvent(self, event) self.spinner.stop() class FindInFilesWidget(QWidget): """ Find in files widget """ sig_finished = Signal() def __init__(self, parent, search_text=r"# ?TODO|# ?FIXME|# ?XXX", search_text_regexp=True, search_path=None, exclude=r"\.pyc$|\.orig$|\.hg|\.svn", exclude_idx=None, exclude_regexp=True, supported_encodings=("utf-8", "iso-8859-1", "cp1252"), in_python_path=False, more_options=False, case_sensitive=True, external_path_history=[]): QWidget.__init__(self, parent) self.setWindowTitle(_('Find in files')) self.search_thread = None self.search_path = '' self.get_pythonpath_callback = None self.status_bar = FileProgressBar(self) self.status_bar.hide() self.find_options = FindOptions(self, search_text, search_text_regexp, search_path, exclude, exclude_idx, exclude_regexp, supported_encodings, in_python_path, more_options, case_sensitive, external_path_history) self.find_options.find.connect(self.find) self.find_options.stop.connect(self.stop_and_reset_thread) self.result_browser = ResultsBrowser(self) hlayout = QHBoxLayout() hlayout.addWidget(self.result_browser) layout = QVBoxLayout() left, _x, right, bottom = layout.getContentsMargins() layout.setContentsMargins(left, 0, right, bottom) layout.addWidget(self.find_options) layout.addLayout(hlayout) layout.addWidget(self.status_bar) self.setLayout(layout) def set_search_text(self, text): """Set search pattern""" self.find_options.set_search_text(text) def find(self): """Call the find function""" options = self.find_options.get_options() if options is None: return self.stop_and_reset_thread(ignore_results=True) self.search_thread = SearchThread(self) self.search_thread.get_pythonpath_callback = ( self.get_pythonpath_callback) self.search_thread.sig_finished.connect(self.search_complete) self.search_thread.sig_current_file.connect( lambda x: self.status_bar.set_label_path(x, folder=False) ) self.search_thread.sig_current_folder.connect( lambda x: self.status_bar.set_label_path(x, folder=True) ) self.search_thread.sig_file_match.connect( self.result_browser.append_result ) self.search_thread.sig_out_print.connect( lambda x: sys.stdout.write(str(x) + "\n") ) self.status_bar.reset() self.result_browser.clear_title( self.find_options.search_text.currentText()) self.search_thread.initialize(*options) self.search_thread.start() self.find_options.ok_button.setEnabled(False) self.find_options.stop_button.setEnabled(True) self.status_bar.show() def stop_and_reset_thread(self, ignore_results=False): """Stop current search thread and clean-up""" if self.search_thread is not None: if self.search_thread.isRunning(): if ignore_results: self.search_thread.sig_finished.disconnect( self.search_complete) self.search_thread.stop() self.search_thread.wait() self.search_thread.setParent(None) self.search_thread = None def closing_widget(self): """Perform actions before widget is closed""" self.stop_and_reset_thread(ignore_results=True) def search_complete(self, completed): """Current search thread has finished""" self.result_browser.set_sorting(ON) self.find_options.ok_button.setEnabled(True) self.find_options.stop_button.setEnabled(False) self.status_bar.hide() self.result_browser.expandAll() if self.search_thread is None: return self.sig_finished.emit() found = self.search_thread.get_results() self.stop_and_reset_thread() if found is not None: results, pathlist, nb, error_flag = found self.result_browser.show() def test(): """Run Find in Files widget test""" from spyder.utils.qthelpers import qapplication app = qapplication() widget = FindInFilesWidget(None) widget.resize(640, 480) widget.show() sys.exit(app.exec_()) if __name__ == '__main__': test() spyder-3.2.6/spyder/widgets/editor.py0000664000175000017500000036020713224740762020455 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Editor Widget""" # pylint: disable=C0103 # pylint: disable=R0903 # pylint: disable=R0911 # pylint: disable=R0201 # Local imports from __future__ import print_function import os import os.path as osp import sys from collections import MutableSequence # Third party imports from qtpy import is_pyqt46 from qtpy.compat import getsavefilename from qtpy.QtCore import (QByteArray, QFileInfo, QObject, QPoint, QSize, Qt, QThread, QTimer, Signal, Slot) from qtpy.QtGui import QFont from qtpy.QtWidgets import (QAction, QApplication, QFileDialog, QHBoxLayout, QMainWindow, QMessageBox, QMenu, QSplitter, QVBoxLayout, QWidget, QListWidget, QListWidgetItem) # Local imports from spyder.config.base import _, DEBUG, PYTEST, STDERR, STDOUT from spyder.config.gui import config_shortcut, get_shortcut from spyder.config.utils import (get_edit_filetypes, get_edit_filters, get_filter, is_kde_desktop, is_anaconda) from spyder.py3compat import qbytearray_to_str, to_text_string from spyder.utils import icon_manager as ima from spyder.utils import (codeanalysis, encoding, sourcecode, syntaxhighlighters) from spyder.utils.qthelpers import (add_actions, create_action, create_toolbutton, mimedata2url) from spyder.widgets.editortools import OutlineExplorerWidget from spyder.widgets.fileswitcher import FileSwitcher from spyder.widgets.findreplace import FindReplace from spyder.widgets.sourcecode import codeeditor from spyder.widgets.sourcecode.base import TextEditBaseWidget # analysis:ignore from spyder.widgets.sourcecode.codeeditor import Printer # analysis:ignore from spyder.widgets.sourcecode.codeeditor import get_file_language from spyder.widgets.status import (CursorPositionStatus, EncodingStatus, EOLStatus, ReadWriteStatus) from spyder.widgets.tabs import BaseTabs from spyder.config.main import CONF from spyder.widgets.explorer import show_in_external_file_explorer DEBUG_EDITOR = DEBUG >= 3 class AnalysisThread(QThread): """Analysis thread""" def __init__(self, parent, checker, source_code): super(AnalysisThread, self).__init__(parent) self.checker = checker self.results = None self.source_code = source_code def run(self): """Run analysis""" try: self.results = self.checker(self.source_code) except Exception: if DEBUG_EDITOR: import traceback traceback.print_exc(file=STDERR) class ThreadManager(QObject): """Analysis thread manager""" def __init__(self, parent, max_simultaneous_threads=2): super(ThreadManager, self).__init__(parent) self.max_simultaneous_threads = max_simultaneous_threads self.started_threads = {} self.pending_threads = [] self.end_callbacks = {} def close_threads(self, parent): """Close threads associated to parent_id""" if DEBUG_EDITOR: print("Call to 'close_threads'", file=STDOUT) if parent is None: # Closing all threads self.pending_threads = [] threadlist = [] for threads in list(self.started_threads.values()): threadlist += threads else: parent_id = id(parent) self.pending_threads = [(_th, _id) for (_th, _id) in self.pending_threads if _id != parent_id] threadlist = self.started_threads.get(parent_id, []) for thread in threadlist: if DEBUG_EDITOR: print("Waiting for thread %r to finish" % thread, file=STDOUT) while thread.isRunning(): # We can't terminate thread safely, so we simply wait... QApplication.processEvents() def close_all_threads(self): """Close all threads""" if DEBUG_EDITOR: print("Call to 'close_all_threads'", file=STDOUT) self.close_threads(None) def add_thread(self, checker, end_callback, source_code, parent): """Add thread to queue""" parent_id = id(parent) thread = AnalysisThread(self, checker, source_code) self.end_callbacks[id(thread)] = end_callback self.pending_threads.append((thread, parent_id)) if DEBUG_EDITOR: print("Added thread %r to queue" % thread, file=STDOUT) QTimer.singleShot(50, self.update_queue) def update_queue(self): """Update queue""" started = 0 for parent_id, threadlist in list(self.started_threads.items()): still_running = [] for thread in threadlist: if thread.isFinished(): end_callback = self.end_callbacks.pop(id(thread)) if thread.results is not None: # The thread was executed successfully end_callback(thread.results) thread.setParent(None) thread = None else: still_running.append(thread) started += 1 threadlist = None if still_running: self.started_threads[parent_id] = still_running else: self.started_threads.pop(parent_id) if DEBUG_EDITOR: print("Updating queue:", file=STDOUT) print(" started:", started, file=STDOUT) print(" pending:", len(self.pending_threads), file=STDOUT) if self.pending_threads and started < self.max_simultaneous_threads: thread, parent_id = self.pending_threads.pop(0) thread.finished.connect(self.update_queue) threadlist = self.started_threads.get(parent_id, []) self.started_threads[parent_id] = threadlist+[thread] if DEBUG_EDITOR: print("===>starting:", thread, file=STDOUT) thread.start() class FileInfo(QObject): """File properties""" analysis_results_changed = Signal() todo_results_changed = Signal() save_breakpoints = Signal(str, str) text_changed_at = Signal(str, int) edit_goto = Signal(str, int, str) send_to_help = Signal(str, str, str, str, bool) def __init__(self, filename, encoding, editor, new, threadmanager, introspection_plugin): QObject.__init__(self) self.threadmanager = threadmanager self.filename = filename self.newly_created = new self.default = False # Default untitled file self.encoding = encoding self.editor = editor self.path = [] self.classes = (filename, None, None) self.analysis_results = [] self.todo_results = [] self.lastmodified = QFileInfo(filename).lastModified() self.editor.textChanged.connect(self.text_changed) self.editor.breakpoints_changed.connect(self.breakpoints_changed) self.pyflakes_results = None self.pep8_results = None def text_changed(self): """Editor's text has changed""" self.default = False self.text_changed_at.emit(self.filename, self.editor.get_position('cursor')) def get_source_code(self): """Return associated editor source code""" return to_text_string(self.editor.toPlainText()) def run_code_analysis(self, run_pyflakes, run_pep8): """Run code analysis""" run_pyflakes = run_pyflakes and codeanalysis.is_pyflakes_installed() run_pep8 = run_pep8 and\ codeanalysis.get_checker_executable('pycodestyle') is not None self.pyflakes_results = [] self.pep8_results = [] if self.editor.is_python(): enc = self.encoding.replace('-guessed', '').replace('-bom', '') source_code, enc = encoding.encode(self.get_source_code(), enc) if run_pyflakes: self.pyflakes_results = None if run_pep8: self.pep8_results = None if run_pyflakes: self.threadmanager.add_thread(codeanalysis.check_with_pyflakes, self.pyflakes_analysis_finished, source_code, self) if run_pep8: self.threadmanager.add_thread(codeanalysis.check_with_pep8, self.pep8_analysis_finished, source_code, self) def pyflakes_analysis_finished(self, results): """Pyflakes code analysis thread has finished""" self.pyflakes_results = results if self.pep8_results is not None: self.code_analysis_finished() def pep8_analysis_finished(self, results): """Pep8 code analysis thread has finished""" self.pep8_results = results if self.pyflakes_results is not None: self.code_analysis_finished() def code_analysis_finished(self): """Code analysis thread has finished""" self.set_analysis_results(self.pyflakes_results+self.pep8_results) self.analysis_results_changed.emit() def set_analysis_results(self, results): """Set analysis results and update warning markers in editor""" self.analysis_results = results self.editor.process_code_analysis(results) def cleanup_analysis_results(self): """Clean-up analysis results""" self.analysis_results = [] self.editor.cleanup_code_analysis() def run_todo_finder(self): """Run TODO finder""" if self.editor.is_python(): self.threadmanager.add_thread(codeanalysis.find_tasks, self.todo_finished, self.get_source_code(), self) def todo_finished(self, results): """Code analysis thread has finished""" self.set_todo_results(results) self.todo_results_changed.emit() def set_todo_results(self, results): """Set TODO results and update markers in editor""" self.todo_results = results self.editor.process_todo(results) def cleanup_todo_results(self): """Clean-up TODO finder results""" self.todo_results = [] def breakpoints_changed(self): """Breakpoint list has changed""" breakpoints = self.editor.get_breakpoints() if self.editor.breakpoints != breakpoints: self.editor.breakpoints = breakpoints self.save_breakpoints.emit(self.filename, repr(breakpoints)) class StackHistory(MutableSequence): """Handles editor stack history. Works as a list of numbers corresponding to tab indexes. Internally elements are saved using objects id's. """ def __init__(self, editor): self.history = list() self.id_list = list() self.editor = editor def _update_id_list(self): """Update list of corresponpding ids and tabs.""" self.id_list = [id(self.editor.tabs.widget(_i)) for _i in range(self.editor.tabs.count())] def refresh(self): """Remove editors that are not longer open.""" self._update_id_list() for _id in self.history[:]: if _id not in self.id_list: self.history.remove(_id) def __len__(self): return len(self.history) def __getitem__(self, i): self._update_id_list() try: return self.id_list.index(self.history[i]) except ValueError: self.refresh() raise IndexError def __delitem__(self, i): del self.history[i] def __setitem__(self, i, v): _id = id(self.editor.tabs.widget(v)) self.history[i] = _id def __str__(self): return str(list(self)) def insert(self, i, tab_index): """Insert the widget (at tab index) in the position i (index).""" _id = id(self.editor.tabs.widget(tab_index)) self.history.insert(i, _id) def remove(self, tab_index): """Remove the widget at the corresponding tab_index.""" _id = id(self.editor.tabs.widget(tab_index)) if _id in self.history: self.history.remove(_id) class TabSwitcherWidget(QListWidget): """Show tabs in mru order and change between them.""" def __init__(self, parent, stack_history, tabs): QListWidget.__init__(self, parent) self.setWindowFlags(Qt.SubWindow | Qt.FramelessWindowHint | Qt.Dialog) self.editor = parent self.stack_history = stack_history self.tabs = tabs self.setSelectionMode(QListWidget.SingleSelection) self.itemActivated.connect(self.item_selected) self.id_list = [] self.load_data() size = CONF.get('main', 'completion/size') self.resize(*size) self.set_dialog_position() self.setCurrentRow(0) config_shortcut(lambda: self.select_row(-1), context='Editor', name='Go to previous file', parent=self) config_shortcut(lambda: self.select_row(1), context='Editor', name='Go to next file', parent=self) def load_data(self): """Fill ListWidget with the tabs texts. Add elements in inverse order of stack_history. """ for index in reversed(self.stack_history): text = self.tabs.tabText(index) text = text.replace('&', '') item = QListWidgetItem(ima.icon('TextFileIcon'), text) self.addItem(item) def item_selected(self, item=None): """Change to the selected document and hide this widget.""" if item is None: item = self.currentItem() # stack history is in inverse order try: index = self.stack_history[-(self.currentRow()+1)] except IndexError: pass else: self.editor.set_stack_index(index) self.editor.current_changed(index) self.hide() def select_row(self, steps): """Move selected row a number of steps. Iterates in a cyclic behaviour. """ row = (self.currentRow() + steps) % self.count() self.setCurrentRow(row) def set_dialog_position(self): """Positions the tab switcher in the top-center of the editor.""" left = self.editor.geometry().width()/2 - self.width()/2 top = self.editor.tabs.tabBar().geometry().height() self.move(self.editor.mapToGlobal(QPoint(left, top))) def keyReleaseEvent(self, event): """Reimplement Qt method. Handle "most recent used" tab behavior, When ctrl is released and tab_switcher is visible, tab will be changed. """ if self.isVisible(): qsc = get_shortcut(context='Editor', name='Go to next file') for key in qsc.split('+'): key = key.lower() if ((key == 'ctrl' and event.key() == Qt.Key_Control) or (key == 'alt' and event.key() == Qt.Key_Alt)): self.item_selected() event.accept() def keyPressEvent(self, event): """Reimplement Qt method to allow cyclic behavior.""" if event.key() == Qt.Key_Down: self.select_row(1) elif event.key() == Qt.Key_Up: self.select_row(-1) class EditorStack(QWidget): reset_statusbar = Signal() readonly_changed = Signal(bool) encoding_changed = Signal(str) sig_editor_cursor_position_changed = Signal(int, int) sig_refresh_eol_chars = Signal(str) starting_long_process = Signal(str) ending_long_process = Signal(str) redirect_stdio = Signal(bool) exec_in_extconsole = Signal(str, bool) update_plugin_title = Signal() editor_focus_changed = Signal() zoom_in = Signal() zoom_out = Signal() zoom_reset = Signal() sig_close_file = Signal(str, str) file_saved = Signal(str, str, str) file_renamed_in_data = Signal(str, str, str) create_new_window = Signal() opened_files_list_changed = Signal() analysis_results_changed = Signal() todo_results_changed = Signal() update_code_analysis_actions = Signal() refresh_file_dependent_actions = Signal() refresh_save_all_action = Signal() save_breakpoints = Signal(str, str) text_changed_at = Signal(str, int) current_file_changed = Signal(str ,int) plugin_load = Signal((str,), ()) edit_goto = Signal(str, int, str) split_vertically = Signal() split_horizontally = Signal() sig_new_file = Signal((str,), ()) sig_save_as = Signal() sig_prev_edit_pos = Signal() sig_prev_cursor = Signal() sig_next_cursor = Signal() def __init__(self, parent, actions): QWidget.__init__(self, parent) self.setAttribute(Qt.WA_DeleteOnClose) self.threadmanager = ThreadManager(self) self.newwindow_action = None self.horsplit_action = None self.versplit_action = None self.close_action = None self.__get_split_actions() layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) self.menu = None self.fileswitcher_dlg = None # self.filelist_btn = None # self.previous_btn = None # self.next_btn = None self.tabs = None self.tabs_switcher = None self.stack_history = StackHistory(self) self.setup_editorstack(parent, layout) self.find_widget = None self.data = [] fileswitcher_action = create_action(self, _("File switcher..."), icon=ima.icon('filelist'), triggered=self.open_fileswitcher_dlg) symbolfinder_action = create_action(self, _("Find symbols in file..."), icon=ima.icon('symbol_find'), triggered=self.open_symbolfinder_dlg) copy_to_cb_action = create_action(self, _("Copy path to clipboard"), icon=ima.icon('editcopy'), triggered=lambda: QApplication.clipboard().setText(self.get_current_filename())) close_right = create_action(self, _("Close all to the right"), triggered=self.close_all_right) close_all_but_this = create_action(self, _("Close all but this"), triggered=self.close_all_but_this) if sys.platform == 'darwin': text=_("Show in Finder") else: text= _("Show in external file explorer") external_fileexp_action = create_action(self, text, triggered=self.show_in_external_file_explorer) self.menu_actions = actions + [external_fileexp_action, None, fileswitcher_action, symbolfinder_action, copy_to_cb_action, None, close_right, close_all_but_this] self.outlineexplorer = None self.help = None self.unregister_callback = None self.is_closable = False self.new_action = None self.open_action = None self.save_action = None self.revert_action = None self.tempfile_path = None self.title = _("Editor") self.pyflakes_enabled = True self.pep8_enabled = False self.todolist_enabled = True self.realtime_analysis_enabled = False self.is_analysis_done = False self.linenumbers_enabled = True self.blanks_enabled = False self.edgeline_enabled = True self.edgeline_column = 79 self.codecompletion_auto_enabled = True self.codecompletion_case_enabled = False self.codecompletion_enter_enabled = False self.calltips_enabled = True self.go_to_definition_enabled = True self.close_parentheses_enabled = True self.close_quotes_enabled = True self.add_colons_enabled = True self.auto_unindent_enabled = True self.indent_chars = " "*4 self.tab_stop_width_spaces = 4 self.help_enabled = False self.default_font = None self.wrap_enabled = False self.tabmode_enabled = False self.intelligent_backspace_enabled = True self.highlight_current_line_enabled = False self.highlight_current_cell_enabled = False self.occurrence_highlighting_enabled = True self.occurrence_highlighting_timeout=1500 self.checkeolchars_enabled = True self.always_remove_trailing_spaces = False self.fullpath_sorting_enabled = None self.focus_to_editor = True self.set_fullpath_sorting_enabled(False) self.create_new_file_if_empty = True ccs = 'Spyder' if ccs not in syntaxhighlighters.COLOR_SCHEME_NAMES: ccs = syntaxhighlighters.COLOR_SCHEME_NAMES[0] self.color_scheme = ccs self.introspector = None self.__file_status_flag = False # Real-time code analysis self.analysis_timer = QTimer(self) self.analysis_timer.setSingleShot(True) self.analysis_timer.setInterval(2000) self.analysis_timer.timeout.connect(self.analyze_script) # Accepting drops self.setAcceptDrops(True) # Local shortcuts self.shortcuts = self.create_shortcuts() #For opening last closed tabs self.last_closed_files = [] # Reference to save msgbox and avoid memory to be freed. self.msgbox = None # File types and filters used by the Save As dialog self.edit_filetypes = None self.edit_filters = None # For testing self.save_dialog_on_tests = not PYTEST @Slot() def show_in_external_file_explorer(self, fnames=None): """Show file in external file explorer""" if fnames is None: fnames = self.get_current_filename() show_in_external_file_explorer(fnames) def create_shortcuts(self): """Create local shortcuts""" # --- Configurable shortcuts inspect = config_shortcut(self.inspect_current_object, context='Editor', name='Inspect current object', parent=self) set_breakpoint = config_shortcut(self.set_or_clear_breakpoint, context='Editor', name='Breakpoint', parent=self) set_cond_breakpoint = config_shortcut( self.set_or_edit_conditional_breakpoint, context='Editor', name='Conditional breakpoint', parent=self) gotoline = config_shortcut(self.go_to_line, context='Editor', name='Go to line', parent=self) tab = config_shortcut(lambda: self.tab_navigation_mru(forward=False), context='Editor', name='Go to previous file', parent=self) tabshift = config_shortcut(self.tab_navigation_mru, context='Editor', name='Go to next file', parent=self) prevtab = config_shortcut(lambda: self.tabs.tab_navigate(-1), context='Editor', name='Cycle to previous file', parent=self) nexttab = config_shortcut(lambda: self.tabs.tab_navigate(1), context='Editor', name='Cycle to next file', parent=self) run_selection = config_shortcut(self.run_selection, context='Editor', name='Run selection', parent=self) new_file = config_shortcut(lambda : self.sig_new_file[()].emit(), context='Editor', name='New file', parent=self) open_file = config_shortcut(lambda : self.plugin_load[()].emit(), context='Editor', name='Open file', parent=self) save_file = config_shortcut(self.save, context='Editor', name='Save file', parent=self) save_all = config_shortcut(self.save_all, context='Editor', name='Save all', parent=self) save_as = config_shortcut(lambda : self.sig_save_as.emit(), context='Editor', name='Save As', parent=self) close_all = config_shortcut(self.close_all_files, context='Editor', name='Close all', parent=self) prev_edit_pos = config_shortcut(lambda : self.sig_prev_edit_pos.emit(), context="Editor", name="Last edit location", parent=self) prev_cursor = config_shortcut(lambda : self.sig_prev_cursor.emit(), context="Editor", name="Previous cursor position", parent=self) next_cursor = config_shortcut(lambda : self.sig_next_cursor.emit(), context="Editor", name="Next cursor position", parent=self) zoom_in_1 = config_shortcut(lambda : self.zoom_in.emit(), context="Editor", name="zoom in 1", parent=self) zoom_in_2 = config_shortcut(lambda : self.zoom_in.emit(), context="Editor", name="zoom in 2", parent=self) zoom_out = config_shortcut(lambda : self.zoom_out.emit(), context="Editor", name="zoom out", parent=self) zoom_reset = config_shortcut(lambda: self.zoom_reset.emit(), context="Editor", name="zoom reset", parent=self) close_file_1 = config_shortcut(self.close_file, context="Editor", name="close file 1", parent=self) close_file_2 = config_shortcut(self.close_file, context="Editor", name="close file 2", parent=self) run_cell = config_shortcut(self.run_cell, context="Editor", name="run cell", parent=self) run_cell_and_advance = config_shortcut(self.run_cell_and_advance, context="Editor", name="run cell and advance", parent=self) go_to_next_cell = config_shortcut(self.advance_cell, context="Editor", name="go to next cell", parent=self) go_to_previous_cell = config_shortcut(lambda: self.advance_cell(reverse=True), context="Editor", name="go to previous cell", parent=self) re_run_last_cell = config_shortcut(self.re_run_last_cell, context="Editor", name="re-run last cell", parent=self) # Return configurable ones return [inspect, set_breakpoint, set_cond_breakpoint, gotoline, tab, tabshift, run_selection, new_file, open_file, save_file, save_all, save_as, close_all, prev_edit_pos, prev_cursor, next_cursor, zoom_in_1, zoom_in_2, zoom_out, zoom_reset, close_file_1, close_file_2, run_cell, run_cell_and_advance, go_to_next_cell, go_to_previous_cell, re_run_last_cell, prevtab, nexttab] def get_shortcut_data(self): """ Returns shortcut data, a list of tuples (shortcut, text, default) shortcut (QShortcut or QAction instance) text (string): action/shortcut description default (string): default key sequence """ return [sc.data for sc in self.shortcuts] def setup_editorstack(self, parent, layout): """Setup editorstack's layout""" menu_btn = create_toolbutton(self, icon=ima.icon('tooloptions'), tip=_('Options')) self.menu = QMenu(self) menu_btn.setMenu(self.menu) menu_btn.setPopupMode(menu_btn.InstantPopup) self.menu.aboutToShow.connect(self.__setup_menu) # self.filelist_btn = create_toolbutton(self, # icon=ima.icon('filelist'), # tip=_("File list management"), # triggered=self.open_fileswitcher_dlg) # # self.previous_btn = create_toolbutton(self, # icon=ima.icon('previous'), # tip=_("Previous file"), # triggered=self.go_to_previous_file) # # self.next_btn = create_toolbutton(self, # icon=ima.icon('next'), # tip=_("Next file"), # triggered=self.go_to_next_file) # Optional tabs # corner_widgets = {Qt.TopRightCorner: [self.previous_btn, # self.filelist_btn, self.next_btn, # 5, menu_btn]} corner_widgets = {Qt.TopRightCorner: [menu_btn]} self.tabs = BaseTabs(self, menu=self.menu, menu_use_tooltips=True, corner_widgets=corner_widgets) self.tabs.tabBar().setObjectName('plugin-tab') self.tabs.set_close_function(self.close_file) self.tabs.tabBar().tabMoved.connect(self.move_editorstack_data) self.tabs.setMovable(True) self.stack_history.refresh() if hasattr(self.tabs, 'setDocumentMode') \ and not sys.platform == 'darwin': # Don't set document mode to true on OSX because it generates # a crash when the editor is detached from the main window # Fixes Issue 561 self.tabs.setDocumentMode(True) self.tabs.currentChanged.connect(self.current_changed) if sys.platform == 'darwin': tab_container = QWidget() tab_container.setObjectName('tab-container') tab_layout = QHBoxLayout(tab_container) tab_layout.setContentsMargins(0, 0, 0, 0) tab_layout.addWidget(self.tabs) layout.addWidget(tab_container) else: layout.addWidget(self.tabs) def add_corner_widgets_to_tabbar(self, widgets): self.tabs.add_corner_widgets(widgets) def closeEvent(self, event): self.threadmanager.close_all_threads() self.analysis_timer.timeout.disconnect(self.analyze_script) # Remove editor references from the outline explorer settings if self.outlineexplorer is not None: for finfo in self.data: self.outlineexplorer.remove_editor(finfo.editor) QWidget.closeEvent(self, event) if is_pyqt46: self.destroyed.emit() def clone_editor_from(self, other_finfo, set_current): fname = other_finfo.filename enc = other_finfo.encoding new = other_finfo.newly_created finfo = self.create_new_editor(fname, enc, "", set_current=set_current, new=new, cloned_from=other_finfo.editor) finfo.set_analysis_results(other_finfo.analysis_results) finfo.set_todo_results(other_finfo.todo_results) return finfo.editor def clone_from(self, other): """Clone EditorStack from other instance""" for other_finfo in other.data: self.clone_editor_from(other_finfo, set_current=True) self.set_stack_index(other.get_stack_index()) @Slot() def open_fileswitcher_dlg(self): """Open file list management dialog box""" if not self.tabs.count(): return if self.fileswitcher_dlg is not None and \ self.fileswitcher_dlg.is_visible: self.fileswitcher_dlg.hide() self.fileswitcher_dlg.is_visible = False return self.fileswitcher_dlg = FileSwitcher(self, self, self.tabs, self.data, ima.icon('TextFileIcon')) self.fileswitcher_dlg.sig_goto_file.connect(self.set_stack_index) self.fileswitcher_dlg.show() self.fileswitcher_dlg.is_visible = True @Slot() def open_symbolfinder_dlg(self): self.open_fileswitcher_dlg() self.fileswitcher_dlg.set_search_text('@') def get_current_tab_manager(self): """Get the widget with the TabWidget attribute.""" return self def go_to_line(self, line=None): """Go to line dialog""" if line is not None: # When this method is called from the flileswitcher, a line # number is specified, so there is no need for the dialog. self.get_current_editor().go_to_line(line) else: if self.data: self.get_current_editor().exec_gotolinedialog() def set_or_clear_breakpoint(self): """Set/clear breakpoint""" if self.data: editor = self.get_current_editor() editor.add_remove_breakpoint() def set_or_edit_conditional_breakpoint(self): """Set conditional breakpoint""" if self.data: editor = self.get_current_editor() editor.add_remove_breakpoint(edit_condition=True) def inspect_current_object(self): """Inspect current object in the Help plugin""" if self.introspector: editor = self.get_current_editor() position = editor.get_position('cursor') self.help.switch_to_editor_source() self.introspector.show_object_info(position, auto=False) else: text = self.get_current_editor().get_current_object() if text: self.send_to_help(text, force=True) #------ Editor Widget Settings def set_closable(self, state): """Parent widget must handle the closable state""" self.is_closable = state def set_io_actions(self, new_action, open_action, save_action, revert_action): self.new_action = new_action self.open_action = open_action self.save_action = save_action self.revert_action = revert_action def set_find_widget(self, find_widget): self.find_widget = find_widget def set_outlineexplorer(self, outlineexplorer): self.outlineexplorer = outlineexplorer self.outlineexplorer.outlineexplorer_is_visible.connect( self._refresh_outlineexplorer) def initialize_outlineexplorer(self): """This method is called separately from 'set_oulineexplorer' to avoid doing unnecessary updates when there are multiple editor windows""" for index in range(self.get_stack_count()): if index != self.get_stack_index(): self._refresh_outlineexplorer(index=index) def add_outlineexplorer_button(self, editor_plugin): oe_btn = create_toolbutton(editor_plugin) oe_btn.setDefaultAction(self.outlineexplorer.visibility_action) self.add_corner_widgets_to_tabbar([5, oe_btn]) def set_help(self, help_plugin): self.help = help_plugin def set_tempfile_path(self, path): self.tempfile_path = path def set_title(self, text): self.title = text def __update_editor_margins(self, editor): editor.setup_margins(linenumbers=self.linenumbers_enabled, markers=self.has_markers()) def __codeanalysis_settings_changed(self, current_finfo): if self.data: run_pyflakes, run_pep8 = self.pyflakes_enabled, self.pep8_enabled for finfo in self.data: self.__update_editor_margins(finfo.editor) finfo.cleanup_analysis_results() if (run_pyflakes or run_pep8) and current_finfo is not None: if current_finfo is not finfo: finfo.run_code_analysis(run_pyflakes, run_pep8) def set_pyflakes_enabled(self, state, current_finfo=None): # CONF.get(self.CONF_SECTION, 'code_analysis/pyflakes') self.pyflakes_enabled = state self.__codeanalysis_settings_changed(current_finfo) def set_pep8_enabled(self, state, current_finfo=None): # CONF.get(self.CONF_SECTION, 'code_analysis/pep8') self.pep8_enabled = state self.__codeanalysis_settings_changed(current_finfo) def has_markers(self): """Return True if this editorstack has a marker margin for TODOs or code analysis""" return self.todolist_enabled or self.pyflakes_enabled\ or self.pep8_enabled def set_todolist_enabled(self, state, current_finfo=None): # CONF.get(self.CONF_SECTION, 'todo_list') self.todolist_enabled = state if self.data: for finfo in self.data: self.__update_editor_margins(finfo.editor) finfo.cleanup_todo_results() if state and current_finfo is not None: if current_finfo is not finfo: finfo.run_todo_finder() def set_realtime_analysis_enabled(self, state): self.realtime_analysis_enabled = state def set_realtime_analysis_timeout(self, timeout): self.analysis_timer.setInterval(timeout) def set_linenumbers_enabled(self, state, current_finfo=None): # CONF.get(self.CONF_SECTION, 'line_numbers') self.linenumbers_enabled = state if self.data: for finfo in self.data: self.__update_editor_margins(finfo.editor) def set_blanks_enabled(self, state): self.blanks_enabled = state if self.data: for finfo in self.data: finfo.editor.set_blanks_enabled(state) def set_edgeline_enabled(self, state): # CONF.get(self.CONF_SECTION, 'edge_line') self.edgeline_enabled = state if self.data: for finfo in self.data: finfo.editor.set_edge_line_enabled(state) def set_edgeline_column(self, column): # CONF.get(self.CONF_SECTION, 'edge_line_column') self.edgeline_column = column if self.data: for finfo in self.data: finfo.editor.set_edge_line_column(column) def set_codecompletion_auto_enabled(self, state): # CONF.get(self.CONF_SECTION, 'codecompletion_auto') self.codecompletion_auto_enabled = state if self.data: for finfo in self.data: finfo.editor.set_codecompletion_auto(state) def set_codecompletion_case_enabled(self, state): self.codecompletion_case_enabled = state if self.data: for finfo in self.data: finfo.editor.set_codecompletion_case(state) def set_codecompletion_enter_enabled(self, state): self.codecompletion_enter_enabled = state if self.data: for finfo in self.data: finfo.editor.set_codecompletion_enter(state) def set_calltips_enabled(self, state): # CONF.get(self.CONF_SECTION, 'calltips') self.calltips_enabled = state if self.data: for finfo in self.data: finfo.editor.set_calltips(state) def set_go_to_definition_enabled(self, state): # CONF.get(self.CONF_SECTION, 'go_to_definition') self.go_to_definition_enabled = state if self.data: for finfo in self.data: finfo.editor.set_go_to_definition_enabled(state) def set_close_parentheses_enabled(self, state): # CONF.get(self.CONF_SECTION, 'close_parentheses') self.close_parentheses_enabled = state if self.data: for finfo in self.data: finfo.editor.set_close_parentheses_enabled(state) def set_close_quotes_enabled(self, state): # CONF.get(self.CONF_SECTION, 'close_quotes') self.close_quotes_enabled = state if self.data: for finfo in self.data: finfo.editor.set_close_quotes_enabled(state) def set_add_colons_enabled(self, state): # CONF.get(self.CONF_SECTION, 'add_colons') self.add_colons_enabled = state if self.data: for finfo in self.data: finfo.editor.set_add_colons_enabled(state) def set_auto_unindent_enabled(self, state): # CONF.get(self.CONF_SECTION, 'auto_unindent') self.auto_unindent_enabled = state if self.data: for finfo in self.data: finfo.editor.set_auto_unindent_enabled(state) def set_indent_chars(self, indent_chars): # CONF.get(self.CONF_SECTION, 'indent_chars') indent_chars = indent_chars[1:-1] # removing the leading/ending '*' self.indent_chars = indent_chars if self.data: for finfo in self.data: finfo.editor.set_indent_chars(indent_chars) def set_tab_stop_width_spaces(self, tab_stop_width_spaces): # CONF.get(self.CONF_SECTION, 'tab_stop_width') self.tab_stop_width_spaces = tab_stop_width_spaces if self.data: for finfo in self.data: finfo.editor.setTabStopWidth(tab_stop_width_spaces * self.fontMetrics().width('9')) def set_help_enabled(self, state): self.help_enabled = state def set_default_font(self, font, color_scheme=None): self.default_font = font if color_scheme is not None: self.color_scheme = color_scheme if self.data: for finfo in self.data: finfo.editor.set_font(font, color_scheme) def set_color_scheme(self, color_scheme): self.color_scheme = color_scheme if self.data: for finfo in self.data: finfo.editor.set_color_scheme(color_scheme) def set_wrap_enabled(self, state): # CONF.get(self.CONF_SECTION, 'wrap') self.wrap_enabled = state if self.data: for finfo in self.data: finfo.editor.toggle_wrap_mode(state) def set_tabmode_enabled(self, state): # CONF.get(self.CONF_SECTION, 'tab_always_indent') self.tabmode_enabled = state if self.data: for finfo in self.data: finfo.editor.set_tab_mode(state) def set_intelligent_backspace_enabled(self, state): # CONF.get(self.CONF_SECTION, 'intelligent_backspace') self.intelligent_backspace_enabled = state if self.data: for finfo in self.data: finfo.editor.toggle_intelligent_backspace(state) def set_occurrence_highlighting_enabled(self, state): # CONF.get(self.CONF_SECTION, 'occurrence_highlighting') self.occurrence_highlighting_enabled = state if self.data: for finfo in self.data: finfo.editor.set_occurrence_highlighting(state) def set_occurrence_highlighting_timeout(self, timeout): # CONF.get(self.CONF_SECTION, 'occurrence_highlighting/timeout') self.occurrence_highlighting_timeout = timeout if self.data: for finfo in self.data: finfo.editor.set_occurrence_timeout(timeout) def set_highlight_current_line_enabled(self, state): self.highlight_current_line_enabled = state if self.data: for finfo in self.data: finfo.editor.set_highlight_current_line(state) def set_highlight_current_cell_enabled(self, state): self.highlight_current_cell_enabled = state if self.data: for finfo in self.data: finfo.editor.set_highlight_current_cell(state) def set_checkeolchars_enabled(self, state): # CONF.get(self.CONF_SECTION, 'check_eol_chars') self.checkeolchars_enabled = state def set_fullpath_sorting_enabled(self, state): # CONF.get(self.CONF_SECTION, 'fullpath_sorting') self.fullpath_sorting_enabled = state if self.data: finfo = self.data[self.get_stack_index()] new_index = self.data.index(finfo) self.__repopulate_stack() self.set_stack_index(new_index) def set_always_remove_trailing_spaces(self, state): # CONF.get(self.CONF_SECTION, 'always_remove_trailing_spaces') self.always_remove_trailing_spaces = state def set_focus_to_editor(self, state): self.focus_to_editor = state def set_introspector(self, introspector): self.introspector = introspector #------ Stacked widget management def get_stack_index(self): return self.tabs.currentIndex() def get_current_finfo(self): if self.data: return self.data[self.get_stack_index()] def get_current_editor(self): return self.tabs.currentWidget() def get_stack_count(self): return self.tabs.count() def set_stack_index(self, index, instance=None): if instance == self or instance == None: self.tabs.setCurrentIndex(index) def set_tabbar_visible(self, state): self.tabs.tabBar().setVisible(state) def remove_from_data(self, index): self.tabs.blockSignals(True) self.tabs.removeTab(index) self.data.pop(index) self.tabs.blockSignals(False) self.update_actions() def __modified_readonly_title(self, title, is_modified, is_readonly): if is_modified is not None and is_modified: title += "*" if is_readonly is not None and is_readonly: title = "(%s)" % title return title def get_tab_text(self, index, is_modified=None, is_readonly=None): """Return tab title.""" files_path_list = [finfo.filename for finfo in self.data] fname = self.data[index].filename fname = sourcecode.disambiguate_fname(files_path_list, fname) return self.__modified_readonly_title(fname, is_modified, is_readonly) def get_tab_tip(self, filename, is_modified=None, is_readonly=None): """Return tab menu title""" if self.fullpath_sorting_enabled: text = filename else: text = u"%s — %s" text = self.__modified_readonly_title(text, is_modified, is_readonly) if self.tempfile_path is not None\ and filename == encoding.to_unicode_from_fs(self.tempfile_path): temp_file_str = to_text_string(_("Temporary file")) if self.fullpath_sorting_enabled: return "%s (%s)" % (text, temp_file_str) else: return text % (temp_file_str, self.tempfile_path) else: if self.fullpath_sorting_enabled: return text else: return text % (osp.basename(filename), osp.dirname(filename)) def add_to_data(self, finfo, set_current): self.data.append(finfo) index = self.data.index(finfo) editor = finfo.editor self.tabs.insertTab(index, editor, self.get_tab_text(index)) self.set_stack_title(index, False) if set_current: self.set_stack_index(index) self.current_changed(index) self.update_actions() def __repopulate_stack(self): self.tabs.blockSignals(True) self.tabs.clear() for finfo in self.data: if finfo.newly_created: is_modified = True else: is_modified = None index = self.data.index(finfo) tab_text = self.get_tab_text(index, is_modified) tab_tip = self.get_tab_tip(finfo.filename) index = self.tabs.addTab(finfo.editor, tab_text) self.tabs.setTabToolTip(index, tab_tip) self.tabs.blockSignals(False) def rename_in_data(self, original_filename, new_filename): index = self.has_filename(original_filename) if index is None: return finfo = self.data[index] if osp.splitext(finfo.filename)[1] != osp.splitext(new_filename)[1]: # File type has changed! txt = to_text_string(finfo.editor.get_text_with_eol()) language = get_file_language(new_filename, txt) finfo.editor.set_language(language) set_new_index = index == self.get_stack_index() current_fname = self.get_current_filename() finfo.filename = new_filename new_index = self.data.index(finfo) self.__repopulate_stack() if set_new_index: self.set_stack_index(new_index) else: # Fixes Issue 1287 self.set_current_filename(current_fname) if self.outlineexplorer is not None: self.outlineexplorer.file_renamed(finfo.editor, finfo.filename) return new_index def set_stack_title(self, index, is_modified): finfo = self.data[index] fname = finfo.filename is_modified = (is_modified or finfo.newly_created) and not finfo.default is_readonly = finfo.editor.isReadOnly() tab_text = self.get_tab_text(index, is_modified, is_readonly) tab_tip = self.get_tab_tip(fname, is_modified, is_readonly) # Only update tab text if have changed, otherwise an unwanted scrolling # will happen when changing tabs. See Issue #1170. if tab_text != self.tabs.tabText(index): self.tabs.setTabText(index, tab_text) self.tabs.setTabToolTip(index, tab_tip) #------ Context menu def __setup_menu(self): """Setup tab context menu before showing it""" self.menu.clear() if self.data: actions = self.menu_actions else: actions = (self.new_action, self.open_action) self.setFocus() # --> Editor.__get_focus_editortabwidget add_actions(self.menu, list(actions) + self.__get_split_actions()) self.close_action.setEnabled(self.is_closable) #------ Hor/Ver splitting def __get_split_actions(self): # New window self.newwindow_action = create_action(self, _("New window"), icon=ima.icon('newwindow'), tip=_("Create a new editor window"), triggered=lambda: self.create_new_window.emit()) # Splitting self.versplit_action = create_action(self, _("Split vertically"), icon=ima.icon('versplit'), tip=_("Split vertically this editor window"), triggered=lambda: self.split_vertically.emit()) self.horsplit_action = create_action(self, _("Split horizontally"), icon=ima.icon('horsplit'), tip=_("Split horizontally this editor window"), triggered=lambda: self.split_horizontally.emit()) self.close_action = create_action(self, _("Close this panel"), icon=ima.icon('close_panel'), triggered=self.close) return [None, self.newwindow_action, None, self.versplit_action, self.horsplit_action, self.close_action] def reset_orientation(self): self.horsplit_action.setEnabled(True) self.versplit_action.setEnabled(True) def set_orientation(self, orientation): self.horsplit_action.setEnabled(orientation == Qt.Horizontal) self.versplit_action.setEnabled(orientation == Qt.Vertical) def update_actions(self): state = self.get_stack_count() > 0 self.horsplit_action.setEnabled(state) self.versplit_action.setEnabled(state) # ------ Accessors def get_current_filename(self): if self.data: return self.data[self.get_stack_index()].filename def has_filename(self, filename): """Return the self.data index position for the filename. Args: filename: Name of the file to search for in self.data. Returns: The self.data index for the filename. Returns None if the filename is not found in self.data. """ fixpath = lambda path: osp.normcase(osp.realpath(path)) for index, finfo in enumerate(self.data): if fixpath(filename) == fixpath(finfo.filename): return index return None def set_current_filename(self, filename): """Set current filename and return the associated editor instance""" index = self.has_filename(filename) if index is not None: self.set_stack_index(index) editor = self.data[index].editor editor.setFocus() return editor def is_file_opened(self, filename=None): """Return if filename is in the editor stack. Args: filename: Name of the file to search for. If filename is None, then checks if any file is open. Returns: True: If filename is None and a file is open. False: If filename is None and no files are open. None: If filename is not None and the file isn't found. integer: Index of file name in editor stack. """ if filename is None: # Is there any file opened? return len(self.data) > 0 else: return self.has_filename(filename) def get_index_from_filename(self, filename): """ Return the position index of a file in the tab bar of the editorstack from its name. """ filenames = [d.filename for d in self.data] return filenames.index(filename) @Slot(int, int) def move_editorstack_data(self, start, end): """Reorder editorstack.data so it is synchronized with the tab bar when tabs are moved.""" if start < 0 or end < 0: return else: steps = abs(end - start) direction = (end-start) // steps # +1 for right, -1 for left data = self.data self.blockSignals(True) for i in range(start, end, direction): data[i], data[i+direction] = data[i+direction], data[i] self.blockSignals(False) self.refresh() #------ Close file, tabwidget... def close_file(self, index=None, force=False): """Close file (index=None -> close current file) Keep current file index unchanged (if current file that is being closed)""" current_index = self.get_stack_index() count = self.get_stack_count() if index is None: if count > 0: index = current_index else: self.find_widget.set_editor(None) return new_index = None if count > 1: if current_index == index: new_index = self._get_previous_file_index() else: new_index = current_index is_ok = force or self.save_if_changed(cancelable=True, index=index) if is_ok: finfo = self.data[index] self.threadmanager.close_threads(finfo) # Removing editor reference from outline explorer settings: if self.outlineexplorer is not None: self.outlineexplorer.remove_editor(finfo.editor) filename = self.data[index].filename self.remove_from_data(index) # We pass self object ID as a QString, because otherwise it would # depend on the platform: long for 64bit, int for 32bit. Replacing # by long all the time is not working on some 32bit platforms # (see Issue 1094, Issue 1098) self.sig_close_file.emit(str(id(self)), filename) if not self.data and self.is_closable: # editortabwidget is empty: removing it # (if it's not the first editortabwidget) self.close() self.opened_files_list_changed.emit() self.update_code_analysis_actions.emit() self._refresh_outlineexplorer() self.refresh_file_dependent_actions.emit() self.update_plugin_title.emit() editor = self.get_current_editor() if editor: editor.setFocus() if new_index is not None: if index < new_index: new_index -= 1 self.set_stack_index(new_index) self.add_last_closed_file(finfo.filename) if self.get_stack_count() == 0 and self.create_new_file_if_empty: self.sig_new_file[()].emit() return False self.__modify_stack_title() return is_ok def close_all_files(self): """Close all opened scripts""" while self.close_file(): pass def close_all_right(self): """ Close all files opened to the right """ num = self.get_stack_index() n = self.get_stack_count() for i in range(num, n-1): self.close_file(num+1) def close_all_but_this(self): """Close all files but the current one""" self.close_all_right() for i in range(0, self.get_stack_count()-1 ): self.close_file(0) def add_last_closed_file(self, fname): """Add to last closed file list.""" if fname in self.last_closed_files: self.last_closed_files.remove(fname) self.last_closed_files.insert(0, fname) if len(self.last_closed_files) > 10: self.last_closed_files.pop(-1) def get_last_closed_files(self): return self.last_closed_files def set_last_closed_files(self, fnames): self.last_closed_files = fnames #------ Save def save_if_changed(self, cancelable=False, index=None): """Ask user to save file if modified. Args: cancelable: Show Cancel button. index: File to check for modification. Returns: False when save() fails or is cancelled. True when save() is successful, there are no modifications, or user selects No or NoToAll. This function controls the message box prompt for saving changed files. The actual save is performed in save() for each index processed. """ if index is None: indexes = list(range(self.get_stack_count())) else: indexes = [index] buttons = QMessageBox.Yes | QMessageBox.No if cancelable: buttons |= QMessageBox.Cancel unsaved_nb = 0 for index in indexes: if self.data[index].editor.document().isModified(): unsaved_nb += 1 if not unsaved_nb: # No file to save return True if unsaved_nb > 1: buttons |= QMessageBox.YesAll | QMessageBox.NoAll yes_all = False for index in indexes: self.set_stack_index(index) finfo = self.data[index] if finfo.filename == self.tempfile_path or yes_all: if not self.save(index): return False elif (finfo.editor.document().isModified() and self.save_dialog_on_tests): self.msgbox = QMessageBox( QMessageBox.Question, self.title, _("%s has been modified." "
    Do you want to save changes?" ) % osp.basename(finfo.filename), buttons, parent=self) answer = self.msgbox.exec_() if answer == QMessageBox.Yes: if not self.save(index): return False elif answer == QMessageBox.YesAll: if not self.save(index): return False yes_all = True elif answer == QMessageBox.NoAll: return True elif answer == QMessageBox.Cancel: return False return True def save(self, index=None, force=False): """Write text of editor to a file. Args: index: self.data index to save. If None, defaults to currentIndex(). force: Force save regardless of file state. Returns: True upon successful save or when file doesn't need to be saved. False if save failed. If the text isn't modified and it's not newly created, then the save is aborted. If the file hasn't been saved before, then save_as() is invoked. Otherwise, the file is written using the file name currently in self.data. This function doesn't change the file name. """ if index is None: # Save the currently edited file if not self.get_stack_count(): return index = self.get_stack_index() finfo = self.data[index] if not (finfo.editor.document().isModified() or finfo.newly_created) and not force: return True if not osp.isfile(finfo.filename) and not force: # File has not been saved yet return self.save_as(index=index) if self.always_remove_trailing_spaces: self.remove_trailing_spaces(index) txt = to_text_string(finfo.editor.get_text_with_eol()) try: finfo.encoding = encoding.write(txt, finfo.filename, finfo.encoding) finfo.newly_created = False self.encoding_changed.emit(finfo.encoding) finfo.lastmodified = QFileInfo(finfo.filename).lastModified() # We pass self object ID as a QString, because otherwise it would # depend on the platform: long for 64bit, int for 32bit. Replacing # by long all the time is not working on some 32bit platforms # (see Issue 1094, Issue 1098) # The filename is passed instead of an index in case the tabs # have been rearranged (see issue 5703). self.file_saved.emit(str(id(self)), finfo.filename, finfo.filename) finfo.editor.document().setModified(False) self.modification_changed(index=index) self.analyze_script(index) self.introspector.validate() #XXX CodeEditor-only: re-scan the whole text to rebuild outline # explorer data from scratch (could be optimized because # rehighlighting text means searching for all syntax coloring # patterns instead of only searching for class/def patterns which # would be sufficient for outline explorer data. finfo.editor.rehighlight() self._refresh_outlineexplorer(index) return True except EnvironmentError as error: self.msgbox = QMessageBox( QMessageBox.Critical, _("Save"), _("Unable to save file '%s'" "

    Error message:
    %s" ) % (osp.basename(finfo.filename), str(error)), parent=self) self.msgbox.exec_() return False def file_saved_in_other_editorstack(self, original_filename, filename): """ File was just saved in another editorstack, let's synchronize! This avoids file being automatically reloaded. The original filename is passed instead of an index in case the tabs on the editor stacks were moved and are now in a different order - see issue 5703. Filename is passed in case file was just saved as another name. """ index = self.has_filename(original_filename) if index is None: return finfo = self.data[index] finfo.newly_created = False finfo.filename = to_text_string(filename) finfo.lastmodified = QFileInfo(finfo.filename).lastModified() def select_savename(self, original_filename): """Select a name to save a file. Args: original_filename: Used in the dialog to display the current file path and name. Returns: Normalized path for the selected file name or None if no name was selected. """ if self.edit_filetypes is None: self.edit_filetypes = get_edit_filetypes() if self.edit_filters is None: self.edit_filters = get_edit_filters() # Don't use filters on KDE to not make the dialog incredible # slow # Fixes issue 4156 if is_kde_desktop() and not is_anaconda(): filters = '' selectedfilter = '' else: filters = self.edit_filters selectedfilter = get_filter(self.edit_filetypes, osp.splitext(original_filename)[1]) self.redirect_stdio.emit(False) filename, _selfilter = getsavefilename(self, _("Save file"), original_filename, filters=filters, selectedfilter=selectedfilter, options=QFileDialog.HideNameFilterDetails) self.redirect_stdio.emit(True) if filename: return osp.normpath(filename) return None def save_as(self, index=None): """Save file as... Args: index: self.data index for the file to save. Returns: False if no file name was selected or if save() was unsuccessful. True is save() was successful. Gets the new file name from select_savename(). If no name is chosen, then the save_as() aborts. Otherwise, the current stack is checked to see if the selected name already exists and, if so, then the tab with that name is closed. The current stack (self.data) and current tabs are updated with the new name and other file info. The text is written with the new name using save() and the name change is propagated to the other stacks via the file_renamed_in_data signal. """ if index is None: # Save the currently edited file index = self.get_stack_index() finfo = self.data[index] # The next line is necessary to avoid checking if the file exists # While running __check_file_status # See issues 3678 and 3026 finfo.newly_created = True original_filename = finfo.filename filename = self.select_savename(original_filename) if filename: ao_index = self.has_filename(filename) # Note: ao_index == index --> saving an untitled file if ao_index is not None and ao_index != index: if not self.close_file(ao_index): return if ao_index < index: index -= 1 new_index = self.rename_in_data(original_filename, new_filename=filename) # We pass self object ID as a QString, because otherwise it would # depend on the platform: long for 64bit, int for 32bit. Replacing # by long all the time is not working on some 32bit platforms # (see Issue 1094, Issue 1098) self.file_renamed_in_data.emit(str(id(self)), original_filename, filename) ok = self.save(index=new_index, force=True) self.refresh(new_index) self.set_stack_index(new_index) return ok else: return False def save_copy_as(self, index=None): """Save copy of file as... Args: index: self.data index for the file to save. Returns: False if no file name was selected or if save() was unsuccessful. True is save() was successful. Gets the new file name from select_savename(). If no name is chosen, then the save_copy_as() aborts. Otherwise, the current stack is checked to see if the selected name already exists and, if so, then the tab with that name is closed. Unlike save_as(), this calls write() directly instead of using save(). The current file and tab aren't changed at all. The copied file is opened in a new tab. """ if index is None: # Save the currently edited file index = self.get_stack_index() finfo = self.data[index] original_filename = finfo.filename filename = self.select_savename(original_filename) if filename: ao_index = self.has_filename(filename) # Note: ao_index == index --> saving an untitled file if ao_index is not None and ao_index != index: if not self.close_file(ao_index): return if ao_index < index: index -= 1 txt = to_text_string(finfo.editor.get_text_with_eol()) try: finfo.encoding = encoding.write(txt, filename, finfo.encoding) # open created copy file self.plugin_load.emit(filename) return True except EnvironmentError as error: self.msgbox = QMessageBox( QMessageBox.Critical, _("Save"), _("Unable to save file '%s'" "

    Error message:
    %s" ) % (osp.basename(finfo.filename), str(error)), parent=self) self.msgbox.exec_() else: return False def save_all(self): """Save all opened files. Iterate through self.data and call save() on any modified files. """ for index in range(self.get_stack_count()): if self.data[index].editor.document().isModified(): self.save(index) #------ Update UI def start_stop_analysis_timer(self): self.is_analysis_done = False if self.realtime_analysis_enabled: self.analysis_timer.stop() self.analysis_timer.start() def analyze_script(self, index=None): """Analyze current script with pyflakes + find todos""" if self.is_analysis_done: return if index is None: index = self.get_stack_index() if self.data: finfo = self.data[index] run_pyflakes, run_pep8 = self.pyflakes_enabled, self.pep8_enabled if run_pyflakes or run_pep8: finfo.run_code_analysis(run_pyflakes, run_pep8) if self.todolist_enabled: finfo.run_todo_finder() self.is_analysis_done = True def set_analysis_results(self, filename, analysis_results): """Synchronize analysis results between editorstacks""" index = self.has_filename(filename) if index is None: return self.data[index].set_analysis_results(analysis_results) def get_analysis_results(self): if self.data: return self.data[self.get_stack_index()].analysis_results def set_todo_results(self, filename, todo_results): """Synchronize todo results between editorstacks""" index = self.has_filename(filename) if index is None: return self.data[index].set_todo_results(todo_results) def get_todo_results(self): if self.data: return self.data[self.get_stack_index()].todo_results def current_changed(self, index): """Stack index has changed""" # count = self.get_stack_count() # for btn in (self.filelist_btn, self.previous_btn, self.next_btn): # btn.setEnabled(count > 1) editor = self.get_current_editor() if index != -1: editor.setFocus() if DEBUG_EDITOR: print("setfocusto:", editor, file=STDOUT) else: self.reset_statusbar.emit() self.opened_files_list_changed.emit() self.stack_history.refresh() while index in self.stack_history: self.stack_history.remove(index) self.stack_history.append(index) if DEBUG_EDITOR: print("current_changed:", index, self.data[index].editor, end=' ', file=STDOUT) print(self.data[index].editor.get_document_id(), file=STDOUT) self.update_plugin_title.emit() if editor is not None: # Needed in order to handle the close of files open in a directory # that has been renamed. See issue 5157 try: self.current_file_changed.emit(self.data[index].filename, editor.get_position('cursor')) except IndexError: pass def _get_previous_file_index(self): """Return the penultimate element of the stack history.""" try: return self.stack_history[-2] except IndexError: return None def tab_navigation_mru(self, forward=True): """ Tab navigation with "most recently used" behaviour. It's fired when pressing 'go to previous file' or 'go to next file' shortcuts. forward: True: move to next file False: move to previous file """ self.tabs_switcher = TabSwitcherWidget(self, self.stack_history, self.tabs) self.tabs_switcher.show() self.tabs_switcher.select_row(1 if forward else -1) self.tabs_switcher.setFocus() def focus_changed(self): """Editor focus has changed""" fwidget = QApplication.focusWidget() for finfo in self.data: if fwidget is finfo.editor: self.refresh() self.editor_focus_changed.emit() def _refresh_outlineexplorer(self, index=None, update=True, clear=False): """Refresh outline explorer panel""" oe = self.outlineexplorer if oe is None: return if index is None: index = self.get_stack_index() enable = False if self.data: finfo = self.data[index] if finfo.editor.is_python(): enable = True oe.setEnabled(True) oe.set_current_editor(finfo.editor, finfo.filename, update=update, clear=clear) if not enable: oe.setEnabled(False) def __refresh_statusbar(self, index): """Refreshing statusbar widgets""" finfo = self.data[index] self.encoding_changed.emit(finfo.encoding) # Refresh cursor position status: line, index = finfo.editor.get_cursor_line_column() self.sig_editor_cursor_position_changed.emit(line, index) def __refresh_readonly(self, index): finfo = self.data[index] read_only = not QFileInfo(finfo.filename).isWritable() if not osp.isfile(finfo.filename): # This is an 'untitledX.py' file (newly created) read_only = False finfo.editor.setReadOnly(read_only) self.readonly_changed.emit(read_only) def __check_file_status(self, index): """Check if file has been changed in any way outside Spyder: 1. removed, moved or renamed outside Spyder 2. modified outside Spyder""" if self.__file_status_flag: # Avoid infinite loop: when the QMessageBox.question pops, it # gets focus and then give it back to the CodeEditor instance, # triggering a refresh cycle which calls this method return self.__file_status_flag = True finfo = self.data[index] name = osp.basename(finfo.filename) if finfo.newly_created: # File was just created (not yet saved): do nothing # (do not return because of the clean-up at the end of the method) pass elif not osp.isfile(finfo.filename): # File doesn't exist (removed, moved or offline): self.msgbox = QMessageBox( QMessageBox.Warning, self.title, _("%s is unavailable " "(this file may have been removed, moved " "or renamed outside Spyder)." "
    Do you want to close it?") % name, QMessageBox.Yes | QMessageBox.No, self) answer = self.msgbox.exec_() if answer == QMessageBox.Yes: self.close_file(index) else: finfo.newly_created = True finfo.editor.document().setModified(True) self.modification_changed(index=index) else: # Else, testing if it has been modified elsewhere: lastm = QFileInfo(finfo.filename).lastModified() if to_text_string(lastm.toString()) \ != to_text_string(finfo.lastmodified.toString()): if finfo.editor.document().isModified(): self.msgbox = QMessageBox( QMessageBox.Question, self.title, _("%s has been modified outside Spyder." "
    Do you want to reload it and lose all " "your changes?") % name, QMessageBox.Yes | QMessageBox.No, self) answer = self.msgbox.exec_() if answer == QMessageBox.Yes: self.reload(index) else: finfo.lastmodified = lastm else: self.reload(index) # Finally, resetting temporary flag: self.__file_status_flag = False def __modify_stack_title(self): for index, finfo in enumerate(self.data): state = finfo.editor.document().isModified() self.set_stack_title(index, state) def refresh(self, index=None): """Refresh tabwidget""" if index is None: index = self.get_stack_index() # Set current editor if self.get_stack_count(): index = self.get_stack_index() finfo = self.data[index] editor = finfo.editor editor.setFocus() self._refresh_outlineexplorer(index, update=False) self.update_code_analysis_actions.emit() self.__refresh_statusbar(index) self.__refresh_readonly(index) self.__check_file_status(index) self.__modify_stack_title() self.update_plugin_title.emit() else: editor = None # Update the modification-state-dependent parameters self.modification_changed() # Update FindReplace binding self.find_widget.set_editor(editor, refresh=False) def modification_changed(self, state=None, index=None, editor_id=None): """ Current editor's modification state has changed --> change tab title depending on new modification state --> enable/disable save/save all actions """ if editor_id is not None: for index, _finfo in enumerate(self.data): if id(_finfo.editor) == editor_id: break # This must be done before refreshing save/save all actions: # (otherwise Save/Save all actions will always be enabled) self.opened_files_list_changed.emit() # -- if index is None: index = self.get_stack_index() if index == -1: return finfo = self.data[index] if state is None: state = finfo.editor.document().isModified() or finfo.newly_created self.set_stack_title(index, state) # Toggle save/save all actions state self.save_action.setEnabled(state) self.refresh_save_all_action.emit() # Refreshing eol mode eol_chars = finfo.editor.get_line_separator() self.refresh_eol_chars(eol_chars) self.stack_history.refresh() def refresh_eol_chars(self, eol_chars): os_name = sourcecode.get_os_name_from_eol_chars(eol_chars) self.sig_refresh_eol_chars.emit(os_name) #------ Load, reload def reload(self, index): """Reload file from disk""" finfo = self.data[index] txt, finfo.encoding = encoding.read(finfo.filename) finfo.lastmodified = QFileInfo(finfo.filename).lastModified() position = finfo.editor.get_position('cursor') finfo.editor.set_text(txt) finfo.editor.document().setModified(False) finfo.editor.set_cursor_position(position) self.introspector.validate() #XXX CodeEditor-only: re-scan the whole text to rebuild outline # explorer data from scratch (could be optimized because # rehighlighting text means searching for all syntax coloring # patterns instead of only searching for class/def patterns which # would be sufficient for outline explorer data. finfo.editor.rehighlight() self._refresh_outlineexplorer(index) def revert(self): """Revert file from disk""" index = self.get_stack_index() finfo = self.data[index] filename = finfo.filename if finfo.editor.document().isModified(): self.msgbox = QMessageBox( QMessageBox.Warning, self.title, _("All changes to %s will be lost." "
    Do you want to revert file from disk?" ) % osp.basename(filename), QMessageBox.Yes | QMessageBox.No, self) answer = self.msgbox.exec_() if answer != QMessageBox.Yes: return self.reload(index) def create_new_editor(self, fname, enc, txt, set_current, new=False, cloned_from=None): """ Create a new editor instance Returns finfo object (instead of editor as in previous releases) """ editor = codeeditor.CodeEditor(self) introspector = self.introspector editor.get_completions.connect(introspector.get_completions) editor.sig_show_object_info.connect(introspector.show_object_info) editor.go_to_definition.connect(introspector.go_to_definition) finfo = FileInfo(fname, enc, editor, new, self.threadmanager, self.introspector) self.add_to_data(finfo, set_current) finfo.send_to_help.connect(self.send_to_help) finfo.analysis_results_changed.connect( lambda: self.analysis_results_changed.emit()) finfo.todo_results_changed.connect( lambda: self.todo_results_changed.emit()) finfo.edit_goto.connect(lambda fname, lineno, name: self.edit_goto.emit(fname, lineno, name)) finfo.save_breakpoints.connect(lambda s1, s2: self.save_breakpoints.emit(s1, s2)) editor.run_selection.connect(self.run_selection) editor.run_cell.connect(self.run_cell) editor.run_cell_and_advance.connect(self.run_cell_and_advance) editor.re_run_last_cell.connect(self.re_run_last_cell) editor.sig_new_file.connect(self.sig_new_file.emit) language = get_file_language(fname, txt) editor.setup_editor( linenumbers=self.linenumbers_enabled, show_blanks=self.blanks_enabled, edge_line=self.edgeline_enabled, edge_line_column=self.edgeline_column, language=language, markers=self.has_markers(), font=self.default_font, color_scheme=self.color_scheme, wrap=self.wrap_enabled, tab_mode=self.tabmode_enabled, intelligent_backspace=self.intelligent_backspace_enabled, highlight_current_line=self.highlight_current_line_enabled, highlight_current_cell=self.highlight_current_cell_enabled, occurrence_highlighting=self.occurrence_highlighting_enabled, occurrence_timeout=self.occurrence_highlighting_timeout, codecompletion_auto=self.codecompletion_auto_enabled, codecompletion_case=self.codecompletion_case_enabled, codecompletion_enter=self.codecompletion_enter_enabled, calltips=self.calltips_enabled, go_to_definition=self.go_to_definition_enabled, close_parentheses=self.close_parentheses_enabled, close_quotes=self.close_quotes_enabled, add_colons=self.add_colons_enabled, auto_unindent=self.auto_unindent_enabled, indent_chars=self.indent_chars, tab_stop_width_spaces=self.tab_stop_width_spaces, cloned_from=cloned_from, filename=fname) if cloned_from is None: editor.set_text(txt) editor.document().setModified(False) finfo.text_changed_at.connect( lambda fname, position: self.text_changed_at.emit(fname, position)) editor.sig_cursor_position_changed.connect( self.editor_cursor_position_changed) editor.textChanged.connect(self.start_stop_analysis_timer) editor.modificationChanged.connect( lambda state: self.modification_changed(state, editor_id=id(editor))) editor.focus_in.connect(self.focus_changed) editor.zoom_in.connect(lambda: self.zoom_in.emit()) editor.zoom_out.connect(lambda: self.zoom_out.emit()) editor.zoom_reset.connect(lambda: self.zoom_reset.emit()) editor.sig_eol_chars_changed.connect(lambda eol_chars: self.refresh_eol_chars(eol_chars)) self.find_widget.set_editor(editor) self.refresh_file_dependent_actions.emit() self.modification_changed(index=self.data.index(finfo)) # Needs to reset the highlighting on startup in case the PygmentsSH # is in use editor.run_pygments_highlighter() return finfo def editor_cursor_position_changed(self, line, index): """Cursor position of one of the editor in the stack has changed""" self.sig_editor_cursor_position_changed.emit(line, index) def send_to_help(self, qstr1, qstr2=None, qstr3=None, qstr4=None, force=False): """qstr1: obj_text, qstr2: argpspec, qstr3: note, qstr4: doc_text""" if not force and not self.help_enabled: return if self.help is not None \ and (force or self.help.dockwidget.isVisible()): # Help plugin exists and is visible if qstr4 is None: self.help.set_object_text(qstr1, ignore_unknown=True, force_refresh=force) else: objtxt = to_text_string(qstr1) name = objtxt.split('.')[-1] argspec = to_text_string(qstr2) note = to_text_string(qstr3) docstring = to_text_string(qstr4) doc = {'obj_text': objtxt, 'name': name, 'argspec': argspec, 'note': note, 'docstring': docstring} self.help.set_editor_doc(doc, force_refresh=force) editor = self.get_current_editor() editor.setFocus() def new(self, filename, encoding, text, default_content=False): """ Create new filename with *encoding* and *text* """ finfo = self.create_new_editor(filename, encoding, text, set_current=False, new=True) finfo.editor.set_cursor_position('eof') finfo.editor.insert_text(os.linesep) if default_content: finfo.default = True finfo.editor.document().setModified(False) return finfo def load(self, filename, set_current=True): """ Load filename, create an editor instance and return it *Warning* This is loading file, creating editor but not executing the source code analysis -- the analysis must be done by the editor plugin (in case multiple editorstack instances are handled) """ filename = osp.abspath(to_text_string(filename)) self.starting_long_process.emit(_("Loading %s...") % filename) text, enc = encoding.read(filename) finfo = self.create_new_editor(filename, enc, text, set_current) index = self.data.index(finfo) self._refresh_outlineexplorer(index, update=True) self.ending_long_process.emit("") if self.isVisible() and self.checkeolchars_enabled \ and sourcecode.has_mixed_eol_chars(text): name = osp.basename(filename) self.msgbox = QMessageBox( QMessageBox.Warning, self.title, _("%s contains mixed end-of-line " "characters.
    Spyder will fix this " "automatically.") % name, QMessageBox.Ok, self) self.msgbox.exec_() self.set_os_eol_chars(index) self.is_analysis_done = False return finfo def set_os_eol_chars(self, index=None): if index is None: index = self.get_stack_index() finfo = self.data[index] eol_chars = sourcecode.get_eol_chars_from_os_name(os.name) finfo.editor.set_eol_chars(eol_chars) finfo.editor.document().setModified(True) def remove_trailing_spaces(self, index=None): """Remove trailing spaces""" if index is None: index = self.get_stack_index() finfo = self.data[index] finfo.editor.remove_trailing_spaces() def fix_indentation(self, index=None): """Replace tab characters by spaces""" if index is None: index = self.get_stack_index() finfo = self.data[index] finfo.editor.fix_indentation() #------ Run def run_selection(self): """ Run selected text or current line in console. If some text is selected, then execute that text in console. If no text is selected, then execute current line, unless current line is empty. Then, advance cursor to next line. If cursor is on last line and that line is not empty, then add a new blank line and move the cursor there. If cursor is on last line and that line is empty, then do not move cursor. """ text = self.get_current_editor().get_selection_as_executable_code() if text: self.exec_in_extconsole.emit(text, self.focus_to_editor) return editor = self.get_current_editor() line = editor.get_current_line() text = line.lstrip() if text: self.exec_in_extconsole.emit(text, self.focus_to_editor) if editor.is_cursor_on_last_line() and text: editor.append(editor.get_line_separator()) editor.move_cursor_to_next('line', 'down') def run_cell(self): """Run current cell""" text = self.get_current_editor().get_cell_as_executable_code() finfo = self.get_current_finfo() if finfo.editor.is_python() and text: self.exec_in_extconsole.emit(text, self.focus_to_editor) def run_cell_and_advance(self): """Run current cell and advance to the next one""" self.run_cell() self.advance_cell() def advance_cell(self, reverse=False): """Advance to the next cell. reverse = True --> go to previous cell. """ if not reverse: move_func = self.get_current_editor().go_to_next_cell else: move_func = self.get_current_editor().go_to_previous_cell if self.focus_to_editor: move_func() else: term = QApplication.focusWidget() move_func() term.setFocus() term = QApplication.focusWidget() move_func() term.setFocus() def re_run_last_cell(self): text = self.get_current_editor().get_last_cell_as_executable_code() finfo = self.get_current_finfo() if finfo.editor.is_python() and text: self.exec_in_extconsole.emit(text, self.focus_to_editor) #------ Drag and drop def dragEnterEvent(self, event): """Reimplement Qt method Inform Qt about the types of data that the widget accepts""" source = event.mimeData() # The second check is necessary on Windows, where source.hasUrls() # can return True but source.urls() is [] # The third check is needed since a file could be dropped from # compressed files. In Windows mimedata2url(source) returns None # Fixes issue 5218 if source.hasUrls() and source.urls() and mimedata2url(source): all_urls = mimedata2url(source) text = [encoding.is_text_file(url) for url in all_urls] if any(text): event.acceptProposedAction() else: event.ignore() elif source.hasText(): event.acceptProposedAction() elif os.name == 'nt': # This covers cases like dragging from compressed files, # which can be opened by the Editor if they are plain # text, but doesn't come with url info. # Fixes Issue 2032 event.acceptProposedAction() else: event.ignore() def dropEvent(self, event): """Reimplement Qt method Unpack dropped data and handle it""" source = event.mimeData() if source.hasUrls(): files = mimedata2url(source) files = [f for f in files if encoding.is_text_file(f)] files = set(files or []) for fname in files: self.plugin_load.emit(fname) elif source.hasText(): editor = self.get_current_editor() if editor is not None: editor.insert_text( source.text() ) event.acceptProposedAction() class EditorSplitter(QSplitter): def __init__(self, parent, plugin, menu_actions, first=False, register_editorstack_cb=None, unregister_editorstack_cb=None): QSplitter.__init__(self, parent) self.setAttribute(Qt.WA_DeleteOnClose) self.setChildrenCollapsible(False) self.toolbar_list = None self.menu_list = None self.plugin = plugin if register_editorstack_cb is None: register_editorstack_cb = self.plugin.register_editorstack self.register_editorstack_cb = register_editorstack_cb if unregister_editorstack_cb is None: unregister_editorstack_cb = self.plugin.unregister_editorstack self.unregister_editorstack_cb = unregister_editorstack_cb self.menu_actions = menu_actions self.editorstack = EditorStack(self, menu_actions) self.register_editorstack_cb(self.editorstack) if not first: self.plugin.clone_editorstack(editorstack=self.editorstack) self.editorstack.destroyed.connect(lambda: self.editorstack_closed()) self.editorstack.split_vertically.connect( lambda: self.split(orientation=Qt.Vertical)) self.editorstack.split_horizontally.connect( lambda: self.split(orientation=Qt.Horizontal)) self.addWidget(self.editorstack) def closeEvent(self, event): QSplitter.closeEvent(self, event) if is_pyqt46: self.destroyed.emit() def __give_focus_to_remaining_editor(self): focus_widget = self.plugin.get_focus_widget() if focus_widget is not None: focus_widget.setFocus() def editorstack_closed(self): if DEBUG_EDITOR: print("method 'editorstack_closed':", file=STDOUT) print(" self :", self, file=STDOUT) # print >>STDOUT, " sender:", self.sender() self.unregister_editorstack_cb(self.editorstack) self.editorstack = None try: close_splitter = self.count() == 1 except RuntimeError: # editorsplitter has been destroyed (happens when closing a # EditorMainWindow instance) return if close_splitter: # editorstack just closed was the last widget in this QSplitter self.close() return self.__give_focus_to_remaining_editor() def editorsplitter_closed(self): if DEBUG_EDITOR: print("method 'editorsplitter_closed':", file=STDOUT) print(" self :", self, file=STDOUT) # print >>STDOUT, " sender:", self.sender() try: close_splitter = self.count() == 1 and self.editorstack is None except RuntimeError: # editorsplitter has been destroyed (happens when closing a # EditorMainWindow instance) return if close_splitter: # editorsplitter just closed was the last widget in this QSplitter self.close() return elif self.count() == 2 and self.editorstack: # back to the initial state: a single editorstack instance, # as a single widget in this QSplitter: orientation may be changed self.editorstack.reset_orientation() self.__give_focus_to_remaining_editor() def split(self, orientation=Qt.Vertical): self.setOrientation(orientation) self.editorstack.set_orientation(orientation) editorsplitter = EditorSplitter(self.parent(), self.plugin, self.menu_actions, register_editorstack_cb=self.register_editorstack_cb, unregister_editorstack_cb=self.unregister_editorstack_cb) self.addWidget(editorsplitter) editorsplitter.destroyed.connect(lambda: self.editorsplitter_closed()) current_editor = editorsplitter.editorstack.get_current_editor() if current_editor is not None: current_editor.setFocus() def iter_editorstacks(self): editorstacks = [(self.widget(0), self.orientation())] if self.count() > 1: editorsplitter = self.widget(1) editorstacks += editorsplitter.iter_editorstacks() return editorstacks def get_layout_settings(self): """Return layout state""" splitsettings = [] for editorstack, orientation in self.iter_editorstacks(): clines = [] cfname = '' orientation = False if hasattr(editorstack, 'data'): clines = [finfo.editor.get_cursor_line_number() for finfo in editorstack.data] cfname = editorstack.get_current_filename() splitsettings.append((orientation == Qt.Vertical, cfname, clines)) return dict(hexstate=qbytearray_to_str(self.saveState()), sizes=self.sizes(), splitsettings=splitsettings) def set_layout_settings(self, settings): """Restore layout state""" splitsettings = settings.get('splitsettings') if splitsettings is None: return splitter = self editor = None for index, (is_vertical, cfname, clines) in enumerate(splitsettings): if index > 0: splitter.split(Qt.Vertical if is_vertical else Qt.Horizontal) splitter = splitter.widget(1) editorstack = splitter.widget(0) for index, finfo in enumerate(editorstack.data): editor = finfo.editor # FIXME: Temporal fix try: editor.go_to_line(clines[index]) except IndexError: pass editorstack.set_current_filename(cfname) hexstate = settings.get('hexstate') if hexstate is not None: self.restoreState( QByteArray().fromHex( str(hexstate).encode('utf-8')) ) sizes = settings.get('sizes') if sizes is not None: self.setSizes(sizes) if editor is not None: editor.clearFocus() editor.setFocus() class EditorWidget(QSplitter): def __init__(self, parent, plugin, menu_actions, show_fullpath, fullpath_sorting, show_all_files, show_comments): QSplitter.__init__(self, parent) self.setAttribute(Qt.WA_DeleteOnClose) statusbar = parent.statusBar() # Create a status bar self.readwrite_status = ReadWriteStatus(self, statusbar) self.eol_status = EOLStatus(self, statusbar) self.encoding_status = EncodingStatus(self, statusbar) self.cursorpos_status = CursorPositionStatus(self, statusbar) self.editorstacks = [] self.plugin = plugin self.find_widget = FindReplace(self, enable_replace=True) self.plugin.register_widget_shortcuts(self.find_widget) self.find_widget.hide() self.outlineexplorer = OutlineExplorerWidget(self, show_fullpath=show_fullpath, fullpath_sorting=fullpath_sorting, show_all_files=show_all_files, show_comments=show_comments) self.outlineexplorer.edit_goto.connect( lambda filenames, goto, word: plugin.load(filenames=filenames, goto=goto, word=word, editorwindow=self.parent())) editor_widgets = QWidget(self) editor_layout = QVBoxLayout() editor_layout.setContentsMargins(0, 0, 0, 0) editor_widgets.setLayout(editor_layout) editorsplitter = EditorSplitter(self, plugin, menu_actions, register_editorstack_cb=self.register_editorstack, unregister_editorstack_cb=self.unregister_editorstack) self.editorsplitter = editorsplitter editor_layout.addWidget(editorsplitter) editor_layout.addWidget(self.find_widget) splitter = QSplitter(self) splitter.setContentsMargins(0, 0, 0, 0) splitter.addWidget(editor_widgets) splitter.addWidget(self.outlineexplorer) splitter.setStretchFactor(0, 5) splitter.setStretchFactor(1, 1) # Refreshing outline explorer editorsplitter.editorstack.initialize_outlineexplorer() def register_editorstack(self, editorstack): self.editorstacks.append(editorstack) if DEBUG_EDITOR: print("EditorWidget.register_editorstack:", editorstack, file=STDOUT) self.__print_editorstacks() self.plugin.last_focus_editorstack[self.parent()] = editorstack editorstack.set_closable( len(self.editorstacks) > 1 ) editorstack.set_outlineexplorer(self.outlineexplorer) editorstack.set_find_widget(self.find_widget) editorstack.reset_statusbar.connect(self.readwrite_status.hide) editorstack.reset_statusbar.connect(self.encoding_status.hide) editorstack.reset_statusbar.connect(self.cursorpos_status.hide) editorstack.readonly_changed.connect( self.readwrite_status.readonly_changed) editorstack.encoding_changed.connect( self.encoding_status.encoding_changed) editorstack.sig_editor_cursor_position_changed.connect( self.cursorpos_status.cursor_position_changed) editorstack.sig_refresh_eol_chars.connect(self.eol_status.eol_changed) self.plugin.register_editorstack(editorstack) oe_btn = create_toolbutton(self) oe_btn.setDefaultAction(self.outlineexplorer.visibility_action) editorstack.add_corner_widgets_to_tabbar([5, oe_btn]) def __print_editorstacks(self): print("%d editorstack(s) in editorwidget:" \ % len(self.editorstacks), file=STDOUT) for edst in self.editorstacks: print(" ", edst, file=STDOUT) def unregister_editorstack(self, editorstack): if DEBUG_EDITOR: print("EditorWidget.unregister_editorstack:", editorstack, file=STDOUT) self.plugin.unregister_editorstack(editorstack) self.editorstacks.pop(self.editorstacks.index(editorstack)) if DEBUG_EDITOR: self.__print_editorstacks() class EditorMainWindow(QMainWindow): def __init__(self, plugin, menu_actions, toolbar_list, menu_list, show_fullpath, fullpath_sorting, show_all_files, show_comments): QMainWindow.__init__(self) self.setAttribute(Qt.WA_DeleteOnClose) self.window_size = None self.editorwidget = EditorWidget(self, plugin, menu_actions, show_fullpath, fullpath_sorting, show_all_files, show_comments) self.setCentralWidget(self.editorwidget) # Give focus to current editor to update/show all status bar widgets editorstack = self.editorwidget.editorsplitter.editorstack editor = editorstack.get_current_editor() if editor is not None: editor.setFocus() self.setWindowTitle("Spyder - %s" % plugin.windowTitle()) self.setWindowIcon(plugin.windowIcon()) if toolbar_list: self.toolbars = [] for title, object_name, actions in toolbar_list: toolbar = self.addToolBar(title) toolbar.setObjectName(object_name) add_actions(toolbar, actions) self.toolbars.append(toolbar) if menu_list: quit_action = create_action(self, _("Close window"), icon="close_panel.png", tip=_("Close this window"), triggered=self.close) self.menus = [] for index, (title, actions) in enumerate(menu_list): menu = self.menuBar().addMenu(title) if index == 0: # File menu add_actions(menu, actions+[None, quit_action]) else: add_actions(menu, actions) self.menus.append(menu) def get_toolbars(self): """Get the toolbars.""" return self.toolbars def add_toolbars_to_menu(self, menu_title, actions): """Add toolbars to a menu.""" # Six is the position of the view menu in menus list # that you can find in plugins/editor.py setup_other_windows. view_menu = self.menus[6] if actions == self.toolbars and view_menu: toolbars = [] for toolbar in self.toolbars: action = toolbar.toggleViewAction() toolbars.append(action) add_actions(view_menu, toolbars) def load_toolbars(self): """Loads the last visible toolbars from the .ini file.""" toolbars_names = CONF.get('main', 'last_visible_toolbars', default=[]) if toolbars_names: dic = {} for toolbar in self.toolbars: dic[toolbar.objectName()] = toolbar toolbar.toggleViewAction().setChecked(False) toolbar.setVisible(False) for name in toolbars_names: if name in dic: dic[name].toggleViewAction().setChecked(True) dic[name].setVisible(True) def resizeEvent(self, event): """Reimplement Qt method""" if not self.isMaximized() and not self.isFullScreen(): self.window_size = self.size() QMainWindow.resizeEvent(self, event) def closeEvent(self, event): """Reimplement Qt method""" QMainWindow.closeEvent(self, event) if is_pyqt46: self.destroyed.emit() for editorstack in self.editorwidget.editorstacks[:]: if DEBUG_EDITOR: print("--> destroy_editorstack:", editorstack, file=STDOUT) editorstack.destroyed.emit() def get_layout_settings(self): """Return layout state""" splitsettings = self.editorwidget.editorsplitter.get_layout_settings() return dict(size=(self.window_size.width(), self.window_size.height()), pos=(self.pos().x(), self.pos().y()), is_maximized=self.isMaximized(), is_fullscreen=self.isFullScreen(), hexstate=qbytearray_to_str(self.saveState()), splitsettings=splitsettings) def set_layout_settings(self, settings): """Restore layout state""" size = settings.get('size') if size is not None: self.resize( QSize(*size) ) self.window_size = self.size() pos = settings.get('pos') if pos is not None: self.move( QPoint(*pos) ) hexstate = settings.get('hexstate') if hexstate is not None: self.restoreState( QByteArray().fromHex( str(hexstate).encode('utf-8')) ) if settings.get('is_maximized'): self.setWindowState(Qt.WindowMaximized) if settings.get('is_fullscreen'): self.setWindowState(Qt.WindowFullScreen) splitsettings = settings.get('splitsettings') if splitsettings is not None: self.editorwidget.editorsplitter.set_layout_settings(splitsettings) class EditorPluginExample(QSplitter): def __init__(self): QSplitter.__init__(self) menu_actions = [] self.editorstacks = [] self.editorwindows = [] self.last_focus_editorstack = {} # fake self.find_widget = FindReplace(self, enable_replace=True) self.outlineexplorer = OutlineExplorerWidget(self, show_fullpath=False, show_all_files=False) self.outlineexplorer.edit_goto.connect(self.go_to_file) self.editor_splitter = EditorSplitter(self, self, menu_actions, first=True) editor_widgets = QWidget(self) editor_layout = QVBoxLayout() editor_layout.setContentsMargins(0, 0, 0, 0) editor_widgets.setLayout(editor_layout) editor_layout.addWidget(self.editor_splitter) editor_layout.addWidget(self.find_widget) self.setContentsMargins(0, 0, 0, 0) self.addWidget(editor_widgets) self.addWidget(self.outlineexplorer) self.setStretchFactor(0, 5) self.setStretchFactor(1, 1) self.menu_actions = menu_actions self.toolbar_list = None self.menu_list = None self.setup_window([], []) def go_to_file(self, fname, lineno, text): editorstack = self.editorstacks[0] editorstack.set_current_filename(to_text_string(fname)) editor = editorstack.get_current_editor() editor.go_to_line(lineno, word=text) def closeEvent(self, event): for win in self.editorwindows[:]: win.close() if DEBUG_EDITOR: print(len(self.editorwindows), ":", self.editorwindows, file=STDOUT) print(len(self.editorstacks), ":", self.editorstacks, file=STDOUT) event.accept() def load(self, fname): QApplication.processEvents() editorstack = self.editorstacks[0] editorstack.load(fname) editorstack.analyze_script() def register_editorstack(self, editorstack): if DEBUG_EDITOR: print("FakePlugin.register_editorstack:", editorstack, file=STDOUT) self.editorstacks.append(editorstack) if self.isAncestorOf(editorstack): # editorstack is a child of the Editor plugin editorstack.set_fullpath_sorting_enabled(True) editorstack.set_closable( len(self.editorstacks) > 1 ) editorstack.set_outlineexplorer(self.outlineexplorer) editorstack.set_find_widget(self.find_widget) oe_btn = create_toolbutton(self) oe_btn.setDefaultAction(self.outlineexplorer.visibility_action) editorstack.add_corner_widgets_to_tabbar([5, oe_btn]) action = QAction(self) editorstack.set_io_actions(action, action, action, action) font = QFont("Courier New") font.setPointSize(10) editorstack.set_default_font(font, color_scheme='Spyder') editorstack.sig_close_file.connect(self.close_file_in_all_editorstacks) editorstack.file_saved.connect(self.file_saved_in_editorstack) editorstack.file_renamed_in_data.connect( self.file_renamed_in_data_in_editorstack) editorstack.create_new_window.connect(self.create_new_window) editorstack.plugin_load.connect(self.load) def unregister_editorstack(self, editorstack): if DEBUG_EDITOR: print("FakePlugin.unregister_editorstack:", editorstack, file=STDOUT) self.editorstacks.pop(self.editorstacks.index(editorstack)) def clone_editorstack(self, editorstack): editorstack.clone_from(self.editorstacks[0]) def setup_window(self, toolbar_list, menu_list): self.toolbar_list = toolbar_list self.menu_list = menu_list def create_new_window(self): window = EditorMainWindow(self, self.menu_actions, self.toolbar_list, self.menu_list, show_fullpath=False, fullpath_sorting=True, show_all_files=False, show_comments=True) window.resize(self.size()) window.show() self.register_editorwindow(window) window.destroyed.connect(lambda: self.unregister_editorwindow(window)) def register_editorwindow(self, window): if DEBUG_EDITOR: print("register_editorwindowQObject*:", window, file=STDOUT) self.editorwindows.append(window) def unregister_editorwindow(self, window): if DEBUG_EDITOR: print("unregister_editorwindow:", window, file=STDOUT) self.editorwindows.pop(self.editorwindows.index(window)) def get_focus_widget(self): pass @Slot(str, str) def close_file_in_all_editorstacks(self, editorstack_id_str, filename): for editorstack in self.editorstacks: if str(id(editorstack)) != editorstack_id_str: editorstack.blockSignals(True) index = editorstack.get_index_from_filename(filename) editorstack.close_file(index, force=True) editorstack.blockSignals(False) # This method is never called in this plugin example. It's here only # to show how to use the file_saved signal (see above). @Slot(str, str, str) def file_saved_in_editorstack(self, editorstack_id_str, original_filename, filename): """A file was saved in editorstack, this notifies others""" for editorstack in self.editorstacks: if str(id(editorstack)) != editorstack_id_str: editorstack.file_saved_in_other_editorstack(original_filename, filename) # This method is never called in this plugin example. It's here only # to show how to use the file_saved signal (see above). @Slot(str, str, str) def file_renamed_in_data_in_editorstack(self, editorstack_id_str, original_filename, filename): """A file was renamed in data in editorstack, this notifies others""" for editorstack in self.editorstacks: if str(id(editorstack)) != editorstack_id_str: editorstack.rename_in_data(original_filename, filename) def register_widget_shortcuts(self, widget): """Fake!""" pass def test(): from spyder.utils.qthelpers import qapplication from spyder.config.base import get_module_path from spyder.utils.introspection.manager import IntrospectionManager cur_dir = osp.join(get_module_path('spyder'), 'widgets') app = qapplication(test_time=8) introspector = IntrospectionManager() test = EditorPluginExample() test.resize(900, 700) test.show() editorstack = test.editor_splitter.editorstack editorstack.set_introspector(introspector) introspector.set_editor_widget(editorstack) import time t0 = time.time() test.load(osp.join(cur_dir, "editor.py")) test.load(osp.join(cur_dir, "explorer.py")) test.load(osp.join(cur_dir, "variableexplorer", "collectionseditor.py")) test.load(osp.join(cur_dir, "sourcecode", "codeeditor.py")) print("Elapsed time: %.3f s" % (time.time()-t0)) # spyder: test-skip sys.exit(app.exec_()) if __name__ == "__main__": test() spyder-3.2.6/spyder/widgets/arraybuilder.py0000664000175000017500000003037513026261006021641 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Numpy Matrix/Array Builder Widget. """ # TODO: # -Set font based on caller? editor console? and adjust size of widget # -Fix positioning # -Use the same font as editor/console? # Standard library imports from __future__ import division import re # Third party imports from qtpy.QtCore import QEvent, QPoint, Qt from qtpy.QtWidgets import (QDialog, QHBoxLayout, QLineEdit, QTableWidget, QTableWidgetItem, QToolButton, QToolTip, QWidget) # Local imports from spyder.config.base import _ from spyder.utils import icon_manager as ima from spyder.widgets.helperwidgets import HelperToolButton # Constants SHORTCUT_TABLE = "Ctrl+M" SHORTCUT_INLINE = "Ctrl+Alt+M" ELEMENT_SEPARATOR = ', ' ROW_SEPARATOR = ';' BRACES = '], [' NAN_VALUES = ['nan', 'NAN', 'NaN', 'Na', 'NA', 'na'] class NumpyArrayInline(QLineEdit): def __init__(self, parent): QLineEdit.__init__(self, parent) self._parent = parent def keyPressEvent(self, event): """ Qt override. """ if event.key() in [Qt.Key_Enter, Qt.Key_Return]: self._parent.process_text() if self._parent.is_valid(): self._parent.keyPressEvent(event) else: QLineEdit.keyPressEvent(self, event) # to catch the Tab key event def event(self, event): """ Qt override. This is needed to be able to intercept the Tab key press event. """ if event.type() == QEvent.KeyPress: if (event.key() == Qt.Key_Tab or event.key() == Qt.Key_Space): text = self.text() cursor = self.cursorPosition() # fix to include in "undo/redo" history if cursor != 0 and text[cursor-1] == ' ': text = text[:cursor-1] + ROW_SEPARATOR + ' ' +\ text[cursor:] else: text = text[:cursor] + ' ' + text[cursor:] self.setCursorPosition(cursor) self.setText(text) self.setCursorPosition(cursor + 1) return False return QWidget.event(self, event) class NumpyArrayTable(QTableWidget): def __init__(self, parent): QTableWidget.__init__(self, parent) self._parent = parent self.setRowCount(2) self.setColumnCount(2) self.reset_headers() # signals self.cellChanged.connect(self.cell_changed) def keyPressEvent(self, event): """ Qt override. """ if event.key() in [Qt.Key_Enter, Qt.Key_Return]: QTableWidget.keyPressEvent(self, event) # To avoid having to enter one final tab self.setDisabled(True) self.setDisabled(False) self._parent.keyPressEvent(event) else: QTableWidget.keyPressEvent(self, event) def cell_changed(self, row, col): """ """ item = self.item(row, col) value = None if item: rows = self.rowCount() cols = self.columnCount() value = item.text() if value: if row == rows - 1: self.setRowCount(rows + 1) if col == cols - 1: self.setColumnCount(cols + 1) self.reset_headers() def reset_headers(self): """ Update the column and row numbering in the headers. """ rows = self.rowCount() cols = self.columnCount() for r in range(rows): self.setVerticalHeaderItem(r, QTableWidgetItem(str(r))) for c in range(cols): self.setHorizontalHeaderItem(c, QTableWidgetItem(str(c))) self.setColumnWidth(c, 40) def text(self): """ Return the entered array in a parseable form. """ text = [] rows = self.rowCount() cols = self.columnCount() # handle empty table case if rows == 2 and cols == 2: item = self.item(0, 0) if item is None: return '' for r in range(rows - 1): for c in range(cols - 1): item = self.item(r, c) if item is not None: value = item.text() else: value = '0' if not value.strip(): value = '0' text.append(' ') text.append(value) text.append(ROW_SEPARATOR) return ''.join(text[:-1]) # to remove the final uneeded ; class NumpyArrayDialog(QDialog): def __init__(self, parent=None, inline=True, offset=0, force_float=False): QDialog.__init__(self, parent=parent) self._parent = parent self._text = None self._valid = None self._offset = offset # TODO: add this as an option in the General Preferences? self._force_float = force_float self._help_inline = _(""" Numpy Array/Matrix Helper
    Type an array in Matlab : [1 2;3 4]
    or Spyder simplified syntax : 1 2;3 4

    Hit 'Enter' for array or 'Ctrl+Enter' for matrix.

    Hint:
    Use two spaces or two tabs to generate a ';'. """) self._help_table = _(""" Numpy Array/Matrix Helper
    Enter an array in the table.
    Use Tab to move between cells.

    Hit 'Enter' for array or 'Ctrl+Enter' for matrix.

    Hint:
    Use two tabs at the end of a row to move to the next row. """) # Widgets self._button_warning = QToolButton() self._button_help = HelperToolButton() self._button_help.setIcon(ima.icon('MessageBoxInformation')) style = """ QToolButton { border: 1px solid grey; padding:0px; border-radius: 2px; background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #f6f7fa, stop: 1 #dadbde); } """ self._button_help.setStyleSheet(style) if inline: self._button_help.setToolTip(self._help_inline) self._text = NumpyArrayInline(self) self._widget = self._text else: self._button_help.setToolTip(self._help_table) self._table = NumpyArrayTable(self) self._widget = self._table style = """ QDialog { margin:0px; border: 1px solid grey; padding:0px; border-radius: 2px; }""" self.setStyleSheet(style) style = """ QToolButton { margin:1px; border: 0px solid grey; padding:0px; border-radius: 0px; }""" self._button_warning.setStyleSheet(style) # widget setup self.setWindowFlags(Qt.Window | Qt.Dialog | Qt.FramelessWindowHint) self.setModal(True) self.setWindowOpacity(0.90) self._widget.setMinimumWidth(200) # layout self._layout = QHBoxLayout() self._layout.addWidget(self._widget) self._layout.addWidget(self._button_warning, 1, Qt.AlignTop) self._layout.addWidget(self._button_help, 1, Qt.AlignTop) self.setLayout(self._layout) self._widget.setFocus() def keyPressEvent(self, event): """ Qt override. """ QToolTip.hideText() ctrl = event.modifiers() & Qt.ControlModifier if event.key() in [Qt.Key_Enter, Qt.Key_Return]: if ctrl: self.process_text(array=False) else: self.process_text(array=True) self.accept() else: QDialog.keyPressEvent(self, event) def event(self, event): """ Qt Override. Usefull when in line edit mode. """ if event.type() == QEvent.KeyPress and event.key() == Qt.Key_Tab: return False return QWidget.event(self, event) def process_text(self, array=True): """ Construct the text based on the entered content in the widget. """ if array: prefix = 'np.array([[' else: prefix = 'np.matrix([[' suffix = ']])' values = self._widget.text().strip() if values != '': # cleans repeated spaces exp = r'(\s*)' + ROW_SEPARATOR + r'(\s*)' values = re.sub(exp, ROW_SEPARATOR, values) values = re.sub("\s+", " ", values) values = re.sub("]$", "", values) values = re.sub("^\[", "", values) values = re.sub(ROW_SEPARATOR + r'*$', '', values) # replaces spaces by commas values = values.replace(' ', ELEMENT_SEPARATOR) # iterate to find number of rows and columns new_values = [] rows = values.split(ROW_SEPARATOR) nrows = len(rows) ncols = [] for row in rows: new_row = [] elements = row.split(ELEMENT_SEPARATOR) ncols.append(len(elements)) for e in elements: num = e # replaces not defined values if num in NAN_VALUES: num = 'np.nan' # Convert numbers to floating point if self._force_float: try: num = str(float(e)) except: pass new_row.append(num) new_values.append(ELEMENT_SEPARATOR.join(new_row)) new_values = ROW_SEPARATOR.join(new_values) values = new_values # Check validity if len(set(ncols)) == 1: self._valid = True else: self._valid = False # Single rows are parsed as 1D arrays/matrices if nrows == 1: prefix = prefix[:-1] suffix = suffix.replace("]])", "])") # Fix offset offset = self._offset braces = BRACES.replace(' ', '\n' + ' '*(offset + len(prefix) - 1)) values = values.replace(ROW_SEPARATOR, braces) text = "{0}{1}{2}".format(prefix, values, suffix) self._text = text else: self._text = '' self.update_warning() def update_warning(self): """ Updates the icon and tip based on the validity of the array content. """ widget = self._button_warning if not self.is_valid(): tip = _('Array dimensions not valid') widget.setIcon(ima.icon('MessageBoxWarning')) widget.setToolTip(tip) QToolTip.showText(self._widget.mapToGlobal(QPoint(0, 5)), tip) else: self._button_warning.setToolTip('') def is_valid(self): """ Return if the current array state is valid. """ return self._valid def text(self): """ Return the parsed array/matrix text. """ return self._text @property def array_widget(self): """ Return the array builder widget. """ return self._widget def test(): # pragma: no cover from spyder.utils.qthelpers import qapplication app = qapplication() dlg_table = NumpyArrayDialog(None, inline=False) dlg_inline = NumpyArrayDialog(None, inline=True) dlg_table.show() dlg_inline.show() app.exec_() if __name__ == "__main__": # pragma: no cover test() spyder-3.2.6/spyder/widgets/variableexplorer/0000775000175000017500000000000013225025007022140 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/widgets/variableexplorer/namespacebrowser.py0000664000175000017500000004646613224740762026105 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Namespace browser widget This is the main widget used in the Variable Explorer plugin """ # Standard library imports import os.path as osp # Third library imports (qtpy) from qtpy.compat import getsavefilename, getopenfilenames from qtpy.QtCore import Qt, Signal, Slot from qtpy.QtGui import QCursor from qtpy.QtWidgets import (QApplication, QHBoxLayout, QInputDialog, QMenu, QMessageBox, QToolButton, QVBoxLayout, QWidget) # Third party imports (others) import cloudpickle # Local imports from spyder.config.base import _, get_supported_types from spyder.config.main import CONF from spyder.py3compat import is_text_string, to_text_string from spyder.utils import encoding from spyder.utils import icon_manager as ima from spyder.utils.iofuncs import iofunctions from spyder.utils.misc import fix_reference_name, getcwd_or_home from spyder.utils.programs import is_module_installed from spyder.utils.qthelpers import (add_actions, create_action, create_toolbutton, create_plugin_layout) from spyder.widgets.variableexplorer.collectionseditor import ( RemoteCollectionsEditorTableView) from spyder.widgets.variableexplorer.importwizard import ImportWizard from spyder.widgets.variableexplorer.utils import REMOTE_SETTINGS SUPPORTED_TYPES = get_supported_types() # To be able to get and set variables between Python 2 and 3 PICKLE_PROTOCOL = 2 class NamespaceBrowser(QWidget): """Namespace browser (global variables explorer widget)""" sig_option_changed = Signal(str, object) sig_collapse = Signal() def __init__(self, parent): QWidget.__init__(self, parent) self.shellwidget = None self.is_visible = True self.setup_in_progress = None # Remote dict editor settings self.check_all = None self.exclude_private = None self.exclude_uppercase = None self.exclude_capitalized = None self.exclude_unsupported = None self.excluded_names = None self.minmax = None # Other setting self.dataframe_format = None self.editor = None self.exclude_private_action = None self.exclude_uppercase_action = None self.exclude_capitalized_action = None self.exclude_unsupported_action = None self.filename = None self.var_properties = {} def setup(self, check_all=None, exclude_private=None, exclude_uppercase=None, exclude_capitalized=None, exclude_unsupported=None, excluded_names=None, minmax=None, dataframe_format=None): """ Setup the namespace browser with provided settings. Args: dataframe_format (string): default floating-point format for DataFrame editor """ assert self.shellwidget is not None self.check_all = check_all self.exclude_private = exclude_private self.exclude_uppercase = exclude_uppercase self.exclude_capitalized = exclude_capitalized self.exclude_unsupported = exclude_unsupported self.excluded_names = excluded_names self.minmax = minmax self.dataframe_format = dataframe_format if self.editor is not None: self.editor.setup_menu(minmax) self.editor.set_dataframe_format(dataframe_format) self.exclude_private_action.setChecked(exclude_private) self.exclude_uppercase_action.setChecked(exclude_uppercase) self.exclude_capitalized_action.setChecked(exclude_capitalized) self.exclude_unsupported_action.setChecked(exclude_unsupported) self.refresh_table() return self.editor = RemoteCollectionsEditorTableView( self, None, minmax=minmax, dataframe_format=dataframe_format, get_value_func=self.get_value, set_value_func=self.set_value, new_value_func=self.set_value, remove_values_func=self.remove_values, copy_value_func=self.copy_value, is_list_func=self.is_list, get_len_func=self.get_len, is_array_func=self.is_array, is_image_func=self.is_image, is_dict_func=self.is_dict, is_data_frame_func=self.is_data_frame, is_series_func=self.is_series, get_array_shape_func=self.get_array_shape, get_array_ndim_func=self.get_array_ndim, plot_func=self.plot, imshow_func=self.imshow, show_image_func=self.show_image) self.editor.sig_option_changed.connect(self.sig_option_changed.emit) self.editor.sig_files_dropped.connect(self.import_data) # Setup layout blayout = QHBoxLayout() toolbar = self.setup_toolbar(exclude_private, exclude_uppercase, exclude_capitalized, exclude_unsupported) for widget in toolbar: blayout.addWidget(widget) # Options menu options_button = create_toolbutton(self, text=_('Options'), icon=ima.icon('tooloptions')) options_button.setPopupMode(QToolButton.InstantPopup) menu = QMenu(self) editor = self.editor actions = [self.exclude_private_action, self.exclude_uppercase_action, self.exclude_capitalized_action, self.exclude_unsupported_action, None] if is_module_installed('numpy'): actions.append(editor.minmax_action) add_actions(menu, actions) options_button.setMenu(menu) blayout.addStretch() blayout.addWidget(options_button) layout = create_plugin_layout(blayout, self.editor) self.setLayout(layout) self.sig_option_changed.connect(self.option_changed) def set_shellwidget(self, shellwidget): """Bind shellwidget instance to namespace browser""" self.shellwidget = shellwidget shellwidget.set_namespacebrowser(self) def setup_toolbar(self, exclude_private, exclude_uppercase, exclude_capitalized, exclude_unsupported): """Setup toolbar""" self.setup_in_progress = True toolbar = [] load_button = create_toolbutton(self, text=_('Import data'), icon=ima.icon('fileimport'), triggered=lambda: self.import_data()) self.save_button = create_toolbutton(self, text=_("Save data"), icon=ima.icon('filesave'), triggered=lambda: self.save_data(self.filename)) self.save_button.setEnabled(False) save_as_button = create_toolbutton(self, text=_("Save data as..."), icon=ima.icon('filesaveas'), triggered=self.save_data) reset_namespace_button = create_toolbutton( self, text=_("Remove all variables"), icon=ima.icon('editdelete'), triggered=self.reset_namespace) toolbar += [load_button, self.save_button, save_as_button, reset_namespace_button] self.exclude_private_action = create_action(self, _("Exclude private references"), tip=_("Exclude references which name starts" " with an underscore"), toggled=lambda state: self.sig_option_changed.emit('exclude_private', state)) self.exclude_private_action.setChecked(exclude_private) self.exclude_uppercase_action = create_action(self, _("Exclude all-uppercase references"), tip=_("Exclude references which name is uppercase"), toggled=lambda state: self.sig_option_changed.emit('exclude_uppercase', state)) self.exclude_uppercase_action.setChecked(exclude_uppercase) self.exclude_capitalized_action = create_action(self, _("Exclude capitalized references"), tip=_("Exclude references which name starts with an " "uppercase character"), toggled=lambda state: self.sig_option_changed.emit('exclude_capitalized', state)) self.exclude_capitalized_action.setChecked(exclude_capitalized) self.exclude_unsupported_action = create_action(self, _("Exclude unsupported data types"), tip=_("Exclude references to unsupported data types" " (i.e. which won't be handled/saved correctly)"), toggled=lambda state: self.sig_option_changed.emit('exclude_unsupported', state)) self.exclude_unsupported_action.setChecked(exclude_unsupported) self.setup_in_progress = False return toolbar def option_changed(self, option, value): """Option has changed""" setattr(self, to_text_string(option), value) self.shellwidget.set_namespace_view_settings() self.refresh_table() def visibility_changed(self, enable): """Notify the widget whether its container (the namespace browser plugin is visible or not""" # This is slowing down Spyder a lot if too much data is present in # the Variable Explorer, and users give focus to it after being hidden. # This also happens when the Variable Explorer is visible and users # give focus to Spyder after using another application (like Chrome # or Firefox). # That's why we've decided to remove this feature # Fixes Issue 2593 # # self.is_visible = enable # if enable: # self.refresh_table() pass def get_view_settings(self): """Return dict editor view settings""" settings = {} for name in REMOTE_SETTINGS: settings[name] = getattr(self, name) return settings def refresh_table(self): """Refresh variable table""" if self.is_visible and self.isVisible(): self.shellwidget.refresh_namespacebrowser() try: self.editor.resizeRowToContents() except TypeError: pass def process_remote_view(self, remote_view): """Process remote view""" if remote_view is not None: self.set_data(remote_view) def set_var_properties(self, properties): """Set properties of variables""" if properties is not None: self.var_properties = properties #------ Remote commands ------------------------------------ def get_value(self, name): value = self.shellwidget.get_value(name) # Reset temporal variable where value is saved to # save memory self.shellwidget._kernel_value = None return value def set_value(self, name, value): """Set value for a variable.""" try: # We need to enclose values in a list to be able to send # them to the kernel in Python 2 svalue = [cloudpickle.dumps(value, protocol=PICKLE_PROTOCOL)] self.shellwidget.set_value(name, svalue) except TypeError as e: QMessageBox.critical(self, _("Error"), "TypeError: %s" % to_text_string(e)) self.refresh_table() def remove_values(self, names): for name in names: self.shellwidget.remove_value(name) self.refresh_table() def copy_value(self, orig_name, new_name): self.shellwidget.copy_value(orig_name, new_name) self.refresh_table() def is_list(self, name): """Return True if variable is a list or a tuple""" return self.var_properties[name]['is_list'] def is_dict(self, name): """Return True if variable is a dictionary""" return self.var_properties[name]['is_dict'] def get_len(self, name): """Return sequence length""" return self.var_properties[name]['len'] def is_array(self, name): """Return True if variable is a NumPy array""" return self.var_properties[name]['is_array'] def is_image(self, name): """Return True if variable is a PIL.Image image""" return self.var_properties[name]['is_image'] def is_data_frame(self, name): """Return True if variable is a DataFrame""" return self.var_properties[name]['is_data_frame'] def is_series(self, name): """Return True if variable is a Series""" return self.var_properties[name]['is_series'] def get_array_shape(self, name): """Return array's shape""" return self.var_properties[name]['array_shape'] def get_array_ndim(self, name): """Return array's ndim""" return self.var_properties[name]['array_ndim'] def plot(self, name, funcname): sw = self.shellwidget if sw._reading: sw.dbg_exec_magic('varexp', '--%s %s' % (funcname, name)) else: sw.execute("%%varexp --%s %s" % (funcname, name)) def imshow(self, name): sw = self.shellwidget if sw._reading: sw.dbg_exec_magic('varexp', '--imshow %s' % name) else: sw.execute("%%varexp --imshow %s" % name) def show_image(self, name): command = "%s.show()" % name sw = self.shellwidget if sw._reading: sw.kernel_client.input(command) else: sw.execute(command) # ------ Set, load and save data ------------------------------------------ def set_data(self, data): """Set data.""" if data != self.editor.model.get_data(): self.editor.set_data(data) self.editor.adjust_columns() def collapse(self): """Collapse.""" self.sig_collapse.emit() @Slot(bool) @Slot(list) 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_or_home() 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, _("Unsupported file extension '%s'

    " "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) 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() self.set_value(var_name, clip_data) except Exception as error: error_message = str(error) else: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() error_message = self.shellwidget.load_data(self.filename, ext) self.shellwidget._kernel_reply = None QApplication.restoreOverrideCursor() QApplication.processEvents() if error_message is not None: QMessageBox.critical(self, title, _("Unable to load '%s'" "

    Error message:
    %s" ) % (self.filename, error_message)) self.refresh_table() @Slot() def reset_namespace(self): warning = CONF.get('ipython_console', 'show_reset_namespace_warning') self.shellwidget.reset_namespace(warning=warning, silent=True, message=True) @Slot() def save_data(self, filename=None): """Save data""" if filename is None: filename = self.filename if filename is None: filename = getcwd_or_home() filename, _selfilter = getsavefilename(self, _("Save data"), filename, iofunctions.save_filters) if filename: self.filename = filename else: return False QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() error_message = self.shellwidget.save_namespace(self.filename) self.shellwidget._kernel_reply = None QApplication.restoreOverrideCursor() QApplication.processEvents() if error_message is not None: QMessageBox.critical(self, _("Save data"), _("Unable to save current workspace" "

    Error message:
    %s") % error_message) self.save_button.setEnabled(self.filename is not None) spyder-3.2.6/spyder/widgets/variableexplorer/arrayeditor.py0000664000175000017500000010001313224121062025027 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ NumPy Array Editor Dialog based on Qt """ # pylint: disable=C0103 # pylint: disable=R0903 # pylint: disable=R0911 # pylint: disable=R0201 # Standard library imports from __future__ import print_function # Third party imports from qtpy.compat import from_qvariant, to_qvariant from qtpy.QtCore import (QAbstractTableModel, QItemSelection, QLocale, QItemSelectionRange, QModelIndex, Qt, Slot) from qtpy.QtGui import QColor, QCursor, QDoubleValidator, QKeySequence from qtpy.QtWidgets import (QAbstractItemDelegate, QApplication, QCheckBox, QComboBox, QDialog, QDialogButtonBox, QGridLayout, QHBoxLayout, QInputDialog, QItemDelegate, QLabel, QLineEdit, QMenu, QMessageBox, QPushButton, QSpinBox, QStackedWidget, QTableView, QVBoxLayout, QWidget) import numpy as np # Local imports from spyder.config.base import _ from spyder.config.fonts import DEFAULT_SMALL_DELTA from spyder.config.gui import get_font, config_shortcut from spyder.py3compat import (io, is_binary_string, is_string, is_text_string, PY3, to_binary_string, to_text_string) from spyder.utils import icon_manager as ima from spyder.utils.qthelpers import add_actions, create_action, keybinding # Note: string and unicode data types will be formatted with '%s' (see below) SUPPORTED_FORMATS = { 'single': '%.6g', 'double': '%.6g', 'float_': '%.6g', 'longfloat': '%.6g', 'float16': '%.6g', 'float32': '%.6g', 'float64': '%.6g', 'float96': '%.6g', 'float128': '%.6g', 'csingle': '%r', 'complex_': '%r', 'clongfloat': '%r', 'complex64': '%r', 'complex128': '%r', 'complex192': '%r', 'complex256': '%r', 'byte': '%d', 'bytes8': '%s', 'short': '%d', 'intc': '%d', 'int_': '%d', 'longlong': '%d', 'intp': '%d', 'int8': '%d', 'int16': '%d', 'int32': '%d', 'int64': '%d', 'ubyte': '%d', 'ushort': '%d', 'uintc': '%d', 'uint': '%d', 'ulonglong': '%d', 'uintp': '%d', 'uint8': '%d', 'uint16': '%d', 'uint32': '%d', 'uint64': '%d', 'bool_': '%r', 'bool8': '%r', 'bool': '%r', } LARGE_SIZE = 5e5 LARGE_NROWS = 1e5 LARGE_COLS = 60 #============================================================================== # Utility functions #============================================================================== def is_float(dtype): """Return True if datatype dtype is a float kind""" return ('float' in dtype.name) or dtype.name in ['single', 'double'] def is_number(dtype): """Return True is datatype dtype is a number kind""" return is_float(dtype) or ('int' in dtype.name) or ('long' in dtype.name) \ or ('short' in dtype.name) def get_idx_rect(index_list): """Extract the boundaries from a list of indexes""" rows, cols = list(zip(*[(i.row(), i.column()) for i in index_list])) return ( min(rows), max(rows), min(cols), max(cols) ) #============================================================================== # Main classes #============================================================================== class ArrayModel(QAbstractTableModel): """Array Editor Table Model""" ROWS_TO_LOAD = 500 COLS_TO_LOAD = 40 def __init__(self, data, format="%.6g", xlabels=None, ylabels=None, readonly=False, parent=None): QAbstractTableModel.__init__(self) self.dialog = parent self.changes = {} self.xlabels = xlabels self.ylabels = ylabels self.readonly = readonly self.test_array = np.array([0], dtype=data.dtype) # for complex numbers, shading will be based on absolute value # but for all other types it will be the real part if data.dtype in (np.complex64, np.complex128): self.color_func = np.abs else: self.color_func = np.real # Backgroundcolor settings huerange = [.66, .99] # Hue self.sat = .7 # Saturation self.val = 1. # Value self.alp = .6 # Alpha-channel self._data = data self._format = format self.total_rows = self._data.shape[0] self.total_cols = self._data.shape[1] size = self.total_rows * self.total_cols try: self.vmin = np.nanmin(self.color_func(data)) self.vmax = np.nanmax(self.color_func(data)) if self.vmax == self.vmin: self.vmin -= 1 self.hue0 = huerange[0] self.dhue = huerange[1]-huerange[0] self.bgcolor_enabled = True except (TypeError, ValueError): self.vmin = None self.vmax = None self.hue0 = None self.dhue = None self.bgcolor_enabled = False # Use paging when the total size, number of rows or number of # columns is too large if size > LARGE_SIZE: self.rows_loaded = self.ROWS_TO_LOAD self.cols_loaded = self.COLS_TO_LOAD else: if self.total_rows > LARGE_NROWS: self.rows_loaded = self.ROWS_TO_LOAD else: self.rows_loaded = self.total_rows if self.total_cols > LARGE_COLS: self.cols_loaded = self.COLS_TO_LOAD else: self.cols_loaded = self.total_cols def get_format(self): """Return current format""" # Avoid accessing the private attribute _format from outside return self._format def get_data(self): """Return data""" return self._data def set_format(self, format): """Change display format""" self._format = format self.reset() def columnCount(self, qindex=QModelIndex()): """Array column number""" if self.total_cols <= self.cols_loaded: return self.total_cols else: return self.cols_loaded def rowCount(self, qindex=QModelIndex()): """Array row number""" if self.total_rows <= self.rows_loaded: return self.total_rows else: return self.rows_loaded def can_fetch_more(self, rows=False, columns=False): if rows: if self.total_rows > self.rows_loaded: return True else: return False if columns: if self.total_cols > self.cols_loaded: return True else: return False def fetch_more(self, rows=False, columns=False): if self.can_fetch_more(rows=rows): reminder = self.total_rows - self.rows_loaded items_to_fetch = min(reminder, self.ROWS_TO_LOAD) self.beginInsertRows(QModelIndex(), self.rows_loaded, self.rows_loaded + items_to_fetch - 1) self.rows_loaded += items_to_fetch self.endInsertRows() if self.can_fetch_more(columns=columns): reminder = self.total_cols - self.cols_loaded items_to_fetch = min(reminder, self.COLS_TO_LOAD) self.beginInsertColumns(QModelIndex(), self.cols_loaded, self.cols_loaded + items_to_fetch - 1) self.cols_loaded += items_to_fetch self.endInsertColumns() def bgcolor(self, state): """Toggle backgroundcolor""" self.bgcolor_enabled = state > 0 self.reset() def get_value(self, index): i = index.row() j = index.column() if len(self._data.shape) == 1: value = self._data[j] else: value = self._data[i, j] return self.changes.get((i, j), value) 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: try: return to_qvariant(self._format % value) except TypeError: self.readonly = True return repr(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: try: hue = (self.hue0 + self.dhue * (float(self.vmax) - self.color_func(value)) / (float(self.vmax) - self.vmin)) hue = float(np.abs(hue)) color = QColor.fromHsvF(hue, self.sat, self.val, self.alp) return to_qvariant(color) except TypeError: return to_qvariant() elif role == Qt.FontRole: return to_qvariant(get_font(font_size_delta=DEFAULT_SMALL_DELTA)) return to_qvariant() 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) dtype = self._data.dtype.name if dtype == "bool": try: val = bool(float(value)) except ValueError: val = value.lower() == "true" elif dtype.startswith("string") or dtype.startswith("bytes"): val = to_binary_string(value, 'utf8') elif dtype.startswith("unicode") or dtype.startswith("str"): 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("OverflowError: " + str(e)) # spyder: test-skip QMessageBox.critical(self.dialog, "Error", "Overflow error: %s" % str(e)) return False # Add change to self.changes self.changes[(i, j)] = val self.dataChanged.emit(index, index) if not is_string(val): if val > self.vmax: self.vmax = val if val < self.vmin: self.vmin = val return True def flags(self, index): """Set editable flag""" if not index.isValid(): return Qt.ItemIsEnabled return Qt.ItemFlags(QAbstractTableModel.flags(self, index)| Qt.ItemIsEditable) def headerData(self, section, orientation, role=Qt.DisplayRole): """Set header data""" if role != Qt.DisplayRole: return to_qvariant() labels = self.xlabels if orientation == Qt.Horizontal else self.ylabels if labels is None: return to_qvariant(int(section)) else: return to_qvariant(labels[section]) def reset(self): self.beginResetModel() self.endResetModel() class ArrayDelegate(QItemDelegate): """Array Editor Item Delegate""" def __init__(self, dtype, parent=None): QItemDelegate.__init__(self, parent) self.dtype = dtype def createEditor(self, parent, option, index): """Create editor widget""" model = index.model() value = model.get_value(index) if model._data.dtype.name == "bool": value = not value model.setData(index, to_qvariant(value)) return elif value is not np.ma.masked: editor = QLineEdit(parent) editor.setFont(get_font(font_size_delta=DEFAULT_SMALL_DELTA)) editor.setAlignment(Qt.AlignCenter) if is_number(self.dtype): validator = QDoubleValidator(editor) validator.setLocale(QLocale('C')) editor.setValidator(validator) editor.returnPressed.connect(self.commitAndCloseEditor) return editor def commitAndCloseEditor(self): """Commit and close editor""" editor = self.sender() # Avoid a segfault with PyQt5. Variable value won't be changed # but at least Spyder won't crash. It seems generated by a # bug in sip. See # http://comments.gmane.org/gmane.comp.python.pyqt-pykde/26544 try: self.commitData.emit(editor) except AttributeError: pass self.closeEditor.emit(editor, QAbstractItemDelegate.NoHint) def setEditorData(self, editor, index): """Set editor widget's data""" text = from_qvariant(index.model().data(index, Qt.DisplayRole), str) editor.setText(text) #TODO: Implement "Paste" (from clipboard) feature class ArrayView(QTableView): """Array view class""" def __init__(self, parent, model, dtype, shape): QTableView.__init__(self, parent) self.setModel(model) self.setItemDelegate(ArrayDelegate(dtype, self)) total_width = 0 for k in range(shape[1]): total_width += self.columnWidth(k) self.viewport().resize(min(total_width, 1024), self.height()) self.shape = shape self.menu = self.setup_menu() config_shortcut(self.copy, context='variable_explorer', name='copy', parent=self) self.horizontalScrollBar().valueChanged.connect( lambda val: self.load_more_data(val, columns=True)) self.verticalScrollBar().valueChanged.connect( lambda val: self.load_more_data(val, rows=True)) def load_more_data(self, value, rows=False, columns=False): old_selection = self.selectionModel().selection() old_rows_loaded = old_cols_loaded = None if rows and value == self.verticalScrollBar().maximum(): old_rows_loaded = self.model().rows_loaded self.model().fetch_more(rows=rows) if columns and value == self.horizontalScrollBar().maximum(): old_cols_loaded = self.model().cols_loaded self.model().fetch_more(columns=columns) if old_rows_loaded is not None or old_cols_loaded is not None: # if we've changed anything, update selection new_selection = QItemSelection() for part in old_selection: top = part.top() bottom = part.bottom() if (old_rows_loaded is not None and top == 0 and bottom == (old_rows_loaded-1)): # complete column selected (so expand it to match updated range) bottom = self.model().rows_loaded-1 left = part.left() right = part.right() if (old_cols_loaded is not None and left == 0 and right == (old_cols_loaded-1)): # compete row selected (so expand it to match updated range) right = self.model().cols_loaded-1 top_left = self.model().index(top, left) bottom_right = self.model().index(bottom, right) part = QItemSelectionRange(top_left, bottom_right) new_selection.append(part) self.selectionModel().select(new_selection, self.selectionModel().ClearAndSelect) def resize_to_contents(self): """Resize cells to contents""" QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) self.resizeColumnsToContents() self.model().fetch_more(columns=True) self.resizeColumnsToContents() QApplication.restoreOverrideCursor() def setup_menu(self): """Setup context menu""" self.copy_action = create_action(self, _('Copy'), shortcut=keybinding('Copy'), icon=ima.icon('editcopy'), triggered=self.copy, context=Qt.WidgetShortcut) menu = QMenu(self) add_actions(menu, [self.copy_action, ]) return menu def contextMenuEvent(self, event): """Reimplement Qt method""" self.menu.popup(event.globalPos()) event.accept() def keyPressEvent(self, event): """Reimplement Qt method""" if event == QKeySequence.Copy: self.copy() else: QTableView.keyPressEvent(self, event) def _sel_to_text(self, cell_range): """Copy an array portion to a unicode string""" if not cell_range: return row_min, row_max, col_min, col_max = get_idx_rect(cell_range) if col_min == 0 and col_max == (self.model().cols_loaded-1): # we've selected a whole column. It isn't possible to # select only the first part of a column without loading more, # so we can treat it as intentional and copy the whole thing col_max = self.model().total_cols-1 if row_min == 0 and row_max == (self.model().rows_loaded-1): row_max = self.model().total_rows-1 _data = self.model().get_data() if PY3: output = io.BytesIO() else: output = io.StringIO() try: np.savetxt(output, _data[row_min:row_max+1, col_min:col_max+1], delimiter='\t', fmt=self.model().get_format()) except: QMessageBox.warning(self, _("Warning"), _("It was not possible to copy values for " "this array")) return contents = output.getvalue().decode('utf-8') output.close() return contents @Slot() def copy(self): """Copy text to clipboard""" cliptxt = self._sel_to_text( self.selectedIndexes() ) clipboard = QApplication.clipboard() clipboard.setText(cliptxt) class ArrayEditorWidget(QWidget): def __init__(self, parent, data, readonly=False, xlabels=None, ylabels=None): QWidget.__init__(self, parent) self.data = data self.old_data_shape = None if len(self.data.shape) == 1: self.old_data_shape = self.data.shape self.data.shape = (self.data.shape[0], 1) elif len(self.data.shape) == 0: self.old_data_shape = self.data.shape self.data.shape = (1, 1) format = SUPPORTED_FORMATS.get(data.dtype.name, '%s') self.model = ArrayModel(self.data, format=format, xlabels=xlabels, ylabels=ylabels, readonly=readonly, parent=self) self.view = ArrayView(self, self.model, data.dtype, data.shape) btn_layout = QHBoxLayout() btn_layout.setAlignment(Qt.AlignLeft) btn = QPushButton(_( "Format")) # disable format button for int type btn.setEnabled(is_float(data.dtype)) btn_layout.addWidget(btn) btn.clicked.connect(self.change_format) btn = QPushButton(_( "Resize")) btn_layout.addWidget(btn) btn.clicked.connect(self.view.resize_to_contents) bgcolor = QCheckBox(_( 'Background color')) bgcolor.setChecked(self.model.bgcolor_enabled) bgcolor.setEnabled(self.model.bgcolor_enabled) bgcolor.stateChanged.connect(self.model.bgcolor) btn_layout.addWidget(bgcolor) layout = QVBoxLayout() layout.addWidget(self.view) layout.addLayout(btn_layout) self.setLayout(layout) def accept_changes(self): """Accept changes""" for (i, j), value in list(self.model.changes.items()): self.data[i, j] = value if self.old_data_shape is not None: self.data.shape = self.old_data_shape def reject_changes(self): """Reject changes""" if self.old_data_shape is not None: self.data.shape = self.old_data_shape def change_format(self): """Change display format""" format, valid = QInputDialog.getText(self, _( 'Format'), _( "Float formatting"), QLineEdit.Normal, self.model.get_format()) if valid: format = str(format) try: format % 1.1 except: QMessageBox.critical(self, _("Error"), _("Format (%s) is incorrect") % format) return self.model.set_format(format) class ArrayEditor(QDialog): """Array Editor Dialog""" def __init__(self, parent=None): QDialog.__init__(self, parent) # Destroying the C++ object right after closing the dialog box, # otherwise it may be garbage-collected in another QThread # (e.g. the editor's analysis thread in Spyder), thus leading to # a segmentation fault on UNIX or an application crash on Windows self.setAttribute(Qt.WA_DeleteOnClose) self.data = None self.arraywidget = None self.stack = None self.layout = None # Values for 3d array editor self.dim_indexes = [{}, {}, {}] self.last_dim = 0 # Adjust this for changing the startup dimension def setup_and_check(self, data, title='', readonly=False, xlabels=None, ylabels=None): """ Setup ArrayEditor: return False if data is not supported, True otherwise """ self.data = data self.data.flags.writeable = True is_record_array = data.dtype.names is not None is_masked_array = isinstance(data, np.ma.MaskedArray) if data.ndim > 3: self.error(_("Arrays with more than 3 dimensions are not " "supported")) return False if xlabels is not None and len(xlabels) != self.data.shape[1]: self.error(_("The 'xlabels' argument length do no match array " "column number")) return False if ylabels is not None and len(ylabels) != self.data.shape[0]: self.error(_("The 'ylabels' argument length do no match array row " "number")) return False if not is_record_array: dtn = data.dtype.name if dtn not in SUPPORTED_FORMATS and not dtn.startswith('str') \ and not dtn.startswith('unicode'): arr = _("%s arrays") % data.dtype.name self.error(_("%s are currently not supported") % arr) return False self.layout = QGridLayout() self.setLayout(self.layout) self.setWindowIcon(ima.icon('arredit')) if title: title = to_text_string(title) + " - " + _("NumPy array") else: title = _("Array editor") if readonly: title += ' (' + _('read only') + ')' self.setWindowTitle(title) self.resize(600, 500) # Stack widget self.stack = QStackedWidget(self) if is_record_array: for name in data.dtype.names: self.stack.addWidget(ArrayEditorWidget(self, data[name], readonly, xlabels, ylabels)) elif is_masked_array: self.stack.addWidget(ArrayEditorWidget(self, data, readonly, xlabels, ylabels)) self.stack.addWidget(ArrayEditorWidget(self, data.data, readonly, xlabels, ylabels)) self.stack.addWidget(ArrayEditorWidget(self, data.mask, readonly, xlabels, ylabels)) elif data.ndim == 3: pass else: self.stack.addWidget(ArrayEditorWidget(self, data, readonly, xlabels, ylabels)) self.arraywidget = self.stack.currentWidget() self.stack.currentChanged.connect(self.current_widget_changed) self.layout.addWidget(self.stack, 1, 0) # Buttons configuration btn_layout = QHBoxLayout() if is_record_array or is_masked_array or data.ndim == 3: if is_record_array: btn_layout.addWidget(QLabel(_("Record array fields:"))) names = [] for name in data.dtype.names: field = data.dtype.fields[name] text = name if len(field) >= 3: title = field[2] if not is_text_string(title): title = repr(title) text += ' - '+title names.append(text) else: names = [_('Masked data'), _('Data'), _('Mask')] if data.ndim == 3: # QSpinBox self.index_spin = QSpinBox(self, keyboardTracking=False) self.index_spin.valueChanged.connect(self.change_active_widget) # QComboBox names = [str(i) for i in range(3)] ra_combo = QComboBox(self) ra_combo.addItems(names) ra_combo.currentIndexChanged.connect(self.current_dim_changed) # Adding the widgets to layout label = QLabel(_("Axis:")) btn_layout.addWidget(label) btn_layout.addWidget(ra_combo) self.shape_label = QLabel() btn_layout.addWidget(self.shape_label) label = QLabel(_("Index:")) btn_layout.addWidget(label) btn_layout.addWidget(self.index_spin) self.slicing_label = QLabel() btn_layout.addWidget(self.slicing_label) # set the widget to display when launched self.current_dim_changed(self.last_dim) else: ra_combo = QComboBox(self) ra_combo.currentIndexChanged.connect(self.stack.setCurrentIndex) ra_combo.addItems(names) btn_layout.addWidget(ra_combo) if is_masked_array: label = QLabel(_("Warning: changes are applied separately")) label.setToolTip(_("For performance reasons, changes applied "\ "to masked array won't be reflected in "\ "array's data (and vice-versa).")) btn_layout.addWidget(label) btn_layout.addStretch() bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) bbox.accepted.connect(self.accept) bbox.rejected.connect(self.reject) btn_layout.addWidget(bbox) self.layout.addLayout(btn_layout, 2, 0) self.setMinimumSize(400, 300) # Make the dialog act as a window self.setWindowFlags(Qt.Window) return True def current_widget_changed(self, index): self.arraywidget = self.stack.widget(index) def change_active_widget(self, index): """ This is implemented for handling negative values in index for 3d arrays, to give the same behavior as slicing """ string_index = [':']*3 string_index[self.last_dim] = '%i' self.slicing_label.setText((r"Slicing: [" + ", ".join(string_index) + "]") % index) if index < 0: data_index = self.data.shape[self.last_dim] + index else: data_index = index slice_index = [slice(None)]*3 slice_index[self.last_dim] = data_index stack_index = self.dim_indexes[self.last_dim].get(data_index) if stack_index == None: stack_index = self.stack.count() try: self.stack.addWidget(ArrayEditorWidget(self, self.data[slice_index])) except IndexError: # Handle arrays of size 0 in one axis self.stack.addWidget(ArrayEditorWidget(self, self.data)) self.dim_indexes[self.last_dim][data_index] = stack_index self.stack.update() self.stack.setCurrentIndex(stack_index) def current_dim_changed(self, index): """ This change the active axis the array editor is plotting over in 3D """ self.last_dim = index string_size = ['%i']*3 string_size[index] = '%i' self.shape_label.setText(('Shape: (' + ', '.join(string_size) + ') ') % self.data.shape) if self.index_spin.value() != 0: self.index_spin.setValue(0) else: # this is done since if the value is currently 0 it does not emit # currentIndexChanged(int) self.change_active_widget(0) self.index_spin.setRange(-self.data.shape[index], self.data.shape[index]-1) @Slot() def accept(self): """Reimplement Qt method""" for index in range(self.stack.count()): self.stack.widget(index).accept_changes() QDialog.accept(self) def get_value(self): """Return modified array -- this is *not* a copy""" # It is import to avoid accessing Qt C++ object as it has probably # already been destroyed, due to the Qt.WA_DeleteOnClose attribute return self.data def error(self, message): """An error occured, closing the dialog box""" QMessageBox.critical(self, _("Array editor"), message) self.setAttribute(Qt.WA_DeleteOnClose) self.reject() @Slot() def reject(self): """Reimplement Qt method""" if self.arraywidget is not None: for index in range(self.stack.count()): self.stack.widget(index).reject_changes() QDialog.reject(self) spyder-3.2.6/spyder/widgets/variableexplorer/dataframeeditor.py0000664000175000017500000010054213224740762025662 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the New BSD License # # DataFrameModel is based on the class ArrayModel from array editor # and the class DataFrameModel from the pandas project. # Present in pandas.sandbox.qtpandas in v0.13.1 # Copyright (c) 2011-2012, Lambda Foundry, Inc. # and PyData Development Team All rights reserved """ Pandas DataFrame Editor Dialog """ # Third party imports from qtpy import API from qtpy.compat import from_qvariant, to_qvariant from qtpy.QtCore import QAbstractTableModel, QModelIndex, Qt, Signal, Slot from qtpy.QtGui import QColor, QCursor from qtpy.QtWidgets import (QApplication, QCheckBox, QDialogButtonBox, QDialog, QGridLayout, QHBoxLayout, QInputDialog, QLineEdit, QMenu, QMessageBox, QPushButton, QTableView, QHeaderView) from pandas import DataFrame, DatetimeIndex, Series import numpy as np # Local imports from spyder.config.base import _ from spyder.config.fonts import DEFAULT_SMALL_DELTA from spyder.config.gui import get_font, config_shortcut from spyder.py3compat import (io, is_text_string, PY2, to_text_string, TEXT_TYPES) from spyder.utils import encoding from spyder.utils import icon_manager as ima from spyder.utils.qthelpers import (add_actions, create_action, keybinding, qapplication) from spyder.widgets.variableexplorer.arrayeditor import get_idx_rect # Supported Numbers and complex numbers REAL_NUMBER_TYPES = (float, int, np.int64, np.int32) COMPLEX_NUMBER_TYPES = (complex, np.complex64, np.complex128) # Used to convert bool intrance to false since bool('False') will return True _bool_false = ['false', 'f', '0', '0.', '0.0', ' '] # Default format for data frames with floats DEFAULT_FORMAT = '%.6g' # Limit at which dataframe is considered so large that it is loaded on demand LARGE_SIZE = 5e5 LARGE_NROWS = 1e5 LARGE_COLS = 60 # Background colours BACKGROUND_NUMBER_MINHUE = 0.66 # hue for largest number BACKGROUND_NUMBER_HUERANGE = 0.33 # (hue for smallest) minus (hue for largest) BACKGROUND_NUMBER_SATURATION = 0.7 BACKGROUND_NUMBER_VALUE = 1.0 BACKGROUND_NUMBER_ALPHA = 0.6 BACKGROUND_NONNUMBER_COLOR = Qt.lightGray BACKGROUND_INDEX_ALPHA = 0.8 BACKGROUND_STRING_ALPHA = 0.05 BACKGROUND_MISC_ALPHA = 0.3 def bool_false_check(value): """ Used to convert bool intrance to false since any string in bool('') will return True """ if value.lower() in _bool_false: value = '' return value def global_max(col_vals, index): """Returns the global maximum and minimum""" col_vals_without_None = [x for x in col_vals if x is not None] max_col, min_col = zip(*col_vals_without_None) return max(max_col), min(min_col) class DataFrameModel(QAbstractTableModel): """ DataFrame Table Model""" ROWS_TO_LOAD = 500 COLS_TO_LOAD = 40 def __init__(self, dataFrame, format=DEFAULT_FORMAT, parent=None): QAbstractTableModel.__init__(self) self.dialog = parent self.df = dataFrame self.df_index = dataFrame.index.tolist() self.df_header = dataFrame.columns.tolist() self._format = format self.complex_intran = None self.total_rows = self.df.shape[0] self.total_cols = self.df.shape[1] size = self.total_rows * self.total_cols self.max_min_col = None if size < LARGE_SIZE: self.max_min_col_update() self.colum_avg_enabled = True self.bgcolor_enabled = True self.colum_avg(1) else: self.colum_avg_enabled = False self.bgcolor_enabled = False self.colum_avg(0) # Use paging when the total size, number of rows or number of # columns is too large if size > LARGE_SIZE: self.rows_loaded = self.ROWS_TO_LOAD self.cols_loaded = self.COLS_TO_LOAD else: if self.total_rows > LARGE_NROWS: self.rows_loaded = self.ROWS_TO_LOAD else: self.rows_loaded = self.total_rows if self.total_cols > LARGE_COLS: self.cols_loaded = self.COLS_TO_LOAD else: self.cols_loaded = self.total_cols def max_min_col_update(self): """ Determines the maximum and minimum number in each column. The result is a list whose k-th entry is [vmax, vmin], where vmax and vmin denote the maximum and minimum of the k-th column (ignoring NaN). This list is stored in self.max_min_col. If the k-th column has a non-numerical dtype, then the k-th entry is set to None. If the dtype is complex, then compute the maximum and minimum of the absolute values. If vmax equals vmin, then vmin is decreased by one. """ if self.df.shape[0] == 0: # If no rows to compute max/min then return return self.max_min_col = [] for dummy, col in self.df.iteritems(): if col.dtype in REAL_NUMBER_TYPES + COMPLEX_NUMBER_TYPES: if col.dtype in REAL_NUMBER_TYPES: vmax = col.max(skipna=True) vmin = col.min(skipna=True) else: vmax = col.abs().max(skipna=True) vmin = col.abs().min(skipna=True) if vmax != vmin: max_min = [vmax, vmin] else: max_min = [vmax, vmin - 1] else: max_min = None self.max_min_col.append(max_min) def get_format(self): """Return current format""" # Avoid accessing the private attribute _format from outside return self._format def set_format(self, format): """Change display format""" self._format = format self.reset() def bgcolor(self, state): """Toggle backgroundcolor""" self.bgcolor_enabled = state > 0 self.reset() def colum_avg(self, state): """Toggle backgroundcolor""" self.colum_avg_enabled = state > 0 if self.colum_avg_enabled: self.return_max = lambda col_vals, index: col_vals[index] else: self.return_max = global_max self.reset() def headerData(self, section, orientation, role=Qt.DisplayRole): """Set header data""" if role != Qt.DisplayRole: return to_qvariant() if orientation == Qt.Horizontal: if section == 0: return 'Index' elif section == 1 and PY2: # 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: header = to_text_string(self.df_header[0], encoding='utf-8-sig') except: header = to_text_string(self.df_header[0]) return to_qvariant(header) elif isinstance(self.df_header[section-1], TEXT_TYPES): # Get the proper encoding of the text in the header. # Fixes Issue 3896 if not PY2: try: header = self.df_header[section-1].encode('utf-8') coding = 'utf-8-sig' except: header = self.df_header[section-1].encode('utf-8') coding = encoding.get_coding(header) else: header = self.df_header[section-1] coding = encoding.get_coding(header) return to_qvariant(to_text_string(header, encoding=coding)) else: return to_qvariant(to_text_string(self.df_header[section-1])) else: return to_qvariant() def get_bgcolor(self, index): """Background color depending on value""" column = index.column() if column == 0: color = QColor(BACKGROUND_NONNUMBER_COLOR) color.setAlphaF(BACKGROUND_INDEX_ALPHA) return color if not self.bgcolor_enabled: return value = self.get_value(index.row(), column-1) if self.max_min_col[column - 1] is None: color = QColor(BACKGROUND_NONNUMBER_COLOR) if is_text_string(value): color.setAlphaF(BACKGROUND_STRING_ALPHA) else: color.setAlphaF(BACKGROUND_MISC_ALPHA) else: if isinstance(value, COMPLEX_NUMBER_TYPES): color_func = abs else: color_func = float vmax, vmin = self.return_max(self.max_min_col, column-1) hue = (BACKGROUND_NUMBER_MINHUE + BACKGROUND_NUMBER_HUERANGE * (vmax - color_func(value)) / (vmax - vmin)) hue = float(abs(hue)) if hue > 1: hue = 1 color = QColor.fromHsvF(hue, BACKGROUND_NUMBER_SATURATION, BACKGROUND_NUMBER_VALUE, BACKGROUND_NUMBER_ALPHA) return color def get_value(self, row, column): """Returns the value of the DataFrame""" # To increase the performance iat is used but that requires error # handling, so fallback uses iloc try: value = self.df.iat[row, column] except: value = self.df.iloc[row, column] return value def update_df_index(self): """"Update the DataFrame index""" self.df_index = self.df.index.tolist() def data(self, index, role=Qt.DisplayRole): """Cell content""" if not index.isValid(): return to_qvariant() if role == Qt.DisplayRole or role == Qt.EditRole: column = index.column() row = index.row() if column == 0: return to_qvariant(to_text_string(self.df_index[row])) else: value = self.get_value(row, column-1) if isinstance(value, float): try: return to_qvariant(self._format % value) except (ValueError, TypeError): # may happen if format = '%d' and value = NaN; # see issue 4139 return to_qvariant(DEFAULT_FORMAT % value) else: try: return to_qvariant(to_text_string(value)) except UnicodeDecodeError: return to_qvariant(encoding.to_unicode(value)) elif role == Qt.BackgroundColorRole: return to_qvariant(self.get_bgcolor(index)) elif role == Qt.FontRole: return to_qvariant(get_font(font_size_delta=DEFAULT_SMALL_DELTA)) return to_qvariant() def sort(self, column, order=Qt.AscendingOrder): """Overriding sort method""" if self.complex_intran is not None: if self.complex_intran.any(axis=0).iloc[column-1]: QMessageBox.critical(self.dialog, "Error", "TypeError error: no ordering " "relation is defined for complex numbers") return False try: ascending = order == Qt.AscendingOrder if column > 0: try: self.df.sort_values(by=self.df.columns[column-1], ascending=ascending, inplace=True, kind='mergesort') except AttributeError: # for pandas version < 0.17 self.df.sort(columns=self.df.columns[column-1], ascending=ascending, inplace=True, kind='mergesort') except ValueError as e: # Not possible to sort on duplicate columns #5225 QMessageBox.critical(self.dialog, "Error", "ValueError: %s" % to_text_string(e)) except SystemError as e: # Not possible to sort on category dtypes #5361 QMessageBox.critical(self.dialog, "Error", "SystemError: %s" % to_text_string(e)) self.update_df_index() else: self.df.sort_index(inplace=True, ascending=ascending) self.update_df_index() except TypeError as e: QMessageBox.critical(self.dialog, "Error", "TypeError error: %s" % str(e)) return False self.reset() return True def flags(self, index): """Set flags""" if index.column() == 0: return Qt.ItemIsEnabled | Qt.ItemIsSelectable return Qt.ItemFlags(QAbstractTableModel.flags(self, index) | Qt.ItemIsEditable) def setData(self, index, value, role=Qt.EditRole, change_type=None): """Cell content change""" column = index.column() row = index.row() if change_type is not None: try: value = self.data(index, role=Qt.DisplayRole) val = from_qvariant(value, str) if change_type is bool: val = bool_false_check(val) self.df.iloc[row, column - 1] = change_type(val) except ValueError: self.df.iloc[row, column - 1] = change_type('0') else: val = from_qvariant(value, str) current_value = self.get_value(row, column-1) if isinstance(current_value, (bool, np.bool_)): val = bool_false_check(val) supported_types = (bool, np.bool_) + REAL_NUMBER_TYPES if (isinstance(current_value, supported_types) or is_text_string(current_value)): try: self.df.iloc[row, column-1] = current_value.__class__(val) except (ValueError, OverflowError) as e: QMessageBox.critical(self.dialog, "Error", str(type(e).__name__) + ": " + str(e)) return False else: QMessageBox.critical(self.dialog, "Error", "Editing dtype {0!s} not yet supported." .format(type(current_value).__name__)) return False self.max_min_col_update() return True def get_data(self): """Return data""" return self.df def rowCount(self, index=QModelIndex()): """DataFrame row number""" if self.total_rows <= self.rows_loaded: return self.total_rows else: return self.rows_loaded def can_fetch_more(self, rows=False, columns=False): if rows: if self.total_rows > self.rows_loaded: return True else: return False if columns: if self.total_cols > self.cols_loaded: return True else: return False def fetch_more(self, rows=False, columns=False): if self.can_fetch_more(rows=rows): reminder = self.total_rows - self.rows_loaded items_to_fetch = min(reminder, self.ROWS_TO_LOAD) self.beginInsertRows(QModelIndex(), self.rows_loaded, self.rows_loaded + items_to_fetch - 1) self.rows_loaded += items_to_fetch self.endInsertRows() if self.can_fetch_more(columns=columns): reminder = self.total_cols - self.cols_loaded items_to_fetch = min(reminder, self.COLS_TO_LOAD) self.beginInsertColumns(QModelIndex(), self.cols_loaded, self.cols_loaded + items_to_fetch - 1) self.cols_loaded += items_to_fetch self.endInsertColumns() def columnCount(self, index=QModelIndex()): """DataFrame column number""" # This is done to implement series if len(self.df.shape) == 1: return 2 elif self.total_cols <= self.cols_loaded: return self.total_cols + 1 else: return self.cols_loaded + 1 def reset(self): self.beginResetModel() self.endResetModel() class FrozenTableView(QTableView): """This class implements a table with its first column frozen For more information please see: http://doc.qt.io/qt-5/qtwidgets-itemviews-frozencolumn-example.html""" def __init__(self, parent): """Constructor.""" QTableView.__init__(self, parent) self.parent = parent self.setModel(parent.model()) self.setFocusPolicy(Qt.NoFocus) self.verticalHeader().hide() try: self.horizontalHeader().setSectionResizeMode(QHeaderView.Fixed) except: # support for qtpy<1.2.0 self.horizontalHeader().setResizeMode(QHeaderView.Fixed) parent.viewport().stackUnder(self) self.setSelectionModel(parent.selectionModel()) for col in range(1, parent.model().columnCount()): self.setColumnHidden(col, True) self.setColumnWidth(0, parent.columnWidth(0)) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.show() self.setVerticalScrollMode(1) def update_geometry(self): """Update the frozen column size when an update occurs in its parent table""" self.setGeometry(self.parent.verticalHeader().width() + self.parent.frameWidth(), self.parent.frameWidth(), self.parent.columnWidth(0), self.parent.viewport().height() + self.parent.horizontalHeader().height()) class DataFrameView(QTableView): """Data Frame view class""" def __init__(self, parent, model): QTableView.__init__(self, parent) self.setModel(model) self.frozen_table_view = FrozenTableView(self) self.frozen_table_view.update_geometry() self.setHorizontalScrollMode(1) self.setVerticalScrollMode(1) self.horizontalHeader().sectionResized.connect(self.update_section_width) self.verticalHeader().sectionResized.connect(self.update_section_height) self.frozen_table_view.verticalScrollBar().valueChanged.connect( self.verticalScrollBar().setValue) self.sort_old = [None] self.header_class = self.horizontalHeader() self.header_class.sectionClicked.connect(self.sortByColumn) self.menu = self.setup_menu() config_shortcut(self.copy, context='variable_explorer', name='copy', parent=self) self.horizontalScrollBar().valueChanged.connect( lambda val: self.load_more_data(val, columns=True)) self.verticalScrollBar().valueChanged.connect( lambda val: self.load_more_data(val, rows=True)) self.verticalScrollBar().valueChanged.connect( self.frozen_table_view.verticalScrollBar().setValue) def update_section_width(self, logical_index, old_size, new_size): """Update the horizontal width of the frozen column when a change takes place in the first column of the table""" if logical_index == 0: self.frozen_table_view.setColumnWidth(0, new_size) self.frozen_table_view.update_geometry() def update_section_height(self, logical_index, old_size, new_size): """Update the vertical width of the frozen column when a change takes place on any of the rows""" self.frozen_table_view.setRowHeight(logical_index, new_size) def resizeEvent(self, event): """Update the frozen column dimensions. Updates takes place when the enclosing window of this table reports a dimension change """ QTableView.resizeEvent(self, event) self.frozen_table_view.update_geometry() def moveCursor(self, cursor_action, modifiers): """Update the table position. Updates the position along with the frozen column when the cursor (selector) changes its position """ current = QTableView.moveCursor(self, cursor_action, modifiers) col_width = (self.frozen_table_view.columnWidth(0) + self.frozen_table_view.columnWidth(1)) topleft_x = self.visualRect(current).topLeft().x() overflow = self.MoveLeft and current.column() > 1 overflow = overflow and topleft_x < col_width if cursor_action == overflow: new_value = (self.horizontalScrollBar().value() + topleft_x - col_width) self.horizontalScrollBar().setValue(new_value) return current def scrollTo(self, index, hint): """Scroll the table. It is necessary to ensure that the item at index is visible. The view will try to position the item according to the given hint. This method does not takes effect only if the frozen column is scrolled. """ if index.column() > 1: QTableView.scrollTo(self, index, hint) def load_more_data(self, value, rows=False, columns=False): if rows and value == self.verticalScrollBar().maximum(): self.model().fetch_more(rows=rows) if columns and value == self.horizontalScrollBar().maximum(): self.model().fetch_more(columns=columns) def sortByColumn(self, index): """ Implement a Column sort """ if self.sort_old == [None]: self.header_class.setSortIndicatorShown(True) sort_order = self.header_class.sortIndicatorOrder() if not self.model().sort(index, sort_order): if len(self.sort_old) != 2: self.header_class.setSortIndicatorShown(False) else: self.header_class.setSortIndicator(self.sort_old[0], self.sort_old[1]) return self.sort_old = [index, self.header_class.sortIndicatorOrder()] def contextMenuEvent(self, event): """Reimplement Qt method""" self.menu.popup(event.globalPos()) event.accept() def setup_menu(self): """Setup context menu""" copy_action = create_action(self, _('Copy'), shortcut=keybinding('Copy'), icon=ima.icon('editcopy'), triggered=self.copy, context=Qt.WidgetShortcut) functions = ((_("To bool"), bool), (_("To complex"), complex), (_("To int"), int), (_("To float"), float), (_("To str"), to_text_string)) types_in_menu = [copy_action] for name, func in functions: # QAction.triggered works differently for PySide and PyQt if not API == 'pyside': slot = lambda _checked, func=func: self.change_type(func) else: slot = lambda func=func: self.change_type(func) types_in_menu += [create_action(self, name, triggered=slot, context=Qt.WidgetShortcut)] menu = QMenu(self) add_actions(menu, types_in_menu) return menu def change_type(self, func): """A function that changes types of cells""" model = self.model() index_list = self.selectedIndexes() [model.setData(i, '', change_type=func) for i in index_list] @Slot() def copy(self): """Copy text to clipboard""" if not self.selectedIndexes(): return (row_min, row_max, col_min, col_max) = get_idx_rect(self.selectedIndexes()) index = header = False if col_min == 0: col_min = 1 index = True df = self.model().df if col_max == 0: # To copy indices contents = '\n'.join(map(str, df.index.tolist()[slice(row_min, row_max+1)])) else: # To copy DataFrame if (col_min == 0 or col_min == 1) and (df.shape[1] == col_max): header = True obj = df.iloc[slice(row_min, row_max+1), slice(col_min-1, col_max)] output = io.StringIO() obj.to_csv(output, sep='\t', index=index, header=header) if not PY2: contents = output.getvalue() else: contents = output.getvalue().decode('utf-8') output.close() clipboard = QApplication.clipboard() clipboard.setText(contents) class DataFrameEditor(QDialog): """ Dialog for displaying and editing DataFrame and related objects. Signals ------- sig_option_changed(str, object): Raised if an option is changed. Arguments are name of option and its new value. """ sig_option_changed = Signal(str, object) def __init__(self, parent=None): QDialog.__init__(self, parent) # Destroying the C++ object right after closing the dialog box, # otherwise it may be garbage-collected in another QThread # (e.g. the editor's analysis thread in Spyder), thus leading to # a segmentation fault on UNIX or an application crash on Windows self.setAttribute(Qt.WA_DeleteOnClose) self.is_series = False self.layout = None def setup_and_check(self, data, title=''): """ Setup DataFrameEditor: return False if data is not supported, True otherwise. Supported types for data are DataFrame, Series and DatetimeIndex. """ self.layout = QGridLayout() self.setLayout(self.layout) self.setWindowIcon(ima.icon('arredit')) if title: title = to_text_string(title) + " - %s" % data.__class__.__name__ else: title = _("%s editor") % data.__class__.__name__ if isinstance(data, Series): self.is_series = True data = data.to_frame() elif isinstance(data, DatetimeIndex): data = DataFrame(data) 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) btn.clicked.connect(self.change_format) btn = QPushButton(_('Resize')) btn_layout.addWidget(btn) btn.clicked.connect(self.resize_to_contents) bgcolor = QCheckBox(_('Background color')) bgcolor.setChecked(self.dataModel.bgcolor_enabled) bgcolor.setEnabled(self.dataModel.bgcolor_enabled) bgcolor.stateChanged.connect(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_series and self.dataModel.bgcolor_enabled) self.bgcolor_global.stateChanged.connect(self.dataModel.colum_avg) btn_layout.addWidget(self.bgcolor_global) btn_layout.addStretch() bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) bbox.accepted.connect(self.accept) bbox.rejected.connect(self.reject) btn_layout.addWidget(bbox) self.layout.addLayout(btn_layout, 2, 0) return True def change_bgcolor_enable(self, state): """ This is implementet so column min/max is only active when bgcolor is """ self.dataModel.bgcolor(state) self.bgcolor_global.setEnabled(not self.is_series and state > 0) def change_format(self): """ Ask user for display format for floats and use it. This function also checks whether the format is valid and emits `sig_option_changed`. """ format, valid = QInputDialog.getText(self, _('Format'), _("Float formatting"), QLineEdit.Normal, self.dataModel.get_format()) if valid: format = str(format) try: format % 1.1 except: msg = _("Format ({}) is incorrect").format(format) QMessageBox.critical(self, _("Error"), msg) return if not format.startswith('%'): msg = _("Format ({}) should start with '%'").format(format) QMessageBox.critical(self, _("Error"), msg) return self.dataModel.set_format(format) self.sig_option_changed.emit('dataframe_format', format) def get_value(self): """Return modified Dataframe -- this is *not* a copy""" # It is import to avoid accessing Qt C++ object as it has probably # already been destroyed, due to the Qt.WA_DeleteOnClose attribute df = self.dataModel.get_data() if self.is_series: return df.iloc[:, 0] else: return df def resize_to_contents(self): QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) self.dataTable.resizeColumnsToContents() self.dataModel.fetch_more(columns=True) self.dataTable.resizeColumnsToContents() QApplication.restoreOverrideCursor() #============================================================================== # Tests #============================================================================== def test_edit(data, title="", parent=None): """Test subroutine""" app = qapplication() # analysis:ignore dlg = DataFrameEditor(parent=parent) if dlg.setup_and_check(data, title=title): dlg.exec_() return dlg.get_value() else: import sys sys.exit(1) def test(): """DataFrame editor test""" from numpy import nan from pandas.util.testing import assert_frame_equal, assert_series_equal df1 = DataFrame([ [True, "bool"], [1+1j, "complex"], ['test', "string"], [1.11, "float"], [1, "int"], [np.random.rand(3, 3), "Unkown type"], ["Large value", 100], ["áéí", "unicode"] ], index=['a', 'b', nan, nan, nan, 'c', "Test global max", 'd'], columns=[nan, 'Type']) out = test_edit(df1) assert_frame_equal(df1, out) result = Series([True, "bool"], index=[nan, 'Type'], name='a') out = test_edit(df1.iloc[0]) assert_series_equal(result, out) df1 = DataFrame(np.random.rand(100100, 10)) out = test_edit(df1) assert_frame_equal(out, df1) series = Series(np.arange(10), name=0) out = test_edit(series) assert_series_equal(series, out) if __name__ == '__main__': test() spyder-3.2.6/spyder/widgets/variableexplorer/tests/0000775000175000017500000000000013225025007023302 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/widgets/variableexplorer/tests/test_importwizard.py0000664000175000017500000000132313156676664027475 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for importwizard.py """ # Test library imports import pytest # Local imports from spyder.widgets.variableexplorer.importwizard import ImportWizard @pytest.fixture def setup_importwizard(qtbot, text): """Set up ImportWizard.""" importwizard = ImportWizard(None, text) qtbot.addWidget(importwizard) return importwizard def test_importwizard(qtbot): """Run ImportWizard dialog.""" text = u"17/11/1976\t1.34\n14/05/09\t3.14" importwizard = setup_importwizard(qtbot, text) importwizard.show() assert importwizard if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/widgets/variableexplorer/tests/test_dataframeeditor.py0000664000175000017500000004511713224740762030071 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License """ Tests for dataframeeditor.py """ from __future__ import division # Standard library imports from sys import platform try: from unittest.mock import Mock, ANY except ImportError: from mock import Mock, ANY # Python 2 import os # Third party imports from pandas import DataFrame, date_range, read_csv, concat from qtpy import PYQT4 from qtpy.QtGui import QColor from qtpy.QtCore import Qt, QTimer import numpy import pytest from flaky import flaky # Local imports from spyder.utils.programs import is_module_installed from spyder.utils.test import close_message_box from spyder.widgets.variableexplorer import dataframeeditor from spyder.widgets.variableexplorer.dataframeeditor import ( DataFrameEditor, DataFrameModel) from spyder.py3compat import PY2 FILES_PATH = os.path.dirname(os.path.realpath(__file__)) # Helper functions def colorclose(color, hsva_expected): """ Compares HSV values which are stored as 16-bit integers. """ hsva_actual = color.getHsvF() return all(abs(a-b) <= 2**(-16) for (a,b) in zip(hsva_actual, hsva_expected)) def data(dfm, i, j): return dfm.data(dfm.createIndex(i, j)) def bgcolor(dfm, i, j): return dfm.get_bgcolor(dfm.createIndex(i, j)) # --- Tests # ----------------------------------------------------------------------------- def test_dataframemodel_basic(): df = DataFrame({'colA': [1, 3], 'colB': ['c', 'a']}) dfm = DataFrameModel(df) assert dfm.rowCount() == 2 assert dfm.columnCount() == 3 assert data(dfm, 0, 0) == '0' assert data(dfm, 0, 1) == '1' assert data(dfm, 0, 2) == 'c' assert data(dfm, 1, 0) == '1' assert data(dfm, 1, 1) == '3' assert data(dfm, 1, 2) == 'a' def test_dataframemodel_sort(): df = DataFrame({'colA': [1, 3], 'colB': ['c', 'a']}) dfm = DataFrameModel(df) dfm.sort(2) assert data(dfm, 0, 0) == '1' assert data(dfm, 0, 1) == '3' assert data(dfm, 0, 2) == 'a' assert data(dfm, 1, 0) == '0' assert data(dfm, 1, 1) == '1' assert data(dfm, 1, 2) == 'c' def test_dataframemodel_sort_is_stable(): # cf. issue 3010 df = DataFrame([[2,14], [2,13], [2,16], [1,3], [2,9], [1,15], [1,17], [2,2], [2,10], [1,6], [2,5], [2,8], [1,11], [1,1], [1,12], [1,4], [2,7]]) dfm = DataFrameModel(df) dfm.sort(2) dfm.sort(1) col2 = [data(dfm, i, 2) for i in range(len(df))] assert col2 == [str(x) for x in [1, 3, 4, 6, 11, 12, 15, 17, 2, 5, 7, 8, 9, 10, 13, 14, 16]] def test_dataframemodel_max_min_col_update(): df = DataFrame([[1, 2.0], [2, 2.5], [3, 9.0]]) dfm = DataFrameModel(df) assert dfm.max_min_col == [[3, 1], [9.0, 2.0]] def test_dataframemodel_max_min_col_update_constant(): df = DataFrame([[1, 2.0], [1, 2.0], [1, 2.0]]) dfm = DataFrameModel(df) assert dfm.max_min_col == [[1, 0], [2.0, 1.0]] def test_dataframemodel_with_timezone_aware_timestamps(): # cf. issue 2940 df = DataFrame([x] for x in date_range('20150101', periods=5, tz='UTC')) dfm = DataFrameModel(df) assert dfm.max_min_col == [None] def test_dataframemodel_with_categories(): # cf. issue 3308 df = DataFrame({"id": [1, 2, 3, 4, 5, 6], "raw_grade": ['a', 'b', 'b', 'a', 'a', 'e']}) df["grade"] = df["raw_grade"].astype("category") dfm = DataFrameModel(df) assert dfm.max_min_col == [[6, 1], None, None] def test_dataframemodel_get_bgcolor_with_numbers(): df = DataFrame([[0, 10], [1, 20], [2, 40]]) dfm = DataFrameModel(df) h0 = dataframeeditor.BACKGROUND_NUMBER_MINHUE dh = dataframeeditor.BACKGROUND_NUMBER_HUERANGE s = dataframeeditor.BACKGROUND_NUMBER_SATURATION v = dataframeeditor.BACKGROUND_NUMBER_VALUE a = dataframeeditor.BACKGROUND_NUMBER_ALPHA assert colorclose(bgcolor(dfm, 0, 1), (h0 + dh, s, v, a)) assert colorclose(bgcolor(dfm, 1, 1), (h0 + 1 / 2 * dh, s, v, a)) assert colorclose(bgcolor(dfm, 2, 1), (h0, s, v, a)) assert colorclose(bgcolor(dfm, 0, 2), (h0 + dh, s, v, a)) assert colorclose(bgcolor(dfm, 1, 2), (h0 + 2 / 3 * dh, s, v, a)) assert colorclose(bgcolor(dfm, 2, 2), (h0, s, v, a)) def test_dataframemodel_get_bgcolor_with_numbers_using_global_max(): df = DataFrame([[0, 10], [1, 20], [2, 40]]) dfm = DataFrameModel(df) dfm.colum_avg(0) h0 = dataframeeditor.BACKGROUND_NUMBER_MINHUE dh = dataframeeditor.BACKGROUND_NUMBER_HUERANGE s = dataframeeditor.BACKGROUND_NUMBER_SATURATION v = dataframeeditor.BACKGROUND_NUMBER_VALUE a = dataframeeditor.BACKGROUND_NUMBER_ALPHA assert colorclose(bgcolor(dfm, 0, 1), (h0 + dh, s, v, a)) assert colorclose(bgcolor(dfm, 1, 1), (h0 + 39 / 40 * dh, s, v, a)) assert colorclose(bgcolor(dfm, 2, 1), (h0 + 38 / 40 * dh, s, v, a)) assert colorclose(bgcolor(dfm, 0, 2), (h0 + 30 / 40 * dh, s, v, a)) assert colorclose(bgcolor(dfm, 1, 2), (h0 + 20 / 40 * dh, s, v, a)) assert colorclose(bgcolor(dfm, 2, 2), (h0, s, v, a)) def test_dataframemodel_get_bgcolor_for_index(): df = DataFrame([[0]]) dfm = DataFrameModel(df) h, s, v, dummy = QColor(dataframeeditor.BACKGROUND_NONNUMBER_COLOR).getHsvF() a = dataframeeditor.BACKGROUND_INDEX_ALPHA assert colorclose(bgcolor(dfm, 0, 0), (h, s, v, a)) def test_dataframemodel_get_bgcolor_with_string(): df = DataFrame([['xxx']]) dfm = DataFrameModel(df) h, s, v, dummy = QColor(dataframeeditor.BACKGROUND_NONNUMBER_COLOR).getHsvF() a = dataframeeditor.BACKGROUND_STRING_ALPHA assert colorclose(bgcolor(dfm, 0, 1), (h, s, v, a)) def test_dataframemodel_get_bgcolor_with_object(): df = DataFrame([[None]]) dfm = DataFrameModel(df) h, s, v, dummy = QColor(dataframeeditor.BACKGROUND_NONNUMBER_COLOR).getHsvF() a = dataframeeditor.BACKGROUND_MISC_ALPHA assert colorclose(bgcolor(dfm, 0, 1), (h, s, v, a)) def test_dataframemodel_with_format_percent_d_and_nan(): """ Test DataFrameModel with format `%d` and dataframe containing NaN Regression test for issue 4139. """ np_array = numpy.zeros(2) np_array[1] = numpy.nan dataframe = DataFrame(np_array) dfm = DataFrameModel(dataframe, format='%d') assert data(dfm, 0, 1) == '0' assert data(dfm, 1, 1) == 'nan' def test_change_format_emits_signal(qtbot, monkeypatch): mockQInputDialog = Mock() mockQInputDialog.getText = lambda parent, title, label, mode, text: ('%10.3e', True) monkeypatch.setattr('spyder.widgets.variableexplorer.dataframeeditor.QInputDialog', mockQInputDialog) df = DataFrame([[0]]) editor = DataFrameEditor(None) editor.setup_and_check(df) with qtbot.waitSignal(editor.sig_option_changed) as blocker: editor.change_format() assert blocker.args == ['dataframe_format', '%10.3e'] def test_change_format_with_format_not_starting_with_percent(qtbot, monkeypatch): mockQInputDialog = Mock() mockQInputDialog.getText = lambda parent, title, label, mode, text: ('xxx%f', True) monkeypatch.setattr('spyder.widgets.variableexplorer.dataframeeditor' '.QInputDialog', mockQInputDialog) monkeypatch.setattr('spyder.widgets.variableexplorer.dataframeeditor' '.QMessageBox.critical', Mock()) df = DataFrame([[0]]) editor = DataFrameEditor(None) editor.setup_and_check(df) with qtbot.assertNotEmitted(editor.sig_option_changed): editor.change_format() def test_header_bom(): df = read_csv(os.path.join(FILES_PATH, 'issue_2514.csv')) editor = DataFrameEditor(None) editor.setup_and_check(df) model = editor.dataModel assert model.headerData(1, orientation=Qt.Horizontal) == "Date (MMM-YY)" @pytest.mark.skipif(is_module_installed('pandas', '<0.19'), reason="It doesn't work for Pandas 0.19-") def test_header_encoding(): df = read_csv(os.path.join(FILES_PATH, 'issue_3896.csv')) editor = DataFrameEditor(None) editor.setup_and_check(df) model = editor.dataModel assert model.headerData(0, orientation=Qt.Horizontal) == "Index" assert model.headerData(1, orientation=Qt.Horizontal) == "Unnamed: 0" assert model.headerData(2, orientation=Qt.Horizontal) == "Unieke_Idcode" assert model.headerData(3, orientation=Qt.Horizontal) == "a" assert model.headerData(4, orientation=Qt.Horizontal) == "b" assert model.headerData(5, orientation=Qt.Horizontal) == "c" assert model.headerData(6, orientation=Qt.Horizontal) == "d" def test_dataframeeditor_with_datetimeindex(): rng = date_range('20150101', periods=3) editor = DataFrameEditor(None) editor.setup_and_check(rng) dfm = editor.dataModel assert dfm.rowCount() == 3 assert dfm.columnCount() == 2 assert data(dfm, 0, 1) == '2015-01-01 00:00:00' assert data(dfm, 1, 1) == '2015-01-02 00:00:00' assert data(dfm, 2, 1) == '2015-01-03 00:00:00' @pytest.mark.skipif(not os.name == 'nt', reason="It segfaults too much on Linux") def test_sort_dataframe_with_duplicate_column(qtbot): df = DataFrame({'A': [1, 3, 2], 'B': [4, 6, 5]}) df = concat((df, df.A), axis=1) editor = DataFrameEditor(None) editor.setup_and_check(df) dfm = editor.dataModel QTimer.singleShot(1000, lambda: close_message_box(qtbot)) editor.dataModel.sort(1) assert [data(dfm, row, 1) for row in range(len(df))] == ['1', '3', '2'] assert [data(dfm, row, 2) for row in range(len(df))] == ['4', '6', '5'] editor.dataModel.sort(2) assert [data(dfm, row, 1) for row in range(len(df))] == ['1', '2', '3'] assert [data(dfm, row, 2) for row in range(len(df))] == ['4', '5', '6'] @pytest.mark.skipif(not os.name == 'nt', reason="It segfaults too much on Linux") def test_sort_dataframe_with_category_dtypes(qtbot): # cf. issue 5361 df = DataFrame({'A': [1, 2, 3, 4], 'B': ['a', 'b', 'c', 'd']}) df = df.astype(dtype={'B': 'category'}) df_cols = df.dtypes editor = DataFrameEditor(None) editor.setup_and_check(df_cols) dfm = editor.dataModel QTimer.singleShot(1000, lambda: close_message_box(qtbot)) editor.dataModel.sort(1) assert data(dfm, 0, 1) == 'int64' assert data(dfm, 1, 1) == 'category' def test_dataframemodel_set_data_overflow(monkeypatch): """Unit test #6114: entry of an overflow int caught and handled properly""" MockQMessageBox = Mock() attr_to_patch = ('spyder.widgets.variableexplorer' + '.dataframeeditor.QMessageBox') monkeypatch.setattr(attr_to_patch, MockQMessageBox) # Numpy doesn't raise the OverflowError for ints smaller than 64 bits if platform.startswith('linux'): int32_bit_exponent = 66 else: int32_bit_exponent = 34 test_parameters = [(1, numpy.int32, int32_bit_exponent), (2, numpy.int64, 66)] for idx, int_type, bit_exponent in test_parameters: test_df = DataFrame(numpy.arange(7, 11), dtype=int_type) model = DataFrameModel(test_df.copy()) index = model.createIndex(2, 1) assert not model.setData(index, str(int(2 ** bit_exponent))) MockQMessageBox.critical.assert_called_with(ANY, "Error", ANY) assert MockQMessageBox.critical.call_count == idx assert numpy.sum(test_df[0].as_matrix() == model.df.as_matrix()) == len(test_df) @flaky(max_runs=3) @pytest.mark.skipif(platform.startswith('linux'), reason="Fails on some Linux platforms locally and Travis.") def test_dataframeeditor_edit_overflow(qtbot, monkeypatch): """Test #6114: entry of an overflow int is caught and handled properly""" MockQMessageBox = Mock() attr_to_patch = ('spyder.widgets.variableexplorer' + '.dataframeeditor.QMessageBox') monkeypatch.setattr(attr_to_patch, MockQMessageBox) # Numpy doesn't raise the OverflowError for ints smaller than 64 bits if platform.startswith('linux'): int32_bit_exponent = 66 else: int32_bit_exponent = 34 test_parameters = [(1, numpy.int32, int32_bit_exponent), (2, numpy.int64, 66)] expected_df = DataFrame([5, 6, 7, 3, 4]) for idx, int_type, bit_exponet in test_parameters: test_df = DataFrame(numpy.arange(0, 5), dtype=int_type) dialog = DataFrameEditor() assert dialog.setup_and_check(test_df, 'Test Dataframe') dialog.show() qtbot.waitForWindowShown(dialog) view = dialog.dataTable qtbot.keyPress(view, Qt.Key_Right) qtbot.keyClicks(view, '5') qtbot.keyPress(view, Qt.Key_Down) qtbot.keyPress(view, Qt.Key_Space) qtbot.keyPress(view.focusWidget(), Qt.Key_Backspace) qtbot.keyClicks(view.focusWidget(), str(int(2 ** bit_exponet))) qtbot.keyPress(view.focusWidget(), Qt.Key_Down) MockQMessageBox.critical.assert_called_with(ANY, "Error", ANY) assert MockQMessageBox.critical.call_count == idx qtbot.keyClicks(view, '7') qtbot.keyPress(view, Qt.Key_Up) qtbot.keyClicks(view, '6') qtbot.keyPress(view, Qt.Key_Down) qtbot.keyPress(view, Qt.Key_Return) assert numpy.sum(expected_df[0].as_matrix() == dialog.get_value().as_matrix()) == len(expected_df) def test_dataframemodel_set_data_complex(monkeypatch): """Unit test #6115: editing complex dtypes raises error in df editor""" MockQMessageBox = Mock() attr_to_patch = ('spyder.widgets.variableexplorer' + '.dataframeeditor.QMessageBox') monkeypatch.setattr(attr_to_patch, MockQMessageBox) test_params = [(1, numpy.complex128), (2, numpy.complex64), (3, complex)] for count, complex_type in test_params: test_df = DataFrame(numpy.arange(10, 15), dtype=complex_type) model = DataFrameModel(test_df.copy()) index = model.createIndex(2, 1) assert not model.setData(index, '42') MockQMessageBox.critical.assert_called_with(ANY, "Error", ANY) assert MockQMessageBox.critical.call_count == count assert numpy.sum(test_df[0].as_matrix() == model.df.as_matrix()) == len(test_df) @flaky(max_runs=3) @pytest.mark.skipif(os.environ.get('CI', None) is not None or platform.startswith('linux'), reason="Fails on Travis for no good reason.") def test_dataframeeditor_edit_complex(qtbot, monkeypatch): """Test for #6115: editing complex dtypes raises error in df editor""" MockQMessageBox = Mock() attr_to_patch = ('spyder.widgets.variableexplorer' + '.dataframeeditor.QMessageBox') monkeypatch.setattr(attr_to_patch, MockQMessageBox) test_params = [(1, numpy.complex128), (2, numpy.complex64), (3, complex)] for count, complex_type in test_params: test_df = DataFrame(numpy.arange(10, 15), dtype=complex_type) dialog = DataFrameEditor() assert dialog.setup_and_check(test_df, 'Test Dataframe') dialog.show() qtbot.waitForWindowShown(dialog) view = dialog.dataTable qtbot.keyPress(view, Qt.Key_Right) qtbot.keyPress(view, Qt.Key_Down) qtbot.keyPress(view, Qt.Key_Space) qtbot.keyPress(view.focusWidget(), Qt.Key_Backspace) qtbot.keyClicks(view.focusWidget(), "42") qtbot.keyPress(view.focusWidget(), Qt.Key_Down) MockQMessageBox.critical.assert_called_with(ANY, "Error", ANY) assert MockQMessageBox.critical.call_count == count * 2 - 1 qtbot.keyPress(view, Qt.Key_Down) qtbot.keyClick(view, '1') qtbot.keyPress(view.focusWidget(), Qt.Key_Down) MockQMessageBox.critical.assert_called_with( ANY, "Error", ("Editing dtype {0!s} not yet supported." .format(type(test_df.iloc[1, 0]).__name__))) assert MockQMessageBox.critical.call_count == count * 2 qtbot.keyPress(view, Qt.Key_Return) qtbot.wait(1000) assert numpy.sum(test_df[0].as_matrix() == dialog.get_value().as_matrix()) == len(test_df) def test_dataframemodel_set_data_bool(monkeypatch): """Unit test that bools are editible in df and false-y strs are detected""" MockQMessageBox = Mock() attr_to_patch = ('spyder.widgets.variableexplorer' + '.dataframeeditor.QMessageBox') monkeypatch.setattr(attr_to_patch, MockQMessageBox) test_params = [numpy.bool_, numpy.bool, bool] test_strs = ['foo', 'false', 'f', '0', '0.', '0.0', '', ' '] expected_df = DataFrame([1, 0, 0, 0, 0, 0, 0, 0, 0], dtype=bool) for bool_type in test_params: test_df = DataFrame([0, 1, 1, 1, 1, 1, 1, 1, 0], dtype=bool_type) model = DataFrameModel(test_df.copy()) for idx, test_str in enumerate(test_strs): assert model.setData(model.createIndex(idx, 1), test_str) assert not MockQMessageBox.critical.called assert numpy.sum(expected_df[0].as_matrix() == model.df.as_matrix()[:, 0]) == len(expected_df) @flaky(max_runs=3) @pytest.mark.skipif(os.environ.get('CI', None) is not None or platform.startswith('linux'), reason="Fails on Travis for no good reason.") def test_dataframeeditor_edit_bool(qtbot, monkeypatch): """Unit test that bools are editible in df and false-y strs are detected""" MockQMessageBox = Mock() attr_to_patch = ('spyder.widgets.variableexplorer' + '.dataframeeditor.QMessageBox') monkeypatch.setattr(attr_to_patch, MockQMessageBox) test_params = [numpy.bool_, numpy.bool, bool] test_strs = ['foo', 'false', 'f', '0', '0.', '0.0', '', ' '] expected_df = DataFrame([1, 0, 0, 0, 0, 0, 0, 0, 0], dtype=bool) for bool_type in test_params: test_df = DataFrame([0, 1, 1, 1, 1, 1, 1, 1, 0], dtype=bool_type) dialog = DataFrameEditor() assert dialog.setup_and_check(test_df, 'Test Dataframe') dialog.show() qtbot.waitForWindowShown(dialog) view = dialog.dataTable qtbot.keyPress(view, Qt.Key_Right) for test_str in test_strs: qtbot.keyPress(view, Qt.Key_Space) qtbot.keyPress(view.focusWidget(), Qt.Key_Backspace) qtbot.keyClicks(view.focusWidget(), test_str) qtbot.keyPress(view.focusWidget(), Qt.Key_Down) assert not MockQMessageBox.critical.called qtbot.keyPress(view, Qt.Key_Return) qtbot.wait(1000) assert (numpy.sum(expected_df[0].as_matrix() == dialog.get_value().as_matrix()[:, 0]) == len(expected_df)) if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/widgets/variableexplorer/tests/test_namespacebrowser.py0000664000175000017500000000147713211142273030264 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License """ Tests for namespacebrowser.py """ # Standard library imports try: from unittest.mock import Mock except ImportError: from mock import Mock # Python 2 # Third party imports import pytest # Local imports from spyder.widgets.variableexplorer.namespacebrowser import NamespaceBrowser def test_setup_sets_dataframe_format(qtbot): browser = NamespaceBrowser(None) browser.set_shellwidget(Mock()) browser.setup(exclude_private=True, exclude_uppercase=True, exclude_capitalized=True, exclude_unsupported=True, minmax=False, dataframe_format='%10.5f') assert browser.editor.model.dataframe_format == '%10.5f' if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/widgets/variableexplorer/tests/test_utils.py0000664000175000017500000001734413224740762026077 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License """ Tests for utils.py """ from collections import defaultdict import datetime # Third party imports import numpy as np import pandas as pd import pytest # Local imports from spyder.config.base import get_supported_types from spyder.py3compat import PY2 from spyder.widgets.variableexplorer.utils import (sort_against, is_supported, value_to_display) def generate_complex_object(): """Taken from issue #4221.""" bug = defaultdict(list) for i in range(50000): a = {j:np.random.rand(10) for j in range(10)} bug[i] = a return bug COMPLEX_OBJECT = generate_complex_object() DF = pd.DataFrame([1,2,3]) PANEL = pd.Panel({0: pd.DataFrame([1,2]), 1:pd.DataFrame([3,4])}) # --- Tests # ----------------------------------------------------------------------------- def test_sort_against(): lista = [5, 6, 7] listb = [2, 3, 1] res = sort_against(lista, listb) assert res == [7, 5, 6] def test_sort_against_is_stable(): lista = [3, 0, 1] listb = [1, 1, 1] res = sort_against(lista, listb) assert res == lista def test_none_values_are_supported(): """Tests that None values are displayed by default""" supported_types = get_supported_types() mode = 'editable' none_var = None none_list = [2, None, 3, None] none_dict = {'a': None, 'b': 4} none_tuple = (None, [3, None, 4], 'eggs') assert is_supported(none_var, filters=tuple(supported_types[mode])) assert is_supported(none_list, filters=tuple(supported_types[mode])) assert is_supported(none_dict, filters=tuple(supported_types[mode])) assert is_supported(none_tuple, filters=tuple(supported_types[mode])) def test_str_subclass_display(): """Test for value_to_display of subclasses of str/basestring.""" class Test(str): def __repr__(self): return 'test' value = Test() value_display = value_to_display(value) assert 'Test object' in value_display def test_default_display(): """Tests for default_display.""" # Display of defaultdict assert (value_to_display(COMPLEX_OBJECT) == 'defaultdict object of collections module') # Display of array of COMPLEX_OBJECT assert (value_to_display(np.array(COMPLEX_OBJECT)) == 'ndarray object of numpy module') # Display of Panel assert (value_to_display(PANEL) == 'Panel object of pandas.core.panel module') def test_list_display(): """Tests for display of lists.""" long_list = list(range(100)) # Simple list assert value_to_display([1, 2, 3]) == '[1, 2, 3]' # Long list assert (value_to_display(long_list) == '[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...]') # Short list of lists assert (value_to_display([long_list] * 3) == '[[0, 1, 2, 3, 4, ...], [0, 1, 2, 3, 4, ...], [0, 1, 2, 3, 4, ...]]') # Long list of lists result = '[' + ''.join('[0, 1, 2, 3, 4, ...], '*10)[:-2] + ']' assert value_to_display([long_list] * 10) == result[:70] + ' ...' # Multiple level lists assert (value_to_display([[1, 2, 3, [4], 5]] + long_list) == '[[1, 2, 3, [...], 5], 0, 1, 2, 3, 4, 5, 6, 7, 8, ...]') assert value_to_display([1, 2, [DF]]) == '[1, 2, [Dataframe]]' assert value_to_display([1, 2, [[DF], PANEL]]) == '[1, 2, [[...], Panel]]' # List of complex object assert value_to_display([COMPLEX_OBJECT]) == '[defaultdict]' # List of composed objects li = [COMPLEX_OBJECT, PANEL, 1, {1:2, 3:4}, DF] result = '[defaultdict, Panel, 1, {1:2, 3:4}, Dataframe]' assert value_to_display(li) == result # List starting with a non-supported object (#5313) supported_types = tuple(get_supported_types()['editable']) li = [len, 1] assert value_to_display(li) == '[builtin_function_or_method, 1]' assert is_supported(li, filters=supported_types) def test_dict_display(): """Tests for display of dicts.""" long_list = list(range(100)) long_dict = dict(zip(list(range(100)), list(range(100)))) # Simple dict assert value_to_display({0:0, 'a':'b'}) == "{0:0, 'a':'b'}" # Long dict assert (value_to_display(long_dict) == '{0:0, 1:1, 2:2, 3:3, 4:4, 5:5, 6:6, 7:7, 8:8, 9:9, ...}') # Short list of lists assert (value_to_display({1:long_dict, 2:long_dict}) == '{1:{0:0, 1:1, 2:2, 3:3, 4:4, ...}, 2:{0:0, 1:1, 2:2, 3:3, 4:4, ...}}') # Long dict of dicts result = ('{(0, 0, 0, 0, 0, ...):[0, 1, 2, 3, 4, ...], ' '(1, 1, 1, 1, 1, ...):[0, 1, 2, 3, 4, ...]}') assert value_to_display({(0,)*100:long_list, (1,)*100:long_list}) == result[:70] + ' ...' # Multiple level dicts assert (value_to_display({0: {1:1, 2:2, 3:3, 4:{0:0}, 5:5}, 1:1}) == '{0:{1:1, 2:2, 3:3, 4:{...}, 5:5}, 1:1}') assert value_to_display({0:0, 1:1, 2:2, 3:DF}) == '{0:0, 1:1, 2:2, 3:Dataframe}' assert value_to_display({0:0, 1:1, 2:[[DF], PANEL]}) == '{0:0, 1:1, 2:[[...], Panel]}' # Dict of complex object assert value_to_display({0:COMPLEX_OBJECT}) == '{0:defaultdict}' # Dict of composed objects li = {0:COMPLEX_OBJECT, 1:PANEL, 2:2, 3:{0:0, 1:1}, 4:DF} result = '{0:defaultdict, 1:Panel, 2:2, 3:{0:0, 1:1}, 4:Dataframe}' assert value_to_display(li) == result # Dict starting with a non-supported object (#5313) supported_types = tuple(get_supported_types()['editable']) di = {max: len, 1: 1} assert value_to_display(di) in ( '{builtin_function_or_method:builtin_function_or_method, 1:1}', '{1:1, builtin_function_or_method:builtin_function_or_method}') assert is_supported(di, filters=supported_types) def test_datetime_display(): """Simple tests that dates, datetimes and timedeltas display correctly.""" test_date = datetime.date(2017, 12, 18) test_date_2 = datetime.date(2017, 2, 2) test_datetime = datetime.datetime(2017, 12, 18, 13, 43, 2) test_datetime_2 = datetime.datetime(2017, 8, 18, 0, 41, 27) test_timedelta = datetime.timedelta(-1, 2000) test_timedelta_2 = datetime.timedelta(0, 3600) # Simple dates/datetimes/timedeltas assert value_to_display(test_date) == '2017-12-18' assert value_to_display(test_datetime) == '2017-12-18 13:43:02' assert value_to_display(test_timedelta) == '-1 day, 0:33:20' # Lists of dates/datetimes/timedeltas assert (value_to_display([test_date, test_date_2]) == '[2017-12-18, 2017-02-02]') assert (value_to_display([test_datetime, test_datetime_2]) == '[2017-12-18 13:43:02, 2017-08-18 00:41:27]') assert (value_to_display([test_timedelta, test_timedelta_2]) == '[-1 day, 0:33:20, 1:00:00]') # Tuple of dates/datetimes/timedeltas assert (value_to_display((test_date, test_datetime, test_timedelta)) == '(2017-12-18, 2017-12-18 13:43:02, -1 day, 0:33:20)') # Dict of dates/datetimes/timedeltas assert (value_to_display({0: test_date, 1: test_datetime, 2: test_timedelta_2}) == ("{0:2017-12-18, 1:2017-12-18 13:43:02, 2:1:00:00}")) def test_str_in_container_display(): """Test that strings are displayed correctly inside lists or dicts.""" # Assert that both bytes and unicode return the right display assert value_to_display([b'a', u'b']) == "['a', 'b']" # Encoded unicode gives bytes and it can't be transformed to # unicode again. So this test the except part of # is_binary_string(value) in value_to_display if PY2: assert value_to_display([u'Э'.encode('cp1251')]) == "['\xdd']" if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/widgets/variableexplorer/tests/issue_3896.csv0000664000175000017500000000023113156676664025664 0ustar carloscarlos00000000000000,Unieke_Idcode,a,b,c,d,f,g,h,i,j,k,l,m,n,o,p,q 0,flooooo,0.55,10100103,595,sdsdsdf,sadsf,70,..,X1,30,01/02/2014,8.72E+12,sdsf,dsffds,dsdfbvdfg,ff, spyder-3.2.6/spyder/widgets/variableexplorer/tests/issue_2514.csv0000664000175000017500000000051713156676664025655 0ustar carloscarlos00000000000000Date (MMM-YY),"El Salvador, San Salvador, Sorghum (Maicillo), Retail, (USD/Kg)","El Salvador, San Salvador, Sorghum (Maicillo), Wholesale, (USD/Kg)","El Salvador, San Salvador, Wheat (flour), Retail, (USD/Kg)","El Salvador, San Salvador, Wheat (flour), Wholesale, (USD/Kg)" Jan-2006,0.28,0.19,0.54,0.41 Feb-2006,0.28,0.19,0.54,0.41 spyder-3.2.6/spyder/widgets/variableexplorer/tests/test_texteditor.py0000664000175000017500000000224113224121062027102 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for texteditor.py """ # Test library imports import pytest # Local imports from spyder.py3compat import PY3 from spyder.widgets.variableexplorer.texteditor import TextEditor @pytest.fixture def setup_texteditor(qtbot, text): """Set up TextEditor.""" texteditor = TextEditor(text) qtbot.addWidget(texteditor) return texteditor def test_texteditor(qtbot): """Run TextEditor dialog.""" text = """01234567890123456789012345678901234567890123456789012345678901234567890123456789 dedekdh elkd ezd ekjd lekdj elkdfjelfjk e""" texteditor = setup_texteditor(qtbot, text) texteditor.show() assert texteditor dlg_text = texteditor.get_value() assert text == dlg_text @pytest.mark.skipif(PY3, reason="It makes no sense in Python 3") def test_texteditor_setup_and_check(): import string dig_its = string.digits translate_digits = string.maketrans(dig_its,len(dig_its)*' ') editor = TextEditor(None) assert not editor.setup_and_check(translate_digits) if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/widgets/variableexplorer/tests/test_collectioneditor.py0000664000175000017500000002650013224740762030273 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License """ Tests for collectionseditor.py """ # Standard library imports import os # Example module for testing display inside collecitoneditor import copy import datetime try: from unittest.mock import Mock, ANY except ImportError: from mock import Mock, ANY # Python 2 # Third party imports import pandas import pytest from flaky import flaky # Local imports from spyder.widgets.variableexplorer.collectionseditor import ( CollectionsEditorTableView, CollectionsModel, CollectionsEditor, LARGE_NROWS, ROWS_TO_LOAD) # Helper functions def data(cm, i, j): return cm.data(cm.createIndex(i, j)) def data_table(cm, n_rows, n_cols): return [[data(cm, i, j) for i in range(n_rows)] for j in range(n_cols)] # --- Tests # ----------------------------------------------------------------------------- def test_create_dataframeeditor_with_correct_format(qtbot, monkeypatch): MockDataFrameEditor = Mock() mockDataFrameEditor_instance = MockDataFrameEditor() monkeypatch.setattr('spyder.widgets.variableexplorer.collectionseditor.DataFrameEditor', MockDataFrameEditor) df = pandas.DataFrame(['foo', 'bar']) editor = CollectionsEditorTableView(None, {'df': df}) qtbot.addWidget(editor) editor.set_dataframe_format('%10d') editor.delegate.createEditor(None, None, editor.model.createIndex(0, 3)) mockDataFrameEditor_instance.dataModel.set_format.assert_called_once_with('%10d') def test_accept_sig_option_changed_from_dataframeeditor(qtbot, monkeypatch): df = pandas.DataFrame(['foo', 'bar']) editor = CollectionsEditorTableView(None, {'df': df}) qtbot.addWidget(editor) editor.set_dataframe_format('%10d') assert editor.model.dataframe_format == '%10d' editor.delegate.createEditor(None, None, editor.model.createIndex(0, 3)) dataframe_editor = next(iter(editor.delegate._editors.values()))['editor'] qtbot.addWidget(dataframe_editor) dataframe_editor.sig_option_changed.emit('dataframe_format', '%5f') assert editor.model.dataframe_format == '%5f' def test_collectionsmodel_with_two_ints(): coll = {'x': 1, 'y': 2} cm = CollectionsModel(None, coll) assert cm.rowCount() == 2 assert cm.columnCount() == 4 # dict is unordered, so first row might be x or y assert data(cm, 0, 0) in {'x', 'y'} if data(cm, 0, 0) == 'x': row_with_x = 0 row_with_y = 1 else: row_with_x = 1 row_with_y = 0 assert data(cm, row_with_x, 1) == 'int' assert data(cm, row_with_x, 2) == '1' assert data(cm, row_with_x, 3) == '1' assert data(cm, row_with_y, 0) == 'y' assert data(cm, row_with_y, 1) == 'int' assert data(cm, row_with_y, 2) == '1' assert data(cm, row_with_y, 3) == '2' def test_collectionsmodel_with_datetimeindex(): # Regression test for issue #3380 rng = pandas.date_range('10/1/2016', periods=25, freq='bq') coll = {'rng': rng} cm = CollectionsModel(None, coll) assert data(cm, 0, 0) == 'rng' assert data(cm, 0, 1) == 'DatetimeIndex' assert data(cm, 0, 2) == '(25,)' or data(cm, 0, 2) == '(25L,)' assert data(cm, 0, 3) == rng.summary() def test_shows_dataframeeditor_when_editing_datetimeindex(qtbot, monkeypatch): MockDataFrameEditor = Mock() mockDataFrameEditor_instance = MockDataFrameEditor() monkeypatch.setattr('spyder.widgets.variableexplorer.collectionseditor.DataFrameEditor', MockDataFrameEditor) rng = pandas.date_range('10/1/2016', periods=25, freq='bq') coll = {'rng': rng} editor = CollectionsEditorTableView(None, coll) editor.delegate.createEditor(None, None, editor.model.createIndex(0, 3)) mockDataFrameEditor_instance.show.assert_called_once_with() def test_sort_collectionsmodel(): coll = [1, 3, 2] cm = CollectionsModel(None, coll) assert cm.rowCount() == 3 assert cm.columnCount() == 4 cm.sort(0) # sort by index assert data_table(cm, 3, 4) == [['0', '1', '2'], ['int', 'int', 'int'], ['1', '1', '1'], ['1', '3', '2']] cm.sort(3) # sort by value assert data_table(cm, 3, 4) == [['0', '2', '1'], ['int', 'int', 'int'], ['1', '1', '1'], ['1', '2', '3']] coll = [[1, 2], 3] cm = CollectionsModel(None, coll) assert cm.rowCount() == 2 assert cm.columnCount() == 4 cm.sort(1) # sort by type assert data_table(cm, 2, 4) == [['1', '0'], ['int', 'list'], ['1', '2'], ['3', '[1, 2]']] cm.sort(2) # sort by size assert data_table(cm, 2, 4) == [['1', '0'], ['int', 'list'], ['1', '2'], ['3', '[1, 2]']] def test_sort_collectionsmodel_with_many_rows(): coll = list(range(2*LARGE_NROWS)) cm = CollectionsModel(None, coll) assert cm.rowCount() == cm.rows_loaded == ROWS_TO_LOAD assert cm.columnCount() == 4 cm.sort(1) # This was causing an issue (#5232) cm.fetchMore() assert cm.rowCount() == 2 * ROWS_TO_LOAD for _ in range(3): cm.fetchMore() assert cm.rowCount() == len(coll) def test_rename_and_duplicate_item_in_collection_editor(): collections = {'list': ([1, 2, 3], False, True), 'tuple': ((1, 2, 3), False, False), 'dict': ({'a': 1, 'b': 2}, True, True)} for coll, rename_enabled, duplicate_enabled in collections.values(): coll_copy = copy.copy(coll) editor = CollectionsEditorTableView(None, coll) assert editor.rename_action.isEnabled() assert editor.duplicate_action.isEnabled() editor.setCurrentIndex(editor.model.createIndex(0, 0)) editor.refresh_menu() assert editor.rename_action.isEnabled() == rename_enabled assert editor.duplicate_action.isEnabled() == duplicate_enabled if isinstance(coll, list): editor.duplicate_item() assert editor.model.get_data() == coll_copy + [coll_copy[0]] def test_edit_mutable_and_immutable_types(monkeypatch): """Check to ensure mutable types (lists, dicts) and individual values are editable, but not immutable ones (tuples) or anything inside of them, per #5991""" MockQLineEdit = Mock() attr_to_patch_qlineedit = ('spyder.widgets.variableexplorer.' + 'collectionseditor.QLineEdit') monkeypatch.setattr(attr_to_patch_qlineedit, MockQLineEdit) MockTextEditor = Mock() attr_to_patch_textedit = ('spyder.widgets.variableexplorer.' + 'collectionseditor.TextEditor') monkeypatch.setattr(attr_to_patch_textedit, MockTextEditor) MockQDateTimeEdit = Mock() attr_to_patch_qdatetimeedit = ('spyder.widgets.variableexplorer.' + 'collectionseditor.QDateTimeEdit') monkeypatch.setattr(attr_to_patch_qdatetimeedit, MockQDateTimeEdit) MockCollectionsEditor = Mock() mockCollectionsEditor_instance = MockCollectionsEditor() attr_to_patch_coledit = ('spyder.widgets.variableexplorer.' + 'collectionseditor.CollectionsEditor') monkeypatch.setattr(attr_to_patch_coledit, MockCollectionsEditor) list_test = [1, "012345678901234567901234567890123456789012", datetime.datetime(2017, 12, 24, 7, 9), [1, 2, 3], (2, "eggs")] tup_test = tuple(list_test) # Tests for mutable type (list) # editor_list = CollectionsEditorTableView(None, list_test) # Directly editable values inside list editor_list_value = editor_list.delegate.createEditor( None, None, editor_list.model.createIndex(0, 3)) assert editor_list_value is not None assert MockQLineEdit.call_count == 1 # Text Editor for long text inside list editor_list.delegate.createEditor(None, None, editor_list.model.createIndex(1, 3)) assert MockTextEditor.call_count == 2 MockTextEditor.assert_called_with(ANY, ANY, readonly=False) # Datetime inside list editor_list_datetime = editor_list.delegate.createEditor( None, None, editor_list.model.createIndex(2, 3)) assert editor_list_datetime is not None assert MockQDateTimeEdit.call_count == 1 # List inside list editor_list.delegate.createEditor(None, None, editor_list.model.createIndex(3, 3)) assert mockCollectionsEditor_instance.show.call_count == 1 mockCollectionsEditor_instance.setup.assert_called_with(ANY, ANY, icon=ANY, readonly=False) # Tuple inside list editor_list.delegate.createEditor(None, None, editor_list.model.createIndex(4, 3)) assert mockCollectionsEditor_instance.show.call_count == 2 mockCollectionsEditor_instance.setup.assert_called_with(ANY, ANY, icon=ANY, readonly=True) # Tests for immutable type (tuple) # editor_tup = CollectionsEditorTableView(None, tup_test) # Directly editable values inside tuple editor_tup_value = editor_tup.delegate.createEditor( None, None, editor_tup.model.createIndex(0, 3)) assert editor_tup_value is None assert MockQLineEdit.call_count == 1 # Text Editor for long text inside tuple editor_tup.delegate.createEditor(None, None, editor_tup.model.createIndex(1, 3)) assert MockTextEditor.call_count == 4 MockTextEditor.assert_called_with(ANY, ANY, readonly=True) # Datetime inside tuple editor_tup_datetime = editor_tup.delegate.createEditor( None, None, editor_tup.model.createIndex(2, 3)) assert editor_tup_datetime is None assert MockQDateTimeEdit.call_count == 1 # List inside tuple editor_tup.delegate.createEditor(None, None, editor_tup.model.createIndex(3, 3)) assert mockCollectionsEditor_instance.show.call_count == 3 mockCollectionsEditor_instance.setup.assert_called_with(ANY, ANY, icon=ANY, readonly=True) # Tuple inside tuple editor_tup.delegate.createEditor(None, None, editor_tup.model.createIndex(4, 3)) assert mockCollectionsEditor_instance.show.call_count == 4 mockCollectionsEditor_instance.setup.assert_called_with(ANY, ANY, icon=ANY, readonly=True) @flaky(max_runs=3) def test_view_module_in_coledit(): """Check that modules don't produce an error when trying to open them in Variable Explorer, and are set as readonly. Regression test for #6080""" editor = CollectionsEditor() editor.setup(os, "module_test", readonly=False) assert editor.widget.editor.readonly if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/widgets/variableexplorer/tests/__init__.py0000664000175000017500000000050213156676664025440 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Copyright (c) Spyder Project Contributors # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Tests.""" spyder-3.2.6/spyder/widgets/variableexplorer/tests/test_arrayeditor.py0000664000175000017500000002225713224121062027245 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License """ Tests for arrayeditor.py """ # Standard library imports import os from sys import platform try: from unittest.mock import Mock, ANY except ImportError: from mock import Mock, ANY # Python 2 # Third party imports import numpy as np from numpy.testing import assert_array_equal import pytest from qtpy.QtCore import Qt from flaky import flaky # Local imports from spyder.widgets.variableexplorer.arrayeditor import ArrayEditor, ArrayModel def launch_arrayeditor(data, title="", xlabels=None, ylabels=None): """Helper routine to launch an arrayeditor and return its result""" dlg = ArrayEditor() assert dlg.setup_and_check(data, title, xlabels=xlabels, ylabels=ylabels) dlg.show() dlg.accept() # trigger slot connected to OK button return dlg.get_value() def setup_arrayeditor(qbot, data, title="", xlabels=None, ylabels=None): """Setups an arrayeditor.""" dlg = ArrayEditor() dlg.setup_and_check(data, title, xlabels=xlabels, ylabels=ylabels) dlg.show() qbot.addWidget(dlg) return dlg # --- Tests # ----------------------------------------------------------------------------- def test_type_errors(qtbot): """Verify that we don't get a TypeError for certain structured arrays. Fixes issue 5254. """ arr = np.ones(2, dtype=[('X', 'f8', (2,10)), ('S', 'S10')]) dlg = setup_arrayeditor(qtbot, arr) qtbot.keyClick(dlg.arraywidget.view, Qt.Key_Down, modifier=Qt.ShiftModifier) contents = dlg.arraywidget.model.get_value(dlg.arraywidget.model.index(0, 0)) assert_array_equal(contents, np.ones(10)) def test_arrayeditor_format(qtbot): """Changes the format of the array and validates its selected content.""" arr = np.array([1, 2, 3], dtype=np.float32) dlg = setup_arrayeditor(qtbot, arr, "test array float32") qtbot.keyClick(dlg.arraywidget.view, Qt.Key_Down, modifier=Qt.ShiftModifier) qtbot.keyClick(dlg.arraywidget.view, Qt.Key_Down, modifier=Qt.ShiftModifier) contents = dlg.arraywidget.view._sel_to_text(dlg.arraywidget.view.selectedIndexes()) assert contents == "1\n2\n" dlg.arraywidget.view.model().set_format("%.18e") assert dlg.arraywidget.view.model().get_format() == "%.18e" qtbot.keyClick(dlg.arraywidget.view, Qt.Key_Down, modifier=Qt.ShiftModifier) qtbot.keyClick(dlg.arraywidget.view, Qt.Key_Down, modifier=Qt.ShiftModifier) contents = dlg.arraywidget.view._sel_to_text(dlg.arraywidget.view.selectedIndexes()) assert contents == "1.000000000000000000e+00\n2.000000000000000000e+00\n" def test_arrayeditor_with_string_array(qtbot): arr = np.array(["kjrekrjkejr"]) assert arr == launch_arrayeditor(arr, "string array") def test_arrayeditor_with_unicode_array(qtbot): arr = np.array([u"ñññéáíó"]) assert arr == launch_arrayeditor(arr, "unicode array") def test_arrayeditor_with_masked_array(qtbot): arr = np.ma.array([[1, 0], [1, 0]], mask=[[True, False], [False, False]]) assert_array_equal(arr, launch_arrayeditor(arr, "masked array")) def test_arrayeditor_with_record_array(qtbot): arr = np.zeros((2, 2), {'names': ('red', 'green', 'blue'), 'formats': (np.float32, np.float32, np.float32)}) assert_array_equal(arr, launch_arrayeditor(arr, "record array")) @pytest.mark.skipif(not os.name == 'nt', reason="It segfaults sometimes on Linux") def test_arrayeditor_with_record_array_with_titles(qtbot): arr = np.array([(0, 0.0), (0, 0.0), (0, 0.0)], dtype=[(('title 1', 'x'), '|i1'), (('title 2', 'y'), '>f4')]) assert_array_equal(arr, launch_arrayeditor(arr, "record array with titles")) def test_arrayeditor_with_float_array(qtbot): arr = np.random.rand(5, 5) assert_array_equal(arr, launch_arrayeditor(arr, "float array", xlabels=['a', 'b', 'c', 'd', 'e'])) def test_arrayeditor_with_complex_array(qtbot): arr = np.round(np.random.rand(5, 5)*10)+\ np.round(np.random.rand(5, 5)*10)*1j assert_array_equal(arr, launch_arrayeditor(arr, "complex array", xlabels=np.linspace(-12, 12, 5), ylabels=np.linspace(-12, 12, 5))) def test_arrayeditor_with_bool_array(qtbot): arr_in = np.array([True, False, True]) arr_out = launch_arrayeditor(arr_in, "bool array") assert arr_in is arr_out def test_arrayeditor_with_int8_array(qtbot): arr = np.array([1, 2, 3], dtype="int8") assert_array_equal(arr, launch_arrayeditor(arr, "int array")) def test_arrayeditor_with_float16_array(qtbot): arr = np.zeros((5,5), dtype=np.float16) assert_array_equal(arr, launch_arrayeditor(arr, "float16 array")) def test_arrayeditor_with_3d_array(qtbot): arr = np.zeros((3,3,4)) arr[0,0,0]=1 arr[0,0,1]=2 arr[0,0,2]=3 assert_array_equal(arr, launch_arrayeditor(arr, "3D array")) def test_arrayeditor_with_empty_3d_array(qtbot): arr = np.zeros((0, 10, 2)) assert_array_equal(arr, launch_arrayeditor(arr, "3D array")) arra = np.zeros((1, 10, 2)) assert_array_equal(arr, launch_arrayeditor(arr, "3D array")) def test_arrayeditor_edit_1d_array(qtbot): exp_arr = np.array([1, 0, 2, 3, 4]) arr = np.arange(0, 5) dlg = ArrayEditor() assert dlg.setup_and_check(arr, '1D array', xlabels=None, ylabels=None) dlg.show() qtbot.waitForWindowShown(dlg) view = dlg.arraywidget.view qtbot.keyPress(view, Qt.Key_Down) qtbot.keyPress(view, Qt.Key_Up) qtbot.keyClicks(view, '1') qtbot.keyPress(view, Qt.Key_Down) qtbot.keyClicks(view, '0') qtbot.keyPress(view, Qt.Key_Down) qtbot.keyPress(view, Qt.Key_Return) assert np.sum(exp_arr == dlg.get_value()) == 5 def test_arrayeditor_edit_2d_array(qtbot): arr = np.ones((3, 3)) diff_arr = arr.copy() dlg = ArrayEditor() assert dlg.setup_and_check(arr, '2D array', xlabels=None, ylabels=None) dlg.show() qtbot.waitForWindowShown(dlg) view = dlg.arraywidget.view qtbot.keyPress(view, Qt.Key_Down) qtbot.keyPress(view, Qt.Key_Right) qtbot.keyClicks(view, '3') qtbot.keyPress(view, Qt.Key_Down) qtbot.keyPress(view, Qt.Key_Right) qtbot.keyClicks(view, '0') qtbot.keyPress(view, Qt.Key_Left) qtbot.keyPress(view, Qt.Key_Return) assert np.sum(diff_arr != dlg.get_value()) == 2 def test_arraymodel_set_data_overflow(monkeypatch): """Unit test #6114: entry of an overflow int caught and handled properly""" MockQMessageBox = Mock() attr_to_patch = 'spyder.widgets.variableexplorer.arrayeditor.QMessageBox' monkeypatch.setattr(attr_to_patch, MockQMessageBox) # Numpy doesn't raise OverflowError on Linux for ints smaller than 64 bits if platform.startswith('linux'): int32_bit_exponent = 66 else: int32_bit_exponent = 34 test_parameters = [(1, np.int32, int32_bit_exponent), (2, np.int64, 66)] for idx, int_type, bit_exponent in test_parameters: test_array = np.array([[5], [6], [7], [3], [4]], dtype=int_type) model = ArrayModel(test_array.copy()) index = model.createIndex(0, 2) assert not model.setData(index, str(int(2 ** bit_exponent))) MockQMessageBox.critical.assert_called_with(ANY, "Error", ANY) assert MockQMessageBox.critical.call_count == idx assert np.sum(test_array == model._data) == len(test_array) @flaky(max_runs=3) def test_arrayeditor_edit_overflow(qtbot, monkeypatch): """Int. test #6114: entry of an overflow int caught and handled properly""" MockQMessageBox = Mock() attr_to_patch = 'spyder.widgets.variableexplorer.arrayeditor.QMessageBox' monkeypatch.setattr(attr_to_patch, MockQMessageBox) # Numpy doesn't raise the OverflowError for ints smaller than 64 bits if platform.startswith('linux'): int32_bit_exponent = 66 else: int32_bit_exponent = 34 test_parameters = [(1, np.int32, int32_bit_exponent), (2, np.int64, 66)] expected_array = np.array([5, 6, 7, 3, 4]) for idx, int_type, bit_exponent in test_parameters: test_array = np.arange(0, 5).astype(int_type) dialog = ArrayEditor() assert dialog.setup_and_check(test_array, '1D array', xlabels=None, ylabels=None) dialog.show() qtbot.waitForWindowShown(dialog) view = dialog.arraywidget.view qtbot.keyPress(view, Qt.Key_Down) qtbot.keyPress(view, Qt.Key_Up) qtbot.keyClicks(view, '5') qtbot.keyPress(view, Qt.Key_Down) qtbot.keyPress(view, Qt.Key_Space) qtbot.keyClicks(view.focusWidget(), str(int(2 ** bit_exponent))) qtbot.keyPress(view.focusWidget(), Qt.Key_Down) MockQMessageBox.critical.assert_called_with(ANY, "Error", ANY) assert MockQMessageBox.critical.call_count == idx qtbot.keyClicks(view, '7') qtbot.keyPress(view, Qt.Key_Up) qtbot.keyClicks(view, '6') qtbot.keyPress(view, Qt.Key_Down) qtbot.keyPress(view, Qt.Key_Return) assert np.sum(expected_array == dialog.get_value()) == len(expected_array) if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/widgets/variableexplorer/collectionseditor.py0000664000175000017500000016321713224740762026264 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Collections (i.e. dictionary, list and tuple) editor widget and dialog """ #TODO: Multiple selection: open as many editors (array/dict/...) as necessary, # at the same time # pylint: disable=C0103 # pylint: disable=R0903 # pylint: disable=R0911 # pylint: disable=R0201 # Standard library imports from __future__ import print_function import datetime import gc import sys import warnings # Third party imports from qtpy.compat import getsavefilename, to_qvariant from qtpy.QtCore import (QAbstractTableModel, QDateTime, QModelIndex, Qt, Signal, Slot) from qtpy.QtGui import QColor, QKeySequence from qtpy.QtWidgets import (QAbstractItemDelegate, QApplication, QDateEdit, QDateTimeEdit, QDialog, QDialogButtonBox, QInputDialog, QItemDelegate, QLineEdit, QMenu, QMessageBox, QTableView, QVBoxLayout, QWidget) # Local import from spyder.config.base import _ from spyder.config.fonts import DEFAULT_SMALL_DELTA from spyder.config.gui import get_font from spyder.py3compat import (io, is_binary_string, is_text_string, PY3, to_text_string) from spyder.utils import icon_manager as ima from spyder.utils.misc import fix_reference_name, getcwd_or_home from spyder.utils.qthelpers import (add_actions, create_action, mimedata2url) from spyder.widgets.variableexplorer.importwizard import ImportWizard from spyder.widgets.variableexplorer.texteditor import TextEditor from spyder.widgets.variableexplorer.utils import ( array, DataFrame, DatetimeIndex, display_to_value, FakeObject, get_color_name, get_human_readable_type, get_size, Image, is_editable_type, is_known_type, MaskedArray, ndarray, np_savetxt, Series, sort_against, try_to_eval, unsorted_unique, value_to_display, get_object_attrs, get_type_string) if ndarray is not FakeObject: from spyder.widgets.variableexplorer.arrayeditor import ArrayEditor if DataFrame is not FakeObject: from spyder.widgets.variableexplorer.dataframeeditor import DataFrameEditor LARGE_NROWS = 100 ROWS_TO_LOAD = 50 class ProxyObject(object): """Dictionary proxy to an unknown object.""" def __init__(self, obj): """Constructor.""" self.__obj__ = obj def __len__(self): """Get len according to detected attributes.""" return len(get_object_attrs(self.__obj__)) def __getitem__(self, key): """Get attribute corresponding to key.""" return getattr(self.__obj__, key) def __setitem__(self, key, value): """Set attribute corresponding to key with value.""" try: setattr(self.__obj__, key, value) except TypeError: pass class ReadOnlyCollectionsModel(QAbstractTableModel): """CollectionsEditor Read-Only Table Model""" def __init__(self, parent, data, title="", names=False, minmax=False, dataframe_format=None, remote=False): QAbstractTableModel.__init__(self, parent) if data is None: data = {} self.names = names self.minmax = minmax self.dataframe_format = dataframe_format self.remote = remote self.header0 = None self._data = None self.total_rows = None self.showndata = None self.keys = None self.title = to_text_string(title) # in case title is not a string if self.title: self.title = self.title + ' - ' self.sizes = [] self.types = [] self.set_data(data) def get_data(self): """Return model data""" return self._data def set_data(self, data, coll_filter=None): """Set model data""" self._data = data data_type = get_type_string(data) if coll_filter is not None and not self.remote and \ isinstance(data, (tuple, list, dict)): data = coll_filter(data) self.showndata = data self.header0 = _("Index") if self.names: self.header0 = _("Name") if isinstance(data, tuple): self.keys = list(range(len(data))) self.title += _("Tuple") elif isinstance(data, list): self.keys = list(range(len(data))) self.title += _("List") elif isinstance(data, dict): self.keys = list(data.keys()) self.title += _("Dictionary") if not self.names: self.header0 = _("Key") else: self.keys = get_object_attrs(data) self._data = data = self.showndata = ProxyObject(data) if not self.names: self.header0 = _("Attribute") if not isinstance(self._data, ProxyObject): self.title += (' (' + str(len(self.keys)) + ' ' + _("elements") + ')') else: self.title += data_type self.total_rows = len(self.keys) if self.total_rows > LARGE_NROWS: self.rows_loaded = ROWS_TO_LOAD else: self.rows_loaded = self.total_rows self.set_size_and_type() self.reset() def set_size_and_type(self, start=None, stop=None): data = self._data if start is None and stop is None: start = 0 stop = self.rows_loaded fetch_more = False else: fetch_more = True if self.remote: sizes = [ data[self.keys[index]]['size'] for index in range(start, stop) ] types = [ data[self.keys[index]]['type'] for index in range(start, stop) ] else: sizes = [ get_size(data[self.keys[index]]) for index in range(start, stop) ] types = [ get_human_readable_type(data[self.keys[index]]) for index in range(start, stop) ] if fetch_more: self.sizes = self.sizes + sizes self.types = self.types + types else: self.sizes = sizes self.types = types def sort(self, column, order=Qt.AscendingOrder): """Overriding sort method""" reverse = (order==Qt.DescendingOrder) if column == 0: self.sizes = sort_against(self.sizes, self.keys, reverse) self.types = sort_against(self.types, self.keys, reverse) try: self.keys.sort(reverse=reverse) except: pass elif column == 1: self.keys[:self.rows_loaded] = sort_against(self.keys, self.types, reverse) self.sizes = sort_against(self.sizes, self.types, reverse) try: self.types.sort(reverse=reverse) except: pass elif column == 2: self.keys[:self.rows_loaded] = sort_against(self.keys, self.sizes, reverse) self.types = sort_against(self.types, self.sizes, reverse) try: self.sizes.sort(reverse=reverse) except: pass elif column == 3: values = [self._data[key] for key in self.keys] self.keys = sort_against(self.keys, values, reverse) self.sizes = sort_against(self.sizes, values, reverse) self.types = sort_against(self.types, values, reverse) self.beginResetModel() self.endResetModel() def columnCount(self, qindex=QModelIndex()): """Array column number""" return 4 def rowCount(self, index=QModelIndex()): """Array row number""" if self.total_rows <= self.rows_loaded: return self.total_rows else: return self.rows_loaded def canFetchMore(self, index=QModelIndex()): if self.total_rows > self.rows_loaded: return True else: return False def fetchMore(self, index=QModelIndex()): reminder = self.total_rows - self.rows_loaded items_to_fetch = min(reminder, ROWS_TO_LOAD) self.set_size_and_type(self.rows_loaded, self.rows_loaded + items_to_fetch) self.beginInsertRows(QModelIndex(), self.rows_loaded, self.rows_loaded + items_to_fetch - 1) self.rows_loaded += items_to_fetch self.endInsertRows() def get_index_from_key(self, key): try: return self.createIndex(self.keys.index(key), 0) except (RuntimeError, ValueError): return QModelIndex() def get_key(self, index): """Return current key""" return self.keys[index.row()] def get_value(self, index): """Return current value""" if index.column() == 0: return self.keys[ index.row() ] elif index.column() == 1: return self.types[ index.row() ] elif index.column() == 2: return self.sizes[ index.row() ] else: return self._data[ self.keys[index.row()] ] def get_bgcolor(self, index): """Background color depending on value""" if index.column() == 0: color = QColor(Qt.lightGray) color.setAlphaF(.05) elif index.column() < 3: color = QColor(Qt.lightGray) color.setAlphaF(.2) else: color = QColor(Qt.lightGray) color.setAlphaF(.3) return color def data(self, index, role=Qt.DisplayRole): """Cell content""" if not index.isValid(): return to_qvariant() value = self.get_value(index) if index.column() == 3 and self.remote: value = value['view'] if index.column() == 3: display = value_to_display(value, minmax=self.minmax) else: display = to_text_string(value) if role == Qt.DisplayRole: return to_qvariant(display) elif role == Qt.EditRole: return to_qvariant(value_to_display(value)) elif role == Qt.TextAlignmentRole: if index.column() == 3: if len(display.splitlines()) < 3: return to_qvariant(int(Qt.AlignLeft|Qt.AlignVCenter)) else: return to_qvariant(int(Qt.AlignLeft|Qt.AlignTop)) else: return to_qvariant(int(Qt.AlignLeft|Qt.AlignVCenter)) elif role == Qt.BackgroundColorRole: return to_qvariant( self.get_bgcolor(index) ) elif role == Qt.FontRole: return to_qvariant(get_font(font_size_delta=DEFAULT_SMALL_DELTA)) return to_qvariant() def headerData(self, section, orientation, role=Qt.DisplayRole): """Overriding method headerData""" if role != Qt.DisplayRole: return to_qvariant() i_column = int(section) if orientation == Qt.Horizontal: headers = (self.header0, _("Type"), _("Size"), _("Value")) return to_qvariant( headers[i_column] ) else: return to_qvariant() def flags(self, index): """Overriding method flags""" # This method was implemented in CollectionsModel only, but to enable # tuple exploration (even without editing), this method was moved here if not index.isValid(): return Qt.ItemIsEnabled return Qt.ItemFlags(QAbstractTableModel.flags(self, index)| Qt.ItemIsEditable) def reset(self): self.beginResetModel() self.endResetModel() class CollectionsModel(ReadOnlyCollectionsModel): """Collections Table Model""" def set_value(self, index, value): """Set value""" self._data[ self.keys[index.row()] ] = value self.showndata[ self.keys[index.row()] ] = value self.sizes[index.row()] = get_size(value) self.types[index.row()] = get_human_readable_type(value) def get_bgcolor(self, index): """Background color depending on value""" value = self.get_value(index) if index.column() < 3: color = ReadOnlyCollectionsModel.get_bgcolor(self, index) else: if self.remote: color_name = value['color'] else: color_name = get_color_name(value) color = QColor(color_name) color.setAlphaF(.2) return color def setData(self, index, value, role=Qt.EditRole): """Cell content change""" if not index.isValid(): return False if index.column() < 3: return False value = display_to_value(value, self.get_value(index), ignore_errors=True) self.set_value(index, value) self.dataChanged.emit(index, index) return True class CollectionsDelegate(QItemDelegate): """CollectionsEditor Item Delegate""" def __init__(self, parent=None): QItemDelegate.__init__(self, parent) self._editors = {} # keep references on opened editors def get_value(self, index): if index.isValid(): return index.model().get_value(index) def set_value(self, index, value): if index.isValid(): index.model().set_value(index, value) def show_warning(self, index): """ Decide if showing a warning when the user is trying to view a big variable associated to a Tablemodel index This avoids getting the variables' value to know its size and type, using instead those already computed by the TableModel. The problem is when a variable is too big, it can take a lot of time just to get its value """ try: val_size = index.model().sizes[index.row()] val_type = index.model().types[index.row()] except: return False if val_type in ['list', 'tuple', 'dict'] and int(val_size) > 1e5: return True else: return False def createEditor(self, parent, option, index): """Overriding method createEditor""" if index.column() < 3: return None if self.show_warning(index): answer = QMessageBox.warning(self.parent(), _("Warning"), _("Opening this variable can be slow\n\n" "Do you want to continue anyway?"), QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.No: return None try: value = self.get_value(index) if value is None: return None except Exception as msg: QMessageBox.critical(self.parent(), _("Error"), _("Spyder was unable to retrieve the value of " "this variable from the console.

    " "The error mesage was:
    " "%s" ) % to_text_string(msg)) return key = index.model().get_key(index) readonly = isinstance(value, tuple) or self.parent().readonly \ or not is_known_type(value) #---editor = CollectionsEditor if isinstance(value, (list, tuple, dict)): editor = CollectionsEditor() editor.setup(value, key, icon=self.parent().windowIcon(), readonly=readonly) self.create_dialog(editor, dict(model=index.model(), editor=editor, key=key, readonly=readonly)) return None #---editor = ArrayEditor elif isinstance(value, (ndarray, MaskedArray)) \ and ndarray is not FakeObject: editor = ArrayEditor(parent) if not editor.setup_and_check(value, title=key, readonly=readonly): return self.create_dialog(editor, dict(model=index.model(), editor=editor, key=key, readonly=readonly)) return None #---showing image elif isinstance(value, Image) and ndarray is not FakeObject \ and Image is not FakeObject: arr = array(value) editor = ArrayEditor(parent) if not editor.setup_and_check(arr, title=key, readonly=readonly): return conv_func = lambda arr: Image.fromarray(arr, mode=value.mode) self.create_dialog(editor, dict(model=index.model(), editor=editor, key=key, readonly=readonly, conv=conv_func)) return None #--editor = DataFrameEditor elif isinstance(value, (DataFrame, DatetimeIndex, Series)) \ and DataFrame is not FakeObject: editor = DataFrameEditor() if not editor.setup_and_check(value, title=key): return editor.dataModel.set_format(index.model().dataframe_format) editor.sig_option_changed.connect(self.change_option) self.create_dialog(editor, dict(model=index.model(), editor=editor, key=key, readonly=readonly)) return None #---editor = QDateEdit or QDateTimeEdit elif isinstance(value, datetime.date): if readonly: return None else: if isinstance(value, datetime.datetime): editor = QDateTimeEdit(value, parent) else: editor = QDateEdit(value, parent) editor.setCalendarPopup(True) editor.setFont(get_font(font_size_delta=DEFAULT_SMALL_DELTA)) return editor #---editor = TextEditor elif is_text_string(value) and len(value) > 40: te = TextEditor(None) if te.setup_and_check(value): editor = TextEditor(value, key, readonly=readonly) self.create_dialog(editor, dict(model=index.model(), editor=editor, key=key, readonly=readonly)) return None #---editor = QLineEdit elif is_editable_type(value): if readonly: return None else: editor = QLineEdit(parent) editor.setFont(get_font(font_size_delta=DEFAULT_SMALL_DELTA)) editor.setAlignment(Qt.AlignLeft) # This is making Spyder crash because the QLineEdit that it's # been modified is removed and a new one is created after # evaluation. So the object on which this method is trying to # act doesn't exist anymore. # editor.returnPressed.connect(self.commitAndCloseEditor) return editor #---editor = CollectionsEditor for an arbitrary object else: editor = CollectionsEditor() editor.setup(value, key, icon=self.parent().windowIcon(), readonly=readonly) self.create_dialog(editor, dict(model=index.model(), editor=editor, key=key, readonly=readonly)) return None def create_dialog(self, editor, data): self._editors[id(editor)] = data editor.accepted.connect( lambda eid=id(editor): self.editor_accepted(eid)) editor.rejected.connect( lambda eid=id(editor): self.editor_rejected(eid)) editor.show() @Slot(str, object) def change_option(self, option_name, new_value): """ Change configuration option. This function is called when a `sig_option_changed` signal is received. At the moment, this signal can only come from a DataFrameEditor. """ if option_name == 'dataframe_format': self.parent().set_dataframe_format(new_value) def editor_accepted(self, editor_id): data = self._editors[editor_id] if not data['readonly']: index = data['model'].get_index_from_key(data['key']) value = data['editor'].get_value() conv_func = data.get('conv', lambda v: v) self.set_value(index, conv_func(value)) self._editors.pop(editor_id) self.free_memory() def editor_rejected(self, editor_id): self._editors.pop(editor_id) self.free_memory() def free_memory(self): """Free memory after closing an editor.""" gc.collect() def commitAndCloseEditor(self): """Overriding method commitAndCloseEditor""" editor = self.sender() # Avoid a segfault with PyQt5. Variable value won't be changed # but at least Spyder won't crash. It seems generated by a # bug in sip. See # http://comments.gmane.org/gmane.comp.python.pyqt-pykde/26544 try: self.commitData.emit(editor) except AttributeError: pass self.closeEditor.emit(editor, QAbstractItemDelegate.NoHint) def setEditorData(self, editor, index): """ Overriding method setEditorData Model --> Editor """ value = self.get_value(index) if isinstance(editor, QLineEdit): if is_binary_string(value): try: value = to_text_string(value, 'utf8') except: pass if not is_text_string(value): value = repr(value) editor.setText(value) elif isinstance(editor, QDateEdit): editor.setDate(value) elif isinstance(editor, QDateTimeEdit): editor.setDateTime(QDateTime(value.date(), value.time())) def setModelData(self, editor, model, index): """ Overriding method setModelData Editor --> Model """ if not hasattr(model, "set_value"): # Read-only mode return if isinstance(editor, QLineEdit): value = editor.text() try: value = display_to_value(to_qvariant(value), self.get_value(index), ignore_errors=False) except Exception as msg: raise QMessageBox.critical(editor, _("Edit item"), _("Unable to assign data to item." "

    Error message:
    %s" ) % str(msg)) return elif isinstance(editor, QDateEdit): qdate = editor.date() value = datetime.date( qdate.year(), qdate.month(), qdate.day() ) elif isinstance(editor, QDateTimeEdit): qdatetime = editor.dateTime() qdate = qdatetime.date() qtime = qdatetime.time() value = datetime.datetime( qdate.year(), qdate.month(), qdate.day(), qtime.hour(), qtime.minute(), qtime.second() ) else: # Should not happen... raise RuntimeError("Unsupported editor widget") self.set_value(index, value) class BaseTableView(QTableView): """Base collection editor table view""" sig_option_changed = Signal(str, object) sig_files_dropped = Signal(list) redirect_stdio = Signal(bool) def __init__(self, parent): QTableView.__init__(self, parent) self.array_filename = None self.menu = None self.empty_ws_menu = None self.paste_action = None self.copy_action = None self.edit_action = None self.plot_action = None self.hist_action = None self.imshow_action = None self.save_array_action = None self.insert_action = None self.remove_action = None self.minmax_action = None self.rename_action = None self.duplicate_action = None self.delegate = None self.setAcceptDrops(True) def setup_table(self): """Setup table""" self.horizontalHeader().setStretchLastSection(True) self.adjust_columns() # Sorting columns self.setSortingEnabled(True) self.sortByColumn(0, Qt.AscendingOrder) def setup_menu(self, minmax): """Setup context menu""" if self.minmax_action is not None: self.minmax_action.setChecked(minmax) return resize_action = create_action(self, _("Resize rows to contents"), triggered=self.resizeRowsToContents) self.paste_action = create_action(self, _("Paste"), icon=ima.icon('editpaste'), triggered=self.paste) self.copy_action = create_action(self, _("Copy"), icon=ima.icon('editcopy'), triggered=self.copy) self.edit_action = create_action(self, _("Edit"), icon=ima.icon('edit'), triggered=self.edit_item) self.plot_action = create_action(self, _("Plot"), icon=ima.icon('plot'), triggered=lambda: self.plot_item('plot')) self.plot_action.setVisible(False) self.hist_action = create_action(self, _("Histogram"), icon=ima.icon('hist'), triggered=lambda: self.plot_item('hist')) self.hist_action.setVisible(False) self.imshow_action = create_action(self, _("Show image"), icon=ima.icon('imshow'), triggered=self.imshow_item) self.imshow_action.setVisible(False) self.save_array_action = create_action(self, _("Save array"), icon=ima.icon('filesave'), triggered=self.save_array) self.save_array_action.setVisible(False) self.insert_action = create_action(self, _("Insert"), icon=ima.icon('insert'), triggered=self.insert_item) self.remove_action = create_action(self, _("Remove"), icon=ima.icon('editdelete'), triggered=self.remove_item) self.minmax_action = create_action(self, _("Show arrays min/max"), toggled=self.toggle_minmax) self.minmax_action.setChecked(minmax) self.toggle_minmax(minmax) self.rename_action = create_action(self, _("Rename"), icon=ima.icon('rename'), triggered=self.rename_item) self.duplicate_action = create_action(self, _("Duplicate"), icon=ima.icon('edit_add'), triggered=self.duplicate_item) menu = QMenu(self) menu_actions = [self.edit_action, self.plot_action, self.hist_action, self.imshow_action, self.save_array_action, self.insert_action, self.remove_action, self.copy_action, self.paste_action, None, self.rename_action, self.duplicate_action, None, resize_action] if ndarray is not FakeObject: menu_actions.append(self.minmax_action) add_actions(menu, menu_actions) self.empty_ws_menu = QMenu(self) add_actions(self.empty_ws_menu, [self.insert_action, self.paste_action, None, resize_action]) return menu #------ Remote/local API --------------------------------------------------- def remove_values(self, keys): """Remove values from data""" raise NotImplementedError def copy_value(self, orig_key, new_key): """Copy value""" raise NotImplementedError def new_value(self, key, value): """Create new value in data""" raise NotImplementedError def is_list(self, key): """Return True if variable is a list or a tuple""" raise NotImplementedError def get_len(self, key): """Return sequence length""" raise NotImplementedError def is_array(self, key): """Return True if variable is a numpy array""" raise NotImplementedError def is_image(self, key): """Return True if variable is a PIL.Image image""" raise NotImplementedError def is_dict(self, key): """Return True if variable is a dictionary""" raise NotImplementedError def get_array_shape(self, key): """Return array's shape""" raise NotImplementedError def get_array_ndim(self, key): """Return array's ndim""" raise NotImplementedError def oedit(self, key): """Edit item""" raise NotImplementedError def plot(self, key, funcname): """Plot item""" raise NotImplementedError def imshow(self, key): """Show item's image""" raise NotImplementedError def show_image(self, key): """Show image (item is a PIL image)""" raise NotImplementedError #--------------------------------------------------------------------------- def refresh_menu(self): """Refresh context menu""" index = self.currentIndex() condition = index.isValid() self.edit_action.setEnabled( condition ) self.remove_action.setEnabled( condition ) self.refresh_plot_entries(index) def refresh_plot_entries(self, index): if index.isValid(): key = self.model.get_key(index) is_list = self.is_list(key) is_array = self.is_array(key) and self.get_len(key) != 0 condition_plot = (is_array and len(self.get_array_shape(key)) <= 2) condition_hist = (is_array and self.get_array_ndim(key) == 1) condition_imshow = condition_plot and self.get_array_ndim(key) == 2 condition_imshow = condition_imshow or self.is_image(key) else: is_array = condition_plot = condition_imshow = is_list \ = condition_hist = False self.plot_action.setVisible(condition_plot or is_list) self.hist_action.setVisible(condition_hist or is_list) self.imshow_action.setVisible(condition_imshow) self.save_array_action.setVisible(is_array) def adjust_columns(self): """Resize two first columns to contents""" for col in range(3): self.resizeColumnToContents(col) def set_data(self, data): """Set table data""" if data is not None: self.model.set_data(data, self.dictfilter) self.sortByColumn(0, Qt.AscendingOrder) def mousePressEvent(self, event): """Reimplement Qt method""" if event.button() != Qt.LeftButton: QTableView.mousePressEvent(self, event) return index_clicked = self.indexAt(event.pos()) if index_clicked.isValid(): if index_clicked == self.currentIndex() \ and index_clicked in self.selectedIndexes(): self.clearSelection() else: QTableView.mousePressEvent(self, event) else: self.clearSelection() event.accept() def mouseDoubleClickEvent(self, event): """Reimplement Qt method""" index_clicked = self.indexAt(event.pos()) if index_clicked.isValid(): row = index_clicked.row() # TODO: Remove hard coded "Value" column number (3 here) index_clicked = index_clicked.child(row, 3) self.edit(index_clicked) else: event.accept() def keyPressEvent(self, event): """Reimplement Qt methods""" if event.key() == Qt.Key_Delete: self.remove_item() elif event.key() == Qt.Key_F2: self.rename_item() elif event == QKeySequence.Copy: self.copy() elif event == QKeySequence.Paste: self.paste() else: QTableView.keyPressEvent(self, event) def contextMenuEvent(self, event): """Reimplement Qt method""" if self.model.showndata: self.refresh_menu() self.menu.popup(event.globalPos()) event.accept() else: self.empty_ws_menu.popup(event.globalPos()) event.accept() def dragEnterEvent(self, event): """Allow user to drag files""" if mimedata2url(event.mimeData()): event.accept() else: event.ignore() def dragMoveEvent(self, event): """Allow user to move files""" if mimedata2url(event.mimeData()): event.setDropAction(Qt.CopyAction) event.accept() else: event.ignore() def dropEvent(self, event): """Allow user to drop supported files""" urls = mimedata2url(event.mimeData()) if urls: event.setDropAction(Qt.CopyAction) event.accept() self.sig_files_dropped.emit(urls) else: event.ignore() @Slot(bool) def toggle_minmax(self, state): """Toggle min/max display for numpy arrays""" self.sig_option_changed.emit('minmax', state) self.model.minmax = state @Slot(str) def set_dataframe_format(self, new_format): """ Set format to use in DataframeEditor. Args: new_format (string): e.g. "%.3f" """ self.sig_option_changed.emit('dataframe_format', new_format) self.model.dataframe_format = new_format @Slot() def edit_item(self): """Edit item""" index = self.currentIndex() if not index.isValid(): return # TODO: Remove hard coded "Value" column number (3 here) self.edit(index.child(index.row(), 3)) @Slot() def remove_item(self): """Remove item""" indexes = self.selectedIndexes() if not indexes: return for index in indexes: if not index.isValid(): return one = _("Do you want to remove the selected item?") more = _("Do you want to remove all selected items?") answer = QMessageBox.question(self, _( "Remove"), one if len(indexes) == 1 else more, QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: idx_rows = unsorted_unique([idx.row() for idx in indexes]) keys = [ self.model.keys[idx_row] for idx_row in idx_rows ] self.remove_values(keys) def copy_item(self, erase_original=False): """Copy item""" indexes = self.selectedIndexes() if not indexes: return idx_rows = unsorted_unique([idx.row() for idx in indexes]) if len(idx_rows) > 1 or not indexes[0].isValid(): return orig_key = self.model.keys[idx_rows[0]] if erase_original: title = _('Rename') field_text = _('New variable name:') else: title = _('Duplicate') field_text = _('Variable name:') data = self.model.get_data() if isinstance(data, (list, set)): new_key, valid = len(data), True else: new_key, valid = QInputDialog.getText(self, title, field_text, QLineEdit.Normal, orig_key) if valid and to_text_string(new_key): new_key = try_to_eval(to_text_string(new_key)) if new_key == orig_key: return self.copy_value(orig_key, new_key) if erase_original: self.remove_values([orig_key]) @Slot() def duplicate_item(self): """Duplicate item""" self.copy_item() @Slot() def rename_item(self): """Rename item""" self.copy_item(True) @Slot() def insert_item(self): """Insert item""" index = self.currentIndex() if not index.isValid(): row = self.model.rowCount() else: row = index.row() data = self.model.get_data() if isinstance(data, list): key = row data.insert(row, '') elif isinstance(data, dict): key, valid = QInputDialog.getText(self, _( 'Insert'), _( 'Key:'), QLineEdit.Normal) if valid and to_text_string(key): key = try_to_eval(to_text_string(key)) else: return else: return value, valid = QInputDialog.getText(self, _('Insert'), _('Value:'), QLineEdit.Normal) if valid and to_text_string(value): self.new_value(key, try_to_eval(to_text_string(value))) def __prepare_plot(self): try: import guiqwt.pyplot #analysis:ignore return True except: try: if 'matplotlib' not in sys.modules: import matplotlib matplotlib.use("Qt4Agg") return True except: QMessageBox.warning(self, _("Import error"), _("Please install matplotlib" " or guiqwt.")) def plot_item(self, funcname): """Plot item""" index = self.currentIndex() if self.__prepare_plot(): key = self.model.get_key(index) try: self.plot(key, funcname) except (ValueError, TypeError) as error: QMessageBox.critical(self, _( "Plot"), _("Unable to plot data." "

    Error message:
    %s" ) % str(error)) @Slot() def imshow_item(self): """Imshow item""" index = self.currentIndex() if self.__prepare_plot(): key = self.model.get_key(index) try: if self.is_image(key): self.show_image(key) else: self.imshow(key) except (ValueError, TypeError) as error: QMessageBox.critical(self, _( "Plot"), _("Unable to show image." "

    Error message:
    %s" ) % str(error)) @Slot() def save_array(self): """Save array""" title = _( "Save array") if self.array_filename is None: self.array_filename = getcwd_or_home() self.redirect_stdio.emit(False) filename, _selfilter = getsavefilename(self, title, self.array_filename, _("NumPy arrays")+" (*.npy)") self.redirect_stdio.emit(True) if filename: self.array_filename = filename data = self.delegate.get_value( self.currentIndex() ) try: import numpy as np np.save(self.array_filename, data) except Exception as error: QMessageBox.critical(self, title, _("Unable to save array" "

    Error message:
    %s" ) % str(error)) @Slot() def copy(self): """Copy text to clipboard""" clipboard = QApplication.clipboard() clipl = [] for idx in self.selectedIndexes(): if not idx.isValid(): continue obj = self.delegate.get_value(idx) # Check if we are trying to copy a numpy array, and if so make sure # to copy the whole thing in a tab separated format if isinstance(obj, (ndarray, MaskedArray)) \ and ndarray is not FakeObject: if PY3: output = io.BytesIO() else: output = io.StringIO() try: np_savetxt(output, obj, delimiter='\t') except: QMessageBox.warning(self, _("Warning"), _("It was not possible to copy " "this array")) return obj = output.getvalue().decode('utf-8') output.close() elif isinstance(obj, (DataFrame, Series)) \ and DataFrame is not FakeObject: output = io.StringIO() obj.to_csv(output, sep='\t', index=True, header=True) if PY3: obj = output.getvalue() else: obj = output.getvalue().decode('utf-8') output.close() elif is_binary_string(obj): obj = to_text_string(obj, 'utf8') else: obj = to_text_string(obj) clipl.append(obj) clipboard.setText('\n'.join(clipl)) def import_from_string(self, text, title=None): """Import data from string""" data = self.model.get_data() editor = ImportWizard(self, text, title=title, contents_title=_("Clipboard contents"), varname=fix_reference_name("data", blacklist=list(data.keys()))) if editor.exec_(): var_name, clip_data = editor.get_data() self.new_value(var_name, clip_data) @Slot() def paste(self): """Import text/data/code from clipboard""" clipboard = QApplication.clipboard() cliptext = '' if clipboard.mimeData().hasText(): cliptext = to_text_string(clipboard.text()) if cliptext.strip(): self.import_from_string(cliptext, title=_("Import from clipboard")) else: QMessageBox.warning(self, _( "Empty clipboard"), _("Nothing to be imported from clipboard.")) class CollectionsEditorTableView(BaseTableView): """CollectionsEditor table view""" def __init__(self, parent, data, readonly=False, title="", names=False, minmax=False): BaseTableView.__init__(self, parent) self.dictfilter = None self.readonly = readonly or isinstance(data, tuple) CollectionsModelClass = ReadOnlyCollectionsModel if self.readonly \ else CollectionsModel self.model = CollectionsModelClass(self, data, title, names=names, minmax=minmax) self.setModel(self.model) self.delegate = CollectionsDelegate(self) self.setItemDelegate(self.delegate) self.setup_table() self.menu = self.setup_menu(minmax) #------ Remote/local API --------------------------------------------------- def remove_values(self, keys): """Remove values from data""" data = self.model.get_data() for key in sorted(keys, reverse=True): data.pop(key) self.set_data(data) def copy_value(self, orig_key, new_key): """Copy value""" data = self.model.get_data() if isinstance(data, list): data.append(data[orig_key]) if isinstance(data, set): data.add(data[orig_key]) else: data[new_key] = data[orig_key] self.set_data(data) def new_value(self, key, value): """Create new value in data""" data = self.model.get_data() data[key] = value self.set_data(data) def is_list(self, key): """Return True if variable is a list or a tuple""" data = self.model.get_data() return isinstance(data[key], (tuple, list)) def get_len(self, key): """Return sequence length""" data = self.model.get_data() return len(data[key]) def is_array(self, key): """Return True if variable is a numpy array""" data = self.model.get_data() return isinstance(data[key], (ndarray, MaskedArray)) def is_image(self, key): """Return True if variable is a PIL.Image image""" data = self.model.get_data() return isinstance(data[key], Image) def is_dict(self, key): """Return True if variable is a dictionary""" data = self.model.get_data() return isinstance(data[key], dict) def get_array_shape(self, key): """Return array's shape""" data = self.model.get_data() return data[key].shape def get_array_ndim(self, key): """Return array's ndim""" data = self.model.get_data() return data[key].ndim def oedit(self, key): """Edit item""" data = self.model.get_data() from spyder.widgets.variableexplorer.objecteditor import oedit oedit(data[key]) def plot(self, key, funcname): """Plot item""" data = self.model.get_data() import spyder.pyplot as plt plt.figure() getattr(plt, funcname)(data[key]) plt.show() def imshow(self, key): """Show item's image""" data = self.model.get_data() import spyder.pyplot as plt plt.figure() plt.imshow(data[key]) plt.show() def show_image(self, key): """Show image (item is a PIL image)""" data = self.model.get_data() data[key].show() #--------------------------------------------------------------------------- def refresh_menu(self): """Refresh context menu""" data = self.model.get_data() index = self.currentIndex() condition = (not isinstance(data, tuple)) and index.isValid() \ and not self.readonly self.edit_action.setEnabled( condition ) self.remove_action.setEnabled( condition ) self.insert_action.setEnabled( not self.readonly ) self.duplicate_action.setEnabled(condition) condition_rename = not isinstance(data, (tuple, list, set)) self.rename_action.setEnabled(condition_rename) self.refresh_plot_entries(index) def set_filter(self, dictfilter=None): """Set table dict filter""" self.dictfilter = dictfilter class CollectionsEditorWidget(QWidget): """Dictionary Editor Widget""" def __init__(self, parent, data, readonly=False, title="", remote=False): QWidget.__init__(self, parent) if remote: self.editor = RemoteCollectionsEditorTableView(self, data, readonly) else: self.editor = CollectionsEditorTableView(self, data, readonly, title) layout = QVBoxLayout() layout.addWidget(self.editor) self.setLayout(layout) def set_data(self, data): """Set DictEditor data""" self.editor.set_data(data) def get_title(self): """Get model title""" return self.editor.model.title class CollectionsEditor(QDialog): """Collections Editor Dialog""" def __init__(self, parent=None): QDialog.__init__(self, parent) # Destroying the C++ object right after closing the dialog box, # otherwise it may be garbage-collected in another QThread # (e.g. the editor's analysis thread in Spyder), thus leading to # a segmentation fault on UNIX or an application crash on Windows self.setAttribute(Qt.WA_DeleteOnClose) self.data_copy = None self.widget = None def setup(self, data, title='', readonly=False, width=650, remote=False, icon=None, parent=None): """Setup editor.""" if isinstance(data, dict): # dictionnary self.data_copy = data.copy() datalen = len(data) elif isinstance(data, (tuple, list)): # list, tuple self.data_copy = data[:] datalen = len(data) else: # unknown object import copy try: self.data_copy = copy.deepcopy(data) except NotImplementedError: self.data_copy = copy.copy(data) except (TypeError, AttributeError): readonly = True self.data_copy = data datalen = len(get_object_attrs(data)) self.widget = CollectionsEditorWidget(self, self.data_copy, title=title, readonly=readonly, remote=remote) layout = QVBoxLayout() layout.addWidget(self.widget) self.setLayout(layout) # Buttons configuration buttons = QDialogButtonBox.Ok if not readonly: buttons = buttons | QDialogButtonBox.Cancel self.bbox = QDialogButtonBox(buttons) self.bbox.accepted.connect(self.accept) if not readonly: self.bbox.rejected.connect(self.reject) layout.addWidget(self.bbox) constant = 121 row_height = 30 error_margin = 10 height = constant + row_height * min([10, datalen]) + error_margin self.resize(width, height) self.setWindowTitle(self.widget.get_title()) if icon is None: self.setWindowIcon(ima.icon('dictedit')) # Make the dialog act as a window self.setWindowFlags(Qt.Window) def get_value(self): """Return modified copy of dictionary or list""" # It is import to avoid accessing Qt C++ object as it has probably # already been destroyed, due to the Qt.WA_DeleteOnClose attribute return self.data_copy class DictEditor(CollectionsEditor): def __init__(self, parent=None): warnings.warn("`DictEditor` has been renamed to `CollectionsEditor` in " "Spyder 3. Please use `CollectionsEditor` instead", RuntimeWarning) CollectionsEditor.__init__(self, parent) #----Remote versions of CollectionsDelegate and CollectionsEditorTableView class RemoteCollectionsDelegate(CollectionsDelegate): """CollectionsEditor Item Delegate""" def __init__(self, parent=None, get_value_func=None, set_value_func=None): CollectionsDelegate.__init__(self, parent) self.get_value_func = get_value_func self.set_value_func = set_value_func def get_value(self, index): if index.isValid(): name = index.model().keys[index.row()] return self.get_value_func(name) def set_value(self, index, value): if index.isValid(): name = index.model().keys[index.row()] self.set_value_func(name, value) class RemoteCollectionsEditorTableView(BaseTableView): """DictEditor table view""" def __init__(self, parent, data, minmax=False, dataframe_format=None, get_value_func=None, set_value_func=None, new_value_func=None, remove_values_func=None, copy_value_func=None, is_list_func=None, get_len_func=None, is_array_func=None, is_image_func=None, is_dict_func=None, get_array_shape_func=None, get_array_ndim_func=None, plot_func=None, imshow_func=None, is_data_frame_func=None, is_series_func=None, show_image_func=None): BaseTableView.__init__(self, parent) self.remove_values = remove_values_func self.copy_value = copy_value_func self.new_value = new_value_func self.is_data_frame = is_data_frame_func self.is_series = is_series_func self.is_list = is_list_func self.get_len = get_len_func self.is_array = is_array_func self.is_image = is_image_func self.is_dict = is_dict_func self.get_array_shape = get_array_shape_func self.get_array_ndim = get_array_ndim_func self.plot = plot_func self.imshow = imshow_func self.show_image = show_image_func self.dictfilter = None self.model = None self.delegate = None self.readonly = False self.model = CollectionsModel(self, data, names=True, minmax=minmax, dataframe_format=dataframe_format, remote=True) self.setModel(self.model) self.delegate = RemoteCollectionsDelegate(self, get_value_func, set_value_func) self.setItemDelegate(self.delegate) self.setup_table() self.menu = self.setup_menu(minmax) def setup_menu(self, minmax): """Setup context menu""" menu = BaseTableView.setup_menu(self, minmax) return menu # ============================================================================= # Tests # ============================================================================= def get_test_data(): """Create test data.""" import numpy as np from spyder.pil_patch import Image image = Image.fromarray(np.random.random_integers(255, size=(100, 100)), mode='P') testdict = {'d': 1, 'a': np.random.rand(10, 10), 'b': [1, 2]} testdate = datetime.date(1945, 5, 8) class Foobar(object): def __init__(self): self.text = "toto" self.testdict = testdict self.testdate = testdate foobar = Foobar() return {'object': foobar, 'str': 'kjkj kj k j j kj k jkj', 'unicode': to_text_string('éù', 'utf-8'), 'list': [1, 3, [sorted, 5, 6], 'kjkj', None], 'tuple': ([1, testdate, testdict], 'kjkj', None), 'dict': testdict, 'float': 1.2233, 'int': 223, 'bool': True, 'array': np.random.rand(10, 10), 'masked_array': np.ma.array([[1, 0], [1, 0]], mask=[[True, False], [False, False]]), '1D-array': np.linspace(-10, 10), 'empty_array': np.array([]), 'image': image, 'date': testdate, 'datetime': datetime.datetime(1945, 5, 8), 'complex': 2+1j, 'complex64': np.complex64(2+1j), 'int8_scalar': np.int8(8), 'int16_scalar': np.int16(16), 'int32_scalar': np.int32(32), 'bool_scalar': np.bool(8), 'unsupported1': np.arccos, 'unsupported2': np.cast, # Test for Issue #3518 'big_struct_array': np.zeros(1000, dtype=[('ID', 'f8'), ('param1', 'f8', 5000)]), } def editor_test(): """Collections editor test""" from spyder.utils.qthelpers import qapplication app = qapplication() #analysis:ignore dialog = CollectionsEditor() dialog.setup(get_test_data()) dialog.show() app.exec_() def remote_editor_test(): """Remote collections editor test""" from spyder.utils.qthelpers import qapplication app = qapplication() from spyder.plugins.variableexplorer import VariableExplorer from spyder.widgets.variableexplorer.utils import make_remote_view remote = make_remote_view(get_test_data(), VariableExplorer(None).get_settings()) dialog = CollectionsEditor() dialog.setup(remote, remote=True) dialog.show() app.exec_() if __name__ == "__main__": editor_test() remote_editor_test() spyder-3.2.6/spyder/widgets/variableexplorer/objecteditor.py0000664000175000017500000001374413224740762025213 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Generic object editor dialog """ # Standard library imports from __future__ import print_function # Third party imports from qtpy.QtCore import QObject # Local imports from spyder.py3compat import is_text_string class DialogKeeper(QObject): def __init__(self): QObject.__init__(self) self.dialogs = {} self.namespace = None def set_namespace(self, namespace): self.namespace = namespace def create_dialog(self, dialog, refname, func): self.dialogs[id(dialog)] = dialog, refname, func dialog.accepted.connect( lambda eid=id(dialog): self.editor_accepted(eid)) dialog.rejected.connect( lambda eid=id(dialog): self.editor_rejected(eid)) dialog.show() dialog.activateWindow() dialog.raise_() def editor_accepted(self, dialog_id): dialog, refname, func = self.dialogs[dialog_id] self.namespace[refname] = func(dialog) self.dialogs.pop(dialog_id) def editor_rejected(self, dialog_id): self.dialogs.pop(dialog_id) keeper = DialogKeeper() def create_dialog(obj, obj_name): """Creates the editor dialog and returns a tuple (dialog, func) where func is the function to be called with the dialog instance as argument, after quitting the dialog box The role of this intermediate function is to allow easy monkey-patching. (uschmitt suggested this indirection here so that he can monkey patch oedit to show eMZed related data) """ # Local import from spyder.widgets.variableexplorer.texteditor import TextEditor from spyder.widgets.variableexplorer.utils import (ndarray, FakeObject, Image, is_known_type, DataFrame, Series) from spyder.widgets.variableexplorer.collectionseditor import CollectionsEditor from spyder.widgets.variableexplorer.arrayeditor import ArrayEditor if DataFrame is not FakeObject: from spyder.widgets.variableexplorer.dataframeeditor import DataFrameEditor conv_func = lambda data: data readonly = not is_known_type(obj) if isinstance(obj, ndarray) and ndarray is not FakeObject: dialog = ArrayEditor() if not dialog.setup_and_check(obj, title=obj_name, readonly=readonly): return elif isinstance(obj, Image) and Image is not FakeObject \ and ndarray is not FakeObject: dialog = ArrayEditor() import numpy as np data = np.array(obj) if not dialog.setup_and_check(data, title=obj_name, readonly=readonly): return from spyder.pil_patch import Image conv_func = lambda data: Image.fromarray(data, mode=obj.mode) elif isinstance(obj, (DataFrame, Series)) and DataFrame is not FakeObject: dialog = DataFrameEditor() if not dialog.setup_and_check(obj): return elif is_text_string(obj): dialog = TextEditor(obj, title=obj_name, readonly=readonly) else: dialog = CollectionsEditor() dialog.setup(obj, title=obj_name, readonly=readonly) def end_func(dialog): return conv_func(dialog.get_value()) return dialog, end_func def oedit(obj, modal=True, namespace=None): """Edit the object 'obj' in a GUI-based editor and return the edited copy (if Cancel is pressed, return None) The object 'obj' is a container Supported container types: dict, list, tuple, str/unicode or numpy.array (instantiate a new QApplication if necessary, so it can be called directly from the interpreter) """ # Local import from spyder.utils.qthelpers import qapplication app = qapplication() if modal: obj_name = '' else: assert is_text_string(obj) obj_name = obj if namespace is None: namespace = globals() keeper.set_namespace(namespace) obj = namespace[obj_name] # keep QApplication reference alive in the Python interpreter: namespace['__qapp__'] = app result = create_dialog(obj, obj_name) if result is None: return dialog, end_func = result if modal: if dialog.exec_(): return end_func(dialog) else: keeper.create_dialog(dialog, obj_name, end_func) import os if os.name == 'nt': app.exec_() #============================================================================== # Tests #============================================================================== def test(): """Run object editor test""" import datetime, numpy as np from spyder.pil_patch import Image data = np.random.random_integers(255, size=(100, 100)).astype('uint8') image = Image.fromarray(data) example = {'str': 'kjkj kj k j j kj k jkj', 'list': [1, 3, 4, 'kjkj', None], 'dict': {'d': 1, 'a': np.random.rand(10, 10), 'b': [1, 2]}, 'float': 1.2233, 'array': np.random.rand(10, 10), 'image': image, 'date': datetime.date(1945, 5, 8), 'datetime': datetime.datetime(1945, 5, 8), } image = oedit(image) class Foobar(object): def __init__(self): self.text = "toto" foobar = Foobar() print(oedit(foobar)) # spyder: test-skip print(oedit(example)) # spyder: test-skip print(oedit(np.random.rand(10, 10))) # spyder: test-skip print(oedit(oedit.__doc__)) # spyder: test-skip print(example) # spyder: test-skip if __name__ == "__main__": test() spyder-3.2.6/spyder/widgets/variableexplorer/texteditor.py0000664000175000017500000000765113211142273024716 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Text editor dialog """ # Standard library imports from __future__ import print_function # Third party imports from qtpy.QtCore import Qt from qtpy.QtWidgets import QDialog, QDialogButtonBox, QTextEdit, QVBoxLayout # Local import from spyder.config.base import _ from spyder.config.gui import get_font from spyder.py3compat import (is_binary_string, to_binary_string, to_text_string) from spyder.utils import icon_manager as ima class TextEditor(QDialog): """Array Editor Dialog""" def __init__(self, text, title='', font=None, parent=None, readonly=False, size=(400, 300)): QDialog.__init__(self, parent) # Destroying the C++ object right after closing the dialog box, # otherwise it may be garbage-collected in another QThread # (e.g. the editor's analysis thread in Spyder), thus leading to # a segmentation fault on UNIX or an application crash on Windows self.setAttribute(Qt.WA_DeleteOnClose) self.text = None # Display text as unicode if it comes as bytes, so users see # its right representation if is_binary_string(text): self.is_binary = True text = to_text_string(text, 'utf8') else: self.is_binary = False self.layout = QVBoxLayout() self.setLayout(self.layout) # Text edit self.edit = QTextEdit(parent) self.edit.textChanged.connect(self.text_changed) self.edit.setReadOnly(readonly) self.edit.setPlainText(text) if font is None: font = get_font() self.edit.setFont(font) self.layout.addWidget(self.edit) # Buttons configuration buttons = QDialogButtonBox.Ok if not readonly: buttons = buttons | QDialogButtonBox.Cancel bbox = QDialogButtonBox(buttons) bbox.accepted.connect(self.accept) bbox.rejected.connect(self.reject) self.layout.addWidget(bbox) # Make the dialog act as a window self.setWindowFlags(Qt.Window) self.setWindowIcon(ima.icon('edit')) self.setWindowTitle(_("Text editor") + \ "%s" % (" - "+str(title) if str(title) else "")) self.resize(size[0], size[1]) def text_changed(self): """Text has changed""" # Save text as bytes, if it was initially bytes if self.is_binary: self.text = to_binary_string(self.edit.toPlainText(), 'utf8') else: self.text = to_text_string(self.edit.toPlainText()) def get_value(self): """Return modified text""" # It is import to avoid accessing Qt C++ object as it has probably # already been destroyed, due to the Qt.WA_DeleteOnClose attribute return self.text def setup_and_check(self, value): """Verify if TextEditor is able to display strings passed to it.""" try: to_text_string(value, 'utf8') return True except: return False #============================================================================== # Tests #============================================================================== def test(): """Text editor demo""" from spyder.utils.qthelpers import qapplication _app = qapplication() # analysis:ignore text = """01234567890123456789012345678901234567890123456789012345678901234567890123456789 dedekdh elkd ezd ekjd lekdj elkdfjelfjk e""" dialog = TextEditor(text) dialog.exec_() dlg_text = dialog.get_value() assert text == dlg_text if __name__ == "__main__": test() spyder-3.2.6/spyder/widgets/variableexplorer/utils.py0000664000175000017500000005652413224740762023701 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Utilities """ from __future__ import print_function from itertools import islice import re # Local imports from spyder.config.base import get_supported_types from spyder.py3compat import (NUMERIC_TYPES, TEXT_TYPES, to_text_string, is_text_string, is_type_text_string, is_binary_string, PY2, to_binary_string, iteritems) from spyder.utils import programs from spyder import dependencies from spyder.config.base import _ #============================================================================== # Dependencies #============================================================================== PANDAS_REQVER = '>=0.13.1' dependencies.add('pandas', _("View and edit DataFrames and Series in the " "Variable Explorer"), required_version=PANDAS_REQVER, optional=True) NUMPY_REQVER = '>=1.7' dependencies.add("numpy", _("View and edit two and three dimensional arrays " "in the Variable Explorer"), required_version=NUMPY_REQVER, optional=True) #============================================================================== # FakeObject #============================================================================== class FakeObject(object): """Fake class used in replacement of missing modules""" pass #============================================================================== # Numpy arrays and numeric types support #============================================================================== try: from numpy import (ndarray, array, matrix, recarray, int64, int32, float64, float32, complex64, complex128) from numpy.ma import MaskedArray from numpy import savetxt as np_savetxt from numpy import get_printoptions, set_printoptions except: ndarray = array = matrix = recarray = MaskedArray = np_savetxt = \ int64 = int32 = float64 = float32 = complex64 = complex128 = FakeObject def get_numpy_dtype(obj): """Return NumPy data type associated to obj Return None if NumPy is not available or if obj is not a NumPy array or scalar""" if ndarray is not FakeObject: # NumPy is available import numpy as np if isinstance(obj, np.generic) or isinstance(obj, np.ndarray): # Numpy scalars all inherit from np.generic. # Numpy arrays all inherit from np.ndarray. # If we check that we are certain we have one of these # types then we are less likely to generate an exception below. try: return obj.dtype.type except (AttributeError, RuntimeError): # AttributeError: some NumPy objects have no dtype attribute # RuntimeError: happens with NetCDF objects (Issue 998) return #============================================================================== # Pandas support #============================================================================== if programs.is_module_installed('pandas', PANDAS_REQVER): try: from pandas import DataFrame, DatetimeIndex, Series except: DataFrame = DatetimeIndex = Series = FakeObject else: DataFrame = DatetimeIndex = Series = FakeObject # analysis:ignore #============================================================================== # PIL Images support #============================================================================== try: from spyder import pil_patch Image = pil_patch.Image.Image except: Image = FakeObject # analysis:ignore #============================================================================== # BeautifulSoup support (see Issue 2448) #============================================================================== try: import bs4 NavigableString = bs4.element.NavigableString except: NavigableString = FakeObject # analysis:ignore #============================================================================== # Misc. #============================================================================== def address(obj): """Return object address as a string: ''""" return "<%s @ %s>" % (obj.__class__.__name__, hex(id(obj)).upper().replace('X', 'x')) def try_to_eval(value): """Try to eval value""" try: return eval(value) except (NameError, SyntaxError, ImportError): return value def get_size(item): """Return size of an item of arbitrary type""" if isinstance(item, (list, tuple, dict)): return len(item) elif isinstance(item, (ndarray, MaskedArray)): return item.shape elif isinstance(item, Image): return item.size if isinstance(item, (DataFrame, DatetimeIndex, Series)): return item.shape else: return 1 def get_object_attrs(obj): """ Get the attributes of an object using dir. This filters protected attributes """ attrs = [k for k in dir(obj) if not k.startswith('__')] if not attrs: attrs = dir(obj) return attrs #============================================================================== # Date and datetime objects support #============================================================================== import datetime try: from dateutil.parser import parse as dateparse except: def dateparse(datestr): # analysis:ignore """Just for 'year, month, day' strings""" return datetime.datetime( *list(map(int, datestr.split(','))) ) def datestr_to_datetime(value): rp = value.rfind('(')+1 v = dateparse(value[rp:-1]) print(value, "-->", v) # spyder: test-skip return v def str_to_timedelta(value): """Convert a string to a datetime.timedelta value. The following strings are accepted: - 'datetime.timedelta(1, 5, 12345)' - 'timedelta(1, 5, 12345)' - '(1, 5, 12345)' - '1, 5, 12345' - '1' if there are less then three parameters, the missing parameters are assumed to be 0. Variations in the spacing of the parameters are allowed. Raises: ValueError for strings not matching the above criterion. """ m = re.match('^(?:(?:datetime\.)?timedelta)?' '\(?' '([^)]*)' '\)?$', value) if not m: raise ValueError('Invalid string for datetime.timedelta') args = [int(a.strip()) for a in m.group(1).split(',')] return datetime.timedelta(*args) #============================================================================== # Background colors for supported types #============================================================================== ARRAY_COLOR = "#00ff00" SCALAR_COLOR = "#0000ff" COLORS = { bool: "#ff00ff", NUMERIC_TYPES: SCALAR_COLOR, list: "#ffff00", dict: "#00ffff", tuple: "#c0c0c0", TEXT_TYPES: "#800000", (ndarray, MaskedArray, matrix, DataFrame, Series, DatetimeIndex): ARRAY_COLOR, Image: "#008000", datetime.date: "#808000", datetime.timedelta: "#808000", } CUSTOM_TYPE_COLOR = "#7755aa" UNSUPPORTED_COLOR = "#ffffff" def get_color_name(value): """Return color name depending on value type""" if not is_known_type(value): return CUSTOM_TYPE_COLOR for typ, name in list(COLORS.items()): if isinstance(value, typ): return name else: np_dtype = get_numpy_dtype(value) if np_dtype is None or not hasattr(value, 'size'): return UNSUPPORTED_COLOR elif value.size == 1: return SCALAR_COLOR else: return ARRAY_COLOR def is_editable_type(value): """Return True if data type is editable with a standard GUI-based editor, like CollectionsEditor, ArrayEditor, QDateEdit or a simple QLineEdit""" return get_color_name(value) not in (UNSUPPORTED_COLOR, CUSTOM_TYPE_COLOR) #============================================================================== # Sorting #============================================================================== def sort_against(list1, list2, reverse=False): """ Arrange items of list1 in the same order as sorted(list2). In other words, apply to list1 the permutation which takes list2 to sorted(list2, reverse). """ try: return [item for _, item in sorted(zip(list2, list1), key=lambda x: x[0], reverse=reverse)] except: return list1 def unsorted_unique(lista): """Removes duplicates from lista neglecting its initial ordering""" return list(set(lista)) #============================================================================== # Display <--> Value #============================================================================== def default_display(value, with_module=True): """Default display for unknown objects.""" object_type = type(value) try: name = object_type.__name__ module = object_type.__module__ if with_module: return name + ' object of ' + module + ' module' else: return name except: type_str = to_text_string(object_type) return type_str[1:-1] def collections_display(value, level): """Display for collections (i.e. list, tuple and dict).""" is_dict = isinstance(value, dict) # Get elements if is_dict: elements = iteritems(value) else: elements = value # Truncate values truncate = False if level == 1 and len(value) > 10: elements = islice(elements, 10) if is_dict else value[:10] truncate = True elif level == 2 and len(value) > 5: elements = islice(elements, 5) if is_dict else value[:5] truncate = True # Get display of each element if level <= 2: if is_dict: displays = [value_to_display(k, level=level) + ':' + value_to_display(v, level=level) for (k, v) in list(elements)] else: displays = [value_to_display(e, level=level) for e in elements] if truncate: displays.append('...') display = ', '.join(displays) else: display = '...' # Return display if is_dict: display = '{' + display + '}' elif isinstance(value, list): display = '[' + display + ']' else: display = '(' + display + ')' return display def value_to_display(value, minmax=False, level=0): """Convert value for display purpose""" # To save current Numpy threshold np_threshold = FakeObject try: numeric_numpy_types = (int64, int32, float64, float32, complex128, complex64) if ndarray is not FakeObject: # Save threshold np_threshold = get_printoptions().get('threshold') # Set max number of elements to show for Numpy arrays # in our display set_printoptions(threshold=10) if isinstance(value, recarray): if level == 0: fields = value.names display = 'Field names: ' + ', '.join(fields) else: display = 'Recarray' elif isinstance(value, MaskedArray): display = 'Masked array' elif isinstance(value, ndarray): if level == 0: if minmax: try: display = 'Min: %r\nMax: %r' % (value.min(), value.max()) except (TypeError, ValueError): if value.dtype.type in numeric_numpy_types: display = repr(value) else: display = default_display(value) elif value.dtype.type in numeric_numpy_types: display = repr(value) else: display = default_display(value) else: display = 'Numpy array' elif any([type(value) == t for t in [list, tuple, dict]]): display = collections_display(value, level+1) elif isinstance(value, Image): if level == 0: display = '%s Mode: %s' % (address(value), value.mode) else: display = 'Image' elif isinstance(value, DataFrame): if level == 0: 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] display = 'Column names: ' + ', '.join(list(cols)) else: display = 'Dataframe' elif isinstance(value, NavigableString): # Fixes Issue 2448 display = to_text_string(value) if level > 0: display = u"'" + display + u"'" elif isinstance(value, DatetimeIndex): if level == 0: display = value.summary() else: display = 'DatetimeIndex' elif is_binary_string(value): # We don't apply this to classes that extend string types # See issue 5636 if is_type_text_string(value): try: display = to_text_string(value, 'utf8') if level > 0: display = u"'" + display + u"'" except: display = value if level > 0: display = b"'" + display + b"'" else: display = default_display(value) elif is_text_string(value): # We don't apply this to classes that extend string types # See issue 5636 if is_type_text_string(value): display = value if level > 0: display = u"'" + display + u"'" else: display = default_display(value) elif (isinstance(value, datetime.date) or isinstance(value, datetime.timedelta)): display = str(value) elif (isinstance(value, NUMERIC_TYPES) or isinstance(value, bool) or isinstance(value, numeric_numpy_types)): display = repr(value) else: if level == 0: display = default_display(value) else: display = default_display(value, with_module=False) except: display = default_display(value) # Truncate display at 70 chars to avoid freezing Spyder # because of large displays if len(display) > 70: display = display[:70].rstrip() + ' ...' # Restore Numpy threshold if np_threshold is not FakeObject: set_printoptions(threshold=np_threshold) return display def display_to_value(value, default_value, ignore_errors=True): """Convert back to value""" from qtpy.compat import from_qvariant value = from_qvariant(value, to_text_string) try: np_dtype = get_numpy_dtype(default_value) if isinstance(default_value, bool): # We must test for boolean before NumPy data types # because `bool` class derives from `int` class try: value = bool(float(value)) except ValueError: value = value.lower() == "true" elif np_dtype is not None: if 'complex' in str(type(default_value)): value = np_dtype(complex(value)) else: value = np_dtype(value) elif is_binary_string(default_value): value = to_binary_string(value, 'utf8') elif is_text_string(default_value): value = to_text_string(value) elif isinstance(default_value, complex): value = complex(value) elif isinstance(default_value, float): value = float(value) elif isinstance(default_value, int): try: value = int(value) except ValueError: value = float(value) elif isinstance(default_value, datetime.datetime): value = datestr_to_datetime(value) elif isinstance(default_value, datetime.date): value = datestr_to_datetime(value).date() elif isinstance(default_value, datetime.timedelta): value = str_to_timedelta(value) elif ignore_errors: value = try_to_eval(value) else: value = eval(value) except (ValueError, SyntaxError): if ignore_errors: value = try_to_eval(value) else: return default_value return value # ============================================================================= # Types # ============================================================================= def get_type_string(item): """Return type string of an object.""" if isinstance(item, DataFrame): return "DataFrame" if isinstance(item, DatetimeIndex): return "DatetimeIndex" if isinstance(item, Series): return "Series" found = re.findall(r"<(?:type|class) '(\S*)'>", to_text_string(type(item))) if found: return found[0] def is_known_type(item): """Return True if object has a known type""" # Unfortunately, the masked array case is specific return isinstance(item, MaskedArray) or get_type_string(item) is not None def get_human_readable_type(item): """Return human-readable type string of an item""" if isinstance(item, (ndarray, MaskedArray)): return item.dtype.name elif isinstance(item, Image): return "Image" else: text = get_type_string(item) if text is None: text = to_text_string('unknown') else: return text[text.find('.')+1:] #============================================================================== # Globals filter: filter namespace dictionaries (to be edited in # CollectionsEditor) #============================================================================== def is_supported(value, check_all=False, filters=None, iterate=False): """Return True if the value is supported, False otherwise""" assert filters is not None if value is None: return True if not is_editable_type(value): return False elif not isinstance(value, filters): return False elif iterate: if isinstance(value, (list, tuple, set)): valid_count = 0 for val in value: if is_supported(val, filters=filters, iterate=check_all): valid_count += 1 if not check_all: break return valid_count > 0 elif isinstance(value, dict): for key, val in list(value.items()): if not is_supported(key, filters=filters, iterate=check_all) \ or not is_supported(val, filters=filters, iterate=check_all): return False if not check_all: break return True def globalsfilter(input_dict, check_all=False, filters=None, exclude_private=None, exclude_capitalized=None, exclude_uppercase=None, exclude_unsupported=None, excluded_names=None): """Keep only objects that can be pickled""" output_dict = {} for key, value in list(input_dict.items()): excluded = (exclude_private and key.startswith('_')) or \ (exclude_capitalized and key[0].isupper()) or \ (exclude_uppercase and key.isupper() and len(key) > 1 and not key[1:].isdigit()) or \ (key in excluded_names) or \ (exclude_unsupported and \ not is_supported(value, check_all=check_all, filters=filters)) if not excluded: output_dict[key] = value return output_dict #============================================================================== # Create view to be displayed by NamespaceBrowser #============================================================================== REMOTE_SETTINGS = ('check_all', 'exclude_private', 'exclude_uppercase', 'exclude_capitalized', 'exclude_unsupported', 'excluded_names', 'minmax') def get_remote_data(data, settings, mode, more_excluded_names=None): """ Return globals according to filter described in *settings*: * data: data to be filtered (dictionary) * settings: variable explorer settings (dictionary) * mode (string): 'editable' or 'picklable' * more_excluded_names: additional excluded names (list) """ supported_types = get_supported_types() assert mode in list(supported_types.keys()) excluded_names = settings['excluded_names'] if more_excluded_names is not None: excluded_names += more_excluded_names return globalsfilter(data, check_all=settings['check_all'], filters=tuple(supported_types[mode]), exclude_private=settings['exclude_private'], exclude_uppercase=settings['exclude_uppercase'], exclude_capitalized=settings['exclude_capitalized'], exclude_unsupported=settings['exclude_unsupported'], excluded_names=excluded_names) def make_remote_view(data, settings, more_excluded_names=None): """ Make a remote view of dictionary *data* -> globals explorer """ data = get_remote_data(data, settings, mode='editable', more_excluded_names=more_excluded_names) remote = {} for key, value in list(data.items()): view = value_to_display(value, minmax=settings['minmax']) remote[key] = {'type': get_human_readable_type(value), 'size': get_size(value), 'color': get_color_name(value), 'view': view} return remote spyder-3.2.6/spyder/widgets/variableexplorer/__init__.py0000664000175000017500000000042213026261006024247 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ spyder.widgets.variableexplorer =============================== Variable Explorer related widgets """ spyder-3.2.6/spyder/widgets/variableexplorer/importwizard.py0000664000175000017500000006013213224740762025262 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Text data Importing Wizard based on Qt """ # Standard library imports from __future__ import print_function from functools import partial as ft_partial # Third party imports from qtpy.compat import to_qvariant from qtpy.QtCore import QAbstractTableModel, QModelIndex, Qt, Signal, Slot from qtpy.QtGui import QColor, QIntValidator from qtpy.QtWidgets import (QCheckBox, QDialog, QFrame, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLineEdit, QPushButton, QMenu, QMessageBox, QRadioButton, QSizePolicy, QSpacerItem, QTableView, QTabWidget, QTextEdit, QVBoxLayout, QWidget) # If pandas fails to import here (for any reason), Spyder # will crash at startup. try: import pandas as pd except: pd = None # Local import from spyder.config.base import _ from spyder.py3compat import (INT_TYPES, io, TEXT_TYPES, to_text_string, zip_longest) from spyder.utils import programs from spyder.utils import icon_manager as ima from spyder.utils.qthelpers import add_actions, create_action def try_to_parse(value): _types = ('int', 'float') for _t in _types: try: _val = eval("%s('%s')" % (_t, value)) return _val except (ValueError, SyntaxError): pass return value def try_to_eval(value): try: return eval(value) except (NameError, SyntaxError, ImportError): return value #----Numpy arrays support class FakeObject(object): """Fake class used in replacement of missing modules""" pass try: from numpy import ndarray, array except: class ndarray(FakeObject): # analysis:ignore """Fake ndarray""" pass #----date and datetime objects support import datetime try: from dateutil.parser import parse as dateparse except: def dateparse(datestr, dayfirst=True): # analysis:ignore """Just for 'day/month/year' strings""" _a, _b, _c = list(map(int, datestr.split('/'))) if dayfirst: return datetime.datetime(_c, _b, _a) return datetime.datetime(_c, _a, _b) def datestr_to_datetime(value, dayfirst=True): return dateparse(value, dayfirst=dayfirst) #----Background colors for supported types COLORS = { bool: Qt.magenta, tuple([float] + list(INT_TYPES)): Qt.blue, list: Qt.yellow, dict: Qt.cyan, tuple: Qt.lightGray, TEXT_TYPES: Qt.darkRed, ndarray: Qt.green, datetime.date: Qt.darkYellow, } def get_color(value, alpha): """Return color depending on value type""" color = QColor() for typ in COLORS: if isinstance(value, typ): color = QColor(COLORS[typ]) color.setAlphaF(alpha) return color class ContentsWidget(QWidget): """Import wizard contents widget""" asDataChanged = Signal(bool) def __init__(self, parent, text): QWidget.__init__(self, parent) self.text_editor = QTextEdit(self) self.text_editor.setText(text) self.text_editor.setReadOnly(True) # Type frame type_layout = QHBoxLayout() type_label = QLabel(_("Import as")) type_layout.addWidget(type_label) data_btn = QRadioButton(_("data")) data_btn.setChecked(True) self._as_data= True type_layout.addWidget(data_btn) code_btn = QRadioButton(_("code")) self._as_code = False type_layout.addWidget(code_btn) txt_btn = QRadioButton(_("text")) type_layout.addWidget(txt_btn) h_spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) type_layout.addItem(h_spacer) type_frame = QFrame() type_frame.setLayout(type_layout) # Opts frame grid_layout = QGridLayout() grid_layout.setSpacing(0) col_label = QLabel(_("Column separator:")) grid_layout.addWidget(col_label, 0, 0) col_w = QWidget() col_btn_layout = QHBoxLayout() self.tab_btn = QRadioButton(_("Tab")) self.tab_btn.setChecked(False) col_btn_layout.addWidget(self.tab_btn) self.ws_btn = QRadioButton(_("Whitespace")) self.ws_btn.setChecked(False) col_btn_layout.addWidget(self.ws_btn) other_btn_col = QRadioButton(_("other")) other_btn_col.setChecked(True) col_btn_layout.addWidget(other_btn_col) col_w.setLayout(col_btn_layout) grid_layout.addWidget(col_w, 0, 1) self.line_edt = QLineEdit(",") self.line_edt.setMaximumWidth(30) self.line_edt.setEnabled(True) other_btn_col.toggled.connect(self.line_edt.setEnabled) grid_layout.addWidget(self.line_edt, 0, 2) row_label = QLabel(_("Row separator:")) grid_layout.addWidget(row_label, 1, 0) row_w = QWidget() row_btn_layout = QHBoxLayout() self.eol_btn = QRadioButton(_("EOL")) self.eol_btn.setChecked(True) row_btn_layout.addWidget(self.eol_btn) other_btn_row = QRadioButton(_("other")) row_btn_layout.addWidget(other_btn_row) row_w.setLayout(row_btn_layout) grid_layout.addWidget(row_w, 1, 1) self.line_edt_row = QLineEdit(";") self.line_edt_row.setMaximumWidth(30) self.line_edt_row.setEnabled(False) other_btn_row.toggled.connect(self.line_edt_row.setEnabled) grid_layout.addWidget(self.line_edt_row, 1, 2) grid_layout.setRowMinimumHeight(2, 15) other_group = QGroupBox(_("Additional options")) other_layout = QGridLayout() other_group.setLayout(other_layout) skiprows_label = QLabel(_("Skip rows:")) other_layout.addWidget(skiprows_label, 0, 0) self.skiprows_edt = QLineEdit('0') self.skiprows_edt.setMaximumWidth(30) intvalid = QIntValidator(0, len(to_text_string(text).splitlines()), self.skiprows_edt) self.skiprows_edt.setValidator(intvalid) other_layout.addWidget(self.skiprows_edt, 0, 1) other_layout.setColumnMinimumWidth(2, 5) comments_label = QLabel(_("Comments:")) other_layout.addWidget(comments_label, 0, 3) self.comments_edt = QLineEdit('#') self.comments_edt.setMaximumWidth(30) other_layout.addWidget(self.comments_edt, 0, 4) self.trnsp_box = QCheckBox(_("Transpose")) #self.trnsp_box.setEnabled(False) other_layout.addWidget(self.trnsp_box, 1, 0, 2, 0) grid_layout.addWidget(other_group, 3, 0, 2, 0) opts_frame = QFrame() opts_frame.setLayout(grid_layout) data_btn.toggled.connect(opts_frame.setEnabled) data_btn.toggled.connect(self.set_as_data) code_btn.toggled.connect(self.set_as_code) # self.connect(txt_btn, SIGNAL("toggled(bool)"), # self, SLOT("is_text(bool)")) # Final layout layout = QVBoxLayout() layout.addWidget(type_frame) layout.addWidget(self.text_editor) layout.addWidget(opts_frame) self.setLayout(layout) def get_as_data(self): """Return if data type conversion""" return self._as_data def get_as_code(self): """Return if code type conversion""" return self._as_code def get_as_num(self): """Return if numeric type conversion""" return self._as_num def get_col_sep(self): """Return the column separator""" if self.tab_btn.isChecked(): return u"\t" elif self.ws_btn.isChecked(): return None return to_text_string(self.line_edt.text()) def get_row_sep(self): """Return the row separator""" if self.eol_btn.isChecked(): return u"\n" return to_text_string(self.line_edt_row.text()) def get_skiprows(self): """Return number of lines to be skipped""" return int(to_text_string(self.skiprows_edt.text())) def get_comments(self): """Return comment string""" return to_text_string(self.comments_edt.text()) @Slot(bool) def set_as_data(self, as_data): """Set if data type conversion""" self._as_data = as_data self.asDataChanged.emit(as_data) @Slot(bool) def set_as_code(self, as_code): """Set if code type conversion""" self._as_code = as_code class PreviewTableModel(QAbstractTableModel): """Import wizard preview table model""" def __init__(self, data=[], parent=None): QAbstractTableModel.__init__(self, parent) self._data = data def rowCount(self, parent=QModelIndex()): """Return row count""" return len(self._data) def columnCount(self, parent=QModelIndex()): """Return column count""" return len(self._data[0]) def _display_data(self, index): """Return a data element""" return to_qvariant(self._data[index.row()][index.column()]) def data(self, index, role=Qt.DisplayRole): """Return a model data element""" if not index.isValid(): return to_qvariant() if role == Qt.DisplayRole: return self._display_data(index) elif role == Qt.BackgroundColorRole: return to_qvariant(get_color(self._data[index.row()][index.column()], .2)) elif role == Qt.TextAlignmentRole: return to_qvariant(int(Qt.AlignRight|Qt.AlignVCenter)) return to_qvariant() def setData(self, index, value, role=Qt.EditRole): """Set model data""" return False def get_data(self): """Return a copy of model data""" return self._data[:][:] def parse_data_type(self, index, **kwargs): """Parse a type to an other type""" if not index.isValid(): return False try: if kwargs['atype'] == "date": self._data[index.row()][index.column()] = \ datestr_to_datetime(self._data[index.row()][index.column()], kwargs['dayfirst']).date() elif kwargs['atype'] == "perc": _tmp = self._data[index.row()][index.column()].replace("%", "") self._data[index.row()][index.column()] = eval(_tmp)/100. elif kwargs['atype'] == "account": _tmp = self._data[index.row()][index.column()].replace(",", "") self._data[index.row()][index.column()] = eval(_tmp) elif kwargs['atype'] == "unicode": self._data[index.row()][index.column()] = to_text_string( self._data[index.row()][index.column()]) elif kwargs['atype'] == "int": self._data[index.row()][index.column()] = int( self._data[index.row()][index.column()]) elif kwargs['atype'] == "float": self._data[index.row()][index.column()] = float( self._data[index.row()][index.column()]) self.dataChanged.emit(index, index) except Exception as instance: print(instance) # spyder: test-skip def reset(self): self.beginResetModel() self.endResetModel() class PreviewTable(QTableView): """Import wizard preview widget""" def __init__(self, parent): QTableView.__init__(self, parent) self._model = None # Setting up actions self.date_dayfirst_action = create_action(self, "dayfirst", triggered=ft_partial(self.parse_to_type, atype="date", dayfirst=True)) self.date_monthfirst_action = create_action(self, "monthfirst", triggered=ft_partial(self.parse_to_type, atype="date", dayfirst=False)) self.perc_action = create_action(self, "perc", triggered=ft_partial(self.parse_to_type, atype="perc")) self.acc_action = create_action(self, "account", triggered=ft_partial(self.parse_to_type, atype="account")) self.str_action = create_action(self, "unicode", triggered=ft_partial(self.parse_to_type, atype="unicode")) self.int_action = create_action(self, "int", triggered=ft_partial(self.parse_to_type, atype="int")) self.float_action = create_action(self, "float", triggered=ft_partial(self.parse_to_type, atype="float")) # Setting up menus self.date_menu = QMenu() self.date_menu.setTitle("Date") add_actions( self.date_menu, (self.date_dayfirst_action, self.date_monthfirst_action)) self.parse_menu = QMenu(self) self.parse_menu.addMenu(self.date_menu) add_actions( self.parse_menu, (self.perc_action, self.acc_action)) self.parse_menu.setTitle("String to") self.opt_menu = QMenu(self) self.opt_menu.addMenu(self.parse_menu) add_actions( self.opt_menu, (self.str_action, self.int_action, self.float_action)) def _shape_text(self, text, colsep=u"\t", rowsep=u"\n", transpose=False, skiprows=0, comments='#'): """Decode the shape of the given text""" assert colsep != rowsep out = [] text_rows = text.split(rowsep)[skiprows:] for row in text_rows: stripped = to_text_string(row).strip() if len(stripped) == 0 or stripped.startswith(comments): continue line = to_text_string(row).split(colsep) line = [try_to_parse(to_text_string(x)) for x in line] out.append(line) # Replace missing elements with np.nan's or None's if programs.is_module_installed('numpy'): from numpy import nan out = list(zip_longest(*out, fillvalue=nan)) else: out = list(zip_longest(*out, fillvalue=None)) # Tranpose the last result to get the expected one out = [[r[col] for r in out] for col in range(len(out[0]))] if transpose: return [[r[col] for r in out] for col in range(len(out[0]))] return out def get_data(self): """Return model data""" if self._model is None: return None return self._model.get_data() def process_data(self, text, colsep=u"\t", rowsep=u"\n", transpose=False, skiprows=0, comments='#'): """Put data into table model""" data = self._shape_text(text, colsep, rowsep, transpose, skiprows, comments) self._model = PreviewTableModel(data) self.setModel(self._model) @Slot() def parse_to_type(self,**kwargs): """Parse to a given type""" indexes = self.selectedIndexes() if not indexes: return for index in indexes: self.model().parse_data_type(index, **kwargs) def contextMenuEvent(self, event): """Reimplement Qt method""" self.opt_menu.popup(event.globalPos()) event.accept() class PreviewWidget(QWidget): """Import wizard preview widget""" def __init__(self, parent): QWidget.__init__(self, parent) vert_layout = QVBoxLayout() # Type frame type_layout = QHBoxLayout() type_label = QLabel(_("Import as")) type_layout.addWidget(type_label) self.array_btn = array_btn = QRadioButton(_("array")) array_btn.setEnabled(ndarray is not FakeObject) array_btn.setChecked(ndarray is not FakeObject) type_layout.addWidget(array_btn) list_btn = QRadioButton(_("list")) list_btn.setChecked(not array_btn.isChecked()) type_layout.addWidget(list_btn) if pd: self.df_btn = df_btn = QRadioButton(_("DataFrame")) df_btn.setChecked(False) type_layout.addWidget(df_btn) h_spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) type_layout.addItem(h_spacer) type_frame = QFrame() type_frame.setLayout(type_layout) self._table_view = PreviewTable(self) vert_layout.addWidget(type_frame) vert_layout.addWidget(self._table_view) self.setLayout(vert_layout) def open_data(self, text, colsep=u"\t", rowsep=u"\n", transpose=False, skiprows=0, comments='#'): """Open clipboard text as table""" if pd: self.pd_text = text self.pd_info = dict(sep=colsep, lineterminator=rowsep, skiprows=skiprows, comment=comments) if colsep is None: self.pd_info = dict(lineterminator=rowsep, skiprows=skiprows, comment=comments, delim_whitespace=True) self._table_view.process_data(text, colsep, rowsep, transpose, skiprows, comments) def get_data(self): """Return table data""" return self._table_view.get_data() class ImportWizard(QDialog): """Text data import wizard""" def __init__(self, parent, text, title=None, icon=None, contents_title=None, varname=None): QDialog.__init__(self, parent) # Destroying the C++ object right after closing the dialog box, # otherwise it may be garbage-collected in another QThread # (e.g. the editor's analysis thread in Spyder), thus leading to # a segmentation fault on UNIX or an application crash on Windows self.setAttribute(Qt.WA_DeleteOnClose) if title is None: title = _("Import wizard") self.setWindowTitle(title) if icon is None: self.setWindowIcon(ima.icon('fileimport')) if contents_title is None: contents_title = _("Raw text") if varname is None: varname = _("variable_name") self.var_name, self.clip_data = None, None # Setting GUI self.tab_widget = QTabWidget(self) self.text_widget = ContentsWidget(self, text) self.table_widget = PreviewWidget(self) self.tab_widget.addTab(self.text_widget, _("text")) self.tab_widget.setTabText(0, contents_title) self.tab_widget.addTab(self.table_widget, _("table")) self.tab_widget.setTabText(1, _("Preview")) self.tab_widget.setTabEnabled(1, False) name_layout = QHBoxLayout() name_label = QLabel(_("Variable Name")) name_layout.addWidget(name_label) self.name_edt = QLineEdit() self.name_edt.setText(varname) name_layout.addWidget(self.name_edt) btns_layout = QHBoxLayout() cancel_btn = QPushButton(_("Cancel")) btns_layout.addWidget(cancel_btn) cancel_btn.clicked.connect(self.reject) h_spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) btns_layout.addItem(h_spacer) self.back_btn = QPushButton(_("Previous")) self.back_btn.setEnabled(False) btns_layout.addWidget(self.back_btn) self.back_btn.clicked.connect(ft_partial(self._set_step, step=-1)) self.fwd_btn = QPushButton(_("Next")) if not text: self.fwd_btn.setEnabled(False) btns_layout.addWidget(self.fwd_btn) self.fwd_btn.clicked.connect(ft_partial(self._set_step, step=1)) self.done_btn = QPushButton(_("Done")) self.done_btn.setEnabled(False) btns_layout.addWidget(self.done_btn) self.done_btn.clicked.connect(self.process) self.text_widget.asDataChanged.connect(self.fwd_btn.setEnabled) self.text_widget.asDataChanged.connect(self.done_btn.setDisabled) layout = QVBoxLayout() layout.addLayout(name_layout) layout.addWidget(self.tab_widget) layout.addLayout(btns_layout) self.setLayout(layout) def _focus_tab(self, tab_idx): """Change tab focus""" for i in range(self.tab_widget.count()): self.tab_widget.setTabEnabled(i, False) self.tab_widget.setTabEnabled(tab_idx, True) self.tab_widget.setCurrentIndex(tab_idx) def _set_step(self, step): """Proceed to a given step""" new_tab = self.tab_widget.currentIndex() + step assert new_tab < self.tab_widget.count() and new_tab >= 0 if new_tab == self.tab_widget.count()-1: try: self.table_widget.open_data(self._get_plain_text(), self.text_widget.get_col_sep(), self.text_widget.get_row_sep(), self.text_widget.trnsp_box.isChecked(), self.text_widget.get_skiprows(), self.text_widget.get_comments()) self.done_btn.setEnabled(True) self.done_btn.setDefault(True) self.fwd_btn.setEnabled(False) self.back_btn.setEnabled(True) except (SyntaxError, AssertionError) as error: QMessageBox.critical(self, _("Import wizard"), _("Unable to proceed to next step" "

    Please check your entries." "

    Error message:
    %s") % str(error)) return elif new_tab == 0: self.done_btn.setEnabled(False) self.fwd_btn.setEnabled(True) self.back_btn.setEnabled(False) self._focus_tab(new_tab) def get_data(self): """Return processed data""" # It is import to avoid accessing Qt C++ object as it has probably # already been destroyed, due to the Qt.WA_DeleteOnClose attribute return self.var_name, self.clip_data def _simplify_shape(self, alist, rec=0): """Reduce the alist dimension if needed""" if rec != 0: if len(alist) == 1: return alist[-1] return alist if len(alist) == 1: return self._simplify_shape(alist[-1], 1) return [self._simplify_shape(al, 1) for al in alist] def _get_table_data(self): """Return clipboard processed as data""" data = self._simplify_shape( self.table_widget.get_data()) if self.table_widget.array_btn.isChecked(): return array(data) elif pd and self.table_widget.df_btn.isChecked(): info = self.table_widget.pd_info buf = io.StringIO(self.table_widget.pd_text) return pd.read_csv(buf, **info) return data def _get_plain_text(self): """Return clipboard as text""" return self.text_widget.text_editor.toPlainText() @Slot() 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 test(text): """Test""" from spyder.utils.qthelpers import qapplication _app = qapplication() # analysis:ignore dialog = ImportWizard(None, text) if dialog.exec_(): print(dialog.get_data()) # spyder: test-skip if __name__ == "__main__": test(u"17/11/1976\t1.34\n14/05/09\t3.14") spyder-3.2.6/spyder/widgets/internalshell.py0000664000175000017500000003751113224121062022014 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Internal shell widget : PythonShellWidget + Interpreter""" # pylint: disable=C0103 # pylint: disable=R0903 # pylint: disable=R0911 # pylint: disable=R0201 #FIXME: Internal shell MT: for i in range(100000): print i -> bug # Standard library imports from time import time import os import threading # Third party imports from qtpy.QtCore import QEventLoop, QObject, Signal, Slot from qtpy.QtWidgets import QMessageBox # Local imports from spyder import get_versions from spyder.interpreter import Interpreter from spyder.py3compat import (builtins, to_binary_string, to_text_string) from spyder.utils import icon_manager as ima from spyder.utils import programs from spyder.utils.dochelpers import getargtxt, getdoc, getobjdir, getsource from spyder.utils.misc import get_error_match, getcwd_or_home from spyder.utils.qthelpers import create_action from spyder.widgets.shell import PythonShellWidget from spyder.widgets.variableexplorer.objecteditor import oedit # TODO: remove the CONF object and make it work anyway # In fact, this 'CONF' object has nothing to do in package spyder/widgets # which should not contain anything directly related to Spyder's main app from spyder.config.base import _, DEBUG, get_conf_path from spyder.config.main import CONF builtins.oedit = oedit def create_banner(message): """Create internal shell banner""" if message is None: versions = get_versions() return 'Python %s %dbits [%s]'\ % (versions['python'], versions['bitness'], versions['system']) else: return message class SysOutput(QObject): """Handle standard I/O queue""" data_avail = Signal() def __init__(self): QObject.__init__(self) self.queue = [] self.lock = threading.Lock() def write(self, val): self.lock.acquire() self.queue.append(val) self.lock.release() self.data_avail.emit() def empty_queue(self): self.lock.acquire() s = "".join(self.queue) self.queue = [] self.lock.release() return s # We need to add this method to fix Issue 1789 def flush(self): pass # This is needed to fix Issue 2984 @property def closed(self): return False class WidgetProxyData(object): pass class WidgetProxy(QObject): """Handle Shell widget refresh signal""" sig_new_prompt = Signal(str) sig_set_readonly = Signal(bool) sig_edit = Signal(str, bool) sig_wait_input = Signal(str) def __init__(self, input_condition): QObject.__init__(self) self.input_data = None self.input_condition = input_condition def new_prompt(self, prompt): self.sig_new_prompt.emit(prompt) def set_readonly(self, state): self.sig_set_readonly.emit(state) def edit(self, filename, external_editor=False): self.sig_edit.emit(filename, external_editor) def data_available(self): """Return True if input data is available""" return self.input_data is not WidgetProxyData def wait_input(self, prompt=''): self.input_data = WidgetProxyData self.sig_wait_input.emit(prompt) def end_input(self, cmd): self.input_condition.acquire() self.input_data = cmd self.input_condition.notify() self.input_condition.release() class InternalShell(PythonShellWidget): """Shell base widget: link between PythonShellWidget and Interpreter""" status = Signal(str) refresh = Signal() go_to_error = Signal(str) focus_changed = Signal() def __init__(self, parent=None, namespace=None, commands=[], message=None, max_line_count=300, font=None, exitfunc=None, profile=False, multithreaded=True, light_background=True): PythonShellWidget.__init__(self, parent, get_conf_path('history_internal.py'), profile) self.set_light_background(light_background) self.multithreaded = multithreaded self.setMaximumBlockCount(max_line_count) if font is not None: self.set_font(font) # Allow raw_input support: self.input_loop = None self.input_mode = False # KeyboardInterrupt support self.interrupted = False # used only for not-multithreaded mode self.sig_keyboard_interrupt.connect(self.keyboard_interrupt) # Code completion / calltips getcfg = lambda option: CONF.get('internal_console', option) case_sensitive = getcfg('codecompletion/case_sensitive') self.set_codecompletion_case(case_sensitive) # 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.status.emit('') # Embedded shell -- requires the monitor (which installs the # 'open_in_spyder' function in builtins) if hasattr(builtins, 'open_in_spyder'): self.go_to_error.connect(self.open_with_external_spyder) #------ Interpreter def start_interpreter(self, namespace): """Start Python interpreter""" self.clear() if self.interpreter is not None: self.interpreter.closing() self.interpreter = Interpreter(namespace, self.exitfunc, SysOutput, WidgetProxy, DEBUG) self.interpreter.stdout_write.data_avail.connect(self.stdout_avail) self.interpreter.stderr_write.data_avail.connect(self.stderr_avail) self.interpreter.widget_proxy.sig_set_readonly.connect(self.setReadOnly) self.interpreter.widget_proxy.sig_new_prompt.connect(self.new_prompt) self.interpreter.widget_proxy.sig_edit.connect(self.edit_script) self.interpreter.widget_proxy.sig_wait_input.connect(self.wait_input) if self.multithreaded: self.interpreter.start() # Interpreter banner banner = create_banner(self.message) self.write(banner, prompt=True) # Initial commands for cmd in self.commands: self.run_command(cmd, history=False, new_prompt=False) # First prompt self.new_prompt(self.interpreter.p1) self.refresh.emit() return self.interpreter def exit_interpreter(self): """Exit interpreter""" self.interpreter.exit_flag = True if self.multithreaded: self.interpreter.stdin_write.write(to_binary_string('\n')) self.interpreter.restore_stds() def edit_script(self, filename, external_editor): filename = to_text_string(filename) if external_editor: self.external_editor(filename) else: self.parent().edit_script(filename) def stdout_avail(self): """Data is available in stdout, let's empty the queue and write it!""" data = self.interpreter.stdout_write.empty_queue() if data: self.write(data) def stderr_avail(self): """Data is available in stderr, let's empty the queue and write it!""" data = self.interpreter.stderr_write.empty_queue() if data: self.write(data, error=True) self.flush(error=True) #------Raw input support def wait_input(self, prompt=''): """Wait for input (raw_input support)""" self.new_prompt(prompt) self.setFocus() self.input_mode = True self.input_loop = QEventLoop() self.input_loop.exec_() self.input_loop = None def end_input(self, cmd): """End of wait_input mode""" self.input_mode = False self.input_loop.exit() self.interpreter.widget_proxy.end_input(cmd) #----- Menus, actions, ... def setup_context_menu(self): """Reimplement PythonShellWidget method""" PythonShellWidget.setup_context_menu(self) self.help_action = create_action(self, _("Help..."), icon=ima.icon('DialogHelpButton'), triggered=self.help) self.menu.addAction(self.help_action) @Slot() def help(self): """Help on Spyder console""" QMessageBox.about(self, _("Help"), """%s

    %s
    edit foobar.py

    %s
    xedit foobar.py

    %s
    run foobar.py

    %s
    clear x, y

    %s
    !ls

    %s
    object?

    %s
    result = oedit(object) """ % (_('Shell special commands:'), _('Internal editor:'), _('External editor:'), _('Run script:'), _('Remove references:'), _('System commands:'), _('Python help:'), _('GUI-based editor:'))) #------ External editing def open_with_external_spyder(self, text): """Load file in external Spyder's editor, if available This method is used only for embedded consoles (could also be useful if we ever implement the magic %edit command)""" match = get_error_match(to_text_string(text)) if match: fname, lnb = match.groups() builtins.open_in_spyder(fname, int(lnb)) def external_editor(self, filename, goto=-1): """Edit in an external editor Recommended: SciTE (e.g. to go to line where an error did occur)""" editor_path = CONF.get('internal_console', 'external_editor/path') goto_option = CONF.get('internal_console', 'external_editor/gotoline') try: args = [filename] if goto > 0 and goto_option: args.append('%s%d'.format(goto_option, goto)) programs.run_program(editor_path, args) except OSError: self.write_error("External editor was not found:" " %s\n" % editor_path) #------ I/O def flush(self, error=False, prompt=False): """Reimplement ShellBaseWidget method""" PythonShellWidget.flush(self, error=error, prompt=prompt) if self.interrupted: self.interrupted = False raise KeyboardInterrupt #------ Clear terminal def clear_terminal(self): """Reimplement ShellBaseWidget method""" self.clear() self.new_prompt(self.interpreter.p2 if self.interpreter.more else self.interpreter.p1) #------ Keyboard events def on_enter(self, command): """on_enter""" if self.profile: # Simple profiling test t0 = time() for _ in range(10): self.execute_command(command) self.insert_text(u"\n<Δt>=%dms\n" % (1e2*(time()-t0))) self.new_prompt(self.interpreter.p1) else: self.execute_command(command) self.__flush_eventqueue() def keyPressEvent(self, event): """ Reimplement Qt Method Enhanced keypress event handler """ if self.preprocess_keyevent(event): # Event was accepted in self.preprocess_keyevent return self.postprocess_keyevent(event) def __flush_eventqueue(self): """Flush keyboard event queue""" while self.eventqueue: past_event = self.eventqueue.pop(0) self.postprocess_keyevent(past_event) #------ Command execution def keyboard_interrupt(self): """Simulate keyboard interrupt""" if self.multithreaded: self.interpreter.raise_keyboard_interrupt() else: if self.interpreter.more: self.write_error("\nKeyboardInterrupt\n") self.interpreter.more = False self.new_prompt(self.interpreter.p1) self.interpreter.resetbuffer() else: self.interrupted = True def execute_lines(self, lines): """ Execute a set of lines as multiple command lines: multiple lines of text to be executed as single commands """ for line in lines.splitlines(): stripped_line = line.strip() if stripped_line.startswith('#'): continue self.write(line+os.linesep, flush=True) self.execute_command(line+"\n") self.flush() def execute_command(self, cmd): """ Execute a command cmd: one-line command only, with '\n' at the end """ if self.input_mode: self.end_input(cmd) return if cmd.endswith('\n'): cmd = cmd[:-1] # cls command if cmd == 'cls': self.clear_terminal() return self.run_command(cmd) def run_command(self, cmd, history=True, new_prompt=True): """Run command in interpreter""" if not cmd: cmd = '' else: if history: self.add_to_history(cmd) self.interpreter.stdin_write.write(to_binary_string(cmd + '\n')) if not self.multithreaded: self.interpreter.run_line() self.refresh.emit() #------ Code completion / Calltips def _eval(self, text): """Is text a valid object?""" return self.interpreter.eval(text) def get_dir(self, objtxt): """Return dir(object)""" obj, valid = self._eval(objtxt) if valid: return getobjdir(obj) def get_globals_keys(self): """Return shell globals() keys""" return list(self.interpreter.namespace.keys()) def get_cdlistdir(self): """Return shell current directory list dir""" return os.listdir(getcwd_or_home()) def iscallable(self, objtxt): """Is object callable?""" obj, valid = self._eval(objtxt) if valid: return callable(obj) def get_arglist(self, objtxt): """Get func/method argument list""" obj, valid = self._eval(objtxt) if valid: return getargtxt(obj) def get__doc__(self, objtxt): """Get object __doc__""" obj, valid = self._eval(objtxt) if valid: return obj.__doc__ def get_doc(self, objtxt): """Get object documentation dictionary""" obj, valid = self._eval(objtxt) if valid: return getdoc(obj) def get_source(self, objtxt): """Get object source""" obj, valid = self._eval(objtxt) if valid: return getsource(obj) def is_defined(self, objtxt, force_import=False): """Return True if object is defined""" return self.interpreter.is_defined(objtxt, force_import) spyder-3.2.6/spyder/widgets/pydocgui.py0000664000175000017500000000777613224740762021023 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """pydoc widget""" # Standard library imports import os.path as osp import sys # Third party imports from qtpy.QtCore import Qt, QThread, QUrl, Signal from qtpy.QtGui import QCursor from qtpy.QtWidgets import QApplication # Local imports from spyder.config.base import _ from spyder.py3compat import PY3, to_text_string from spyder.utils.misc import select_port from spyder.widgets.browser import WebBrowser class PydocServer(QThread): """Pydoc server""" server_started = Signal() def __init__(self, port=7464): QThread.__init__(self) self.port = port self.server = None self.complete = False def run(self): import pydoc if PY3: # Python 3 self.callback(pydoc._start_server(pydoc._url_handler, self.port)) else: # Python 2 pydoc.serve(self.port, self.callback, self.completer) def callback(self, server): self.server = server self.server_started.emit() def completer(self): self.complete = True def quit_server(self): if PY3: # Python 3 if self.server.serving: self.server.stop() else: # Python 2 self.server.quit = 1 class PydocBrowser(WebBrowser): """ pydoc widget """ DEFAULT_PORT = 30128 def __init__(self, parent): WebBrowser.__init__(self, parent) self.server = None self.port = None def initialize(self): """Start pydoc server""" QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() self.start_server() # Initializing continues in `initialize_continued` method... def initialize_continued(self): """Load home page""" self.go_home() QApplication.restoreOverrideCursor() def is_server_running(self): """Return True if pydoc server is already running""" return self.server is not None def closeEvent(self, event): self.server.quit_server() # while not self.server.complete: #XXX Is it really necessary? # pass event.accept() #------ Public API ----------------------------------------------------- def start_server(self): """Start pydoc server""" if self.server is None: self.port = select_port(default_port=self.DEFAULT_PORT) self.set_home_url('http://localhost:%d/' % self.port) elif self.server.isRunning(): self.server.server_started.disconnect(self.initialize_continued) self.server.quit() self.server = PydocServer(port=self.port) self.server.server_started.connect(self.initialize_continued) self.server.start() #------ WebBrowser API ----------------------------------------------------- def get_label(self): """Return address label text""" return _("Module or package:") def reload(self): """Reload page""" self.start_server() WebBrowser.reload(self) def text_to_url(self, text): """Convert text address into QUrl object""" if text.startswith('/'): text = text[1:] return QUrl(self.home_url.toString()+text+'.html') 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 test(): """Run web browser""" from spyder.utils.qthelpers import qapplication app = qapplication(test_time=8) widget = PydocBrowser(None) widget.show() widget.initialize() sys.exit(app.exec_()) if __name__ == '__main__': test() spyder-3.2.6/spyder/widgets/tests/0000775000175000017500000000000013225025007017734 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/widgets/tests/test_findinfiles.py0000664000175000017500000000766613224740762023671 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for findinfiles.py """ # Test library imports import os import pytest import os.path as osp from pytestqt import qtbot # Local imports import spyder.widgets.findinfiles from spyder.widgets.findinfiles import FindInFilesWidget LOCATION = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__))) def process_search_results(results): """ Transform result representation from the output of the widget to the test framework comparison representation. """ matches = {} for result in results.values(): file, line, col = result filename = osp.basename(file) if filename not in matches: matches[filename] = [] matches[filename].append((line, col)) matches[filename] = sorted(matches[filename]) return matches @pytest.fixture def setup_findinfiles(qtbot, *args, **kwargs): """Set up find in files widget.""" widget = FindInFilesWidget(None, *args, **kwargs) qtbot.addWidget(widget) return widget def expected_results(): results = {'spam.txt': [(1, 0), (1, 5), (3, 22)], 'spam.py': [(2, 7), (5, 1), (7, 12)], 'spam.cpp': [(2, 9), (6, 15), (8, 2), (11, 4), (11, 10), (13, 12)] } return results def expected_case_unsensitive_results(): results = {'spam.txt': [(1, 10)], 'ham.txt': [(1, 0), (1, 10), (3, 0), (4, 0), (5, 4), (9, 0), (10, 0)]} return results def test_findinfiles(qtbot): """Run find in files widget.""" find_in_files = setup_findinfiles(qtbot) find_in_files.resize(640, 480) find_in_files.show() assert find_in_files def test_find_in_files_search(qtbot): """ Test the find in files utility by searching a string located on a set of known files. The results of the test should be equal to the expected search result values. """ find_in_files = setup_findinfiles(qtbot) find_in_files.set_search_text("spam") find_in_files.find_options.set_directory(osp.join(LOCATION, "data")) find_in_files.find() blocker = qtbot.waitSignal(find_in_files.sig_finished) blocker.wait() matches = process_search_results(find_in_files.result_browser.data) assert expected_results() == matches def test_exclude_extension(qtbot): find_in_files = setup_findinfiles(qtbot, exclude="\.py$") find_in_files.set_search_text("spam") find_in_files.find_options.set_directory(osp.join(LOCATION, "data")) find_in_files.find() blocker = qtbot.waitSignal(find_in_files.sig_finished) blocker.wait() matches = process_search_results(find_in_files.result_browser.data) files_filtered = True for file in matches: filename, ext = osp.splitext(file) if ext == '.py': files_filtered = False break assert files_filtered def test_case_unsensitive_search(qtbot): find_in_files = setup_findinfiles(qtbot, case_sensitive=False) find_in_files.set_search_text('ham') find_in_files.find_options.set_directory(osp.join(LOCATION, "data")) find_in_files.find() blocker = qtbot.waitSignal(find_in_files.sig_finished) blocker.wait() matches = process_search_results(find_in_files.result_browser.data) print(matches) assert expected_case_unsensitive_results() == matches def test_case_sensitive_search(qtbot): find_in_files = setup_findinfiles(qtbot) find_in_files.set_search_text('HaM') find_in_files.find_options.set_directory(osp.join(LOCATION, "data")) find_in_files.find() blocker = qtbot.waitSignal(find_in_files.sig_finished) blocker.wait() matches = process_search_results(find_in_files.result_browser.data) print(matches) assert matches == {'ham.txt': [(9, 0)]} if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/widgets/tests/test_editor.py0000664000175000017500000004441213224740762022653 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for editor.py """ # Standard library imports from sys import platform try: from unittest.mock import Mock, MagicMock except ImportError: from mock import Mock, MagicMock # Python 2 # Third party imports import pytest from flaky import flaky from qtpy.QtCore import Qt from qtpy.QtGui import QTextCursor # Local imports from spyder.utils.fixtures import setup_editor from spyder.widgets.editor import EditorStack, EditorSplitter from spyder.widgets.findreplace import FindReplace from spyder.py3compat import PY2 # Qt Test Fixtures #-------------------------------- @pytest.fixture def base_editor_bot(qtbot): editor_stack = EditorStack(None, []) editor_stack.set_introspector(Mock()) editor_stack.set_find_widget(Mock()) editor_stack.set_io_actions(Mock(), Mock(), Mock(), Mock()) return editor_stack, qtbot @pytest.fixture def editor_bot(base_editor_bot): """ Set up EditorStack with CodeEditor containing some Python code. The cursor is at the empty line below the code. Returns tuple with EditorStack and CodeEditor. """ editor_stack, qtbot = base_editor_bot text = ('a = 1\n' 'print(a)\n' '\n' 'x = 2') # a newline is added at end finfo = editor_stack.new('foo.py', 'utf-8', text) qtbot.addWidget(editor_stack) return editor_stack, finfo.editor, qtbot @pytest.fixture def editor_find_replace_bot(base_editor_bot): editor_stack, qtbot = base_editor_bot text = ('spam bacon\n' 'spam sausage\n' 'spam egg') finfo = editor_stack.new('spam.py', 'utf-8', text) find_replace = FindReplace(None, enable_replace=True) editor_stack.set_find_widget(find_replace) find_replace.set_editor(finfo.editor) qtbot.addWidget(editor_stack) return editor_stack, finfo.editor, find_replace, qtbot @pytest.fixture def editor_cells_bot(base_editor_bot): editor_stack, qtbot = base_editor_bot text = ('# %%\n' '# 1 cell\n' '# print(1)\n' '# %%\n' '# 2 cell\n' '# print(2)\n' '# %%\n' '# 3 cell\n' '# print(3)\n') finfo = editor_stack.new('cells.py', 'utf-8', text) find_replace = FindReplace(None, enable_replace=True) qtbot.addWidget(editor_stack) return editor_stack, finfo.editor, qtbot @pytest.fixture def editor_splitter_bot(qtbot): """Create editor splitter.""" editor_splitter = EditorSplitter(None, Mock(), [], first=True) qtbot.addWidget(editor_splitter) editor_splitter.show() yield editor_splitter editor_splitter.destroy() # Tests #------------------------------- def test_find_number_matches(qtbot): """Test for number matches in find/replace.""" editor_stack, editor = setup_editor(qtbot) editor_stack.find_widget.case_button.setChecked(True) text = ' test \nTEST \nTest \ntesT ' editor.set_text(text) editor_stack.find_widget.search_text.add_text('test') editor_stack.find_widget.find(changed=False, forward=True, rehighlight=False, multiline_replace_check=False) editor_text = editor_stack.find_widget.number_matches_text.text() assert editor_text == '1 of 1' editor_stack.find_widget.search_text.add_text('fail') editor_stack.find_widget.find(changed=False, forward=True, rehighlight=False, multiline_replace_check=False) editor_text = editor_stack.find_widget.number_matches_text.text() assert editor_text == 'no matches' def test_move_current_line_up(editor_bot): editor_stack, editor, qtbot = editor_bot # Move second line up when nothing is selected. editor.go_to_line(2) editor.move_line_up() expected_new_text = ('print(a)\n' 'a = 1\n' '\n' 'x = 2\n') assert editor.toPlainText() == expected_new_text # Move line up when already at the top. editor.move_line_up() assert editor.toPlainText() == expected_new_text # Move fourth line up when part of the line is selected. editor.go_to_line(4) editor.moveCursor(QTextCursor.Right, QTextCursor.MoveAnchor) for i in range(2): editor.moveCursor(QTextCursor.Right, QTextCursor.KeepAnchor) editor.move_line_up() expected_new_text = ('print(a)\n' 'a = 1\n' 'x = 2\n' '\n') assert editor.toPlainText()[:] == expected_new_text def test_move_current_line_down(editor_bot): editor_stack, editor, qtbot = editor_bot # Move fourth line down when nothing is selected. editor.go_to_line(4) editor.move_line_down() expected_new_text = ('a = 1\n' 'print(a)\n' '\n' '\n' 'x = 2') assert editor.toPlainText() == expected_new_text # Move line down when already at the bottom. editor.move_line_down() assert editor.toPlainText() == expected_new_text # Move first line down when part of the line is selected. editor.go_to_line(1) editor.moveCursor(QTextCursor.Right, QTextCursor.MoveAnchor) for i in range(2): editor.moveCursor(QTextCursor.Right, QTextCursor.KeepAnchor) editor.move_line_down() expected_new_text = ('print(a)\n' 'a = 1\n' '\n' '\n' 'x = 2') assert editor.toPlainText() == expected_new_text def test_move_multiple_lines_up(editor_bot): editor_stack, editor, qtbot = editor_bot # Move second and third lines up. editor.go_to_line(2) cursor = editor.textCursor() cursor.movePosition(QTextCursor.Down, QTextCursor.KeepAnchor) cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor) editor.setTextCursor(cursor) editor.move_line_up() expected_new_text = ('print(a)\n' '\n' 'a = 1\n' 'x = 2\n') assert editor.toPlainText() == expected_new_text # Move first and second lines up (to test already at top condition). editor.move_line_up() assert editor.toPlainText() == expected_new_text def test_move_multiple_lines_down(editor_bot): editor_stack, editor, qtbot = editor_bot # Move third and fourth lines down. editor.go_to_line(3) cursor = editor.textCursor() cursor.movePosition(QTextCursor.Down, QTextCursor.KeepAnchor) cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor) editor.setTextCursor(cursor) editor.move_line_down() expected_new_text = ('a = 1\n' 'print(a)\n' '\n' '\n' 'x = 2') assert editor.toPlainText() == expected_new_text # Move fourht and fifth lines down (to test already at bottom condition). editor.move_line_down() assert editor.toPlainText() == expected_new_text def test_run_top_line(editor_bot): editor_stack, editor, qtbot = editor_bot editor.go_to_line(1) # line number is one based editor.move_cursor(3) with qtbot.waitSignal(editor_stack.exec_in_extconsole) as blocker: editor_stack.run_selection() assert blocker.signal_triggered assert blocker.args[0] == 'a = 1' # check cursor moves to start of next line; note line number is zero based assert editor.get_cursor_line_column() == (1, 0) def test_run_last_nonempty_line(editor_bot): editor_stack, editor, qtbot = editor_bot editor.go_to_line(4) with qtbot.waitSignal(editor_stack.exec_in_extconsole) as blocker: editor_stack.run_selection() assert blocker.signal_triggered assert blocker.args[0] == 'x = 2' assert editor.get_cursor_line_column() == (4, 0) # check cursor moves down def test_run_empty_line_in_middle(editor_bot): editor_stack, editor, qtbot = editor_bot editor.go_to_line(3) with qtbot.assertNotEmitted(editor_stack.exec_in_extconsole): editor_stack.run_selection() assert editor.get_cursor_line_column() == (3, 0) # check cursor moves down def test_run_last_line_when_empty(editor_bot): editor_stack, editor, qtbot = editor_bot with qtbot.assertNotEmitted(editor_stack.exec_in_extconsole): editor_stack.run_selection() # check cursor doesn't move assert editor.get_cursor_line_column() == (4, 0) def test_run_last_line_when_nonempty(editor_bot): editor_stack, editor, qtbot = editor_bot editor.stdkey_backspace() # delete empty line at end old_text = editor.toPlainText() with qtbot.waitSignal(editor_stack.exec_in_extconsole) as blocker: editor_stack.run_selection() assert blocker.signal_triggered assert blocker.args[0] == 'x = 2' expected_new_text = old_text + editor.get_line_separator() # check blank line got added assert editor.toPlainText() == expected_new_text assert editor.get_cursor_line_column() == (4, 0) # check cursor moves down def test_find_replace_case_sensitive(qtbot): editor_stack, editor = setup_editor(qtbot) editor_stack.find_widget.case_button.setChecked(True) text = ' test \nTEST \nTest \ntesT ' editor.set_text(text) editor_stack.find_widget.search_text.add_text('test') editor_stack.find_widget.replace_text.add_text('pass') editor_stack.find_widget.replace_find() editor_stack.find_widget.replace_find() editor_stack.find_widget.replace_find() editor_stack.find_widget.replace_find() editor_text = editor.toPlainText() assert editor_text == ' pass \nTEST \nTest \ntesT ' def test_replace_current_selected_line(editor_find_replace_bot): editor_stack, editor, finder, qtbot = editor_find_replace_bot expected_new_text = ('ham bacon\n' 'spam sausage\n' 'spam egg') old_text = editor.toPlainText() finder.show() finder.show_replace() qtbot.keyClicks(finder.search_text, 'spam') qtbot.keyClicks(finder.replace_text, 'ham') qtbot.keyPress(finder.replace_text, Qt.Key_Return) assert editor.toPlainText()[0:-1] == expected_new_text def test_replace_enter_press(editor_find_replace_bot): """Test advance forward pressing Enter, and backwards with Shift+Enter.""" editor_stack, editor, finder, qtbot = editor_find_replace_bot text = ' \nspam \nspam \nspam ' editor.set_text(text) finder.show() finder.search_text.add_text('spam') # search forward qtbot.keyPress(finder.search_text, Qt.Key_Return) assert editor.get_cursor_line_column() == (1,4) qtbot.keyPress(finder.search_text, Qt.Key_Return) assert editor.get_cursor_line_column() == (2,4) qtbot.keyPress(finder.search_text, Qt.Key_Return) assert editor.get_cursor_line_column() == (3,4) # search backwards qtbot.keyPress(finder.search_text, Qt.Key_Return, modifier=Qt.ShiftModifier) assert editor.get_cursor_line_column() == (2,4) qtbot.keyPress(finder.search_text, Qt.Key_Return, modifier=Qt.ShiftModifier) assert editor.get_cursor_line_column() == (1,4) qtbot.keyPress(finder.search_text, Qt.Key_Return, modifier=Qt.ShiftModifier) assert editor.get_cursor_line_column() == (3,4) def test_replace_plain_regex(editor_find_replace_bot): """Test that regex reserved characters are displayed as plain text.""" editor_stack, editor, finder, qtbot = editor_find_replace_bot expected_new_text = ('.\\[()]*test bacon\n' 'spam sausage\n' 'spam egg') finder.show() finder.show_replace() qtbot.keyClicks(finder.search_text, 'spam') qtbot.keyClicks(finder.replace_text, '.\[()]*test') qtbot.keyPress(finder.replace_text, Qt.Key_Return) assert editor.toPlainText()[0:-1] == expected_new_text def test_replace_invalid_regex(editor_find_replace_bot): """Assert that replacing an invalid regexp does nothing.""" editor_stack, editor, finder, qtbot = editor_find_replace_bot old_text = editor.toPlainText() finder.show() finder.show_replace() qtbot.keyClicks(finder.search_text, '\\') qtbot.keyClicks(finder.replace_text, 'anything') if not finder.re_button.isChecked(): qtbot.mouseClick(finder.re_button, Qt.LeftButton) qtbot.mouseClick(finder.replace_button, Qt.LeftButton) assert editor.toPlainText() == old_text qtbot.mouseClick(finder.replace_sel_button, Qt.LeftButton) assert editor.toPlainText() == old_text qtbot.mouseClick(finder.replace_all_button, Qt.LeftButton) assert editor.toPlainText() == old_text def test_selection_escape_characters(editor_find_replace_bot): editor_stack, editor, finder, qtbot = editor_find_replace_bot expected_new_text = ('spam bacon\n' 'spam sausage\n' 'spam egg\n' '\\n \\t some escape characters') qtbot.keyClicks(editor, '\\n \\t escape characters') finder.show() finder.show_replace() qtbot.keyClicks(finder.search_text, 'escape') qtbot.keyClicks(finder.replace_text, 'some escape') # Select last line cursor = editor.textCursor() cursor.select(QTextCursor.LineUnderCursor) assert cursor.selection().toPlainText() == "\\n \\t escape characters" #replace finder.replace_find_selection() assert editor.toPlainText() == expected_new_text def test_advance_cell(editor_cells_bot): editor_stack, editor, qtbot = editor_cells_bot # cursor at the end of the file assert editor.get_cursor_line_column() == (10, 0) # advance backwards to the begining of the 3rd cell editor_stack.advance_cell(reverse=True) assert editor.get_cursor_line_column() == (6, 0) # advance backwards to 2nd cell editor_stack.advance_cell(reverse=True) assert editor.get_cursor_line_column() == (3, 0) # advance backwards to 1st cell editor_stack.advance_cell(reverse=True) assert editor.get_cursor_line_column() == (0, 0) # advance to 2nd cell editor_stack.advance_cell() assert editor.get_cursor_line_column() == (3, 0) # advance to 3rd cell editor_stack.advance_cell() assert editor.get_cursor_line_column() == (6, 0) @pytest.mark.skipif(PY2, reason="Python2 does not support unicode very well") def test_get_current_word(base_editor_bot): """Test getting selected valid python word.""" editor_stack, qtbot = base_editor_bot text = ('some words with non-ascii characters\n' 'niño\n' 'garçon\n' 'α alpha greek\n' '123valid_python_word') finfo = editor_stack.new('foo.py', 'utf-8', text) qtbot.addWidget(editor_stack) editor = finfo.editor editor.go_to_line(1) # Select some editor.moveCursor(QTextCursor.EndOfWord, QTextCursor.KeepAnchor) assert 'some' == editor.textCursor().selectedText() assert editor.get_current_word() == 'some' # Select niño editor.go_to_line(2) editor.moveCursor(QTextCursor.EndOfWord, QTextCursor.KeepAnchor) assert 'niño' == editor.textCursor().selectedText() assert editor.get_current_word() == 'niño' # Select garçon editor.go_to_line(3) editor.moveCursor(QTextCursor.EndOfWord, QTextCursor.KeepAnchor) assert 'garçon' == editor.textCursor().selectedText() assert editor.get_current_word() == 'garçon' # Select α editor.go_to_line(4) editor.moveCursor(QTextCursor.EndOfWord, QTextCursor.KeepAnchor) assert 'α' == editor.textCursor().selectedText() assert editor.get_current_word() == 'α' # Select valid_python_word, should search first valid python word editor.go_to_line(5) editor.moveCursor(QTextCursor.EndOfWord, QTextCursor.KeepAnchor) assert '123valid_python_word' == editor.textCursor().selectedText() assert editor.get_current_word() == 'valid_python_word' def test_editor_splitter_init(editor_splitter_bot): """"Test EditorSplitter.__init__.""" es = editor_splitter_bot assert es.orientation() == Qt.Horizontal assert es.testAttribute(Qt.WA_DeleteOnClose) assert not es.childrenCollapsible() assert not es.toolbar_list assert not es.menu_list assert es.register_editorstack_cb == es.plugin.register_editorstack assert es.unregister_editorstack_cb == es.plugin.unregister_editorstack # No menu actions in parameter call. assert not es.menu_actions # EditorStack adds its own menu actions to the existing actions. assert es.editorstack.menu_actions assert isinstance(es.editorstack, EditorStack) es.plugin.register_editorstack.assert_called_with(es.editorstack) es.plugin.unregister_editorstack.assert_not_called() es.plugin.clone_editorstack.assert_not_called() assert es.count() == 1 assert es.widget(0) == es.editorstack def test_tab_keypress_properly_caught_find_replace(editor_find_replace_bot): """Check that tab works in find/replace dialog. Regression test #3674. Mock test—more isolated but less flimsy.""" editor_stack, editor, finder, qtbot = editor_find_replace_bot text = ' \nspam \nspam \nspam ' editor.set_text(text) finder.show() finder.show_replace() finder.focusNextChild = MagicMock(name="focusNextChild") qtbot.keyPress(finder.search_text, Qt.Key_Tab) finder.focusNextChild.assert_called_once_with() @flaky(max_runs=3) @pytest.mark.skipif(platform.startswith('linux'), reason="This test fails on Linux, for unknown reasons.") def test_tab_moves_focus_from_search_to_replace(editor_find_replace_bot): """Check that tab works in find/replace dialog. Regression test #3674. "Real world" test—more comprehensive but potentially less robust.""" editor_stack, editor, finder, qtbot = editor_find_replace_bot text = ' \nspam \nspam \nspam ' editor.set_text(text) finder.show() finder.show_replace() qtbot.wait(100) finder.search_text.setFocus() qtbot.wait(100) assert finder.search_text.hasFocus() assert not finder.replace_text.hasFocus() qtbot.keyPress(finder.search_text, Qt.Key_Tab) qtbot.wait(100) assert not finder.search_text.hasFocus() assert finder.replace_text.hasFocus() if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/widgets/tests/test_pydocgui.py0000664000175000017500000000107713156676664023225 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for pydocgui.py """ # Test library imports import pytest # Local imports from spyder.widgets.pydocgui import PydocBrowser @pytest.fixture def setup_pydocbrowser(qtbot): """Set up pydocbrowser.""" widget = PydocBrowser(None) qtbot.addWidget(widget) return widget def test_pydocbrowser(qtbot): """Run Pydoc Browser.""" browser = setup_pydocbrowser(qtbot) assert browser if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/widgets/tests/test_save.py0000664000175000017500000002734413224121062022312 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for EditorStack save methods. """ # Standard library imports try: from unittest.mock import Mock except ImportError: from mock import Mock # Python 2 # Third party imports import pytest # Local imports from spyder.widgets import editor # Helpers # -------------------------------- def add_files(editorstack): editorstack.close_action.setEnabled(False) editorstack.set_introspector(Mock()) editorstack.set_find_widget(Mock()) editorstack.set_io_actions(Mock(), Mock(), Mock(), Mock()) editorstack.new('foo.py', 'utf-8', 'a = 1\n' 'print(a)\n' '\n' 'x = 2') editorstack.new('secondtab.py', 'utf-8', 'print(spam)') with open(__file__) as f: text = f.read() editorstack.new(__file__, 'utf-8', text) # Qt Test Fixtures # -------------------------------- @pytest.fixture def base_editor_bot(qtbot): editor_stack = editor.EditorStack(None, []) editor_stack.set_introspector(Mock()) editor_stack.set_find_widget(Mock()) editor_stack.set_io_actions(Mock(), Mock(), Mock(), Mock()) return editor_stack, qtbot @pytest.fixture def editor_bot(base_editor_bot, request): """ Set up EditorStack with CodeEditors containing some Python code. The cursor is at the empty line below the code. """ editor_stack, qtbot = base_editor_bot show_save_dialog = request.node.get_marker('show_save_dialog') if show_save_dialog: editor_stack.save_dialog_on_tests = True qtbot.addWidget(editor_stack) add_files(editor_stack) return editor_stack, qtbot @pytest.fixture def editor_splitter_bot(qtbot): """Create editor splitter.""" es = editor_splitter = editor.EditorSplitter(None, Mock(), [], first=True) qtbot.addWidget(es) es.show() yield es es.destroy() @pytest.fixture def editor_splitter_layout_bot(editor_splitter_bot): """Create editor splitter for testing layouts.""" es = editor_splitter_bot es.plugin.clone_editorstack.side_effect = add_files # Setup editor info for this EditorStack. add_files(es.editorstack) return es # Tests # ------------------------------- @pytest.mark.show_save_dialog def test_save_if_changed(editor_bot, mocker): """Test EditorStack.save_if_changed().""" editor_stack, qtbot = editor_bot save_if_changed = editor_stack.save_if_changed mocker.patch.object(editor.QMessageBox, 'exec_') mocker.patch.object(editor_stack, 'save') editor_stack.save.return_value = True # No file changed - returns True. editor_stack.data[0].editor.document().setModified(False) editor_stack.data[1].editor.document().setModified(False) editor_stack.data[2].editor.document().setModified(False) assert save_if_changed() is True assert not editor_stack.save.called editor_stack.data[0].editor.document().setModified(True) editor_stack.data[1].editor.document().setModified(True) editor_stack.data[2].editor.document().setModified(True) # Cancel button - returns False. editor.QMessageBox.exec_.return_value = editor.QMessageBox.Cancel assert save_if_changed(index=0, cancelable=True) is False assert not editor_stack.save.called assert editor_stack.tabs.currentIndex() == 0 # Yes button - return value from save(). editor.QMessageBox.exec_.return_value = editor.QMessageBox.Yes assert save_if_changed(index=0, cancelable=True) is True assert editor_stack.save.called # YesToAll button - if any save() fails, then return False. editor_stack.save.reset_mock() editor.QMessageBox.exec_.return_value = editor.QMessageBox.YesToAll assert save_if_changed() is True assert editor_stack.save.call_count == 3 # No button - returns True. editor_stack.save.reset_mock() editor.QMessageBox.exec_.return_value = editor.QMessageBox.No assert save_if_changed(index=0, cancelable=True) is True assert not editor_stack.save.called # NoToAll button - returns True. editor_stack.save.reset_mock() editor.QMessageBox.exec_.return_value = editor.QMessageBox.NoToAll assert save_if_changed() is True assert not editor_stack.save.called # Tempfile doesn't show message box - always calls save(). editor.QMessageBox.exec_.reset_mock() editor_stack.set_tempfile_path(__file__) editor_stack.save.return_value = False assert save_if_changed(index=2, cancelable=True) is False assert editor_stack.save.called editor.QMessageBox.exec_.assert_not_called() def test_save(editor_bot, mocker): """Test EditorStack.save().""" editor_stack, qtbot = editor_bot save = editor_stack.save mocker.patch.object(editor.QMessageBox, 'exec_') mocker.patch.object(editor.os.path, 'isfile') mocker.patch.object(editor.encoding, 'write') mocker.patch.object(editor_stack, 'save_as') save_file_saved = editor_stack.file_saved editor_stack.file_saved = Mock() editor.encoding.write.return_value = 'utf-8' # Not modified and not newly created - don't write. editor_stack.data[0].editor.document().setModified(False) editor_stack.data[0].newly_created = False assert save(index=0) is True assert not editor.encoding.write.called # File modified. editor_stack.data[0].editor.document().setModified(True) # File not saved yet - call save_as(). editor.os.path.isfile.return_value = False editor_stack.save_as.return_value = 'save_as_called' assert save(index=0) == 'save_as_called' editor_stack.save_as.assert_called_with(index=0) assert not editor.encoding.write.called # Force save. editor.os.path.isfile.return_value = True assert save(index=0, force=True) assert editor.encoding.write.called == 1 editor_stack.file_saved.emit.assert_called_with(str(id(editor_stack)), 'foo.py', 'foo.py') editor_stack.file_saved = save_file_saved def test_file_saved_in_other_editorstack(editor_splitter_layout_bot): """Test EditorStack.file_saved_in_other_editorstack().""" es = editor_splitter_layout_bot es.split() # Represents changed editor stack. panel1 = es.editorstack # Represents split editor stack. panel2 = es.widget(1).editorstack # Tabs match. for i in range(3): assert panel1.data[i].filename == panel2.data[i].filename # Rearrange tabs on first panel so that tabs aren't the same anymore. panel1.tabs.tabBar().moveTab(0, 1) assert panel1.data[0].filename == panel2.data[1].filename assert panel1.data[1].filename == panel2.data[0].filename assert panel1.data[2].filename == panel2.data[2].filename # Call file_saved_in_other_editorstack to align stacks. panel2.file_saved_in_other_editorstack(panel1.data[0].filename, panel1.data[0].filename) panel2.file_saved_in_other_editorstack(panel1.data[1].filename, panel1.data[1].filename) # Originally this test showed that using index as an arg instead # of the original_filename would incorrectly update the names on panel2. # See issue 5703. assert panel1.data[0].filename == panel2.data[1].filename assert panel1.data[1].filename == panel2.data[0].filename assert panel1.data[2].filename == panel2.data[2].filename def test_select_savename(editor_bot, mocker): """Test EditorStack.select_savename().""" editor_stack, qtbot = editor_bot select_savename = editor_stack.select_savename mocker.patch.object(editor, 'getsavefilename') save_redirect_stdio = editor_stack.redirect_stdio editor_stack.redirect_stdio = Mock() # Cancel selection. editor.getsavefilename.return_value = ('', '') assert select_savename(__file__) is None # Select same name. editor.getsavefilename.return_value = (__file__, '') assert select_savename(__file__) == __file__ # Select different name. editor.getsavefilename.return_value = ('mytest.py', '') assert select_savename(__file__) == 'mytest.py' # Restore. editor_stack.redirect_stdio = save_redirect_stdio def test_save_as(editor_bot, mocker): """Test EditorStack.save_as().""" editor_stack, qtbot = editor_bot save_as = editor_stack.save_as mocker.patch.object(editor.encoding, 'write') mocker.patch.object(editor_stack, 'save') mocker.patch.object(editor_stack, 'close_file') mocker.patch.object(editor_stack, 'select_savename') mocker.patch.object(editor_stack, 'rename_in_data') mocker.patch.object(editor_stack, 'refresh') save_file_renamed_in_data = editor_stack.file_renamed_in_data editor_stack.file_renamed_in_data = Mock() editor.encoding.write.return_value = 'utf-8' editor_stack.save.return_value = True # No save name. editor_stack.select_savename.return_value = None assert save_as() is False assert not editor_stack.save.called # Save name is in the stack, but not the current index. editor_stack.select_savename.return_value = 'foo.py' editor_stack.close_file.return_value = False assert save_as(index=2) is None assert not editor_stack.save.called # Save name is in the stack, but not the current index. editor_stack.close_file.return_value = True assert save_as(index=2) is True editor_stack.close_file.assert_called_with(0) assert editor_stack.save.called # This index is one less because the tab with the saved name was closed. editor_stack.rename_in_data.assert_called_with(__file__, new_filename='foo.py') assert editor_stack.file_renamed_in_data.emit.called == 1 assert editor_stack.save.called == 1 assert editor_stack.refresh.called == 1 # Restore. editor_stack.file_renamed_in_data = save_file_renamed_in_data def test_save_copy_as(editor_bot, mocker): """Test EditorStack.save_copy as().""" editor_stack, qtbot = editor_bot save_copy_as = editor_stack.save_copy_as mocker.patch.object(editor.QMessageBox, 'exec_') mocker.patch.object(editor.encoding, 'write') mocker.patch.object(editor_stack, 'close_file') mocker.patch.object(editor_stack, 'select_savename') save_plugin_load = editor_stack.plugin_load editor_stack.plugin_load = Mock() editor.encoding.write.return_value = 'utf-8' # No save name. editor_stack.select_savename.return_value = None assert save_copy_as() is False assert not editor.encoding.write.called # Save name is in the stack, but not the current index. editor_stack.select_savename.return_value = 'foo.py' editor_stack.close_file.return_value = False assert save_copy_as(index=2) is None assert not editor.encoding.write.called # Save name is in the stack, but not the current index. editor_stack.close_file.return_value = True assert save_copy_as(index=2) is True editor_stack.close_file.assert_called_with(0) assert editor.encoding.write.called editor_stack.plugin_load.emit.assert_called_with('foo.py') # Restore mocked objects. editor_stack.plugin_load = save_plugin_load def test_save_all(editor_bot, mocker): """Test EditorStack.save_all().""" editor_stack, qtbot = editor_bot save_all = editor_stack.save_all mocker.patch.object(editor_stack, 'save') # Save return value isn't used in save_all. editor_stack.save.return_value = False save_all() assert editor_stack.save.call_count == 3 editor_stack.save.assert_any_call(0) editor_stack.save.assert_any_call(1) editor_stack.save.assert_any_call(2) with pytest.raises(AssertionError): editor_stack.save.assert_any_call(3) if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/widgets/tests/test_status.py0000664000175000017500000000215713156676664022725 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for status.py """ # Test library imports import pytest # Thrid party imports from qtpy.QtWidgets import QMainWindow # Local imports from spyder.widgets.status import (ReadWriteStatus, EOLStatus, EncodingStatus, CursorPositionStatus, MemoryStatus, CPUStatus) @pytest.fixture def setup_status_bar(qtbot): """Set up StatusBarWidget.""" win = QMainWindow() win.setWindowTitle("Status widgets test") win.resize(900, 300) statusbar = win.statusBar() qtbot.addWidget(win) return (win, statusbar) def test_status_bar(qtbot): """Run StatusBarWidget.""" win, statusbar = setup_status_bar(qtbot) swidgets = [] for klass in (ReadWriteStatus, EOLStatus, EncodingStatus, CursorPositionStatus, MemoryStatus, CPUStatus): swidget = klass(win, statusbar) swidgets.append(swidget) assert win assert len(swidgets) == 6 if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/widgets/tests/test_browser.py0000664000175000017500000000117613156676664023065 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for browser.py """ # Test library imports import pytest # Local imports from spyder.widgets.browser import WebBrowser @pytest.fixture def setup_browser(qtbot): """Set up WebBrowser.""" widget = WebBrowser() qtbot.addWidget(widget) return widget def test_browser(qtbot): """Run web browser.""" browser = setup_browser(qtbot) browser.set_home_url('http://www.google.com/') browser.go_home() browser.show() assert browser if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/widgets/tests/test_array_builder.py0000664000175000017500000001450213045506024024176 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for the Numpy Matrix/Array Builder Widget. """ # Third party imports from qtpy.QtCore import Qt from pytestqt import qtbot import pytest # Local imports from spyder.widgets.arraybuilder import NumpyArrayDialog # --- Fixtures # ----------------------------------------------------------------------------- @pytest.fixture def botinline(qtbot): dialog = NumpyArrayDialog(inline=True) qtbot.addWidget(dialog) dialog.show() return qtbot, dialog, dialog.array_widget @pytest.fixture def botinlinefloat(qtbot): dialog = NumpyArrayDialog(inline=True, force_float=True) qtbot.addWidget(dialog) dialog.show() return qtbot, dialog, dialog.array_widget @pytest.fixture def botarray(qtbot): dialog = NumpyArrayDialog(inline=False) qtbot.addWidget(dialog) dialog.show() return qtbot, dialog, dialog.array_widget # --- Tests # ----------------------------------------------------------------------------- def test_array_inline_array(botinline): qtbot, dialog, widget = botinline qtbot.keyClicks(widget, '1 2 3 4 5 6') qtbot.keyPress(widget, Qt.Key_Return) value = dialog.text() assert value == 'np.array([[1, 2, 3],\n [4, 5, 6]])' def test_array_inline_matrix(botinline): qtbot, dialog, widget = botinline qtbot.keyClicks(widget, '4 5 6 7 8 9') qtbot.keyPress(widget, Qt.Key_Return, modifier=Qt.ControlModifier) value = dialog.text() assert value == 'np.matrix([[4, 5, 6],\n [7, 8, 9]])' def test_array_inline_array_invalid(botinline): qtbot, dialog, widget = botinline qtbot.keyClicks(widget, '1 2 3 4 5 6 7') qtbot.keyPress(widget, Qt.Key_Return) dialog.update_warning() assert not dialog.is_valid() def test_array_inline_1d_array(botinline): qtbot, dialog, widget = botinline qtbot.keyClicks(widget, '4 5 6') qtbot.keyPress(widget, Qt.Key_Return, modifier=Qt.ControlModifier) value = dialog.text() assert value == 'np.matrix([4, 5, 6])' def test_array_inline_nan_array(botinline): qtbot, dialog, widget = botinline qtbot.keyClicks(widget, '4 nan 6 8 9') qtbot.keyPress(widget, Qt.Key_Return, modifier=Qt.ControlModifier) value = dialog.text() assert value == 'np.matrix([4, np.nan, 6, 8, 9])' def test_array_inline_force_float_array(botinlinefloat): qtbot, dialog, widget = botinlinefloat qtbot.keyClicks(widget, '4 5 6 8 9') qtbot.keyPress(widget, Qt.Key_Return, modifier=Qt.ControlModifier) value = dialog.text() assert value == 'np.matrix([4.0, 5.0, 6.0, 8.0, 9.0])' def test_array_inline_force_float_error_array(botinlinefloat): qtbot, dialog, widget = botinlinefloat qtbot.keyClicks(widget, '4 5 6 a 9') qtbot.keyPress(widget, Qt.Key_Return, modifier=Qt.ControlModifier) value = dialog.text() assert value == 'np.matrix([4.0, 5.0, 6.0, a, 9.0])' def test_array_table_array(botarray): qtbot, dialog, widget = botarray qtbot.keyClick(widget, Qt.Key_1) qtbot.keyClick(widget, Qt.Key_Tab) qtbot.keyClick(widget, Qt.Key_2) qtbot.keyClick(widget, Qt.Key_Tab) qtbot.keyClick(widget, Qt.Key_Backtab) # Hack: in the tests the selected cell is wrong qtbot.keyClick(widget, Qt.Key_3) qtbot.keyClick(widget, Qt.Key_Tab) qtbot.keyClick(widget, Qt.Key_4) qtbot.keyClick(widget, Qt.Key_Tab) qtbot.keyClick(widget, Qt.Key_5) qtbot.keyClick(widget, Qt.Key_Tab) qtbot.keyClick(widget, Qt.Key_6) qtbot.keyClick(widget, Qt.Key_Tab) # Hack: in the tests the selected cell is wrong qtbot.keyClick(widget, Qt.Key_Return, modifier=Qt.NoModifier) value = dialog.text() assert value == 'np.array([[1, 2, 3],\n [4, 5, 6]])' def test_array_table_matrix(botarray): # analysis:ignore qtbot, dialog, widget = botarray qtbot.keyClick(widget, Qt.Key_1) qtbot.keyClick(widget, Qt.Key_Tab) qtbot.keyClick(widget, Qt.Key_2) qtbot.keyClick(widget, Qt.Key_Tab) qtbot.keyClick(widget, Qt.Key_Backtab) # Hack: in the tests the selected cell is wrong qtbot.keyClick(widget, Qt.Key_3) qtbot.keyClick(widget, Qt.Key_Tab) qtbot.keyClick(widget, Qt.Key_4) qtbot.keyClick(widget, Qt.Key_Tab) qtbot.keyClick(widget, Qt.Key_5) qtbot.keyClick(widget, Qt.Key_Tab) qtbot.keyClick(widget, Qt.Key_6) qtbot.keyClick(widget, Qt.Key_Tab) # Hack: in the tests the selected cell is wrong qtbot.keyClick(widget, Qt.Key_Return, modifier=Qt.ControlModifier) value = dialog.text() assert value == 'np.matrix([[1, 2, 3],\n [4, 5, 6]])' def test_array_table_array_empty_items(botarray): # analysis:ignore qtbot, dialog, widget = botarray qtbot.keyClick(widget, Qt.Key_Tab) qtbot.keyClick(widget, Qt.Key_2) qtbot.keyClick(widget, Qt.Key_Tab) qtbot.keyClick(widget, Qt.Key_Backtab) # Hack: in the tests the selected cell is wrong qtbot.keyClick(widget, Qt.Key_3) qtbot.keyClick(widget, Qt.Key_Tab) qtbot.keyClick(widget, Qt.Key_Tab) qtbot.keyClick(widget, Qt.Key_5) qtbot.keyClick(widget, Qt.Key_Tab) qtbot.keyClick(widget, Qt.Key_6) qtbot.keyClick(widget, Qt.Key_Tab) # Hack: in the tests the selected cell is wrong qtbot.keyClick(widget, Qt.Key_Return, modifier=Qt.NoModifier) value = dialog.text() assert value == 'np.array([[0, 2, 3],\n [0, 5, 6]])' def test_array_table_array_spaces_in_item(botarray): # analysis:ignore qtbot, dialog, widget = botarray qtbot.keyClicks(widget, ' ') qtbot.keyClick(widget, Qt.Key_Tab) qtbot.keyClick(widget, Qt.Key_2) qtbot.keyClick(widget, Qt.Key_Tab) qtbot.keyClick(widget, Qt.Key_Backtab) qtbot.keyClick(widget, Qt.Key_3) qtbot.keyClick(widget, Qt.Key_Tab) qtbot.keyClick(widget, Qt.Key_Tab) qtbot.keyClick(widget, Qt.Key_5) qtbot.keyClick(widget, Qt.Key_Tab) qtbot.keyClick(widget, Qt.Key_6) qtbot.keyClick(widget, Qt.Key_Tab) # Hack: in the tests the selected cell is wrong qtbot.keyClick(widget, Qt.Key_Return, modifier=Qt.NoModifier) value = dialog.text() assert value == 'np.array([[0, 2, 3],\n [0, 5, 6]])' def test_array_table_matrix_empty(botarray): # analysis:ignore qtbot, dialog, widget = botarray qtbot.keyClick(widget, Qt.Key_Return, modifier=Qt.NoModifier) value = dialog.text() assert value == '' spyder-3.2.6/spyder/widgets/tests/test_pathmanager.py0000664000175000017500000001053613224121062023636 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for pathmanager.py """ # Standard library imports import sys import os # Test library imports import pytest from qtpy import PYQT4 from qtpy.QtCore import Qt # Local imports from spyder.py3compat import PY3 from spyder.widgets import pathmanager as pathmanager_mod from spyder.utils.programs import is_module_installed @pytest.fixture def setup_pathmanager(qtbot, parent=None, pathlist=None, ro_pathlist=None, sync=True): """Set up PathManager.""" widget = pathmanager_mod.PathManager(None, pathlist=pathlist, ro_pathlist=ro_pathlist) qtbot.addWidget(widget) return widget @pytest.mark.skipif(PY3 and PYQT4, reason="It segfaults frequently") def test_pathmanager(qtbot): """Run PathManager test""" pathmanager = setup_pathmanager(qtbot, None, pathlist=sys.path[:-10], ro_pathlist=sys.path[-10:]) pathmanager.show() assert pathmanager def test_check_uncheck_path(qtbot): """ Test that checking and unchecking a path in the PathManager correctly update the not active path list. """ pathmanager = setup_pathmanager(qtbot, None, pathlist=sys.path[:-10], ro_pathlist=sys.path[-10:]) # Assert that all paths are checked. for row in range(pathmanager.listwidget.count()): assert pathmanager.listwidget.item(row).checkState() == Qt.Checked # Uncheck a path and assert that it is added to the not active path list. pathmanager.listwidget.item(3).setCheckState(Qt.Unchecked) assert pathmanager.not_active_pathlist == [sys.path[3]] # Check an uncheked path and assert that it is removed from the not active # path list. pathmanager.listwidget.item(3).setCheckState(Qt.Checked) assert pathmanager.not_active_pathlist == [] @pytest.mark.skipif(os.name != 'nt' or not is_module_installed('win32con'), reason=("This feature is not applicable for Unix " "systems and pywin32 is needed")) def test_synchronize_with_PYTHONPATH(qtbot, mocker): pathmanager = setup_pathmanager(qtbot, None, pathlist=['path1', 'path2', 'path3'], ro_pathlist=['path4', 'path5', 'path6']) # Import here to prevent an ImportError when testing on unix systems from spyder.utils.environ import (get_user_env, set_user_env, listdict2envdict) # Store PYTHONPATH original state env = get_user_env() original_pathlist = env.get('PYTHONPATH', []) # Mock the dialog window and answer "Yes" to clear contents of PYTHONPATH # before adding Spyder's path list mocker.patch.object(pathmanager_mod.QMessageBox, 'question', return_value=pathmanager_mod.QMessageBox.Yes) # Assert that PYTHONPATH is synchronized correctly with Spyder's path list pathmanager.synchronize() expected_pathlist = ['path1', 'path2', 'path3', 'path4', 'path5', 'path6'] env = get_user_env() assert env['PYTHONPATH'] == expected_pathlist # Uncheck 'path2' and assert that it is removed from PYTHONPATH when it # is synchronized with Spyder's path list pathmanager.listwidget.item(1).setCheckState(Qt.Unchecked) pathmanager.synchronize() expected_pathlist = ['path1', 'path3', 'path4', 'path5', 'path6'] env = get_user_env() assert env['PYTHONPATH'] == expected_pathlist # Mock the dialog window and answer "No" to clear contents of PYTHONPATH # before adding Spyder's path list mocker.patch.object(pathmanager_mod.QMessageBox, 'question', return_value=pathmanager_mod.QMessageBox.No) # Uncheck 'path3' and assert that it is kept in PYTHONPATH when it # is synchronized with Spyder's path list pathmanager.listwidget.item(2).setCheckState(Qt.Unchecked) pathmanager.synchronize() expected_pathlist = ['path3', 'path1', 'path4', 'path5', 'path6'] env = get_user_env() assert env['PYTHONPATH'] == expected_pathlist # Restore PYTHONPATH to its original state env['PYTHONPATH'] = original_pathlist set_user_env(listdict2envdict(env)) if __name__ == "__main__": pytest.main([os.path.basename(__file__)]) spyder-3.2.6/spyder/widgets/tests/test_codeeditor.py0000664000175000017500000000575613224740762023516 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # # Third party imports from qtpy.QtCore import Qt from qtpy.QtGui import QFont, QTextCursor from pytestqt import qtbot import pytest # Local imports from spyder.widgets.editor import codeeditor # --- Fixtures # ----------------------------------------------------------------------------- @pytest.fixture def editorbot(qtbot): widget = codeeditor.CodeEditor(None) widget.setup_editor(linenumbers=True, markers=True, tab_mode=False, font=QFont("Courier New", 10), show_blanks=True, color_scheme='Zenburn') widget.setup_editor(language='Python') qtbot.addWidget(widget) widget.show() return qtbot, widget # --- Tests # ----------------------------------------------------------------------------- # testing lowercase transformation functionality def test_editor_upper_to_lower(editorbot): qtbot, widget = editorbot text = 'UPPERCASE' widget.set_text(text) cursor = widget.textCursor() cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor) widget.setTextCursor(cursor) widget.transform_to_lowercase() new_text = widget.get_text('sof', 'eof') assert text != new_text def test_editor_lower_to_upper(editorbot): qtbot, widget = editorbot text = 'uppercase' widget.set_text(text) cursor = widget.textCursor() cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor) widget.setTextCursor(cursor) widget.transform_to_uppercase() new_text = widget.get_text('sof', 'eof') assert text != new_text def test_editor_complete_backet(editorbot): qtbot, editor = editorbot editor.textCursor().insertText('foo') qtbot.keyClicks(editor, '(') assert editor.toPlainText() == 'foo()' assert editor.textCursor().columnNumber() == 4 def test_editor_complete_bracket_nested(editorbot): qtbot, editor = editorbot editor.textCursor().insertText('foo(bar)') editor.move_cursor(-1) qtbot.keyClicks(editor, '(') assert editor.toPlainText() == 'foo(bar())' assert editor.textCursor().columnNumber() == 8 def test_editor_bracket_closing(editorbot): qtbot, editor = editorbot editor.textCursor().insertText('foo(bar(x') qtbot.keyClicks(editor, ')') assert editor.toPlainText() == 'foo(bar(x)' assert editor.textCursor().columnNumber() == 10 qtbot.keyClicks(editor, ')') assert editor.toPlainText() == 'foo(bar(x))' assert editor.textCursor().columnNumber() == 11 # same ')' closing with existing brackets starting at 'foo(bar(x|))' editor.move_cursor(-2) qtbot.keyClicks(editor, ')') assert editor.toPlainText() == 'foo(bar(x))' assert editor.textCursor().columnNumber() == 10 qtbot.keyClicks(editor, ')') assert editor.toPlainText() == 'foo(bar(x))' assert editor.textCursor().columnNumber() == 11 spyder-3.2.6/spyder/widgets/tests/data/0000775000175000017500000000000013225025007020645 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/widgets/tests/data/ham.txt0000664000175000017500000000024613224121062022152 0ustar carloscarlos00000000000000ham(N) -> ham(N, 1, 1). ham(0, F1, _) -> F1; ham(N, F1, F2) when N > 0 -> ham(N - 1, F2, F2 + F1). Eggs = 10. Sausage = atom. HaM = false. Ham = Eggs + Sausage.spyder-3.2.6/spyder/widgets/tests/data/spam.cpp0000664000175000017500000000022213211142273022305 0ustar carloscarlos00000000000000#include #include namespace eggs; typedef struct spam { int sausage; } spam; int spam(*spam ptr) { printf("spam\n"); }spyder-3.2.6/spyder/widgets/tests/data/spam.txt0000664000175000017500000000006513211142273022347 0ustar carloscarlos00000000000000spam spam ham eggs sausage lorem ipsum sit dolor spamspyder-3.2.6/spyder/widgets/tests/test_helperwidgets.py0000664000175000017500000000164413156676664024250 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for helperwidgets.py """ # Test library imports import pytest # Third party imports from qtpy.QtWidgets import QMessageBox # Local imports from spyder.widgets.helperwidgets import MessageCheckBox @pytest.fixture def setup_messagecheckbox(qtbot): """Set up MessageCheckBox.""" widget = MessageCheckBox() qtbot.addWidget(widget) return widget def test_messagecheckbox(qtbot): """Run Message Checkbox.""" box = setup_messagecheckbox(qtbot) box.setWindowTitle("Spyder updates") box.setText("Testing checkbox") box.set_checkbox_text("Check for updates on startup?") box.setStandardButtons(QMessageBox.Ok) box.setDefaultButton(QMessageBox.Ok) box.setIcon(QMessageBox.Information) box.show() assert box if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/widgets/tests/test_explorer.py0000664000175000017500000000170713156676664023242 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for explorer.py """ # Test library imports import pytest # Local imports from spyder.widgets.explorer import FileExplorerTest, ProjectExplorerTest @pytest.fixture def setup_file_explorer(qtbot): """Set up FileExplorerTest.""" widget = FileExplorerTest() qtbot.addWidget(widget) return widget @pytest.fixture def setup_project_explorer(qtbot): """Set up FileExplorerTest.""" widget = ProjectExplorerTest() qtbot.addWidget(widget) return widget def test_file_explorer(qtbot): """Run FileExplorerTest.""" fe = setup_file_explorer(qtbot) fe.resize(640, 480) fe.show() assert fe def test_project_explorer(qtbot): """Run ProjectExplorerTest.""" pe = setup_project_explorer(qtbot) pe.resize(640, 480) pe.show() assert pe if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/widgets/tests/__init__.py0000664000175000017500000000050213156676664022072 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Copyright (c) Spyder Project Contributors # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Tests.""" spyder-3.2.6/spyder/widgets/tests/test_dependencies.py0000664000175000017500000000152013224740762024004 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for dependencies.py """ # Test library imports import pytest # Local imports from spyder.widgets.dependencies import DependenciesDialog from spyder import dependencies @pytest.fixture def setup_dependencies(qtbot): """Set up dependency widget test.""" widget = DependenciesDialog(None) qtbot.addWidget(widget) return widget def test_dependencies(qtbot): """Run dependency widget test.""" # Test sample dependencies.add("zmq", "Run introspection services", ">=10.0") dependencies.add("foo", "Non-existent module", ">=1.0") dlg = setup_dependencies(qtbot) dlg.set_data(dependencies.DEPENDENCIES) dlg.show() assert dlg if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/widgets/helperwidgets.py0000664000175000017500000002033113224121062022006 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Helper widgets. """ # Third party imports from qtpy import PYQT5 from qtpy.QtCore import QPoint, QSize, Qt from qtpy.QtGui import QAbstractTextDocumentLayout, QPainter, QTextDocument from qtpy.QtWidgets import (QApplication, QCheckBox, QLineEdit, QMessageBox, QSpacerItem, QStyle, QStyledItemDelegate, QStyleOptionViewItem, QToolButton, QToolTip, QVBoxLayout) # Local imports from spyder.config.base import _ from spyder.utils import icon_manager as ima from spyder.utils.qthelpers import get_std_icon class HelperToolButton(QToolButton): """Subclasses QToolButton, to provide a simple tooltip on mousedown. """ def __init__(self): QToolButton.__init__(self) self.setIcon(get_std_icon('MessageBoxInformation')) style = """ QToolButton { border: 1px solid grey; padding:0px; border-radius: 2px; background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #f6f7fa, stop: 1 #dadbde); } """ self.setStyleSheet(style) def setToolTip(self, text): self._tip_text = text def toolTip(self): return self._tip_text def mousePressEvent(self, event): QToolTip.hideText() def mouseReleaseEvent(self, event): QToolTip.showText(self.mapToGlobal(QPoint(0, self.height())), self._tip_text) class MessageCheckBox(QMessageBox): """ A QMessageBox derived widget that includes a QCheckBox aligned to the right under the message and on top of the buttons. """ def __init__(self, *args, **kwargs): super(MessageCheckBox, self).__init__(*args, **kwargs) self._checkbox = QCheckBox() # Set layout to include checkbox size = 9 check_layout = QVBoxLayout() check_layout.addItem(QSpacerItem(size, size)) check_layout.addWidget(self._checkbox, 0, Qt.AlignRight) check_layout.addItem(QSpacerItem(size, size)) # Access the Layout of the MessageBox to add the Checkbox layout = self.layout() if PYQT5: layout.addLayout(check_layout, 1, 2) else: layout.addLayout(check_layout, 1, 1) # --- Public API # Methods to access the checkbox def is_checked(self): return self._checkbox.isChecked() def set_checked(self, value): return self._checkbox.setChecked(value) def set_check_visible(self, value): self._checkbox.setVisible(value) def is_check_visible(self): self._checkbox.isVisible() def checkbox_text(self): self._checkbox.text() def set_checkbox_text(self, text): self._checkbox.setText(text) class HTMLDelegate(QStyledItemDelegate): """With this delegate, a QListWidgetItem or a QTableItem can render HTML. Taken from http://stackoverflow.com/a/5443112/2399799 """ def __init__(self, parent, margin=0): super(HTMLDelegate, self).__init__(parent) self._margin = margin def paint(self, painter, option, index): options = QStyleOptionViewItem(option) self.initStyleOption(options, index) style = (QApplication.style() if options.widget is None else options.widget.style()) doc = QTextDocument() doc.setDocumentMargin(self._margin) doc.setHtml(options.text) options.text = "" style.drawControl(QStyle.CE_ItemViewItem, options, painter) ctx = QAbstractTextDocumentLayout.PaintContext() textRect = style.subElementRect(QStyle.SE_ItemViewItemText, options) painter.save() # Adjustments for the file switcher if hasattr(options.widget, 'files_list'): if style.objectName() in ['oxygen', 'qtcurve', 'breeze']: if options.widget.files_list: painter.translate(textRect.topLeft() + QPoint(4, -9)) else: painter.translate(textRect.topLeft()) else: if options.widget.files_list: painter.translate(textRect.topLeft() + QPoint(4, 4)) else: painter.translate(textRect.topLeft() + QPoint(2, 4)) else: painter.translate(textRect.topLeft() + QPoint(0, -3)) doc.documentLayout().draw(painter, ctx) painter.restore() def sizeHint(self, option, index): options = QStyleOptionViewItem(option) self.initStyleOption(options, index) doc = QTextDocument() doc.setHtml(options.text) return QSize(doc.idealWidth(), doc.size().height() - 2) class IconLineEdit(QLineEdit): """Custom QLineEdit that includes an icon representing the validation.""" def __init__(self, *args, **kwargs): super(IconLineEdit, self).__init__(*args, **kwargs) self._status = True self._status_set = True self._valid_icon = ima.icon('todo') self._invalid_icon = ima.icon('warning') self._set_icon = ima.icon('todo_list') self._application_style = QApplication.style().objectName() self._refresh() self._paint_count = 0 self._icon_visible = False def _refresh(self): """After an application style change, the paintEvent updates the custom defined stylesheet. """ padding = self.height() css_base = """QLineEdit {{ border: none; padding-right: {padding}px; }} """ css_oxygen = """QLineEdit {{background: transparent; border: none; padding-right: {padding}px; }} """ if self._application_style == 'oxygen': css_template = css_oxygen else: css_template = css_base css = css_template.format(padding=padding) self.setStyleSheet(css) self.update() def hide_status_icon(self): """Show the status icon.""" self._icon_visible = False self.repaint() self.update() def show_status_icon(self): """Hide the status icon.""" self._icon_visible = True self.repaint() self.update() def update_status(self, value, value_set): """Update the status and set_status to update the icons to display.""" self._status = value self._status_set = value_set self.repaint() self.update() def paintEvent(self, event): """Qt Override. Include a validation icon to the left of the line edit. """ super(IconLineEdit, self).paintEvent(event) painter = QPainter(self) rect = self.geometry() space = int((rect.height())/6) h = rect.height() - space w = rect.width() - h if self._icon_visible: if self._status and self._status_set: pixmap = self._set_icon.pixmap(h, h) elif self._status: pixmap = self._valid_icon.pixmap(h, h) else: pixmap = self._invalid_icon.pixmap(h, h) painter.drawPixmap(w, space, pixmap) application_style = QApplication.style().objectName() if self._application_style != application_style: self._application_style = application_style self._refresh() # Small hack to gurantee correct padding on Spyder start if self._paint_count < 5: self._paint_count += 1 self._refresh() def test_msgcheckbox(): from spyder.utils.qthelpers import qapplication app = qapplication() box = MessageCheckBox() box.setWindowTitle(_("Spyder updates")) box.setText("Testing checkbox") box.set_checkbox_text("Check for updates on startup?") box.setStandardButtons(QMessageBox.Ok) box.setDefaultButton(QMessageBox.Ok) box.setIcon(QMessageBox.Information) box.exec_() if __name__ == '__main__': test_msgcheckbox() spyder-3.2.6/spyder/widgets/projects/0000775000175000017500000000000013225025007020423 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/widgets/projects/type/0000775000175000017500000000000013225025007021404 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/widgets/projects/type/python.py0000664000175000017500000000535313026261006023305 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Copyright © Spyder Project Contributors # # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) # ----------------------------------------------------------------------------- """Python project type""" import os import os.path as osp from spyder.config.base import _ from spyder.widgets.projects.type import EmptyProject class PythonProject(EmptyProject): """Python project.""" PROJECT_TYPE_NAME = _('Python project') IGNORE_FILE = """""" def _get_relative_pythonpath(self): """Return PYTHONPATH list as relative paths""" # Workaround to replace os.path.relpath (new in Python v2.6): offset = len(self.root_path)+len(os.pathsep) return [path[offset:] for path in self.pythonpath] def _set_relative_pythonpath(self, value): """Set PYTHONPATH list relative paths""" self.pythonpath = [osp.abspath(osp.join(self.root_path, path)) for path in value] relative_pythonpath = property(_get_relative_pythonpath, _set_relative_pythonpath) # --- Python Path def is_in_pythonpath(self, dirname): """Return True if dirname is in project's PYTHONPATH""" return fixpath(dirname) in [fixpath(_p) for _p in self.pythonpath] def get_pythonpath(self): """Return a copy of pythonpath attribute""" return self.pythonpath[:] def set_pythonpath(self, pythonpath): """Set project's PYTHONPATH""" self.pythonpath = pythonpath self.save() def remove_from_pythonpath(self, path): """Remove path from project's PYTHONPATH Return True if path was removed, False if it was not found""" pathlist = self.get_pythonpath() if path in pathlist: pathlist.pop(pathlist.index(path)) self.set_pythonpath(pathlist) return True else: return False def add_to_pythonpath(self, path): """Add path to project's PYTHONPATH Return True if path was added, False if it was already there""" pathlist = self.get_pythonpath() if path in pathlist: return False else: pathlist.insert(0, path) self.set_pythonpath(pathlist) return True class PythonPackageProject(PythonProject): """ """ PROJECT_TYPE_NAME = _('Python package') IGNORE_FILE = """ """ STRUCTURE_TEMPATE = { 'relative_path/test.py': """ test """, 'other/test.py': """ test """, } spyder-3.2.6/spyder/widgets/projects/type/__init__.py0000664000175000017500000002012113224121062023506 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Copyright © Spyder Project Contributors # # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) # ----------------------------------------------------------------------------- """Project types""" import os import os.path as osp from collections import OrderedDict from spyder.config.base import _ from spyder.py3compat import to_text_string from spyder.widgets.projects.config import (ProjectConfig, CODESTYLE, CODESTYLE_DEFAULTS, CODESTYLE_VERSION, WORKSPACE, WORKSPACE_DEFAULTS, WORKSPACE_VERSION, ENCODING, ENCODING_DEFAULTS, ENCODING_VERSION, VCS, VCS_DEFAULTS, VCS_VERSION) class BaseProject(object): """Spyder base project. This base class must not be used directly, but inherited from. It does not assume that python is specific to this project. """ PROJECT_FOLDER = '.spyproject' PROJECT_TYPE_NAME = None IGNORE_FILE = "" CONFIG_SETUP = {WORKSPACE: {'filename': '{0}.ini'.format(WORKSPACE), 'defaults': WORKSPACE_DEFAULTS, 'version': WORKSPACE_VERSION}, CODESTYLE: {'filename': '{0}.ini'.format(CODESTYLE), 'defaults': CODESTYLE_DEFAULTS, 'version': CODESTYLE_VERSION}, ENCODING: {'filename': '{0}.ini'.format(ENCODING), 'defaults': ENCODING_DEFAULTS, 'version': ENCODING_VERSION}, VCS: {'filename': '{0}.ini'.format(VCS), 'defaults': VCS_DEFAULTS, 'version': VCS_VERSION} } def __init__(self, root_path): self.name = None self.root_path = root_path self.open_project_files = [] self.open_non_project_files = [] self.config_files = [] self.CONF = {} # Configuration files self.related_projects = [] # storing project path, not project objects # self.pythonpath = [] self.opened = True self.ioerror_flag = False self.create_project_config_files() # --- Helpers # ------------------------------------------------------------------------- def set_recent_files(self, recent_files): """Set a list of files opened by the project.""" for recent_file in recent_files[:]: if not os.path.isfile(recent_file): recent_files.remove(recent_file) self.CONF[WORKSPACE].set('main', 'recent_files', list(OrderedDict.fromkeys(recent_files))) def get_recent_files(self): """Return a list of files opened by the project.""" recent_files = self.CONF[WORKSPACE].get('main', 'recent_files', default=[]) for recent_file in recent_files[:]: if not os.path.isfile(recent_file): recent_files.remove(recent_file) return list(OrderedDict.fromkeys(recent_files)) def create_project_config_files(self): """ """ dic = self.CONFIG_SETUP for key in dic: name = key filename = dic[key]['filename'] defaults = dic[key]['defaults'] version = dic[key]['version'] self.CONF[key] = ProjectConfig(name, self.root_path, filename, defaults=defaults, load=True, version=version) def get_conf_files(self): """ """ return self.CONF def add_ignore_lines(self, lines): """ """ text = self.IGNORE_FILE for line in lines: text += line self.IGNORE_FILE = text def set_root_path(self, root_path): """Set project root path.""" if self.name is None: self.name = osp.basename(root_path) self.root_path = to_text_string(root_path) config_path = self.__get_project_config_path() if osp.exists(config_path): self.load() else: if not osp.isdir(self.root_path): os.mkdir(self.root_path) self.save() def rename(self, new_name): """Rename project and rename its root path accordingly.""" old_name = self.name self.name = new_name pypath = self.relative_pythonpath # ?? self.root_path = self.root_path[:-len(old_name)]+new_name self.relative_pythonpath = pypath # ?? self.save() def __get_project_config_folder(self): """Return project configuration folder.""" return osp.join(self.root_path, self.PROJECT_FOLDER) def __get_project_config_path(self): """Return project configuration path""" return osp.join(self.root_path, self.CONFIG_NAME) def load(self): """Load project data""" # fname = self.__get_project_config_path() # try: # # Old format (Spyder 2.0-2.1 for Python 2) # with open(fname, 'U') as fdesc: # data = pickle.loads(fdesc.read()) # except (pickle.PickleError, TypeError, UnicodeDecodeError, # AttributeError): # try: # # New format (Spyder >=2.2 for Python 2 and Python 3) # with open(fname, 'rb') as fdesc: # data = pickle.loads(fdesc.read()) # except (IOError, OSError, pickle.PickleError): # self.ioerror_flag = True # return # Compatibilty with old project explorer file format: # if 'relative_pythonpath' not in data: # print("Warning: converting old configuration file " # "for project '%s'" % data['name'], file=STDERR) # self.pythonpath = data['pythonpath'] # data['relative_pythonpath'] = self.relative_pythonpath # for attr in self.CONFIG_ATTR: # setattr(self, attr, data[attr]) # self.save() def save(self): """Save project data""" # data = {} # for attr in self.PROJECT_ATTR: # data[attr] = getattr(self, attr) # try: # with open(self.__get_project_config_path(), 'wb') as fdesc: # pickle.dump(data, fdesc, 2) # except (IOError, OSError): # self.ioerror_flag = True # def delete(self): # """Delete project""" # os.remove(self.__get_project_config_path()) # # # --- Misc. # def get_related_projects(self): # """Return related projects path list""" # return self.related_projects # # def set_related_projects(self, related_projects): # """Set related projects""" # self.related_projects = related_projects # self.save() # # def open(self): # """Open project""" # self.opened = True # self.save() # # def close(self): # """Close project""" # self.opened = False # self.save() # # def is_opened(self): # """Return True if project is opened""" # return self.opened # # def is_file_in_project(self, fname): # """Return True if file *fname* is in one of the project subfolders""" # fixed_root = fixpath(self.root_path) # return fixpath(fname) == fixed_root or\ # fixpath(osp.dirname(fname)).startswith(fixed_root) # # def is_root_path(self, dirname): # """Return True if dirname is project's root path""" # return fixpath(dirname) == fixpath(self.root_path) class EmptyProject(BaseProject): """Empty Project""" PROJECT_TYPE_NAME = _('Empty project') spyder-3.2.6/spyder/widgets/projects/configdialog.py0000664000175000017500000001470313156676664023457 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Copyright © Spyder Project Contributors # # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) # ----------------------------------------------------------------------------- """Configuration dialog for projects""" from qtpy.QtWidgets import QGroupBox, QVBoxLayout from spyder.config.base import _ from spyder.plugins.configdialog import ConfigDialog, GeneralConfigPage from spyder.utils.qthelpers import get_icon from spyder.config.user import NoDefault from spyder.widgets.projects import EmptyProject from spyder.widgets.projects.config import (WORKSPACE, VCS, ENCODING, CODESTYLE) class ProjectPreferences(ConfigDialog): """ """ def __init__(self, parent, project): super(ProjectPreferences, self).__init__() self._main = parent self._project = project self._project_preferences = [WorkspaceConfigPage] #, VersionConfigPage] self.setWindowTitle(_("Project preferences")) self.setWindowIcon(get_icon("configure.png")) self.setup_dialog() def setup_dialog(self): """ """ # Move to spyder.py # dlg = ConfigDialog(self) # dlg.size_change.connect(self.set_prefs_size) # if self.prefs_dialog_size is not None: # dlg.resize(self.prefs_dialog_size) for PrefPageClass in self._project_preferences: widget = PrefPageClass(self, self._main, self._project) widget.initialize() self.add_page(widget) class ProjectConfigPage(GeneralConfigPage): """General config page that redefines the configuration accessors.""" CONF_SECTION = None NAME = None ICON = None def __init__(self, parent, main, project): self._project = project self._conf_files = project.get_conf_files() self._conf = self._conf_files[self.CONF_SECTION] GeneralConfigPage.__init__(self, parent, main) def set_option(self, option, value): """ """ CONF = self._conf CONF.set(self.CONF_SECTION, option, value) def get_option(self, option, default=NoDefault): """" """ CONF = self._conf return CONF.get(self.CONF_SECTION, option, default) class WorkspaceConfigPage(ProjectConfigPage): CONF_SECTION = WORKSPACE NAME = _("General") ICON = "genprefs.png" def setup_page(self): newcb = self.create_checkbox # --- Workspace interface_group = QGroupBox(_("Interface")) restore_data_box = newcb(_("Restore data on startup"), 'restore_data_on_startup') save_data_box = newcb(_("Save data on exit"), 'save_data_on_exit') save_history_box = newcb(_("Save history"), 'save_history') save_non_project_box = newcb(_("Save non project files opened"), 'save_non_project_files') interface_layout = QVBoxLayout() interface_layout.addWidget(restore_data_box) interface_layout.addWidget(save_data_box) interface_layout.addWidget(save_history_box) interface_layout.addWidget(save_non_project_box) interface_group.setLayout(interface_layout) vlayout = QVBoxLayout() vlayout.addWidget(interface_group) vlayout.addStretch(1) self.setLayout(vlayout) def apply_settings(self, options): """ """ pass # TODO: #self.main.apply_settings() class CodeConfigPage(ProjectConfigPage): CONF_SECTION = CODESTYLE NAME = _("Code") ICON = "genprefs.png" def setup_page(self): newcb = self.create_checkbox # --- Workspace interface_group = QGroupBox(_("Workspace")) restore_data_box = newcb(_("Restore data on startup"), 'restore_data_on_startup') save_data_box = newcb(_("Save data on exit"), 'save_data_on_exit') save_history_box = newcb(_("Save history"), 'save_history') save_non_project_box = newcb(_("Save non project files opened"), 'save_non_project_files') interface_layout = QVBoxLayout() interface_layout.addWidget(restore_data_box) interface_layout.addWidget(save_data_box) interface_layout.addWidget(save_history_box) interface_layout.addWidget(save_non_project_box) interface_group.setLayout(interface_layout) vlayout = QVBoxLayout() vlayout.addWidget(interface_group) vlayout.addStretch(1) self.setLayout(vlayout) def apply_settings(self, options): """ """ print('applied') # spyder: test-skip #self.main.apply_settings() class VersionConfigPage(ProjectConfigPage): CONF_SECTION = VCS NAME = _("Version control") ICON = "genprefs.png" def setup_page(self): newcb = self.create_checkbox # --- Workspace vcs_group = QGroupBox(_("Version control")) use_version_control = newcb(_("Use version control"), 'use_version_control') styles = ['git', 'hg'] choices = list(zip(styles, [style.lower() for style in styles])) vcs_combo = self.create_combobox(_('Version control system'), choices, 'version_control_system', default='git') vcs_layout = QVBoxLayout() vcs_layout.addWidget(use_version_control) vcs_layout.addWidget(vcs_combo) vcs_group.setLayout(vcs_layout) vlayout = QVBoxLayout() vlayout.addWidget(vcs_group) vlayout.addStretch(1) self.setLayout(vlayout) def apply_settings(self, options): """ """ print('applied') # spyder: test-skip #self.main.apply_settings() if __name__ == "__main__": import os.path as osp import tempfile from spyder.utils.qthelpers import qapplication app = qapplication() proj_dir = tempfile.mkdtemp() + osp.sep + '.spyproject' proj = EmptyProject(proj_dir) dlg = ProjectPreferences(None, proj) dlg.show() app.exec_() spyder-3.2.6/spyder/widgets/projects/projectdialog.py0000664000175000017500000001640613026261006023632 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Copyright © Spyder Project Contributors # # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) # ----------------------------------------------------------------------------- """Project creation dialog.""" from __future__ import print_function # Standard library imports import errno import os import os.path as osp import sys import tempfile # Third party imports from qtpy.compat import getexistingdirectory from qtpy.QtCore import Qt, Signal from qtpy.QtWidgets import (QVBoxLayout, QLabel, QLineEdit, QPushButton, QDialog, QComboBox, QGridLayout, QToolButton, QDialogButtonBox, QGroupBox, QRadioButton, QHBoxLayout) # Local imports from spyder.config.base import _, get_home_dir from spyder.utils.qthelpers import get_std_icon from spyder.py3compat import to_text_string from spyder.widgets.projects import get_available_project_types def is_writable(path): """Check if path has write access""" try: testfile = tempfile.TemporaryFile(dir=path) testfile.close() except OSError as e: if e.errno == errno.EACCES: # 13 return False return True class ProjectDialog(QDialog): """Project creation dialog.""" # path, type, packages sig_project_creation_requested = Signal(object, object, object) def __init__(self, parent): """Project creation dialog.""" super(ProjectDialog, self).__init__(parent=parent) # Variables current_python_version = '.'.join([to_text_string(sys.version_info[0]), to_text_string(sys.version_info[1])]) python_versions = ['2.7', '3.4', '3.5'] if current_python_version not in python_versions: python_versions.append(current_python_version) python_versions = sorted(python_versions) self.project_name = None self.location = get_home_dir() # Widgets self.groupbox = QGroupBox() self.radio_new_dir = QRadioButton(_("New directory")) self.radio_from_dir = QRadioButton(_("Existing directory")) self.label_project_name = QLabel(_('Project name')) self.label_location = QLabel(_('Location')) self.label_project_type = QLabel(_('Project type')) self.label_python_version = QLabel(_('Python version')) self.text_project_name = QLineEdit() self.text_location = QLineEdit(get_home_dir()) self.combo_project_type = QComboBox() self.combo_python_version = QComboBox() self.button_select_location = QToolButton() self.button_cancel = QPushButton(_('Cancel')) self.button_create = QPushButton(_('Create')) self.bbox = QDialogButtonBox(Qt.Horizontal) self.bbox.addButton(self.button_cancel, QDialogButtonBox.ActionRole) self.bbox.addButton(self.button_create, QDialogButtonBox.ActionRole) # Widget setup self.combo_python_version.addItems(python_versions) self.radio_new_dir.setChecked(True) self.text_location.setEnabled(True) self.text_location.setReadOnly(True) self.button_select_location.setIcon(get_std_icon('DirOpenIcon')) self.button_cancel.setDefault(True) self.button_cancel.setAutoDefault(True) self.button_create.setEnabled(False) self.combo_project_type.addItems(self._get_project_types()) self.combo_python_version.setCurrentIndex( python_versions.index(current_python_version)) self.setWindowTitle(_('Create new project')) self.setFixedWidth(500) self.label_python_version.setVisible(False) self.combo_python_version.setVisible(False) # Layouts layout_top = QHBoxLayout() layout_top.addWidget(self.radio_new_dir) layout_top.addWidget(self.radio_from_dir) layout_top.addStretch(1) self.groupbox.setLayout(layout_top) layout_grid = QGridLayout() layout_grid.addWidget(self.label_project_name, 0, 0) layout_grid.addWidget(self.text_project_name, 0, 1, 1, 2) layout_grid.addWidget(self.label_location, 1, 0) layout_grid.addWidget(self.text_location, 1, 1) layout_grid.addWidget(self.button_select_location, 1, 2) layout_grid.addWidget(self.label_project_type, 2, 0) layout_grid.addWidget(self.combo_project_type, 2, 1, 1, 2) layout_grid.addWidget(self.label_python_version, 3, 0) layout_grid.addWidget(self.combo_python_version, 3, 1, 1, 2) layout = QVBoxLayout() layout.addWidget(self.groupbox) layout.addSpacing(10) layout.addLayout(layout_grid) layout.addStretch() layout.addSpacing(20) layout.addWidget(self.bbox) self.setLayout(layout) # Signals and slots self.button_select_location.clicked.connect(self.select_location) self.button_create.clicked.connect(self.create_project) self.button_cancel.clicked.connect(self.close) self.radio_from_dir.clicked.connect(self.update_location) self.radio_new_dir.clicked.connect(self.update_location) self.text_project_name.textChanged.connect(self.update_location) def _get_project_types(self): """Get all available project types.""" project_types = get_available_project_types() projects = [] for project in project_types: projects.append(project.PROJECT_TYPE_NAME) return projects def select_location(self): """Select directory.""" location = getexistingdirectory(self, _("Select directory"), self.location) if location: if is_writable(location): self.location = location self.update_location() def update_location(self, text=''): """Update text of location.""" self.text_project_name.setEnabled(self.radio_new_dir.isChecked()) name = self.text_project_name.text().strip() if name and self.radio_new_dir.isChecked(): path = osp.join(self.location, name) self.button_create.setDisabled(os.path.isdir(path)) elif self.radio_from_dir.isChecked(): self.button_create.setEnabled(True) path = self.location else: self.button_create.setEnabled(False) path = self.location self.text_location.setText(path) def create_project(self): """Create project.""" packages = ['python={0}'.format(self.combo_python_version.currentText())] self.sig_project_creation_requested.emit( self.text_location.text(), self.combo_project_type.currentText(), packages) self.accept() def test(): """Local test.""" from spyder.utils.qthelpers import qapplication app = qapplication() dlg = ProjectDialog(None) dlg.show() sys.exit(app.exec_()) if __name__ == "__main__": test() spyder-3.2.6/spyder/widgets/projects/tests/0000775000175000017500000000000013225025007021565 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/widgets/projects/tests/test_projectdialog.py0000664000175000017500000000113413156676664026053 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for projectdialog.py """ # Test library imports import pytest # Local imports from spyder.widgets.projects.projectdialog import ProjectDialog @pytest.fixture def setup_projects_dialog(qtbot): """Set up ProjectDialog.""" dlg = ProjectDialog(None) qtbot.addWidget(dlg) return dlg def test_project_dialog(qtbot): """Run project dialog.""" dlg = setup_projects_dialog(qtbot) dlg.show() assert dlg if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/widgets/projects/tests/test_project_explorer.py0000664000175000017500000000134213156676664026614 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for explorer.py """ # Test library imports import pytest # Local imports from spyder.widgets.projects.explorer import ProjectExplorerTest @pytest.fixture def setup_projects_explorer(qtbot): """Set up ProjectExplorerWidgetTest.""" project_explorer = ProjectExplorerTest() qtbot.addWidget(project_explorer) return project_explorer def test_project_explorer(qtbot): """Run project explorer.""" project_explorer = setup_projects_explorer(qtbot) project_explorer.resize(250, 480) project_explorer.show() assert project_explorer if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/widgets/projects/tests/test_project.py0000664000175000017500000000414113224121062024641 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for __init__.py. """ # Test library imports import pytest import os.path as osp # Local imports from spyder.widgets.projects import EmptyProject from spyder.widgets.projects.config import (CODESTYLE, WORKSPACE, ENCODING, VCS) @pytest.fixture(scope='session') def project_test(tmpdir_factory): """ Fixture for create a temporary project. Returns: project_dir: fixture of temporary project dir. project: EmptyProject object. """ project_dir = tmpdir_factory.mktemp("test_project") project = EmptyProject(str(project_dir)) return project_dir, project def test_empty_project(project_test): """Test creation of anEmpy project, and its configuration files.""" project_dir, project = project_test assert project.root_path == str(project_dir) # Assert Project onfigs conf_files = project.get_conf_files() for dir_ in [CODESTYLE, WORKSPACE, ENCODING, VCS]: assert dir_ in conf_files project_config = conf_files[dir_] # assert configurations files assert osp.exists(project_config.filename()) def test_set_load_recent_files(project_test): """Test saving and loading files from the configuration. Saving/loading should preserved the order, and remove duplicates. """ project_dir, project = project_test # Create some files for testing files_paths = [] for f in ['a.py', 'b.py', 'c.py']: file_ = project_dir.join(f) file_.write('# Some dummy content') files_paths.append(str(file_)) # setting and loading project.set_recent_files(files_paths[:]) assert project.get_recent_files() == files_paths # adding a duplicate elemnent files_paths_duplicate = files_paths + [files_paths[0]] assert len(files_paths_duplicate) == len(files_paths) + 1 project.set_recent_files(files_paths_duplicate[:]) assert project.get_recent_files() == files_paths if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/widgets/projects/tests/test_configdialog.py0000664000175000017500000000175713156676664025665 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for configdialog.py """ # Standard librery imports import os.path as osp import tempfile # Test library imports import pytest # Local imports from spyder.widgets.projects.configdialog import (EmptyProject, ProjectPreferences) @pytest.fixture def setup_projects_preferences(qtbot): """Set up ProjectPreferences.""" project_dir = tempfile.mkdtemp() + osp.sep + '.spyproject' project = EmptyProject(project_dir) project_preferences = ProjectPreferences(None, project) qtbot.addWidget(project_preferences) return (project, project_preferences) def test_projects_preferences(qtbot): """Run Project Preferences.""" project, preferences = setup_projects_preferences(qtbot) preferences.resize(250, 480) preferences.show() assert preferences if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/widgets/projects/tests/__init__.py0000664000175000017500000000050213156676664023723 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Copyright (c) Spyder Project Contributors # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Tests.""" spyder-3.2.6/spyder/widgets/projects/explorer.py0000664000175000017500000002701213224740762022652 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Project Explorer""" # pylint: disable=C0103 # Standard library imports from __future__ import print_function import os.path as osp import shutil # Third party imports from qtpy.QtCore import Qt, Signal, Slot from qtpy.QtWidgets import (QAbstractItemView, QHBoxLayout, QHeaderView, QLabel, QMessageBox, QVBoxLayout, QWidget) # Local imports from spyder.config.base import _ from spyder.py3compat import to_text_string from spyder.utils import misc from spyder.utils.qthelpers import create_action from spyder.widgets.explorer import FilteredDirView class ExplorerTreeWidget(FilteredDirView): """Explorer tree widget""" sig_delete_project = Signal() def __init__(self, parent, show_hscrollbar=True): FilteredDirView.__init__(self, parent) self.last_folder = None self.setSelectionMode(FilteredDirView.ExtendedSelection) self.show_hscrollbar = show_hscrollbar # Enable drag & drop events self.setDragEnabled(True) self.setDragDropMode(FilteredDirView.DragDrop) #------DirView API--------------------------------------------------------- def setup_common_actions(self): """Setup context menu common actions""" actions = FilteredDirView.setup_common_actions(self) # Toggle horizontal scrollbar hscrollbar_action = create_action(self, _("Show horizontal scrollbar"), toggled=self.toggle_hscrollbar) hscrollbar_action.setChecked(self.show_hscrollbar) self.toggle_hscrollbar(self.show_hscrollbar) return actions + [hscrollbar_action] #------Public API---------------------------------------------------------- @Slot(bool) def toggle_hscrollbar(self, checked): """Toggle horizontal scrollbar""" self.parent_widget.sig_option_changed.emit('show_hscrollbar', checked) self.show_hscrollbar = checked self.header().setStretchLastSection(not checked) self.header().setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel) try: self.header().setSectionResizeMode(QHeaderView.ResizeToContents) except: # support for qtpy<1.2.0 self.header().setResizeMode(QHeaderView.ResizeToContents) #---- Internal drag & drop def dragMoveEvent(self, event): """Reimplement Qt method""" index = self.indexAt(event.pos()) if index: dst = self.get_filename(index) if osp.isdir(dst): event.acceptProposedAction() else: event.ignore() else: event.ignore() def dropEvent(self, event): """Reimplement Qt method""" event.ignore() action = event.dropAction() if action not in (Qt.MoveAction, Qt.CopyAction): return # QTreeView must not remove the source items even in MoveAction mode: # event.setDropAction(Qt.CopyAction) dst = self.get_filename(self.indexAt(event.pos())) yes_to_all, no_to_all = None, None src_list = [to_text_string(url.toString()) for url in event.mimeData().urls()] if len(src_list) > 1: buttons = QMessageBox.Yes|QMessageBox.YesAll| \ QMessageBox.No|QMessageBox.NoAll|QMessageBox.Cancel else: buttons = QMessageBox.Yes|QMessageBox.No for src in src_list: if src == dst: continue dst_fname = osp.join(dst, osp.basename(src)) if osp.exists(dst_fname): if yes_to_all is not None or no_to_all is not None: if no_to_all: continue elif osp.isfile(dst_fname): answer = QMessageBox.warning(self, _('Project explorer'), _('File %s already exists.
    ' 'Do you want to overwrite it?') % dst_fname, buttons) if answer == QMessageBox.No: continue elif answer == QMessageBox.Cancel: break elif answer == QMessageBox.YesAll: yes_to_all = True elif answer == QMessageBox.NoAll: no_to_all = True continue else: QMessageBox.critical(self, _('Project explorer'), _('Folder %s already exists.' ) % dst_fname, QMessageBox.Ok) event.setDropAction(Qt.CopyAction) return try: if action == Qt.CopyAction: if osp.isfile(src): shutil.copy(src, dst) else: shutil.copytree(src, dst) else: if osp.isfile(src): misc.move_file(src, dst) else: shutil.move(src, dst) self.parent_widget.removed.emit(src) except EnvironmentError as error: if action == Qt.CopyAction: action_str = _('copy') else: action_str = _('move') QMessageBox.critical(self, _("Project Explorer"), _("Unable to %s %s" "

    Error message:
    %s" ) % (action_str, src, to_text_string(error))) @Slot() def delete(self, fnames=None): """Delete files""" if fnames is None: fnames = self.get_selected_filenames() multiple = len(fnames) > 1 yes_to_all = None for fname in fnames: if fname == self.proxymodel.path_list[0]: self.sig_delete_project.emit() else: yes_to_all = self.delete_file(fname, multiple, yes_to_all) if yes_to_all is not None and not yes_to_all: # Canceled break class ProjectExplorerWidget(QWidget): """Project Explorer""" sig_option_changed = Signal(str, object) sig_open_file = Signal(str) def __init__(self, parent, name_filters=[], show_all=True, show_hscrollbar=True): QWidget.__init__(self, parent) self.treewidget = None self.emptywidget = None self.name_filters = name_filters self.show_all = show_all self.show_hscrollbar = show_hscrollbar self.setup_layout() def setup_layout(self): """Setup project explorer widget layout""" self.emptywidget = ExplorerTreeWidget(self) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.emptywidget) self.setLayout(layout) def closing_widget(self): """Perform actions before widget is closed""" pass def set_project_dir(self, directory): """Set the project directory""" if directory is not None: project = directory.split(osp.sep)[-1] self.treewidget.set_root_path(osp.dirname(directory)) self.treewidget.set_folder_names([project]) self.treewidget.setup_project_view() try: self.treewidget.setExpanded(self.treewidget.get_index(directory), True) except TypeError: pass def clear(self): """Show an empty view""" self.treewidget.hide() self.emptywidget.show() def setup_project(self, directory): """Setup project""" if self.treewidget is not None: self.treewidget.hide() # Setup a new tree widget self.treewidget = ExplorerTreeWidget(self, self.show_hscrollbar) self.treewidget.setup(name_filters=self.name_filters, show_all=self.show_all) self.treewidget.setup_view() self.emptywidget.hide() self.treewidget.show() self.layout().addWidget(self.treewidget) # Setup the directory shown by the tree self.set_project_dir(directory) # Signal to delete the project self.treewidget.sig_delete_project.connect(self.delete_project) def delete_project(self): """Delete current project without deleting the files in the directory.""" if self.current_active_project: path = self.current_active_project.root_path buttons = QMessageBox.Yes|QMessageBox.No answer = QMessageBox.warning(self, _("Delete"), _("Do you really want " "to delete {filename}?

    " "Note: This action will only delete " "the project. Its files are going to be " "preserved on disk." ).format(filename=osp.basename(path)), buttons) if answer == QMessageBox.Yes: try: self.close_project() shutil.rmtree(osp.join(path,'.spyproject')) except EnvironmentError as error: QMessageBox.critical(self, _("Project Explorer"), _("Unable to delete {varpath}" "

    The error message was:
    {error}" ) .format(varpath=path,error=to_text_string(error))) #============================================================================== # Tests #============================================================================== class ProjectExplorerTest(QWidget): def __init__(self): QWidget.__init__(self) vlayout = QVBoxLayout() self.setLayout(vlayout) self.explorer = ProjectExplorerWidget(None, show_all=True) self.explorer.setup_project(osp.dirname(osp.abspath(__file__))) vlayout.addWidget(self.explorer) hlayout1 = QHBoxLayout() vlayout.addLayout(hlayout1) label = QLabel("Open file:") label.setAlignment(Qt.AlignRight) hlayout1.addWidget(label) self.label1 = QLabel() hlayout1.addWidget(self.label1) self.explorer.sig_open_file.connect(self.label1.setText) hlayout3 = QHBoxLayout() vlayout.addLayout(hlayout3) label = QLabel("Option changed:") label.setAlignment(Qt.AlignRight) hlayout3.addWidget(label) self.label3 = QLabel() hlayout3.addWidget(self.label3) self.explorer.sig_option_changed.connect( lambda x, y: self.label3.setText('option_changed: %r, %r' % (x, y))) def test(): from spyder.utils.qthelpers import qapplication app = qapplication() test = ProjectExplorerTest() test.resize(250, 480) test.show() app.exec_() if __name__ == "__main__": test() spyder-3.2.6/spyder/widgets/projects/config.py0000664000175000017500000000507013224740762022257 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Copyright © Spyder Project Contributors # # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) # ----------------------------------------------------------------------------- """Configuration options for projects""" # Standard library imports import os # Local imports from spyder.config.user import UserConfig PROJECT_FILENAME = '.spyproj' PROJECT_FOLDER = '.spyproject' # Project configuration defaults WORKSPACE = 'workspace' WORKSPACE_DEFAULTS = [ (WORKSPACE, {'restore_data_on_startup': True, 'save_data_on_exit': True, 'save_history': True, 'save_non_project_files': False, } )] WORKSPACE_VERSION = '0.1.0' CODESTYLE = 'codestyle' CODESTYLE_DEFAULTS = [ (CODESTYLE, {'indentation': True, } )] CODESTYLE_VERSION = '0.1.0' ENCODING = 'encoding' ENCODING_DEFAULTS = [ (ENCODING, {'text_encoding': 'utf-8', } )] ENCODING_VERSION = '0.1.0' VCS = 'vcs' VCS_DEFAULTS = [ (VCS, {'use_version_control': False, 'version_control_system': '', } )] VCS_VERSION = '0.1.0' class ProjectConfig(UserConfig): """ProjectConfig class, based on UserConfig. Parameters ---------- name: str name of the config defaults: tuple dictionnary containing options *or* list of tuples (section_name, options) version: str version of the configuration file (X.Y.Z format) filename: str configuration file will be saved in %home%/subfolder/%name%.ini """ DEFAULT_SECTION_NAME = 'main' def __init__(self, name, root_path, filename, defaults=None, load=True, version=None): self.project_root_path = root_path # Config rootpath self._root_path = os.path.join(root_path, PROJECT_FOLDER) self._filename = filename # Create folder if non existent if not os.path.isdir(self._root_path): os.makedirs(self._root_path) # Add file # NOTE: We have to think better about the uses of this file # with open(os.path.join(root_path, PROJECT_FILENAME), 'w') as f: # f.write('spyder-ide project\n') UserConfig.__init__(self, name, defaults=defaults, load=load, version=version, subfolder=None, backup=False, raw_mode=True, remove_obsolete=True) spyder-3.2.6/spyder/widgets/projects/__init__.py0000664000175000017500000000607613026261006022545 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Copyright © Spyder Project Contributors # # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) # ----------------------------------------------------------------------------- """Projects""" # Local imports from spyder.widgets.projects.type import EmptyProject from spyder.widgets.projects.type.python import PythonProject def get_available_project_types(): """ """ # return [EmptyProject, PythonProject, PythonPackageProject, DjangoProject, # SpyderPluginProject] + get_available_project_types_plugins() return ([EmptyProject] + get_available_project_types_plugins()) def get_available_project_types_plugins(): """ """ return [] #def components(path): # ''' # Returns the individual components of the given file path # string (for the local operating system). # # The returned components, when joined with os.path.join(), point to # the same location as the original path. # ''' # components = [] # # The loop guarantees that the returned components can be # # os.path.joined with the path separator and point to the same # # location: # while True: # (new_path, tail) = osp.split(path) # Works on any platform # components.append(tail) # if new_path == path: # Root (including drive, on Windows) reached # break # path = new_path # components.append(new_path) # # components.reverse() # First component first # return components # # #def longest_prefix(iter0, iter1): # ''' # Returns the longest common prefix of the given two iterables. # ''' # longest_prefix = [] # for (elmt0, elmt1) in itertools.izip(iter0, iter1): # if elmt0 != elmt1: # break # longest_prefix.append(elmt0) # return longest_prefix # # #def common_prefix_path(path0, path1): # return os.path.join(*longest_prefix(components(path0), components(path1))) # # #def has_children_files(path, include, exclude, show_all): # """Return True if path has children files""" # try: # return len(listdir(path, include, exclude, show_all)) > 0 # except (IOError, OSError): # return False # # #def is_drive_path(path): # """Return True if path is a drive (Windows)""" # path = osp.abspath(path) # return osp.normpath(osp.join(path, osp.pardir)) == path # # #def get_dir_icon(dirname, project): # """Return appropriate directory icon""" # if is_drive_path(dirname): # return get_std_icon('DriveHDIcon') # prefix = 'pp_' if dirname in project.get_pythonpath() else '' # if dirname == project.root_path: # if project.is_opened(): # return get_icon(prefix+'project.png') # else: # return get_icon('project_closed.png') # elif osp.isfile(osp.join(dirname, '__init__.py')): # return get_icon(prefix+'package.png') # else: # return get_icon(prefix+'folder.png') spyder-3.2.6/spyder/widgets/tabs.py0000664000175000017500000004366313224121062020106 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Tabs widget""" # pylint: disable=C0103 # pylint: disable=R0903 # pylint: disable=R0911 # pylint: disable=R0201 # Standard library imports import os.path as osp import sys # Third party imports from qtpy import PYQT5 from qtpy.QtCore import (QByteArray, QEvent, QMimeData, QPoint, Qt, Signal, Slot) from qtpy.QtGui import QDrag from qtpy.QtWidgets import (QApplication, QHBoxLayout, QMenu, QTabBar, QTabWidget, QWidget, QLineEdit) # Local imports from spyder.config.base import _ from spyder.config.gui import config_shortcut from spyder.py3compat import PY2, to_binary_string, to_text_string from spyder.utils import icon_manager as ima from spyder.utils.misc import get_common_path from spyder.utils.qthelpers import (add_actions, create_action, create_toolbutton) class EditTabNamePopup(QLineEdit): """Popup on top of the tab to edit its name.""" def __init__(self, parent, split_char, split_index): """Popup on top of the tab to edit its name.""" # Variables # Parent (main) self.main = parent if parent is not None else self.parent() self.split_char = split_char self.split_index = split_index # Track which tab is being edited self.tab_index = None # Widget setup QLineEdit.__init__(self, parent=None) # Slot to handle tab name update self.editingFinished.connect(self.edit_finished) # Even filter to catch clicks and ESC key self.installEventFilter(self) # Clean borders and no shadow to blend with tab if PYQT5: self.setWindowFlags( Qt.Popup | Qt.FramelessWindowHint | Qt.NoDropShadowWindowHint ) else: self.setWindowFlags( Qt.Popup | Qt.FramelessWindowHint ) self.setFrame(False) # Align with tab name self.setTextMargins(9, 0, 0, 0) def eventFilter(self, widget, event): """Catch clicks outside the object and ESC key press.""" if ((event.type() == QEvent.MouseButtonPress and not self.geometry().contains(event.globalPos())) or (event.type() == QEvent.KeyPress and event.key() == Qt.Key_Escape)): # Exits editing self.hide() self.setFocus(False) return True # Event is not interessant, raise to parent return QLineEdit.eventFilter(self, widget, event) def edit_tab(self, index): """Activate the edit tab.""" # Sets focus, shows cursor self.setFocus(True) # Updates tab index self.tab_index = index # Gets tab size and shrinks to avoid overlapping tab borders rect = self.main.tabRect(index) rect.adjust(1, 1, -2, -1) # Sets size self.setFixedSize(rect.size()) # Places on top of the tab self.move(self.main.mapToGlobal(rect.topLeft())) # Copies tab name and selects all text = self.main.tabText(index) text = text.replace(u'&', u'') if self.split_char: text = text.split(self.split_char)[self.split_index] self.setText(text) self.selectAll() if not self.isVisible(): # Makes editor visible self.show() def edit_finished(self): """On clean exit, update tab name.""" # Hides editor self.hide() if isinstance(self.tab_index, int) and self.tab_index >= 0: # We are editing a valid tab, update name tab_text = to_text_string(self.text()) self.main.setTabText(self.tab_index, tab_text) self.main.sig_change_name.emit(tab_text) class TabBar(QTabBar): """Tabs base class with drag and drop support""" sig_move_tab = Signal((int, int), (str, int, int)) sig_change_name = Signal(str) def __init__(self, parent, ancestor, rename_tabs=False, split_char='', split_index=0): QTabBar.__init__(self, parent) self.ancestor = ancestor # To style tabs on Mac if sys.platform == 'darwin': self.setObjectName('plugin-tab') # Dragging tabs self.__drag_start_pos = QPoint() self.setAcceptDrops(True) self.setUsesScrollButtons(True) self.setMovable(True) # Tab name editor self.rename_tabs = rename_tabs if self.rename_tabs: # Creates tab name editor self.tab_name_editor = EditTabNamePopup(self, split_char, split_index) else: self.tab_name_editor = None def mousePressEvent(self, event): """Reimplement Qt method""" if event.button() == Qt.LeftButton: self.__drag_start_pos = QPoint(event.pos()) QTabBar.mousePressEvent(self, event) def mouseMoveEvent(self, event): """Override Qt method""" # FIXME: This was added by Pierre presumably to move tabs # between plugins, but righit now it's breaking the regular # Qt drag behavior for tabs, so we're commenting it for # now #if event.buttons() == Qt.MouseButtons(Qt.LeftButton) and \ # (event.pos() - self.__drag_start_pos).manhattanLength() > \ # QApplication.startDragDistance(): # drag = QDrag(self) # mimeData = QMimeData()# # ancestor_id = to_text_string(id(self.ancestor)) # parent_widget_id = to_text_string(id(self.parentWidget())) # self_id = to_text_string(id(self)) # source_index = to_text_string(self.tabAt(self.__drag_start_pos)) # mimeData.setData("parent-id", to_binary_string(ancestor_id)) # mimeData.setData("tabwidget-id", # to_binary_string(parent_widget_id)) # mimeData.setData("tabbar-id", to_binary_string(self_id)) # mimeData.setData("source-index", to_binary_string(source_index)) # drag.setMimeData(mimeData) # drag.exec_() QTabBar.mouseMoveEvent(self, event) def dragEnterEvent(self, event): """Override Qt method""" mimeData = event.mimeData() formats = list(mimeData.formats()) if "parent-id" in formats and \ int(mimeData.data("parent-id")) == id(self.ancestor): event.acceptProposedAction() QTabBar.dragEnterEvent(self, event) def dropEvent(self, event): """Override Qt method""" mimeData = event.mimeData() index_from = int(mimeData.data("source-index")) index_to = self.tabAt(event.pos()) if index_to == -1: index_to = self.count() if int(mimeData.data("tabbar-id")) != id(self): tabwidget_from = to_text_string(mimeData.data("tabwidget-id")) # We pass self object ID as a QString, because otherwise it would # depend on the platform: long for 64bit, int for 32bit. Replacing # by long all the time is not working on some 32bit platforms # (see Issue 1094, Issue 1098) self.sig_move_tab[(str, int, int)].emit(tabwidget_from, index_from, index_to) event.acceptProposedAction() elif index_from != index_to: self.sig_move_tab.emit(index_from, index_to) event.acceptProposedAction() QTabBar.dropEvent(self, event) def mouseDoubleClickEvent(self, event): """Override Qt method to trigger the tab name editor.""" if self.rename_tabs is True and \ event.buttons() == Qt.MouseButtons(Qt.LeftButton): # Tab index index = self.tabAt(event.pos()) if index >= 0: # Tab is valid, call tab name editor self.tab_name_editor.edit_tab(index) else: # Event is not interesting, raise to parent QTabBar.mouseDoubleClickEvent(self, event) class BaseTabs(QTabWidget): """TabWidget with context menu and corner widgets""" sig_close_tab = Signal(int) def __init__(self, parent, actions=None, menu=None, corner_widgets=None, menu_use_tooltips=False): QTabWidget.__init__(self, parent) self.setUsesScrollButtons(True) # To style tabs on Mac if sys.platform == 'darwin': self.setObjectName('plugin-tab') self.corner_widgets = {} self.menu_use_tooltips = menu_use_tooltips if menu is None: self.menu = QMenu(self) if actions: add_actions(self.menu, actions) else: self.menu = menu # Corner widgets if corner_widgets is None: corner_widgets = {} corner_widgets.setdefault(Qt.TopLeftCorner, []) corner_widgets.setdefault(Qt.TopRightCorner, []) self.browse_button = create_toolbutton(self, icon=ima.icon('browse_tab'), tip=_("Browse tabs")) self.browse_tabs_menu = QMenu(self) self.browse_button.setMenu(self.browse_tabs_menu) self.browse_button.setPopupMode(self.browse_button.InstantPopup) self.browse_tabs_menu.aboutToShow.connect(self.update_browse_tabs_menu) corner_widgets[Qt.TopLeftCorner] += [self.browse_button] self.set_corner_widgets(corner_widgets) 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 set_corner_widgets(self, corner_widgets): """ Set tabs corner widgets corner_widgets: dictionary of (corner, widgets) corner: Qt.TopLeftCorner or Qt.TopRightCorner widgets: list of widgets (may contains integers to add spacings) """ assert isinstance(corner_widgets, dict) assert all(key in (Qt.TopLeftCorner, Qt.TopRightCorner) for key in corner_widgets) self.corner_widgets.update(corner_widgets) for corner, widgets in list(self.corner_widgets.items()): cwidget = QWidget() cwidget.hide() prev_widget = self.cornerWidget(corner) if prev_widget: prev_widget.close() self.setCornerWidget(cwidget, corner) clayout = QHBoxLayout() clayout.setContentsMargins(0, 0, 0, 0) for widget in widgets: if isinstance(widget, int): clayout.addSpacing(widget) else: clayout.addWidget(widget) cwidget.setLayout(clayout) cwidget.show() def add_corner_widgets(self, widgets, corner=Qt.TopRightCorner): self.set_corner_widgets({corner: self.corner_widgets.get(corner, [])+widgets}) def contextMenuEvent(self, event): """Override Qt method""" self.setCurrentIndex(self.tabBar().tabAt(event.pos())) if self.menu: self.menu.popup(event.globalPos()) def mousePressEvent(self, event): """Override Qt method""" if event.button() == Qt.MidButton: index = self.tabBar().tabAt(event.pos()) if index >= 0: self.sig_close_tab.emit(index) event.accept() return QTabWidget.mousePressEvent(self, event) def keyPressEvent(self, event): """Override Qt method""" ctrl = event.modifiers() & Qt.ControlModifier key = event.key() handled = False if ctrl and self.count() > 0: index = self.currentIndex() if key == Qt.Key_PageUp: if index > 0: self.setCurrentIndex(index - 1) else: self.setCurrentIndex(self.count() - 1) handled = True elif key == Qt.Key_PageDown: if index < self.count() - 1: self.setCurrentIndex(index + 1) else: self.setCurrentIndex(0) handled = True if not handled: QTabWidget.keyPressEvent(self, event) def tab_navigate(self, delta=1): """Ctrl+Tab""" if delta > 0 and self.currentIndex() == self.count()-1: index = delta-1 elif delta < 0 and self.currentIndex() == 0: index = self.count()+delta else: index = self.currentIndex()+delta self.setCurrentIndex(index) def set_close_function(self, func): """Setting Tabs close function None -> tabs are not closable""" state = func is not None if state: self.sig_close_tab.connect(func) try: # Assuming Qt >= 4.5 QTabWidget.setTabsClosable(self, state) self.tabCloseRequested.connect(func) except AttributeError: # Workaround for Qt < 4.5 close_button = create_toolbutton(self, triggered=func, icon=ima.icon('fileclose'), tip=_("Close current tab")) self.setCornerWidget(close_button if state else None) class Tabs(BaseTabs): """BaseTabs widget with movable tabs and tab navigation shortcuts""" # Signals move_data = Signal(int, int) move_tab_finished = Signal() sig_move_tab = Signal(str, str, int, int) def __init__(self, parent, actions=None, menu=None, corner_widgets=None, menu_use_tooltips=False, rename_tabs=False, split_char='', split_index=0): BaseTabs.__init__(self, parent, actions, menu, corner_widgets, menu_use_tooltips) tab_bar = TabBar(self, parent, rename_tabs=rename_tabs, split_char=split_char, split_index=split_index) tab_bar.sig_move_tab.connect(self.move_tab) tab_bar.sig_move_tab[(str, int, int)].connect( self.move_tab_from_another_tabwidget) self.setTabBar(tab_bar) config_shortcut(lambda: self.tab_navigate(1), context='editor', name='go to next file', parent=parent) config_shortcut(lambda: self.tab_navigate(-1), context='editor', name='go to previous file', parent=parent) config_shortcut(lambda: self.sig_close_tab.emit(self.currentIndex()), context='editor', name='close file 1', parent=parent) config_shortcut(lambda: self.sig_close_tab.emit(self.currentIndex()), context='editor', name='close file 2', parent=parent) @Slot(int, int) def move_tab(self, index_from, index_to): """Move tab inside a tabwidget""" self.move_data.emit(index_from, index_to) tip, text = self.tabToolTip(index_from), self.tabText(index_from) icon, widget = self.tabIcon(index_from), self.widget(index_from) current_widget = self.currentWidget() self.removeTab(index_from) self.insertTab(index_to, widget, icon, text) self.setTabToolTip(index_to, tip) self.setCurrentWidget(current_widget) self.move_tab_finished.emit() @Slot(str, int, int) def move_tab_from_another_tabwidget(self, tabwidget_from, index_from, index_to): """Move tab from a tabwidget to another""" # We pass self object IDs as QString objs, because otherwise it would # depend on the platform: long for 64bit, int for 32bit. Replacing # by long all the time is not working on some 32bit platforms # (see Issue 1094, Issue 1098) self.sig_move_tab.emit(tabwidget_from, to_text_string(id(self)), index_from, index_to) spyder-3.2.6/spyder/widgets/explorer.py0000664000175000017500000015176613224740762021037 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Files and Directories Explorer""" # pylint: disable=C0103 # pylint: disable=R0903 # pylint: disable=R0911 # pylint: disable=R0201 # Standard library imports from __future__ import with_statement import os import os.path as osp import re import shutil import subprocess import sys import mimetypes as mime # Third party imports from qtpy import API, is_pyqt46 from qtpy.compat import getsavefilename, getexistingdirectory from qtpy.QtCore import (QDir, QFileInfo, QMimeData, QSize, QSortFilterProxyModel, Qt, QTimer, QUrl, Signal, Slot) from qtpy.QtGui import QDrag from qtpy.QtWidgets import (QFileSystemModel, QHBoxLayout, QFileIconProvider, QInputDialog, QLabel, QLineEdit, QMenu, QMessageBox, QToolButton, QTreeView, QVBoxLayout, QWidget) # Local imports from spyder.config.base import _ from spyder.py3compat import (str_lower, to_binary_string, to_text_string) from spyder.utils import icon_manager as ima from spyder.utils import encoding, misc, programs, vcs from spyder.utils.qthelpers import (add_actions, create_action, file_uri, create_plugin_layout) from spyder.utils.misc import getcwd_or_home try: from nbconvert import PythonExporter as nbexporter except: nbexporter = None # analysis:ignore def open_file_in_external_explorer(filename): if sys.platform == "darwin": subprocess.call(["open", "-R", filename]) else: filename=os.path.dirname(filename) if os.name == 'nt': os.startfile(filename) else: subprocess.call(["xdg-open", filename]) def show_in_external_file_explorer(fnames=None): """Show files in external file explorer Args: fnames (list): Names of files to show. """ if not isinstance(fnames, (tuple, list)): fnames = [fnames] for fname in fnames: open_file_in_external_explorer(fname) def fixpath(path): """Normalize path fixing case, making absolute and removing symlinks""" norm = osp.normcase if os.name == 'nt' else osp.normpath return norm(osp.abspath(osp.realpath(path))) def create_script(fname): """Create a new Python script""" text = os.linesep.join(["# -*- coding: utf-8 -*-", "", ""]) encoding.write(to_text_string(text), fname, 'utf-8') 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 has_subdirectories(path, include, exclude, show_all): """Return True if path has subdirectories""" try: # > 1 because of '..' return len( listdir(path, include, exclude, show_all, folders_only=True) ) > 1 except (IOError, OSError): return False class IconProvider(QFileIconProvider): BIN_FILES = {x: 'ArchiveFileIcon' for x in ['zip', 'x-tar', 'x-7z-compressed', 'rar']} DOCUMENT_FILES = {'vnd.ms-powerpoint': 'PowerpointFileIcon', 'vnd.openxmlformats-officedocument.' 'presentationml.presentation': 'PowerpointFileIcon', 'msword': 'WordFileIcon', 'vnd.openxmlformats-officedocument.' 'wordprocessingml.document': 'WordFileIcon', 'vnd.ms-excel': 'ExcelFileIcon', 'vnd.openxmlformats-officedocument.' 'spreadsheetml.sheet': 'ExcelFileIcon', 'pdf': 'PDFIcon'} OFFICE_FILES = {'.xlsx': 'ExcelFileIcon', '.docx': 'WordFileIcon', '.pptx': 'PowerpointFileIcon'} """Project tree widget icon provider""" def __init__(self, treeview): super(IconProvider, self).__init__() self.treeview = treeview self.application_icons = {} self.application_icons.update(self.BIN_FILES) self.application_icons.update(self.DOCUMENT_FILES) @Slot(int) @Slot(QFileInfo) def icon(self, icontype_or_qfileinfo): """Reimplement Qt method""" if isinstance(icontype_or_qfileinfo, QFileIconProvider.IconType): return super(IconProvider, self).icon(icontype_or_qfileinfo) else: qfileinfo = icontype_or_qfileinfo fname = osp.normpath(to_text_string(qfileinfo.absoluteFilePath())) if osp.isdir(fname): return ima.icon('DirOpenIcon') else: basename = osp.basename(fname) _, extension = osp.splitext(basename) mime_type, _ = mime.guess_type(basename) icon = ima.icon('FileIcon') if extension in self.OFFICE_FILES: icon = ima.icon(self.OFFICE_FILES[extension]) if mime_type is not None: try: # Fix for issue 5080. Even though mimetypes.guess_type # documentation states that the return value will be # None or a tuple of the form type/subtype, in the # Windows registry, .sql has a mimetype of text\plain # instead of text/plain therefore mimetypes is # returning it incorrectly. file_type, bin_name = mime_type.split('/') except ValueError: file_type = 'text' if file_type == 'text': icon = ima.icon('TextFileIcon') elif file_type == 'audio': icon = ima.icon('AudioFileIcon') elif file_type == 'video': icon = ima.icon('VideoFileIcon') elif file_type == 'image': icon = ima.icon('ImageFileIcon') elif file_type == 'application': if bin_name in self.application_icons: icon = ima.icon(self.application_icons[bin_name]) return icon class DirView(QTreeView): """Base file/directory tree view""" def __init__(self, parent=None): super(DirView, self).__init__(parent) self.name_filters = ['*.py'] self.parent_widget = parent self.show_all = None self.menu = None self.common_actions = None self.__expanded_state = None self._to_be_loaded = None self.fsmodel = None self.setup_fs_model() self._scrollbar_positions = None #---- Model def setup_fs_model(self): """Setup filesystem model""" filters = QDir.AllDirs | QDir.Files | QDir.Drives | QDir.NoDotAndDotDot self.fsmodel = QFileSystemModel(self) self.fsmodel.setFilter(filters) self.fsmodel.setNameFilterDisables(False) def install_model(self): """Install filesystem model""" self.setModel(self.fsmodel) def setup_view(self): """Setup view""" self.install_model() if not is_pyqt46: self.fsmodel.directoryLoaded.connect( lambda: self.resizeColumnToContents(0)) self.setAnimated(False) self.setSortingEnabled(True) self.sortByColumn(0, Qt.AscendingOrder) self.fsmodel.modelReset.connect(self.reset_icon_provider) self.reset_icon_provider() # Disable the view of .spyproject. self.filter_directories() def set_name_filters(self, name_filters): """Set name filters""" self.name_filters = name_filters self.fsmodel.setNameFilters(name_filters) def set_show_all(self, state): """Toggle 'show all files' state""" if state: self.fsmodel.setNameFilters([]) else: self.fsmodel.setNameFilters(self.name_filters) def get_filename(self, index): """Return filename associated with *index*""" if index: return osp.normpath(to_text_string(self.fsmodel.filePath(index))) def get_index(self, filename): """Return index associated with filename""" return self.fsmodel.index(filename) def get_selected_filenames(self): """Return selected filenames""" if self.selectionMode() == self.ExtendedSelection: return [self.get_filename(idx) for idx in self.selectedIndexes()] else: return [self.get_filename(self.currentIndex())] def get_dirname(self, index): """Return dirname associated with *index*""" fname = self.get_filename(index) if fname: if osp.isdir(fname): return fname else: return osp.dirname(fname) #---- Tree view widget def setup(self, name_filters=['*.py', '*.pyw'], show_all=False): """Setup tree widget""" self.setup_view() self.set_name_filters(name_filters) self.show_all = show_all # Setup context menu self.menu = QMenu(self) self.common_actions = self.setup_common_actions() def reset_icon_provider(self): """Reset file system model icon provider The purpose of this is to refresh files/directories icons""" self.fsmodel.setIconProvider(IconProvider(self)) #---- Context menu def setup_common_actions(self): """Setup context menu common actions""" # Filters filters_action = create_action(self, _("Edit filename filters..."), None, ima.icon('filter'), triggered=self.edit_filter) # Show all files all_action = create_action(self, _("Show all files"), toggled=self.toggle_all) all_action.setChecked(self.show_all) self.toggle_all(self.show_all) return [filters_action, all_action] @Slot() def edit_filter(self): """Edit name filters""" filters, valid = QInputDialog.getText(self, _('Edit filename filters'), _('Name filters:'), QLineEdit.Normal, ", ".join(self.name_filters)) if valid: filters = [f.strip() for f in to_text_string(filters).split(',')] self.parent_widget.sig_option_changed.emit('name_filters', filters) self.set_name_filters(filters) @Slot(bool) def toggle_all(self, checked): """Toggle all files mode""" self.parent_widget.sig_option_changed.emit('show_all', checked) self.show_all = checked self.set_show_all(checked) def create_file_new_actions(self, fnames): """Return actions for submenu 'New...'""" if not fnames: return [] new_file_act = create_action(self, _("File..."), icon=ima.icon('filenew'), triggered=lambda: self.new_file(fnames[-1])) new_module_act = create_action(self, _("Module..."), icon=ima.icon('spyder'), triggered=lambda: self.new_module(fnames[-1])) new_folder_act = create_action(self, _("Folder..."), icon=ima.icon('folder_new'), triggered=lambda: self.new_folder(fnames[-1])) new_package_act = create_action(self, _("Package..."), icon=ima.icon('package_new'), triggered=lambda: self.new_package(fnames[-1])) return [new_file_act, new_folder_act, None, new_module_act, new_package_act] def create_file_import_actions(self, fnames): """Return actions for submenu 'Import...'""" return [] def create_file_manage_actions(self, fnames): """Return file management actions""" only_files = all([osp.isfile(_fn) for _fn in fnames]) only_modules = all([osp.splitext(_fn)[1] in ('.py', '.pyw', '.ipy') for _fn in fnames]) only_notebooks = all([osp.splitext(_fn)[1] == '.ipynb' for _fn in fnames]) only_valid = all([encoding.is_text_file(_fn) for _fn in fnames]) run_action = create_action(self, _("Run"), icon=ima.icon('run'), triggered=self.run) edit_action = create_action(self, _("Edit"), icon=ima.icon('edit'), triggered=self.clicked) move_action = create_action(self, _("Move..."), icon="move.png", triggered=self.move) delete_action = create_action(self, _("Delete..."), icon=ima.icon('editdelete'), triggered=self.delete) rename_action = create_action(self, _("Rename..."), icon=ima.icon('rename'), triggered=self.rename) open_action = create_action(self, _("Open"), triggered=self.open) ipynb_convert_action = create_action(self, _("Convert to Python script"), icon=ima.icon('python'), triggered=self.convert_notebooks) actions = [] if only_modules: actions.append(run_action) if only_valid and only_files: actions.append(edit_action) else: actions.append(open_action) if sys.platform == 'darwin': text=_("Show in Finder") else: text=_("Show in external file explorer") external_fileexp_action = create_action(self, text, triggered=self.show_in_external_file_explorer) actions.append(external_fileexp_action) actions += [delete_action, rename_action] basedir = fixpath(osp.dirname(fnames[0])) if all([fixpath(osp.dirname(_fn)) == basedir for _fn in fnames]): actions.append(move_action) actions += [None] if only_notebooks and nbexporter is not None: actions.append(ipynb_convert_action) # VCS support is quite limited for now, so we are enabling the VCS # related actions only when a single file/folder is selected: dirname = fnames[0] if osp.isdir(fnames[0]) else osp.dirname(fnames[0]) if len(fnames) == 1 and vcs.is_vcs_repository(dirname): # QAction.triggered works differently for PySide and PyQt if not API == 'pyside': commit_slot = lambda _checked, fnames=[dirname]:\ self.vcs_command(fnames, 'commit') browse_slot = lambda _checked, fnames=[dirname]:\ self.vcs_command(fnames, 'browse') else: commit_slot = lambda fnames=[dirname]:\ self.vcs_command(fnames, 'commit') browse_slot = lambda fnames=[dirname]:\ self.vcs_command(fnames, 'browse') vcs_ci = create_action(self, _("Commit"), icon=ima.icon('vcs_commit'), triggered=commit_slot) vcs_log = create_action(self, _("Browse repository"), icon=ima.icon('vcs_browse'), triggered=browse_slot) actions += [None, vcs_ci, vcs_log] return actions def create_folder_manage_actions(self, fnames): """Return folder management actions""" actions = [] if os.name == 'nt': _title = _("Open command prompt here") else: _title = _("Open terminal here") _title = _("Open IPython console here") action = create_action(self, _title, triggered=lambda: self.open_interpreter(fnames)) actions.append(action) return actions def create_context_menu_actions(self): """Create context menu actions""" actions = [] fnames = self.get_selected_filenames() new_actions = self.create_file_new_actions(fnames) if len(new_actions) > 1: # Creating a submenu only if there is more than one entry new_act_menu = QMenu(_('New'), self) add_actions(new_act_menu, new_actions) actions.append(new_act_menu) else: actions += new_actions import_actions = self.create_file_import_actions(fnames) if len(import_actions) > 1: # Creating a submenu only if there is more than one entry import_act_menu = QMenu(_('Import'), self) add_actions(import_act_menu, import_actions) actions.append(import_act_menu) else: actions += import_actions if actions: actions.append(None) if fnames: actions += self.create_file_manage_actions(fnames) if actions: actions.append(None) if fnames and all([osp.isdir(_fn) for _fn in fnames]): actions += self.create_folder_manage_actions(fnames) if actions: actions.append(None) actions += self.common_actions return actions def update_menu(self): """Update context menu""" self.menu.clear() add_actions(self.menu, self.create_context_menu_actions()) #---- Events def viewportEvent(self, event): """Reimplement Qt method""" # Prevent Qt from crashing or showing warnings like: # "QSortFilterProxyModel: index from wrong model passed to # mapFromSource", probably due to the fact that the file system model # is being built. See Issue 1250. # # This workaround was inspired by the following KDE bug: # https://bugs.kde.org/show_bug.cgi?id=172198 # # Apparently, this is a bug from Qt itself. self.executeDelayedItemsLayout() return QTreeView.viewportEvent(self, event) def contextMenuEvent(self, event): """Override Qt method""" self.update_menu() self.menu.popup(event.globalPos()) def keyPressEvent(self, event): """Reimplement Qt method""" if event.key() in (Qt.Key_Enter, Qt.Key_Return): self.clicked() elif event.key() == Qt.Key_F2: self.rename() elif event.key() == Qt.Key_Delete: self.delete() elif event.key() == Qt.Key_Backspace: self.go_to_parent_directory() else: QTreeView.keyPressEvent(self, event) def mouseDoubleClickEvent(self, event): """Reimplement Qt method""" QTreeView.mouseDoubleClickEvent(self, event) self.clicked() @Slot() def clicked(self): """Selected item was double-clicked or enter/return was pressed""" fnames = self.get_selected_filenames() for fname in fnames: if osp.isdir(fname): self.directory_clicked(fname) else: self.open([fname]) def directory_clicked(self, dirname): """Directory was just clicked""" pass #---- Drag def dragEnterEvent(self, event): """Drag and Drop - Enter event""" event.setAccepted(event.mimeData().hasFormat("text/plain")) def dragMoveEvent(self, event): """Drag and Drop - Move event""" if (event.mimeData().hasFormat("text/plain")): event.setDropAction(Qt.MoveAction) event.accept() else: event.ignore() def startDrag(self, dropActions): """Reimplement Qt Method - handle drag event""" data = QMimeData() data.setUrls([QUrl(fname) for fname in self.get_selected_filenames()]) drag = QDrag(self) drag.setMimeData(data) drag.exec_() #---- File/Directory actions @Slot() def open(self, fnames=None): """Open files with the appropriate application""" if fnames is None: fnames = self.get_selected_filenames() for fname in fnames: if osp.isfile(fname) and encoding.is_text_file(fname): self.parent_widget.sig_open_file.emit(fname) else: self.open_outside_spyder([fname]) def open_outside_spyder(self, fnames): """Open file outside Spyder with the appropriate application If this does not work, opening unknown file in Spyder, as text file""" for path in sorted(fnames): path = file_uri(path) ok = programs.start_file(path) if not ok: self.parent_widget.edit.emit(path) def open_interpreter(self, fnames): """Open interpreter""" for path in sorted(fnames): self.parent_widget.open_interpreter.emit(path) @Slot() def run(self, fnames=None): """Run Python scripts""" if fnames is None: fnames = self.get_selected_filenames() for fname in fnames: self.parent_widget.run.emit(fname) def remove_tree(self, dirname): """Remove whole directory tree Reimplemented in project explorer widget""" shutil.rmtree(dirname, onerror=misc.onerror) 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 %s?" ) % 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"), _("Unable to %s %s" "

    Error message:
    %s" ) % (action_str, fname, to_text_string(error))) return False @Slot() def delete(self, fnames=None): """Delete files""" if fnames is None: fnames = self.get_selected_filenames() multiple = len(fnames) > 1 yes_to_all = None for fname in fnames: spyproject_path = osp.join(fname,'.spyproject') if osp.isdir(fname) and osp.exists(spyproject_path): QMessageBox.information(self, _('File Explorer'), _("The current directory contains a " "project.

    " "If you want to delete" " the project, please go to " "Projects » Delete " "Project")) else: yes_to_all = self.delete_file(fname, multiple, yes_to_all) if yes_to_all is not None and not yes_to_all: # Canceled break def convert_notebook(self, fname): """Convert an IPython notebook to a Python script in editor""" try: script = nbexporter().from_filename(fname)[0] except Exception as e: QMessageBox.critical(self, _('Conversion error'), _("It was not possible to convert this " "notebook. The error is:\n\n") + \ to_text_string(e)) return self.parent_widget.sig_new_file.emit(script) @Slot() def convert_notebooks(self): """Convert IPython notebooks to Python scripts in editor""" fnames = self.get_selected_filenames() if not isinstance(fnames, (tuple, list)): fnames = [fnames] for fname in fnames: self.convert_notebook(fname) 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 %s and " "overwrite the existing file %s?" ) % (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"), _("Unable to rename file %s" "

    Error message:
    %s" ) % (osp.basename(fname), to_text_string(error))) @Slot() def show_in_external_file_explorer(self, fnames=None): """Show file in external file explorer""" if fnames is None: fnames = self.get_selected_filenames() show_in_external_file_explorer(fnames) @Slot() def rename(self, fnames=None): """Rename files""" if fnames is None: fnames = self.get_selected_filenames() if not isinstance(fnames, (tuple, list)): fnames = [fnames] for fname in fnames: self.rename_file(fname) @Slot() 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"), _("Unable to move %s" "

    Error message:
    %s" ) % (basename, to_text_string(error))) 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, _("Unable " "to create folder %s" "

    Error message:
    %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, _("Unable " "to create file %s" "

    Error message:
    %s" ) % (fname, to_text_string(error))) def new_folder(self, basedir): """New folder""" title = _('New folder') subtitle = _('Folder name:') self.create_new_folder(basedir, title, subtitle, is_package=False) def new_package(self, basedir): """New package""" title = _('New package') subtitle = _('Package name:') self.create_new_folder(basedir, title, subtitle, is_package=True) 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.redirect_stdio.emit(False) fname, _selfilter = getsavefilename(self, title, current_path, filters) self.parent_widget.redirect_stdio.emit(True) if fname: try: create_func(fname) return fname except EnvironmentError as error: QMessageBox.critical(self, _("New file"), _("Unable to create file %s" "

    Error message:
    %s" ) % (fname, to_text_string(error))) def new_file(self, basedir): """New file""" title = _("New file") filters = _("All files")+" (*)" def create_func(fname): """File creation callback""" if osp.splitext(fname)[1] in ('.py', '.pyw', '.ipy'): create_script(fname) else: with open(fname, 'wb') as f: f.write(to_binary_string('')) fname = self.create_new_file(basedir, title, filters, create_func) if fname is not None: self.open([fname]) def new_module(self, basedir): """New module""" title = _("New module") filters = _("Python scripts")+" (*.py *.pyw *.ipy)" create_func = lambda fname: self.parent_widget.create_module.emit(fname) self.create_new_file(basedir, title, filters, create_func) def go_to_parent_directory(self): pass #----- VCS actions def vcs_command(self, fnames, action): """VCS action (commit, browse)""" try: for path in sorted(fnames): vcs.run_vcs_tool(path, action) except vcs.ActionToolNotFound as error: msg = _("For %s support, please install one of the
    " "following tools:

    %s")\ % (error.vcsname, ', '.join(error.tools)) QMessageBox.critical(self, _("Error"), _("""Unable to find external program.

    %s""") % to_text_string(msg)) #----- Settings def get_scrollbar_position(self): """Return scrollbar positions""" return (self.horizontalScrollBar().value(), self.verticalScrollBar().value()) def set_scrollbar_position(self, position): """Set scrollbar positions""" # Scrollbars will be restored after the expanded state self._scrollbar_positions = position if self._to_be_loaded is not None and len(self._to_be_loaded) == 0: self.restore_scrollbar_positions() def restore_scrollbar_positions(self): """Restore scrollbar positions once tree is loaded""" hor, ver = self._scrollbar_positions self.horizontalScrollBar().setValue(hor) self.verticalScrollBar().setValue(ver) def get_expanded_state(self): """Return expanded state""" self.save_expanded_state() return self.__expanded_state def set_expanded_state(self, state): """Set expanded state""" self.__expanded_state = state self.restore_expanded_state() def save_expanded_state(self): """Save all items expanded state""" model = self.model() # If model is not installed, 'model' will be None: this happens when # using the Project Explorer without having selected a workspace yet if model is not None: self.__expanded_state = [] for idx in model.persistentIndexList(): if self.isExpanded(idx): self.__expanded_state.append(self.get_filename(idx)) def restore_directory_state(self, fname): """Restore directory expanded state""" root = osp.normpath(to_text_string(fname)) if not osp.exists(root): # Directory has been (re)moved outside Spyder return for basename in os.listdir(root): path = osp.normpath(osp.join(root, basename)) if osp.isdir(path) and path in self.__expanded_state: self.__expanded_state.pop(self.__expanded_state.index(path)) if self._to_be_loaded is None: self._to_be_loaded = [] self._to_be_loaded.append(path) self.setExpanded(self.get_index(path), True) if not self.__expanded_state and not is_pyqt46: self.fsmodel.directoryLoaded.disconnect(self.restore_directory_state) def follow_directories_loaded(self, fname): """Follow directories loaded during startup""" if self._to_be_loaded is None: return path = osp.normpath(to_text_string(fname)) if path in self._to_be_loaded: self._to_be_loaded.remove(path) if self._to_be_loaded is not None and len(self._to_be_loaded) == 0 \ and not is_pyqt46: self.fsmodel.directoryLoaded.disconnect( self.follow_directories_loaded) if self._scrollbar_positions is not None: # The tree view need some time to render branches: QTimer.singleShot(50, self.restore_scrollbar_positions) def restore_expanded_state(self): """Restore all items expanded state""" if self.__expanded_state is not None: # In the old project explorer, the expanded state was a dictionnary: if isinstance(self.__expanded_state, list) and not is_pyqt46: self.fsmodel.directoryLoaded.connect( self.restore_directory_state) self.fsmodel.directoryLoaded.connect( self.follow_directories_loaded) def filter_directories(self): """Filter the directories to show""" index = self.get_index('.spyproject') if index is not None: self.setRowHidden(index.row(), index.parent(), True) class ProxyModel(QSortFilterProxyModel): """Proxy model: filters tree view""" def __init__(self, parent): super(ProxyModel, self).__init__(parent) self.root_path = None self.path_list = [] self.setDynamicSortFilter(True) def setup_filter(self, root_path, path_list): """Setup proxy model filter parameters""" self.root_path = osp.normpath(to_text_string(root_path)) self.path_list = [osp.normpath(to_text_string(p)) for p in path_list] self.invalidateFilter() def sort(self, column, order=Qt.AscendingOrder): """Reimplement Qt method""" self.sourceModel().sort(column, order) def filterAcceptsRow(self, row, parent_index): """Reimplement Qt method""" if self.root_path is None: return True index = self.sourceModel().index(row, 0, parent_index) path = osp.normpath(to_text_string(self.sourceModel().filePath(index))) if self.root_path.startswith(path): # This is necessary because parent folders need to be scanned return True else: for p in self.path_list: if path == p or path.startswith(p+os.sep): return True else: return False def data(self, index, role): """Show tooltip with full path only for the root directory""" if role == Qt.ToolTipRole: root_dir = self.path_list[0].split(osp.sep)[-1] if index.data() == root_dir: return osp.join(self.root_path, root_dir) return QSortFilterProxyModel.data(self, index, role) class FilteredDirView(DirView): """Filtered file/directory tree view""" def __init__(self, parent=None): super(FilteredDirView, self).__init__(parent) self.proxymodel = None self.setup_proxy_model() self.root_path = None #---- Model def setup_proxy_model(self): """Setup proxy model""" self.proxymodel = ProxyModel(self) self.proxymodel.setSourceModel(self.fsmodel) def install_model(self): """Install proxy model""" if self.root_path is not None: self.setModel(self.proxymodel) def set_root_path(self, root_path): """Set root path""" self.root_path = root_path self.install_model() index = self.fsmodel.setRootPath(root_path) self.setRootIndex(self.proxymodel.mapFromSource(index)) def get_index(self, filename): """Return index associated with filename""" index = self.fsmodel.index(filename) if index.isValid() and index.model() is self.fsmodel: return self.proxymodel.mapFromSource(index) def set_folder_names(self, folder_names): """Set folder names""" assert self.root_path is not None path_list = [osp.join(self.root_path, dirname) for dirname in folder_names] self.proxymodel.setup_filter(self.root_path, path_list) def get_filename(self, index): """Return filename from index""" if index: path = self.fsmodel.filePath(self.proxymodel.mapToSource(index)) return osp.normpath(to_text_string(path)) def setup_project_view(self): """Setup view for projects""" for i in [1, 2, 3]: self.hideColumn(i) self.setHeaderHidden(True) # Disable the view of .spyproject. self.filter_directories() class ExplorerTreeWidget(DirView): """File/directory explorer tree widget show_cd_only: Show current directory only (True/False: enable/disable the option None: enable the option and do not allow the user to disable it)""" set_previous_enabled = Signal(bool) set_next_enabled = Signal(bool) def __init__(self, parent=None, show_cd_only=None): DirView.__init__(self, parent) self.history = [] self.histindex = None self.show_cd_only = show_cd_only self.__original_root_index = None self.__last_folder = None self.menu = None self.common_actions = None # Enable drag events self.setDragEnabled(True) #---- Context menu def setup_common_actions(self): """Setup context menu common actions""" actions = super(ExplorerTreeWidget, self).setup_common_actions() if self.show_cd_only is None: # Enabling the 'show current directory only' option but do not # allow the user to disable it self.show_cd_only = True else: # Show current directory only cd_only_action = create_action(self, _("Show current directory only"), toggled=self.toggle_show_cd_only) cd_only_action.setChecked(self.show_cd_only) self.toggle_show_cd_only(self.show_cd_only) actions.append(cd_only_action) return actions @Slot(bool) def toggle_show_cd_only(self, checked): """Toggle show current directory only mode""" self.parent_widget.sig_option_changed.emit('show_cd_only', checked) self.show_cd_only = checked if checked: if self.__last_folder is not None: self.set_current_folder(self.__last_folder) elif self.__original_root_index is not None: self.setRootIndex(self.__original_root_index) #---- Refreshing widget def set_current_folder(self, folder): """Set current folder and return associated model index""" index = self.fsmodel.setRootPath(folder) self.__last_folder = folder if self.show_cd_only: if self.__original_root_index is None: self.__original_root_index = self.rootIndex() self.setRootIndex(index) return index def get_current_folder(self): return self.__last_folder def refresh(self, new_path=None, force_current=False): """Refresh widget force=False: won't refresh widget if path has not changed""" if new_path is None: new_path = getcwd_or_home() if force_current: index = self.set_current_folder(new_path) self.expand(index) self.setCurrentIndex(index) self.set_previous_enabled.emit( self.histindex is not None and self.histindex > 0) self.set_next_enabled.emit(self.histindex is not None and \ self.histindex < len(self.history)-1) # Disable the view of .spyproject. self.filter_directories() #---- Events def directory_clicked(self, dirname): """Directory was just clicked""" self.chdir(directory=dirname) #---- Files/Directories Actions @Slot() def go_to_parent_directory(self): """Go to parent directory""" self.chdir(osp.abspath(osp.join(getcwd_or_home(), os.pardir))) @Slot() def go_to_previous_directory(self): """Back to previous directory""" self.histindex -= 1 self.chdir(browsing_history=True) @Slot() def go_to_next_directory(self): """Return to next directory""" self.histindex += 1 self.chdir(browsing_history=True) def update_history(self, directory): """Update browse history""" directory = osp.abspath(to_text_string(directory)) if directory in self.history: self.histindex = self.history.index(directory) 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) try: PermissionError FileNotFoundError except NameError: PermissionError = OSError if os.name == 'nt': FileNotFoundError = WindowsError else: FileNotFoundError = IOError 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")) except FileNotFoundError: # Handle renaming directories on the fly. See issue #5183 self.history.pop(self.histindex) class ExplorerWidget(QWidget): """Explorer widget""" sig_option_changed = Signal(str, object) sig_open_file = Signal(str) sig_new_file = Signal(str) redirect_stdio = Signal(bool) open_dir = Signal(str) def __init__(self, parent=None, name_filters=['*.py', '*.pyw'], show_all=False, show_cd_only=None, show_icontext=True): QWidget.__init__(self, parent) # Widgets self.treewidget = ExplorerTreeWidget(self, show_cd_only=show_cd_only) button_previous = QToolButton(self) button_next = QToolButton(self) button_parent = QToolButton(self) self.button_menu = QToolButton(self) menu = QMenu(self) self.action_widgets = [button_previous, button_next, button_parent, self.button_menu] # Actions icontext_action = create_action(self, _("Show icons and text"), toggled=self.toggle_icontext) previous_action = create_action(self, text=_("Previous"), icon=ima.icon('ArrowBack'), triggered=self.treewidget.go_to_previous_directory) next_action = create_action(self, text=_("Next"), icon=ima.icon('ArrowForward'), triggered=self.treewidget.go_to_next_directory) parent_action = create_action(self, text=_("Parent"), icon=ima.icon('ArrowUp'), triggered=self.treewidget.go_to_parent_directory) options_action = create_action(self, text='', tip=_('Options')) # Setup widgets self.treewidget.setup(name_filters=name_filters, show_all=show_all) self.treewidget.chdir(getcwd_or_home()) self.treewidget.common_actions += [None, icontext_action] button_previous.setDefaultAction(previous_action) previous_action.setEnabled(False) button_next.setDefaultAction(next_action) next_action.setEnabled(False) button_parent.setDefaultAction(parent_action) self.button_menu.setIcon(ima.icon('tooloptions')) self.button_menu.setPopupMode(QToolButton.InstantPopup) self.button_menu.setMenu(menu) add_actions(menu, self.treewidget.common_actions) options_action.setMenu(menu) self.toggle_icontext(show_icontext) icontext_action.setChecked(show_icontext) for widget in self.action_widgets: widget.setAutoRaise(True) widget.setIconSize(QSize(16, 16)) # Layouts blayout = QHBoxLayout() blayout.addWidget(button_previous) blayout.addWidget(button_next) blayout.addWidget(button_parent) blayout.addStretch() blayout.addWidget(self.button_menu) layout = create_plugin_layout(blayout, self.treewidget) self.setLayout(layout) # Signals and slots self.treewidget.set_previous_enabled.connect( previous_action.setEnabled) self.treewidget.set_next_enabled.connect(next_action.setEnabled) @Slot(bool) def toggle_icontext(self, state): """Toggle icon text""" self.sig_option_changed.emit('show_icontext', state) for widget in self.action_widgets: if widget is not self.button_menu: if state: widget.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) else: widget.setToolButtonStyle(Qt.ToolButtonIconOnly) #============================================================================== # Tests #============================================================================== class FileExplorerTest(QWidget): def __init__(self): QWidget.__init__(self) vlayout = QVBoxLayout() self.setLayout(vlayout) self.explorer = ExplorerWidget(self, show_cd_only=None) vlayout.addWidget(self.explorer) hlayout1 = QHBoxLayout() vlayout.addLayout(hlayout1) label = QLabel("Open file:") label.setAlignment(Qt.AlignRight) hlayout1.addWidget(label) self.label1 = QLabel() hlayout1.addWidget(self.label1) self.explorer.sig_open_file.connect(self.label1.setText) hlayout2 = QHBoxLayout() vlayout.addLayout(hlayout2) label = QLabel("Open dir:") label.setAlignment(Qt.AlignRight) hlayout2.addWidget(label) self.label2 = QLabel() hlayout2.addWidget(self.label2) self.explorer.open_dir.connect(self.label2.setText) hlayout3 = QHBoxLayout() vlayout.addLayout(hlayout3) label = QLabel("Option changed:") label.setAlignment(Qt.AlignRight) hlayout3.addWidget(label) self.label3 = QLabel() hlayout3.addWidget(self.label3) self.explorer.sig_option_changed.connect( lambda x, y: self.label3.setText('option_changed: %r, %r' % (x, y))) self.explorer.open_dir.connect( lambda: self.explorer.treewidget.refresh('..')) class ProjectExplorerTest(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) vlayout = QVBoxLayout() self.setLayout(vlayout) self.treewidget = FilteredDirView(self) self.treewidget.setup_view() self.treewidget.set_root_path(osp.dirname(osp.abspath(__file__))) self.treewidget.set_folder_names(['variableexplorer']) self.treewidget.setup_project_view() vlayout.addWidget(self.treewidget) def test(file_explorer): from spyder.utils.qthelpers import qapplication app = qapplication() if file_explorer: test = FileExplorerTest() else: test = ProjectExplorerTest() test.resize(640, 480) test.show() app.exec_() if __name__ == "__main__": test(file_explorer=True) test(file_explorer=False) spyder-3.2.6/spyder/widgets/onecolumntree.py0000664000175000017500000002001413026261006022020 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) # Third party imports from qtpy.QtCore import Slot from qtpy.QtWidgets import QTreeWidget, QMenu # Local imports from spyder.config.base import _ from spyder.utils import icon_manager as ima from spyder.utils.qthelpers import (add_actions, create_action, get_item_user_text) class OneColumnTree(QTreeWidget): """One-column tree widget with context menu, ...""" def __init__(self, parent): QTreeWidget.__init__(self, parent) self.setItemsExpandable(True) self.setColumnCount(1) self.itemActivated.connect(self.activated) self.itemClicked.connect(self.clicked) # Setup context menu self.menu = QMenu(self) self.collapse_all_action = None self.collapse_selection_action = None self.expand_all_action = None self.expand_selection_action = None self.common_actions = self.setup_common_actions() self.__expanded_state = None self.itemSelectionChanged.connect(self.item_selection_changed) self.item_selection_changed() def activated(self, item): """Double-click event""" raise NotImplementedError def clicked(self, item): pass def set_title(self, title): self.setHeaderLabels([title]) def setup_common_actions(self): """Setup context menu common actions""" self.collapse_all_action = create_action(self, text=_('Collapse all'), icon=ima.icon('collapse'), triggered=self.collapseAll) self.expand_all_action = create_action(self, text=_('Expand all'), icon=ima.icon('expand'), triggered=self.expandAll) self.restore_action = create_action(self, text=_('Restore'), tip=_('Restore original tree layout'), icon=ima.icon('restore'), triggered=self.restore) self.collapse_selection_action = create_action(self, text=_('Collapse selection'), icon=ima.icon('collapse_selection'), triggered=self.collapse_selection) self.expand_selection_action = create_action(self, text=_('Expand selection'), icon=ima.icon('expand_selection'), triggered=self.expand_selection) return [self.collapse_all_action, self.expand_all_action, self.restore_action, None, self.collapse_selection_action, self.expand_selection_action] def update_menu(self): self.menu.clear() items = self.selectedItems() actions = self.get_actions_from_items(items) if actions: actions.append(None) actions += self.common_actions add_actions(self.menu, actions) def get_actions_from_items(self, items): # Right here: add other actions if necessary # (reimplement this method) return [] @Slot() def restore(self): self.collapseAll() for item in self.get_top_level_items(): self.expandItem(item) def is_item_expandable(self, item): """To be reimplemented in child class See example in project explorer widget""" return True def __expand_item(self, item): if self.is_item_expandable(item): self.expandItem(item) for index in range(item.childCount()): child = item.child(index) self.__expand_item(child) @Slot() def expand_selection(self): items = self.selectedItems() if not items: items = self.get_top_level_items() for item in items: self.__expand_item(item) if items: self.scrollToItem(items[0]) def __collapse_item(self, item): self.collapseItem(item) for index in range(item.childCount()): child = item.child(index) self.__collapse_item(child) @Slot() def collapse_selection(self): items = self.selectedItems() if not items: items = self.get_top_level_items() for item in items: self.__collapse_item(item) if items: self.scrollToItem(items[0]) def item_selection_changed(self): """Item selection has changed""" is_selection = len(self.selectedItems()) > 0 self.expand_selection_action.setEnabled(is_selection) self.collapse_selection_action.setEnabled(is_selection) def get_top_level_items(self): """Iterate over top level items""" return [self.topLevelItem(_i) for _i in range(self.topLevelItemCount())] def get_items(self): """Return items (excluding top level items)""" itemlist = [] def add_to_itemlist(item): for index in range(item.childCount()): citem = item.child(index) itemlist.append(citem) add_to_itemlist(citem) for tlitem in self.get_top_level_items(): add_to_itemlist(tlitem) return itemlist def get_scrollbar_position(self): return (self.horizontalScrollBar().value(), self.verticalScrollBar().value()) def set_scrollbar_position(self, position): hor, ver = position self.horizontalScrollBar().setValue(hor) self.verticalScrollBar().setValue(ver) def get_expanded_state(self): self.save_expanded_state() return self.__expanded_state def set_expanded_state(self, state): self.__expanded_state = state self.restore_expanded_state() def save_expanded_state(self): """Save all items expanded state""" self.__expanded_state = {} def add_to_state(item): user_text = get_item_user_text(item) self.__expanded_state[hash(user_text)] = item.isExpanded() def browse_children(item): add_to_state(item) for index in range(item.childCount()): citem = item.child(index) user_text = get_item_user_text(citem) self.__expanded_state[hash(user_text)] = citem.isExpanded() browse_children(citem) for tlitem in self.get_top_level_items(): browse_children(tlitem) def restore_expanded_state(self): """Restore all items expanded state""" if self.__expanded_state is None: return for item in self.get_items()+self.get_top_level_items(): user_text = get_item_user_text(item) is_expanded = self.__expanded_state.get(hash(user_text)) if is_expanded is not None: item.setExpanded(is_expanded) def sort_top_level_items(self, key): """Sorting tree wrt top level items""" self.save_expanded_state() items = sorted([self.takeTopLevelItem(0) for index in range(self.topLevelItemCount())], key=key) for index, item in enumerate(items): self.insertTopLevelItem(index, item) self.restore_expanded_state() def contextMenuEvent(self, event): """Override Qt method""" self.update_menu() self.menu.popup(event.globalPos()) spyder-3.2.6/spyder/widgets/colors.py0000664000175000017500000000554213026261006020453 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) # Third party imports from qtpy.QtCore import Property, QSize, Signal, Slot from qtpy.QtGui import QColor, QIcon, QPixmap from qtpy.QtWidgets import QColorDialog, QHBoxLayout, QLineEdit, QPushButton # Local imports from spyder.py3compat import is_text_string class ColorButton(QPushButton): """ Color choosing push button """ colorChanged = Signal(QColor) def __init__(self, parent=None): QPushButton.__init__(self, parent) self.setFixedSize(20, 20) self.setIconSize(QSize(12, 12)) self.clicked.connect(self.choose_color) self._color = QColor() def choose_color(self): color = QColorDialog.getColor(self._color, self.parentWidget(), 'Select Color', QColorDialog.ShowAlphaChannel) if color.isValid(): self.set_color(color) def get_color(self): return self._color @Slot(QColor) def set_color(self, color): if color != self._color: self._color = color self.colorChanged.emit(self._color) pixmap = QPixmap(self.iconSize()) pixmap.fill(color) self.setIcon(QIcon(pixmap)) color = Property("QColor", get_color, set_color) def text_to_qcolor(text): """ Create a QColor from specified string Avoid warning from Qt when an invalid QColor is instantiated """ color = QColor() text = str(text) if not is_text_string(text): return color if text.startswith('#') and len(text)==7: correct = '#0123456789abcdef' for char in text: if char.lower() not in correct: return color elif text not in list(QColor.colorNames()): return color color.setNamedColor(text) return color class ColorLayout(QHBoxLayout): """Color-specialized QLineEdit layout""" def __init__(self, color, parent=None): QHBoxLayout.__init__(self) assert isinstance(color, QColor) self.lineedit = QLineEdit(color.name(), parent) self.lineedit.textChanged.connect(self.update_color) self.addWidget(self.lineedit) self.colorbtn = ColorButton(parent) self.colorbtn.color = color self.colorbtn.colorChanged.connect(self.update_text) self.addWidget(self.colorbtn) def update_color(self, text): color = text_to_qcolor(text) if color.isValid(): self.colorbtn.color = color def update_text(self, color): self.lineedit.setText(color.name()) def text(self): return self.lineedit.text() spyder-3.2.6/spyder/widgets/mixins.py0000664000175000017500000007713613224740762020504 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Mix-in classes These classes were created to be able to provide Spyder's regular text and console widget features to an independant widget based on QTextEdit for the IPython console plugin. """ # Standard library imports from xml.sax.saxutils import escape import os import os.path as osp import re import sre_constants import textwrap # Third party imports from qtpy.QtCore import QPoint, Qt from qtpy.QtGui import QCursor, QTextCursor, QTextDocument from qtpy.QtWidgets import QApplication, QToolTip from qtpy import QT_VERSION # Local imports from spyder.config.base import _ from spyder.py3compat import is_text_string, to_text_string from spyder.utils import encoding, sourcecode, programs from spyder.utils.dochelpers import (getargspecfromtext, getobj, getsignaturefromtext) from spyder.utils.misc import get_error_match from spyder.widgets.arraybuilder import NumpyArrayDialog QT55_VERSION = programs.check_version(QT_VERSION, "5.5", ">=") if QT55_VERSION: from qtpy.QtCore import QRegularExpression else: from qtpy.QtCore import QRegExp class BaseEditMixin(object): def __init__(self): self.eol_chars = None self.calltip_size = 600 #------Line number area def get_linenumberarea_width(self): """Return line number area width""" # Implemented in CodeEditor, but needed for calltip/completion widgets return 0 #------Calltips def _format_signature(self, text): formatted_lines = [] name = text.split('(')[0] rows = textwrap.wrap(text, width=50, subsequent_indent=' '*(len(name)+1)) for r in rows: r = escape(r) # Escape most common html chars r = r.replace(' ', ' ') for char in ['=', ',', '(', ')', '*', '**']: r = r.replace(char, '' + \ char + '') formatted_lines.append(r) signature = '
    '.join(formatted_lines) return signature, rows def show_calltip(self, title, text, signature=False, color='#2D62FF', at_line=None, at_position=None): """Show calltip""" if text is None or len(text) == 0: return # Saving cursor position: if at_position is None: at_position = self.get_position('cursor') self.calltip_position = at_position # Preparing text: if signature: text, wrapped_textlines = self._format_signature(text) else: if isinstance(text, list): text = "\n ".join(text) text = text.replace('\n', '
    ') if len(text) > self.calltip_size: text = text[:self.calltip_size] + " ..." # Formatting text font = self.font() size = font.pointSize() family = font.family() format1 = '

    '\ % (family, size, color) format2 = '
    '\ % (family, size-1 if size > 9 else size) tiptext = format1 + ('%s
    ' % title) + '
    ' + \ format2 + text + "
    " # Showing tooltip at cursor position: cx, cy = self.get_coordinates('cursor') if at_line is not None: cx = 5 cursor = QTextCursor(self.document().findBlockByNumber(at_line-1)) cy = self.cursorRect(cursor).top() point = self.mapToGlobal(QPoint(cx, cy)) point.setX(point.x()+self.get_linenumberarea_width()) point.setY(point.y()+font.pointSize()+5) if signature: self.calltip_widget.show_tip(point, tiptext, wrapped_textlines) else: QToolTip.showText(point, tiptext) #------EOL characters def set_eol_chars(self, text): """Set widget end-of-line (EOL) characters from text (analyzes text)""" if not is_text_string(text): # testing for QString (PyQt API#1) text = to_text_string(text) eol_chars = sourcecode.get_eol_chars(text) is_document_modified = eol_chars is not None and self.eol_chars is not None self.eol_chars = eol_chars if is_document_modified: self.document().setModified(True) if self.sig_eol_chars_changed is not None: self.sig_eol_chars_changed.emit(eol_chars) def get_line_separator(self): """Return line separator based on current EOL mode""" if self.eol_chars is not None: return self.eol_chars else: return os.linesep def get_text_with_eol(self): """Same as 'toPlainText', replace '\n' by correct end-of-line characters""" utext = to_text_string(self.toPlainText()) lines = utext.splitlines() linesep = self.get_line_separator() txt = linesep.join(lines) if utext.endswith('\n'): txt += linesep return txt #------Positions, coordinates (cursor, EOF, ...) def get_position(self, subject): """Get offset in character for the given subject from the start of text edit area""" cursor = self.textCursor() if subject == 'cursor': pass elif subject == 'sol': cursor.movePosition(QTextCursor.StartOfBlock) elif subject == 'eol': cursor.movePosition(QTextCursor.EndOfBlock) elif subject == 'eof': cursor.movePosition(QTextCursor.End) elif subject == 'sof': cursor.movePosition(QTextCursor.Start) else: # Assuming that input argument was already a position return subject return cursor.position() def get_coordinates(self, position): position = self.get_position(position) cursor = self.textCursor() cursor.setPosition(position) point = self.cursorRect(cursor).center() return point.x(), point.y() def get_cursor_line_column(self): """Return cursor (line, column) numbers""" cursor = self.textCursor() return cursor.blockNumber(), cursor.columnNumber() def get_cursor_line_number(self): """Return cursor line number""" return self.textCursor().blockNumber()+1 def set_cursor_position(self, position): """Set cursor position""" position = self.get_position(position) cursor = self.textCursor() cursor.setPosition(position) self.setTextCursor(cursor) self.ensureCursorVisible() def move_cursor(self, chars=0): """Move cursor to left or right (unit: characters)""" direction = QTextCursor.Right if chars > 0 else QTextCursor.Left for _i in range(abs(chars)): self.moveCursor(direction, QTextCursor.MoveAnchor) def is_cursor_on_first_line(self): """Return True if cursor is on the first line""" cursor = self.textCursor() cursor.movePosition(QTextCursor.StartOfBlock) return cursor.atStart() def is_cursor_on_last_line(self): """Return True if cursor is on the last line""" cursor = self.textCursor() cursor.movePosition(QTextCursor.EndOfBlock) return cursor.atEnd() def is_cursor_at_end(self): """Return True if cursor is at the end of the text""" return self.textCursor().atEnd() def is_cursor_before(self, position, char_offset=0): """Return True if cursor is before *position*""" position = self.get_position(position) + char_offset cursor = self.textCursor() cursor.movePosition(QTextCursor.End) if position < cursor.position(): cursor.setPosition(position) return self.textCursor() < cursor def __move_cursor_anchor(self, what, direction, move_mode): assert what in ('character', 'word', 'line') if what == 'character': if direction == 'left': self.moveCursor(QTextCursor.PreviousCharacter, move_mode) elif direction == 'right': self.moveCursor(QTextCursor.NextCharacter, move_mode) elif what == 'word': if direction == 'left': self.moveCursor(QTextCursor.PreviousWord, move_mode) elif direction == 'right': self.moveCursor(QTextCursor.NextWord, move_mode) elif what == 'line': if direction == 'down': self.moveCursor(QTextCursor.NextBlock, move_mode) elif direction == 'up': self.moveCursor(QTextCursor.PreviousBlock, move_mode) def move_cursor_to_next(self, what='word', direction='left'): """ Move cursor to next *what* ('word' or 'character') toward *direction* ('left' or 'right') """ self.__move_cursor_anchor(what, direction, QTextCursor.MoveAnchor) #------Selection def clear_selection(self): """Clear current selection""" cursor = self.textCursor() cursor.clearSelection() self.setTextCursor(cursor) def extend_selection_to_next(self, what='word', direction='left'): """ Extend selection to next *what* ('word' or 'character') toward *direction* ('left' or 'right') """ self.__move_cursor_anchor(what, direction, QTextCursor.KeepAnchor) #------Text: get, set, ... def __select_text(self, position_from, position_to): position_from = self.get_position(position_from) position_to = self.get_position(position_to) cursor = self.textCursor() cursor.setPosition(position_from) cursor.setPosition(position_to, QTextCursor.KeepAnchor) return cursor def get_text_line(self, line_nb): """Return text line at line number *line_nb*""" # Taking into account the case when a file ends in an empty line, # since splitlines doesn't return that line as the last element # TODO: Make this function more efficient try: return to_text_string(self.toPlainText()).splitlines()[line_nb] except IndexError: return self.get_line_separator() def get_text(self, position_from, position_to): """ Return text between *position_from* and *position_to* Positions may be positions or 'sol', 'eol', 'sof', 'eof' or 'cursor' """ cursor = self.__select_text(position_from, position_to) text = to_text_string(cursor.selectedText()) all_text = position_from == 'sof' and position_to == 'eof' if text and not all_text: while text.endswith("\n"): text = text[:-1] while text.endswith(u"\u2029"): text = text[:-1] return text def get_character(self, position, offset=0): """Return character at *position* with the given offset.""" position = self.get_position(position) + offset cursor = self.textCursor() cursor.movePosition(QTextCursor.End) if position < cursor.position(): cursor.setPosition(position) cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor) return to_text_string(cursor.selectedText()) else: return '' def insert_text(self, text): """Insert text at cursor position""" if not self.isReadOnly(): self.textCursor().insertText(text) def replace_text(self, position_from, position_to, text): cursor = self.__select_text(position_from, position_to) cursor.removeSelectedText() cursor.insertText(text) def remove_text(self, position_from, position_to): cursor = self.__select_text(position_from, position_to) cursor.removeSelectedText() 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()) # find a valid python variable name match = re.findall(r'([^\d\W]\w*)', text, re.UNICODE) if match: return match[0] def get_current_line(self): """Return current line's text""" cursor = self.textCursor() cursor.select(QTextCursor.BlockUnderCursor) return to_text_string(cursor.selectedText()) def get_current_line_to_cursor(self): """Return text from prompt to cursor""" return self.get_text(self.current_prompt_pos, 'cursor') def get_line_number_at(self, coordinates): """Return line number at *coordinates* (QPoint)""" cursor = self.cursorForPosition(coordinates) return cursor.blockNumber()-1 def get_line_at(self, coordinates): """Return line at *coordinates* (QPoint)""" cursor = self.cursorForPosition(coordinates) cursor.select(QTextCursor.BlockUnderCursor) return to_text_string(cursor.selectedText()).replace(u'\u2029', '') def get_word_at(self, coordinates): """Return word at *coordinates* (QPoint)""" cursor = self.cursorForPosition(coordinates) cursor.select(QTextCursor.WordUnderCursor) return to_text_string(cursor.selectedText()) def get_block_indentation(self, block_nb): """Return line indentation (character number)""" text = to_text_string(self.document().findBlockByNumber(block_nb).text()) text = text.replace("\t", " "*self.tab_stop_width_spaces) return len(text)-len(text.lstrip()) def get_selection_bounds(self): """Return selection bounds (block numbers)""" cursor = self.textCursor() start, end = cursor.selectionStart(), cursor.selectionEnd() block_start = self.document().findBlock(start) block_end = self.document().findBlock(end) return sorted([block_start.blockNumber(), block_end.blockNumber()]) #------Text selection def has_selected_text(self): """Returns True if some text is selected""" return bool(to_text_string(self.textCursor().selectedText())) def get_selected_text(self): """ Return text selected by current text cursor, converted in unicode Replace the unicode line separator character \u2029 by the line separator characters returned by get_line_separator """ return to_text_string(self.textCursor().selectedText()).replace(u"\u2029", self.get_line_separator()) def remove_selected_text(self): """Delete selected text""" self.textCursor().removeSelectedText() 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() #------Find/replace 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 find_text(self, text, changed=True, forward=True, case=False, words=False, regexp=False): """Find text""" cursor = self.textCursor() findflag = QTextDocument.FindFlag() if not forward: findflag = findflag | QTextDocument.FindBackward if case: findflag = findflag | QTextDocument.FindCaseSensitively moves = [QTextCursor.NoMove] if forward: moves += [QTextCursor.NextWord, QTextCursor.Start] if changed: if to_text_string(cursor.selectedText()): new_position = min([cursor.selectionStart(), cursor.selectionEnd()]) cursor.setPosition(new_position) else: cursor.movePosition(QTextCursor.PreviousWord) else: moves += [QTextCursor.End] if not regexp: text = re.escape(to_text_string(text)) if QT55_VERSION: pattern = QRegularExpression(r"\b{}\b".format(text) if words else text) if case: pattern.setPatternOptions( QRegularExpression.CaseInsensitiveOption) else: pattern = QRegExp(r"\b{}\b".format(text) if words else text, Qt.CaseSensitive if case else Qt.CaseInsensitive, QRegExp.RegExp2) for move in moves: cursor.movePosition(move) if regexp and '\\n' in text: # Multiline regular expression found_cursor = self.find_multiline_pattern(pattern, cursor, findflag) else: # Single line find: using the QTextDocument's find function, # probably much more efficient than ours found_cursor = self.document().find(pattern, cursor, findflag) if found_cursor is not None and not found_cursor.isNull(): self.setTextCursor(found_cursor) return True return False def is_editor(self): """Needs to be overloaded in the codeeditor where it will be True""" return False def get_number_matches(self, pattern, source_text='', case=False): """Get the number of matches for the searched text.""" pattern = to_text_string(pattern) if not pattern: return 0 if not source_text: source_text = to_text_string(self.toPlainText()) try: if case: regobj = re.compile(pattern) else: regobj = re.compile(pattern, re.IGNORECASE) except sre_constants.error: return number_matches = 0 for match in regobj.finditer(source_text): number_matches += 1 return number_matches def get_match_number(self, pattern, case=False): """Get number of the match for the searched text.""" position = self.textCursor().position() source_text = self.get_text(position_from='sof', position_to=position) match_number = self.get_number_matches(pattern, source_text=source_text, case=case) return match_number # --- Numpy matrix/array helper / See 'spyder/widgets/arraybuilder.py' def enter_array_inline(self): """ """ self._enter_array(True) def enter_array_table(self): """ """ self._enter_array(False) def _enter_array(self, inline): """ """ offset = self.get_position('cursor') - self.get_position('sol') rect = self.cursorRect() dlg = NumpyArrayDialog(self, inline, offset) # TODO: adapt to font size x = rect.left() x = x + self.get_linenumberarea_width() - 14 y = rect.top() + (rect.bottom() - rect.top())/2 y = y - dlg.height()/2 - 3 pos = QPoint(x, y) dlg.move(self.mapToGlobal(pos)) # called from editor if self.is_editor(): python_like_check = self.is_python_like() suffix = '\n' # called from a console else: python_like_check = True suffix = '' if python_like_check and dlg.exec_(): text = dlg.text() + suffix if text != '': cursor = self.textCursor() cursor.beginEditBlock() cursor.insertText(text) cursor.endEditBlock() class TracebackLinksMixin(object): """ """ QT_CLASS = None go_to_error = None def __init__(self): self.__cursor_changed = False self.setMouseTracking(True) #------Mouse events def mouseReleaseEvent(self, event): """Go to error""" self.QT_CLASS.mouseReleaseEvent(self, event) text = self.get_line_at(event.pos()) if get_error_match(text) and not self.has_selected_text(): if self.go_to_error is not None: self.go_to_error.emit(text) def mouseMoveEvent(self, event): """Show Pointing Hand Cursor on error messages""" text = self.get_line_at(event.pos()) if get_error_match(text): if not self.__cursor_changed: QApplication.setOverrideCursor(QCursor(Qt.PointingHandCursor)) self.__cursor_changed = True event.accept() return if self.__cursor_changed: QApplication.restoreOverrideCursor() self.__cursor_changed = False self.QT_CLASS.mouseMoveEvent(self, event) def leaveEvent(self, event): """If cursor has not been restored yet, do it now""" if self.__cursor_changed: QApplication.restoreOverrideCursor() self.__cursor_changed = False self.QT_CLASS.leaveEvent(self, event) class GetHelpMixin(object): def __init__(self): self.help = None self.help_enabled = False def set_help(self, help_plugin): """Set Help DockWidget reference""" self.help = help_plugin def set_help_enabled(self, state): self.help_enabled = state def inspect_current_object(self): text = '' text1 = self.get_text('sol', 'cursor') tl1 = re.findall(r'([a-zA-Z_]+[0-9a-zA-Z_\.]*)', text1) if tl1 and text1.endswith(tl1[-1]): text += tl1[-1] text2 = self.get_text('cursor', 'eol') tl2 = re.findall(r'([0-9a-zA-Z_\.]+[0-9a-zA-Z_\.]*)', text2) if tl2 and text2.startswith(tl2[0]): text += tl2[0] if text: self.show_object_info(text, force=True) def show_object_info(self, text, call=False, force=False): """Show signature calltip and/or docstring in the Help plugin""" text = to_text_string(text) # Show docstring help_enabled = self.help_enabled or force if force and self.help is not None: self.help.dockwidget.setVisible(True) self.help.dockwidget.raise_() if help_enabled and (self.help is not None) and \ (self.help.dockwidget.isVisible()): # Help widget exists and is visible if hasattr(self, 'get_doc'): self.help.set_shell(self) else: self.help.set_shell(self.parent()) self.help.set_object_text(text, ignore_unknown=False) self.setFocus() # if help was not at top level, raising it to # top will automatically give it focus because of # the visibility_changed signal, so we must give # focus back to shell # Show calltip if call and self.calltips: # Display argument list if this is a function call iscallable = self.iscallable(text) if iscallable is not None: if iscallable: arglist = self.get_arglist(text) name = text.split('.')[-1] argspec = signature = '' if isinstance(arglist, bool): arglist = [] if arglist: argspec = '(' + ''.join(arglist) + ')' else: doc = self.get__doc__(text) if doc is not None: # This covers cases like np.abs, whose docstring is # the same as np.absolute and because of that a # proper signature can't be obtained correctly argspec = getargspecfromtext(doc) if not argspec: signature = getsignaturefromtext(doc, name) if argspec or signature: if argspec: tiptext = name + argspec else: tiptext = signature self.show_calltip(_("Arguments"), tiptext, signature=True, color='#2D62FF') def get_last_obj(self, last=False): """ Return the last valid object on the current line """ return getobj(self.get_current_line_to_cursor(), last=last) class SaveHistoryMixin(object): INITHISTORY = None SEPARATOR = None HISTORY_FILENAMES = [] append_to_history = None def __init__(self, history_filename=''): self.history_filename = history_filename self.create_history_filename() def create_history_filename(self): """Create history_filename with INITHISTORY if it doesn't exist.""" if self.history_filename and not osp.isfile(self.history_filename): encoding.writelines(self.INITHISTORY, self.history_filename) 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 self.HISTORY_FILENAMES: self.HISTORY_FILENAMES.append(self.history_filename) text = self.SEPARATOR + text encoding.write(text, self.history_filename, mode='ab') if self.append_to_history is not None: self.append_to_history.emit(self.history_filename, text) class BrowseHistoryMixin(object): def __init__(self): self.history = [] self.histidx = None self.hist_wholeline = False def clear_line(self): """Clear current line (without clearing console prompt)""" self.remove_text(self.current_prompt_pos, 'eof') def browse_history(self, backward): """Browse history""" if self.is_cursor_before('eol') and self.hist_wholeline: self.hist_wholeline = False tocursor = self.get_current_line_to_cursor() text, self.histidx = self.find_in_history(tocursor, self.histidx, backward) if text is not None: if self.hist_wholeline: self.clear_line() self.insert_text(text) else: cursor_position = self.get_position('cursor') # Removing text from cursor to the end of the line self.remove_text('cursor', 'eol') # Inserting history text self.insert_text(text) self.set_cursor_position(cursor_position) def find_in_history(self, tocursor, start_idx, backward): """Find text 'tocursor' in history, from index 'start_idx'""" if start_idx is None: start_idx = len(self.history) # Finding text in history step = -1 if backward else 1 idx = start_idx if len(tocursor) == 0 or self.hist_wholeline: idx += step if idx >= len(self.history) or len(self.history) == 0: return "", len(self.history) elif idx < 0: idx = 0 self.hist_wholeline = True return self.history[idx], idx else: for index in range(len(self.history)): idx = (start_idx+step*(index+1)) % len(self.history) entry = self.history[idx] if entry.startswith(tocursor): return entry[len(tocursor):], idx else: return None, start_idx def reset_search_pos(self): """Reset the position from which to search the history""" self.histidx = None spyder-3.2.6/spyder/widgets/dependencies.py0000664000175000017500000001674713224740762021624 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Module checking Spyder runtime dependencies""" # Standard library imports import sys # Third party imports from qtpy.compat import to_qvariant from qtpy.QtCore import Qt, QModelIndex, QAbstractTableModel from qtpy.QtGui import QColor from qtpy.QtWidgets import (QApplication, QDialog, QDialogButtonBox, QHBoxLayout, QItemDelegate, QLabel, QPushButton, QTableView, QVBoxLayout) # Local imports from spyder import __version__ from spyder.config.base import _ from spyder.utils import icon_manager as ima class DependenciesTableModel(QAbstractTableModel): def __init__(self, parent, dependencies): QAbstractTableModel.__init__(self, parent) self.dependencies = None self.set_data(dependencies) def set_data(self, dependencies): """Set model data""" self.dependencies = dependencies self.reset() def rowCount(self, qindex=QModelIndex()): """Array row number""" return len(self.dependencies) def columnCount(self, qindex=QModelIndex()): """Array column count""" return 4 def sort(self, column, order=Qt.DescendingOrder): """Overriding sort method""" if column == 0: self.dependencies.sort(key=lambda dep: getattr(dep, 'modname')) elif column == 1: pass elif column == 2: pass elif column == 3: pass self.reset() def headerData(self, section, orientation, role=Qt.DisplayRole): """Overriding method headerData""" if role != Qt.DisplayRole: return to_qvariant() i_column = int(section) if orientation == Qt.Horizontal: headers = (_("Module"), _(" Required "), _(" Installed "), _("Provided features")) return to_qvariant( headers[i_column] ) else: return to_qvariant() def get_value(self, index): """Return current value""" dep = self.dependencies[index.row()] return (dep.modname, dep.required_version, dep.get_installed_version(), dep.features)[index.column()] def data(self, index, role=Qt.DisplayRole): """Return data at table index""" if not index.isValid(): return to_qvariant() dep = self.dependencies[index.row()] if role == Qt.DisplayRole: if index.column() == 0: value = self.get_value(index) return to_qvariant(value) else: value = self.get_value(index) return to_qvariant(value) elif role == Qt.TextAlignmentRole: return to_qvariant(int(Qt.AlignLeft|Qt.AlignVCenter)) elif role == Qt.BackgroundColorRole: from spyder.dependencies import Dependency status = dep.get_status() if status == Dependency.NOK: color = QColor(Qt.red) color.setAlphaF(.25) return to_qvariant(color) def reset(self): self.beginResetModel() self.endResetModel() class DependenciesDelegate(QItemDelegate): def __init__(self, parent=None): QItemDelegate.__init__(self, parent) class DependenciesTableView(QTableView): def __init__(self, parent, data): QTableView.__init__(self, parent) self.model = DependenciesTableModel(self, data) self.setModel(self.model) self.delegate = DependenciesDelegate(self) self.setItemDelegate(self.delegate) self.setup_table() def setup_table(self): """Setup table""" self.horizontalHeader().setStretchLastSection(True) self.adjust_columns() self.columnAt(0) # Sorting columns self.setSortingEnabled(False) self.sortByColumn(0, Qt.DescendingOrder) def adjust_columns(self): """Resize three first columns to contents""" for col in range(3): self.resizeColumnToContents(col) class DependenciesDialog(QDialog): def __init__(self, parent): QDialog.__init__(self, parent) self.setWindowTitle("Spyder %s: %s" % (__version__, _("Dependencies"))) self.setWindowIcon(ima.icon('tooloptions')) self.setModal(True) self.view = DependenciesTableView(self, []) opt_mods = ['NumPy', 'Matplotlib', 'Pandas', 'SymPy', 'Cython'] self.label = QLabel(_("Spyder depends on several Python modules to " "provide the right functionality for all its " "panes. The table below shows the required " "and installed versions (if any) of all of " "them.

    " "Note: You can safely use Spyder " "without the following modules installed: " "%s and %s.

    " "Please also note that new " "dependencies or changed ones will be correctly " "detected only after Spyder is restarted.") % (', '.join(opt_mods[:-1]), opt_mods[-1])) self.label.setWordWrap(True) self.label.setAlignment(Qt.AlignJustify) self.label.setContentsMargins(5, 8, 12, 10) btn = QPushButton(_("Copy to clipboard"), ) btn.clicked.connect(self.copy_to_clipboard) bbox = QDialogButtonBox(QDialogButtonBox.Ok) bbox.accepted.connect(self.accept) hlayout = QHBoxLayout() hlayout.addWidget(btn) hlayout.addStretch() hlayout.addWidget(bbox) vlayout = QVBoxLayout() vlayout.addWidget(self.label) vlayout.addWidget(self.view) vlayout.addLayout(hlayout) self.setLayout(vlayout) self.resize(630, 420) def exec_(self): self.show() # we need an explicit show() because resizeRowsToContents() does only # work correctly after the widget has been drawn. Without this the # dimensions are not known yet. self.view.resizeRowsToContents() super(DependenciesDialog, self).exec_() def set_data(self, dependencies): self.view.model.set_data(dependencies) self.view.adjust_columns() self.view.sortByColumn(0, Qt.DescendingOrder) def copy_to_clipboard(self): from spyder.dependencies import status QApplication.clipboard().setText(status()) def test(): """Run dependency widget test""" from spyder import dependencies # Test sample dependencies.add("IPython", "Enhanced Python interpreter", ">=0.13") dependencies.add("matplotlib", "Interactive data plotting", ">=1.0") dependencies.add("sympy", "Symbolic Mathematics", ">=10.0") dependencies.add("foo", "Non-existent module", ">=1.0") from spyder.utils.qthelpers import qapplication app = qapplication() dlg = DependenciesDialog(None) dlg.set_data(dependencies.DEPENDENCIES) dlg.show() sys.exit(dlg.exec_()) if __name__ == '__main__': test() spyder-3.2.6/spyder/widgets/status.py0000664000175000017500000002103113211142273020464 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Status bar widgets.""" # Standard library imports import os # Third party imports from qtpy.QtCore import Qt, QTimer from qtpy.QtWidgets import QHBoxLayout, QLabel, QWidget # Local imports from spyder import dependencies from spyder.config.base import _ from spyder.config.gui import get_font from spyder.py3compat import to_text_string if not os.name == 'nt': PSUTIL_REQVER = '>=0.3' dependencies.add("psutil", _("CPU and memory usage info in the status bar"), required_version=PSUTIL_REQVER) class StatusBarWidget(QWidget): """Status bar widget base.""" def __init__(self, parent, statusbar): """Status bar widget base.""" super(StatusBarWidget, self).__init__(parent) self.label_font = get_font(option='rich_font') self.label_font.setPointSize(self.font().pointSize()) self.label_font.setBold(True) # Layouts layout = QHBoxLayout() layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) # Setup statusbar.addPermanentWidget(self) # ============================================================================= # Main window-related status bar widgets # ============================================================================= class BaseTimerStatus(StatusBarWidget): """Status bar widget base for widgets that update based on timers.""" TITLE = None TIP = None def __init__(self, parent, statusbar): """Status bar widget base for widgets that update based on timers.""" super(BaseTimerStatus, self).__init__(parent, statusbar) # Widgets self.label = QLabel(self.TITLE) self.value = QLabel() # Widget setup self.setToolTip(self.TIP) self.value.setAlignment(Qt.AlignRight) self.value.setFont(self.label_font) fm = self.value.fontMetrics() self.value.setMinimumWidth(fm.width('000%')) # Layout layout = self.layout() layout.addWidget(self.label) layout.addWidget(self.value) layout.addSpacing(20) # Setup if self.is_supported(): self.timer = QTimer() self.timer.timeout.connect(self.update_label) self.timer.start(2000) else: self.timer = None self.hide() def set_interval(self, interval): """Set timer interval (ms).""" if self.timer is not None: self.timer.setInterval(interval) def import_test(self): """Raise ImportError if feature is not supported.""" raise NotImplementedError def is_supported(self): """Return True if feature is supported.""" try: self.import_test() return True except ImportError: return False def get_value(self): """Return value (e.g. CPU or memory usage).""" raise NotImplementedError def update_label(self): """Update status label widget, if widget is visible.""" if self.isVisible(): self.value.setText('%d %%' % self.get_value()) class MemoryStatus(BaseTimerStatus): """Status bar widget for system memory usage.""" TITLE = _("Memory:") TIP = _("Memory usage status: " "requires the `psutil` (>=v0.3) library on non-Windows platforms") def import_test(self): """Raise ImportError if feature is not supported.""" from spyder.utils.system import memory_usage # analysis:ignore def get_value(self): """Return memory usage.""" from spyder.utils.system import memory_usage return memory_usage() class CPUStatus(BaseTimerStatus): """Status bar widget for system cpu usage.""" TITLE = _("CPU:") TIP = _("CPU usage status: requires the `psutil` (>=v0.3) library") def import_test(self): """Raise ImportError if feature is not supported.""" from spyder.utils import programs if not programs.is_module_installed('psutil', '>=0.2.0'): # The `interval` argument in `psutil.cpu_percent` function # was introduced in v0.2.0 raise ImportError def get_value(self): """Return CPU usage.""" import psutil return psutil.cpu_percent(interval=0) # ============================================================================= # Editor-related status bar widgets # ============================================================================= class ReadWriteStatus(StatusBarWidget): """Status bar widget for current file read/write mode.""" def __init__(self, parent, statusbar): """Status bar widget for current file read/write mode.""" super(ReadWriteStatus, self).__init__(parent, statusbar) # Widget self.label = QLabel(_("Permissions:")) self.readwrite = QLabel() # Widget setup self.label.setAlignment(Qt.AlignRight) self.readwrite.setFont(self.label_font) # Layouts layout = self.layout() layout.addWidget(self.label) layout.addWidget(self.readwrite) layout.addSpacing(20) def readonly_changed(self, readonly): """Update read/write file status.""" readwrite = "R" if readonly else "RW" self.readwrite.setText(readwrite.ljust(3)) class EOLStatus(StatusBarWidget): """Status bar widget for the current file end of line.""" def __init__(self, parent, statusbar): """Status bar widget for the current file end of line.""" super(EOLStatus, self).__init__(parent, statusbar) # Widget self.label = QLabel(_("End-of-lines:")) self.eol = QLabel() # Widget setup self.label.setAlignment(Qt.AlignRight) self.eol.setFont(self.label_font) # Layouts layout = self.layout() layout.addWidget(self.label) layout.addWidget(self.eol) layout.addSpacing(20) def eol_changed(self, os_name): """Update end of line status.""" os_name = to_text_string(os_name) self.eol.setText({"nt": "CRLF", "posix": "LF"}.get(os_name, "CR")) class EncodingStatus(StatusBarWidget): """Status bar widget for the current file encoding.""" def __init__(self, parent, statusbar): """Status bar widget for the current file encoding.""" super(EncodingStatus, self).__init__(parent, statusbar) # Widgets self.label = QLabel(_("Encoding:")) self.encoding = QLabel() # Widget setup self.label.setAlignment(Qt.AlignRight) self.encoding.setFont(self.label_font) # Layouts layout = self.layout() layout.addWidget(self.label) layout.addWidget(self.encoding) layout.addSpacing(20) def encoding_changed(self, encoding): """Update encoding of current file.""" self.encoding.setText(str(encoding).upper().ljust(15)) class CursorPositionStatus(StatusBarWidget): """Status bar widget for the current file cursor postion.""" def __init__(self, parent, statusbar): """Status bar widget for the current file cursor postion.""" super(CursorPositionStatus, self).__init__(parent, statusbar) # Widget self.label_line = QLabel(_("Line:")) self.label_column = QLabel(_("Column:")) self.column = QLabel() self.line = QLabel() # Widget setup self.line.setFont(self.label_font) self.column.setFont(self.label_font) # Layout layout = self.layout() layout.addWidget(self.label_line) layout.addWidget(self.line) layout.addWidget(self.label_column) layout.addWidget(self.column) self.setLayout(layout) def cursor_position_changed(self, line, index): """Update cursos position.""" self.line.setText("%-6d" % (line+1)) self.column.setText("%-4d" % (index+1)) def test(): from qtpy.QtWidgets import QMainWindow from spyder.utils.qthelpers import qapplication app = qapplication(test_time=5) win = QMainWindow() win.setWindowTitle("Status widgets test") win.resize(900, 300) statusbar = win.statusBar() swidgets = [] for klass in (ReadWriteStatus, EOLStatus, EncodingStatus, CursorPositionStatus, MemoryStatus, CPUStatus): swidget = klass(win, statusbar) swidgets.append(swidget) win.show() app.exec_() if __name__ == "__main__": test() spyder-3.2.6/spyder/widgets/fileswitcher.py0000664000175000017500000007264313224121062021645 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) # Standard library imports from __future__ import print_function import os import os.path as osp # Third party imports from qtpy.QtCore import Signal, QEvent, QObject, QRegExp, QSize, Qt from qtpy.QtGui import (QIcon, QRegExpValidator, QTextCursor) from qtpy.QtWidgets import (QDialog, QHBoxLayout, QLabel, QLineEdit, QListWidget, QListWidgetItem, QVBoxLayout, QMainWindow) # Local imports from spyder.config.base import _ from spyder.py3compat import iteritems, to_text_string from spyder.utils import icon_manager as ima from spyder.utils.stringmatching import get_search_scores from spyder.widgets.helperwidgets import HelperToolButton, HTMLDelegate # --- Python Outline explorer helpers def process_python_symbol_data(oedata): """Returns a list with line number, definition name, fold and token.""" symbol_list = [] for key in oedata: val = oedata[key] if val and key != 'found_cell_separators': if val.is_class_or_function(): symbol_list.append((key, val.def_name, val.fold_level, val.get_token())) return sorted(symbol_list) def get_python_symbol_icons(oedata): """Return a list of icons for oedata of a python file.""" class_icon = ima.icon('class') method_icon = ima.icon('method') function_icon = ima.icon('function') private_icon = ima.icon('private1') super_private_icon = ima.icon('private2') symbols = process_python_symbol_data(oedata) # line - 1, name, fold level fold_levels = sorted(list(set([s[2] for s in symbols]))) parents = [None]*len(symbols) icons = [None]*len(symbols) indexes = [] parent = None for level in fold_levels: for index, item in enumerate(symbols): line, name, fold_level, token = item if index in indexes: continue if fold_level == level: indexes.append(index) parent = item else: parents[index] = parent for index, item in enumerate(symbols): parent = parents[index] if item[-1] == 'def': icons[index] = function_icon elif item[-1] == 'class': icons[index] = class_icon else: icons[index] = QIcon() if parent is not None: if parent[-1] == 'class': if item[-1] == 'def' and item[1].startswith('__'): icons[index] = super_private_icon elif item[-1] == 'def' and item[1].startswith('_'): icons[index] = private_icon else: icons[index] = method_icon return icons def shorten_paths(path_list, is_unsaved): """ Takes a list of paths and tries to "intelligently" shorten them all. The aim is to make it clear to the user where the paths differ, as that is likely what they care about. Note that this operates on a list of paths not on individual paths. If the path ends in an actual file name, it will be trimmed off. """ # TODO: at the end, if the path is too long, should do a more dumb kind of # shortening, but not completely dumb. # Convert the path strings to a list of tokens and start building the # new_path using the drive path_list = path_list[:] # Make a local copy new_path_list = [] for ii, (path, is_unsav) in enumerate(zip(path_list, is_unsaved)): if is_unsav: new_path_list.append(_('unsaved file')) path_list[ii] = None else: drive, path = osp.splitdrive(osp.dirname(path)) new_path_list.append(drive + osp.sep) path_list[ii] = [part for part in path.split(osp.sep) if part] def recurse_level(level_idx): sep = os.sep # If toks are all empty we need not have recursed here if not any(level_idx.values()): return # Firstly, find the longest common prefix for all in the level # s = len of longest common prefix sample_toks = list(level_idx.values())[0] if not sample_toks: s = 0 else: for s, sample_val in enumerate(sample_toks): if not all(len(toks) > s and toks[s] == sample_val for toks in level_idx.values()): break # Shorten longest common prefix if s == 0: short_form = '' else: if s == 1: short_form = sample_toks[0] elif s == 2: short_form = sample_toks[0] + sep + sample_toks[1] else: short_form = "..." + sep + sample_toks[s-1] for idx in level_idx: new_path_list[idx] += short_form + sep level_idx[idx] = level_idx[idx][s:] # Group the remaining bit after the common prefix, shorten, and recurse while level_idx: k, group = 0, level_idx # k is length of the group's common prefix while True: # Abort if we've gone beyond end of one or more in the group prospective_group = {idx: toks for idx, toks in group.items() if len(toks) == k} if prospective_group: if k == 0: # we spit out the group with no suffix group = prospective_group break # Only keep going if all n still match on the kth token _, sample_toks = next(iteritems(group)) prospective_group = {idx: toks for idx, toks in group.items() if toks[k] == sample_toks[k]} if len(prospective_group) == len(group) or k == 0: group = prospective_group k += 1 else: break _, sample_toks = next(iteritems(group)) if k == 0: short_form = '' elif k == 1: short_form = sample_toks[0] elif k == 2: short_form = sample_toks[0] + sep + sample_toks[1] else: # k > 2 short_form = sample_toks[0] + "..." + sep + sample_toks[k-1] for idx in group.keys(): new_path_list[idx] += short_form + (sep if k > 0 else '') del level_idx[idx] recurse_level({idx: toks[k:] for idx, toks in group.items()}) recurse_level({i: pl for i, pl in enumerate(path_list) if pl}) return [path.rstrip(os.sep) for path in new_path_list] class KeyPressFilter(QObject): """Use with `installEventFilter` to get up/down arrow key press signal.""" UP, DOWN = [-1, 1] # Step constants sig_up_key_pressed = Signal() sig_down_key_pressed = Signal() def eventFilter(self, src, e): if e.type() == QEvent.KeyPress: if e.key() == Qt.Key_Up: self.sig_up_key_pressed.emit() elif e.key() == Qt.Key_Down: self.sig_down_key_pressed.emit() return super(KeyPressFilter, self).eventFilter(src, e) class FilesFilterLine(QLineEdit): """QLineEdit used to filter files by name.""" # User has not clicked outside this widget clicked_outside = False def focusOutEvent(self, event): """ Detect when the focus goes out of this widget. This is used to make the file switcher leave focus on the last selected file by the user. """ self.clicked_outside = True return super(QLineEdit, self).focusOutEvent(event) class FileSwitcher(QDialog): """A Sublime-like file switcher.""" sig_goto_file = Signal(int, object) # Constants that define the mode in which the list widget is working # FILE_MODE is for a list of files, SYMBOL_MODE if for a list of symbols # in a given file when using the '@' symbol. FILE_MODE, SYMBOL_MODE = [1, 2] MAX_WIDTH = 600 def __init__(self, parent, plugin, tabs, data, icon): QDialog.__init__(self, parent) # Variables self.plugins_tabs = [] self.plugins_data = [] self.plugins_instances = [] self.add_plugin(plugin, tabs, data, icon) self.plugin = None # Last plugin with focus self.mode = self.FILE_MODE # By default start in this mode self.initial_cursors = None # {fullpath: QCursor} self.initial_path = None # Fullpath of initial active editor self.initial_widget = None # Initial active editor self.line_number = None # Selected line number in filer self.is_visible = False # Is the switcher visible? help_text = _("Press Enter to switch files or Esc to " "cancel.

    Type to filter filenames.

    " "Use :number to go to a line, e.g. " "main:42
    " "Use @symbol_text to go to a symbol, e.g. " "@init" "

    Press Ctrl+W to close current tab.
    ") # Either allow searching for a line number or a symbol but not both regex = QRegExp("([A-Za-z0-9_]{0,100}@[A-Za-z0-9_]{0,100})|" + "([A-Za-z0-9_]{0,100}:{0,1}[0-9]{0,100})") # Widgets self.edit = FilesFilterLine(self) self.help = HelperToolButton() self.list = QListWidget(self) self.filter = KeyPressFilter() regex_validator = QRegExpValidator(regex, self.edit) # Widgets setup self.setWindowFlags(Qt.Popup | Qt.FramelessWindowHint) self.setWindowOpacity(0.95) self.edit.installEventFilter(self.filter) self.edit.setValidator(regex_validator) self.help.setToolTip(help_text) self.list.setItemDelegate(HTMLDelegate(self)) # Layout edit_layout = QHBoxLayout() edit_layout.addWidget(self.edit) edit_layout.addWidget(self.help) layout = QVBoxLayout() layout.addLayout(edit_layout) layout.addWidget(self.list) self.setLayout(layout) # Signals self.rejected.connect(self.restore_initial_state) self.filter.sig_up_key_pressed.connect(self.previous_row) self.filter.sig_down_key_pressed.connect(self.next_row) self.edit.returnPressed.connect(self.accept) self.edit.textChanged.connect(self.setup) self.list.itemSelectionChanged.connect(self.item_selection_changed) self.list.clicked.connect(self.edit.setFocus) # --- Properties @property def widgets(self): widgets = [] for plugin in self.plugins_instances: tabs = self.get_plugin_tabwidget(plugin) widgets += [(tabs.widget(index), plugin) for index in range(tabs.count())] return widgets @property def line_count(self): line_count = [] for widget in self.widgets: try: current_line_count = widget[0].get_line_count() except AttributeError: current_line_count = 0 line_count.append(current_line_count) return line_count @property def save_status(self): save_status = [] for da, icon in self.plugins_data: save_status += [getattr(td, 'newly_created', False) for td in da] return save_status @property def paths(self): paths = [] for plugin in self.plugins_instances: da = self.get_plugin_data(plugin) paths += [getattr(td, 'filename', None) for td in da] return paths @property def filenames(self): filenames = [] for plugin in self.plugins_instances: da = self.get_plugin_data(plugin) filenames += [os.path.basename(getattr(td, 'filename', None)) for td in da] return filenames @property def icons(self): icons = [] for da, icon in self.plugins_data: icons += [icon for td in da] return icons @property def current_path(self): return self.paths_by_widget.get(self.get_widget(), None) @property def paths_by_widget(self): widgets = [w[0] for w in self.widgets] return dict(zip(widgets, self.paths)) @property def widgets_by_path(self): widgets = [w[0] for w in self.widgets] return dict(zip(self.paths, widgets)) @property def filter_text(self): """Get the normalized (lowecase) content of the filter text.""" return to_text_string(self.edit.text()).lower() def set_search_text(self, _str): self.edit.setText(_str) def save_initial_state(self): """Save initial cursors and initial active widget.""" paths = self.paths self.initial_widget = self.get_widget() self.initial_cursors = {} for i, editor in enumerate(self.widgets): if editor is self.initial_widget: self.initial_path = paths[i] # This try is needed to make the fileswitcher work with # plugins that does not have a textCursor. try: self.initial_cursors[paths[i]] = editor.textCursor() except AttributeError: pass def accept(self): self.is_visible = False QDialog.accept(self) self.list.clear() def restore_initial_state(self): """Restores initial cursors and initial active editor.""" self.list.clear() self.is_visible = False widgets = self.widgets_by_path if not self.edit.clicked_outside: for path in self.initial_cursors: cursor = self.initial_cursors[path] if path in widgets: self.set_editor_cursor(widgets[path], cursor) if self.initial_widget in self.paths_by_widget: index = self.paths.index(self.initial_path) self.sig_goto_file.emit(index) def set_dialog_position(self): """Positions the file switcher dialog.""" parent = self.parent() geo = parent.geometry() width = self.list.width() # This has been set in setup left = parent.geometry().width()/2 - width/2 # Note: the +1 pixel on the top makes it look better if isinstance(parent, QMainWindow): top = (parent.toolbars_menu.geometry().height() + parent.menuBar().geometry().height() + 1) else: top = self.plugins_tabs[0][0].tabBar().geometry().height() + 1 while parent: geo = parent.geometry() top += geo.top() left += geo.left() parent = parent.parent() self.move(left, top) def get_item_size(self, content): """ Get the max size (width and height) for the elements of a list of strings as a QLabel. """ strings = [] if content: for rich_text in content: label = QLabel(rich_text) label.setTextFormat(Qt.PlainText) strings.append(label.text()) fm = label.fontMetrics() return (max([fm.width(s) * 1.3 for s in strings]), fm.height()) def fix_size(self, content): """ Adjusts the width and height of the file switcher based on the relative size of the parent and content. """ # Update size of dialog based on relative size of the parent if content: width, height = self.get_item_size(content) # Width parent = self.parent() relative_width = parent.geometry().width() * 0.65 if relative_width > self.MAX_WIDTH: relative_width = self.MAX_WIDTH self.list.setMinimumWidth(relative_width) # Height if len(content) < 8: max_entries = len(content) else: max_entries = 8 max_height = height * max_entries * 2.5 self.list.setMinimumHeight(max_height) # Resize self.list.resize(relative_width, self.list.height()) # --- Helper methods: List widget def count(self): """Gets the item count in the list widget.""" return self.list.count() def current_row(self): """Returns the current selected row in the list widget.""" return self.list.currentRow() def set_current_row(self, row): """Sets the current selected row in the list widget.""" return self.list.setCurrentRow(row) def select_row(self, steps): """Select row in list widget based on a number of steps with direction. Steps can be positive (next rows) or negative (previous rows). """ row = self.current_row() + steps if 0 <= row < self.count(): self.set_current_row(row) def previous_row(self): """Select previous row in list widget.""" if self.mode == self.SYMBOL_MODE: self.select_row(-1) return prev_row = self.current_row() - 1 if prev_row >= 0: title = self.list.item(prev_row).text() else: title = '' if prev_row == 0 and '

    ' in title: self.list.scrollToTop() elif '

    ' in title: # Select the next previous row, the one following is a title self.select_row(-2) else: self.select_row(-1) def next_row(self): """Select next row in list widget.""" if self.mode == self.SYMBOL_MODE: self.select_row(+1) return next_row = self.current_row() + 1 if next_row < self.count(): if '

    ' in self.list.item(next_row).text(): # Select the next next row, the one following is a title self.select_row(+2) else: self.select_row(+1) def get_stack_index(self, stack_index, plugin_index): """Get the real index of the selected item.""" other_plugins_count = sum([other_tabs[0].count() \ for other_tabs in \ self.plugins_tabs[:plugin_index]]) real_index = stack_index - other_plugins_count return real_index # --- Helper methods: Widget def get_plugin_data(self, plugin): """Get the data object of the plugin's current tab manager.""" # The data object is named "data" in the editor plugin while it is # named "clients" in the notebook plugin. try: data = plugin.get_current_tab_manager().data except AttributeError: data = plugin.get_current_tab_manager().clients return data def get_plugin_tabwidget(self, plugin): """Get the tabwidget of the plugin's current tab manager.""" # The tab widget is named "tabs" in the editor plugin while it is # named "tabwidget" in the notebook plugin. try: tabwidget = plugin.get_current_tab_manager().tabs except AttributeError: tabwidget = plugin.get_current_tab_manager().tabwidget return tabwidget def get_widget(self, index=None, path=None, tabs=None): """Get widget by index. If no tabs and index specified the current active widget is returned. """ if (index and tabs) or (path and tabs): return tabs.widget(index) elif self.plugin: return self.get_plugin_tabwidget(self.plugin).currentWidget() else: return self.plugins_tabs[0][0].currentWidget() def set_editor_cursor(self, editor, cursor): """Set the cursor of an editor.""" pos = cursor.position() anchor = cursor.anchor() new_cursor = QTextCursor() if pos == anchor: new_cursor.movePosition(pos) else: new_cursor.movePosition(anchor) new_cursor.movePosition(pos, QTextCursor.KeepAnchor) editor.setTextCursor(cursor) def goto_line(self, line_number): """Go to specified line number in current active editor.""" if line_number: line_number = int(line_number) try: self.plugin.go_to_line(line_number) except AttributeError: pass # --- Helper methods: Outline explorer def get_symbol_list(self): """Get the list of symbols present in the file.""" try: oedata = self.get_widget().get_outlineexplorer_data() except AttributeError: oedata = {} return oedata # --- Handlers def item_selection_changed(self): """List widget item selection change handler.""" row = self.current_row() if self.count() and row >= 0: if '

    ' in self.list.currentItem().text() and row == 0: self.next_row() if self.mode == self.FILE_MODE: try: stack_index = self.paths.index(self.filtered_path[row]) self.plugin = self.widgets[stack_index][1] plugin_index = self.plugins_instances.index(self.plugin) # Count the real index in the tabWidget of the # current plugin real_index = self.get_stack_index(stack_index, plugin_index) self.sig_goto_file.emit(real_index, self.plugin.get_current_tab_manager()) self.goto_line(self.line_number) try: self.plugin.switch_to_plugin() self.raise_() except AttributeError: # The widget using the fileswitcher is not a plugin pass self.edit.setFocus() except ValueError: pass else: line_number = self.filtered_symbol_lines[row] self.goto_line(line_number) def setup_file_list(self, filter_text, current_path): """Setup list widget content for file list display.""" short_paths = shorten_paths(self.paths, self.save_status) paths = self.paths icons = self.icons results = [] trying_for_line_number = ':' in filter_text # Get optional line number if trying_for_line_number: filter_text, line_number = filter_text.split(':') if line_number == '': line_number = None # Get all the available filenames scores = get_search_scores('', self.filenames, template="{0}") else: line_number = None # Get all available filenames and get the scores for # "fuzzy" matching scores = get_search_scores(filter_text, self.filenames, template="{0}") # Get max width to determine if shortpaths should be used max_width = self.get_item_size(paths)[0] self.fix_size(paths) # Build the text that will appear on the list widget for index, score in enumerate(scores): text, rich_text, score_value = score if score_value != -1: text_item = '' + rich_text.replace('&', '') + '' if trying_for_line_number: text_item += " [{0:} {1:}]".format(self.line_count[index], _("lines")) if max_width > self.list.width(): text_item += u"
    {0:}".format(short_paths[index]) else: text_item += u"
    {0:}".format(paths[index]) if (trying_for_line_number and self.line_count[index] != 0 or not trying_for_line_number): results.append((score_value, index, text_item)) # Sort the obtained scores and populate the list widget self.filtered_path = [] plugin = None for result in sorted(results): index = result[1] path = paths[index] icon = icons[index] text = '' try: title = self.widgets[index][1].get_plugin_title().split(' - ') if plugin != title[0]: plugin = title[0] text += '
    ' + plugin + '
    ' item = QListWidgetItem(text) item.setToolTip(path) item.setSizeHint(QSize(0, 25)) item.setFlags(Qt.ItemIsEditable) self.list.addItem(item) self.filtered_path.append(path) except: # The widget using the fileswitcher is not a plugin pass text = '' text += result[-1] item = QListWidgetItem(icon, text) item.setToolTip(path) item.setSizeHint(QSize(0, 25)) self.list.addItem(item) self.filtered_path.append(path) # To adjust the delegate layout for KDE themes self.list.files_list = True # Move selected item in list accordingly and update list size if current_path in self.filtered_path: self.set_current_row(self.filtered_path.index(current_path)) elif self.filtered_path: self.set_current_row(0) # If a line number is searched look for it self.line_number = line_number self.goto_line(line_number) def setup_symbol_list(self, filter_text, current_path): """Setup list widget content for symbol list display.""" # Get optional symbol name filter_text, symbol_text = filter_text.split('@') # Fetch the Outline explorer data, get the icons and values oedata = self.get_symbol_list() icons = get_python_symbol_icons(oedata) # The list of paths here is needed in order to have the same # point of measurement for the list widget size as in the file list # See issue 4648 paths = self.paths # Update list size self.fix_size(paths) symbol_list = process_python_symbol_data(oedata) line_fold_token = [(item[0], item[2], item[3]) for item in symbol_list] choices = [item[1] for item in symbol_list] scores = get_search_scores(symbol_text, choices, template="{0}") # Build the text that will appear on the list widget results = [] lines = [] self.filtered_symbol_lines = [] for index, score in enumerate(scores): text, rich_text, score_value = score line, fold_level, token = line_fold_token[index] lines.append(text) if score_value != -1: results.append((score_value, line, text, rich_text, fold_level, icons[index], token)) template = '{0}{1}' for (score, line, text, rich_text, fold_level, icon, token) in sorted(results): fold_space = ' '*(fold_level) line_number = line + 1 self.filtered_symbol_lines.append(line_number) textline = template.format(fold_space, rich_text) item = QListWidgetItem(icon, textline) item.setSizeHint(QSize(0, 16)) self.list.addItem(item) # To adjust the delegate layout for KDE themes self.list.files_list = False # Select edit line when using symbol search initially. # See issue 5661 self.edit.setFocus() # Move selected item in list accordingly # NOTE: Doing this is causing two problems: # 1. It makes the cursor to auto-jump to the last selected # symbol after opening or closing a different file # 2. It moves the cursor to the first symbol by default, # which is very distracting. # That's why this line is commented! # self.set_current_row(0) def setup(self): """Setup list widget content.""" if len(self.plugins_tabs) == 0: self.close() return self.list.clear() current_path = self.current_path filter_text = self.filter_text # Get optional line or symbol to define mode and method handler trying_for_symbol = ('@' in self.filter_text) if trying_for_symbol: self.mode = self.SYMBOL_MODE self.setup_symbol_list(filter_text, current_path) else: self.mode = self.FILE_MODE self.setup_file_list(filter_text, current_path) # Set position according to size self.set_dialog_position() def show(self): """ Override Qt method to force an update of the fileswitcher before showing it. See Issue #5317 and PR #5389. """ self.setup() super(FileSwitcher, self).show() def add_plugin(self, plugin, tabs, data, icon): """Add a plugin to display its files.""" self.plugins_tabs.append((tabs, plugin)) self.plugins_data.append((data, icon)) self.plugins_instances.append(plugin) spyder-3.2.6/spyder/widgets/pathmanager.py0000664000175000017500000002735213224121062021441 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Spyder path manager""" # Standard library imports from __future__ import print_function import os import os.path as osp import sys # Third party imports from qtpy.compat import getexistingdirectory from qtpy.QtCore import Qt, Signal, Slot from qtpy.QtWidgets import (QDialog, QDialogButtonBox, QHBoxLayout, QListWidget, QListWidgetItem, QMessageBox, QVBoxLayout, QCheckBox) # Local imports from spyder.config.base import _ from spyder.utils.misc import getcwd_or_home from spyder.utils import icon_manager as ima from spyder.utils.qthelpers import create_toolbutton class PathManager(QDialog): redirect_stdio = Signal(bool) def __init__(self, parent=None, pathlist=None, ro_pathlist=None, not_active_pathlist=None, sync=True): QDialog.__init__(self, parent) # Destroying the C++ object right after closing the dialog box, # otherwise it may be garbage-collected in another QThread # (e.g. the editor's analysis thread in Spyder), thus leading to # a segmentation fault on UNIX or an application crash on Windows self.setAttribute(Qt.WA_DeleteOnClose) assert isinstance(pathlist, list) self.pathlist = pathlist if not_active_pathlist is None: not_active_pathlist = [] self.not_active_pathlist = not_active_pathlist if ro_pathlist is None: ro_pathlist = [] self.ro_pathlist = ro_pathlist self.last_path = getcwd_or_home() self.setWindowTitle(_("PYTHONPATH manager")) self.setWindowIcon(ima.icon('pythonpath')) self.resize(500, 300) self.selection_widgets = [] layout = QVBoxLayout() self.setLayout(layout) top_layout = QHBoxLayout() layout.addLayout(top_layout) self.toolbar_widgets1 = self.setup_top_toolbar(top_layout) self.listwidget = QListWidget(self) self.listwidget.currentRowChanged.connect(self.refresh) self.listwidget.itemChanged.connect(self.update_not_active_pathlist) layout.addWidget(self.listwidget) bottom_layout = QHBoxLayout() layout.addLayout(bottom_layout) self.sync_button = None self.toolbar_widgets2 = self.setup_bottom_toolbar(bottom_layout, sync) # Buttons configuration bbox = QDialogButtonBox(QDialogButtonBox.Close) bbox.rejected.connect(self.reject) bottom_layout.addWidget(bbox) self.update_list() self.refresh() @property def active_pathlist(self): return [path for path in self.pathlist if path not in self.not_active_pathlist] def _add_widgets_to_layout(self, layout, widgets): layout.setAlignment(Qt.AlignLeft) for widget in widgets: layout.addWidget(widget) def setup_top_toolbar(self, layout): toolbar = [] movetop_button = create_toolbutton(self, text=_("Move to top"), icon=ima.icon('2uparrow'), triggered=lambda: self.move_to(absolute=0), text_beside_icon=True) toolbar.append(movetop_button) moveup_button = create_toolbutton(self, text=_("Move up"), icon=ima.icon('1uparrow'), triggered=lambda: self.move_to(relative=-1), text_beside_icon=True) toolbar.append(moveup_button) movedown_button = create_toolbutton(self, text=_("Move down"), icon=ima.icon('1downarrow'), triggered=lambda: self.move_to(relative=1), text_beside_icon=True) toolbar.append(movedown_button) movebottom_button = create_toolbutton(self, text=_("Move to bottom"), icon=ima.icon('2downarrow'), triggered=lambda: self.move_to(absolute=1), text_beside_icon=True) toolbar.append(movebottom_button) self.selection_widgets.extend(toolbar) self._add_widgets_to_layout(layout, toolbar) return toolbar def setup_bottom_toolbar(self, layout, sync=True): toolbar = [] add_button = create_toolbutton(self, text=_('Add path'), icon=ima.icon('edit_add'), triggered=self.add_path, text_beside_icon=True) toolbar.append(add_button) remove_button = create_toolbutton(self, text=_('Remove path'), icon=ima.icon('edit_remove'), triggered=self.remove_path, text_beside_icon=True) toolbar.append(remove_button) self.selection_widgets.append(remove_button) self._add_widgets_to_layout(layout, toolbar) layout.addStretch(1) if os.name == 'nt' and sync: self.sync_button = create_toolbutton(self, text=_("Synchronize..."), icon=ima.icon('fileimport'), triggered=self.synchronize, tip=_("Synchronize Spyder's path list with PYTHONPATH " "environment variable"), text_beside_icon=True) layout.addWidget(self.sync_button) return toolbar @Slot() def synchronize(self): """ Synchronize Spyder's path list with PYTHONPATH environment variable Only apply to: current user, on Windows platforms """ answer = QMessageBox.question(self, _("Synchronize"), _("This will synchronize Spyder's path list with " "PYTHONPATH environment variable for current user, " "allowing you to run your Python modules outside Spyder " "without having to configure sys.path. " "
    Do you want to clear contents of PYTHONPATH before " "adding Spyder's path list?"), QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel) if answer == QMessageBox.Cancel: return elif answer == QMessageBox.Yes: remove = True else: remove = False from spyder.utils.environ import (get_user_env, set_user_env, listdict2envdict) env = get_user_env() if remove: ppath = self.active_pathlist+self.ro_pathlist else: ppath = env.get('PYTHONPATH', []) if not isinstance(ppath, list): ppath = [ppath] ppath = [path for path in ppath if path not in (self.active_pathlist+self.ro_pathlist)] ppath.extend(self.active_pathlist+self.ro_pathlist) env['PYTHONPATH'] = ppath set_user_env(listdict2envdict(env), parent=self) def get_path_list(self): """Return path list (does not include the read-only path list)""" return self.pathlist def update_not_active_pathlist(self, item): path = item.text() if bool(item.checkState()) is True: self.remove_from_not_active_pathlist(path) else: self.add_to_not_active_pathlist(path) def add_to_not_active_pathlist(self, path): if path not in self.not_active_pathlist: self.not_active_pathlist.append(path) def remove_from_not_active_pathlist(self, path): if path in self.not_active_pathlist: self.not_active_pathlist.remove(path) def update_list(self): """Update path list""" self.listwidget.clear() for name in self.pathlist+self.ro_pathlist: item = QListWidgetItem(name) item.setIcon(ima.icon('DirClosedIcon')) if name in self.ro_pathlist: item.setFlags(Qt.NoItemFlags | Qt.ItemIsUserCheckable) item.setCheckState(Qt.Checked) elif name in self.not_active_pathlist: item.setFlags(item.flags() | Qt.ItemIsUserCheckable) item.setCheckState(Qt.Unchecked) else: item.setFlags(item.flags() | Qt.ItemIsUserCheckable) item.setCheckState(Qt.Checked) self.listwidget.addItem(item) self.refresh() def refresh(self, row=None): """Refresh widget""" for widget in self.selection_widgets: widget.setEnabled(self.listwidget.currentItem() is not None) not_empty = self.listwidget.count() > 0 if self.sync_button is not None: self.sync_button.setEnabled(not_empty) def move_to(self, absolute=None, relative=None): index = self.listwidget.currentRow() if absolute is not None: if absolute: new_index = len(self.pathlist)-1 else: new_index = 0 else: new_index = index + relative new_index = max(0, min(len(self.pathlist)-1, new_index)) path = self.pathlist.pop(index) self.pathlist.insert(new_index, path) self.update_list() self.listwidget.setCurrentRow(new_index) @Slot() def remove_path(self): answer = QMessageBox.warning(self, _("Remove path"), _("Do you really want to remove selected path?"), QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: self.pathlist.pop(self.listwidget.currentRow()) self.remove_from_not_active_pathlist( self.listwidget.currentItem().text()) self.update_list() @Slot() def add_path(self): self.redirect_stdio.emit(False) directory = getexistingdirectory(self, _("Select directory"), self.last_path) self.redirect_stdio.emit(True) if directory: directory = osp.abspath(directory) self.last_path = directory if directory in self.pathlist: item = self.listwidget.findItems(directory, Qt.MatchExactly)[0] item.setCheckState(Qt.Checked) answer = QMessageBox.question(self, _("Add path"), _("This directory is already included in Spyder path " "list.
    Do you want to move it to the top of " "the list?"), QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: self.pathlist.remove(directory) else: return self.pathlist.insert(0, directory) self.update_list() def test(): """Run path manager test""" from spyder.utils.qthelpers import qapplication _app = qapplication() # analysis:ignore test = PathManager(None, pathlist=sys.path[:-10], ro_pathlist=sys.path[-10:]) test.exec_() print(test.get_path_list()) # spyder: test-skip if __name__ == "__main__": test() spyder-3.2.6/spyder/widgets/shell.py0000664000175000017500000011240313211142273020254 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Shell widgets: base, python and terminal""" # pylint: disable=C0103 # pylint: disable=R0903 # pylint: disable=R0911 # pylint: disable=R0201 # Standard library imports import keyword import locale import os import os.path as osp import re import sys import time # Third party imports from qtpy.compat import getsavefilename from qtpy.QtCore import Property, QCoreApplication, Qt, QTimer, Signal, Slot from qtpy.QtGui import QKeySequence, QTextCharFormat, QTextCursor from qtpy.QtWidgets import QApplication, QMenu, QMessageBox, QToolTip # Local import from spyder.config.base import _, DEBUG, get_conf_path, STDERR from spyder.config.gui import config_shortcut, get_shortcut from spyder.config.main import CONF from spyder.py3compat import (builtins, is_string, is_text_string, PY3, to_text_string) from spyder.utils import encoding from spyder.utils import icon_manager as ima from spyder.utils.qthelpers import (add_actions, create_action, keybinding, restore_keyevent) from spyder.widgets.mixins import (GetHelpMixin, SaveHistoryMixin, TracebackLinksMixin, BrowseHistoryMixin) from spyder.widgets.sourcecode.base import ConsoleBaseWidget class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin, BrowseHistoryMixin): """ Shell base widget """ redirect_stdio = Signal(bool) sig_keyboard_interrupt = Signal() execute = Signal(str) append_to_history = Signal(str, str) def __init__(self, parent, history_filename, profile=False, initial_message=None): """ parent : specifies the parent widget """ ConsoleBaseWidget.__init__(self, parent) SaveHistoryMixin.__init__(self, history_filename) BrowseHistoryMixin.__init__(self) # Prompt position: tuple (line, index) self.current_prompt_pos = None self.new_input_line = True # History assert is_text_string(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() # Simple profiling test self.profile = profile # Buffer to increase performance of write/flush operations self.__buffer = [] if initial_message: self.__buffer.append(initial_message) self.__timestamp = 0.0 self.__flushtimer = QTimer(self) self.__flushtimer.setSingleShot(True) self.__flushtimer.timeout.connect(self.flush) # Give focus to widget self.setFocus() # Cursor width self.setCursorWidth( CONF.get('main', 'cursor/width') ) def toggle_wrap_mode(self, enable): """Enable/disable wrap mode""" self.set_wrap_mode('character' if enable else None) def set_font(self, font): """Set shell styles font""" self.setFont(font) self.set_pythonshell_font(font) cursor = self.textCursor() cursor.select(QTextCursor.Document) charformat = QTextCharFormat() charformat.setFontFamily(font.family()) charformat.setFontPointSize(font.pointSize()) cursor.mergeCharFormat(charformat) #------ Context menu def setup_context_menu(self): """Setup shell context menu""" self.menu = QMenu(self) self.cut_action = create_action(self, _("Cut"), shortcut=keybinding('Cut'), icon=ima.icon('editcut'), triggered=self.cut) self.copy_action = create_action(self, _("Copy"), shortcut=keybinding('Copy'), icon=ima.icon('editcopy'), triggered=self.copy) paste_action = create_action(self, _("Paste"), shortcut=keybinding('Paste'), icon=ima.icon('editpaste'), triggered=self.paste) save_action = create_action(self, _("Save history log..."), icon=ima.icon('filesave'), tip=_("Save current history log (i.e. all " "inputs and outputs) in a text file"), triggered=self.save_historylog) self.delete_action = create_action(self, _("Delete"), shortcut=keybinding('Delete'), icon=ima.icon('editdelete'), triggered=self.delete) selectall_action = create_action(self, _("Select All"), shortcut=keybinding('SelectAll'), icon=ima.icon('selectall'), triggered=self.selectAll) add_actions(self.menu, (self.cut_action, self.copy_action, paste_action, self.delete_action, None, selectall_action, None, save_action) ) def contextMenuEvent(self, event): """Reimplement Qt method""" state = self.has_selected_text() self.copy_action.setEnabled(state) self.cut_action.setEnabled(state) self.delete_action.setEnabled(state) self.menu.popup(event.globalPos()) event.accept() #------ Input buffer def get_current_line_from_cursor(self): return self.get_text('cursor', 'eof') def _select_input(self): """Select current line (without selecting console prompt)""" line, index = self.get_position('eof') if self.current_prompt_pos is None: pline, pindex = line, index else: pline, pindex = self.current_prompt_pos self.setSelection(pline, pindex, line, index) @Slot() def clear_terminal(self): """ Clear terminal window Child classes reimplement this method to write prompt """ self.clear() # The buffer being edited def _set_input_buffer(self, text): """Set input buffer""" if self.current_prompt_pos is not None: self.replace_text(self.current_prompt_pos, 'eol', text) else: self.insert(text) self.set_cursor_position('eof') def _get_input_buffer(self): """Return input buffer""" input_buffer = '' if self.current_prompt_pos is not None: input_buffer = self.get_text(self.current_prompt_pos, 'eol') input_buffer = input_buffer.replace(os.linesep, '\n') return input_buffer input_buffer = Property("QString", _get_input_buffer, _set_input_buffer) #------ Prompt def new_prompt(self, prompt): """ Print a new prompt and save its (line, index) position """ if self.get_cursor_line_column()[1] != 0: self.write('\n') self.write(prompt, prompt=True) # now we update our cursor giving end of prompt self.current_prompt_pos = self.get_position('cursor') self.ensureCursorVisible() self.new_input_line = False def check_selection(self): """ Check if selected text is r/w, otherwise remove read-only parts of selection """ if self.current_prompt_pos is None: self.set_cursor_position('eof') else: self.truncate_selection(self.current_prompt_pos) #------ Copy / Keyboard interrupt @Slot() def copy(self): """Copy text to clipboard... or keyboard interrupt""" if self.has_selected_text(): ConsoleBaseWidget.copy(self) elif not sys.platform == 'darwin': self.interrupt() def interrupt(self): """Keyboard interrupt""" self.sig_keyboard_interrupt.emit() @Slot() def cut(self): """Cut text""" self.check_selection() if self.has_selected_text(): ConsoleBaseWidget.cut(self) @Slot() def delete(self): """Remove selected text""" self.check_selection() if self.has_selected_text(): ConsoleBaseWidget.remove_selected_text(self) @Slot() def save_historylog(self): """Save current history log (all text in console)""" title = _("Save history log") self.redirect_stdio.emit(False) filename, _selfilter = getsavefilename(self, title, self.historylog_filename, "%s (*.log)" % _("History logs")) self.redirect_stdio.emit(True) if filename: filename = osp.normpath(filename) try: encoding.write(to_text_string(self.get_text_with_eol()), filename) self.historylog_filename = filename CONF.set('main', 'historylog_filename', filename) except EnvironmentError as error: QMessageBox.critical(self, title, _("Unable to save file '%s'" "

    Error message:
    %s" ) % (osp.basename(filename), to_text_string(error))) #------ Basic keypress event handler def on_enter(self, command): """on_enter""" self.execute_command(command) def execute_command(self, command): self.execute.emit(command) self.add_to_history(command) self.new_input_line = True def on_new_line(self): """On new input line""" self.set_cursor_position('eof') self.current_prompt_pos = self.get_position('cursor') self.new_input_line = False @Slot() def paste(self): """Reimplemented slot to handle multiline paste action""" if self.new_input_line: self.on_new_line() ConsoleBaseWidget.paste(self) def keyPressEvent(self, event): """ Reimplement Qt Method Basic keypress event handler (reimplemented in InternalShell to add more sophisticated features) """ if self.preprocess_keyevent(event): # Event was accepted in self.preprocess_keyevent return self.postprocess_keyevent(event) def preprocess_keyevent(self, event): """Pre-process keypress event: return True if event is accepted, false otherwise""" # Copy must be done first to be able to copy read-only text parts # (otherwise, right below, we would remove selection # if not on current line) ctrl = event.modifiers() & Qt.ControlModifier meta = event.modifiers() & Qt.MetaModifier # meta=ctrl in OSX if event.key() == Qt.Key_C and \ ((Qt.MetaModifier | Qt.ControlModifier) & event.modifiers()): if meta and sys.platform == 'darwin': self.interrupt() elif ctrl: self.copy() event.accept() return True if self.new_input_line and ( len(event.text()) or event.key() in \ (Qt.Key_Up, Qt.Key_Down, Qt.Key_Left, Qt.Key_Right) ): self.on_new_line() return False def postprocess_keyevent(self, event): """Post-process keypress event: in InternalShell, this is method is called when shell is ready""" event, text, key, ctrl, shift = restore_keyevent(event) # Is cursor on the last line? and after prompt? if len(text): #XXX: Shouldn't it be: `if len(unicode(text).strip(os.linesep))` ? if self.has_selected_text(): self.check_selection() self.restrict_cursor_position(self.current_prompt_pos, 'eof') cursor_position = self.get_position('cursor') if key in (Qt.Key_Return, Qt.Key_Enter): if self.is_cursor_on_last_line(): self._key_enter() # add and run selection else: self.insert_text(self.get_selected_text(), at_end=True) elif key == Qt.Key_Insert and not shift and not ctrl: self.setOverwriteMode(not self.overwriteMode()) elif key == Qt.Key_Delete: if self.has_selected_text(): self.check_selection() self.remove_selected_text() elif self.is_cursor_on_last_line(): self.stdkey_clear() elif key == Qt.Key_Backspace: self._key_backspace(cursor_position) elif key == Qt.Key_Tab: self._key_tab() elif key == Qt.Key_Space and ctrl: self._key_ctrl_space() elif key == Qt.Key_Left: if self.current_prompt_pos == cursor_position: # Avoid moving cursor on prompt return method = self.extend_selection_to_next if shift \ else self.move_cursor_to_next method('word' if ctrl else 'character', direction='left') elif key == Qt.Key_Right: if self.is_cursor_at_end(): return method = self.extend_selection_to_next if shift \ else self.move_cursor_to_next method('word' if ctrl else 'character', direction='right') elif (key == Qt.Key_Home) or ((key == Qt.Key_Up) and ctrl): self._key_home(shift, ctrl) elif (key == Qt.Key_End) or ((key == Qt.Key_Down) and ctrl): self._key_end(shift, ctrl) elif key == Qt.Key_Up: if not self.is_cursor_on_last_line(): self.set_cursor_position('eof') y_cursor = self.get_coordinates(cursor_position)[1] y_prompt = self.get_coordinates(self.current_prompt_pos)[1] if y_cursor > y_prompt: self.stdkey_up(shift) else: self.browse_history(backward=True) elif key == Qt.Key_Down: if not self.is_cursor_on_last_line(): self.set_cursor_position('eof') y_cursor = self.get_coordinates(cursor_position)[1] y_end = self.get_coordinates('eol')[1] if y_cursor < y_end: self.stdkey_down(shift) else: self.browse_history(backward=False) elif key in (Qt.Key_PageUp, Qt.Key_PageDown): #XXX: Find a way to do this programmatically instead of calling # widget keyhandler (this won't work if the *event* is coming from # the event queue - i.e. if the busy buffer is ever implemented) ConsoleBaseWidget.keyPressEvent(self, event) elif key == Qt.Key_Escape and shift: self.clear_line() elif key == Qt.Key_Escape: self._key_escape() elif key == Qt.Key_L and ctrl: self.clear_terminal() elif key == Qt.Key_V and ctrl: self.paste() elif key == Qt.Key_X and ctrl: self.cut() elif key == Qt.Key_Z and ctrl: self.undo() elif key == Qt.Key_Y and ctrl: self.redo() elif key == Qt.Key_A and ctrl: self.selectAll() elif key == Qt.Key_Question and not self.has_selected_text(): self._key_question(text) elif key == Qt.Key_ParenLeft and not self.has_selected_text(): self._key_parenleft(text) elif key == Qt.Key_Period and not self.has_selected_text(): self._key_period(text) elif len(text) and not self.isReadOnly(): self.hist_wholeline = False self.insert_text(text) self._key_other(text) else: # Let the parent widget handle the key press event ConsoleBaseWidget.keyPressEvent(self, event) #------ Key handlers def _key_enter(self): command = self.input_buffer self.insert_text('\n', at_end=True) self.on_enter(command) self.flush() def _key_other(self, text): raise NotImplementedError def _key_backspace(self, cursor_position): raise NotImplementedError def _key_tab(self): raise NotImplementedError def _key_ctrl_space(self): raise NotImplementedError def _key_home(self, shift, ctrl): if self.is_cursor_on_last_line(): self.stdkey_home(shift, ctrl, self.current_prompt_pos) def _key_end(self, shift, ctrl): if self.is_cursor_on_last_line(): self.stdkey_end(shift, ctrl) def _key_pageup(self): raise NotImplementedError def _key_pagedown(self): raise NotImplementedError def _key_escape(self): raise NotImplementedError def _key_question(self, text): raise NotImplementedError def _key_parenleft(self, text): raise NotImplementedError def _key_period(self, text): raise NotImplementedError #------ History Management def load_history(self): """Load history from a .py file in user home directory""" if osp.isfile(self.history_filename): rawhistory, _ = encoding.readlines(self.history_filename) rawhistory = [line.replace('\n', '') for line in rawhistory] if rawhistory[1] != self.INITHISTORY[1]: rawhistory[1] = self.INITHISTORY[1] else: rawhistory = self.INITHISTORY history = [line for line in rawhistory \ if line and not line.startswith('#')] # Truncating history to X entries: while len(history) >= CONF.get('historylog', 'max_entries'): del history[0] while rawhistory[0].startswith('#'): del rawhistory[0] del rawhistory[0] # Saving truncated history: encoding.writelines(rawhistory, self.history_filename) return history #------ Simulation standards input/output def write_error(self, text): """Simulate stderr""" self.flush() self.write(text, flush=True, error=True) if DEBUG: STDERR.write(text) def write(self, text, flush=False, error=False, prompt=False): """Simulate stdout and stderr""" if prompt: self.flush() if not is_string(text): # This test is useful to discriminate QStrings from decoded str text = to_text_string(text) self.__buffer.append(text) ts = time.time() if flush or prompt: self.flush(error=error, prompt=prompt) elif ts - self.__timestamp > 0.05: self.flush(error=error) self.__timestamp = ts # Timer to flush strings cached by last write() operation in series self.__flushtimer.start(50) def flush(self, error=False, prompt=False): """Flush buffer, write text to console""" # Fix for Issue 2452 if PY3: try: text = "".join(self.__buffer) except TypeError: text = b"".join(self.__buffer) try: text = text.decode( locale.getdefaultlocale()[1] ) except: pass else: text = "".join(self.__buffer) self.__buffer = [] self.insert_text(text, at_end=True, error=error, prompt=prompt) QCoreApplication.processEvents() self.repaint() # Clear input buffer: self.new_input_line = True #------ Text Insertion def insert_text(self, text, at_end=False, error=False, prompt=False): """ Insert text at the current cursor position or at the end of the command line """ if at_end: # Insert text at the end of the command line self.append_text_to_shell(text, error, prompt) else: # Insert text at current cursor position ConsoleBaseWidget.insert_text(self, text) #------ Re-implemented Qt Methods def focusNextPrevChild(self, next): """ Reimplemented to stop Tab moving to the next window """ if next: return False return ConsoleBaseWidget.focusNextPrevChild(self, next) #------ Drag and drop def dragEnterEvent(self, event): """Drag and Drop - Enter event""" event.setAccepted(event.mimeData().hasFormat("text/plain")) def dragMoveEvent(self, event): """Drag and Drop - Move event""" if (event.mimeData().hasFormat("text/plain")): event.setDropAction(Qt.MoveAction) event.accept() else: event.ignore() def dropEvent(self, event): """Drag and Drop - Drop event""" if (event.mimeData().hasFormat("text/plain")): text = to_text_string(event.mimeData().text()) if self.new_input_line: self.on_new_line() self.insert_text(text, at_end=True) self.setFocus() event.setDropAction(Qt.MoveAction) event.accept() else: event.ignore() def drop_pathlist(self, pathlist): """Drop path list""" raise NotImplementedError # Example how to debug complex interclass call chains: # # from spyder.utils.debug import log_methods_calls # log_methods_calls('log.log', ShellBaseWidget) class PythonShellWidget(TracebackLinksMixin, ShellBaseWidget, GetHelpMixin): """Python shell widget""" QT_CLASS = ShellBaseWidget INITHISTORY = ['# -*- coding: utf-8 -*-', '# *** Spyder Python Console History Log ***',] SEPARATOR = '%s##---(%s)---' % (os.linesep*2, time.ctime()) go_to_error = Signal(str) def __init__(self, parent, history_filename, profile=False, initial_message=None): ShellBaseWidget.__init__(self, parent, history_filename, profile, initial_message) TracebackLinksMixin.__init__(self) GetHelpMixin.__init__(self) # Local shortcuts self.shortcuts = self.create_shortcuts() def create_shortcuts(self): array_inline = config_shortcut(lambda: self.enter_array_inline(), context='array_builder', name='enter array inline', parent=self) array_table = config_shortcut(lambda: self.enter_array_table(), context='array_builder', name='enter array table', parent=self) inspectsc = config_shortcut(self.inspect_current_object, context='Console', name='Inspect current object', parent=self) return [inspectsc, array_inline, array_table] def get_shortcut_data(self): """ Returns shortcut data, a list of tuples (shortcut, text, default) shortcut (QShortcut or QAction instance) text (string): action/shortcut description default (string): default key sequence """ return [sc.data for sc in self.shortcuts] #------ Context menu def setup_context_menu(self): """Reimplements ShellBaseWidget method""" ShellBaseWidget.setup_context_menu(self) self.copy_without_prompts_action = create_action(self, _("Copy without prompts"), icon=ima.icon('copywop'), triggered=self.copy_without_prompts) clear_line_action = create_action(self, _("Clear line"), QKeySequence(get_shortcut('console', 'Clear line')), icon=ima.icon('editdelete'), tip=_("Clear line"), triggered=self.clear_line) clear_action = create_action(self, _("Clear shell"), QKeySequence(get_shortcut('console', 'Clear shell')), icon=ima.icon('editclear'), tip=_("Clear shell contents " "('cls' command)"), triggered=self.clear_terminal) add_actions(self.menu, (self.copy_without_prompts_action, clear_line_action, clear_action)) def contextMenuEvent(self, event): """Reimplements ShellBaseWidget method""" state = self.has_selected_text() self.copy_without_prompts_action.setEnabled(state) ShellBaseWidget.contextMenuEvent(self, event) @Slot() def copy_without_prompts(self): """Copy text to clipboard without prompts""" text = self.get_selected_text() lines = text.split(os.linesep) for index, line in enumerate(lines): if line.startswith('>>> ') or line.startswith('... '): lines[index] = line[4:] text = os.linesep.join(lines) QApplication.clipboard().setText(text) #------ Key handlers def postprocess_keyevent(self, event): """Process keypress event""" ShellBaseWidget.postprocess_keyevent(self, event) if QToolTip.isVisible(): _event, _text, key, _ctrl, _shift = restore_keyevent(event) self.hide_tooltip_if_necessary(key) def _key_other(self, text): """1 character key""" if self.is_completion_widget_visible(): self.completion_text += text def _key_backspace(self, cursor_position): """Action for Backspace key""" if self.has_selected_text(): self.check_selection() self.remove_selected_text() elif self.current_prompt_pos == cursor_position: # Avoid deleting prompt return elif self.is_cursor_on_last_line(): self.stdkey_backspace() if self.is_completion_widget_visible(): # Removing only last character because if there was a selection # the completion widget would have been canceled self.completion_text = self.completion_text[:-1] def _key_tab(self): """Action for TAB key""" if self.is_cursor_on_last_line(): empty_line = not self.get_current_line_to_cursor().strip() if empty_line: self.stdkey_tab() else: self.show_code_completion(automatic=False) def _key_ctrl_space(self): """Action for Ctrl+Space""" if not self.is_completion_widget_visible(): self.show_code_completion(automatic=False) def _key_pageup(self): """Action for PageUp key""" pass def _key_pagedown(self): """Action for PageDown key""" pass def _key_escape(self): """Action for ESCAPE key""" if self.is_completion_widget_visible(): self.hide_completion_widget() def _key_question(self, text): """Action for '?'""" if self.get_current_line_to_cursor(): last_obj = self.get_last_obj() if last_obj and not last_obj.isdigit(): self.show_object_info(last_obj) self.insert_text(text) # In case calltip and completion are shown at the same time: if self.is_completion_widget_visible(): self.completion_text += '?' def _key_parenleft(self, text): """Action for '('""" self.hide_completion_widget() if self.get_current_line_to_cursor(): last_obj = self.get_last_obj() if last_obj and not last_obj.isdigit(): self.insert_text(text) self.show_object_info(last_obj, call=True) return self.insert_text(text) def _key_period(self, text): """Action for '.'""" self.insert_text(text) if self.codecompletion_auto: # Enable auto-completion only if last token isn't a float last_obj = self.get_last_obj() if last_obj and not last_obj.isdigit(): self.show_code_completion(automatic=True) #------ Paste def paste(self): """Reimplemented slot to handle multiline paste action""" text = to_text_string(QApplication.clipboard().text()) if len(text.splitlines()) > 1: # Multiline paste if self.new_input_line: self.on_new_line() self.remove_selected_text() # Remove selection, eventually end = self.get_current_line_from_cursor() lines = self.get_current_line_to_cursor() + text + end self.clear_line() self.execute_lines(lines) self.move_cursor(-len(end)) else: # Standard paste ShellBaseWidget.paste(self) #------ Code Completion / Calltips # Methods implemented in child class: # (e.g. InternalShell) def get_dir(self, objtxt): """Return dir(object)""" raise NotImplementedError def get_module_completion(self, objtxt): """Return module completion list associated to object name""" pass def get_globals_keys(self): """Return shell globals() keys""" raise NotImplementedError def get_cdlistdir(self): """Return shell current directory list dir""" raise NotImplementedError def iscallable(self, objtxt): """Is object callable?""" raise NotImplementedError def get_arglist(self, objtxt): """Get func/method argument list""" raise NotImplementedError def get__doc__(self, objtxt): """Get object __doc__""" raise NotImplementedError def get_doc(self, objtxt): """Get object documentation dictionary""" raise NotImplementedError def get_source(self, objtxt): """Get object source""" raise NotImplementedError def is_defined(self, objtxt, force_import=False): """Return True if object is defined""" raise NotImplementedError def show_code_completion(self, automatic): """Display a completion list based on the current line""" # Note: unicode conversion is needed only for ExternalShellBase text = to_text_string(self.get_current_line_to_cursor()) last_obj = self.get_last_obj() if not text: return if text.startswith('import '): obj_list = self.get_module_completion(text) words = text.split(' ') if ',' in words[-1]: words = words[-1].split(',') self.show_completion_list(obj_list, completion_text=words[-1], automatic=automatic) return elif text.startswith('from '): obj_list = self.get_module_completion(text) if obj_list is None: return words = text.split(' ') if '(' in words[-1]: words = words[:-2] + words[-1].split('(') if ',' in words[-1]: words = words[:-2] + words[-1].split(',') self.show_completion_list(obj_list, completion_text=words[-1], automatic=automatic) return obj_dir = self.get_dir(last_obj) if last_obj and obj_dir and text.endswith('.'): self.show_completion_list(obj_dir, automatic=automatic) return # Builtins and globals if not text.endswith('.') and last_obj \ and re.match(r'[a-zA-Z_0-9]*$', last_obj): b_k_g = dir(builtins)+self.get_globals_keys()+keyword.kwlist for objname in b_k_g: if objname.startswith(last_obj) and objname != last_obj: self.show_completion_list(b_k_g, completion_text=last_obj, automatic=automatic) return else: return # Looking for an incomplete completion if last_obj is None: last_obj = text dot_pos = last_obj.rfind('.') if dot_pos != -1: if dot_pos == len(last_obj)-1: completion_text = "" else: completion_text = last_obj[dot_pos+1:] last_obj = last_obj[:dot_pos] completions = self.get_dir(last_obj) if completions is not None: self.show_completion_list(completions, completion_text=completion_text, automatic=automatic) return # Looking for ' or ": filename completion q_pos = max([text.rfind("'"), text.rfind('"')]) if q_pos != -1: completions = self.get_cdlistdir() if completions: self.show_completion_list(completions, completion_text=text[q_pos+1:], automatic=automatic) return #------ Drag'n Drop def drop_pathlist(self, pathlist): """Drop path list""" if pathlist: files = ["r'%s'" % path for path in pathlist] if len(files) == 1: text = files[0] else: text = "[" + ", ".join(files) + "]" if self.new_input_line: self.on_new_line() self.insert_text(text) self.setFocus() class TerminalWidget(ShellBaseWidget): """ Terminal widget """ COM = 'rem' if os.name == 'nt' else '#' INITHISTORY = ['%s *** Spyder Terminal History Log ***' % COM, COM,] SEPARATOR = '%s%s ---(%s)---' % (os.linesep*2, COM, time.ctime()) go_to_error = Signal(str) def __init__(self, parent, history_filename, profile=False): ShellBaseWidget.__init__(self, parent, history_filename, profile) #------ Key handlers def _key_other(self, text): """1 character key""" pass def _key_backspace(self, cursor_position): """Action for Backspace key""" if self.has_selected_text(): self.check_selection() self.remove_selected_text() elif self.current_prompt_pos == cursor_position: # Avoid deleting prompt return elif self.is_cursor_on_last_line(): self.stdkey_backspace() def _key_tab(self): """Action for TAB key""" if self.is_cursor_on_last_line(): self.stdkey_tab() def _key_ctrl_space(self): """Action for Ctrl+Space""" pass def _key_escape(self): """Action for ESCAPE key""" self.clear_line() def _key_question(self, text): """Action for '?'""" self.insert_text(text) def _key_parenleft(self, text): """Action for '('""" self.insert_text(text) def _key_period(self, text): """Action for '.'""" self.insert_text(text) #------ Drag'n Drop def drop_pathlist(self, pathlist): """Drop path list""" if pathlist: files = ['"%s"' % path for path in pathlist] if len(files) == 1: text = files[0] else: text = " ".join(files) if self.new_input_line: self.on_new_line() self.insert_text(text) self.setFocus() spyder-3.2.6/spyder/widgets/findreplace.py0000664000175000017500000006140213224740762021436 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Find/Replace widget""" # pylint: disable=C0103 # pylint: disable=R0903 # pylint: disable=R0911 # pylint: disable=R0201 # Standard library imports import re # Third party imports from qtpy.QtCore import Qt, QTimer, Signal, Slot, QEvent from qtpy.QtGui import QTextCursor from qtpy.QtWidgets import (QGridLayout, QHBoxLayout, QLabel, QSizePolicy, QWidget) # Local imports from spyder.config.base import _ from spyder.config.gui import config_shortcut from spyder.py3compat import to_text_string from spyder.utils import icon_manager as ima from spyder.utils.qthelpers import create_toolbutton, get_icon from spyder.widgets.comboboxes import PatternComboBox def is_position_sup(pos1, pos2): """Return True is pos1 > pos2""" return pos1 > pos2 def is_position_inf(pos1, pos2): """Return True is pos1 < pos2""" return pos1 < pos2 class FindReplace(QWidget): """Find widget""" STYLE = {False: "background-color:rgb(255, 175, 90);", True: "", None: "", 'regexp_error': "background-color:rgb(255, 80, 80);", } TOOLTIP = {False: _("No matches"), True: _("Search string"), None: _("Search string"), 'regexp_error': _("Regular expression error") } visibility_changed = Signal(bool) return_shift_pressed = Signal() return_pressed = Signal() def __init__(self, parent, enable_replace=False): QWidget.__init__(self, parent) self.enable_replace = enable_replace self.editor = None self.is_code_editor = None glayout = QGridLayout() glayout.setContentsMargins(0, 0, 0, 0) self.setLayout(glayout) self.close_button = create_toolbutton(self, triggered=self.hide, icon=ima.icon('DialogCloseButton')) glayout.addWidget(self.close_button, 0, 0) # Find layout self.search_text = PatternComboBox(self, tip=_("Search string"), adjust_to_minimum=False) self.return_shift_pressed.connect( lambda: self.find(changed=False, forward=False, rehighlight=False, multiline_replace_check = False)) self.return_pressed.connect( lambda: self.find(changed=False, forward=True, rehighlight=False, multiline_replace_check = False)) self.search_text.lineEdit().textEdited.connect( self.text_has_been_edited) self.number_matches_text = QLabel(self) self.previous_button = create_toolbutton(self, triggered=self.find_previous, icon=ima.icon('ArrowUp')) self.next_button = create_toolbutton(self, triggered=self.find_next, icon=ima.icon('ArrowDown')) self.next_button.clicked.connect(self.update_search_combo) self.previous_button.clicked.connect(self.update_search_combo) self.re_button = create_toolbutton(self, icon=ima.icon('advanced'), tip=_("Regular expression")) self.re_button.setCheckable(True) self.re_button.toggled.connect(lambda state: self.find()) self.case_button = create_toolbutton(self, icon=get_icon("upper_lower.png"), tip=_("Case Sensitive")) self.case_button.setCheckable(True) self.case_button.toggled.connect(lambda state: self.find()) self.words_button = create_toolbutton(self, icon=get_icon("whole_words.png"), tip=_("Whole words")) self.words_button.setCheckable(True) self.words_button.toggled.connect(lambda state: self.find()) self.highlight_button = create_toolbutton(self, icon=get_icon("highlight.png"), tip=_("Highlight matches")) self.highlight_button.setCheckable(True) self.highlight_button.toggled.connect(self.toggle_highlighting) hlayout = QHBoxLayout() self.widgets = [self.close_button, self.search_text, self.number_matches_text, self.previous_button, self.next_button, self.re_button, self.case_button, self.words_button, self.highlight_button] for widget in self.widgets[1:]: hlayout.addWidget(widget) glayout.addLayout(hlayout, 0, 1) # Replace layout replace_with = QLabel(_("Replace with:")) self.replace_text = PatternComboBox(self, adjust_to_minimum=False, tip=_('Replace string')) self.replace_text.valid.connect( lambda _: self.replace_find(focus_replace_text=True)) self.replace_button = create_toolbutton(self, text=_('Replace/find next'), icon=ima.icon('DialogApplyButton'), triggered=self.replace_find, text_beside_icon=True) self.replace_sel_button = create_toolbutton(self, text=_('Replace selection'), icon=ima.icon('DialogApplyButton'), triggered=self.replace_find_selection, text_beside_icon=True) self.replace_sel_button.clicked.connect(self.update_replace_combo) self.replace_sel_button.clicked.connect(self.update_search_combo) self.replace_all_button = create_toolbutton(self, text=_('Replace all'), icon=ima.icon('DialogApplyButton'), triggered=self.replace_find_all, text_beside_icon=True) self.replace_all_button.clicked.connect(self.update_replace_combo) self.replace_all_button.clicked.connect(self.update_search_combo) self.replace_layout = QHBoxLayout() widgets = [replace_with, self.replace_text, self.replace_button, self.replace_sel_button, self.replace_all_button] for widget in widgets: self.replace_layout.addWidget(widget) glayout.addLayout(self.replace_layout, 1, 1) self.widgets.extend(widgets) self.replace_widgets = widgets self.hide_replace() self.search_text.setTabOrder(self.search_text, self.replace_text) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.shortcuts = self.create_shortcuts(parent) self.highlight_timer = QTimer(self) self.highlight_timer.setSingleShot(True) self.highlight_timer.setInterval(1000) self.highlight_timer.timeout.connect(self.highlight_matches) self.search_text.installEventFilter(self) def eventFilter(self, widget, event): """Event filter for search_text widget. Emits signals when presing Enter and Shift+Enter. This signals are used for search forward and backward. Also, a crude hack to get tab working in the Find/Replace boxes. """ if event.type() == QEvent.KeyPress: key = event.key() shift = event.modifiers() & Qt.ShiftModifier if key == Qt.Key_Return: if shift: self.return_shift_pressed.emit() else: self.return_pressed.emit() if key == Qt.Key_Tab: self.focusNextChild() return super(FindReplace, self).eventFilter(widget, event) def create_shortcuts(self, parent): """Create shortcuts for this widget""" # Configurable findnext = config_shortcut(self.find_next, context='_', name='Find next', parent=parent) findprev = config_shortcut(self.find_previous, context='_', name='Find previous', parent=parent) togglefind = config_shortcut(self.show, context='_', name='Find text', parent=parent) togglereplace = config_shortcut(self.show_replace, context='_', name='Replace text', parent=parent) hide = config_shortcut(self.hide, context='_', name='hide find and replace', parent=self) return [findnext, findprev, togglefind, togglereplace, hide] def get_shortcut_data(self): """ Returns shortcut data, a list of tuples (shortcut, text, default) shortcut (QShortcut or QAction instance) text (string): action/shortcut description default (string): default key sequence """ return [sc.data for sc in self.shortcuts] def update_search_combo(self): self.search_text.lineEdit().returnPressed.emit() def update_replace_combo(self): self.replace_text.lineEdit().returnPressed.emit() def toggle_replace_widgets(self): if self.enable_replace: # Toggle replace widgets if self.replace_widgets[0].isVisible(): self.hide_replace() self.hide() else: self.show_replace() if len(to_text_string(self.search_text.currentText()))>0: self.replace_text.setFocus() @Slot(bool) def toggle_highlighting(self, state): """Toggle the 'highlight all results' feature""" if self.editor is not None: if state: self.highlight_matches() else: self.clear_matches() def show(self, hide_replace=True): """Overrides Qt Method""" QWidget.show(self) self.visibility_changed.emit(True) self.change_number_matches() if self.editor is not None: if hide_replace: if self.replace_widgets[0].isVisible(): self.hide_replace() text = self.editor.get_selected_text() # When selecting several lines, and replace box is activated the # text won't be replaced for the selection if hide_replace or len(text.splitlines())<=1: highlighted = True # If no text is highlighted for search, use whatever word is # under the cursor if not text: highlighted = False try: cursor = self.editor.textCursor() cursor.select(QTextCursor.WordUnderCursor) text = to_text_string(cursor.selectedText()) except AttributeError: # We can't do this for all widgets, e.g. WebView's pass # Now that text value is sorted out, use it for the search if text and not self.search_text.currentText() or highlighted: self.search_text.setEditText(text) self.search_text.lineEdit().selectAll() self.refresh() else: self.search_text.lineEdit().selectAll() self.search_text.setFocus() @Slot() def hide(self): """Overrides Qt Method""" for widget in self.replace_widgets: widget.hide() QWidget.hide(self) self.visibility_changed.emit(False) if self.editor is not None: self.editor.setFocus() self.clear_matches() def show_replace(self): """Show replace widgets""" self.show(hide_replace=False) for widget in self.replace_widgets: widget.show() def hide_replace(self): """Hide replace widgets""" for widget in self.replace_widgets: widget.hide() def refresh(self): """Refresh widget""" if self.isHidden(): if self.editor is not None: self.clear_matches() return state = self.editor is not None for widget in self.widgets: widget.setEnabled(state) if state: self.find() def set_editor(self, editor, refresh=True): """ Set associated editor/web page: codeeditor.base.TextEditBaseWidget browser.WebView """ self.editor = editor # Note: This is necessary to test widgets/editor.py # in Qt builds that don't have web widgets try: from qtpy.QtWebEngineWidgets import QWebEngineView except ImportError: QWebEngineView = type(None) self.words_button.setVisible(not isinstance(editor, QWebEngineView)) self.re_button.setVisible(not isinstance(editor, QWebEngineView)) from spyder.widgets.sourcecode.codeeditor import CodeEditor self.is_code_editor = isinstance(editor, CodeEditor) self.highlight_button.setVisible(self.is_code_editor) if refresh: self.refresh() if self.isHidden() and editor is not None: self.clear_matches() @Slot() def find_next(self): """Find next occurrence""" state = self.find(changed=False, forward=True, rehighlight=False, multiline_replace_check=False) self.editor.setFocus() self.search_text.add_current_text() return state @Slot() def find_previous(self): """Find previous occurrence""" state = self.find(changed=False, forward=False, rehighlight=False, multiline_replace_check=False) self.editor.setFocus() return state def text_has_been_edited(self, text): """Find text has been edited (this slot won't be triggered when setting the search pattern combo box text programmatically)""" self.find(changed=True, forward=True, start_highlight_timer=True) def highlight_matches(self): """Highlight found results""" if self.is_code_editor and self.highlight_button.isChecked(): text = self.search_text.currentText() words = self.words_button.isChecked() regexp = self.re_button.isChecked() self.editor.highlight_found_results(text, words=words, regexp=regexp) def clear_matches(self): """Clear all highlighted matches""" if self.is_code_editor: self.editor.clear_found_results() def find(self, changed=True, forward=True, rehighlight=True, start_highlight_timer=False, multiline_replace_check=True): """Call the find function""" # When several lines are selected in the editor and replace box is activated, # dynamic search is deactivated to prevent changing the selection. Otherwise # we show matching items. def regexp_error_msg(pattern): """Returns None if the pattern is a valid regular expression or a string describing why the pattern is invalid. """ try: re.compile(pattern) except re.error as e: return str(e) return None if multiline_replace_check and self.replace_widgets[0].isVisible() and \ len(to_text_string(self.editor.get_selected_text()).splitlines())>1: return None text = self.search_text.currentText() if len(text) == 0: self.search_text.lineEdit().setStyleSheet("") if not self.is_code_editor: # Clears the selection for WebEngine self.editor.find_text('') self.change_number_matches() return None else: case = self.case_button.isChecked() words = self.words_button.isChecked() regexp = self.re_button.isChecked() found = self.editor.find_text(text, changed, forward, case=case, words=words, regexp=regexp) stylesheet = self.STYLE[found] tooltip = self.TOOLTIP[found] if not found and regexp: error_msg = regexp_error_msg(text) if error_msg: # special styling for regexp errors stylesheet = self.STYLE['regexp_error'] tooltip = self.TOOLTIP['regexp_error'] + ': ' + error_msg self.search_text.lineEdit().setStyleSheet(stylesheet) self.search_text.setToolTip(tooltip) if self.is_code_editor and found: if rehighlight or not self.editor.found_results: self.highlight_timer.stop() if start_highlight_timer: self.highlight_timer.start() else: self.highlight_matches() else: self.clear_matches() number_matches = self.editor.get_number_matches(text, case=case) if hasattr(self.editor, 'get_match_number'): match_number = self.editor.get_match_number(text, case=case) else: match_number = 0 self.change_number_matches(current_match=match_number, total_matches=number_matches) return found @Slot() def replace_find(self, focus_replace_text=False, replace_all=False): """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()) re_pattern = None if self.re_button.isChecked(): try: re_pattern = re.compile(search_text) except re.error: return # do nothing with an invalid regexp 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 re_pattern is None: has_selected = self.editor.has_selected_text() if has_selected and cmptxt1 == cmptxt2: # Text was already found, do nothing pass else: if not self.find(changed=False, forward=True, rehighlight=False): break else: if len(re_pattern.findall(cmptxt2)) > 0: 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 occurrence break position0 = position1 if re_pattern is None: cursor.removeSelectedText() cursor.insertText(replace_text) else: seltxt = to_text_string(cursor.selectedText()) cursor.removeSelectedText() cursor.insertText(re_pattern.sub(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 replace_all: break if cursor is not None: cursor.endEditBlock() if focus_replace_text: self.replace_text.setFocus() @Slot() def replace_find_all(self, focus_replace_text=False): """Replace and find all matching occurrences""" self.replace_find(focus_replace_text, replace_all=True) @Slot() def replace_find_selection(self, focus_replace_text=False): """Replace and find in the current selection""" if self.editor is not None: replace_text = to_text_string(self.replace_text.currentText()) search_text = to_text_string(self.search_text.currentText()) case = self.case_button.isChecked() words = self.words_button.isChecked() re_flags = re.MULTILINE if case else re.IGNORECASE|re.MULTILINE re_pattern = None if self.re_button.isChecked(): pattern = search_text else: pattern = re.escape(search_text) replace_text = re.escape(replace_text) if words: # match whole words only pattern = r'\b{pattern}\b'.format(pattern=pattern) try: re_pattern = re.compile(pattern, flags=re_flags) except re.error as e: return # do nothing with an invalid regexp selected_text = to_text_string(self.editor.get_selected_text()) replacement = re_pattern.sub(replace_text, selected_text) if replacement != selected_text: cursor = self.editor.textCursor() cursor.beginEditBlock() cursor.removeSelectedText() if not self.re_button.isChecked(): replacement = re.sub(r'\\(?![nrtf])(.)', r'\1', replacement) cursor.insertText(replacement) cursor.endEditBlock() if focus_replace_text: self.replace_text.setFocus() else: self.editor.setFocus() def change_number_matches(self, current_match=0, total_matches=0): """Change number of match and total matches.""" if current_match and total_matches: matches_string = "{} {} {}".format(current_match, _("of"), total_matches) self.number_matches_text.setText(matches_string) elif total_matches: matches_string = "{} {}".format(total_matches, _("matches")) self.number_matches_text.setText(matches_string) else: self.number_matches_text.setText(_("no matches")) spyder-3.2.6/spyder/widgets/calltip.py0000664000175000017500000003010013156676663020615 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- #----------------------------------------------------------------------------- # Copyright (c) IPython Development Team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file COPYING.txt, distributed with IPython. #----------------------------------------------------------------------------- """ Calltip widget used only to show signatures """ # Standard library imports from unicodedata import category # Third party imports from qtpy.QtCore import QBasicTimer, QCoreApplication, QEvent, Qt from qtpy.QtGui import QCursor, QPalette from qtpy.QtWidgets import (QFrame, QLabel, QTextEdit, QPlainTextEdit, QStyle, QStyleOptionFrame, QStylePainter, QToolTip) # Local imports from spyder.py3compat import to_text_string class CallTipWidget(QLabel): """ Shows call tips by parsing the current text of Q[Plain]TextEdit. """ #-------------------------------------------------------------------------- # 'QObject' interface #-------------------------------------------------------------------------- def __init__(self, text_edit, hide_timer_on=False): """ Create a call tip manager that is attached to the specified Qt text edit widget. """ assert isinstance(text_edit, (QTextEdit, QPlainTextEdit)) super(CallTipWidget, self).__init__(None, Qt.ToolTip) self.app = QCoreApplication.instance() self.hide_timer_on = hide_timer_on self.tip = None self._hide_timer = QBasicTimer() self._text_edit = text_edit self.setFont(text_edit.document().defaultFont()) self.setForegroundRole(QPalette.ToolTipText) self.setBackgroundRole(QPalette.ToolTipBase) self.setPalette(QToolTip.palette()) self.setAlignment(Qt.AlignLeft) self.setIndent(1) self.setFrameStyle(QFrame.NoFrame) self.setMargin(1 + self.style().pixelMetric( QStyle.PM_ToolTipLabelFrameWidth, None, self)) def eventFilter(self, obj, event): """ Reimplemented to hide on certain key presses and on text edit focus changes. """ if obj == self._text_edit: etype = event.type() if etype == QEvent.KeyPress: key = event.key() cursor = self._text_edit.textCursor() prev_char = self._text_edit.get_character(cursor.position(), offset=-1) if key in (Qt.Key_Enter, Qt.Key_Return, Qt.Key_Down, Qt.Key_Up): self.hide() elif key == Qt.Key_Escape: self.hide() return True elif prev_char == ')': self.hide() elif etype == QEvent.FocusOut: self.hide() elif etype == QEvent.Enter: if (self._hide_timer.isActive() and self.app.topLevelAt(QCursor.pos()) == self): self._hide_timer.stop() elif etype == QEvent.Leave: self._leave_event_hide() return super(CallTipWidget, self).eventFilter(obj, event) def timerEvent(self, event): """ Reimplemented to hide the widget when the hide timer fires. """ if event.timerId() == self._hide_timer.timerId(): self._hide_timer.stop() self.hide() #-------------------------------------------------------------------------- # 'QWidget' interface #-------------------------------------------------------------------------- def enterEvent(self, event): """ Reimplemented to cancel the hide timer. """ super(CallTipWidget, self).enterEvent(event) if (self._hide_timer.isActive() and self.app.topLevelAt(QCursor.pos()) == self): self._hide_timer.stop() def hideEvent(self, event): """ Reimplemented to disconnect signal handlers and event filter. """ super(CallTipWidget, self).hideEvent(event) self._text_edit.cursorPositionChanged.disconnect( self._cursor_position_changed) self._text_edit.removeEventFilter(self) def leaveEvent(self, event): """ Reimplemented to start the hide timer. """ super(CallTipWidget, self).leaveEvent(event) self._leave_event_hide() def mousePressEvent(self, event): super(CallTipWidget, self).mousePressEvent(event) self.hide() def paintEvent(self, event): """ Reimplemented to paint the background panel. """ painter = QStylePainter(self) option = QStyleOptionFrame() option.initFrom(self) painter.drawPrimitive(QStyle.PE_PanelTipLabel, option) painter.end() super(CallTipWidget, self).paintEvent(event) def setFont(self, font): """ Reimplemented to allow use of this method as a slot. """ super(CallTipWidget, self).setFont(font) def showEvent(self, event): """ Reimplemented to connect signal handlers and event filter. """ super(CallTipWidget, self).showEvent(event) self._text_edit.cursorPositionChanged.connect( self._cursor_position_changed) self._text_edit.installEventFilter(self) def focusOutEvent(self, event): """ Reimplemented to hide it when focus goes out of the main window. """ self.hide() #-------------------------------------------------------------------------- # 'CallTipWidget' interface #-------------------------------------------------------------------------- def show_tip(self, point, tip, wrapped_tiplines): """ Attempts to show the specified tip at the current cursor location. """ # Don't attempt to show it if it's already visible and the text # to be displayed is the same as the one displayed before. if self.isVisible(): if self.tip == tip: return True else: self.hide() # Attempt to find the cursor position at which to show the call tip. text_edit = self._text_edit cursor = text_edit.textCursor() search_pos = cursor.position() - 1 self._start_position, _ = self._find_parenthesis(search_pos, forward=False) if self._start_position == -1: return False if self.hide_timer_on: self._hide_timer.stop() # Logic to decide how much time to show the calltip depending # on the amount of text present if len(wrapped_tiplines) == 1: args = wrapped_tiplines[0].split('(')[1] nargs = len(args.split(',')) if nargs == 1: hide_time = 1400 elif nargs == 2: hide_time = 1600 else: hide_time = 1800 elif len(wrapped_tiplines) == 2: args1 = wrapped_tiplines[1].strip() nargs1 = len(args1.split(',')) if nargs1 == 1: hide_time = 2500 else: hide_time = 2800 else: hide_time = 3500 self._hide_timer.start(hide_time, self) # Set the text and resize the widget accordingly. self.tip = tip self.setText(tip) self.resize(self.sizeHint()) # Locate and show the widget. Place the tip below the current line # unless it would be off the screen. In that case, decide the best # location based trying to minimize the area that goes off-screen. padding = 3 # Distance in pixels between cursor bounds and tip box. cursor_rect = text_edit.cursorRect(cursor) screen_rect = self.app.desktop().screenGeometry(text_edit) point.setY(point.y() + padding) tip_height = self.size().height() tip_width = self.size().width() vertical = 'bottom' horizontal = 'Right' if point.y() + tip_height > screen_rect.height() + screen_rect.y(): point_ = text_edit.mapToGlobal(cursor_rect.topRight()) # If tip is still off screen, check if point is in top or bottom # half of screen. if point_.y() - tip_height < padding: # If point is in upper half of screen, show tip below it. # otherwise above it. if 2*point.y() < screen_rect.height(): vertical = 'bottom' else: vertical = 'top' else: vertical = 'top' if point.x() + tip_width > screen_rect.width() + screen_rect.x(): point_ = text_edit.mapToGlobal(cursor_rect.topRight()) # If tip is still off-screen, check if point is in the right or # left half of the screen. if point_.x() - tip_width < padding: if 2*point.x() < screen_rect.width(): horizontal = 'Right' else: horizontal = 'Left' else: horizontal = 'Left' pos = getattr(cursor_rect, '%s%s' %(vertical, horizontal)) adjusted_point = text_edit.mapToGlobal(pos()) if vertical == 'top': point.setY(adjusted_point.y() - tip_height - padding) if horizontal == 'Left': point.setX(adjusted_point.x() - tip_width - padding) self.move(point) self.show() return True #-------------------------------------------------------------------------- # Protected interface #-------------------------------------------------------------------------- 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 _leave_event_hide(self): """ Hides the tooltip after some time has passed (assuming the cursor is not over the tooltip). """ if (self.hide_timer_on and not self._hide_timer.isActive() and # If Enter events always came after Leave events, we wouldn't need # this check. But on Mac OS, it sometimes happens the other way # around when the tooltip is created. self.app.topLevelAt(QCursor.pos()) != self): self._hide_timer.start(800, self) #------ Signal handlers ---------------------------------------------------- def _cursor_position_changed(self): """ Updates the tip based on user cursor movement. """ cursor = self._text_edit.textCursor() position = cursor.position() document = self._text_edit.document() char = to_text_string(document.characterAt(position - 1)) if position <= self._start_position: self.hide() elif char == ')': pos, _ = self._find_parenthesis(position - 1, forward=False) if pos == -1: self.hide() spyder-3.2.6/spyder/widgets/__init__.py0000664000175000017500000000055613026261006020711 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ spyder.widgets ============== Widgets defined in this module may be used in any other Qt-based application They are also used in Spyder through the Plugin interface (see spyder.plugins) """ spyder-3.2.6/spyder/widgets/editortools.py0000664000175000017500000005642713224740762021544 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Editor tools: outline explorer, etc.""" # Standard library imports from __future__ import print_function import os.path as osp import re # Third party imports from qtpy.compat import from_qvariant from qtpy.QtCore import Qt, Signal, Slot from qtpy.QtWidgets import QHBoxLayout, QTreeWidgetItem, QVBoxLayout, QWidget # Local imports from spyder.config.base import _, STDOUT from spyder.py3compat import to_text_string from spyder.utils import icon_manager as ima from spyder.utils.qthelpers import (create_action, create_toolbutton, set_item_user_text, create_plugin_layout) from spyder.widgets.onecolumntree import OneColumnTree #=============================================================================== # Class browser #=============================================================================== class PythonCFM(object): """ Collection of helpers to match functions and classes for Python language This has to be reimplemented for other languages for the outline explorer to be supported (not implemented yet: outline explorer won't be populated unless the current script is a Python script) """ def __get_name(self, statmt, text): match = re.match(r'[\ ]*%s ([a-zA-Z0-9_]*)[\ ]*[\(|\:]' % statmt, text) if match is not None: return match.group(1) def get_function_name(self, text): return self.__get_name('def', text) def get_class_name(self, text): return self.__get_name('class', text) class FileRootItem(QTreeWidgetItem): def __init__(self, path, treewidget): QTreeWidgetItem.__init__(self, treewidget, QTreeWidgetItem.Type) self.path = path self.setIcon(0, ima.icon('python')) self.setToolTip(0, path) set_item_user_text(self, path) def set_path(self, path, fullpath): self.path = path self.set_text(fullpath) def set_text(self, fullpath): self.setText(0, self.path if fullpath else osp.basename(self.path)) class TreeItem(QTreeWidgetItem): """Class browser item base class""" def __init__(self, name, line, parent, preceding): if preceding is None: QTreeWidgetItem.__init__(self, parent, QTreeWidgetItem.Type) else: if preceding is not parent: # Preceding must be either the same as item's parent # or have the same parent as item while preceding.parent() is not parent: preceding = preceding.parent() if preceding is None: break if preceding is None: QTreeWidgetItem.__init__(self, parent, QTreeWidgetItem.Type) else: QTreeWidgetItem.__init__(self, parent, preceding, QTreeWidgetItem.Type) self.setText(0, name) parent_text = from_qvariant(parent.data(0, Qt.UserRole), to_text_string) set_item_user_text(self, parent_text+'/'+name) self.line = line def set_icon(self, icon): self.setIcon(0, icon) def setup(self): self.setToolTip(0, _("Line %s") % str(self.line)) class ClassItem(TreeItem): def setup(self): self.set_icon(ima.icon('class')) self.setToolTip(0, _("Class defined at line %s") % str(self.line)) class FunctionItem(TreeItem): def is_method(self): return isinstance(self.parent(), ClassItem) def setup(self): if self.is_method(): self.setToolTip(0, _("Method defined at line %s") % str(self.line)) name = to_text_string(self.text(0)) if name.startswith('__'): self.set_icon(ima.icon('private2')) elif name.startswith('_'): self.set_icon(ima.icon('private1')) else: self.set_icon(ima.icon('method')) else: self.set_icon(ima.icon('function')) self.setToolTip(0, _("Function defined at line %s" ) % str(self.line)) class CommentItem(TreeItem): def __init__(self, name, line, parent, preceding): name = name.lstrip("# ") TreeItem.__init__(self, name, line, parent, preceding) def setup(self): self.set_icon(ima.icon('blockcomment')) font = self.font(0) font.setItalic(True) self.setFont(0, font) self.setToolTip(0, _("Line %s") % str(self.line)) class CellItem(TreeItem): def __init__(self, name, line, parent, preceding): name = name.lstrip("#% ") if name.startswith(""): name = name[10:].lstrip() elif name.startswith("In["): name = name[2:] if name.endswith("]:"): name = name[:-1] name = name.strip() TreeItem.__init__(self, name, line, parent, preceding) def setup(self): self.set_icon(ima.icon('cell')) font = self.font(0) font.setItalic(True) self.setFont(0, font) self.setToolTip(0, _("Cell starts at line %s") % str(self.line)) def get_item_children(item): children = [item.child(index) for index in range(item.childCount())] for child in children[:]: others = get_item_children(child) if others is not None: children += others return sorted(children, key=lambda child: child.line) def item_at_line(root_item, line): previous_item = root_item for item in get_item_children(root_item): if item.line > line: return previous_item previous_item = item def remove_from_tree_cache(tree_cache, line=None, item=None): if line is None: for line, (_it, _level, _debug) in list(tree_cache.items()): if _it is item: break item, _level, debug = tree_cache.pop(line) try: for child in [item.child(_i) for _i in range(item.childCount())]: remove_from_tree_cache(tree_cache, item=child) item.parent().removeChild(item) except RuntimeError: # Item has already been deleted #XXX: remove this debug-related fragment of code print("unable to remove tree item: ", debug, file=STDOUT) class OutlineExplorerTreeWidget(OneColumnTree): def __init__(self, parent, show_fullpath=False, fullpath_sorting=True, show_all_files=True, show_comments=True): self.show_fullpath = show_fullpath self.fullpath_sorting = fullpath_sorting self.show_all_files = show_all_files self.show_comments = show_comments OneColumnTree.__init__(self, parent) self.freeze = False # Freezing widget to avoid any unwanted update self.editor_items = {} self.editor_tree_cache = {} self.editor_ids = {} self.current_editor = None title = _("Outline") self.set_title(title) self.setWindowTitle(title) self.setUniformRowHeights(True) def get_actions_from_items(self, items): """Reimplemented OneColumnTree method""" fromcursor_act = create_action(self, text=_('Go to cursor position'), icon=ima.icon('fromcursor'), triggered=self.go_to_cursor_position) fullpath_act = create_action(self, text=_( 'Show absolute path'), toggled=self.toggle_fullpath_mode) fullpath_act.setChecked(self.show_fullpath) allfiles_act = create_action(self, text=_( 'Show all files'), toggled=self.toggle_show_all_files) allfiles_act.setChecked(self.show_all_files) comment_act = create_action(self, text=_('Show special comments'), toggled=self.toggle_show_comments) comment_act.setChecked(self.show_comments) actions = [fullpath_act, allfiles_act, comment_act, fromcursor_act] return actions @Slot(bool) def toggle_fullpath_mode(self, state): self.show_fullpath = state self.setTextElideMode(Qt.ElideMiddle if state else Qt.ElideRight) for index in range(self.topLevelItemCount()): self.topLevelItem(index).set_text(fullpath=self.show_fullpath) def __hide_or_show_root_items(self, item): """ show_all_files option is disabled: hide all root items except *item* show_all_files option is enabled: do nothing """ for _it in self.get_top_level_items(): _it.setHidden(_it is not item and not self.show_all_files) @Slot(bool) def toggle_show_all_files(self, state): self.show_all_files = state if self.current_editor is not None: editor_id = self.editor_ids[self.current_editor] item = self.editor_items[editor_id] self.__hide_or_show_root_items(item) @Slot(bool) def toggle_show_comments(self, state): self.show_comments = state self.update_all() def set_fullpath_sorting(self, state): self.fullpath_sorting = state self.__sort_toplevel_items() @Slot() def go_to_cursor_position(self): if self.current_editor is not None: line = self.current_editor.get_cursor_line_number() editor_id = self.editor_ids[self.current_editor] root_item = self.editor_items[editor_id] item = item_at_line(root_item, line) self.setCurrentItem(item) self.scrollToItem(item) def clear(self): """Reimplemented Qt method""" self.set_title('') OneColumnTree.clear(self) def set_current_editor(self, editor, fname, update): """Bind editor instance""" editor_id = editor.get_document_id() if editor_id in list(self.editor_ids.values()): item = self.editor_items[editor_id] if not self.freeze: self.scrollToItem(item) self.root_item_selected(item) self.__hide_or_show_root_items(item) if update: self.save_expanded_state() tree_cache = self.editor_tree_cache[editor_id] self.populate_branch(editor, item, tree_cache) self.restore_expanded_state() else: # import time # t0 = time.time() root_item = FileRootItem(fname, self) root_item.set_text(fullpath=self.show_fullpath) tree_cache = self.populate_branch(editor, root_item) self.__sort_toplevel_items() self.__hide_or_show_root_items(root_item) self.root_item_selected(root_item) # print >>STDOUT, "Elapsed time: %d ms" % round((time.time()-t0)*1000) self.editor_items[editor_id] = root_item self.editor_tree_cache[editor_id] = tree_cache self.resizeColumnToContents(0) if editor not in self.editor_ids: self.editor_ids[editor] = editor_id self.current_editor = editor def file_renamed(self, editor, new_filename): """File was renamed, updating outline explorer tree""" editor_id = editor.get_document_id() if editor_id in list(self.editor_ids.values()): root_item = self.editor_items[editor_id] root_item.set_path(new_filename, fullpath=self.show_fullpath) self.__sort_toplevel_items() def update_all(self): self.save_expanded_state() for editor, editor_id in list(self.editor_ids.items()): item = self.editor_items[editor_id] tree_cache = self.editor_tree_cache[editor_id] self.populate_branch(editor, item, tree_cache) self.restore_expanded_state() def remove_editor(self, editor): if editor in self.editor_ids: if self.current_editor is editor: self.current_editor = None editor_id = self.editor_ids.pop(editor) if editor_id not in list(self.editor_ids.values()): root_item = self.editor_items.pop(editor_id) self.editor_tree_cache.pop(editor_id) try: self.takeTopLevelItem(self.indexOfTopLevelItem(root_item)) except RuntimeError: # item has already been removed pass def __sort_toplevel_items(self): if self.fullpath_sorting: sort_func = lambda item: osp.dirname(item.path.lower()) else: sort_func = lambda item: osp.basename(item.path.lower()) self.sort_top_level_items(key=sort_func) def populate_branch(self, editor, root_item, tree_cache=None): if tree_cache is None: tree_cache = {} # Removing cached items for which line is > total line nb for _l in list(tree_cache.keys()): if _l >= editor.get_line_count(): # Checking if key is still in tree cache in case one of its # ancestors was deleted in the meantime (deleting all children): if _l in tree_cache: remove_from_tree_cache(tree_cache, line=_l) ancestors = [(root_item, 0)] previous_item = None previous_level = None oe_data = editor.highlighter.get_outlineexplorer_data() editor.has_cell_separators = oe_data.get('found_cell_separators', False) for block_nb in range(editor.get_line_count()): line_nb = block_nb+1 data = oe_data.get(block_nb) if data is None: level = None else: level = data.fold_level citem, clevel, _d = tree_cache.get(line_nb, (None, None, "")) # Skip iteration if line is not the first line of a foldable block if level is None: if citem is not None: remove_from_tree_cache(tree_cache, line=line_nb) continue # Searching for class/function statements not_class_nor_function = data.is_not_class_nor_function() if not not_class_nor_function: class_name = data.get_class_name() if class_name is None: func_name = data.get_function_name() if func_name is None: if citem is not None: remove_from_tree_cache(tree_cache, line=line_nb) continue if previous_level is not None: if level == previous_level: pass elif level > previous_level+4: # Invalid indentation continue elif level > previous_level: ancestors.append((previous_item, previous_level)) else: while len(ancestors) > 1 and level <= previous_level: ancestors.pop(-1) _item, previous_level = ancestors[-1] parent, _level = ancestors[-1] if citem is not None: cname = to_text_string(citem.text(0)) preceding = root_item if previous_item is None else previous_item if not_class_nor_function: if data.is_comment() and not self.show_comments: if citem is not None: remove_from_tree_cache(tree_cache, line=line_nb) continue if citem is not None: if data.text == cname and level == clevel: previous_level = clevel previous_item = citem continue else: remove_from_tree_cache(tree_cache, line=line_nb) if data.is_comment(): if data.def_type == data.CELL: item = CellItem(data.text, line_nb, parent, preceding) else: item = CommentItem( data.text, line_nb, parent, preceding) else: item = TreeItem(data.text, line_nb, parent, preceding) elif class_name is not None: if citem is not None: if class_name == cname and level == clevel: previous_level = clevel previous_item = citem continue else: remove_from_tree_cache(tree_cache, line=line_nb) item = ClassItem(class_name, line_nb, parent, preceding) else: if citem is not None: if func_name == cname and level == clevel: previous_level = clevel previous_item = citem continue else: remove_from_tree_cache(tree_cache, line=line_nb) item = FunctionItem(func_name, line_nb, parent, preceding) item.setup() debug = "%s -- %s/%s" % (str(item.line).rjust(6), to_text_string(item.parent().text(0)), to_text_string(item.text(0))) tree_cache[line_nb] = (item, level, debug) previous_level = level previous_item = item return tree_cache def root_item_selected(self, item): """Root item has been selected: expanding it and collapsing others""" for index in range(self.topLevelItemCount()): root_item = self.topLevelItem(index) if root_item is item: self.expandItem(root_item) else: self.collapseItem(root_item) def restore(self): """Reimplemented OneColumnTree method""" if self.current_editor is not None: self.collapseAll() editor_id = self.editor_ids[self.current_editor] self.root_item_selected(self.editor_items[editor_id]) def get_root_item(self, item): root_item = item while isinstance(root_item.parent(), QTreeWidgetItem): root_item = root_item.parent() return root_item def activated(self, item): """Double-click event""" line = 0 if isinstance(item, TreeItem): line = item.line root_item = self.get_root_item(item) self.freeze = True if line: self.parent().edit_goto.emit(root_item.path, line, item.text(0)) else: self.parent().edit.emit(root_item.path) self.freeze = False parent = self.current_editor.parent() for editor_id, i_item in list(self.editor_items.items()): if i_item is root_item: for editor, _id in list(self.editor_ids.items()): if _id == editor_id and editor.parent() is parent: self.current_editor = editor break break def clicked(self, item): """Click event""" if isinstance(item, FileRootItem): self.root_item_selected(item) self.activated(item) class OutlineExplorerWidget(QWidget): """Class browser""" edit_goto = Signal(str, int, str) edit = Signal(str) outlineexplorer_is_visible = Signal() def __init__(self, parent=None, show_fullpath=True, fullpath_sorting=True, show_all_files=True, show_comments=True): QWidget.__init__(self, parent) self.treewidget = OutlineExplorerTreeWidget(self, show_fullpath=show_fullpath, fullpath_sorting=fullpath_sorting, show_all_files=show_all_files, show_comments=show_comments) self.visibility_action = create_action(self, _("Show/hide outline explorer"), icon='outline_explorer_vis.png', toggled=self.toggle_visibility) self.visibility_action.setChecked(True) btn_layout = QHBoxLayout() btn_layout.setAlignment(Qt.AlignLeft) for btn in self.setup_buttons(): btn_layout.addWidget(btn) layout = create_plugin_layout(btn_layout, self.treewidget) self.setLayout(layout) @Slot(bool) def toggle_visibility(self, state): self.setVisible(state) current_editor = self.treewidget.current_editor if current_editor is not None: current_editor.clearFocus() current_editor.setFocus() if state: self.outlineexplorer_is_visible.emit() def setup_buttons(self): fromcursor_btn = create_toolbutton(self, icon=ima.icon('fromcursor'), tip=_('Go to cursor position'), triggered=self.treewidget.go_to_cursor_position) collapse_btn = create_toolbutton(self) collapse_btn.setDefaultAction(self.treewidget.collapse_selection_action) expand_btn = create_toolbutton(self) expand_btn.setDefaultAction(self.treewidget.expand_selection_action) restore_btn = create_toolbutton(self) restore_btn.setDefaultAction(self.treewidget.restore_action) return (fromcursor_btn, collapse_btn, expand_btn, restore_btn) def set_current_editor(self, editor, fname, update, clear): if clear: self.remove_editor(editor) if editor.highlighter is not None: self.treewidget.set_current_editor(editor, fname, update) def remove_editor(self, editor): self.treewidget.remove_editor(editor) def get_options(self): """ Return outline explorer options except for fullpath sorting option which is more global """ return dict(show_fullpath=self.treewidget.show_fullpath, show_all_files=self.treewidget.show_all_files, show_comments=self.treewidget.show_comments, expanded_state=self.treewidget.get_expanded_state(), scrollbar_position=self.treewidget.get_scrollbar_position(), visibility=self.isVisible()) def update(self): self.treewidget.update_all() def set_fullpath_sorting(self, state): self.treewidget.set_fullpath_sorting(state) def file_renamed(self, editor, new_filename): self.treewidget.file_renamed(editor, new_filename) spyder-3.2.6/spyder/widgets/sourcecode/0000775000175000017500000000000013225025007020725 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/widgets/sourcecode/codeeditor.py0000664000175000017500000042044513224740762023444 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Editor widget based on QtGui.QPlainTextEdit """ # TODO: Try to separate this module from spyder to create a self # consistent editor module (Qt source code and shell widgets library) # %% This line is for cell execution testing # pylint: disable=C0103 # pylint: disable=R0903 # pylint: disable=R0911 # pylint: disable=R0201 # Standard library imports from __future__ import division from unicodedata import category import os.path as osp import re import sre_constants import sys import time # Third party imports from qtpy import is_pyqt46, QT_VERSION from qtpy.compat import to_qvariant from qtpy.QtCore import QRect, QRegExp, QSize, Qt, QTimer, Signal, Slot from qtpy.QtGui import (QBrush, QColor, QCursor, QFont, QIntValidator, QKeySequence, QPaintEvent, QPainter, QTextBlockUserData, QTextCharFormat, QTextCursor, QTextDocument, QTextFormat, QTextOption) from qtpy.QtPrintSupport import QPrinter from qtpy.QtWidgets import (QApplication, QDialog, QDialogButtonBox, QGridLayout, QHBoxLayout, QInputDialog, QLabel, QLineEdit, QMenu, QMessageBox, QSplitter, QTextEdit, QToolTip, QVBoxLayout, QWidget) # %% This line is for cell execution testing # Local imports from spyder.config.base import get_conf_path, _, DEBUG from spyder.config.gui import config_shortcut, get_shortcut from spyder.config.main import (CONF, RUN_CELL_SHORTCUT, RUN_CELL_AND_ADVANCE_SHORTCUT) from spyder.py3compat import to_text_string from spyder.utils import icon_manager as ima from spyder.utils import syntaxhighlighters as sh from spyder.utils import encoding, sourcecode from spyder.utils.dochelpers import getobj from spyder.utils.programs import check_version from spyder.utils.qthelpers import add_actions, create_action, mimedata2url from spyder.utils.sourcecode import ALL_LANGUAGES, CELL_LANGUAGES from spyder.widgets.editortools import PythonCFM from spyder.widgets.sourcecode.base import TextEditBaseWidget from spyder.widgets.sourcecode.kill_ring import QtKillRing try: import nbformat as nbformat from nbconvert import PythonExporter as nbexporter except: nbformat = None # analysis:ignore # %% This line is for cell execution testing # For debugging purpose: LOG_FILENAME = get_conf_path('codeeditor.log') DEBUG_EDITOR = DEBUG >= 3 QT55_VERSION = check_version(QT_VERSION, "5.5", ">=") def is_letter_or_number(char): """ Returns whether the specified unicode character is a letter or a number. """ cat = category(char) return cat.startswith('L') or cat.startswith('N') # ============================================================================= # Go to line dialog box # ============================================================================= class GoToLineDialog(QDialog): def __init__(self, editor): QDialog.__init__(self, editor, Qt.WindowTitleHint | Qt.WindowCloseButtonHint) # Destroying the C++ object right after closing the dialog box, # otherwise it may be garbage-collected in another QThread # (e.g. the editor's analysis thread in Spyder), thus leading to # a segmentation fault on UNIX or an application crash on Windows self.setAttribute(Qt.WA_DeleteOnClose) self.lineno = None self.editor = editor self.setWindowTitle(_("Editor")) self.setModal(True) label = QLabel(_("Go to line:")) self.lineedit = QLineEdit() validator = QIntValidator(self.lineedit) validator.setRange(1, editor.get_line_count()) self.lineedit.setValidator(validator) self.lineedit.textChanged.connect(self.text_has_changed) cl_label = QLabel(_("Current line:")) cl_label_v = QLabel("%d" % editor.get_cursor_line_number()) last_label = QLabel(_("Line count:")) last_label_v = QLabel("%d" % editor.get_line_count()) glayout = QGridLayout() glayout.addWidget(label, 0, 0, Qt.AlignVCenter|Qt.AlignRight) glayout.addWidget(self.lineedit, 0, 1, Qt.AlignVCenter) glayout.addWidget(cl_label, 1, 0, Qt.AlignVCenter|Qt.AlignRight) glayout.addWidget(cl_label_v, 1, 1, Qt.AlignVCenter) glayout.addWidget(last_label, 2, 0, Qt.AlignVCenter|Qt.AlignRight) glayout.addWidget(last_label_v, 2, 1, Qt.AlignVCenter) bbox = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel, Qt.Vertical, self) bbox.accepted.connect(self.accept) bbox.rejected.connect(self.reject) btnlayout = QVBoxLayout() btnlayout.addWidget(bbox) btnlayout.addStretch(1) ok_button = bbox.button(QDialogButtonBox.Ok) ok_button.setEnabled(False) self.lineedit.textChanged.connect( lambda text: ok_button.setEnabled(len(text) > 0)) layout = QHBoxLayout() layout.addLayout(glayout) layout.addLayout(btnlayout) self.setLayout(layout) self.lineedit.setFocus() def text_has_changed(self, text): """Line edit's text has changed""" text = to_text_string(text) if text: self.lineno = int(text) else: self.lineno = None def get_line_number(self): """Return line number""" # It is import to avoid accessing Qt C++ object as it has probably # already been destroyed, due to the Qt.WA_DeleteOnClose attribute return self.lineno #=============================================================================== # Viewport widgets #=============================================================================== class LineNumberArea(QWidget): """Line number area (on the left side of the text editor widget)""" def __init__(self, editor): QWidget.__init__(self, editor) self.code_editor = editor self.setMouseTracking(True) def sizeHint(self): """Override Qt method""" return QSize(self.code_editor.compute_linenumberarea_width(), 0) def paintEvent(self, event): """Override Qt method""" self.code_editor.linenumberarea_paint_event(event) def mouseMoveEvent(self, event): """Override Qt method""" self.code_editor.linenumberarea_mousemove_event(event) def mouseDoubleClickEvent(self, event): """Override Qt method""" self.code_editor.linenumberarea_mousedoubleclick_event(event) def mousePressEvent(self, event): """Override Qt method""" self.code_editor.linenumberarea_mousepress_event(event) def mouseReleaseEvent(self, event): """Override Qt method""" self.code_editor.linenumberarea_mouserelease_event(event) def wheelEvent(self, event): """Override Qt method""" self.code_editor.wheelEvent(event) class ScrollFlagArea(QWidget): """Source code editor's scroll flag area""" WIDTH = 12 FLAGS_DX = 4 FLAGS_DY = 2 def __init__(self, editor): QWidget.__init__(self, editor) self.setAttribute(Qt.WA_OpaquePaintEvent) self.code_editor = editor editor.verticalScrollBar().valueChanged.connect( lambda value: self.repaint()) def sizeHint(self): """Override Qt method""" return QSize(self.WIDTH, 0) def paintEvent(self, event): """Override Qt method""" self.code_editor.scrollflagarea_paint_event(event) def mousePressEvent(self, event): """Override Qt method""" vsb = self.code_editor.verticalScrollBar() value = self.position_to_value(event.pos().y()-1) vsb.setValue(value-.5*vsb.pageStep()) def get_scale_factor(self, slider=False): """Return scrollbar's scale factor: ratio between pixel span height and value span height""" delta = 0 if slider else 2 vsb = self.code_editor.verticalScrollBar() position_height = vsb.height()-delta-1 value_height = vsb.maximum()-vsb.minimum()+vsb.pageStep() return float(position_height)/value_height def value_to_position(self, y, slider=False): """Convert value to position""" offset = 0 if slider else 1 vsb = self.code_editor.verticalScrollBar() return (y-vsb.minimum())*self.get_scale_factor(slider)+offset def position_to_value(self, y, slider=False): """Convert position to value""" offset = 0 if slider else 1 vsb = self.code_editor.verticalScrollBar() return vsb.minimum()+max([0, (y-offset)/self.get_scale_factor(slider)]) def make_flag_qrect(self, position): """Make flag QRect""" return QRect(self.FLAGS_DX/2, position-self.FLAGS_DY/2, self.WIDTH-self.FLAGS_DX, self.FLAGS_DY) def make_slider_range(self, value): """Make slider range QRect""" vsb = self.code_editor.verticalScrollBar() pos1 = self.value_to_position(value, slider=True) pos2 = self.value_to_position(value + vsb.pageStep(), slider=True) return QRect(1, pos1, self.WIDTH-2, pos2-pos1+1) def wheelEvent(self, event): """Override Qt method""" self.code_editor.wheelEvent(event) class EdgeLine(QWidget): """Source code editor's edge line (default: 79 columns, PEP8)""" def __init__(self, editor): QWidget.__init__(self, editor) self.code_editor = editor self.column = 79 self.setAttribute(Qt.WA_TransparentForMouseEvents) def paintEvent(self, event): """Override Qt method""" painter = QPainter(self) color = QColor(Qt.darkGray) color.setAlphaF(.5) painter.fillRect(event.rect(), color) #=============================================================================== # CodeEditor widget #=============================================================================== class BlockUserData(QTextBlockUserData): def __init__(self, editor): QTextBlockUserData.__init__(self) self.editor = editor self.breakpoint = False self.breakpoint_condition = None self.code_analysis = [] self.todo = '' self.editor.blockuserdata_list.append(self) def is_empty(self): return not self.breakpoint and not self.code_analysis and not self.todo def __del__(self): bud_list = self.editor.blockuserdata_list bud_list.pop(bud_list.index(self)) def set_scrollflagarea_painter(painter, light_color): """Set scroll flag area painter pen and brush colors""" painter.setPen(QColor(light_color).darker(120)) painter.setBrush(QBrush(QColor(light_color))) def get_file_language(filename, text=None): """Get file language from filename""" ext = osp.splitext(filename)[1] if ext.startswith('.'): ext = ext[1:] # file extension with leading dot language = ext if not ext: if text is None: text, _enc = encoding.read(filename) for line in text.splitlines(): if not line.strip(): continue if line.startswith('#!'): shebang = line[2:] if 'python' in shebang: language = 'python' else: break return language class CodeEditor(TextEditBaseWidget): """Source Code Editor Widget based exclusively on Qt""" LANGUAGES = {'Python': (sh.PythonSH, '#', PythonCFM), 'Cython': (sh.CythonSH, '#', PythonCFM), 'Fortran77': (sh.Fortran77SH, 'c', None), 'Fortran': (sh.FortranSH, '!', None), 'Idl': (sh.IdlSH, ';', None), 'Diff': (sh.DiffSH, '', None), 'GetText': (sh.GetTextSH, '#', None), 'Nsis': (sh.NsisSH, '#', None), 'Html': (sh.HtmlSH, '', None), 'Yaml': (sh.YamlSH, '#', None), 'Cpp': (sh.CppSH, '//', None), 'OpenCL': (sh.OpenCLSH, '//', None), 'Enaml': (sh.EnamlSH, '#', PythonCFM), 'Markdown': (sh.MarkdownSH, '#', None), } TAB_ALWAYS_INDENTS = ('py', 'pyw', 'python', 'c', 'cpp', 'cl', 'h') # Custom signal to be emitted upon completion of the editor's paintEvent painted = Signal(QPaintEvent) # To have these attrs when early viewportEvent's are triggered edge_line = None linenumberarea = None breakpoints_changed = Signal() get_completions = Signal(bool) go_to_definition = Signal(int) sig_show_object_info = Signal(int) run_selection = Signal() run_cell_and_advance = Signal() run_cell = Signal() re_run_last_cell = Signal() go_to_definition_regex = Signal(int) sig_cursor_position_changed = Signal(int, int) focus_changed = Signal() sig_new_file = Signal(str) def __init__(self, parent=None): TextEditBaseWidget.__init__(self, parent) self.setFocusPolicy(Qt.StrongFocus) # We use these object names to set the right background # color when changing color schemes or creating new # Editor windows. This seems to be a Qt bug. # Fixes Issue 2028 if sys.platform == 'darwin': plugin_name = repr(parent) if 'editor' in plugin_name.lower(): self.setObjectName('editor') elif 'help' in plugin_name.lower(): self.setObjectName('help') elif 'historylog' in plugin_name.lower(): self.setObjectName('historylog') elif 'configdialog' in plugin_name.lower(): self.setObjectName('configdialog') # Caret (text cursor) self.setCursorWidth( CONF.get('main', 'cursor/width') ) # 79-col edge line self.edge_line_enabled = True self.edge_line = EdgeLine(self) # Blanks enabled self.blanks_enabled = False # Markers self.markers_margin = True self.markers_margin_width = 15 self.error_pixmap = ima.icon('error').pixmap(QSize(14, 14)) self.warning_pixmap = ima.icon('warning').pixmap(QSize(14, 14)) self.todo_pixmap = ima.icon('todo').pixmap(QSize(14, 14)) self.bp_pixmap = ima.icon('breakpoint_big').pixmap(QSize(14, 14)) self.bpc_pixmap = ima.icon('breakpoint_cond_big').pixmap(QSize(14, 14)) # Line number area management self.linenumbers_margin = True self.linenumberarea_enabled = None self.linenumberarea = LineNumberArea(self) self.blockCountChanged.connect(self.update_linenumberarea_width) self.updateRequest.connect(self.update_linenumberarea) self.linenumberarea_pressed = -1 self.linenumberarea_released = -1 # Colors to be defined in _apply_highlighter_color_scheme() # Currentcell color and current line color are defined in base.py self.occurrence_color = None self.ctrl_click_color = None self.sideareas_color = None self.matched_p_color = None self.unmatched_p_color = None self.normal_color = None self.comment_color = None self.linenumbers_color = QColor(Qt.darkGray) # --- Syntax highlight entrypoint --- # # - if set, self.highlighter is responsible for # - coloring raw text data inside editor on load # - coloring text data when editor is cloned # - updating document highlight on line edits # - providing color palette (scheme) for the editor # - providing data for Outliner # - self.highlighter is not responsible for # - background highlight for current line # - background highlight for search / current line occurrences self.highlighter_class = sh.TextSH self.highlighter = None ccs = 'Spyder' if ccs not in sh.COLOR_SCHEME_NAMES: ccs = sh.COLOR_SCHEME_NAMES[0] self.color_scheme = ccs self.highlight_current_line_enabled = False # Scrollbar flag area self.scrollflagarea_enabled = None self.scrollflagarea = ScrollFlagArea(self) self.scrollflagarea.hide() self.warning_color = "#FFAD07" self.error_color = "#EA2B0E" self.todo_color = "#B4D4F3" self.breakpoint_color = "#30E62E" self.update_linenumberarea_width() self.document_id = id(self) # Indicate occurrences of the selected word self.cursorPositionChanged.connect(self.__cursor_position_changed) self.__find_first_pos = None self.__find_flags = None self.supported_language = False self.supported_cell_language = False self.classfunc_match = None self.comment_string = None self._kill_ring = QtKillRing(self) # Block user data self.blockuserdata_list = [] # Update breakpoints if the number of lines in the file changes self.blockCountChanged.connect(self.update_breakpoints) # Highlight using Pygments highlighter timer # --------------------------------------------------------------------- # For files that use the PygmentsSH we parse the full file inside # the highlighter in order to generate the correct coloring. self.timer_syntax_highlight = QTimer(self) self.timer_syntax_highlight.setSingleShot(True) # We wait 300 ms to trigger a new coloring as this value is a good # proxy for estimating when an user has stopped typing self.timer_syntax_highlight.setInterval(300) self.timer_syntax_highlight.timeout.connect( self.run_pygments_highlighter) # Mark occurrences timer self.occurrence_highlighting = None self.occurrence_timer = QTimer(self) self.occurrence_timer.setSingleShot(True) self.occurrence_timer.setInterval(1500) self.occurrence_timer.timeout.connect(self.__mark_occurrences) self.occurrences = [] self.occurrence_color = QColor(Qt.yellow).lighter(160) # Mark found results self.textChanged.connect(self.__text_has_changed) self.found_results = [] self.found_results_color = QColor(Qt.magenta).lighter(180) # Context menu self.gotodef_action = None self.setup_context_menu() # Tab key behavior self.tab_indents = None self.tab_mode = True # see CodeEditor.set_tab_mode # Intelligent backspace mode self.intelligent_backspace = True self.go_to_definition_enabled = False self.close_parentheses_enabled = True self.close_quotes_enabled = False self.add_colons_enabled = True self.auto_unindent_enabled = True # Mouse tracking self.setMouseTracking(True) self.__cursor_changed = False self.ctrl_click_color = QColor(Qt.blue) # Breakpoints self.breakpoints = self.get_breakpoints() # Keyboard shortcuts self.shortcuts = self.create_shortcuts() # Code editor self.__visible_blocks = [] # Visible blocks, update with repaint self.painted.connect(self._draw_editor_cell_divider) self.verticalScrollBar().valueChanged.connect( lambda value: self.rehighlight_cells()) def create_shortcuts(self): codecomp = config_shortcut(self.do_completion, context='Editor', name='Code Completion', parent=self) duplicate_line = config_shortcut(self.duplicate_line, context='Editor', name='Duplicate line', parent=self) copyline = config_shortcut(self.copy_line, context='Editor', name='Copy line', parent=self) deleteline = config_shortcut(self.delete_line, context='Editor', name='Delete line', parent=self) movelineup = config_shortcut(self.move_line_up, context='Editor', name='Move line up', parent=self) movelinedown = config_shortcut(self.move_line_down, context='Editor', name='Move line down', parent=self) gotodef = config_shortcut(self.do_go_to_definition, context='Editor', name='Go to definition', parent=self) toggle_comment = config_shortcut(self.toggle_comment, context='Editor', name='Toggle comment', parent=self) blockcomment = config_shortcut(self.blockcomment, context='Editor', name='Blockcomment', parent=self) unblockcomment = config_shortcut(self.unblockcomment, context='Editor', name='Unblockcomment', parent=self) transform_uppercase = config_shortcut(self.transform_to_uppercase, context='Editor', name='Transform to uppercase', parent=self) transform_lowercase = config_shortcut(self.transform_to_lowercase, context='Editor', name='Transform to lowercase', parent=self) indent = config_shortcut(lambda: self.indent(force=True), context='Editor', name='Indent', parent=self) unindent = config_shortcut(lambda: self.unindent(force=True), context='Editor', name='Unindent', parent=self) def cb_maker(attr): """Make a callback for cursor move event type, (e.g. "Start") """ def cursor_move_event(): cursor = self.textCursor() move_type = getattr(QTextCursor, attr) cursor.movePosition(move_type) self.setTextCursor(cursor) return cursor_move_event line_start = config_shortcut(cb_maker('StartOfLine'), context='Editor', name='Start of line', parent=self) line_end = config_shortcut(cb_maker('EndOfLine'), context='Editor', name='End of line', parent=self) prev_line = config_shortcut(cb_maker('Up'), context='Editor', name='Previous line', parent=self) next_line = config_shortcut(cb_maker('Down'), context='Editor', name='Next line', parent=self) prev_char = config_shortcut(cb_maker('Left'), context='Editor', name='Previous char', parent=self) next_char = config_shortcut(cb_maker('Right'), context='Editor', name='Next char', parent=self) prev_word = config_shortcut(cb_maker('StartOfWord'), context='Editor', name='Previous word', parent=self) next_word = config_shortcut(cb_maker('EndOfWord'), context='Editor', name='Next word', parent=self) kill_line_end = config_shortcut(self.kill_line_end, context='Editor', name='Kill to line end', parent=self) kill_line_start = config_shortcut(self.kill_line_start, context='Editor', name='Kill to line start', parent=self) yank = config_shortcut(self._kill_ring.yank, context='Editor', name='Yank', parent=self) kill_ring_rotate = config_shortcut(self._kill_ring.rotate, context='Editor', name='Rotate kill ring', parent=self) kill_prev_word = config_shortcut(self.kill_prev_word, context='Editor', name='Kill previous word', parent=self) kill_next_word = config_shortcut(self.kill_next_word, context='Editor', name='Kill next word', parent=self) start_doc = config_shortcut(cb_maker('Start'), context='Editor', name='Start of Document', parent=self) end_doc = config_shortcut(cb_maker('End'), context='Editor', name='End of document', parent=self) undo = config_shortcut(self.undo, context='Editor', name='undo', parent=self) redo = config_shortcut(self.redo, context='Editor', name='redo', parent=self) cut = config_shortcut(self.cut, context='Editor', name='cut', parent=self) copy = config_shortcut(self.copy, context='Editor', name='copy', parent=self) paste = config_shortcut(self.paste, context='Editor', name='paste', parent=self) delete = config_shortcut(self.delete, context='Editor', name='delete', parent=self) select_all = config_shortcut(self.selectAll, context='Editor', name='Select All', parent=self) array_inline = config_shortcut(lambda: self.enter_array_inline(), context='array_builder', name='enter array inline', parent=self) array_table = config_shortcut(lambda: self.enter_array_table(), context='array_builder', name='enter array table', parent=self) return [codecomp, duplicate_line, copyline, deleteline, movelineup, movelinedown, gotodef, toggle_comment, blockcomment, unblockcomment, transform_uppercase, transform_lowercase, line_start, line_end, prev_line, next_line, prev_char, next_char, prev_word, next_word, kill_line_end, kill_line_start, yank, kill_ring_rotate, kill_prev_word, kill_next_word, start_doc, end_doc, undo, redo, cut, copy, paste, delete, select_all, array_inline, array_table, indent, unindent] def get_shortcut_data(self): """ Returns shortcut data, a list of tuples (shortcut, text, default) shortcut (QShortcut or QAction instance) text (string): action/shortcut description default (string): default key sequence """ return [sc.data for sc in self.shortcuts] def closeEvent(self, event): TextEditBaseWidget.closeEvent(self, event) if is_pyqt46: self.destroyed.emit() def get_document_id(self): return self.document_id def set_as_clone(self, editor): """Set as clone editor""" self.setDocument(editor.document()) self.document_id = editor.get_document_id() self.highlighter = editor.highlighter self.eol_chars = editor.eol_chars self._apply_highlighter_color_scheme() #-----Widget setup and options def toggle_wrap_mode(self, enable): """Enable/disable wrap mode""" self.set_wrap_mode('word' if enable else None) def setup_editor(self, linenumbers=True, language=None, markers=False, font=None, color_scheme=None, wrap=False, tab_mode=True, intelligent_backspace=True, highlight_current_line=True, highlight_current_cell=True, occurrence_highlighting=True, scrollflagarea=True, edge_line=True, edge_line_column=79, codecompletion_auto=False, codecompletion_case=True, codecompletion_enter=False, show_blanks=False, calltips=None, go_to_definition=False, close_parentheses=True, close_quotes=False, add_colons=True, auto_unindent=True, indent_chars=" "*4, tab_stop_width_spaces=4, cloned_from=None, filename=None, occurrence_timeout=1500): # Code completion and calltips self.set_codecompletion_auto(codecompletion_auto) self.set_codecompletion_case(codecompletion_case) self.set_codecompletion_enter(codecompletion_enter) self.set_calltips(calltips) self.set_go_to_definition_enabled(go_to_definition) self.set_close_parentheses_enabled(close_parentheses) self.set_close_quotes_enabled(close_quotes) self.set_add_colons_enabled(add_colons) self.set_auto_unindent_enabled(auto_unindent) self.set_indent_chars(indent_chars) self.set_tab_stop_width_spaces(tab_stop_width_spaces) # Scrollbar flag area self.set_scrollflagarea_enabled(scrollflagarea) # Edge line self.set_edge_line_enabled(edge_line) self.set_edge_line_column(edge_line_column) # Blanks self.set_blanks_enabled(show_blanks) # Line number area if cloned_from: self.setFont(font) # this is required for line numbers area self.setup_margins(linenumbers, markers) # Lexer self.set_language(language, filename) # Highlight current cell self.set_highlight_current_cell(highlight_current_cell) # Highlight current line self.set_highlight_current_line(highlight_current_line) # Occurrence highlighting self.set_occurrence_highlighting(occurrence_highlighting) self.set_occurrence_timeout(occurrence_timeout) # Tab always indents (even when cursor is not at the begin of line) self.set_tab_mode(tab_mode) # Intelligent backspace self.toggle_intelligent_backspace(intelligent_backspace) if cloned_from is not None: self.set_as_clone(cloned_from) self.update_linenumberarea_width() elif font is not None: self.set_font(font, color_scheme) elif color_scheme is not None: self.set_color_scheme(color_scheme) self.toggle_wrap_mode(wrap) def set_tab_mode(self, enable): """ enabled = tab always indent (otherwise tab indents only when cursor is at the beginning of a line) """ self.tab_mode = enable def toggle_intelligent_backspace(self, state): self.intelligent_backspace = state def set_go_to_definition_enabled(self, enable): """Enable/Disable go-to-definition feature, which is implemented in child class -> Editor widget""" self.go_to_definition_enabled = enable def set_close_parentheses_enabled(self, enable): """Enable/disable automatic parentheses insertion feature""" self.close_parentheses_enabled = enable def set_close_quotes_enabled(self, enable): """Enable/disable automatic quote insertion feature""" self.close_quotes_enabled = enable def set_add_colons_enabled(self, enable): """Enable/disable automatic colons insertion feature""" self.add_colons_enabled = enable def set_auto_unindent_enabled(self, enable): """Enable/disable automatic unindent after else/elif/finally/except""" self.auto_unindent_enabled = enable def set_occurrence_highlighting(self, enable): """Enable/disable occurrence highlighting""" self.occurrence_highlighting = enable if not enable: self.__clear_occurrences() def set_occurrence_timeout(self, timeout): """Set occurrence highlighting timeout (ms)""" self.occurrence_timer.setInterval(timeout) def set_highlight_current_line(self, enable): """Enable/disable current line highlighting""" self.highlight_current_line_enabled = enable if self.highlight_current_line_enabled: self.highlight_current_line() else: self.unhighlight_current_line() def set_highlight_current_cell(self, enable): """Enable/disable current line highlighting""" hl_cell_enable = enable and self.supported_cell_language self.highlight_current_cell_enabled = hl_cell_enable if self.highlight_current_cell_enabled: self.highlight_current_cell() else: self.unhighlight_current_cell() def set_language(self, language, filename=None): self.tab_indents = language in self.TAB_ALWAYS_INDENTS self.comment_string = '' sh_class = sh.TextSH if language is not None: for (key, value) in ALL_LANGUAGES.items(): if language.lower() in value: self.supported_language = True sh_class, comment_string, CFMatch = self.LANGUAGES[key] self.comment_string = comment_string if key in CELL_LANGUAGES: self.supported_cell_language = True self.cell_separators = CELL_LANGUAGES[key] if CFMatch is None: self.classfunc_match = None else: self.classfunc_match = CFMatch() break if filename is not None and not self.supported_language: sh_class = sh.guess_pygments_highlighter(filename) self.support_language = sh_class is not sh.TextSH self._set_highlighter(sh_class) def _set_highlighter(self, sh_class): self.highlighter_class = sh_class if self.highlighter is not None: # Removing old highlighter # TODO: test if leaving parent/document as is eats memory self.highlighter.setParent(None) self.highlighter.setDocument(None) self.highlighter = self.highlighter_class(self.document(), self.font(), self.color_scheme) self._apply_highlighter_color_scheme() def is_json(self): return (isinstance(self.highlighter, sh.PygmentsSH) and self.highlighter._lexer.name == 'JSON') def is_python(self): return self.highlighter_class is sh.PythonSH def is_cython(self): return self.highlighter_class is sh.CythonSH def is_enaml(self): return self.highlighter_class is sh.EnamlSH def is_python_like(self): return self.is_python() or self.is_cython() or self.is_enaml() def intelligent_tab(self): """Provide intelligent behavoir for Tab key press""" leading_text = self.get_text('sol', 'cursor') if not leading_text.strip() or leading_text.endswith('#'): # blank line or start of comment self.indent_or_replace() elif self.in_comment_or_string() and not leading_text.endswith(' '): # in a word in a comment self.do_completion() elif leading_text.endswith('import ') or leading_text[-1] == '.': # blank import or dot completion self.do_completion() elif (leading_text.split()[0] in ['from', 'import'] and not ';' in leading_text): # import line with a single statement # (prevents lines like: `import pdb; pdb.set_trace()`) self.do_completion() elif leading_text[-1] in '(,' or leading_text.endswith(', '): self.indent_or_replace() elif leading_text.endswith(' '): # if the line ends with a space, indent self.indent_or_replace() elif re.search(r"[^\d\W]\w*\Z", leading_text, re.UNICODE): # if the line ends with a non-whitespace character self.do_completion() else: self.indent_or_replace() def intelligent_backtab(self): """Provide intelligent behavoir for Shift+Tab key press""" leading_text = self.get_text('sol', 'cursor') if not leading_text.strip(): # blank line self.unindent() elif self.in_comment_or_string(): self.unindent() elif leading_text[-1] in '(,' or leading_text.endswith(', '): position = self.get_position('cursor') self.show_object_info(position) else: # if the line ends with any other character but comma self.unindent() def rehighlight(self): """ Rehighlight the whole document to rebuild outline explorer data and import statements data from scratch """ if self.highlighter is not None: self.highlighter.rehighlight() if self.highlight_current_cell_enabled: self.highlight_current_cell() else: self.unhighlight_current_cell() if self.highlight_current_line_enabled: self.highlight_current_line() else: self.unhighlight_current_line() def rehighlight_cells(self): """Rehighlight cells when moving the scrollbar""" if self.highlight_current_cell_enabled: self.highlight_current_cell() def setup_margins(self, linenumbers=True, markers=True): """ Setup margin settings (except font, now set in self.set_font) """ self.linenumbers_margin = linenumbers self.markers_margin = markers self.set_linenumberarea_enabled(linenumbers or markers) def remove_trailing_spaces(self): """Remove trailing spaces""" cursor = self.textCursor() cursor.beginEditBlock() cursor.movePosition(QTextCursor.Start) while True: cursor.movePosition(QTextCursor.EndOfBlock) text = to_text_string(cursor.block().text()) length = len(text)-len(text.rstrip()) if length > 0: cursor.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor, length) cursor.removeSelectedText() if cursor.atEnd(): break cursor.movePosition(QTextCursor.NextBlock) cursor.endEditBlock() def fix_indentation(self): """Replace tabs by spaces""" text_before = to_text_string(self.toPlainText()) text_after = sourcecode.fix_indentation(text_before) if text_before != text_after: self.setPlainText(text_after) self.document().setModified(True) def get_current_object(self): """Return current object (string) """ source_code = to_text_string(self.toPlainText()) offset = self.get_position('cursor') return sourcecode.get_primary_at(source_code, offset) @Slot() def delete(self): """Remove selected text""" if self.has_selected_text(): self.remove_selected_text() #------Find occurrences def __find_first(self, text): """Find first occurrence: scan whole document""" flags = QTextDocument.FindCaseSensitively|QTextDocument.FindWholeWords cursor = self.textCursor() # Scanning whole document cursor.movePosition(QTextCursor.Start) regexp = QRegExp(r"\b%s\b" % QRegExp.escape(text), Qt.CaseSensitive) cursor = self.document().find(regexp, cursor, flags) self.__find_first_pos = cursor.position() return cursor def __find_next(self, text, cursor): """Find next occurrence""" flags = QTextDocument.FindCaseSensitively|QTextDocument.FindWholeWords regexp = QRegExp(r"\b%s\b" % QRegExp.escape(text), Qt.CaseSensitive) cursor = self.document().find(regexp, cursor, flags) if cursor.position() != self.__find_first_pos: return cursor def __cursor_position_changed(self): """Cursor position has changed""" line, column = self.get_cursor_line_column() self.sig_cursor_position_changed.emit(line, column) if self.highlight_current_cell_enabled: self.highlight_current_cell() else: self.unhighlight_current_cell() if self.highlight_current_line_enabled: self.highlight_current_line() else: self.unhighlight_current_line() if self.occurrence_highlighting: self.occurrence_timer.stop() self.occurrence_timer.start() def __clear_occurrences(self): """Clear occurrence markers""" self.occurrences = [] self.clear_extra_selections('occurrences') self.scrollflagarea.update() def __highlight_selection(self, key, cursor, foreground_color=None, background_color=None, underline_color=None, underline_style=QTextCharFormat.SpellCheckUnderline, update=False): extra_selections = self.get_extra_selections(key) selection = QTextEdit.ExtraSelection() if foreground_color is not None: selection.format.setForeground(foreground_color) if background_color is not None: selection.format.setBackground(background_color) if underline_color is not None: selection.format.setProperty(QTextFormat.TextUnderlineStyle, to_qvariant(underline_style)) selection.format.setProperty(QTextFormat.TextUnderlineColor, to_qvariant(underline_color)) selection.format.setProperty(QTextFormat.FullWidthSelection, to_qvariant(True)) selection.cursor = cursor extra_selections.append(selection) self.set_extra_selections(key, extra_selections) if update: self.update_extra_selections() def __mark_occurrences(self): """Marking occurrences of the currently selected word""" self.__clear_occurrences() if not self.supported_language: return text = self.get_current_word() if text is None: return if self.has_selected_text() and self.get_selected_text() != text: return if (self.is_python_like()) and \ (sourcecode.is_keyword(to_text_string(text)) or \ to_text_string(text) == 'self'): return # Highlighting all occurrences of word *text* cursor = self.__find_first(text) self.occurrences = [] while cursor: self.occurrences.append(cursor.blockNumber()) self.__highlight_selection('occurrences', cursor, background_color=self.occurrence_color) cursor = self.__find_next(text, cursor) self.update_extra_selections() if len(self.occurrences) > 1 and self.occurrences[-1] == 0: # XXX: this is never happening with PySide but it's necessary # for PyQt4... this must be related to a different behavior for # the QTextDocument.find function between those two libraries self.occurrences.pop(-1) self.scrollflagarea.update() #-----highlight found results (find/replace widget) def highlight_found_results(self, pattern, words=False, regexp=False): """Highlight all found patterns""" pattern = to_text_string(pattern) if not pattern: return if not regexp: pattern = re.escape(to_text_string(pattern)) pattern = r"\b%s\b" % pattern if words else pattern text = to_text_string(self.toPlainText()) try: regobj = re.compile(pattern) except sre_constants.error: return extra_selections = [] self.found_results = [] for match in regobj.finditer(text): pos1, pos2 = match.span() selection = QTextEdit.ExtraSelection() selection.format.setBackground(self.found_results_color) selection.cursor = self.textCursor() selection.cursor.setPosition(pos1) self.found_results.append(selection.cursor.blockNumber()) selection.cursor.setPosition(pos2, QTextCursor.KeepAnchor) extra_selections.append(selection) self.set_extra_selections('find', extra_selections) self.update_extra_selections() def clear_found_results(self): """Clear found results highlighting""" self.found_results = [] self.clear_extra_selections('find') self.scrollflagarea.update() def __text_has_changed(self): """Text has changed, eventually clear found results highlighting""" if self.found_results: self.clear_found_results() #-----markers def get_markers_margin(self): if self.markers_margin: return self.markers_margin_width else: return 0 #-----linenumberarea def set_linenumberarea_enabled(self, state): self.linenumberarea_enabled = state self.linenumberarea.setVisible(state) self.update_linenumberarea_width() def get_linenumberarea_width(self): """Return current line number area width""" return self.linenumberarea.contentsRect().width() def compute_linenumberarea_width(self): """Compute and return line number area width""" if not self.linenumberarea_enabled: return 0 digits = 1 maxb = max(1, self.blockCount()) while maxb >= 10: maxb /= 10 digits += 1 if self.linenumbers_margin: linenumbers_margin = 3+self.fontMetrics().width('9'*digits) else: linenumbers_margin = 0 return linenumbers_margin+self.get_markers_margin() def update_linenumberarea_width(self, new_block_count=None): """ Update line number area width. new_block_count is needed to handle blockCountChanged(int) signal """ self.setViewportMargins(self.compute_linenumberarea_width(), 0, self.get_scrollflagarea_width(), 0) def update_linenumberarea(self, qrect, dy): """Update line number area""" if dy: self.linenumberarea.scroll(0, dy) else: self.linenumberarea.update(0, qrect.y(), self.linenumberarea.width(), qrect.height()) if qrect.contains(self.viewport().rect()): self.update_linenumberarea_width() def linenumberarea_paint_event(self, event): """Painting line number area""" painter = QPainter(self.linenumberarea) painter.fillRect(event.rect(), self.sideareas_color) # This is needed to make that the font size of line numbers # be the same as the text one when zooming # See Issues 2296 and 4811 font = self.font() font_height = self.fontMetrics().height() active_block = self.textCursor().block() active_line_number = active_block.blockNumber() + 1 def draw_pixmap(ytop, pixmap): if not QT55_VERSION: pixmap_height = pixmap.height() else: # scale pixmap height to device independent pixels pixmap_height = pixmap.height() / pixmap.devicePixelRatio() painter.drawPixmap(0, ytop + (font_height-pixmap_height) / 2, pixmap) for top, line_number, block in self.visible_blocks: if self.linenumbers_margin: if line_number == active_line_number: font.setWeight(font.Bold) painter.setFont(font) painter.setPen(self.normal_color) else: font.setWeight(font.Normal) painter.setFont(font) painter.setPen(self.linenumbers_color) painter.drawText(0, top, self.linenumberarea.width(), font_height, Qt.AlignRight | Qt.AlignBottom, to_text_string(line_number)) data = block.userData() if self.markers_margin and data: if data.code_analysis: for _message, error in data.code_analysis: if error: break if error: draw_pixmap(top, self.error_pixmap) else: draw_pixmap(top, self.warning_pixmap) if data.todo: draw_pixmap(top, self.todo_pixmap) if data.breakpoint: if data.breakpoint_condition is None: draw_pixmap(top, self.bp_pixmap) else: draw_pixmap(top, self.bpc_pixmap) def __get_linenumber_from_mouse_event(self, event): """Return line number from mouse event""" block = self.firstVisibleBlock() line_number = block.blockNumber() top = self.blockBoundingGeometry(block).translated( self.contentOffset()).top() bottom = top + self.blockBoundingRect(block).height() while block.isValid() and top < event.pos().y(): block = block.next() top = bottom bottom = top + self.blockBoundingRect(block).height() line_number += 1 return line_number def linenumberarea_mousemove_event(self, event): """Handling line number area mouse move event""" line_number = self.__get_linenumber_from_mouse_event(event) block = self.document().findBlockByNumber(line_number-1) data = block.userData() # this disables pyflakes messages if there is an active drag/selection # operation check = self.linenumberarea_released == -1 if data and data.code_analysis and check: self.__show_code_analysis_results(line_number, data.code_analysis) if event.buttons() == Qt.LeftButton: self.linenumberarea_released = line_number self.linenumberarea_select_lines(self.linenumberarea_pressed, self.linenumberarea_released) def linenumberarea_mousedoubleclick_event(self, event): """Handling line number area mouse double-click event""" line_number = self.__get_linenumber_from_mouse_event(event) shift = event.modifiers() & Qt.ShiftModifier self.add_remove_breakpoint(line_number, edit_condition=shift) def linenumberarea_mousepress_event(self, event): """Handling line number area mouse double press event""" line_number = self.__get_linenumber_from_mouse_event(event) self.linenumberarea_pressed = line_number self.linenumberarea_released = line_number self.linenumberarea_select_lines(self.linenumberarea_pressed, self.linenumberarea_released) def linenumberarea_mouserelease_event(self, event): """Handling line number area mouse release event""" self.linenumberarea_released = -1 self.linenumberarea_pressed = -1 def linenumberarea_select_lines(self, linenumber_pressed, linenumber_released): """Select line(s) after a mouse press/mouse press drag event""" find_block_by_line_number = self.document().findBlockByLineNumber move_n_blocks = (linenumber_released - linenumber_pressed) start_line = linenumber_pressed start_block = find_block_by_line_number(start_line - 1) cursor = self.textCursor() cursor.setPosition(start_block.position()) # Select/drag downwards if move_n_blocks > 0: for n in range(abs(move_n_blocks) + 1): cursor.movePosition(cursor.NextBlock, cursor.KeepAnchor) # Select/drag upwards or select single line else: cursor.movePosition(cursor.NextBlock) for n in range(abs(move_n_blocks) + 1): cursor.movePosition(cursor.PreviousBlock, cursor.KeepAnchor) # Account for last line case if linenumber_released == self.blockCount(): cursor.movePosition(cursor.EndOfBlock, cursor.KeepAnchor) else: cursor.movePosition(cursor.StartOfBlock, cursor.KeepAnchor) self.setTextCursor(cursor) #------Breakpoints def add_remove_breakpoint(self, line_number=None, condition=None, edit_condition=False): """Add/remove breakpoint""" if not self.is_python_like(): return if line_number is None: block = self.textCursor().block() else: block = self.document().findBlockByNumber(line_number-1) data = block.userData() if not data: data = BlockUserData(self) data.breakpoint = True elif not edit_condition: data.breakpoint = not data.breakpoint data.breakpoint_condition = None if condition is not None: data.breakpoint_condition = condition if edit_condition: condition = data.breakpoint_condition condition, valid = QInputDialog.getText(self, _('Breakpoint'), _("Condition:"), QLineEdit.Normal, condition) if not valid: return data.breakpoint = True data.breakpoint_condition = str(condition) if condition else None if data.breakpoint: text = to_text_string(block.text()).strip() if len(text) == 0 or text.startswith(('#', '"', "'")): data.breakpoint = False block.setUserData(data) self.linenumberarea.update() self.scrollflagarea.update() self.breakpoints_changed.emit() def get_breakpoints(self): """Get breakpoints""" breakpoints = [] block = self.document().firstBlock() for line_number in range(1, self.document().blockCount()+1): data = block.userData() if data and data.breakpoint: breakpoints.append((line_number, data.breakpoint_condition)) block = block.next() return breakpoints def clear_breakpoints(self): """Clear breakpoints""" self.breakpoints = [] for data in self.blockuserdata_list[:]: data.breakpoint = False # data.breakpoint_condition = None # not necessary, but logical if data.is_empty(): # This is not calling the __del__ in BlockUserData. Not # sure if it's supposed to or not, but that seems to be the # intent. del data def set_breakpoints(self, breakpoints): """Set breakpoints""" self.clear_breakpoints() for line_number, condition in breakpoints: self.add_remove_breakpoint(line_number, condition) def update_breakpoints(self): """Update breakpoints""" self.breakpoints_changed.emit() #-----Code introspection def do_completion(self, automatic=False): """Trigger completion""" if not self.is_completion_widget_visible(): self.get_completions.emit(automatic) def do_go_to_definition(self): """Trigger go-to-definition""" if not self.in_comment_or_string(): self.go_to_definition.emit(self.textCursor().position()) def show_object_info(self, position): """Trigger a calltip""" self.sig_show_object_info.emit(position) #-----edge line def set_edge_line_enabled(self, state): """Toggle edge line visibility""" self.edge_line_enabled = state self.edge_line.setVisible(state) def set_edge_line_column(self, column): """Set edge line column value""" self.edge_line.column = column self.edge_line.update() # -----blank spaces def set_blanks_enabled(self, state): """Toggle blanks visibility""" self.blanks_enabled = state option = self.document().defaultTextOption() option.setFlags(option.flags() | \ QTextOption.AddSpaceForLineAndParagraphSeparators) if self.blanks_enabled: option.setFlags(option.flags() | QTextOption.ShowTabsAndSpaces) else: option.setFlags(option.flags() & ~QTextOption.ShowTabsAndSpaces) self.document().setDefaultTextOption(option) # Rehighlight to make the spaces less apparent. self.rehighlight() #-----scrollflagarea def set_scrollflagarea_enabled(self, state): """Toggle scroll flag area visibility""" self.scrollflagarea_enabled = state self.scrollflagarea.setVisible(state) self.update_linenumberarea_width() def get_scrollflagarea_width(self): """Return scroll flag area width""" if self.scrollflagarea_enabled: return ScrollFlagArea.WIDTH else: return 0 def scrollflagarea_paint_event(self, event): """Painting the scroll flag area""" make_flag = self.scrollflagarea.make_flag_qrect make_slider = self.scrollflagarea.make_slider_range # Filling the whole painting area painter = QPainter(self.scrollflagarea) painter.fillRect(event.rect(), self.sideareas_color) block = self.document().firstBlock() # Painting warnings and todos for line_number in range(1, self.document().blockCount()+1): data = block.userData() if data: position = self.scrollflagarea.value_to_position(line_number) if data.code_analysis: # Warnings color = self.warning_color for _message, error in data.code_analysis: if error: color = self.error_color break set_scrollflagarea_painter(painter, color) painter.drawRect(make_flag(position)) if data.todo: # TODOs set_scrollflagarea_painter(painter, self.todo_color) painter.drawRect(make_flag(position)) if data.breakpoint: # Breakpoints set_scrollflagarea_painter(painter, self.breakpoint_color) painter.drawRect(make_flag(position)) block = block.next() # Occurrences if self.occurrences: set_scrollflagarea_painter(painter, self.occurrence_color) for line_number in self.occurrences: position = self.scrollflagarea.value_to_position(line_number) painter.drawRect(make_flag(position)) # Found results if self.found_results: set_scrollflagarea_painter(painter, self.found_results_color) for line_number in self.found_results: position = self.scrollflagarea.value_to_position(line_number) painter.drawRect(make_flag(position)) # Painting the slider range pen_color = QColor(Qt.white) pen_color.setAlphaF(.8) painter.setPen(pen_color) brush_color = QColor(Qt.white) brush_color.setAlphaF(.5) painter.setBrush(QBrush(brush_color)) painter.drawRect(make_slider(self.firstVisibleBlock().blockNumber())) def resizeEvent(self, event): """Reimplemented Qt method to handle line number area resizing""" TextEditBaseWidget.resizeEvent(self, event) cr = self.contentsRect() self.linenumberarea.setGeometry(\ QRect(cr.left(), cr.top(), self.compute_linenumberarea_width(), cr.height())) self.__set_scrollflagarea_geometry(cr) def __set_scrollflagarea_geometry(self, contentrect): """Set scroll flag area geometry""" cr = contentrect if self.verticalScrollBar().isVisible(): vsbw = self.verticalScrollBar().contentsRect().width() else: vsbw = 0 _left, _top, right, _bottom = self.getContentsMargins() if right > vsbw: # Depending on the platform (e.g. on Ubuntu), the scrollbar sizes # may be taken into account in the contents margins whereas it is # not on Windows for example vsbw = 0 self.scrollflagarea.setGeometry(\ QRect(cr.right()-ScrollFlagArea.WIDTH-vsbw, cr.top(), self.scrollflagarea.WIDTH, cr.height())) #-----edgeline def viewportEvent(self, event): """Override Qt method""" # 79-column edge line offset = self.contentOffset() x = self.blockBoundingGeometry(self.firstVisibleBlock()) \ .translated(offset.x(), offset.y()).left() \ +self.get_linenumberarea_width() \ +self.fontMetrics().width('9'*self.edge_line.column)+5 cr = self.contentsRect() self.edge_line.setGeometry(QRect(x, cr.top(), 1, cr.bottom())) self.__set_scrollflagarea_geometry(cr) return TextEditBaseWidget.viewportEvent(self, event) #-----Misc. def _apply_highlighter_color_scheme(self): """Apply color scheme from syntax highlighter to the editor""" hl = self.highlighter if hl is not None: self.set_palette(background=hl.get_background_color(), foreground=hl.get_foreground_color()) self.currentline_color = hl.get_currentline_color() self.currentcell_color = hl.get_currentcell_color() self.occurrence_color = hl.get_occurrence_color() self.ctrl_click_color = hl.get_ctrlclick_color() self.sideareas_color = hl.get_sideareas_color() self.comment_color = hl.get_comment_color() self.normal_color = hl.get_foreground_color() self.matched_p_color = hl.get_matched_p_color() self.unmatched_p_color = hl.get_unmatched_p_color() def apply_highlighter_settings(self, color_scheme=None): """Apply syntax highlighter settings""" if self.highlighter is not None: # Updating highlighter settings (font and color scheme) self.highlighter.setup_formats(self.font()) if color_scheme is not None: self.set_color_scheme(color_scheme) else: self.highlighter.rehighlight() def get_outlineexplorer_data(self): """Get data provided by the Outline Explorer""" return self.highlighter.get_outlineexplorer_data() def set_font(self, font, color_scheme=None): """Set font""" # Note: why using this method to set color scheme instead of # 'set_color_scheme'? To avoid rehighlighting the document twice # at startup. if color_scheme is not None: self.color_scheme = color_scheme self.setFont(font) self.update_linenumberarea_width() self.apply_highlighter_settings(color_scheme) def set_color_scheme(self, color_scheme): """Set color scheme for syntax highlighting""" self.color_scheme = color_scheme if self.highlighter is not None: # this calls self.highlighter.rehighlight() self.highlighter.set_color_scheme(color_scheme) self._apply_highlighter_color_scheme() if self.highlight_current_cell_enabled: self.highlight_current_cell() else: self.unhighlight_current_cell() if self.highlight_current_line_enabled: self.highlight_current_line() else: self.unhighlight_current_line() def set_text(self, text): """Set the text of the editor""" self.setPlainText(text) self.set_eol_chars(text) #if self.supported_language: #self.highlighter.rehighlight() def set_text_from_file(self, filename, language=None): """Set the text of the editor from file *fname*""" text, _enc = encoding.read(filename) if language is None: language = get_file_language(filename, text) self.set_language(language, filename) self.set_text(text) def append(self, text): """Append text to the end of the text widget""" cursor = self.textCursor() cursor.movePosition(QTextCursor.End) cursor.insertText(text) @Slot() def paste(self): """ Reimplement QPlainTextEdit's method to fix the following issue: on Windows, pasted text has only 'LF' EOL chars even if the original text has 'CRLF' EOL chars """ clipboard = QApplication.clipboard() text = to_text_string(clipboard.text()) if len(text.splitlines()) > 1: eol_chars = self.get_line_separator() clipboard.setText( eol_chars.join((text+eol_chars).splitlines()) ) # Standard paste TextEditBaseWidget.paste(self) def get_block_data(self, block): """Return block data (from syntax highlighter)""" return self.highlighter.block_data.get(block) def get_fold_level(self, block_nb): """Is it a fold header line? If so, return fold level If not, return None""" block = self.document().findBlockByNumber(block_nb) return self.get_block_data(block).fold_level #=============================================================================== # High-level editor features #=============================================================================== @Slot() def center_cursor_on_next_focus(self): """QPlainTextEdit's "centerCursor" requires the widget to be visible""" self.centerCursor() self.focus_in.disconnect(self.center_cursor_on_next_focus) def go_to_line(self, line, word=''): """Go to line number *line* and eventually highlight it""" line = min(line, self.get_line_count()) block = self.document().findBlockByNumber(line-1) self.setTextCursor(QTextCursor(block)) if self.isVisible(): self.centerCursor() else: self.focus_in.connect(self.center_cursor_on_next_focus) self.horizontalScrollBar().setValue(0) if word and to_text_string(word) in to_text_string(block.text()): self.find(word, QTextDocument.FindCaseSensitively) def exec_gotolinedialog(self): """Execute the GoToLineDialog dialog box""" dlg = GoToLineDialog(self) if dlg.exec_(): self.go_to_line(dlg.get_line_number()) def cleanup_code_analysis(self): """Remove all code analysis markers""" self.setUpdatesEnabled(False) self.clear_extra_selections('code_analysis') for data in self.blockuserdata_list[:]: data.code_analysis = [] if data.is_empty(): del data self.setUpdatesEnabled(True) # When the new code analysis results are empty, it is necessary # to update manually the scrollflag and linenumber areas (otherwise, # the old flags will still be displayed): self.scrollflagarea.update() self.linenumberarea.update() def process_code_analysis(self, check_results): """Analyze filename code with pyflakes""" self.cleanup_code_analysis() if check_results is None: # Not able to compile module return self.setUpdatesEnabled(False) cursor = self.textCursor() document = self.document() flags = QTextDocument.FindCaseSensitively|QTextDocument.FindWholeWords for message, line_number in check_results: error = 'syntax' in message # Note: line_number start from 1 (not 0) block = self.document().findBlockByNumber(line_number-1) data = block.userData() if not data: data = BlockUserData(self) data.code_analysis.append( (message, error) ) block.setUserData(data) refs = re.findall(r"\'[a-zA-Z0-9_]*\'", message) for ref in refs: # Highlighting found references text = ref[1:-1] # Scanning line number *line* and following lines if continued def is_line_splitted(line_no): text = to_text_string( document.findBlockByNumber(line_no).text()) stripped = text.strip() return stripped.endswith('\\') or stripped.endswith(',') \ or len(stripped) == 0 line2 = line_number-1 while line2 < self.blockCount()-1 and is_line_splitted(line2): line2 += 1 cursor.setPosition(block.position()) cursor.movePosition(QTextCursor.StartOfBlock) regexp = QRegExp(r"\b%s\b" % QRegExp.escape(text), Qt.CaseSensitive) color = self.error_color if error else self.warning_color # Highlighting all occurrences (this is a compromise as pyflakes # do not provide the column number -- see Issue 709 on Spyder's # GoogleCode project website) cursor = document.find(regexp, cursor, flags) if cursor: while cursor and cursor.blockNumber() <= line2 \ and cursor.blockNumber() >= line_number-1 \ and cursor.position() > 0: self.__highlight_selection('code_analysis', cursor, underline_color=QColor(color)) cursor = document.find(text, cursor, flags) self.update_extra_selections() self.setUpdatesEnabled(True) self.linenumberarea.update() def __show_code_analysis_results(self, line_number, code_analysis): """Show warning/error messages""" msglist = [ msg for msg, _error in code_analysis ] self.show_calltip(_("Code analysis"), msglist, color='#129625', at_line=line_number) def go_to_next_warning(self): """Go to next code analysis warning message and return new cursor position""" block = self.textCursor().block() line_count = self.document().blockCount() while True: if block.blockNumber()+1 < line_count: block = block.next() else: block = self.document().firstBlock() data = block.userData() if data and data.code_analysis: break line_number = block.blockNumber()+1 self.go_to_line(line_number) self.__show_code_analysis_results(line_number, data.code_analysis) return self.get_position('cursor') def go_to_previous_warning(self): """Go to previous code analysis warning message and return new cursor position""" block = self.textCursor().block() while True: if block.blockNumber() > 0: block = block.previous() else: block = self.document().lastBlock() data = block.userData() if data and data.code_analysis: break line_number = block.blockNumber()+1 self.go_to_line(line_number) self.__show_code_analysis_results(line_number, data.code_analysis) return self.get_position('cursor') #------Tasks management def go_to_next_todo(self): """Go to next todo and return new cursor position""" block = self.textCursor().block() line_count = self.document().blockCount() while True: if block.blockNumber()+1 < line_count: block = block.next() else: block = self.document().firstBlock() data = block.userData() if data and data.todo: break line_number = block.blockNumber()+1 self.go_to_line(line_number) self.show_calltip(_("To do"), data.todo, color='#3096FC', at_line=line_number) return self.get_position('cursor') def process_todo(self, todo_results): """Process todo finder results""" for data in self.blockuserdata_list[:]: data.todo = '' if data.is_empty(): del data for message, line_number in todo_results: block = self.document().findBlockByNumber(line_number-1) data = block.userData() if not data: data = BlockUserData(self) data.todo = message block.setUserData(data) self.scrollflagarea.update() #------Comments/Indentation def add_prefix(self, prefix): """Add prefix to current line or selected line(s)""" cursor = self.textCursor() if self.has_selected_text(): # Add prefix to selected line(s) start_pos, end_pos = cursor.selectionStart(), cursor.selectionEnd() # Let's see if selection begins at a block start first_pos = min([start_pos, end_pos]) first_cursor = self.textCursor() first_cursor.setPosition(first_pos) begins_at_block_start = first_cursor.atBlockStart() cursor.beginEditBlock() cursor.setPosition(end_pos) # Check if end_pos is at the start of a block: if so, starting # changes from the previous block if cursor.atBlockStart(): cursor.movePosition(QTextCursor.PreviousBlock) if cursor.position() < start_pos: cursor.setPosition(start_pos) while cursor.position() >= start_pos: cursor.movePosition(QTextCursor.StartOfBlock) cursor.insertText(prefix) if start_pos == 0 and cursor.blockNumber() == 0: # Avoid infinite loop when indenting the very first line break cursor.movePosition(QTextCursor.PreviousBlock) cursor.movePosition(QTextCursor.EndOfBlock) cursor.endEditBlock() if begins_at_block_start: # Extending selection to prefix: cursor = self.textCursor() start_pos = cursor.selectionStart() end_pos = cursor.selectionEnd() if start_pos < end_pos: start_pos -= len(prefix) else: end_pos -= len(prefix) cursor.setPosition(start_pos, QTextCursor.MoveAnchor) cursor.setPosition(end_pos, QTextCursor.KeepAnchor) self.setTextCursor(cursor) else: # Add prefix to current line cursor.beginEditBlock() cursor.movePosition(QTextCursor.StartOfBlock) cursor.insertText(prefix) cursor.endEditBlock() def __is_cursor_at_start_of_block(self, cursor): cursor.movePosition(QTextCursor.StartOfBlock) def remove_suffix(self, suffix): """ Remove suffix from current line (there should not be any selection) """ cursor = self.textCursor() cursor.setPosition(cursor.position()-len(suffix), QTextCursor.KeepAnchor) if to_text_string(cursor.selectedText()) == suffix: cursor.removeSelectedText() def remove_prefix(self, prefix): """Remove prefix from current line or selected line(s)""" cursor = self.textCursor() if self.has_selected_text(): # Remove prefix from selected line(s) start_pos, end_pos = sorted([cursor.selectionStart(), cursor.selectionEnd()]) cursor.setPosition(start_pos) if not cursor.atBlockStart(): cursor.movePosition(QTextCursor.StartOfBlock) start_pos = cursor.position() cursor.beginEditBlock() cursor.setPosition(end_pos) # Check if end_pos is at the start of a block: if so, starting # changes from the previous block if cursor.atBlockStart(): cursor.movePosition(QTextCursor.PreviousBlock) if cursor.position() < start_pos: cursor.setPosition(start_pos) cursor.movePosition(QTextCursor.StartOfBlock) old_pos = None while cursor.position() >= start_pos: new_pos = cursor.position() if old_pos == new_pos: break else: old_pos = new_pos line_text = to_text_string(cursor.block().text()) if (prefix.strip() and line_text.lstrip().startswith(prefix) or line_text.startswith(prefix)): cursor.movePosition(QTextCursor.Right, QTextCursor.MoveAnchor, line_text.find(prefix)) cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, len(prefix)) cursor.removeSelectedText() cursor.movePosition(QTextCursor.PreviousBlock) cursor.endEditBlock() else: # Remove prefix from current line cursor.movePosition(QTextCursor.StartOfBlock) line_text = to_text_string(cursor.block().text()) if (prefix.strip() and line_text.lstrip().startswith(prefix) or line_text.startswith(prefix)): cursor.movePosition(QTextCursor.Right, QTextCursor.MoveAnchor, line_text.find(prefix)) cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, len(prefix)) cursor.removeSelectedText() def fix_indent(self, *args, **kwargs): """Indent line according to the preferences""" if self.is_python_like(): return self.fix_indent_smart(*args, **kwargs) else: return self.simple_indentation(*args, **kwargs) def simple_indentation(self, forward=True, **kwargs): """ Simply preserve the indentation-level of the previous line. """ cursor = self.textCursor() block_nb = cursor.blockNumber() prev_block = self.document().findBlockByLineNumber(block_nb-1) prevline = to_text_string(prev_block.text()) indentation = re.match(r"\s*", prevline).group() # Unident if not forward: indentation = indentation[len(self.indent_chars):] cursor.insertText(indentation) return False # simple indentation don't fix indentation def fix_indent_smart(self, forward=True, comment_or_string=False): """ Fix indentation (Python only, no text selection) forward=True: fix indent only if text is not enough indented (otherwise force indent) forward=False: fix indent only if text is too much indented (otherwise force unindent) Returns True if indent needed to be fixed """ cursor = self.textCursor() block_nb = cursor.blockNumber() # find the line that contains our scope diff_paren = 0 diff_brack = 0 diff_curly = 0 add_indent = False prevline = None prevtext = "" for prevline in range(block_nb-1, -1, -1): cursor.movePosition(QTextCursor.PreviousBlock) prevtext = to_text_string(cursor.block().text()).rstrip() # Remove inline comment inline_comment = prevtext.find('#') if inline_comment != -1: prevtext = prevtext[:inline_comment] if ((self.is_python_like() and not prevtext.strip().startswith('#') and prevtext) or prevtext): if not "return" in prevtext.strip().split()[:1] and \ (prevtext.strip().endswith(')') or prevtext.strip().endswith(']') or prevtext.strip().endswith('}')): comment_or_string = True # prevent further parsing elif prevtext.strip().endswith(':') and self.is_python_like(): add_indent = True comment_or_string = True if (prevtext.count(')') > prevtext.count('(')): diff_paren = prevtext.count(')') - prevtext.count('(') elif (prevtext.count(']') > prevtext.count('[')): diff_brack = prevtext.count(']') - prevtext.count('[') elif (prevtext.count('}') > prevtext.count('{')): diff_curly = prevtext.count('}') - prevtext.count('{') elif diff_paren or diff_brack or diff_curly: diff_paren += prevtext.count(')') - prevtext.count('(') diff_brack += prevtext.count(']') - prevtext.count('[') diff_curly += prevtext.count('}') - prevtext.count('{') if not (diff_paren or diff_brack or diff_curly): break else: break if prevline: correct_indent = self.get_block_indentation(prevline) else: correct_indent = 0 indent = self.get_block_indentation(block_nb) if add_indent: if self.indent_chars == '\t': correct_indent += self.tab_stop_width_spaces else: correct_indent += len(self.indent_chars) if not comment_or_string: if prevtext.endswith(':') and self.is_python_like(): # Indent if self.indent_chars == '\t': correct_indent += self.tab_stop_width_spaces else: correct_indent += len(self.indent_chars) elif self.is_python_like() and \ (prevtext.endswith('continue') or prevtext.endswith('break') or prevtext.endswith('pass') or ("return" in prevtext.strip().split()[:1] and len(re.split(r'\(|\{|\[', prevtext)) == len(re.split(r'\)|\}|\]', prevtext)))): # Unindent if self.indent_chars == '\t': correct_indent -= self.tab_stop_width_spaces else: correct_indent -= len(self.indent_chars) elif len(re.split(r'\(|\{|\[', prevtext)) > 1: # Check if all braces are matching using a stack stack = ['dummy'] # Dummy elemet to avoid index errors deactivate = None for c in prevtext: if deactivate is not None: if c == deactivate: deactivate = None elif c in ["'", '"']: deactivate = c elif c in ['(', '[','{']: stack.append(c) elif c == ')' and stack[-1] == '(': stack.pop() elif c == ']' and stack[-1] == '[': stack.pop() elif c == '}' and stack[-1] == '{': stack.pop() if len(stack) == 1: # all braces matching pass # Hanging indent # find out if the last one is (, {, or []}) # only if prevtext is long that the hanging indentation elif (re.search(r'[\(|\{|\[]\s*$', prevtext) is not None and ((self.indent_chars == '\t' and self.tab_stop_width_spaces * 2 < len(prevtext)) or (self.indent_chars.startswith(' ') and len(self.indent_chars) * 2 < len(prevtext)))): if self.indent_chars == '\t': correct_indent += self.tab_stop_width_spaces * 2 else: correct_indent += len(self.indent_chars) * 2 else: rlmap = {")":"(", "]":"[", "}":"{"} for par in rlmap: i_right = prevtext.rfind(par) if i_right != -1: prevtext = prevtext[:i_right] for _i in range(len(prevtext.split(par))): i_left = prevtext.rfind(rlmap[par]) if i_left != -1: prevtext = prevtext[:i_left] else: break else: if prevtext.strip(): if len(re.split(r'\(|\{|\[', prevtext)) > 1: #correct indent only if there are still opening brackets prevexpr = re.split(r'\(|\{|\[', prevtext)[-1] correct_indent = len(prevtext)-len(prevexpr) else: correct_indent = len(prevtext) if not (diff_paren or diff_brack or diff_curly) and \ not prevtext.endswith(':') and prevline: cur_indent = self.get_block_indentation(block_nb - 1) is_blank = not self.get_text_line(block_nb - 1).strip() prevline_indent = self.get_block_indentation(prevline) trailing_text = self.get_text_line(block_nb).strip() if cur_indent < prevline_indent and \ (trailing_text or is_blank): if cur_indent % len(self.indent_chars) == 0: correct_indent = cur_indent else: correct_indent = cur_indent \ + (len(self.indent_chars) - cur_indent % len(self.indent_chars)) if (forward and indent >= correct_indent) or \ (not forward and indent <= correct_indent): # No indentation fix is necessary return False if correct_indent >= 0: cursor = self.textCursor() cursor.movePosition(QTextCursor.StartOfBlock) if self.indent_chars == '\t': indent = indent // self.tab_stop_width_spaces cursor.setPosition(cursor.position()+indent, QTextCursor.KeepAnchor) cursor.removeSelectedText() if self.indent_chars == '\t': indent_text = '\t' * (correct_indent // self.tab_stop_width_spaces) \ + ' ' * (correct_indent % self.tab_stop_width_spaces) else: indent_text = ' '*correct_indent cursor.insertText(indent_text) return True @Slot() def clear_all_output(self): """Removes all ouput in the ipynb format (Json only)""" try: nb = nbformat.reads(self.toPlainText(), as_version=4) if nb.cells: for cell in nb.cells: if 'outputs' in cell: cell['outputs'] = [] if 'prompt_number' in cell: cell['prompt_number'] = None # We do the following rather than using self.setPlainText # to benefit from QTextEdit's undo/redo feature. self.selectAll() self.insertPlainText(nbformat.writes(nb)) except Exception as e: QMessageBox.critical(self, _('Removal error'), _("It was not possible to remove outputs from " "this notebook. The error is:\n\n") + \ to_text_string(e)) return @Slot() def convert_notebook(self): """Convert an IPython notebook to a Python script in editor""" try: nb = nbformat.reads(self.toPlainText(), as_version=4) script = nbexporter().from_notebook_node(nb)[0] except Exception as e: QMessageBox.critical(self, _('Conversion error'), _("It was not possible to convert this " "notebook. The error is:\n\n") + \ to_text_string(e)) return self.sig_new_file.emit(script) def indent(self, force=False): """ Indent current line or selection force=True: indent even if cursor is not a the beginning of the line """ leading_text = self.get_text('sol', 'cursor') if self.has_selected_text(): self.add_prefix(self.indent_chars) elif force or not leading_text.strip() \ or (self.tab_indents and self.tab_mode): if self.is_python_like(): if not self.fix_indent(forward=True): self.add_prefix(self.indent_chars) else: self.add_prefix(self.indent_chars) else: if len(self.indent_chars) > 1: length = len(self.indent_chars) self.insert_text(" "*(length-(len(leading_text) % length))) else: self.insert_text(self.indent_chars) def indent_or_replace(self): """Indent or replace by 4 spaces depending on selection and tab mode""" if (self.tab_indents and self.tab_mode) or not self.has_selected_text(): self.indent() else: cursor = self.textCursor() if self.get_selected_text() == \ to_text_string(cursor.block().text()): self.indent() else: cursor1 = self.textCursor() cursor1.setPosition(cursor.selectionStart()) cursor2 = self.textCursor() cursor2.setPosition(cursor.selectionEnd()) if cursor1.blockNumber() != cursor2.blockNumber(): self.indent() else: self.replace(self.indent_chars) def unindent(self, force=False): """ Unindent current line or selection force=True: unindent even if cursor is not a the beginning of the line """ if self.has_selected_text(): self.remove_prefix(self.indent_chars) else: leading_text = self.get_text('sol', 'cursor') if force or not leading_text.strip() \ or (self.tab_indents and self.tab_mode): if self.is_python_like(): if not self.fix_indent(forward=False): self.remove_prefix(self.indent_chars) elif leading_text.endswith('\t'): self.remove_prefix('\t') else: self.remove_prefix(self.indent_chars) @Slot() def toggle_comment(self): """Toggle comment on current line or selection""" cursor = self.textCursor() start_pos, end_pos = sorted([cursor.selectionStart(), cursor.selectionEnd()]) cursor.setPosition(end_pos) last_line = cursor.block().blockNumber() if cursor.atBlockStart() and start_pos != end_pos: last_line -= 1 cursor.setPosition(start_pos) first_line = cursor.block().blockNumber() # If the selection contains only commented lines and surrounding # whitespace, uncomment. Otherwise, comment. is_comment_or_whitespace = True at_least_one_comment = False for _line_nb in range(first_line, last_line+1): text = to_text_string(cursor.block().text()).lstrip() is_comment = text.startswith(self.comment_string) is_whitespace = (text == '') is_comment_or_whitespace *= (is_comment or is_whitespace) if is_comment: at_least_one_comment = True cursor.movePosition(QTextCursor.NextBlock) if is_comment_or_whitespace and at_least_one_comment: self.uncomment() else: self.comment() def comment(self): """Comment current line or selection.""" self.add_prefix(self.comment_string) def uncomment(self): """Uncomment current line or selection.""" self.remove_prefix(self.comment_string) def __blockcomment_bar(self): return self.comment_string + ' ' + '=' * (78 - len(self.comment_string)) def transform_to_uppercase(self): """Change to uppercase current line or selection.""" cursor = self.textCursor() prev_pos = cursor.position() selected_text = to_text_string(cursor.selectedText()) if len(selected_text) == 0: prev_pos = cursor.position() cursor.select(QTextCursor.WordUnderCursor) selected_text = to_text_string(cursor.selectedText()) s = selected_text.upper() cursor.insertText(s) self.set_cursor_position(prev_pos) def transform_to_lowercase(self): """Change to lowercase current line or selection.""" cursor = self.textCursor() prev_pos = cursor.position() selected_text = to_text_string(cursor.selectedText()) if len(selected_text) == 0: prev_pos = cursor.position() cursor.select(QTextCursor.WordUnderCursor) selected_text = to_text_string(cursor.selectedText()) s = selected_text.lower() cursor.insertText(s) self.set_cursor_position(prev_pos) def blockcomment(self): """Block comment current line or selection.""" comline = self.__blockcomment_bar() + self.get_line_separator() cursor = self.textCursor() if self.has_selected_text(): self.extend_selection_to_complete_lines() start_pos, end_pos = cursor.selectionStart(), cursor.selectionEnd() else: start_pos = end_pos = cursor.position() cursor.beginEditBlock() cursor.setPosition(start_pos) cursor.movePosition(QTextCursor.StartOfBlock) while cursor.position() <= end_pos: cursor.insertText(self.comment_string + " ") cursor.movePosition(QTextCursor.EndOfBlock) if cursor.atEnd(): break cursor.movePosition(QTextCursor.NextBlock) end_pos += len(self.comment_string + " ") cursor.setPosition(end_pos) cursor.movePosition(QTextCursor.EndOfBlock) if cursor.atEnd(): cursor.insertText(self.get_line_separator()) else: cursor.movePosition(QTextCursor.NextBlock) cursor.insertText(comline) cursor.setPosition(start_pos) cursor.movePosition(QTextCursor.StartOfBlock) cursor.insertText(comline) cursor.endEditBlock() def unblockcomment(self): """Un-block comment current line or selection""" def __is_comment_bar(cursor): return to_text_string(cursor.block().text() ).startswith(self.__blockcomment_bar()) # Finding first comment bar cursor1 = self.textCursor() if __is_comment_bar(cursor1): return while not __is_comment_bar(cursor1): cursor1.movePosition(QTextCursor.PreviousBlock) if cursor1.atStart(): break if not __is_comment_bar(cursor1): return def __in_block_comment(cursor): cs = self.comment_string return to_text_string(cursor.block().text()).startswith(cs) # Finding second comment bar cursor2 = QTextCursor(cursor1) cursor2.movePosition(QTextCursor.NextBlock) while not __is_comment_bar(cursor2) and __in_block_comment(cursor2): cursor2.movePosition(QTextCursor.NextBlock) if cursor2.block() == self.document().lastBlock(): break if not __is_comment_bar(cursor2): return # Removing block comment cursor3 = self.textCursor() cursor3.beginEditBlock() cursor3.setPosition(cursor1.position()) cursor3.movePosition(QTextCursor.NextBlock) while cursor3.position() < cursor2.position(): cursor3.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor) if not cursor3.atBlockEnd(): # standard commenting inserts '# ' but a trailing space on an # empty line might be stripped. cursor3.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor) cursor3.removeSelectedText() cursor3.movePosition(QTextCursor.NextBlock) for cursor in (cursor2, cursor1): cursor3.setPosition(cursor.position()) cursor3.select(QTextCursor.BlockUnderCursor) cursor3.removeSelectedText() cursor3.endEditBlock() #------Kill ring handlers # Taken from Jupyter's QtConsole # Copyright (c) 2001-2015, IPython Development Team # Copyright (c) 2015-, Jupyter Development Team def kill_line_end(self): """Kill the text on the current line from the cursor forward""" cursor = self.textCursor() cursor.clearSelection() cursor.movePosition(QTextCursor.EndOfLine, QTextCursor.KeepAnchor) if not cursor.hasSelection(): # Line deletion cursor.movePosition(QTextCursor.NextBlock, QTextCursor.KeepAnchor) self._kill_ring.kill_cursor(cursor) self.setTextCursor(cursor) def kill_line_start(self): """Kill the text on the current line from the cursor backward""" cursor = self.textCursor() cursor.clearSelection() cursor.movePosition(QTextCursor.StartOfBlock, QTextCursor.KeepAnchor) self._kill_ring.kill_cursor(cursor) self.setTextCursor(cursor) def _get_word_start_cursor(self, position): """Find the start of the word to the left of the given position. If a sequence of non-word characters precedes the first word, skip over them. (This emulates the behavior of bash, emacs, etc.) """ document = self.document() position -= 1 while (position and not is_letter_or_number(document.characterAt(position))): position -= 1 while position and is_letter_or_number(document.characterAt(position)): position -= 1 cursor = self.textCursor() cursor.setPosition(position + 1) return cursor def _get_word_end_cursor(self, position): """Find the end of the word to the right of the given position. If a sequence of non-word characters precedes the first word, skip over them. (This emulates the behavior of bash, emacs, etc.) """ document = self.document() cursor = self.textCursor() position = cursor.position() cursor.movePosition(QTextCursor.End) end = cursor.position() while (position < end and not is_letter_or_number(document.characterAt(position))): position += 1 while (position < end and is_letter_or_number(document.characterAt(position))): position += 1 cursor.setPosition(position) return cursor def kill_prev_word(self): """Kill the previous word""" position = self.textCursor().position() cursor = self._get_word_start_cursor(position) cursor.setPosition(position, QTextCursor.KeepAnchor) self._kill_ring.kill_cursor(cursor) self.setTextCursor(cursor) def kill_next_word(self): """Kill the next word""" position = self.textCursor().position() cursor = self._get_word_end_cursor(position) cursor.setPosition(position, QTextCursor.KeepAnchor) self._kill_ring.kill_cursor(cursor) self.setTextCursor(cursor) #------Autoinsertion of quotes/colons def __get_current_color(self, cursor=None): """Get the syntax highlighting color for the current cursor position""" if cursor is None: cursor = self.textCursor() block = cursor.block() pos = cursor.position() - block.position() # relative pos within block layout = block.layout() block_formats = layout.additionalFormats() if block_formats: # To easily grab current format for autoinsert_colons if cursor.atBlockEnd(): current_format = block_formats[-1].format else: current_format = None for fmt in block_formats: if (pos >= fmt.start) and (pos < fmt.start + fmt.length): current_format = fmt.format if current_format is None: return None color = current_format.foreground().color().name() return color else: return None def in_comment_or_string(self, cursor=None): """Is the cursor inside or next to a comment or string?""" if self.highlighter: if cursor is None: current_color = self.__get_current_color() else: current_color = self.__get_current_color(cursor=cursor) comment_color = self.highlighter.get_color_name('comment') string_color = self.highlighter.get_color_name('string') if (current_color == comment_color) or (current_color == string_color): return True else: return False else: return False def __colon_keyword(self, text): stmt_kws = ['def', 'for', 'if', 'while', 'with', 'class', 'elif', 'except'] whole_kws = ['else', 'try', 'except', 'finally'] text = text.lstrip() words = text.split() if any([text == wk for wk in whole_kws]): return True elif len(words) < 2: return False elif any([words[0] == sk for sk in stmt_kws]): return True else: return False def __forbidden_colon_end_char(self, text): end_chars = [':', '\\', '[', '{', '(', ','] text = text.rstrip() if any([text.endswith(c) for c in end_chars]): return True else: return False def __unmatched_braces_in_line(self, text): block = self.textCursor().block() line_pos = block.position() for pos, char in enumerate(text): if char in ['(', '[', '{']: match = self.find_brace_match(line_pos+pos, char, forward=True) if (match is None) or (match > line_pos+len(text)): return True if char in [')', ']', '}']: match = self.find_brace_match(line_pos+pos, char, forward=False) if (match is None) or (match < line_pos): return True return False def __has_colon_not_in_brackets(self, text): """ Return whether a string has a colon which is not between brackets. This function returns True if the given string has a colon which is not between a pair of (round, square or curly) brackets. It assumes that the brackets in the string are balanced. """ for pos, char in enumerate(text): if char == ':' and not self.__unmatched_braces_in_line(text[:pos]): return True return False def autoinsert_colons(self): """Decide if we want to autoinsert colons""" line_text = self.get_text('sol', 'cursor') if not self.textCursor().atBlockEnd(): return False elif self.in_comment_or_string(): return False elif not self.__colon_keyword(line_text): return False elif self.__forbidden_colon_end_char(line_text): return False elif self.__unmatched_braces_in_line(line_text): return False elif self.__has_colon_not_in_brackets(line_text): return False else: return True def __unmatched_quotes_in_line(self, text): """Return whether a string has open quotes. This simply counts whether the number of quote characters of either type in the string is odd. Take from the IPython project (in IPython/core/completer.py in v0.13) Spyder team: Add some changes to deal with escaped quotes - Copyright (C) 2008-2011 IPython Development Team - Copyright (C) 2001-2007 Fernando Perez. - Copyright (C) 2001 Python Software Foundation, www.python.org Distributed under the terms of the BSD License. """ # We check " first, then ', so complex cases with nested quotes will # get the " to take precedence. text = text.replace("\\'", "") text = text.replace('\\"', '') if text.count('"') % 2: return '"' elif text.count("'") % 2: return "'" else: return '' def __next_char(self): cursor = self.textCursor() cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor) next_char = to_text_string(cursor.selectedText()) return next_char def __in_comment(self): if self.highlighter: current_color = self.__get_current_color() comment_color = self.highlighter.get_color_name('comment') if current_color == comment_color: return True else: return False else: return False def autoinsert_quotes(self, key): """Control how to automatically insert quotes in various situations""" char = {Qt.Key_QuoteDbl: '"', Qt.Key_Apostrophe: '\''}[key] line_text = self.get_text('sol', 'eol') line_to_cursor = self.get_text('sol', 'cursor') cursor = self.textCursor() last_three = self.get_text('sol', 'cursor')[-3:] last_two = self.get_text('sol', 'cursor')[-2:] trailing_text = self.get_text('cursor', 'eol').strip() if self.has_selected_text(): text = ''.join([char, self.get_selected_text(), char]) self.insert_text(text) elif self.__in_comment(): self.insert_text(char) elif len(trailing_text) > 0 and not \ self.__unmatched_quotes_in_line(line_to_cursor) == char: self.insert_text(char) elif self.__unmatched_quotes_in_line(line_text) and \ (not last_three == 3*char): self.insert_text(char) # Move to the right if we are before a quote elif self.__next_char() == char: cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor, 1) cursor.clearSelection() self.setTextCursor(cursor) # Automatic insertion of triple double quotes (for docstrings) elif last_three == 3*char: self.insert_text(3*char) cursor = self.textCursor() cursor.movePosition(QTextCursor.PreviousCharacter, QTextCursor.KeepAnchor, 3) cursor.clearSelection() self.setTextCursor(cursor) # If last two chars are quotes, just insert one more because most # probably the user wants to write a docstring elif last_two == 2*char: self.insert_text(char) # Automatic insertion of quotes else: self.insert_text(2*char) cursor = self.textCursor() cursor.movePosition(QTextCursor.PreviousCharacter) self.setTextCursor(cursor) #=============================================================================== # Qt Event handlers #=============================================================================== def setup_context_menu(self): """Setup context menu""" self.undo_action = create_action( self, _("Undo"), icon=ima.icon('undo'), shortcut=get_shortcut('editor', 'undo'), triggered=self.undo) self.redo_action = create_action( self, _("Redo"), icon=ima.icon('redo'), shortcut=get_shortcut('editor', 'redo'), triggered=self.redo) self.cut_action = create_action( self, _("Cut"), icon=ima.icon('editcut'), shortcut=get_shortcut('editor', 'cut'), triggered=self.cut) self.copy_action = create_action( self, _("Copy"), icon=ima.icon('editcopy'), shortcut=get_shortcut('editor', 'copy'), triggered=self.copy) self.paste_action = create_action( self, _("Paste"), icon=ima.icon('editpaste'), shortcut=get_shortcut('editor', 'paste'), triggered=self.paste) selectall_action = create_action( self, _("Select All"), icon=ima.icon('selectall'), shortcut=get_shortcut('editor', 'select all'), triggered=self.selectAll) toggle_comment_action = create_action( self, _("Comment")+"/"+_("Uncomment"), icon=ima.icon('comment'), shortcut=get_shortcut('editor', 'toggle comment'), triggered=self.toggle_comment) self.clear_all_output_action = create_action( self, _("Clear all ouput"), icon=ima.icon('ipython_console'), triggered=self.clear_all_output) self.ipynb_convert_action = create_action( self, _("Convert to Python script"), icon=ima.icon('python'), triggered=self.convert_notebook) self.gotodef_action = create_action( self, _("Go to definition"), shortcut=get_shortcut('editor', 'go to definition'), triggered=self.go_to_definition_from_cursor) # Run actions self.run_cell_action = create_action( self, _("Run cell"), icon=ima.icon('run_cell'), shortcut=QKeySequence(RUN_CELL_SHORTCUT), triggered=self.run_cell.emit) self.run_cell_and_advance_action = create_action( self, _("Run cell and advance"), icon=ima.icon('run_cell'), shortcut=QKeySequence(RUN_CELL_AND_ADVANCE_SHORTCUT), triggered=self.run_cell_and_advance.emit) self.re_run_last_cell_action = create_action( self, _("Re-run last cell"), icon=ima.icon('run_cell'), shortcut=get_shortcut('editor', 're-run last cell'), triggered=self.re_run_last_cell.emit) self.run_selection_action = create_action( self, _("Run &selection or current line"), icon=ima.icon('run_selection'), shortcut=get_shortcut('editor', 'run selection'), triggered=self.run_selection.emit) # Zoom actions zoom_in_action = create_action( self, _("Zoom in"), icon=ima.icon('zoom_in'), shortcut=QKeySequence(QKeySequence.ZoomIn), triggered=self.zoom_in.emit) zoom_out_action = create_action( self, _("Zoom out"), icon=ima.icon('zoom_out'), shortcut=QKeySequence(QKeySequence.ZoomOut), triggered=self.zoom_out.emit) zoom_reset_action = create_action( self, _("Zoom reset"), shortcut=QKeySequence("Ctrl+0"), triggered=self.zoom_reset.emit) # Build menu self.menu = QMenu(self) actions_1 = [self.run_cell_action, self.run_cell_and_advance_action, self.re_run_last_cell_action, self.run_selection_action, self.gotodef_action, None, self.undo_action, self.redo_action, None, self.cut_action, self.copy_action, self.paste_action, selectall_action] actions_2 = [None, zoom_in_action, zoom_out_action, zoom_reset_action, None, toggle_comment_action] if nbformat is not None: nb_actions = [self.clear_all_output_action, self.ipynb_convert_action, None] actions = actions_1 + nb_actions + actions_2 add_actions(self.menu, actions) else: actions = actions_1 + actions_2 add_actions(self.menu, actions) # Read-only context-menu self.readonly_menu = QMenu(self) add_actions(self.readonly_menu, (self.copy_action, None, selectall_action, self.gotodef_action)) def keyReleaseEvent(self, event): """Override Qt method.""" self.timer_syntax_highlight.start() super(CodeEditor, self).keyReleaseEvent(event) event.ignore() def keyPressEvent(self, event): """Reimplement Qt method""" key = event.key() ctrl = event.modifiers() & Qt.ControlModifier shift = event.modifiers() & Qt.ShiftModifier text = to_text_string(event.text()) has_selection = self.has_selected_text() if text: self.__clear_occurrences() if QToolTip.isVisible(): self.hide_tooltip_if_necessary(key) # Handle the Qt Builtin key sequences checks = [('SelectAll', 'Select All'), ('Copy', 'Copy'), ('Cut', 'Cut'), ('Paste', 'Paste')] for qname, name in checks: seq = getattr(QKeySequence, qname) sc = get_shortcut('editor', name) default = QKeySequence(seq).toString() # XXX - Using debug_print, it can be seen that event and seq # will never be equal, so this code is never executed. # Need to find out the intended purpose and if it should be # retained. if event == seq and sc != default: # if we have overridden it, call our action for shortcut in self.shortcuts: qsc, name, keystr = shortcut.data if keystr == default: qsc.activated.emit() event.ignore() return # otherwise, pass it on to parent event.ignore() return if key in (Qt.Key_Enter, Qt.Key_Return): if not shift and not ctrl: if self.add_colons_enabled and self.is_python_like() and \ self.autoinsert_colons(): self.textCursor().beginEditBlock() self.insert_text(':' + self.get_line_separator()) self.fix_indent() self.textCursor().endEditBlock() elif self.is_completion_widget_visible() \ and self.codecompletion_enter: self.select_completion_list() else: # Check if we're in a comment or a string at the # current position cmt_or_str_cursor = self.in_comment_or_string() # Check if the line start with a comment or string cursor = self.textCursor() cursor.setPosition(cursor.block().position(), QTextCursor.KeepAnchor) cmt_or_str_line_begin = self.in_comment_or_string( cursor=cursor) # Check if we are in a comment or a string cmt_or_str = cmt_or_str_cursor and cmt_or_str_line_begin self.textCursor().beginEditBlock() TextEditBaseWidget.keyPressEvent(self, event) self.fix_indent(comment_or_string=cmt_or_str) self.textCursor().endEditBlock() elif shift: self.run_cell_and_advance.emit() elif ctrl: self.run_cell.emit() elif shift and key == Qt.Key_Delete: # Shift + Del is a Key sequence reserved by most OSes # https://github.com/spyder-ide/spyder/issues/3405 # For now, add back reserved sequence for cut (issue 5973). # Since Ctrl+X is configurable, this should also use preferences. # https://doc.qt.io/qt-5/qkeysequence.html if has_selection: self.cut() else: self.delete_line() elif shift and key == Qt.Key_Insert: # For now, add back reserved sequence for paste (issue 5973). # Since Ctrl+V is configurable, this should also use preferences. # https://doc.qt.io/qt-5/qkeysequence.html self.paste() elif key == Qt.Key_Insert and not shift and not ctrl: self.setOverwriteMode(not self.overwriteMode()) elif key == Qt.Key_Backspace and not shift and not ctrl: leading_text = self.get_text('sol', 'cursor') leading_length = len(leading_text) trailing_spaces = leading_length-len(leading_text.rstrip()) if has_selection or not self.intelligent_backspace: TextEditBaseWidget.keyPressEvent(self, event) else: trailing_text = self.get_text('cursor', 'eol') if not leading_text.strip() \ and leading_length > len(self.indent_chars): if leading_length % len(self.indent_chars) == 0: self.unindent() else: TextEditBaseWidget.keyPressEvent(self, event) elif trailing_spaces and not trailing_text.strip(): self.remove_suffix(leading_text[-trailing_spaces:]) elif leading_text and trailing_text and \ leading_text[-1]+trailing_text[0] in ('()', '[]', '{}', '\'\'', '""'): cursor = self.textCursor() cursor.movePosition(QTextCursor.PreviousCharacter) cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor, 2) cursor.removeSelectedText() else: TextEditBaseWidget.keyPressEvent(self, event) if self.is_completion_widget_visible(): self.completion_text = self.completion_text[:-1] elif key == Qt.Key_Period: self.insert_text(text) if (self.is_python_like()) and not \ self.in_comment_or_string() and self.codecompletion_auto: # Enable auto-completion only if last token isn't a float last_obj = getobj(self.get_text('sol', 'cursor')) if last_obj and not last_obj.isdigit(): self.do_completion(automatic=True) elif key == Qt.Key_Home: self.stdkey_home(shift, ctrl) elif key == Qt.Key_End: # See Issue 495: on MacOS X, it is necessary to redefine this # basic action which should have been implemented natively self.stdkey_end(shift, ctrl) elif text == '(' and not has_selection: self.hide_completion_widget() self.handle_parentheses(text) elif (text in ('[', '{') and not has_selection and self.close_parentheses_enabled): s_trailing_text = self.get_text('cursor', 'eol').strip() if len(s_trailing_text) == 0 or \ s_trailing_text[0] in (',', ')', ']', '}'): self.insert_text({'{': '{}', '[': '[]'}[text]) cursor = self.textCursor() cursor.movePosition(QTextCursor.PreviousCharacter) self.setTextCursor(cursor) else: TextEditBaseWidget.keyPressEvent(self, event) elif key in (Qt.Key_QuoteDbl, Qt.Key_Apostrophe) and \ self.close_quotes_enabled: self.autoinsert_quotes(key) elif key in (Qt.Key_ParenRight, Qt.Key_BraceRight, Qt.Key_BracketRight)\ and not has_selection and self.close_parentheses_enabled \ and not self.textCursor().atBlockEnd(): cursor = self.textCursor() cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor) text = to_text_string(cursor.selectedText()) key_matches_next_char = ( text == {Qt.Key_ParenRight: ')', Qt.Key_BraceRight: '}', Qt.Key_BracketRight: ']'}[key] ) if (key_matches_next_char and not self.__unmatched_braces_in_line(cursor.block().text())): # overwrite an existing brace if all braces in line are matched cursor.clearSelection() self.setTextCursor(cursor) else: TextEditBaseWidget.keyPressEvent(self, event) elif key == Qt.Key_Colon and not has_selection \ and self.auto_unindent_enabled: leading_text = self.get_text('sol', 'cursor') if leading_text.lstrip() in ('else', 'finally'): ind = lambda txt: len(txt)-len(txt.lstrip()) prevtxt = to_text_string(self.textCursor( ).block().previous().text()) if ind(leading_text) == ind(prevtxt): self.unindent(force=True) TextEditBaseWidget.keyPressEvent(self, event) elif key == Qt.Key_Space and not shift and not ctrl \ and not has_selection and self.auto_unindent_enabled: leading_text = self.get_text('sol', 'cursor') if leading_text.lstrip() in ('elif', 'except'): ind = lambda txt: len(txt)-len(txt.lstrip()) prevtxt = to_text_string(self.textCursor( ).block().previous().text()) if ind(leading_text) == ind(prevtxt): self.unindent(force=True) TextEditBaseWidget.keyPressEvent(self, event) elif key == Qt.Key_Tab: # Important note: can't be called with a QShortcut because # of its singular role with respect to widget focus management if not has_selection and not self.tab_mode: self.intelligent_tab() else: # indent the selected text self.indent_or_replace() elif key == Qt.Key_Backtab: # Backtab, i.e. Shift+, could be treated as a QShortcut but # there is no point since can't (see above) if not has_selection and not self.tab_mode: self.intelligent_backtab() else: # indent the selected text self.unindent() else: TextEditBaseWidget.keyPressEvent(self, event) if self.is_completion_widget_visible() and text: self.completion_text += text def run_pygments_highlighter(self): """Run pygments highlighter.""" if isinstance(self.highlighter, sh.PygmentsSH): self.highlighter.make_charlist() def handle_parentheses(self, text): """Handle left and right parenthesis depending on editor config.""" position = self.get_position('cursor') rest = self.get_text('cursor', 'eol').rstrip() valid = not rest or rest[0] in (',', ')', ']', '}') if self.close_parentheses_enabled and valid: self.insert_text('()') cursor = self.textCursor() cursor.movePosition(QTextCursor.PreviousCharacter) self.setTextCursor(cursor) else: self.insert_text(text) if self.is_python_like() and self.get_text('sol', 'cursor') and \ self.calltips: self.sig_show_object_info.emit(position) def mouseMoveEvent(self, event): """Underline words when pressing """ if self.has_selected_text(): TextEditBaseWidget.mouseMoveEvent(self, event) return if self.go_to_definition_enabled and \ event.modifiers() & Qt.ControlModifier: text = self.get_word_at(event.pos()) if text and (self.is_python_like())\ and not sourcecode.is_keyword(to_text_string(text)): if not self.__cursor_changed: QApplication.setOverrideCursor( QCursor(Qt.PointingHandCursor)) self.__cursor_changed = True cursor = self.cursorForPosition(event.pos()) cursor.select(QTextCursor.WordUnderCursor) self.clear_extra_selections('ctrl_click') self.__highlight_selection('ctrl_click', cursor, update=True, foreground_color=self.ctrl_click_color, underline_color=self.ctrl_click_color, underline_style=QTextCharFormat.SingleUnderline) event.accept() return if self.__cursor_changed: QApplication.restoreOverrideCursor() self.__cursor_changed = False self.clear_extra_selections('ctrl_click') TextEditBaseWidget.mouseMoveEvent(self, event) def leaveEvent(self, event): """If cursor has not been restored yet, do it now""" if self.__cursor_changed: QApplication.restoreOverrideCursor() self.__cursor_changed = False self.clear_extra_selections('ctrl_click') TextEditBaseWidget.leaveEvent(self, event) @Slot() def go_to_definition_from_cursor(self, cursor=None): """Go to definition from cursor instance (QTextCursor)""" if not self.go_to_definition_enabled: return if cursor is None: cursor = self.textCursor() if self.in_comment_or_string(): return position = cursor.position() text = to_text_string(cursor.selectedText()) if len(text) == 0: cursor.select(QTextCursor.WordUnderCursor) text = to_text_string(cursor.selectedText()) if not text is None: self.go_to_definition.emit(position) def mousePressEvent(self, event): """Reimplement Qt method""" if event.button() == Qt.LeftButton\ and (event.modifiers() & Qt.ControlModifier): TextEditBaseWidget.mousePressEvent(self, event) cursor = self.cursorForPosition(event.pos()) self.go_to_definition_from_cursor(cursor) else: TextEditBaseWidget.mousePressEvent(self, event) def contextMenuEvent(self, event): """Reimplement Qt method""" nonempty_selection = self.has_selected_text() self.copy_action.setEnabled(nonempty_selection) self.cut_action.setEnabled(nonempty_selection) self.clear_all_output_action.setVisible(self.is_json() and \ nbformat is not None) self.ipynb_convert_action.setVisible(self.is_json() and \ nbformat is not None) self.run_cell_action.setVisible(self.is_python()) self.run_cell_and_advance_action.setVisible(self.is_python()) self.run_selection_action.setVisible(self.is_python()) self.re_run_last_cell_action.setVisible(self.is_python()) self.gotodef_action.setVisible(self.go_to_definition_enabled \ and self.is_python_like()) # Code duplication go_to_definition_from_cursor and mouse_move_event cursor = self.textCursor() text = to_text_string(cursor.selectedText()) if len(text) == 0: cursor.select(QTextCursor.WordUnderCursor) text = to_text_string(cursor.selectedText()) self.undo_action.setEnabled( self.document().isUndoAvailable()) self.redo_action.setEnabled( self.document().isRedoAvailable()) menu = self.menu if self.isReadOnly(): menu = self.readonly_menu menu.popup(event.globalPos()) event.accept() #------ Drag and drop def dragEnterEvent(self, event): """Reimplement Qt method Inform Qt about the types of data that the widget accepts""" if mimedata2url(event.mimeData()): # Let the parent widget handle this event.ignore() else: TextEditBaseWidget.dragEnterEvent(self, event) def dropEvent(self, event): """Reimplement Qt method Unpack dropped data and handle it""" if mimedata2url(event.mimeData()): # Let the parent widget handle this event.ignore() else: TextEditBaseWidget.dropEvent(self, event) #------ Paint event def paintEvent(self, event): """Overrides paint event to update the list of visible blocks""" self.update_visible_blocks(event) TextEditBaseWidget.paintEvent(self, event) self.painted.emit(event) def update_visible_blocks(self, event): """Update the list of visible blocks/lines position""" self.__visible_blocks[:] = [] block = self.firstVisibleBlock() blockNumber = block.blockNumber() top = int(self.blockBoundingGeometry(block).translated( self.contentOffset()).top()) bottom = top + int(self.blockBoundingRect(block).height()) ebottom_top = 0 ebottom_bottom = self.height() while block.isValid(): visible = bottom <= ebottom_bottom if not visible: break if block.isVisible(): self.__visible_blocks.append((top, blockNumber+1, block)) block = block.next() top = bottom bottom = top + int(self.blockBoundingRect(block).height()) blockNumber = block.blockNumber() def _draw_editor_cell_divider(self): """Draw a line on top of a define cell""" if self.supported_cell_language: cell_line_color = self.comment_color painter = QPainter(self.viewport()) pen = painter.pen() pen.setStyle(Qt.SolidLine) pen.setBrush(cell_line_color) painter.setPen(pen) for top, line_number, block in self.visible_blocks: if self.is_cell_separator(block): painter.drawLine(4, top, self.width(), top) @property def visible_blocks(self): """ Returns the list of visible blocks. Each element in the list is a tuple made up of the line top position, the line number (already 1 based), and the QTextBlock itself. :return: A list of tuple(top position, line number, block) :rtype: List of tuple(int, int, QtGui.QTextBlock) """ return self.__visible_blocks def is_editor(self): return True #=============================================================================== # CodeEditor's Printer #=============================================================================== #TODO: Implement the header and footer support class Printer(QPrinter): def __init__(self, mode=QPrinter.ScreenResolution, header_font=None): QPrinter.__init__(self, mode) self.setColorMode(QPrinter.Color) self.setPageOrder(QPrinter.FirstPageFirst) self.date = time.ctime() if header_font is not None: self.header_font = header_font # The following method is simply ignored by QPlainTextEdit # (this is a copy from QsciEditor's Printer) def formatPage(self, painter, drawing, area, pagenr): header = '%s - %s - Page %s' % (self.docName(), self.date, pagenr) painter.save() painter.setFont(self.header_font) painter.setPen(QColor(Qt.black)) if drawing: painter.drawText(area.right()-painter.fontMetrics().width(header), area.top()+painter.fontMetrics().ascent(), header) area.setTop(area.top()+painter.fontMetrics().height()+5) painter.restore() #=============================================================================== # Editor + Class browser test #=============================================================================== class TestWidget(QSplitter): def __init__(self, parent): QSplitter.__init__(self, parent) self.editor = CodeEditor(self) self.editor.setup_editor(linenumbers=True, markers=True, tab_mode=False, font=QFont("Courier New", 10), show_blanks=True, color_scheme='Zenburn') self.addWidget(self.editor) from spyder.widgets.editortools import OutlineExplorerWidget self.classtree = OutlineExplorerWidget(self) self.addWidget(self.classtree) self.classtree.edit_goto.connect( lambda _fn, line, word: self.editor.go_to_line(line, word)) self.setStretchFactor(0, 4) self.setStretchFactor(1, 1) self.setWindowIcon(ima.icon('spyder')) def load(self, filename): self.editor.set_text_from_file(filename) self.setWindowTitle("%s - %s (%s)" % (_("Editor"), osp.basename(filename), osp.dirname(filename))) self.classtree.set_current_editor(self.editor, filename, False, False) def test(fname): from spyder.utils.qthelpers import qapplication app = qapplication(test_time=5) win = TestWidget(None) win.show() win.load(fname) win.resize(900, 700) from spyder.utils.codeanalysis import (check_with_pyflakes, check_with_pep8) source_code = to_text_string(win.editor.toPlainText()) results = check_with_pyflakes(source_code, fname) + \ check_with_pep8(source_code, fname) win.editor.process_code_analysis(results) sys.exit(app.exec_()) if __name__ == '__main__': if len(sys.argv) > 1: fname = sys.argv[1] else: fname = __file__ test(fname) spyder-3.2.6/spyder/widgets/sourcecode/terminal.py0000664000175000017500000001033213026261006023111 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Terminal emulation tools""" import os class ANSIEscapeCodeHandler(object): """ANSI Escape sequences handler""" if os.name == 'nt': # Windows terminal colors: ANSI_COLORS = ( # Normal, Bright/Light ('#000000', '#808080'), # 0: black ('#800000', '#ff0000'), # 1: red ('#008000', '#00ff00'), # 2: green ('#808000', '#ffff00'), # 3: yellow ('#000080', '#0000ff'), # 4: blue ('#800080', '#ff00ff'), # 5: magenta ('#008080', '#00ffff'), # 6: cyan ('#c0c0c0', '#ffffff'), # 7: white ) elif os.name == 'mac': # Terminal.app colors: ANSI_COLORS = ( # Normal, Bright/Light ('#000000', '#818383'), # 0: black ('#C23621', '#FC391F'), # 1: red ('#25BC24', '#25BC24'), # 2: green ('#ADAD27', '#EAEC23'), # 3: yellow ('#492EE1', '#5833FF'), # 4: blue ('#D338D3', '#F935F8'), # 5: magenta ('#33BBC8', '#14F0F0'), # 6: cyan ('#CBCCCD', '#E9EBEB'), # 7: white ) else: # xterm colors: ANSI_COLORS = ( # Normal, Bright/Light ('#000000', '#7F7F7F'), # 0: black ('#CD0000', '#ff0000'), # 1: red ('#00CD00', '#00ff00'), # 2: green ('#CDCD00', '#ffff00'), # 3: yellow ('#0000EE', '#5C5CFF'), # 4: blue ('#CD00CD', '#ff00ff'), # 5: magenta ('#00CDCD', '#00ffff'), # 6: cyan ('#E5E5E5', '#ffffff'), # 7: white ) def __init__(self): self.intensity = 0 self.italic = None self.bold = None self.underline = None self.foreground_color = None self.background_color = None self.default_foreground_color = 30 self.default_background_color = 47 def set_code(self, code): assert isinstance(code, int) if code == 0: # Reset all settings self.reset() elif code == 1: # Text color intensity self.intensity = 1 # The following line is commented because most terminals won't # change the font weight, against ANSI standard recommendation: # self.bold = True elif code == 3: # Italic on self.italic = True elif code == 4: # Underline simple self.underline = True elif code == 22: # Normal text color intensity self.intensity = 0 self.bold = False elif code == 23: # No italic self.italic = False elif code == 24: # No underline self.underline = False elif code >= 30 and code <= 37: # Text color self.foreground_color = code elif code == 39: # Default text color self.foreground_color = self.default_foreground_color elif code >= 40 and code <= 47: # Background color self.background_color = code elif code == 49: # Default background color self.background_color = self.default_background_color self.set_style() def set_style(self): """ Set font style with the following attributes: 'foreground_color', 'background_color', 'italic', 'bold' and 'underline' """ raise NotImplementedError def reset(self): self.current_format = None self.intensity = 0 self.italic = False self.bold = False self.underline = False self.foreground_color = None self.background_color = None spyder-3.2.6/spyder/widgets/sourcecode/tests/0000775000175000017500000000000013225025007022067 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/widgets/sourcecode/tests/test_autocolon.py0000664000175000017500000000633213026261006025507 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for the automatic insertion of colons in the editor """ # Third party imports from qtpy.QtGui import QTextCursor import pytest # Local imports from spyder.utils.qthelpers import qapplication from spyder.widgets.sourcecode.codeeditor import CodeEditor # --- Fixtures # ----------------------------------------------------------------------------- def construct_editor(text): app = qapplication() editor = CodeEditor(parent=None) editor.setup_editor(language='Python') editor.set_text(text) cursor = editor.textCursor() cursor.movePosition(QTextCursor.End) editor.setTextCursor(cursor) return editor # --- Tests # ----------------------------------------------------------------------------- def test_no_auto_colon_after_simple_statement(): editor = construct_editor("x = 1") assert editor.autoinsert_colons() == False def test_auto_colon_after_if_statement(): editor = construct_editor("if x == 1") assert editor.autoinsert_colons() == True def test_no_auto_colon_if_not_at_end_of_line(): editor = construct_editor("if x == 1") cursor = editor.textCursor() cursor.movePosition(QTextCursor.Left) editor.setTextCursor(cursor) assert editor.autoinsert_colons() == False def test_no_auto_colon_if_unterminated_string(): editor = construct_editor("if x == '1") assert editor.autoinsert_colons() == False def test_no_auto_colon_in_comment(): editor = construct_editor("if x == 1 # comment") assert editor.autoinsert_colons() == False def test_no_auto_colon_if_already_ends_in_colon(): editor = construct_editor("if x == 1:") assert editor.autoinsert_colons() == False def test_no_auto_colon_if_ends_in_backslash(): editor = construct_editor("if x == 1 \\") assert editor.autoinsert_colons() == False def test_no_auto_colon_in_one_line_if_statement(): editor = construct_editor("if x < 0: x = 0") assert editor.autoinsert_colons() == False def test_auto_colon_even_if_colon_inside_brackets(): editor = construct_editor("if text[:-1].endswith('bla')") assert editor.autoinsert_colons() == True def test_no_auto_colon_in_listcomp_over_two_lines(): editor = construct_editor("ns = [ n for ns in range(10) \n if n < 5 ]") assert editor.autoinsert_colons() == False # --- Failing tests # ----------------------------------------------------------------------------- @pytest.mark.xfail def test_auto_colon_even_if_colon_inside_quotes(): editor = construct_editor("if text == ':'") assert editor.autoinsert_colons() == True @pytest.mark.xfail def test_no_auto_colon_in_listcomp_over_three_lines(): editor = construct_editor("ns = [ n \n for ns in range(10) \n if n < 5 ]") cursor = editor.textCursor() cursor.movePosition(QTextCursor.Up) cursor.movePosition(QTextCursor.EndOfLine) editor.setTextCursor(cursor) assert editor.autoinsert_colons() == False @pytest.mark.xfail def test_auto_colon_in_two_if_statements_on_one_line(): editor = construct_editor("if x < 0: x = 0; if x == 0") assert editor.autoinsert_colons() == True if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/widgets/sourcecode/tests/test_breakpoints.py0000664000175000017500000002205713224121062026024 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for breakpoints. """ try: from unittest.mock import Mock except ImportError: from mock import Mock # Python 2 # Third party imports import pytest from qtpy.QtGui import QTextCursor # Local imports from spyder import version_info from spyder.py3compat import to_text_string import spyder.widgets.sourcecode.codeeditor as codeeditor # --- Helper methods # ----------------------------------------------------------------------------- def reset_emits(editor): "Reset signal mocks." editor.linenumberarea.reset_mock() if version_info > (4, ): editor.sig_flags_changed.reset_mock() editor.breakpoints_changed.reset_mock() def editor_assert_helper(editor, block=None, bp=False, bpc=None, emits=True): """Run the tests for call to add_remove_breakpoint. Args: editor: CodeEditor instance. block: Block of text. bp: Is breakpoint active? bpc: Condition set for breakpoint. emits: Boolean to test if signals were emitted? """ data = block.userData() assert data.breakpoint == bp assert data.breakpoint_condition == bpc if emits: editor.linenumberarea.update.assert_called_with() if version_info > (4, ): editor.sig_flags_changed.emit.assert_called_with() editor.breakpoints_changed.emit.assert_called_with() else: editor.linenumberarea.update.assert_not_called() if version_info > (4, ): editor.sig_flags_changed.emit.assert_not_called() editor.breakpoints_changed.emit.assert_not_called() # --- Fixtures # ----------------------------------------------------------------------------- @pytest.fixture def code_editor_bot(qtbot): """Create code editor with default Python code.""" editor = codeeditor.CodeEditor(parent=None) indent_chars = ' ' * 4 tab_stop_width_spaces = 4 editor.setup_editor(language='Python', indent_chars=indent_chars, tab_stop_width_spaces=tab_stop_width_spaces) # Mock the screen updates and signal emits to test when they've been # called. editor.linenumberarea = Mock() if version_info > (4, ): editor.sig_flags_changed = Mock() else: editor.get_linenumberarea_width = Mock(return_value=1) editor.breakpoints_changed = Mock() text = ('def f1(a, b):\n' '"Double quote string."\n' '\n' # Blank line. ' c = a * b\n' ' return c\n' ) editor.set_text(text) return editor, qtbot # --- Tests # ----------------------------------------------------------------------------- def test_add_remove_breakpoint(code_editor_bot, mocker): """Test CodeEditor.add_remove_breakpoint().""" editor, qtbot = code_editor_bot arb = editor.add_remove_breakpoint mocker.patch.object(codeeditor.QInputDialog, 'getText') editor.go_to_line(1) block = editor.textCursor().block() # Breakpoints are only for Python-like files. editor.set_language(None) reset_emits(editor) arb() assert block # Block exists. assert not block.userData() # But user data not added to it. editor.linenumberarea.update.assert_not_called() if version_info > (4, ): editor.sig_flags_changed.emit.assert_not_called() editor.breakpoints_changed.emit.assert_not_called() # Reset language. editor.set_language('Python') # Test with default call on text line containing code. reset_emits(editor) arb() editor_assert_helper(editor, block, bp=True, bpc=None, emits=True) # Calling again removes breakpoint. reset_emits(editor) arb() editor_assert_helper(editor, block, bp=False, bpc=None, emits=True) # Test on blank line. reset_emits(editor) editor.go_to_line(3) block = editor.textCursor().block() arb() editor_assert_helper(editor, block, bp=False, bpc=None, emits=True) # Test adding condition on line containing code. reset_emits(editor) block = editor.document().findBlockByLineNumber(3) # Block is one less. arb(line_number=4, condition='a > 50') editor_assert_helper(editor, block, bp=True, bpc='a > 50', emits=True) # Call already set breakpoint with edit condition. reset_emits(editor) codeeditor.QInputDialog.getText.return_value = ('a == 42', False) arb(line_number=4, edit_condition=True) # Condition not changed because edit was cancelled. editor_assert_helper(editor, block, bp=True, bpc='a > 50', emits=False) # Condition changed. codeeditor.QInputDialog.getText.return_value = ('a == 42', True) # OK. reset_emits(editor) arb(line_number=4, edit_condition=True) editor_assert_helper(editor, block, bp=True, bpc='a == 42', emits=True) def test_add_remove_breakpoint_with_edit_condition(code_editor_bot, mocker): """Test add/remove breakpoint with edit_condition.""" # For issue 2179. editor, qtbot = code_editor_bot arb = editor.add_remove_breakpoint mocker.patch.object(codeeditor.QInputDialog, 'getText') linenumber = 5 block = editor.document().findBlockByLineNumber(linenumber - 1) # Call with edit_breakpoint on line that has never had a breakpoint set. # Once a line has a breakpoint set, it remains in userData(), which results # in a different behavior when calling the dialog box (tested below). reset_emits(editor) codeeditor.QInputDialog.getText.return_value = ('b == 1', False) arb(line_number=linenumber, edit_condition=True) data = block.userData() assert not data # Data isn't saved in this case. # Confirm line number area, scrollflag, and breakpoints not called. editor.linenumberarea.update.assert_not_called() if version_info > (4, ): editor.sig_flags_changed.emit.assert_not_called() editor.breakpoints_changed.emit.assert_not_called() # Call as if 'OK' button pressed. reset_emits(editor) codeeditor.QInputDialog.getText.return_value = ('b == 1', True) arb(line_number=linenumber, edit_condition=True) editor_assert_helper(editor, block, bp=True, bpc='b == 1', emits=True) # Call again with dialog cancelled - breakpoint is already active. reset_emits(editor) codeeditor.QInputDialog.getText.return_value = ('b == 9', False) arb(line_number=linenumber, edit_condition=True) # Breakpoint stays active, but signals aren't emitted. editor_assert_helper(editor, block, bp=True, bpc='b == 1', emits=False) # Remove breakpoint and condition. reset_emits(editor) arb(line_number=linenumber) editor_assert_helper(editor, block, bp=False, bpc=None, emits=True) # Call again with dialog cancelled. reset_emits(editor) codeeditor.QInputDialog.getText.return_value = ('b == 9', False) arb(line_number=linenumber, edit_condition=True) editor_assert_helper(editor, block, bp=False, bpc=None, emits=False) def test_get_breakpoints(code_editor_bot): """Test CodeEditor.get_breakpoints.""" editor, qtbot = code_editor_bot arb = editor.add_remove_breakpoint gb = editor.get_breakpoints assert(gb() == []) # Add breakpoints. bp = [(1, None), (3, None), (4, 'a > 1'), (5, 'c == 10')] editor.set_breakpoints(bp) assert(gb() == [(1, None), (4, 'a > 1'), (5, 'c == 10')]) # Only includes active breakpoints. Calling add_remove turns the # status to inactive, even with a change to condition. arb(line_number=1, condition='a < b') arb(line_number=4) assert(gb() == [(5, 'c == 10')]) def test_clear_breakpoints(code_editor_bot): """Test CodeEditor.clear_breakpoints.""" editor, qtbot = code_editor_bot assert len(editor.blockuserdata_list) == 0 bp = [(1, None), (4, None)] editor.set_breakpoints(bp) assert editor.get_breakpoints() == bp assert len(editor.blockuserdata_list) == 2 editor.clear_breakpoints() assert editor.get_breakpoints() == [] # Even though there is a 'del data' that would pop the item from the # list, the __del__ funcion isn't called. assert len(editor.blockuserdata_list) == 2 for data in editor.blockuserdata_list: assert not data.breakpoint def test_set_breakpoints(code_editor_bot): """Test CodeEditor.set_breakpoints.""" editor, qtbot = code_editor_bot editor.set_breakpoints([]) assert editor.get_breakpoints() == [] bp = [(1, 'a > b'), (4, None)] editor.set_breakpoints(bp) assert editor.get_breakpoints() == bp assert editor.blockuserdata_list[0].breakpoint bp = [(1, None), (5, 'c == 50')] editor.set_breakpoints(bp) assert editor.get_breakpoints() == bp assert editor.blockuserdata_list[0].breakpoint def test_update_breakpoints(code_editor_bot): """Test CodeEditor.update_breakpoints.""" editor, qtbot = code_editor_bot reset_emits(editor) editor.breakpoints_changed.emit.assert_not_called() # update_breakpoints is the slot for the blockCountChanged signal. editor.textCursor().insertBlock() editor.breakpoints_changed.emit.assert_called_with() if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/widgets/sourcecode/tests/__init__.py0000664000175000017500000000050213156676664024225 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Copyright (c) Spyder Project Contributors # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Tests.""" spyder-3.2.6/spyder/widgets/sourcecode/tests/test_autoindent.py0000664000175000017500000002364413211142273025663 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for the autoindent features """ # Third party imports from qtpy.QtGui import QTextCursor import pytest # Local imports from spyder.utils.qthelpers import qapplication from spyder.py3compat import to_text_string from spyder.widgets.sourcecode.codeeditor import CodeEditor # --- Fixtures # ----------------------------------------------------------------------------- def get_indent_fix(text, indent_chars=" " * 4, tab_stop_width_spaces=4, sol=False, forward=True, language='Python'): """Return text with last line's indentation fixed.""" app = qapplication() editor = CodeEditor(parent=None) editor.setup_editor(language=language, indent_chars=indent_chars, tab_stop_width_spaces=tab_stop_width_spaces) editor.set_text(text) cursor = editor.textCursor() cursor.movePosition(QTextCursor.End) if sol: lines = text.splitlines(True) repeat = len(lines[-1].lstrip()) cursor.movePosition(QTextCursor.Left, n=repeat) editor.setTextCursor(cursor) editor.fix_indent(forward=forward) return to_text_string(editor.toPlainText()) # --- Tests # ----------------------------------------------------------------------------- def test_simple_tuple(): text = get_indent_fix("this_tuple = (1, 2)\n") assert text == "this_tuple = (1, 2)\n" def test_def_with_newline(): text = get_indent_fix("\ndef function():\n") assert text == "\ndef function():\n ", repr(text) def test_def_with_indented_comment(): text = get_indent_fix("def function():\n # Comment\n") assert text == "def function():\n # Comment\n ", repr(text) def test_brackets_alone(): text = get_indent_fix("def function():\n print []\n") assert text == "def function():\n print []\n ", repr(text) def test_simple_def(): text = get_indent_fix("def function():\n") assert text == "def function():\n ", repr(text) def test_open_parenthesis(): # An open parenthesis with no item is followed by a hanging indent text = get_indent_fix("open_parenthesis(\n") assert text == "open_parenthesis(\n ", repr(text) def test_open_bracket(): # An open bracket with no item is followed by a hanging indent text = get_indent_fix("open_bracket[\n") assert text == "open_bracket[\n ", repr(text) def test_open_curly(): # An open curly bracket with no item is followed by a hanging indent text = get_indent_fix("open_curly{\n") assert text == "open_curly{\n ", repr(text) def test_align_on_parenthesis(): # An open parenthesis with one or more item is followed by an indent # up to the parenthesis. text = get_indent_fix("parenthesis_w_item = (1,\n") assert text == "parenthesis_w_item = (1,\n ", repr(text) def test_align_on_bracket(): # An open bracket with one or more item is followed by an indent # up to the parenthesis. text = get_indent_fix("bracket_w_item = (1,\n") assert text == "bracket_w_item = (1,\n ", repr(text) def test_align_on_curly(): # An open curly bracket with one or more item is followed by an indent # up to the parenthesis. text = get_indent_fix("curly_w_item = (1,\n") assert text == "curly_w_item = (1,\n ", repr(text) def test_keep_unindent(): # Keep line unindented if there is more than one line under the statement text = (" def foo(bar):\n" " generic = bar\n" " \n" " keep_unindent\n") correct_text = (" def foo(bar):\n" " generic = bar\n" " \n" " keep_unindent\n") text = get_indent_fix(text, sol=True) assert text == correct_text, repr(text) def test_keep_unindent_fix_indent(): # Keep line unindented but fix indent if not multiple of len(indent_chars) text = (" for x in range(n):\n" " increment += 1\n" " \n" " keep_unindent\n") correct_text = (" for x in range(n):\n" " increment += 1\n" " \n" " keep_unindent\n") text = get_indent_fix(text, sol=True) assert text == correct_text, repr(text) def test_keep_unindent_if_blank(): # Keep line unindented if return is pressed on a line which is both # blank and unindented. text = (" def f(x):\n" " return x\n" "\n" "") text = get_indent_fix(text) assert text == " def f(x):\n return x\n\n", repr(text) def test_first_line(): # Test fix_indent() when the cursor is on the first line. text = get_indent_fix("import numpy") assert text == "import numpy", repr(text) @pytest.mark.parametrize( "text_input, expected, test_text", [ ("tags = ['(a)', '(b)', '(c)']\n", "tags = ['(a)', '(b)', '(c)']\n", "test_commented_brackets"), ("s = a[(a['a'] == l) & (a['a'] == 1)]['a']\n", "s = a[(a['a'] == l) & (a['a'] == 1)]['a']\n", "test_balanced_brackets"), ("a = (a # some comment\n", "a = (a # some comment\n ", "test_inline_comment"), ("len(a) == 1\n", "len(a) == 1\n", "test_balanced_brackets_not_ending_in_bracket"), ("x = f(\n", "x = f(\n ", "test_short_open_bracket_not_hanging_indent"), ("def some_func():\n return 10\n", "def some_func():\n return 10\n", "test_return"), ("def some_func():\n returns = 10\n", "def some_func():\n returns = 10\n ", "test_return_not_keyword"), ("foo = 1 # Comment open parenthesis (\n", "foo = 1 # Comment open parenthesis (\n", "test_comment_with parenthesis"), ]) def test_indentation_with_spaces(text_input, expected, test_text): text = get_indent_fix(text_input) assert text == expected, test_text def test_def_with_unindented_comment(): text = get_indent_fix("def function():\n# Comment\n") assert text == "def function():\n# Comment\n ", repr(text) # --- Tabs tests # ----------------------------------------------------------------------------- @pytest.mark.parametrize("tab_stop_width_spaces", [1,2,3,4,5,6,7,8]) @pytest.mark.parametrize( "text_input, expected, test_text", [ ("this_tuple = (1, 2)\n", "this_tuple = (1, 2)\n", "simple tuple"), ("\ndef function():\n", "\ndef function():\n\t", "def with new line"), ("def function():\n\t# Comment\n", "def function():\n\t# Comment\n\t", "test with indented comment"), ("def function():\n\tprint []\n", "def function():\n\tprint []\n\t", "test brackets alone"), ("\nsome_long_name = {\n", "\nsome_long_name = {\n\t\t", "indentation after opening bracket"), ("def function():\n", "def function():\n\t", "test simple def"), ("open_parenthesis(\n", "open_parenthesis(\n\t\t", "open parenthesis"), ("tags = ['(a)', '(b)', '(c)']\n", "tags = ['(a)', '(b)', '(c)']\n", "test_commented_brackets"), ("s = a[(a['a'] == l) & (a['a'] == 1)]['a']\n", "s = a[(a['a'] == l) & (a['a'] == 1)]['a']\n", "test_balanced_brackets"), ("def some_func():\n\treturn 10\n", "def some_func():\n\treturn 10\n", "test_return"), ("def some_func():\n\treturns = 10\n", "def some_func():\n\treturns = 10\n\t", "test_return_not_keyword"), ("def function():\n# Comment\n", "def function():\n# Comment\n\t", "test_def_with_unindented_comment"), ]) def test_indentation_with_tabs(text_input, expected, test_text, tab_stop_width_spaces): text = get_indent_fix(text_input, indent_chars="\t", tab_stop_width_spaces=tab_stop_width_spaces) assert text == expected, test_text @pytest.mark.parametrize( "text_input, expected, tab_stop_width_spaces", [ ("print(\n)", "print(\n\t\t)", 1), ("print(\n)", "print(\n\t\t)", 2), ("print(\n)", "print(\n\t\t)", 3), ("print(\n)", "print(\n\t )", 4), ("print(\n)", "print(\n\t )", 5), ("print(\n)", "print(\n\t)", 6), ("print(\n)", "print(\n )", 7), ("print(\n)", "print(\n )", 8), ("a = (a # some comment\n", "a = (a # some comment\n\t ", 4), ]) def test_indentation_with_tabs_parenthesis(text_input, expected, tab_stop_width_spaces): """Simple parenthesis indentation test with different tab stop widths.""" text = get_indent_fix(text_input, indent_chars="\t", tab_stop_width_spaces=tab_stop_width_spaces) assert text == expected, tab_stop_width_spaces @pytest.mark.parametrize("tab_stop_width_spaces", [1,2,3,4,5,6,7,8]) @pytest.mark.parametrize( "text_input, expected, test_text", [ ("\tx = 1", "x = 1", "simple test"), ]) def test_unindentation_with_tabs(text_input, expected, test_text, tab_stop_width_spaces): text = get_indent_fix(text_input, indent_chars="\t", tab_stop_width_spaces=tab_stop_width_spaces, forward=False) assert text == expected, test_text # --- Simple indentation tests # ----------------------------------------------------------------------------- @pytest.mark.parametrize( "text_input, expected, test_text", [ ("hola\n", "hola\n", "witout indentation"), (" hola\n", " hola\n ", "some indentation"), ("\thola\n", "\thola\n\t", "tab indentation"), (" hola(\n", " hola(\n ", "line with parenthesis"), ]) def test_simple_indentation(text_input, expected, test_text,): # language None deactivate smart indentation text = get_indent_fix(text_input, language=None) assert text == expected, test_text if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/widgets/sourcecode/kill_ring.py0000664000175000017500000000732013026261006023253 0ustar carloscarlos00000000000000""" A generic Emacs-style kill ring, as well as a Qt-specific version. Copyright (c) 2001-2015, IPython Development Team Copyright (c) 2015-, Jupyter Development Team All rights reserved. """ # Third party imports from qtpy.QtCore import QObject from qtpy.QtGui import QTextCursor from qtpy.QtWidgets import QTextEdit, QPlainTextEdit # ---------------------------------------------------------------------------- # Classes # ---------------------------------------------------------------------------- class KillRing(object): """ A generic Emacs-style kill ring. """ def __init__(self): self.clear() def clear(self): """ Clears the kill ring. """ self._index = -1 self._ring = [] def kill(self, text): """ Adds some killed text to the ring. """ self._ring.append(text) def yank(self): """ Yank back the most recently killed text. Returns ------- A text string or None. """ self._index = len(self._ring) return self.rotate() def rotate(self): """ Rotate the kill ring, then yank back the new top. Returns ------- A text string or None. """ self._index -= 1 if self._index >= 0: return self._ring[self._index] return None class QtKillRing(QObject): """ A kill ring attached to Q[Plain]TextEdit. """ # ------------------------------------------------------------------------- # QtKillRing interface # ------------------------------------------------------------------------- def __init__(self, text_edit): """ Create a kill ring attached to the specified Qt text edit. """ assert isinstance(text_edit, (QTextEdit, QPlainTextEdit)) super(QtKillRing, self).__init__() self._ring = KillRing() self._prev_yank = None self._skip_cursor = False self._text_edit = text_edit text_edit.cursorPositionChanged.connect(self._cursor_position_changed) def clear(self): """ Clears the kill ring. """ self._ring.clear() self._prev_yank = None def kill(self, text): """ Adds some killed text to the ring. """ self._ring.kill(text) def kill_cursor(self, cursor): """ Kills the text selected by the give cursor. """ text = cursor.selectedText() if text: cursor.removeSelectedText() self.kill(text) def yank(self): """ Yank back the most recently killed text. """ text = self._ring.yank() if text: self._skip_cursor = True cursor = self._text_edit.textCursor() cursor.insertText(text) self._prev_yank = text def rotate(self): """ Rotate the kill ring, then yank back the new top. """ if self._prev_yank: text = self._ring.rotate() if text: self._skip_cursor = True cursor = self._text_edit.textCursor() cursor.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor, n=len(self._prev_yank)) cursor.insertText(text) self._prev_yank = text # ------------------------------------------------------------------------- # Protected interface # ------------------------------------------------------------------------- # ----- Signal handlers --------------------------------------------------- def _cursor_position_changed(self): if self._skip_cursor: self._skip_cursor = False else: self._prev_yank = None spyder-3.2.6/spyder/widgets/sourcecode/base.py0000664000175000017500000016115713224740762022237 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """QPlainTextEdit base class""" # pylint: disable=C0103 # pylint: disable=R0903 # pylint: disable=R0911 # pylint: disable=R0201 # Standard library imports import os import re import sys from collections import OrderedDict # Third party imports from qtpy.compat import to_qvariant from qtpy.QtCore import QEvent, QEventLoop, QPoint, Qt, Signal, Slot from qtpy.QtGui import (QClipboard, QColor, QFont, QMouseEvent, QPalette, QTextCharFormat, QTextFormat, QTextOption, QTextCursor) from qtpy.QtWidgets import (QAbstractItemView, QApplication, QListWidget, QListWidgetItem, QMainWindow, QPlainTextEdit, QTextEdit, QToolTip) # Local imports from spyder.config.gui import get_font from spyder.config.main import CONF from spyder.py3compat import PY3, str_lower, to_text_string from spyder.utils import icon_manager as ima from spyder.widgets.calltip import CallTipWidget from spyder.widgets.mixins import BaseEditMixin from spyder.widgets.sourcecode.terminal import ANSIEscapeCodeHandler def insert_text_to(cursor, text, fmt): """Helper to print text, taking into account backspaces""" while True: index = text.find(chr(8)) # backspace if index == -1: break cursor.insertText(text[:index], fmt) if cursor.positionInBlock() > 0: cursor.deletePreviousChar() text = text[index+1:] cursor.insertText(text, fmt) class CompletionWidget(QListWidget): """Completion list widget""" sig_show_completions = Signal(object) def __init__(self, parent, ancestor): QListWidget.__init__(self, ancestor) self.setWindowFlags(Qt.SubWindow | Qt.FramelessWindowHint) self.textedit = parent self.completion_list = None self.case_sensitive = False self.enter_select = None self.hide() self.itemActivated.connect(self.item_selected) def setup_appearance(self, size, font): self.resize(*size) self.setFont(font) def show_list(self, completion_list, automatic=True): types = [c[1] for c in completion_list] completion_list = [c[0] for c in completion_list] if len(completion_list) == 1 and not automatic: self.textedit.insert_completion(completion_list[0]) return self.completion_list = completion_list self.clear() icons_map = {'instance': 'attribute', 'statement': 'attribute', 'method': 'method', 'function': 'function', 'class': 'class', 'module': 'module'} self.type_list = types if any(types): for (c, t) in zip(completion_list, types): icon = icons_map.get(t, 'no_match') self.addItem(QListWidgetItem(ima.icon(icon), c)) else: self.addItems(completion_list) self.setCurrentRow(0) QApplication.processEvents(QEventLoop.ExcludeUserInputEvents) self.show() self.setFocus() self.raise_() # Retrieving current screen height desktop = QApplication.desktop() srect = desktop.availableGeometry(desktop.screenNumber(self)) screen_right = srect.right() screen_bottom = srect.bottom() point = self.textedit.cursorRect().bottomRight() point.setX(point.x()+self.textedit.get_linenumberarea_width()) point = self.textedit.mapToGlobal(point) # Computing completion widget and its parent right positions comp_right = point.x()+self.width() ancestor = self.parent() if ancestor is None: anc_right = screen_right else: anc_right = min([ancestor.x()+ancestor.width(), screen_right]) # Moving completion widget to the left # if there is not enough space to the right if comp_right > anc_right: point.setX(point.x()-self.width()) # Computing completion widget and its parent bottom positions comp_bottom = point.y()+self.height() ancestor = self.parent() if ancestor is None: anc_bottom = screen_bottom else: anc_bottom = min([ancestor.y()+ancestor.height(), screen_bottom]) # Moving completion widget above if there is not enough space below x_position = point.x() if comp_bottom > anc_bottom: point = self.textedit.cursorRect().topRight() point = self.textedit.mapToGlobal(point) point.setX(x_position) point.setY(point.y()-self.height()) if ancestor is not None: # Useful only if we set parent to 'ancestor' in __init__ point = ancestor.mapFromGlobal(point) self.move(point) if to_text_string(self.textedit.completion_text): # When initialized, if completion text is not empty, we need # to update the displayed list: self.update_current() # signal used for testing self.sig_show_completions.emit(completion_list) def hide(self): QListWidget.hide(self) self.textedit.setFocus() def keyPressEvent(self, event): text, key = event.text(), event.key() alt = event.modifiers() & Qt.AltModifier shift = event.modifiers() & Qt.ShiftModifier ctrl = event.modifiers() & Qt.ControlModifier modifier = shift or ctrl or alt if (key in (Qt.Key_Return, Qt.Key_Enter) and self.enter_select) \ or key == Qt.Key_Tab: self.item_selected() elif key in (Qt.Key_Return, Qt.Key_Enter, Qt.Key_Left, Qt.Key_Right) or text in ('.', ':'): self.hide() self.textedit.keyPressEvent(event) elif key in (Qt.Key_Up, Qt.Key_Down, Qt.Key_PageUp, Qt.Key_PageDown, Qt.Key_Home, Qt.Key_End, Qt.Key_CapsLock) and not modifier: QListWidget.keyPressEvent(self, event) elif len(text) or key == Qt.Key_Backspace: self.textedit.keyPressEvent(event) self.update_current() elif modifier: self.textedit.keyPressEvent(event) else: self.hide() QListWidget.keyPressEvent(self, event) def update_current(self): completion_text = to_text_string(self.textedit.completion_text) if completion_text: for row, completion in enumerate(self.completion_list): if not self.case_sensitive: print(completion_text) # spyder: test-skip completion = completion.lower() completion_text = completion_text.lower() if completion.startswith(completion_text): self.setCurrentRow(row) self.scrollTo(self.currentIndex(), QAbstractItemView.PositionAtTop) break else: self.hide() else: self.hide() def focusOutEvent(self, event): event.ignore() # Don't hide it on Mac when main window loses focus because # keyboard input is lost # Fixes Issue 1318 if sys.platform == "darwin": if event.reason() != Qt.ActiveWindowFocusReason: self.hide() else: self.hide() def item_selected(self, item=None): if item is None: item = self.currentItem() self.textedit.insert_completion( to_text_string(item.text()) ) self.hide() class TextEditBaseWidget(QPlainTextEdit, BaseEditMixin): """Text edit base widget""" BRACE_MATCHING_SCOPE = ('sof', 'eof') cell_separators = None focus_in = Signal() zoom_in = Signal() zoom_out = Signal() zoom_reset = Signal() focus_changed = Signal() sig_eol_chars_changed = Signal(str) def __init__(self, parent=None): QPlainTextEdit.__init__(self, parent) BaseEditMixin.__init__(self) self.setAttribute(Qt.WA_DeleteOnClose) self.extra_selections_dict = OrderedDict() self.textChanged.connect(self.changed) self.cursorPositionChanged.connect(self.cursor_position_changed) self.indent_chars = " "*4 self.tab_stop_width_spaces = 4 # Code completion / calltips if parent is not None: mainwin = parent while not isinstance(mainwin, QMainWindow): mainwin = mainwin.parent() if mainwin is None: break if mainwin is not None: parent = mainwin self.completion_widget = CompletionWidget(self, parent) self.codecompletion_auto = False self.codecompletion_case = True self.codecompletion_enter = False self.completion_text = "" self.setup_completion() self.calltip_widget = CallTipWidget(self, hide_timer_on=False) self.calltips = True self.calltip_position = None self.has_cell_separators = False self.highlight_current_cell_enabled = False # The color values may be overridden by the syntax highlighter # Highlight current line color self.currentline_color = QColor(Qt.red).lighter(190) self.currentcell_color = QColor(Qt.red).lighter(194) # Brace matching self.bracepos = None self.matched_p_color = QColor(Qt.green) self.unmatched_p_color = QColor(Qt.red) self.last_cursor_cell = None def setup_completion(self): size = CONF.get('main', 'completion/size') font = get_font() self.completion_widget.setup_appearance(size, font) def set_indent_chars(self, indent_chars): self.indent_chars = indent_chars def set_tab_stop_width_spaces(self, tab_stop_width_spaces): self.tab_stop_width_spaces = tab_stop_width_spaces self.update_tab_stop_width_spaces() def update_tab_stop_width_spaces(self): self.setTabStopWidth(self.fontMetrics().width( '9' * self.tab_stop_width_spaces)) def set_palette(self, background, foreground): """ Set text editor palette colors: background color and caret (text cursor) color """ palette = QPalette() palette.setColor(QPalette.Base, background) palette.setColor(QPalette.Text, foreground) self.setPalette(palette) # Set the right background color when changing color schemes # or creating new Editor windows. This seems to be a Qt bug. # Fixes Issue 2028 if sys.platform == 'darwin': if self.objectName(): style = "QPlainTextEdit#%s {background: %s; color: %s;}" % \ (self.objectName(), background.name(), foreground.name()) self.setStyleSheet(style) #------Extra selections def extra_selection_length(self, key): selection = self.get_extra_selections(key) if selection: cursor = self.extra_selections_dict[key][0].cursor selection_length = cursor.selectionEnd() - cursor.selectionStart() return selection_length else: return 0 def get_extra_selections(self, key): return self.extra_selections_dict.get(key, []) def set_extra_selections(self, key, extra_selections): self.extra_selections_dict[key] = extra_selections self.extra_selections_dict = \ OrderedDict(sorted(self.extra_selections_dict.items(), key=lambda s: self.extra_selection_length(s[0]), reverse=True)) def update_extra_selections(self): extra_selections = [] # Python 3 compatibility (weird): current line has to be # highlighted first if 'current_cell' in self.extra_selections_dict: extra_selections.extend(self.extra_selections_dict['current_cell']) if 'current_line' in self.extra_selections_dict: extra_selections.extend(self.extra_selections_dict['current_line']) for key, extra in list(self.extra_selections_dict.items()): if not (key == 'current_line' or key == 'current_cell'): extra_selections.extend(extra) self.setExtraSelections(extra_selections) def clear_extra_selections(self, key): self.extra_selections_dict[key] = [] self.update_extra_selections() def changed(self): """Emit changed signal""" self.modificationChanged.emit(self.document().isModified()) #------Highlight current line def highlight_current_line(self): """Highlight current line""" selection = QTextEdit.ExtraSelection() selection.format.setProperty(QTextFormat.FullWidthSelection, to_qvariant(True)) selection.format.setBackground(self.currentline_color) selection.cursor = self.textCursor() selection.cursor.clearSelection() self.set_extra_selections('current_line', [selection]) self.update_extra_selections() def unhighlight_current_line(self): """Unhighlight current line""" self.clear_extra_selections('current_line') #------Highlight current cell def highlight_current_cell(self): """Highlight current cell""" if self.cell_separators is None or \ not self.highlight_current_cell_enabled: return selection = QTextEdit.ExtraSelection() selection.format.setProperty(QTextFormat.FullWidthSelection, to_qvariant(True)) selection.format.setBackground(self.currentcell_color) selection.cursor, whole_file_selected, whole_screen_selected =\ self.select_current_cell_in_visible_portion() if whole_file_selected: self.clear_extra_selections('current_cell') elif whole_screen_selected: if self.has_cell_separators: self.set_extra_selections('current_cell', [selection]) self.update_extra_selections() else: self.clear_extra_selections('current_cell') else: self.set_extra_selections('current_cell', [selection]) self.update_extra_selections() def unhighlight_current_cell(self): """Unhighlight current cell""" self.clear_extra_selections('current_cell') #------Brace matching def find_brace_match(self, position, brace, forward): start_pos, end_pos = self.BRACE_MATCHING_SCOPE if forward: bracemap = {'(': ')', '[': ']', '{': '}'} text = self.get_text(position, end_pos) i_start_open = 1 i_start_close = 1 else: bracemap = {')': '(', ']': '[', '}': '{'} text = self.get_text(start_pos, position) i_start_open = len(text)-1 i_start_close = len(text)-1 while True: if forward: i_close = text.find(bracemap[brace], i_start_close) else: i_close = text.rfind(bracemap[brace], 0, i_start_close+1) if i_close > -1: if forward: i_start_close = i_close+1 i_open = text.find(brace, i_start_open, i_close) else: i_start_close = i_close-1 i_open = text.rfind(brace, i_close, i_start_open+1) if i_open > -1: if forward: i_start_open = i_open+1 else: i_start_open = i_open-1 else: # found matching brace if forward: return position+i_close else: return position-(len(text)-i_close) else: # no matching brace return def __highlight(self, positions, color=None, cancel=False): if cancel: self.clear_extra_selections('brace_matching') return extra_selections = [] for position in positions: if position > self.get_position('eof'): return selection = QTextEdit.ExtraSelection() selection.format.setBackground(color) selection.cursor = self.textCursor() selection.cursor.clearSelection() selection.cursor.setPosition(position) selection.cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor) extra_selections.append(selection) self.set_extra_selections('brace_matching', extra_selections) self.update_extra_selections() 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) #-----Widget setup and options def set_codecompletion_auto(self, state): """Set code completion state""" self.codecompletion_auto = state def set_codecompletion_case(self, state): """Case sensitive completion""" self.codecompletion_case = state self.completion_widget.case_sensitive = state def set_codecompletion_enter(self, state): """Enable Enter key to select completion""" self.codecompletion_enter = state self.completion_widget.enter_select = state def set_calltips(self, state): """Set calltips state""" self.calltips = state def set_wrap_mode(self, mode=None): """ Set wrap mode Valid *mode* values: None, 'word', 'character' """ if mode == 'word': wrap_mode = QTextOption.WrapAtWordBoundaryOrAnywhere elif mode == 'character': wrap_mode = QTextOption.WrapAnywhere else: wrap_mode = QTextOption.NoWrap self.setWordWrapMode(wrap_mode) #------Reimplementing Qt methods @Slot() def copy(self): """ Reimplement Qt method Copy text to clipboard with correct EOL chars """ if self.get_selected_text(): QApplication.clipboard().setText(self.get_selected_text()) def toPlainText(self): """ Reimplement Qt method Fix PyQt4 bug on Windows and Python 3 """ # Fix what appears to be a PyQt4 bug when getting file # contents under Windows and PY3. This bug leads to # corruptions when saving files with certain combinations # of unicode chars on them (like the one attached on # Issue 1546) if os.name == 'nt' and PY3: text = self.get_text('sof', 'eof') return text.replace('\u2028', '\n').replace('\u2029', '\n')\ .replace('\u0085', '\n') else: return super(TextEditBaseWidget, self).toPlainText() def keyPressEvent(self, event): text, key = event.text(), event.key() ctrl = event.modifiers() & Qt.ControlModifier meta = event.modifiers() & Qt.MetaModifier # Use our own copy method for {Ctrl,Cmd}+C to avoid Qt # copying text in HTML (See Issue 2285) if (ctrl or meta) and key == Qt.Key_C: self.copy() else: super(TextEditBaseWidget, self).keyPressEvent(event) #------Text: get, set, ... def get_selection_as_executable_code(self): """Return selected text as a processed text, to be executable in a Python/IPython interpreter""" ls = self.get_line_separator() _indent = lambda line: len(line)-len(line.lstrip()) line_from, line_to = self.get_selection_bounds() text = self.get_selected_text() if not text: return lines = text.split(ls) if len(lines) > 1: # Multiline selection -> eventually fixing indentation original_indent = _indent(self.get_text_line(line_from)) text = (" "*(original_indent-_indent(lines[0])))+text # If there is a common indent to all lines, find it. # Moving from bottom line to top line ensures that blank # lines inherit the indent of the line *below* it, # which is the desired behavior. min_indent = 999 current_indent = 0 lines = text.split(ls) for i in range(len(lines)-1, -1, -1): line = lines[i] if line.strip(): current_indent = _indent(line) min_indent = min(current_indent, min_indent) else: lines[i] = ' ' * current_indent if min_indent: lines = [line[min_indent:] for line in lines] # Remove any leading whitespace or comment lines # since they confuse the reserved word detector that follows below while lines: first_line = lines[0].lstrip() if first_line == '' or first_line[0] == '#': lines.pop(0) else: break # Add an EOL character after indentation blocks that start with some # Python reserved words, so that it gets evaluated automatically # by the console varname = re.compile('[a-zA-Z0-9_]*') # matches valid variable names maybe = False nextexcept = () for n, line in enumerate(lines): if not _indent(line): word = varname.match(line).group() if maybe and word not in nextexcept: lines[n-1] += ls maybe = False if word: if word in ('def', 'for', 'while', 'with', 'class'): maybe = True nextexcept = () elif word == 'if': maybe = True nextexcept = ('elif', 'else') elif word == 'try': maybe = True nextexcept = ('except', 'finally') if maybe: if lines[-1].strip() == '': lines[-1] += ls else: lines.append(ls) return ls.join(lines) def __exec_cell(self): init_cursor = QTextCursor(self.textCursor()) start_pos, end_pos = self.__save_selection() cursor, whole_file_selected = self.select_current_cell() if not whole_file_selected: self.setTextCursor(cursor) text = self.get_selection_as_executable_code() self.last_cursor_cell = init_cursor self.__restore_selection(start_pos, end_pos) if text is not None: text = text.rstrip() return text def get_cell_as_executable_code(self): """Return cell contents as executable code""" return self.__exec_cell() def get_last_cell_as_executable_code(self): text = None if self.last_cursor_cell: self.setTextCursor(self.last_cursor_cell) self.highlight_current_cell() text = self.__exec_cell() return text 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()) if self.cell_separators is None: return False else: return text.lstrip().startswith(self.cell_separators) def select_current_cell(self): """Select cell under cursor cell = group of lines separated by CELL_SEPARATORS returns the textCursor and a boolean indicating if the entire file is selected""" cursor = self.textCursor() cursor.movePosition(QTextCursor.StartOfBlock) cur_pos = prev_pos = cursor.position() # Moving to the next line that is not a separator, if we are # exactly at one of them while self.is_cell_separator(cursor): cursor.movePosition(QTextCursor.NextBlock) prev_pos = cur_pos cur_pos = cursor.position() if cur_pos == prev_pos: return cursor, False prev_pos = cur_pos # If not, move backwards to find the previous separator while not self.is_cell_separator(cursor): cursor.movePosition(QTextCursor.PreviousBlock) prev_pos = cur_pos cur_pos = cursor.position() if cur_pos == prev_pos: if self.is_cell_separator(cursor): return cursor, False else: break cursor.setPosition(prev_pos) cell_at_file_start = cursor.atStart() # Once we find it (or reach the beginning of the file) # move to the next separator (or the end of the file) # so we can grab the cell contents while not self.is_cell_separator(cursor): cursor.movePosition(QTextCursor.NextBlock, QTextCursor.KeepAnchor) cur_pos = cursor.position() if cur_pos == prev_pos: cursor.movePosition(QTextCursor.EndOfBlock, QTextCursor.KeepAnchor) break prev_pos = cur_pos cell_at_file_end = cursor.atEnd() return cursor, cell_at_file_start and cell_at_file_end def select_current_cell_in_visible_portion(self): """Select cell under cursor in the visible portion of the file cell = group of lines separated by CELL_SEPARATORS returns -the textCursor -a boolean indicating if the entire file is selected -a boolean indicating if the entire visible portion of the file is selected""" cursor = self.textCursor() cursor.movePosition(QTextCursor.StartOfBlock) cur_pos = prev_pos = cursor.position() beg_pos = self.cursorForPosition(QPoint(0, 0)).position() bottom_right = QPoint(self.viewport().width() - 1, self.viewport().height() - 1) end_pos = self.cursorForPosition(bottom_right).position() # Moving to the next line that is not a separator, if we are # exactly at one of them while self.is_cell_separator(cursor): cursor.movePosition(QTextCursor.NextBlock) prev_pos = cur_pos cur_pos = cursor.position() if cur_pos == prev_pos: return cursor, False, False prev_pos = cur_pos # If not, move backwards to find the previous separator while not self.is_cell_separator(cursor)\ and cursor.position() >= beg_pos: cursor.movePosition(QTextCursor.PreviousBlock) prev_pos = cur_pos cur_pos = cursor.position() if cur_pos == prev_pos: if self.is_cell_separator(cursor): return cursor, False, False else: break cell_at_screen_start = cursor.position() <= beg_pos cursor.setPosition(prev_pos) cell_at_file_start = cursor.atStart() # Selecting cell header if not cell_at_file_start: cursor.movePosition(QTextCursor.PreviousBlock) cursor.movePosition(QTextCursor.NextBlock, QTextCursor.KeepAnchor) # Once we find it (or reach the beginning of the file) # move to the next separator (or the end of the file) # so we can grab the cell contents while not self.is_cell_separator(cursor)\ and cursor.position() <= end_pos: cursor.movePosition(QTextCursor.NextBlock, QTextCursor.KeepAnchor) cur_pos = cursor.position() if cur_pos == prev_pos: cursor.movePosition(QTextCursor.EndOfBlock, QTextCursor.KeepAnchor) break prev_pos = cur_pos cell_at_file_end = cursor.atEnd() cell_at_screen_end = cursor.position() >= end_pos return cursor,\ cell_at_file_start and cell_at_file_end,\ cell_at_screen_start and cell_at_screen_end def go_to_next_cell(self): """Go to the next cell of lines""" cursor = self.textCursor() cursor.movePosition(QTextCursor.NextBlock) cur_pos = prev_pos = cursor.position() while not self.is_cell_separator(cursor): # Moving to the next code cell cursor.movePosition(QTextCursor.NextBlock) prev_pos = cur_pos cur_pos = cursor.position() if cur_pos == prev_pos: return self.setTextCursor(cursor) def go_to_previous_cell(self): """Go to the previous cell of lines""" cursor = self.textCursor() cur_pos = prev_pos = cursor.position() if self.is_cell_separator(cursor): # Move to the previous cell cursor.movePosition(QTextCursor.PreviousBlock) cur_pos = prev_pos = cursor.position() while not self.is_cell_separator(cursor): # Move to the previous cell or the beginning of the current cell cursor.movePosition(QTextCursor.PreviousBlock) prev_pos = cur_pos cur_pos = cursor.position() if cur_pos == prev_pos: return self.setTextCursor(cursor) def get_line_count(self): """Return document total line number""" return self.blockCount() def __save_selection(self): """Save current cursor selection and return position bounds""" cursor = self.textCursor() return cursor.selectionStart(), cursor.selectionEnd() def __restore_selection(self, start_pos, end_pos): """Restore cursor selection from position bounds""" cursor = self.textCursor() cursor.setPosition(start_pos) cursor.setPosition(end_pos, QTextCursor.KeepAnchor) self.setTextCursor(cursor) def __duplicate_line_or_selection(self, after_current_line=True): """Duplicate current line or selected text""" cursor = self.textCursor() cursor.beginEditBlock() start_pos, end_pos = self.__save_selection() if to_text_string(cursor.selectedText()): cursor.setPosition(end_pos) # Check if end_pos is at the start of a block: if so, starting # changes from the previous block cursor.movePosition(QTextCursor.StartOfBlock, QTextCursor.KeepAnchor) if not to_text_string(cursor.selectedText()): cursor.movePosition(QTextCursor.PreviousBlock) end_pos = cursor.position() cursor.setPosition(start_pos) cursor.movePosition(QTextCursor.StartOfBlock) while cursor.position() <= end_pos: cursor.movePosition(QTextCursor.EndOfBlock, QTextCursor.KeepAnchor) if cursor.atEnd(): cursor_temp = QTextCursor(cursor) cursor_temp.clearSelection() cursor_temp.insertText(self.get_line_separator()) break cursor.movePosition(QTextCursor.NextBlock, QTextCursor.KeepAnchor) text = cursor.selectedText() cursor.clearSelection() if not after_current_line: # Moving cursor before current line/selected text cursor.setPosition(start_pos) cursor.movePosition(QTextCursor.StartOfBlock) start_pos += len(text) end_pos += len(text) cursor.insertText(text) cursor.endEditBlock() self.setTextCursor(cursor) self.__restore_selection(start_pos, end_pos) def duplicate_line(self): """ Duplicate current line or selected text Paste the duplicated text *after* the current line/selected text """ self.__duplicate_line_or_selection(after_current_line=True) def copy_line(self): """ Copy current line or selected text Paste the duplicated text *before* the current line/selected text """ self.__duplicate_line_or_selection(after_current_line=False) def __move_line_or_selection(self, after_current_line=True): """Move current line or selected text""" cursor = self.textCursor() cursor.beginEditBlock() start_pos, end_pos = self.__save_selection() last_line = False # ------ Select text # Get selection start location cursor.setPosition(start_pos) cursor.movePosition(QTextCursor.StartOfBlock) start_pos = cursor.position() # Get selection end location cursor.setPosition(end_pos) if not cursor.atBlockStart() or end_pos == start_pos: cursor.movePosition(QTextCursor.EndOfBlock) cursor.movePosition(QTextCursor.NextBlock) end_pos = cursor.position() # Check if selection ends on the last line of the document if cursor.atEnd(): if not cursor.atBlockStart() or end_pos == start_pos: last_line = True # ------ Stop if at document boundary cursor.setPosition(start_pos) if cursor.atStart() and not after_current_line: # Stop if selection is already at top of the file while moving up cursor.endEditBlock() self.setTextCursor(cursor) self.__restore_selection(start_pos, end_pos) return cursor.setPosition(end_pos, QTextCursor.KeepAnchor) if last_line and after_current_line: # Stop if selection is already at end of the file while moving down cursor.endEditBlock() self.setTextCursor(cursor) self.__restore_selection(start_pos, end_pos) return # ------ Move text sel_text = to_text_string(cursor.selectedText()) cursor.removeSelectedText() if after_current_line: # Shift selection down text = to_text_string(cursor.block().text()) sel_text = os.linesep + sel_text[0:-1] # Move linesep at the start cursor.movePosition(QTextCursor.EndOfBlock) start_pos += len(text)+1 end_pos += len(text) if not cursor.atEnd(): end_pos += 1 else: # Shift selection up if last_line: # Remove the last linesep and add it to the selected text cursor.deletePreviousChar() sel_text = sel_text + os.linesep cursor.movePosition(QTextCursor.StartOfBlock) end_pos += 1 else: cursor.movePosition(QTextCursor.PreviousBlock) text = to_text_string(cursor.block().text()) start_pos -= len(text)+1 end_pos -= len(text)+1 cursor.insertText(sel_text) cursor.endEditBlock() self.setTextCursor(cursor) self.__restore_selection(start_pos, end_pos) def move_line_up(self): """Move up current line or selected text""" self.__move_line_or_selection(after_current_line=False) def move_line_down(self): """Move down current line or selected text""" self.__move_line_or_selection(after_current_line=True) def extend_selection_to_complete_lines(self): """Extend current selection to complete lines""" cursor = self.textCursor() start_pos, end_pos = cursor.selectionStart(), cursor.selectionEnd() cursor.setPosition(start_pos) cursor.setPosition(end_pos, QTextCursor.KeepAnchor) if cursor.atBlockStart(): cursor.movePosition(QTextCursor.PreviousBlock, QTextCursor.KeepAnchor) cursor.movePosition(QTextCursor.EndOfBlock, QTextCursor.KeepAnchor) self.setTextCursor(cursor) def delete_line(self): """Delete current line""" cursor = self.textCursor() if self.has_selected_text(): self.extend_selection_to_complete_lines() start_pos, end_pos = cursor.selectionStart(), cursor.selectionEnd() cursor.setPosition(start_pos) else: start_pos = end_pos = cursor.position() cursor.beginEditBlock() cursor.setPosition(start_pos) cursor.movePosition(QTextCursor.StartOfBlock) while cursor.position() <= end_pos: cursor.movePosition(QTextCursor.EndOfBlock, QTextCursor.KeepAnchor) if cursor.atEnd(): break cursor.movePosition(QTextCursor.NextBlock, QTextCursor.KeepAnchor) cursor.removeSelectedText() cursor.endEditBlock() self.ensureCursorVisible() #------Code completion / Calltips def hide_tooltip_if_necessary(self, key): """Hide calltip when necessary""" try: calltip_char = self.get_character(self.calltip_position) before = self.is_cursor_before(self.calltip_position, char_offset=1) other = key in (Qt.Key_ParenRight, Qt.Key_Period, Qt.Key_Tab) if calltip_char not in ('?', '(') or before or other: QToolTip.hideText() except (IndexError, TypeError): QToolTip.hideText() def show_completion_widget(self, textlist, automatic=True): """Show completion widget""" self.completion_widget.show_list(textlist, automatic=automatic) def hide_completion_widget(self): """Hide completion widget""" self.completion_widget.hide() def show_completion_list(self, completions, completion_text="", automatic=True): """Display the possible completions""" if not completions: return if not isinstance(completions[0], tuple): completions = [(c, '') for c in completions] if len(completions) == 1 and completions[0][0] == completion_text: return self.completion_text = completion_text # Sorting completion list (entries starting with underscore are # put at the end of the list): underscore = set([(comp, t) for (comp, t) in completions if comp.startswith('_')]) completions = sorted(set(completions) - underscore, key=lambda x: str_lower(x[0])) completions += sorted(underscore, key=lambda x: str_lower(x[0])) self.show_completion_widget(completions, automatic=automatic) def select_completion_list(self): """Completion list is active, Enter was just pressed""" self.completion_widget.item_selected() def insert_completion(self, text): if text: cursor = self.textCursor() cursor.movePosition(QTextCursor.PreviousCharacter, QTextCursor.KeepAnchor, len(self.completion_text)) cursor.removeSelectedText() self.insert_text(text) def is_completion_widget_visible(self): """Return True is completion list widget is visible""" return self.completion_widget.isVisible() #------Standard keys def stdkey_clear(self): if not self.has_selected_text(): self.moveCursor(QTextCursor.NextCharacter, QTextCursor.KeepAnchor) self.remove_selected_text() def stdkey_backspace(self): if not self.has_selected_text(): self.moveCursor(QTextCursor.PreviousCharacter, QTextCursor.KeepAnchor) self.remove_selected_text() def __get_move_mode(self, shift): return QTextCursor.KeepAnchor if shift else QTextCursor.MoveAnchor def stdkey_up(self, shift): self.moveCursor(QTextCursor.Up, self.__get_move_mode(shift)) def stdkey_down(self, shift): self.moveCursor(QTextCursor.Down, self.__get_move_mode(shift)) def stdkey_tab(self): self.insert_text(self.indent_chars) def stdkey_home(self, shift, ctrl, prompt_pos=None): """Smart HOME feature: cursor is first moved at indentation position, then at the start of the line""" move_mode = self.__get_move_mode(shift) if ctrl: self.moveCursor(QTextCursor.Start, move_mode) else: cursor = self.textCursor() if prompt_pos is None: start_position = self.get_position('sol') else: start_position = self.get_position(prompt_pos) text = self.get_text(start_position, 'eol') indent_pos = start_position+len(text)-len(text.lstrip()) if cursor.position() != indent_pos: cursor.setPosition(indent_pos, move_mode) else: cursor.setPosition(start_position, move_mode) self.setTextCursor(cursor) def stdkey_end(self, shift, ctrl): move_mode = self.__get_move_mode(shift) if ctrl: self.moveCursor(QTextCursor.End, move_mode) else: self.moveCursor(QTextCursor.EndOfBlock, move_mode) def stdkey_pageup(self): pass def stdkey_pagedown(self): pass def stdkey_escape(self): pass #----Qt Events def mousePressEvent(self, event): """Reimplement Qt method""" if sys.platform.startswith('linux') and event.button() == Qt.MidButton: self.calltip_widget.hide() self.setFocus() event = QMouseEvent(QEvent.MouseButtonPress, event.pos(), Qt.LeftButton, Qt.LeftButton, Qt.NoModifier) QPlainTextEdit.mousePressEvent(self, event) QPlainTextEdit.mouseReleaseEvent(self, event) # Send selection text to clipboard to be able to use # the paste method and avoid the strange Issue 1445 # NOTE: This issue seems a focusing problem but it # seems really hard to track mode_clip = QClipboard.Clipboard mode_sel = QClipboard.Selection text_clip = QApplication.clipboard().text(mode=mode_clip) text_sel = QApplication.clipboard().text(mode=mode_sel) QApplication.clipboard().setText(text_sel, mode=mode_clip) self.paste() QApplication.clipboard().setText(text_clip, mode=mode_clip) else: self.calltip_widget.hide() QPlainTextEdit.mousePressEvent(self, event) def focusInEvent(self, event): """Reimplemented to handle focus""" self.focus_changed.emit() self.focus_in.emit() self.highlight_current_cell() QPlainTextEdit.focusInEvent(self, event) def focusOutEvent(self, event): """Reimplemented to handle focus""" self.focus_changed.emit() QPlainTextEdit.focusOutEvent(self, event) def wheelEvent(self, event): """Reimplemented to emit zoom in/out signals when Ctrl is pressed""" # This feature is disabled on MacOS, see Issue 1510 if sys.platform != 'darwin': if event.modifiers() & Qt.ControlModifier: if hasattr(event, 'angleDelta'): if event.angleDelta().y() < 0: self.zoom_out.emit() elif event.angleDelta().y() > 0: self.zoom_in.emit() elif hasattr(event, 'delta'): if event.delta() < 0: self.zoom_out.emit() elif event.delta() > 0: self.zoom_in.emit() return QPlainTextEdit.wheelEvent(self, event) self.highlight_current_cell() class QtANSIEscapeCodeHandler(ANSIEscapeCodeHandler): def __init__(self): ANSIEscapeCodeHandler.__init__(self) self.base_format = None self.current_format = None def set_light_background(self, state): if state: self.default_foreground_color = 30 self.default_background_color = 47 else: self.default_foreground_color = 37 self.default_background_color = 40 def set_base_format(self, base_format): self.base_format = base_format def get_format(self): return self.current_format def set_style(self): """ Set font style with the following attributes: 'foreground_color', 'background_color', 'italic', 'bold' and 'underline' """ if self.current_format is None: assert self.base_format is not None self.current_format = QTextCharFormat(self.base_format) # Foreground color if self.foreground_color is None: qcolor = self.base_format.foreground() else: cstr = self.ANSI_COLORS[self.foreground_color-30][self.intensity] qcolor = QColor(cstr) self.current_format.setForeground(qcolor) # Background color if self.background_color is None: qcolor = self.base_format.background() else: cstr = self.ANSI_COLORS[self.background_color-40][self.intensity] qcolor = QColor(cstr) self.current_format.setBackground(qcolor) font = self.current_format.font() # Italic if self.italic is None: italic = self.base_format.fontItalic() else: italic = self.italic font.setItalic(italic) # Bold if self.bold is None: bold = self.base_format.font().bold() else: bold = self.bold font.setBold(bold) # Underline if self.underline is None: underline = self.base_format.font().underline() else: underline = self.underline font.setUnderline(underline) self.current_format.setFont(font) def inverse_color(color): color.setHsv(color.hue(), color.saturation(), 255-color.value()) class ConsoleFontStyle(object): def __init__(self, foregroundcolor, backgroundcolor, bold, italic, underline): self.foregroundcolor = foregroundcolor self.backgroundcolor = backgroundcolor self.bold = bold self.italic = italic self.underline = underline self.format = None def apply_style(self, font, light_background, is_default): self.format = QTextCharFormat() self.format.setFont(font) foreground = QColor(self.foregroundcolor) if not light_background and is_default: inverse_color(foreground) self.format.setForeground(foreground) background = QColor(self.backgroundcolor) if not light_background: inverse_color(background) self.format.setBackground(background) font = self.format.font() font.setBold(self.bold) font.setItalic(self.italic) font.setUnderline(self.underline) self.format.setFont(font) class ConsoleBaseWidget(TextEditBaseWidget): """Console base widget""" BRACE_MATCHING_SCOPE = ('sol', 'eol') COLOR_PATTERN = re.compile('\x01?\x1b\[(.*?)m\x02?') exception_occurred = Signal(str, bool) userListActivated = Signal(int, str) completion_widget_activated = Signal(str) def __init__(self, parent=None): TextEditBaseWidget.__init__(self, parent) self.light_background = True self.setMaximumBlockCount(300) # ANSI escape code handler self.ansi_handler = QtANSIEscapeCodeHandler() # Disable undo/redo (nonsense for a console widget...): self.setUndoRedoEnabled(False) self.userListActivated.connect(lambda user_id, text: self.completion_widget_activated.emit(text)) self.default_style = ConsoleFontStyle( foregroundcolor=0x000000, backgroundcolor=0xFFFFFF, bold=False, italic=False, underline=False) self.error_style = ConsoleFontStyle( foregroundcolor=0xFF0000, backgroundcolor=0xFFFFFF, bold=False, italic=False, underline=False) self.traceback_link_style = ConsoleFontStyle( foregroundcolor=0x0000FF, backgroundcolor=0xFFFFFF, bold=True, italic=False, underline=True) self.prompt_style = ConsoleFontStyle( foregroundcolor=0x00AA00, backgroundcolor=0xFFFFFF, bold=True, italic=False, underline=False) self.font_styles = (self.default_style, self.error_style, self.traceback_link_style, self.prompt_style) self.set_pythonshell_font() self.setMouseTracking(True) def set_light_background(self, state): self.light_background = state if state: self.set_palette(background=QColor(Qt.white), foreground=QColor(Qt.darkGray)) else: self.set_palette(background=QColor(Qt.black), foreground=QColor(Qt.lightGray)) self.ansi_handler.set_light_background(state) self.set_pythonshell_font() def set_selection(self, start, end): cursor = self.textCursor() cursor.setPosition(start) cursor.setPosition(end, QTextCursor.KeepAnchor) self.setTextCursor(cursor) def truncate_selection(self, position_from): """Unselect read-only parts in shell, like prompt""" position_from = self.get_position(position_from) cursor = self.textCursor() start, end = cursor.selectionStart(), cursor.selectionEnd() if start < end: start = max([position_from, start]) else: end = max([position_from, end]) self.set_selection(start, end) def restrict_cursor_position(self, position_from, position_to): """In shell, avoid editing text except between prompt and EOF""" position_from = self.get_position(position_from) position_to = self.get_position(position_to) cursor = self.textCursor() cursor_position = cursor.position() if cursor_position < position_from or cursor_position > position_to: self.set_cursor_position(position_to) #------Python shell def insert_text(self, text): """Reimplement TextEditBaseWidget method""" # Eventually this maybe should wrap to insert_text_to if # backspace-handling is required self.textCursor().insertText(text, self.default_style.format) def paste(self): """Reimplement Qt method""" if self.has_selected_text(): self.remove_selected_text() self.insert_text(QApplication.clipboard().text()) def append_text_to_shell(self, text, error, prompt): """ Append text to Python shell In a way, this method overrides the method 'insert_text' when text is inserted at the end of the text widget for a Python shell Handles error messages and show blue underlined links Handles ANSI color sequences Handles ANSI FF sequence """ cursor = self.textCursor() cursor.movePosition(QTextCursor.End) if '\r' in text: # replace \r\n with \n text = text.replace('\r\n', '\n') text = text.replace('\r', '\n') while True: index = text.find(chr(12)) if index == -1: break text = text[index+1:] self.clear() if error: is_traceback = False for text in text.splitlines(True): if text.startswith(' File') \ and not text.startswith(' File "<'): is_traceback = True # Show error links in blue underlined text cursor.insertText(' ', self.default_style.format) cursor.insertText(text[2:], self.traceback_link_style.format) else: # Show error/warning messages in red cursor.insertText(text, self.error_style.format) self.exception_occurred.emit(text, is_traceback) elif prompt: # Show prompt in green insert_text_to(cursor, text, self.prompt_style.format) else: # Show other outputs in black last_end = 0 for match in self.COLOR_PATTERN.finditer(text): insert_text_to(cursor, text[last_end:match.start()], self.default_style.format) last_end = match.end() try: for code in [int(_c) for _c in match.group(1).split(';')]: self.ansi_handler.set_code(code) except ValueError: pass self.default_style.format = self.ansi_handler.get_format() insert_text_to(cursor, text[last_end:], self.default_style.format) # # Slower alternative: # segments = self.COLOR_PATTERN.split(text) # cursor.insertText(segments.pop(0), self.default_style.format) # if segments: # for ansi_tags, text in zip(segments[::2], segments[1::2]): # for ansi_tag in ansi_tags.split(';'): # self.ansi_handler.set_code(int(ansi_tag)) # self.default_style.format = self.ansi_handler.get_format() # cursor.insertText(text, self.default_style.format) self.set_cursor_position('eof') self.setCurrentCharFormat(self.default_style.format) def set_pythonshell_font(self, font=None): """Python Shell only""" if font is None: font = QFont() for style in self.font_styles: style.apply_style(font=font, light_background=self.light_background, is_default=style is self.default_style) self.ansi_handler.set_base_format(self.default_style.format) spyder-3.2.6/spyder/widgets/sourcecode/__init__.py0000664000175000017500000000045713026261006023044 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ spyder.widgets.sourcecode ========================= Source code related widgets (code editor, console) based exclusively on Qt """ spyder-3.2.6/spyder/requirements.py0000664000175000017500000000376413026261006020233 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Module checking Spyder installation requirements""" import sys import os.path as osp from distutils.version import LooseVersion def show_warning(message): """Show warning using Tkinter if available""" try: # If Tkinter is installed (highly probable), showing an error pop-up import Tkinter, tkMessageBox root = Tkinter.Tk() root.withdraw() tkMessageBox.showerror("Spyder", message) except ImportError: pass raise RuntimeError(message) def check_path(): """Check sys.path: is Spyder properly installed?""" dirname = osp.abspath(osp.join(osp.dirname(__file__), osp.pardir)) if dirname not in sys.path: show_warning("Spyder must be installed properly " "(e.g. from source: 'python setup.py install'),\n" "or directory '%s' must be in PYTHONPATH " "environment variable." % dirname) def check_qt(): """Check Qt binding requirements""" qt_infos = dict(pyqt5=("PyQt5", "5.2"), pyqt=("PyQt4", "4.6")) try: import qtpy package_name, required_ver = qt_infos[qtpy.API] actual_ver = qtpy.PYQT_VERSION if LooseVersion(actual_ver) < LooseVersion(required_ver): show_warning("Please check Spyder installation requirements:\n" "%s %s+ is required (found v%s)." % (package_name, required_ver, actual_ver)) except ImportError: show_warning("Failed to import qtpy.\n" "Please check Spyder installation requirements:\n\n" "qtpy 1.1.0+ and either\n" "%s %s+ or\n" "%s %s+\n\n" "are required to run Spyder." % (qt_infos['pyqt5'] + qt_infos['pyqt'])) spyder-3.2.6/spyder/config/0000775000175000017500000000000013225025007016371 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/config/user.py0000664000175000017500000004307213224121062017724 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ This module provides user configuration file management features for Spyder It's based on the ConfigParser module (present in the standard library). """ from __future__ import print_function # Std imports import ast import os import re import os.path as osp import shutil import time # Local imports from spyder.config.base import (get_conf_path, get_home_dir, get_module_source_path, TEST) from spyder.utils.programs import check_version from spyder.py3compat import configparser as cp from spyder.py3compat import PY2, is_text_string, to_text_string # Std imports for Python 2 if PY2: import codecs #============================================================================== # Auxiliary classes #============================================================================== class NoDefault: pass #============================================================================== # Defaults class #============================================================================== class DefaultsConfig(cp.ConfigParser): """ Class used to save defaults to a file and as base class for UserConfig """ def __init__(self, name, subfolder): if PY2: cp.ConfigParser.__init__(self) else: cp.ConfigParser.__init__(self, interpolation=None) self.name = name self.subfolder = subfolder 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" % cp.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 _set(self, section, option, value, verbose): """ Private set method """ if not self.has_section(section): self.add_section( section ) if not is_text_string(value): value = repr( value ) if verbose: print('%s[ %s ] = %s' % (section, option, value)) # spyder: test-skip cp.ConfigParser.set(self, section, option, value) def _save(self): """ Save config into the associated .ini file """ # Don't save settings if we are on testing mode if TEST: return # See Issue 1086 and 1242 for background on why this # method contains all the exception handling. fname = self.filename() def _write_file(fname): if PY2: # Python 2 with codecs.open(fname, 'w', encoding='utf-8') as configfile: self._write(configfile) else: # Python 3 with open(fname, 'w', encoding='utf-8') as configfile: self.write(configfile) try: # the "easy" way _write_file(fname) except IOError: try: # the "delete and sleep" way if osp.isfile(fname): os.remove(fname) time.sleep(0.05) _write_file(fname) except Exception as e: print("Failed to write user configuration file.") # spyder: test-skip print("Please submit a bug report.") # spyder: test-skip raise(e) def filename(self): """Defines the name of the configuration file to use.""" # Needs to be done this way to be used by the project config. # To fix on a later PR self._filename = getattr(self, '_filename', None) self._root_path = getattr(self, '_root_path', None) if self._filename is None and self._root_path is None: return self._filename_global() else: return self._filename_projects() def _filename_projects(self): """Create a .ini filename located in the current project directory. This .ini files stores the specific project preferences for each project created with spyder. """ return osp.join(self._root_path, self._filename) def _filename_global(self): """Create a .ini filename located in user home directory. This .ini files stores the global spyder preferences. """ if self.subfolder is None: config_file = osp.join(get_home_dir(), '.%s.ini' % self.name) return config_file else: folder = get_conf_path() # Save defaults in a "defaults" dir of .spyder2 to not pollute it if 'defaults' in self.name: folder = osp.join(folder, 'defaults') if not osp.isdir(folder): os.mkdir(folder) config_file = osp.join(folder, '%s.ini' % self.name) return config_file def set_defaults(self, defaults): for section, options in defaults: for option in options: new_value = options[ option ] self._set(section, option, new_value, False) #============================================================================== # User config class #============================================================================== class UserConfig(DefaultsConfig): """ UserConfig class, based on ConfigParser name: name of the config defaults: dictionnary containing options *or* list of tuples (section_name, options) version: version of the configuration file (X.Y.Z format) subfolder: configuration file will be saved in %home%/subfolder/%name%.ini Note that 'get' and 'set' arguments number and type differ from the overriden methods """ DEFAULT_SECTION_NAME = 'main' def __init__(self, name, defaults=None, load=True, version=None, subfolder=None, backup=False, raw_mode=False, remove_obsolete=False): DefaultsConfig.__init__(self, name, subfolder) self.raw = 1 if raw_mode else 0 if (version is not None) and (re.match('^(\d+).(\d+).(\d+)$', version) is None): raise ValueError("Version number %r is incorrect - must be in X.Y.Z format" % version) if isinstance(defaults, dict): defaults = [ (self.DEFAULT_SECTION_NAME, defaults) ] self.defaults = defaults if defaults is not None: self.reset_to_defaults(save=False) fname = self.filename() if backup: try: shutil.copyfile(fname, "%s.bak" % fname) except IOError: pass if load: # If config file already exists, it overrides Default options: self.load_from_ini() old_ver = self.get_version(version) _major = lambda _t: _t[:_t.find('.')] _minor = lambda _t: _t[:_t.rfind('.')] # Save new defaults self._save_new_defaults(defaults, version, subfolder) # Updating defaults only if major/minor version is different if _minor(version) != _minor(old_ver): if backup: try: shutil.copyfile(fname, "%s-%s.bak" % (fname, old_ver)) except IOError: pass if check_version(old_ver, '2.4.0', '<'): self.reset_to_defaults(save=False) else: self._update_defaults(defaults, old_ver) # Remove deprecated options if major version has changed if remove_obsolete or _major(version) != _major(old_ver): self._remove_deprecated_options(old_ver) # Set new version number self.set_version(version, save=False) if defaults is None: # If no defaults are defined, set .ini file settings as default self.set_as_defaults() def get_version(self, version='0.0.0'): """Return configuration (not application!) version""" return self.get(self.DEFAULT_SECTION_NAME, 'version', version) def set_version(self, version='0.0.0', save=True): """Set configuration (not application!) version""" self.set(self.DEFAULT_SECTION_NAME, 'version', version, save=save) def load_from_ini(self): """ Load config from the associated .ini file """ try: if PY2: # Python 2 fname = self.filename() if osp.isfile(fname): try: with codecs.open(fname, encoding='utf-8') as configfile: self.readfp(configfile) except IOError: print("Failed reading file", fname) # spyder: test-skip else: # Python 3 self.read(self.filename(), encoding='utf-8') except cp.MissingSectionHeaderError: print("Warning: File contains no section headers.") # spyder: test-skip def _load_old_defaults(self, old_version): """Read old defaults""" old_defaults = cp.ConfigParser() if check_version(old_version, '3.0.0', '<='): path = get_module_source_path('spyder') else: path = osp.dirname(self.filename()) path = osp.join(path, 'defaults') old_defaults.read(osp.join(path, 'defaults-'+old_version+'.ini')) return old_defaults def _save_new_defaults(self, defaults, new_version, subfolder): """Save new defaults""" new_defaults = DefaultsConfig(name='defaults-'+new_version, subfolder=subfolder) if not osp.isfile(new_defaults.filename()): new_defaults.set_defaults(defaults) new_defaults._save() def _update_defaults(self, defaults, old_version, verbose=False): """Update defaults after a change in version""" old_defaults = self._load_old_defaults(old_version) for section, options in defaults: for option in options: new_value = options[ option ] try: old_value = old_defaults.get(section, option) except (cp.NoSectionError, cp.NoOptionError): old_value = None if old_value is None or \ to_text_string(new_value) != old_value: self._set(section, option, new_value, verbose) def _remove_deprecated_options(self, old_version): """ Remove options which are present in the .ini file but not in defaults """ old_defaults = self._load_old_defaults(old_version) for section in old_defaults.sections(): for option, _ in old_defaults.items(section, raw=self.raw): if self.get_default(section, option) is NoDefault: try: self.remove_option(section, option) if len(self.items(section, raw=self.raw)) == 0: self.remove_section(section) except cp.NoSectionError: self.remove_section(section) def cleanup(self): """ Remove .ini file associated to config """ os.remove(self.filename()) def set_as_defaults(self): """ Set defaults from the current config """ self.defaults = [] for section in self.sections(): secdict = {} for option, value in self.items(section, raw=self.raw): secdict[option] = value self.defaults.append( (section, secdict) ) def reset_to_defaults(self, save=True, verbose=False, section=None): """ Reset config to Default values """ for sec, options in self.defaults: if section == None or section == sec: for option in options: value = options[ option ] self._set(sec, option, value, verbose) if save: self._save() def _check_section_option(self, section, option): """ Private method to check section and option types """ if section is None: section = self.DEFAULT_SECTION_NAME elif not is_text_string(section): raise RuntimeError("Argument 'section' must be a string") if not is_text_string(option): raise RuntimeError("Argument 'option' must be a string") return section def get_default(self, section, option): """ Get Default value for a given (section, option) -> useful for type checking in 'get' method """ section = self._check_section_option(section, option) for sec, options in self.defaults: if sec == section: if option in options: return options[ option ] else: return NoDefault def get(self, section, option, default=NoDefault): """ Get an option section=None: attribute a default section name default: default value (if not specified, an exception will be raised if option doesn't exist) """ section = self._check_section_option(section, option) if not self.has_section(section): if default is NoDefault: raise cp.NoSectionError(section) else: self.add_section(section) if not self.has_option(section, option): if default is NoDefault: raise cp.NoOptionError(option, section) else: self.set(section, option, default) return default value = cp.ConfigParser.get(self, section, option, raw=self.raw) # Use type of default_value to parse value correctly default_value = self.get_default(section, option) if isinstance(default_value, bool): value = ast.literal_eval(value) elif isinstance(default_value, float): value = float(value) elif isinstance(default_value, int): value = int(value) elif is_text_string(default_value): if PY2: try: value = value.decode('utf-8') try: # Some str config values expect to be eval after decoding new_value = ast.literal_eval(value) if is_text_string(new_value): value = new_value except (SyntaxError, ValueError): pass except (UnicodeEncodeError, UnicodeDecodeError): pass else: try: # lists, tuples, ... value = ast.literal_eval(value) except (SyntaxError, ValueError): pass return value def set_default(self, section, option, default_value): """ Set Default value for a given (section, option) -> called when a new (section, option) is set and no default exists """ section = self._check_section_option(section, option) for sec, options in self.defaults: if sec == section: options[ option ] = default_value def set(self, section, option, value, verbose=False, save=True): """ Set an option section=None: attribute a default section name """ section = self._check_section_option(section, option) default_value = self.get_default(section, option) if default_value is NoDefault: # This let us save correctly string value options with # no config default that contain non-ascii chars in # Python 2 if PY2 and is_text_string(value): value = repr(value) default_value = value self.set_default(section, option, default_value) if isinstance(default_value, bool): value = bool(value) elif isinstance(default_value, float): value = float(value) elif isinstance(default_value, int): value = int(value) elif not is_text_string(default_value): value = repr(value) self._set(section, option, value, verbose) if save: self._save() def remove_section(self, section): cp.ConfigParser.remove_section(self, section) self._save() def remove_option(self, section, option): cp.ConfigParser.remove_option(self, section, option) self._save() spyder-3.2.6/spyder/config/gui.py0000664000175000017500000001205313156676663017557 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Spyder GUI-related configuration management (for non-GUI configuration, see spyder/config/base.py) Important note regarding shortcuts: For compatibility with QWERTZ keyboards, one must avoid using the following shortcuts: Ctrl + Alt + Q, W, F, G, Y, X, C, V, B, N """ # Standard library imports from collections import namedtuple # Third party imports from qtpy.QtCore import Qt from qtpy.QtGui import QFont, QFontDatabase, QKeySequence from qtpy.QtWidgets import QShortcut # Local imports from spyder.config.main import CONF from spyder.config.user import NoDefault from spyder.py3compat import to_text_string from spyder.utils import syntaxhighlighters as sh # To save metadata about widget shortcuts (needed to build our # preferences page) Shortcut = namedtuple('Shortcut', 'data') def font_is_installed(font): """Check if font is installed""" return [fam for fam in QFontDatabase().families() if to_text_string(fam)==font] def get_family(families): """Return the first installed font family in family list""" if not isinstance(families, list): families = [ families ] for family in families: if font_is_installed(family): return family else: print("Warning: None of the following fonts is installed: %r" % families) # spyder: test-skip return QFont().family() FONT_CACHE = {} def get_font(section='main', option='font', font_size_delta=0): """Get console font properties depending on OS and user options""" font = FONT_CACHE.get((section, option)) if font is None: families = CONF.get(section, option+"/family", None) if families is None: return QFont() family = get_family(families) weight = QFont.Normal italic = CONF.get(section, option+'/italic', False) if CONF.get(section, option+'/bold', False): weight = QFont.Bold size = CONF.get(section, option+'/size', 9) + font_size_delta font = QFont(family, size, weight) font.setItalic(italic) FONT_CACHE[(section, option)] = font size = CONF.get(section, option+'/size', 9) + font_size_delta font.setPointSize(size) return font def set_font(font, section='main', option='font'): """Set font""" CONF.set(section, option+'/family', to_text_string(font.family())) CONF.set(section, option+'/size', float(font.pointSize())) CONF.set(section, option+'/italic', int(font.italic())) CONF.set(section, option+'/bold', int(font.bold())) FONT_CACHE[(section, option)] = font def get_shortcut(context, name): """Get keyboard shortcut (key sequence string)""" return CONF.get('shortcuts', '%s/%s' % (context, name)) def set_shortcut(context, name, keystr): """Set keyboard shortcut (key sequence string)""" CONF.set('shortcuts', '%s/%s' % (context, name), keystr) def fixed_shortcut(keystr, parent, action): """ DEPRECATED: This function will be removed in Spyder 4.0 Define a fixed shortcut according to a keysequence string """ sc = QShortcut(QKeySequence(keystr), parent, action) sc.setContext(Qt.WidgetWithChildrenShortcut) return sc def config_shortcut(action, context, name, parent): """ Create a Shortcut namedtuple for a widget The data contained in this tuple will be registered in our shortcuts preferences page """ keystr = get_shortcut(context, name) qsc = QShortcut(QKeySequence(keystr), parent, action) qsc.setContext(Qt.WidgetWithChildrenShortcut) sc = Shortcut(data=(qsc, context, name)) return sc def iter_shortcuts(): """Iterate over keyboard shortcuts""" for option in CONF.options('shortcuts'): context, name = option.split("/", 1) yield context, name, get_shortcut(context, name) def reset_shortcuts(): """Reset keyboard shortcuts to default values""" CONF.reset_to_defaults(section='shortcuts') def get_color_scheme(name): """Get syntax color scheme""" color_scheme = {} for key in sh.COLOR_SCHEME_KEYS: color_scheme[key] = CONF.get("color_schemes", "%s/%s" % (name, key)) return color_scheme def set_color_scheme(name, color_scheme, replace=True): """Set syntax color scheme""" section = "color_schemes" names = CONF.get("color_schemes", "names", []) for key in sh.COLOR_SCHEME_KEYS: option = "%s/%s" % (name, key) value = CONF.get(section, option, default=None) if value is None or replace or name not in names: CONF.set(section, option, color_scheme[key]) names.append(to_text_string(name)) CONF.set(section, "names", sorted(list(set(names)))) def set_default_color_scheme(name, replace=True): """Reset color scheme to default values""" assert name in sh.COLOR_SCHEME_NAMES set_color_scheme(name, sh.get_color_scheme(name), replace=replace) for _name in sh.COLOR_SCHEME_NAMES: set_default_color_scheme(_name, replace=False) spyder-3.2.6/spyder/config/fonts.py0000664000175000017500000000276313211142272020103 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Spyder font variables """ import os import sys from spyder.config.utils import is_ubuntu #============================================================================== # Main fonts #============================================================================== # Rich text fonts SANS_SERIF = ['Sans Serif', 'DejaVu Sans', 'Bitstream Vera Sans', 'Bitstream Charter', 'Lucida Grande', 'MS Shell Dlg 2', 'Calibri', 'Verdana', 'Geneva', 'Lucid', 'Arial', 'Helvetica', 'Avant Garde', 'Times', 'sans-serif'] # Plan text fonts MONOSPACE = ['Monospace', 'DejaVu Sans Mono', 'Consolas', 'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono', 'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal'] #============================================================================== # Adjust font size per OS #============================================================================== if sys.platform == 'darwin': MONOSPACE = ['Menlo'] + MONOSPACE BIG = MEDIUM = SMALL = 12 elif os.name == 'nt': BIG = MEDIUM = 10 SMALL = 9 elif is_ubuntu(): SANS_SERIF = ['Ubuntu'] + SANS_SERIF MONOSPACE = ['Ubuntu Mono'] + MONOSPACE BIG = MEDIUM = SMALL = 11 else: BIG = 10 MEDIUM = SMALL = 9 DEFAULT_SMALL_DELTA = SMALL - MEDIUM DEFAULT_LARGE_DELTA = SMALL - BIG spyder-3.2.6/spyder/config/main.py0000775000175000017500000007225513224740762017720 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Spyder configuration options Note: Leave this file free of Qt related imports, so that it can be used to quickly load a user config file """ import os import sys import os.path as osp # Local import from spyder.config.base import (CHECK_ALL, EXCLUDED_NAMES, get_home_dir, SUBFOLDER, TEST) from spyder.config.fonts import BIG, MEDIUM, MONOSPACE, SANS_SERIF from spyder.config.user import UserConfig from spyder.config.utils import IMPORT_EXT from spyder.utils import codeanalysis #============================================================================== # Main constants #============================================================================== # Find in files exclude patterns EXCLUDE_PATTERNS = [r'\.pyc$|\.pyo$|\.git'] # Extensions that should be visible in Spyder's file/project explorers SHOW_EXT = ['.py', '.ipynb', '.txt', '.dat', '.pdf', '.png', '.svg'] # Extensions supported by Spyder (Editor or Variable explorer) USEFUL_EXT = IMPORT_EXT + SHOW_EXT # Name filters for file/project explorers (excluding files without extension) NAME_FILTERS = ['README', 'INSTALL', 'LICENSE', 'CHANGELOG'] + \ ['*' + _ext for _ext in USEFUL_EXT if _ext] # Port used to detect if there is a running instance and to communicate with # it to open external files OPEN_FILES_PORT = 21128 # OS Specific WIN = os.name == 'nt' MAC = sys.platform == 'darwin' CTRL = "Meta" if MAC else "Ctrl" # Run cell shortcuts if sys.platform == 'darwin': RUN_CELL_SHORTCUT = 'Meta+Return' else: RUN_CELL_SHORTCUT = 'Ctrl+Return' RE_RUN_LAST_CELL_SHORTCUT = 'Alt+Return' RUN_CELL_AND_ADVANCE_SHORTCUT = 'Shift+Return' # ============================================================================= # Defaults # ============================================================================= DEFAULTS = [ ('main', { 'icon_theme': 'spyder 3', 'single_instance': True, 'open_files_port': OPEN_FILES_PORT, 'tear_off_menus': False, 'normal_screen_resolution': True, 'high_dpi_scaling': False, 'high_dpi_custom_scale_factor': False, 'high_dpi_custom_scale_factors': '1.5', 'vertical_dockwidget_titlebars': False, 'vertical_tabs': False, 'animated_docks': True, 'prompt_on_exit': False, 'panes_locked': True, 'window/size': (1260, 740), 'window/position': (10, 10), 'window/is_maximized': True, 'window/is_fullscreen': False, 'window/prefs_dialog_size': (745, 411), 'show_status_bar': True, 'memory_usage/enable': True, 'memory_usage/timeout': 2000, 'cpu_usage/enable': False, 'cpu_usage/timeout': 2000, 'use_custom_margin': True, 'custom_margin': 0, 'use_custom_cursor_blinking': False, 'show_internal_console_if_traceback': False, 'check_updates_on_startup': True, 'toolbars_visible': True, # Global Spyder fonts 'font/family': MONOSPACE, 'font/size': MEDIUM, 'font/italic': False, 'font/bold': False, 'rich_font/family': SANS_SERIF, 'rich_font/size': BIG, 'rich_font/italic': False, 'rich_font/bold': False, 'cursor/width': 2, 'completion/size': (300, 180), }), ('quick_layouts', { 'place_holder': '', 'names': ['Matlab layout', 'Rstudio layout', 'Vertical split', 'Horizontal split'], 'order': ['Matlab layout', 'Rstudio layout', 'Vertical split', 'Horizontal split'], 'active': ['Matlab layout', 'Rstudio layout', 'Vertical split', 'Horizontal split'], }), ('internal_console', { 'max_line_count': 300, 'working_dir_history': 30, 'working_dir_adjusttocontents': False, 'wrap': True, 'calltips': True, 'codecompletion/auto': False, 'codecompletion/enter_key': True, 'codecompletion/case_sensitive': True, 'external_editor/path': 'SciTE', 'external_editor/gotoline': '-goto:', 'light_background': True, }), ('main_interpreter', { 'default': True, 'custom': False, 'umr/enabled': True, 'umr/verbose': True, 'umr/namelist': [], }), ('ipython_console', { 'show_banner': True, 'completion_type': 0, 'use_pager': False, 'show_calltips': True, 'ask_before_closing': False, 'show_reset_namespace_warning': True, 'buffer_size': 500, 'pylab': True, 'pylab/autoload': False, 'pylab/backend': 0, 'pylab/inline/figure_format': 0, 'pylab/inline/resolution': 72, 'pylab/inline/width': 6, 'pylab/inline/height': 4, 'startup/run_lines': '', 'startup/use_run_file': False, 'startup/run_file': '', 'greedy_completer': False, 'autocall': 0, 'symbolic_math': False, 'in_prompt': '', 'out_prompt': '', 'show_elapsed_time': False }), ('variable_explorer', { 'check_all': CHECK_ALL, 'dataframe_format': '.6g', # No percent sign to avoid problems # with ConfigParser's interpolation 'excluded_names': EXCLUDED_NAMES, 'exclude_private': True, 'exclude_uppercase': True, 'exclude_capitalized': False, 'exclude_unsupported': True, 'truncate': True, 'minmax': False }), ('editor', { 'printer_header/font/family': SANS_SERIF, 'printer_header/font/size': MEDIUM, 'printer_header/font/italic': False, 'printer_header/font/bold': False, 'wrap': False, 'wrapflag': True, 'code_analysis/pyflakes': True, 'code_analysis/pep8': False, 'todo_list': True, 'realtime_analysis': True, 'realtime_analysis/timeout': 2500, 'outline_explorer': True, 'line_numbers': True, 'blank_spaces': False, 'edge_line': True, 'edge_line_column': 79, 'toolbox_panel': True, 'calltips': True, 'go_to_definition': True, 'close_parentheses': True, 'close_quotes': False, 'add_colons': True, 'auto_unindent': True, 'indent_chars': '* *', 'tab_stop_width_spaces': 4, 'codecompletion/auto': True, 'codecompletion/enter_key': True, 'codecompletion/case_sensitive': True, 'check_eol_chars': True, 'tab_always_indent': False, 'intelligent_backspace': True, 'highlight_current_line': True, 'highlight_current_cell': True, 'occurrence_highlighting': True, 'occurrence_highlighting/timeout': 1500, 'always_remove_trailing_spaces': False, 'show_tab_bar': True, 'max_recent_files': 20, 'save_all_before_run': True, 'focus_to_editor': True, 'onsave_analysis': False }), ('historylog', { 'enable': True, 'max_entries': 100, 'wrap': True, 'go_to_eof': True, }), ('help', { 'enable': True, 'max_history_entries': 20, 'wrap': True, 'connect/editor': False, 'connect/ipython_console': False, 'math': True, 'automatic_import': True, }), ('onlinehelp', { 'enable': True, 'zoom_factor': .8, 'max_history_entries': 20, }), ('outline_explorer', { 'enable': True, 'show_fullpath': False, 'show_all_files': False, 'show_comments': True, }), ('project_explorer', { 'name_filters': NAME_FILTERS, 'show_all': True, 'show_hscrollbar': True }), ('explorer', { 'enable': True, 'wrap': True, 'name_filters': NAME_FILTERS, 'show_hidden': True, 'show_all': True, 'show_icontext': False, }), ('find_in_files', { 'enable': True, 'supported_encodings': ["utf-8", "iso-8859-1", "cp1252"], 'exclude': EXCLUDE_PATTERNS, 'exclude_regexp': True, 'search_text_regexp': True, 'search_text': [''], 'search_text_samples': [codeanalysis.TASKS_PATTERN], 'in_python_path': False, 'more_options': False, 'case_sensitive': True }), ('workingdir', { 'working_dir_adjusttocontents': False, 'working_dir_history': 20, 'console/use_project_or_home_directory': False, 'console/use_cwd': True, 'console/use_fixed_directory': False, }), ('shortcuts', { # ---- Global ---- # -- In app/spyder.py '_/close pane': "Shift+Ctrl+F4", '_/lock unlock panes': "Shift+Ctrl+F5", '_/use next layout': "Shift+Alt+PgDown", '_/use previous layout': "Shift+Alt+PgUp", '_/preferences': "Ctrl+Alt+Shift+P", '_/maximize pane': "Ctrl+Alt+Shift+M", '_/fullscreen mode': "F11", '_/save current layout': "Shift+Alt+S", '_/layout preferences': "Shift+Alt+P", '_/show toolbars': "Alt+Shift+T", '_/spyder documentation': "F1", '_/restart': "Shift+Alt+R", '_/quit': "Ctrl+Q", # -- In plugins/editor '_/file switcher': 'Ctrl+P', '_/symbol finder': 'Ctrl+Alt+P', '_/debug': "Ctrl+F5", '_/debug step over': "Ctrl+F10", '_/debug continue': "Ctrl+F12", '_/debug step into': "Ctrl+F11", '_/debug step return': "Ctrl+Shift+F11", '_/debug exit': "Ctrl+Shift+F12", '_/run': "F5", '_/configure': "Ctrl+F6", '_/re-run last script': "F6", # -- In plugins/init '_/switch to help': "Ctrl+Shift+H", '_/switch to outline_explorer': "Ctrl+Shift+O", '_/switch to editor': "Ctrl+Shift+E", '_/switch to historylog': "Ctrl+Shift+L", '_/switch to onlinehelp': "Ctrl+Shift+D", '_/switch to project_explorer': "Ctrl+Shift+P", '_/switch to console': "Ctrl+Shift+C", '_/switch to ipython_console': "Ctrl+Shift+I", '_/switch to variable_explorer': "Ctrl+Shift+V", '_/switch to find_in_files': "Ctrl+Shift+F", '_/switch to explorer': "Ctrl+Shift+X", # -- In widgets/findreplace.py '_/find text': "Ctrl+F", '_/find next': "F3", '_/find previous': "Shift+F3", '_/replace text': "Ctrl+R", '_/hide find and replace': "Escape", # ---- Editor ---- # -- In widgets/sourcecode/codeeditor.py 'editor/code completion': CTRL+'+Space', 'editor/duplicate line': "Ctrl+Alt+Up" if WIN else \ "Shift+Alt+Up", 'editor/copy line': "Ctrl+Alt+Down" if WIN else \ "Shift+Alt+Down", 'editor/delete line': 'Ctrl+D', 'editor/transform to uppercase': 'Ctrl+Shift+U', 'editor/transform to lowercase': 'Ctrl+U', 'editor/indent': 'Ctrl+]', 'editor/unindent': 'Ctrl+[', 'editor/move line up': "Alt+Up", 'editor/move line down': "Alt+Down", 'editor/go to definition': "Ctrl+G", 'editor/toggle comment': "Ctrl+1", 'editor/blockcomment': "Ctrl+4", 'editor/unblockcomment': "Ctrl+5", 'editor/start of line': "Meta+A", 'editor/end of line': "Meta+E", 'editor/previous line': "Meta+P", 'editor/next line': "Meta+N", 'editor/previous char': "Meta+B", 'editor/next char': "Meta+F", 'editor/previous word': "Meta+Left", 'editor/next word': "Meta+Right", 'editor/kill to line end': "Meta+K", 'editor/kill to line start': "Meta+U", 'editor/yank': 'Meta+Y', 'editor/rotate kill ring': 'Shift+Meta+Y', 'editor/kill previous word': 'Meta+Backspace', 'editor/kill next word': 'Meta+D', 'editor/start of document': 'Ctrl+Home', 'editor/end of document': 'Ctrl+End', 'editor/undo': 'Ctrl+Z', 'editor/redo': 'Ctrl+Shift+Z', 'editor/cut': 'Ctrl+X', 'editor/copy': 'Ctrl+C', 'editor/paste': 'Ctrl+V', 'editor/delete': 'Delete', 'editor/select all': "Ctrl+A", # -- In widgets/editor.py 'editor/inspect current object': 'Ctrl+I', 'editor/breakpoint': 'F12', 'editor/conditional breakpoint': 'Shift+F12', 'editor/run selection': "F9", 'editor/go to line': 'Ctrl+L', 'editor/go to previous file': 'Ctrl+Shift+Tab', 'editor/go to next file': 'Ctrl+Tab', 'editor/cycle to previous file': 'Ctrl+PgUp', 'editor/cycle to next file': 'Ctrl+PgDown', 'editor/new file': "Ctrl+N", 'editor/open last closed':"Ctrl+Shift+T", 'editor/open file': "Ctrl+O", 'editor/save file': "Ctrl+S", 'editor/save all': "Ctrl+Alt+S", 'editor/save as': 'Ctrl+Shift+S', 'editor/close all': "Ctrl+Shift+W", 'editor/last edit location': "Ctrl+Alt+Shift+Left", 'editor/previous cursor position': "Ctrl+Alt+Left", 'editor/next cursor position': "Ctrl+Alt+Right", 'editor/zoom in 1': "Ctrl++", 'editor/zoom in 2': "Ctrl+=", 'editor/zoom out': "Ctrl+-", 'editor/zoom reset': "Ctrl+0", 'editor/close file 1': "Ctrl+W", 'editor/close file 2': "Ctrl+F4", 'editor/run cell': RUN_CELL_SHORTCUT, 'editor/run cell and advance': RUN_CELL_AND_ADVANCE_SHORTCUT, 'editor/go to next cell': 'Ctrl+Down', 'editor/go to previous cell': 'Ctrl+Up', 'editor/re-run last cell': RE_RUN_LAST_CELL_SHORTCUT, # -- In Breakpoints '_/switch to breakpoints': "Ctrl+Shift+B", # ---- Consoles (in widgets/shell) ---- 'console/inspect current object': "Ctrl+I", 'console/clear shell': "Ctrl+L", 'console/clear line': "Shift+Escape", # ---- In Pylint ---- 'pylint/run analysis': "F8", # ---- In Profiler ---- 'profiler/run profiler': "F10", # ---- In widgets/ipythonconsole/shell.py ---- 'ipython_console/new tab': "Ctrl+T", 'ipython_console/reset namespace': "Ctrl+Alt+R", 'ipython_console/restart kernel': "Ctrl+.", # ---- In widgets/arraybuider.py ---- 'array_builder/enter array inline': "Ctrl+Alt+M", 'array_builder/enter array table': "Ctrl+M", # ---- In widgets/variableexplorer/aarayeditor.py ---- 'variable_explorer/copy': 'Ctrl+C', }), ('color_schemes', { 'names': ['emacs', 'idle', 'monokai', 'pydev', 'scintilla', 'spyder', 'spyder/dark', 'zenburn', 'solarized/light', 'solarized/dark'], 'selected': 'spyder', # ---- Emacs ---- 'emacs/name': "Emacs", # Name Color Bold Italic 'emacs/background': "#000000", 'emacs/currentline': "#2b2b43", 'emacs/currentcell': "#1c1c2d", 'emacs/occurrence': "#abab67", 'emacs/ctrlclick': "#0000ff", 'emacs/sideareas': "#555555", 'emacs/matched_p': "#009800", 'emacs/unmatched_p': "#c80000", 'emacs/normal': ('#ffffff', False, False), 'emacs/keyword': ('#3c51e8', False, False), 'emacs/builtin': ('#900090', False, False), 'emacs/definition': ('#ff8040', True, False), 'emacs/comment': ('#005100', False, False), 'emacs/string': ('#00aa00', False, True), 'emacs/number': ('#800000', False, False), 'emacs/instance': ('#ffffff', False, True), # ---- IDLE ---- 'idle/name': "IDLE", # Name Color Bold Italic 'idle/background': "#ffffff", 'idle/currentline': "#f2e6f3", 'idle/currentcell': "#feefff", 'idle/occurrence': "#e8f2fe", 'idle/ctrlclick': "#0000ff", 'idle/sideareas': "#efefef", 'idle/matched_p': "#99ff99", 'idle/unmatched_p': "#ff9999", 'idle/normal': ('#000000', False, False), 'idle/keyword': ('#ff7700', True, False), 'idle/builtin': ('#900090', False, False), 'idle/definition': ('#0000ff', False, False), 'idle/comment': ('#dd0000', False, True), 'idle/string': ('#00aa00', False, False), 'idle/number': ('#924900', False, False), 'idle/instance': ('#777777', True, True), # ---- Monokai ---- 'monokai/name': "Monokai", # Name Color Bold Italic 'monokai/background': "#2a2b24", 'monokai/currentline': "#484848", 'monokai/currentcell': "#3d3d3d", 'monokai/occurrence': "#666666", 'monokai/ctrlclick': "#0000ff", 'monokai/sideareas': "#2a2b24", 'monokai/matched_p': "#688060", 'monokai/unmatched_p': "#bd6e76", 'monokai/normal': ("#ddddda", False, False), 'monokai/keyword': ("#f92672", False, False), 'monokai/builtin': ("#ae81ff", False, False), 'monokai/definition': ("#a6e22e", False, False), 'monokai/comment': ("#75715e", False, True), 'monokai/string': ("#e6db74", False, False), 'monokai/number': ("#ae81ff", False, False), 'monokai/instance': ("#ddddda", False, True), # ---- Pydev ---- 'pydev/name': "Pydev", # Name Color Bold Italic 'pydev/background': "#ffffff", 'pydev/currentline': "#e8f2fe", 'pydev/currentcell': "#eff8fe", 'pydev/occurrence': "#ffff99", 'pydev/ctrlclick': "#0000ff", 'pydev/sideareas': "#efefef", 'pydev/matched_p': "#99ff99", 'pydev/unmatched_p': "#ff99992", 'pydev/normal': ('#000000', False, False), 'pydev/keyword': ('#0000ff', False, False), 'pydev/builtin': ('#900090', False, False), 'pydev/definition': ('#000000', True, False), 'pydev/comment': ('#c0c0c0', False, False), 'pydev/string': ('#00aa00', False, True), 'pydev/number': ('#800000', False, False), 'pydev/instance': ('#000000', False, True), # ---- Scintilla ---- 'scintilla/name': "Scintilla", # Name Color Bold Italic 'scintilla/background': "#ffffff", 'scintilla/currentline': "#e1f0d1", 'scintilla/currentcell': "#edfcdc", 'scintilla/occurrence': "#ffff99", 'scintilla/ctrlclick': "#0000ff", 'scintilla/sideareas': "#efefef", 'scintilla/matched_p': "#99ff99", 'scintilla/unmatched_p': "#ff9999", 'scintilla/normal': ('#000000', False, False), 'scintilla/keyword': ('#00007f', True, False), 'scintilla/builtin': ('#000000', False, False), 'scintilla/definition': ('#007f7f', True, False), 'scintilla/comment': ('#007f00', False, False), 'scintilla/string': ('#7f007f', False, False), 'scintilla/number': ('#007f7f', False, False), 'scintilla/instance': ('#000000', False, True), # ---- Spyder ---- 'spyder/name': "Spyder", # Name Color Bold Italic 'spyder/background': "#ffffff", 'spyder/currentline': "#f7ecf8", 'spyder/currentcell': "#fdfdde", 'spyder/occurrence': "#ffff99", 'spyder/ctrlclick': "#0000ff", 'spyder/sideareas': "#efefef", 'spyder/matched_p': "#99ff99", 'spyder/unmatched_p': "#ff9999", 'spyder/normal': ('#000000', False, False), 'spyder/keyword': ('#0000ff', False, False), 'spyder/builtin': ('#900090', False, False), 'spyder/definition': ('#000000', True, False), 'spyder/comment': ('#adadad', False, True), 'spyder/string': ('#00aa00', False, False), 'spyder/number': ('#800000', False, False), 'spyder/instance': ('#924900', False, True), # ---- Spyder/Dark ---- 'spyder/dark/name': "Spyder Dark", # Name Color Bold Italic 'spyder/dark/background': "#131926", 'spyder/dark/currentline': "#2b2b43", 'spyder/dark/currentcell': "#31314e", 'spyder/dark/occurrence': "#abab67", 'spyder/dark/ctrlclick': "#0000ff", 'spyder/dark/sideareas': "#282828", 'spyder/dark/matched_p': "#009800", 'spyder/dark/unmatched_p': "#c80000", 'spyder/dark/normal': ('#ffffff', False, False), 'spyder/dark/keyword': ('#558eff', False, False), 'spyder/dark/builtin': ('#aa00aa', False, False), 'spyder/dark/definition': ('#ffffff', True, False), 'spyder/dark/comment': ('#7f7f7f', False, False), 'spyder/dark/string': ('#11a642', False, True), 'spyder/dark/number': ('#c80000', False, False), 'spyder/dark/instance': ('#be5f00', False, True), # ---- Zenburn ---- 'zenburn/name': "Zenburn", # Name Color Bold Italic 'zenburn/background': "#3f3f3f", 'zenburn/currentline': "#333333", 'zenburn/currentcell': "#2c2c2c", 'zenburn/occurrence': "#7a738f", 'zenburn/ctrlclick': "#0000ff", 'zenburn/sideareas': "#3f3f3f", 'zenburn/matched_p': "#688060", 'zenburn/unmatched_p': "#bd6e76", 'zenburn/normal': ('#dcdccc', False, False), 'zenburn/keyword': ('#dfaf8f', True, False), 'zenburn/builtin': ('#efef8f', False, False), 'zenburn/definition': ('#efef8f', False, False), 'zenburn/comment': ('#7f9f7f', False, True), 'zenburn/string': ('#cc9393', False, False), 'zenburn/number': ('#8cd0d3', False, False), 'zenburn/instance': ('#dcdccc', False, True), # ---- Solarized Light ---- 'solarized/light/name': "Solarized Light", # Name Color Bold Italic 'solarized/light/background': '#fdf6e3', 'solarized/light/currentline': '#f5efdB', 'solarized/light/currentcell': '#eee8d5', 'solarized/light/occurrence': '#839496', 'solarized/light/ctrlclick': '#d33682', 'solarized/light/sideareas': '#eee8d5', 'solarized/light/matched_p': '#586e75', 'solarized/light/unmatched_p': '#dc322f', 'solarized/light/normal': ('#657b83', False, False), 'solarized/light/keyword': ('#859900', False, False), 'solarized/light/builtin': ('#6c71c4', False, False), 'solarized/light/definition': ('#268bd2', True, False), 'solarized/light/comment': ('#93a1a1', False, True), 'solarized/light/string': ('#2aa198', False, False), 'solarized/light/number': ('#cb4b16', False, False), 'solarized/light/instance': ('#b58900', False, True), # ---- Solarized Dark ---- 'solarized/dark/name': "Solarized Dark", # Name Color Bold Italic 'solarized/dark/background': '#002b36', 'solarized/dark/currentline': '#083f4d', 'solarized/dark/currentcell': '#073642', 'solarized/dark/occurrence': '#657b83', 'solarized/dark/ctrlclick': '#d33682', 'solarized/dark/sideareas': '#073642', 'solarized/dark/matched_p': '#93a1a1', 'solarized/dark/unmatched_p': '#dc322f', 'solarized/dark/normal': ('#839496', False, False), 'solarized/dark/keyword': ('#859900', False, False), 'solarized/dark/builtin': ('#6c71c4', False, False), 'solarized/dark/definition': ('#268bd2', True, False), 'solarized/dark/comment': ('#586e75', False, True), 'solarized/dark/string': ('#2aa198', False, False), 'solarized/dark/number': ('#cb4b16', False, False), 'solarized/dark/instance': ('#b58900', False, True) }) ] #============================================================================== # Config instance #============================================================================== # IMPORTANT NOTES: # 1. If you want to *change* the default value of a current option, you need to # do a MINOR update in config version, e.g. from 3.0.0 to 3.1.0 # 2. If you want to *remove* options that are no longer needed in our codebase, # or if you want to *rename* options, then you need to do a MAJOR update in # version, e.g. from 3.0.0 to 4.0.0 # 3. You don't need to touch this value if you're just adding a new option CONF_VERSION = '42.0.0' # Main configuration instance try: CONF = UserConfig('spyder', defaults=DEFAULTS, load=(not TEST), version=CONF_VERSION, subfolder=SUBFOLDER, backup=True, raw_mode=True) except: CONF = UserConfig('spyder', defaults=DEFAULTS, load=False, version=CONF_VERSION, subfolder=SUBFOLDER, backup=True, raw_mode=True) # Removing old .spyder.ini location: old_location = osp.join(get_home_dir(), '.spyder.ini') if osp.isfile(old_location): os.remove(old_location) spyder-3.2.6/spyder/config/tests/0000775000175000017500000000000013225025007017533 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/config/tests/test_user.py0000664000175000017500000000351113224121062022117 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Tests for config/user.py """ # Third party imports import pytest # Local imports from spyder.config.user import UserConfig from spyder.py3compat import PY2 @pytest.fixture def userconfig(tmpdir, monkeypatch): monkeypatch.setattr('spyder.config.user.get_conf_path', lambda: str(tmpdir)) inifile = tmpdir.join('foo.ini') iniContents = '[main]\nversion = 1.0.0\n\n' if PY2: # strings are quoted in Python2 but not in Python3 iniContents += "[section]\noption = 'value'\n\n" else: iniContents += "[section]\noption = value\n\n" inifile.write(iniContents) return UserConfig('foo', defaults={}, subfolder=True, version='1.0.0', raw_mode=True) def test_userconfig_set_percentage_string(userconfig): """Test to set an option with a '%'.""" userconfig.set('section', 'option', '%value') assert userconfig.get('section', 'option') == '%value' def test_userconfig_get_string_from_inifile(userconfig): assert userconfig.get('section', 'option') == 'value' def test_userconfig_get_does_not_eval_functions(userconfig): # regression test for issue #3354 userconfig.set('section', 'option', 'print("foo")') assert userconfig.get('section', 'option') == 'print("foo")' def test_userconfig_set_with_string(userconfig): userconfig.set('section', 'option', 'new value') with open(userconfig.filename()) as inifile: iniContents = inifile.read() expected = '[main]\nversion = 1.0.0\n\n' if PY2: expected += "[section]\noption = 'new value'\n\n" else: expected += "[section]\noption = new value\n\n" assert iniContents == expected if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/config/tests/__init__.py0000664000175000017500000000050213156676663021670 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Copyright (c) Spyder Project Contributors # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Tests.""" spyder-3.2.6/spyder/config/utils.py0000664000175000017500000001532613224121062020107 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Utilities to define configuration values """ import os import os.path as osp import sys from spyder.config.base import _ from spyder.utils import iofuncs #============================================================================== # Constants #============================================================================== # File types supported by the Editor up to Spyder 2.3 EDIT_FILETYPES = [ (_("Python files"), ('.py', '.pyw', '.ipy')), (_("Cython/Pyrex files"), ('.pyx', '.pxd', '.pxi')), (_("C files"), ('.c', '.h')), (_("C++ files"), ('.cc', '.cpp', '.cxx', '.h', '.hh', '.hpp', '.hxx')), (_("OpenCL files"), ('.cl', )), (_("Fortran files"), ('.f', '.for', '.f77', '.f90', '.f95', '.f2k')), (_("IDL files"), ('.pro', )), (_("MATLAB files"), ('.m', )), (_("Julia files"), ('.jl',)), (_("Yaml files"), ('.yaml','.yml',)), (_("Patch and diff files"), ('.patch', '.diff', '.rej')), (_("Batch files"), ('.bat', '.cmd')), (_("Text files"), ('.txt',)), (_("reStructuredText files"), ('.txt', '.rst')), (_("gettext files"), ('.po', '.pot')), (_("NSIS files"), ('.nsi', '.nsh')), (_("Web page files"), ('.scss', '.css', '.htm', '.html',)), (_("XML files"), ('.xml',)), (_("Javascript files"), ('.js',)), (_("Json files"), ('.json',)), (_("IPython notebooks"), ('.ipynb',)), (_("Enaml files"), ('.enaml',)), (_("Configuration files"), ('.properties', '.session', '.ini', '.inf', '.reg', '.cfg', '.desktop')), (_("Markdown files"), ('.md', )), ] # Filter for all files ALL_FILTER = "%s (*)" % _("All files") # Extensions supported by Spyder's Variable explorer IMPORT_EXT = list(iofuncs.iofunctions.load_extensions.values()) #============================================================================== # Auxiliary functions #============================================================================== def _create_filter(title, ftypes): return "%s (*%s)" % (title, " *".join(ftypes)) def _get_filters(filetypes): filters = [] for title, ftypes in filetypes: filters.append(_create_filter(title, ftypes)) filters.append(ALL_FILTER) return ";;".join(filters) def _get_extensions(filetypes): ftype_list = [] for _title, ftypes in filetypes: ftype_list += list(ftypes) return ftype_list def _get_pygments_extensions(): """Return all file type extensions supported by Pygments""" # NOTE: Leave this import here to keep startup process fast! import pygments.lexers as lexers extensions = [] for lx in lexers.get_all_lexers(): lexer_exts = lx[2] if lexer_exts: # Reference: This line was included for leaving untrimmed the # extensions not starting with `*` other_exts = [le for le in lexer_exts if not le.startswith('*')] # Reference: This commented line was replaced by the following one # to trim only extensions that start with '*' # lexer_exts = [le[1:] for le in lexer_exts] lexer_exts = [le[1:] for le in lexer_exts if le.startswith('*')] lexer_exts = [le for le in lexer_exts if not le.endswith('_*')] extensions = extensions + list(lexer_exts) + list(other_exts) return sorted(list(set(extensions))) #============================================================================== # Main functions #============================================================================== def get_filter(filetypes, ext): """Return filter associated to file extension""" if not ext: return ALL_FILTER for title, ftypes in filetypes: if ext in ftypes: return _create_filter(title, ftypes) else: return '' def get_edit_filetypes(): """Get all file types supported by the Editor""" # The filter details are not hidden on Windows, so we can't use # all Pygments extensions on that platform if os.name == 'nt': supported_exts = [] else: supported_exts = _get_pygments_extensions() # NOTE: Try to not add too much extensions to this list to not # make the filter look too big on Windows favorite_exts = ['.py', '.R', '.jl', '.ipynb', '.md', '.pyw', '.pyx', '.c', '.cpp', '.json', '.dat', '.csv', '.tsv', '.txt', '.ini', '.html', '.js', '.h', '.bat'] other_exts = [ext for ext in supported_exts if ext not in favorite_exts] all_exts = tuple(favorite_exts + other_exts) text_filetypes = (_("Supported text files"), all_exts) return [text_filetypes] + EDIT_FILETYPES def get_edit_filters(): """ Return filters associated with the file types supported by the Editor """ edit_filetypes = get_edit_filetypes() return _get_filters(edit_filetypes) def get_edit_extensions(): """ Return extensions associated with the file types supported by the Editor """ edit_filetypes = get_edit_filetypes() return _get_extensions(edit_filetypes)+[''] #============================================================================== # Detection of OS specific versions #============================================================================== def is_ubuntu(): """Detect if we are running in an Ubuntu-based distribution""" if sys.platform.startswith('linux') and osp.isfile('/etc/lsb-release'): release_info = open('/etc/lsb-release').read() if 'Ubuntu' in release_info: return True else: return False else: return False def is_gtk_desktop(): """Detect if we are running in a Gtk-based desktop""" if sys.platform.startswith('linux'): xdg_desktop = os.environ.get('XDG_CURRENT_DESKTOP', '') if xdg_desktop: gtk_desktops = ['Unity', 'GNOME', 'XFCE'] if any([xdg_desktop.startswith(d) for d in gtk_desktops]): return True else: return False else: return False else: return False def is_kde_desktop(): """Detect if we are running in a KDE desktop""" if sys.platform.startswith('linux'): xdg_desktop = os.environ.get('XDG_CURRENT_DESKTOP', '') if xdg_desktop: if 'KDE' in xdg_desktop: return True else: return False else: return False else: return False def is_anaconda(): """ Detect if we are running under Anaconda. Taken from https://stackoverflow.com/a/47610844/438386 """ is_conda = osp.exists(osp.join(sys.prefix, 'conda-meta')) return is_conda spyder-3.2.6/spyder/config/base.py0000664000175000017500000003777513224740762017713 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Spyder base configuration management This file only deals with non-GUI configuration features (in other words, we won't import any PyQt object here, avoiding any sip API incompatibility issue in spyder's non-gui modules) """ from __future__ import print_function import codecs import locale import os.path as osp import os import shutil import sys # Local imports from spyder.utils import encoding from spyder.py3compat import (is_unicode, TEXT_TYPES, INT_TYPES, PY3, to_text_string, is_text_string) #============================================================================== # Only for development #============================================================================== # To activate/deactivate certain things for development # SPYDER_DEV is (and *only* has to be) set in bootstrap.py DEV = os.environ.get('SPYDER_DEV') # For testing purposes # SPYDER_TEST can be set using the --test option of bootstrap.py TEST = os.environ.get('SPYDER_TEST') # To do some adjustments for pytest # This env var is defined in runtests.py PYTEST = os.environ.get('SPYDER_PYTEST') #============================================================================== # Debug helpers #============================================================================== # This is needed after restarting and using debug_print STDOUT = sys.stdout if PY3 else codecs.getwriter('utf-8')(sys.stdout) STDERR = sys.stderr def _get_debug_env(): debug_env = os.environ.get('SPYDER_DEBUG', '') if not debug_env.isdigit(): debug_env = bool(debug_env) return int(debug_env) DEBUG = _get_debug_env() def debug_print(*message): """Output debug messages to stdout""" if DEBUG: ss = STDOUT if PY3: # This is needed after restarting and using debug_print for m in message: ss.buffer.write(str(m).encode('utf-8')) print('', file=ss) else: print(*message, file=ss) #============================================================================== # Configuration paths #============================================================================== # Spyder settings dir # NOTE: During the 2.x.x series this dir was named .spyder2, but # since 3.0+ we've reverted back to use .spyder to simplify major # updates in version (required when we change APIs by Linux # packagers) if sys.platform.startswith('linux'): SUBFOLDER = 'spyder' else: SUBFOLDER = '.spyder' # We can't have PY2 and PY3 settings in the same dir because: # 1. This leads to ugly crashes and freezes (e.g. by trying to # embed a PY2 interpreter in PY3) # 2. We need to save the list of installed modules (for code # completion) separately for each version if PY3: SUBFOLDER = SUBFOLDER + '-py3' def get_home_dir(): """ Return user home directory """ try: # expanduser() returns a raw byte string which needs to be # decoded with the codec that the OS is using to represent file paths. path = encoding.to_unicode_from_fs(osp.expanduser('~')) except: path = '' for env_var in ('HOME', 'USERPROFILE', 'TMP'): if osp.isdir(path): break # os.environ.get() returns a raw byte string which needs to be # decoded with the codec that the OS is using to represent environment # variables. path = encoding.to_unicode_from_fs(os.environ.get(env_var, '')) if path: return path else: raise RuntimeError('Please define environment variable $HOME') def get_conf_path(filename=None): """Return absolute path for configuration file with specified filename""" # This makes us follow the XDG standard to save our settings # on Linux, as it was requested on Issue 2629 if sys.platform.startswith('linux'): xdg_config_home = os.environ.get('XDG_CONFIG_HOME', '') if not xdg_config_home: xdg_config_home = osp.join(get_home_dir(), '.config') if not osp.isdir(xdg_config_home): os.makedirs(xdg_config_home) conf_dir = osp.join(xdg_config_home, SUBFOLDER) else: conf_dir = osp.join(get_home_dir(), SUBFOLDER) if not osp.isdir(conf_dir): os.mkdir(conf_dir) if filename is None: return conf_dir else: return osp.join(conf_dir, filename) def get_module_path(modname): """Return module *modname* base path""" return osp.abspath(osp.dirname(sys.modules[modname].__file__)) def get_module_data_path(modname, relpath=None, attr_name='DATAPATH'): """Return module *modname* data path Note: relpath is ignored if module has an attribute named *attr_name* Handles py2exe/cx_Freeze distributions""" datapath = getattr(sys.modules[modname], attr_name, '') if datapath: return datapath else: datapath = get_module_path(modname) parentdir = osp.join(datapath, osp.pardir) if osp.isfile(parentdir): # Parent directory is not a directory but the 'library.zip' file: # this is either a py2exe or a cx_Freeze distribution datapath = osp.abspath(osp.join(osp.join(parentdir, osp.pardir), modname)) if relpath is not None: datapath = osp.abspath(osp.join(datapath, relpath)) return datapath def get_module_source_path(modname, basename=None): """Return module *modname* source path If *basename* is specified, return *modname.basename* path where *modname* is a package containing the module *basename* *basename* is a filename (not a module name), so it must include the file extension: .py or .pyw Handles py2exe/cx_Freeze distributions""" srcpath = get_module_path(modname) parentdir = osp.join(srcpath, osp.pardir) if osp.isfile(parentdir): # Parent directory is not a directory but the 'library.zip' file: # this is either a py2exe or a cx_Freeze distribution srcpath = osp.abspath(osp.join(osp.join(parentdir, osp.pardir), modname)) if basename is not None: srcpath = osp.abspath(osp.join(srcpath, basename)) return srcpath def is_py2exe_or_cx_Freeze(): """Return True if this is a py2exe/cx_Freeze distribution of Spyder""" return osp.isfile(osp.join(get_module_path('spyder'), osp.pardir)) #============================================================================== # Image path list #============================================================================== IMG_PATH = [] def add_image_path(path): if not osp.isdir(path): return global IMG_PATH IMG_PATH.append(path) for dirpath, dirnames, _filenames in os.walk(path): for dirname in dirnames: IMG_PATH.append(osp.join(dirpath, dirname)) add_image_path(get_module_data_path('spyder', relpath='images')) def get_image_path(name, default="not_found.png"): """Return image absolute path""" for img_path in IMG_PATH: full_path = osp.join(img_path, name) if osp.isfile(full_path): return osp.abspath(full_path) if default is not None: img_path = osp.join(get_module_path('spyder'), 'images') return osp.abspath(osp.join(img_path, default)) #============================================================================== # Translations #============================================================================== LANG_FILE = get_conf_path('langconfig') DEFAULT_LANGUAGE = 'en' # This needs to be updated every time a new language is added to spyder, and is # used by the Preferences configuration to populate the Language QComboBox LANGUAGE_CODES = {'en': u'English', 'fr': u'Français', 'es': u'Español', 'pt_BR': u'Português', 'ru': u'Русский', 'ja': u'日本語' } # Disabled languages (because their translations are outdated) DISABLED_LANGUAGES = [] def get_available_translations(): """ List available translations for spyder based on the folders found in the locale folder. This function checks if LANGUAGE_CODES contain the same information that is found in the 'locale' folder to ensure that when a new language is added, LANGUAGE_CODES is updated. """ locale_path = get_module_data_path("spyder", relpath="locale", attr_name='LOCALEPATH') listdir = os.listdir(locale_path) langs = [d for d in listdir if osp.isdir(osp.join(locale_path, d))] langs = [DEFAULT_LANGUAGE] + langs # Remove disabled languages langs = list( set(langs) - set(DISABLED_LANGUAGES) ) # Check that there is a language code available in case a new translation # is added, to ensure LANGUAGE_CODES is updated. for lang in langs: if lang not in LANGUAGE_CODES: error = _('Update LANGUAGE_CODES (inside config/base.py) if a new ' 'translation has been added to Spyder') raise Exception(error) return langs def get_interface_language(): """ If Spyder has a translation available for the locale language, it will return the version provided by Spyder adjusted for language subdifferences, otherwise it will return DEFAULT_LANGUAGE. Example: 1.) Spyder provides ('en', 'fr', 'es' and 'pt_BR'), if the locale is either 'en_US' or 'en' or 'en_UK', this function will return 'en' 2.) Spyder provides ('en', 'fr', 'es' and 'pt_BR'), if the locale is either 'pt' or 'pt_BR', this function will return 'pt_BR' """ # Solves issue #3627 try: locale_language = locale.getdefaultlocale()[0] except ValueError: locale_language = DEFAULT_LANGUAGE language = DEFAULT_LANGUAGE if locale_language is not None: spyder_languages = get_available_translations() for lang in spyder_languages: if locale_language == lang: language = locale_language break elif locale_language.startswith(lang) or \ lang.startswith(locale_language): language = lang break return language def save_lang_conf(value): """Save language setting to language config file""" with open(LANG_FILE, 'w') as f: f.write(value) def load_lang_conf(): """ Load language setting from language config file if it exists, otherwise try to use the local settings if Spyder provides a translation, or return the default if no translation provided. """ if osp.isfile(LANG_FILE): with open(LANG_FILE, 'r') as f: lang = f.read() else: lang = get_interface_language() save_lang_conf(lang) # Save language again if it's been disabled if lang.strip('\n') in DISABLED_LANGUAGES: lang = DEFAULT_LANGUAGE save_lang_conf(lang) return lang def get_translation(modname, dirname=None): """Return translation callback for module *modname*""" if dirname is None: dirname = modname locale_path = get_module_data_path(dirname, relpath="locale", attr_name='LOCALEPATH') # If LANG is defined in ubuntu, a warning message is displayed, so in unix # systems we define the LANGUAGE variable. language = load_lang_conf() if os.name == 'nt': os.environ["LANG"] = language # Works on Windows else: os.environ["LANGUAGE"] = language # Works on Linux import gettext try: _trans = gettext.translation(modname, locale_path, codeset="utf-8") lgettext = _trans.lgettext def translate_gettext(x): if not PY3 and is_unicode(x): x = x.encode("utf-8") y = lgettext(x) if is_text_string(y) and PY3: return y else: return to_text_string(y, "utf-8") return translate_gettext except IOError as _e: # analysis:ignore # Not using translations def translate_dumb(x): if not is_unicode(x): return to_text_string(x, "utf-8") return x return translate_dumb # Translation callback _ = get_translation("spyder") #============================================================================== # Namespace Browser (Variable Explorer) configuration management #============================================================================== def get_supported_types(): """ Return a dictionnary containing types lists supported by the namespace browser: dict(picklable=picklable_types, editable=editables_types) See: get_remote_data function in spyder/widgets/variableexplorer/utils/monitor.py Note: If you update this list, don't forget to update doc/variablexplorer.rst """ from datetime import date, timedelta editable_types = [int, float, complex, list, dict, tuple, date, timedelta ] + list(TEXT_TYPES) + list(INT_TYPES) try: from numpy import ndarray, matrix, generic editable_types += [ndarray, matrix, generic] except: pass try: from pandas import DataFrame, Series, DatetimeIndex editable_types += [DataFrame, Series, DatetimeIndex] except: pass picklable_types = editable_types[:] try: from spyder.pil_patch import Image editable_types.append(Image.Image) except: pass return dict(picklable=picklable_types, editable=editable_types) # Variable explorer display / check all elements data types for sequences: # (when saving the variable explorer contents, check_all is True, # see widgets/variableexplorer/namespacebrowser.py:NamespaceBrowser.save_data) CHECK_ALL = False #XXX: If True, this should take too much to compute... EXCLUDED_NAMES = ['nan', 'inf', 'infty', 'little_endian', 'colorbar_doc', 'typecodes', '__builtins__', '__main__', '__doc__', 'NaN', 'Inf', 'Infinity', 'sctypes', 'rcParams', 'rcParamsDefault', 'sctypeNA', 'typeNA', 'False_', 'True_',] #============================================================================== # Mac application utilities #============================================================================== if PY3: MAC_APP_NAME = 'Spyder.app' else: MAC_APP_NAME = 'Spyder-Py2.app' def running_in_mac_app(): if sys.platform == "darwin" and MAC_APP_NAME in __file__: return True else: return False #============================================================================== # Reset config files #============================================================================== SAVED_CONFIG_FILES = ('help', 'onlinehelp', 'path', 'pylint.results', 'spyder.ini', 'temp.py', 'temp.spydata', 'template.py', 'history.py', 'history_internal.py', 'workingdir', '.projects', '.spyproject', '.ropeproject', 'monitor.log', 'monitor_debug.log', 'rope.log', 'langconfig', 'spyder.lock') def reset_config_files(): """Remove all config files""" print("*** Reset Spyder settings to defaults ***", file=STDERR) for fname in SAVED_CONFIG_FILES: cfg_fname = get_conf_path(fname) if osp.isfile(cfg_fname) or osp.islink(cfg_fname): os.remove(cfg_fname) elif osp.isdir(cfg_fname): shutil.rmtree(cfg_fname) else: continue print("removing:", cfg_fname, file=STDERR) spyder-3.2.6/spyder/config/__init__.py0000664000175000017500000000000013026261005020467 0ustar carloscarlos00000000000000spyder-3.2.6/spyder/interpreter.py0000664000175000017500000003054513224121062020045 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Shell Interpreter""" from __future__ import print_function import sys import atexit import threading import ctypes import os import re import os.path as osp import pydoc from code import InteractiveConsole # Local imports: from spyder.utils.dochelpers import isdefined from spyder.utils import encoding, programs from spyder.py3compat import is_text_string from spyder.utils.misc import remove_backslashes, getcwd_or_home # Force Python to search modules in the current directory first: sys.path.insert(0, '') def guess_filename(filename): """Guess filename""" if osp.isfile(filename): return filename if not filename.endswith('.py'): filename += '.py' for path in [getcwd_or_home()] + sys.path: fname = osp.join(path, filename) if osp.isfile(fname): return fname elif osp.isfile(fname+'.py'): return fname+'.py' elif osp.isfile(fname+'.pyw'): return fname+'.pyw' return filename class Interpreter(InteractiveConsole, threading.Thread): """Interpreter, executed in a separate thread""" p1 = ">>> " p2 = "... " def __init__(self, namespace=None, exitfunc=None, Output=None, WidgetProxy=None, debug=False): """ namespace: locals send to InteractiveConsole object commands: list of commands executed at startup """ InteractiveConsole.__init__(self, namespace) threading.Thread.__init__(self) self._id = None self.exit_flag = False self.debug = debug # Execution Status self.more = False if exitfunc is not None: atexit.register(exitfunc) self.namespace = self.locals self.namespace['__name__'] = '__main__' self.namespace['execfile'] = self.execfile self.namespace['runfile'] = self.runfile self.namespace['raw_input'] = self.raw_input_replacement self.namespace['help'] = self.help_replacement # Capture all interactive input/output self.initial_stdout = sys.stdout self.initial_stderr = sys.stderr self.initial_stdin = sys.stdin # Create communication pipes pr, pw = os.pipe() self.stdin_read = os.fdopen(pr, "r") self.stdin_write = os.fdopen(pw, "wb", 0) self.stdout_write = Output() self.stderr_write = Output() self.input_condition = threading.Condition() self.widget_proxy = WidgetProxy(self.input_condition) self.redirect_stds() #------ Standard input/output def redirect_stds(self): """Redirects stds""" if not self.debug: sys.stdout = self.stdout_write sys.stderr = self.stderr_write sys.stdin = self.stdin_read def restore_stds(self): """Restore stds""" if not self.debug: sys.stdout = self.initial_stdout sys.stderr = self.initial_stderr sys.stdin = self.initial_stdin def raw_input_replacement(self, prompt=''): """For raw_input builtin function emulation""" self.widget_proxy.wait_input(prompt) self.input_condition.acquire() while not self.widget_proxy.data_available(): self.input_condition.wait() inp = self.widget_proxy.input_data self.input_condition.release() return inp def help_replacement(self, text=None, interactive=False): """For help builtin function emulation""" if text is not None and not interactive: return pydoc.help(text) elif text is None: pyver = "%d.%d" % (sys.version_info[0], sys.version_info[1]) self.write(""" Welcome to Python %s! This is the online help utility. If this is your first time using Python, you should definitely check out the tutorial on the Internet at http://www.python.org/doc/tut/. Enter the name of any module, keyword, or topic to get help on writing Python programs and using Python modules. To quit this help utility and return to the interpreter, just type "quit". To get a list of available modules, keywords, or topics, type "modules", "keywords", or "topics". Each module also comes with a one-line summary of what it does; to list the modules whose summaries contain a given word such as "spam", type "modules spam". """ % pyver) else: text = text.strip() try: eval("pydoc.help(%s)" % text) except (NameError, SyntaxError): print("no Python documentation found for '%r'" % text) # spyder: test-skip self.write(os.linesep) self.widget_proxy.new_prompt("help> ") inp = self.raw_input_replacement() if inp.strip(): self.help_replacement(inp, interactive=True) else: self.write(""" You are now leaving help and returning to the Python interpreter. If you want to ask for help on a particular object directly from the interpreter, you can type "help(object)". Executing "help('string')" has the same effect as typing a particular string at the help> prompt. """) def run_command(self, cmd, new_prompt=True): """Run command in interpreter""" if cmd == 'exit()': self.exit_flag = True self.write('\n') return # -- Special commands type I # (transformed into commands executed in the interpreter) # ? command special_pattern = r"^%s (?:r\')?(?:u\')?\"?\'?([a-zA-Z0-9_\.]+)" run_match = re.match(special_pattern % 'run', cmd) help_match = re.match(r'^([a-zA-Z0-9_\.]+)\?$', cmd) cd_match = re.match(r"^\!cd \"?\'?([a-zA-Z0-9_ \.]+)", cmd) if help_match: cmd = 'help(%s)' % help_match.group(1) # run command elif run_match: filename = guess_filename(run_match.groups()[0]) cmd = "runfile('%s', args=None)" % remove_backslashes(filename) # !cd system command elif cd_match: cmd = 'import os; os.chdir(r"%s")' % cd_match.groups()[0].strip() # -- End of Special commands type I # -- Special commands type II # (don't need code execution in interpreter) xedit_match = re.match(special_pattern % 'xedit', cmd) edit_match = re.match(special_pattern % 'edit', cmd) clear_match = re.match(r"^clear ([a-zA-Z0-9_, ]+)", cmd) # (external) edit command if xedit_match: filename = guess_filename(xedit_match.groups()[0]) self.widget_proxy.edit(filename, external_editor=True) # local edit command elif edit_match: filename = guess_filename(edit_match.groups()[0]) if osp.isfile(filename): self.widget_proxy.edit(filename) else: self.stderr_write.write( "No such file or directory: %s\n" % filename) # remove reference (equivalent to MATLAB's clear command) elif clear_match: varnames = clear_match.groups()[0].replace(' ', '').split(',') for varname in varnames: try: self.namespace.pop(varname) except KeyError: pass # Execute command elif cmd.startswith('!'): # System ! command pipe = programs.run_shell_command(cmd[1:]) txt_out = encoding.transcode( pipe.stdout.read().decode() ) txt_err = encoding.transcode( pipe.stderr.read().decode().rstrip() ) if txt_err: self.stderr_write.write(txt_err) if txt_out: self.stdout_write.write(txt_out) self.stdout_write.write('\n') self.more = False # -- End of Special commands type II else: # Command executed in the interpreter # self.widget_proxy.set_readonly(True) self.more = self.push(cmd) # self.widget_proxy.set_readonly(False) if new_prompt: self.widget_proxy.new_prompt(self.p2 if self.more else self.p1) if not self.more: self.resetbuffer() def run(self): """Wait for input and run it""" while not self.exit_flag: self.run_line() def run_line(self): line = self.stdin_read.readline() if self.exit_flag: return # Remove last character which is always '\n': self.run_command(line[:-1]) def get_thread_id(self): """Return thread id""" if self._id is None: for thread_id, obj in list(threading._active.items()): if obj is self: self._id = thread_id return self._id def raise_keyboard_interrupt(self): if self.isAlive(): ctypes.pythonapi.PyThreadState_SetAsyncExc(self.get_thread_id(), ctypes.py_object(KeyboardInterrupt)) return True else: return False def closing(self): """Actions to be done before restarting this interpreter""" pass def execfile(self, filename): """Exec filename""" source = open(filename, 'r').read() try: try: name = filename.encode('ascii') except UnicodeEncodeError: name = '' code = compile(source, name, "exec") except (OverflowError, SyntaxError): InteractiveConsole.showsyntaxerror(self, filename) else: self.runcode(code) def runfile(self, filename, args=None): """ Run filename args: command line arguments (string) """ if args is not None and not is_text_string(args): raise TypeError("expected a character buffer object") self.namespace['__file__'] = filename sys.argv = [filename] if args is not None: for arg in args.split(): sys.argv.append(arg) self.execfile(filename) sys.argv = [''] self.namespace.pop('__file__') def eval(self, text): """ Evaluate text and return (obj, valid) where *obj* is the object represented by *text* and *valid* is True if object evaluation did not raise any exception """ assert is_text_string(text) try: return eval(text, self.locals), True except: return None, False def is_defined(self, objtxt, force_import=False): """Return True if object is defined""" return isdefined(objtxt, force_import=force_import, namespace=self.locals) #=========================================================================== # InteractiveConsole API #=========================================================================== def push(self, line): """ Push a line of source text to the interpreter The line should not have a trailing newline; it may have internal newlines. The line is appended to a buffer and the interpreter’s runsource() method is called with the concatenated contents of the buffer as source. If this indicates that the command was executed or invalid, the buffer is reset; otherwise, the command is incomplete, and the buffer is left as it was after the line was appended. The return value is True if more input is required, False if the line was dealt with in some way (this is the same as runsource()). """ return InteractiveConsole.push(self, "#coding=utf-8\n" + line) def resetbuffer(self): """Remove any unhandled source text from the input buffer""" InteractiveConsole.resetbuffer(self) spyder-3.2.6/spyder/pyplot.py0000664000175000017500000000026213224121062017022 0ustar carloscarlos00000000000000# -*- coding:utf-8 -*- """ Importing guiqwt's pyplot module or matplotlib's pyplot """ try: from guiqwt.pyplot import * except: from matplotlib.pyplot import * spyder-3.2.6/spyder/__init__.py0000664000175000017500000000615213225024631017243 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- """ Spyder License Agreement (MIT License) -------------------------------------- Copyright (c) Spyder Project Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ version_info = (3, 2, 6) __version__ = '.'.join(map(str, version_info)) __license__ = __doc__ __project_url__ = 'https://github.com/spyder-ide/spyder' __forum_url__ = 'http://groups.google.com/group/spyderlib' # Dear (Debian, RPM, ...) package makers, please feel free to customize the # following path to module's data (images) and translations: DATAPATH = LOCALEPATH = DOCPATH = MATHJAXPATH = JQUERYPATH = '' import os # Directory of the current file __dir__ = os.path.dirname(os.path.abspath(__file__)) def add_to_distribution(dist): """Add package to py2exe/cx_Freeze distribution object Extension to guidata.disthelpers""" try: dist.add_qt_bindings() except AttributeError: raise ImportError("This script requires guidata 1.5+") for _modname in ('spyder', 'spyderplugins'): dist.add_module_data_files(_modname, ("", ), ('.png', '.svg', '.html', '.png', '.txt', '.js', '.inv', '.ico', '.css', '.doctree', '.qm', '.py',), copy_to_root=False) def get_versions(reporev=True): """Get version information for components used by Spyder""" import sys import platform import qtpy import qtpy.QtCore revision = None if reporev: from spyder.utils import vcs revision, branch = vcs.get_git_revision(os.path.dirname(__dir__)) if not sys.platform == 'darwin': # To avoid a crash with our Mac app system = platform.system() else: system = 'Darwin' return { 'spyder': __version__, 'python': platform.python_version(), # "2.7.3" 'bitness': 64 if sys.maxsize > 2**32 else 32, 'qt': qtpy.QtCore.__version__, 'qt_api': qtpy.API_NAME, # PyQt5 or PyQt4 'qt_api_ver': qtpy.PYQT_VERSION, 'system': system, # Linux, Windows, ... 'revision': revision, # '9fdf926eccce' } spyder-3.2.6/spyder/fonts/0000775000175000017500000000000013225025007016255 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/fonts/spyder.ttf0000664000175000017500000002113013026261006020277 0ustar carloscarlos00000000000000`FFTMpd?"<GDEF"OS/2A\ h`cmapL@jcvt ;ogasp"glyf head `6hhea&$$hmtxE vlocaxbmaxp{H nameW4postH ("L_< __ 0 @.\YPfEd@Zf ;U U7 dH&>CZ;BU  ;o,,,\V8V:nR0vF $ v : < J  V ;./<2<2/<2<23!%!!;adV;4&54646&5- : s  :  :4:  %52476;2+"'&5'&547632+"&546   : &&&&:  :&&&& 2"&42"&4!!35 5!"&546ԖԖ֗֘0PPԖ֗P00P/L#!"&=463!2#!"&=463!2#!"&=463!2!!35 5!"'&'&'&=4767676&&&&&&&&&&&&@ ڀ&&&&f&&&&f&&&&UU + ,<L!2#!"&=46!!35 5!"'&'&'&=4767676)2#!"&=46!2#!"&=46@&&&&Z@ &&&&&&&&&&&&UU + &&&&&&&&/L#!"&=463!2#!"&=463!2#!"&=463!2!!35 5!"'&'&'&=4767676&&&&&&&&&&&&@ ڀ&&&&f&&&&f&&&&UU + #!"&5463!2&&&&@&&&&!2#!"&546!!!!!!!4LL44LL4L44LL44L"62346;232#!"&546;476!#+"&5#&5 s`&&NrrNNrrN &&`@&&rNNrrNNr` ~&&@ `"%'&546476;2+"'&5   ( :  -Bt2#!"#"'&'&54767676;!5!5476767676"27654'&'&'&32+!!+"'&'&5476763!265"327654'&wa`Oj66M]FEM23"#.15r$%:Rj : bM+- *r4 "#`\McR43*+2r] jHL87DC\25SpMPh:+,/+ p   11WpW]Q6! .' , 0/E]2+*_/-B2#!"#"'&'&54767676;!5!5476767676"27654'&'&'&wa`Oj66M]FEM23"#.15r$%:Rj :  jHL87DC\25SpMPh:+,/+ p    1A32+!!+"'&'&5476763!265"327654'&M+- *r4 "#`\McR43*+2r]11WpW]Q6! .' , 0/E]2+*_/ jnLRY^cinv|7&''67%"'#'67".#&/7323;&'7 767>767&7%67%'%7&%7:!- r Ni  ,57G >"5Ye    , G $EB@4Rs/rS#KXZU+dG]ۯqaen)1H/B! 9  87ۊ_&   ?JGx:= D!P+xlT S0^f+orTb+;|r= DqX Ui%3232?0547632##"/&#"'76G>*).=;H1>XY?*)W>i>. A==N;>1>?V>7H %Dv')rHa ' 1Ia#"/"/&4?'&463!2#!"&54632762#!"&4?'&4?62762"/"&5463!2&+  r ̐&&s ̐&@&&$  r&@& r  ̐4&s r  ̐4&&&Z@& r  ̐4&& ̐4&&& rI&&4  r ̐&- r ̐&&&4!2#!"&546!!2765@B^^BB^^" @ ^B@B^^BB^  !2#!"&546!2765@B^^BB^^" @ ^B@B^^BB^ `$!2#!"&546!2765!! !!@B^^BB^^" @ @^B@B^^BB^ `@@@"!2#!"&546!2765!!! !@B^^BB^^"` @^B@B^^BB^ `@@(!!!!!5!!5!7673#"'53276?<,BVA?K5$ *f+mB3M.B Dd!!5!!5!!!  !!!!5!!!!!!@W[_3!5463!2+!5463!2#!"&=!!5463!2#!"&=!#5#"&=!!5463!2#!"&=!#53535&&&@@&&&&@&&&&@@&&&&&@@@&&&@&&&&@@&&&&@@&@@&&&&@@@)7K4.#"632&#"327!5#'#"&54>32$ '&'&7676 k $9Hd<)Ф6V6' heCě/m\(Fegg\ggggg9(:)-bb\-$6C.G[R'wfwQ%J7,\gggggggg9M#".'.#"32>7'#".54>327&547 '&'&7676   TPgxU'Ehu;'9f^04be-O:2! dgg\ggggg& "F-;bG *C)RHtFHpD **%d,9\gggggggg"63#!5!!5!54>327&#" '&'&7676 S00+B+.LsJ/gg\gggggZYYhZd2" _)/G@,j \gggggggg3#3#33!335#35##!!$ '&'&7676 hTTſT^gg\ggggguuu+uoo+\gggggggg7K3#!5#63235#63235#4&'.#".#"5 '&'&7676 zzMzRZ!0 oU[(fZ/l`a9&N4gg\gggggUTTe%>' Tw" :$!TcX'#*q5<?\gggggggg ",0D"32654.2#"&546"3264&2#"&46 $ '&'&7676 uts8wOITUHFVUsqsrGUVFGWUm)$igg\gggggߖ\:kKT]=>^\@>\ە[]T]~[]z_TB6\gggggggg"63#!5!>327.#"5 '&'&7676 *{#&aNn2%9l!8I.8oMa*)gg\gggggaP``'(Z2+P&"(N()\gggggggg#%5&'&#!"3!27>7 $$     B\``ۀ  \``!!"%'&546476;2+"'&5' npp  4l5 !!35 5!"'&'&'&=4767676@ UU + !%)-!221#!"&54747676!!!W( (8 R =(8(@  @@#-15!2#!"'&547633332764'&#32+%3535 vVTTVv@vVTTVVqI??@zEL&0;TVv@vVTTVvvVT+D;9;ULDE&0<  *4$ $7#"'"632&$4632"4632#"4632#"ofNMgFfMwvNfR X1#"11"#D10DD01@w wkw w D11D1`DD`D5 @ @>k|!= <  ] r B      /Copyright (c) 2015, sylvain,,,Copyright (c) 2015, sylvain,,,SpyderSpyderBookBookFontForge 2.0 : Spyder : 9-2-2016FontForge 2.0 : Spyder : 9-2-2016SpyderSpyderVersion 001.000 Version 001.000 SpyderSpyder0      !"#$%&'()*+,-.uniE000uniE001uniE005uniE006uniE007uniE008uniE009uniE00AuniE00BuniE00CuniE00DuniE00EuniE00FuniE010uniE011uniE012uniE013uniE014uniE015uniE016uniE017uniE018uniE019uniE01AuniE01BuniE01FuniE020uniE021uniE022uniE023uniE024uniE025uniE026uniE03BuniE03CuniE03DuniE03EuniE042uniE043uniE055uniE056uniE057uniE058uniE059uniE05A=F=Z_spyder-3.2.6/spyder/fonts/spyder-charmap.json0000664000175000017500000000254313026261006022073 0ustar carloscarlos00000000000000{ "continue": "0xE000", "debug": "0xE001", "run-cell": "0xE003", "run-cell-inplace": "0xE004", "step-forward": "0xE005", "step-into": "0xE006", "step-out": "0xE007", "step-over": "0xE008", "stop": "0xE009", "cell": "0xE00A", "cell-code": "0xE03B", "cell-play": "0xE03C", "cell-next": "0xE03D", "cell-border": "0xE03E", "run-one-inplace": "0xE00B", "run-one": "0xE00C", "python-logo": "0xE00D", "python-logo-up": "0xE00E", "python-logo-down": "0xE00F", "spyder-logo-web": "0xE010", "spyder-logo-snake": "0xE011", "spyder-logo-background": "0xE012", "inward": "0xE013", "rows": "0xE014", "window": "0xE015", "maximize-pane": "0xE016", "minimize-pane": "0xE017", "ipython-logo": "0xE018", "ipython-logo-alt": "0xE042", "jupyter-logo": "0xE043", "run-selection": "0xE019", "text-select-all": "0xE01A", "treeview": "0xE01B", "circle-letter-a": "0xE01F", "circle-letter-c": "0xE020", "circle-letter-f": "0xE021", "circle-hash": "0xE022", "circle-letter-m": "0xE023", "circle-percent": "0xE024", "circle-letter-r": "0xE025", "circle-underscore": "0xE026", "cube-front": "0xE055", "cube-bottom": "0xE056", "cube-right": "0xE057", "cube-left": "0xE058", "cube-rear": "0xE059", "cube-top": "0xE060" } spyder-3.2.6/spyder/workers/0000775000175000017500000000000013225025007016620 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/workers/updates.py0000664000175000017500000000664413224740762020664 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) # Standard library imports import json import ssl # Third party imports from qtpy.QtCore import QObject, Signal # Local imports from spyder import __version__ from spyder.config.base import _ from spyder.py3compat import PY3 from spyder.utils.programs import check_version, is_stable_version if PY3: from urllib.request import urlopen from urllib.error import URLError, HTTPError else: from urllib2 import urlopen, URLError, HTTPError class WorkerUpdates(QObject): """ Worker that checks for releases using the Github API without blocking the Spyder user interface, in case of connections issues. """ sig_ready = Signal() def __init__(self, parent, startup): QObject.__init__(self) self._parent = parent self.error = None self.latest_release = None self.startup = startup def check_update_available(self, version, releases): """Checks if there is an update available. It takes as parameters the current version of Spyder and a list of valid cleaned releases in chronological order (what github api returns by default). Example: ['2.3.4', '2.3.3' ...] """ if is_stable_version(version): # Remove non stable versions from the list releases = [r for r in releases if is_stable_version(r)] latest_release = releases[0] if version.endswith('dev'): return (False, latest_release) return (check_version(version, latest_release, '<'), latest_release) def start(self): """Main method of the WorkerUpdates worker""" self.url = 'https://api.github.com/repos/spyder-ide/spyder/releases' self.update_available = False self.latest_release = __version__ error_msg = None try: if hasattr(ssl, '_create_unverified_context'): # Fix for issue # 2685 [Works only with Python >=2.7.9] # More info: https://www.python.org/dev/peps/pep-0476/#opting-out context = ssl._create_unverified_context() page = urlopen(self.url, context=context) else: page = urlopen(self.url) try: data = page.read() # Needed step for python3 compatibility if not isinstance(data, str): data = data.decode() data = json.loads(data) releases = [item['tag_name'].replace('v', '') for item in data] version = __version__ result = self.check_update_available(version, releases) self.update_available, self.latest_release = result except Exception: error_msg = _('Unable to retrieve information.') except HTTPError: error_msg = _('Unable to retrieve information.') except URLError: error_msg = _('Unable to connect to the internet.

    Make ' 'sure the connection is working properly.') except Exception: error_msg = _('Unable to check for updates.') # Don't show dialog when starting up spyder and an error occur if not (self.startup and error_msg is not None): self.error = error_msg self.sig_ready.emit() spyder-3.2.6/spyder/workers/__init__.py0000664000175000017500000000000013026261006020717 0ustar carloscarlos00000000000000spyder-3.2.6/spyder/utils/0000775000175000017500000000000013225025007016264 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/utils/test.py0000664000175000017500000000140513224121062017612 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Tests utilities.""" # Standard library imports import os # Third party imports from qtpy.QtCore import Qt from qtpy.QtWidgets import QMessageBox, QApplication def close_message_box(qtbot): """ Closes QMessageBox's that can appear when testing. You can use this with QTimer to close a QMessageBox. Before calling anything that may show a QMessageBox call: QTimer.singleShot(1000, lambda: close_message_box(qtbot)) """ top_level_widgets = QApplication.topLevelWidgets() for w in top_level_widgets: if isinstance(w, QMessageBox): qtbot.keyClick(w, Qt.Key_Enter) spyder-3.2.6/spyder/utils/dochelpers.py0000664000175000017500000003013713224121062020767 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Utilities and wrappers around inspect module""" from __future__ import print_function import inspect import re # Local imports: from spyder.utils import encoding from spyder.py3compat import (is_text_string, builtins, get_meth_func, get_meth_class_inst, get_meth_class, get_func_defaults, to_text_string, PY2) SYMBOLS = r"[^\'\"a-zA-Z0-9_.]" def getobj(txt, last=False): """Return the last valid object name in string""" txt_end = "" for startchar, endchar in ["[]", "()"]: if txt.endswith(endchar): pos = txt.rfind(startchar) if pos: txt_end = txt[pos:] txt = txt[:pos] tokens = re.split(SYMBOLS, txt) token = None try: while token is None or re.match(SYMBOLS, token): token = tokens.pop() if token.endswith('.'): token = token[:-1] if token.startswith('.'): # Invalid object name return None if last: #XXX: remove this statement as well as the "last" argument token += txt[ txt.rfind(token) + len(token) ] token += txt_end if token: return token except IndexError: return None def getobjdir(obj): """ For standard objects, will simply return dir(obj) In special cases (e.g. WrapITK package), will return only string elements of result returned by dir(obj) """ return [item for item in dir(obj) if is_text_string(item)] def getdoc(obj): """ Return text documentation from an object. This comes in a form of dictionary with four keys: name: The name of the inspected object argspec: It's argspec note: A phrase describing the type of object (function or method) we are inspecting, and the module it belongs to. docstring: It's docstring """ docstring = inspect.getdoc(obj) or inspect.getcomments(obj) or '' # Most of the time doc will only contain ascii characters, but there are # some docstrings that contain non-ascii characters. Not all source files # declare their encoding in the first line, so querying for that might not # yield anything, either. So assume the most commonly used # multi-byte file encoding (which also covers ascii). try: docstring = to_text_string(docstring) except: pass # Doc dict keys doc = {'name': '', 'argspec': '', 'note': '', 'docstring': docstring} if callable(obj): try: name = obj.__name__ except AttributeError: doc['docstring'] = docstring return doc if inspect.ismethod(obj): imclass = get_meth_class(obj) if get_meth_class_inst(obj) is not None: doc['note'] = 'Method of %s instance' \ % get_meth_class_inst(obj).__class__.__name__ else: doc['note'] = 'Unbound %s method' % imclass.__name__ obj = get_meth_func(obj) elif hasattr(obj, '__module__'): doc['note'] = 'Function of %s module' % obj.__module__ else: doc['note'] = 'Function' doc['name'] = obj.__name__ if inspect.isfunction(obj): if PY2: args, varargs, varkw, defaults = inspect.getargspec(obj) doc['argspec'] = inspect.formatargspec( args, varargs, varkw, defaults, formatvalue=lambda o:'='+repr(o)) else: (args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations) = inspect.getfullargspec(obj) doc['argspec'] = inspect.formatargspec( args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations, formatvalue=lambda o:'='+repr(o)) if name == '': doc['name'] = name + ' lambda ' doc['argspec'] = doc['argspec'][1:-1] # remove parentheses else: argspec = getargspecfromtext(doc['docstring']) if argspec: doc['argspec'] = argspec # Many scipy and numpy docstrings begin with a function # signature on the first line. This ends up begin redundant # when we are using title and argspec to create the # rich text "Definition:" field. We'll carefully remove this # redundancy but only under a strict set of conditions: # Remove the starting charaters of the 'doc' portion *iff* # the non-whitespace characters on the first line # match *exactly* the combined function title # and argspec we determined above. signature = doc['name'] + doc['argspec'] docstring_blocks = doc['docstring'].split("\n\n") first_block = docstring_blocks[0].strip() if first_block == signature: doc['docstring'] = doc['docstring'].replace( signature, '', 1).lstrip() else: doc['argspec'] = '(...)' # Remove self from argspec argspec = doc['argspec'] doc['argspec'] = argspec.replace('(self)', '()').replace('(self, ', '(') return doc def getsource(obj): """Wrapper around inspect.getsource""" try: try: src = encoding.to_unicode( inspect.getsource(obj) ) except TypeError: if hasattr(obj, '__class__'): src = encoding.to_unicode( inspect.getsource(obj.__class__) ) else: # Bindings like VTK or ITK require this case src = getdoc(obj) return src except (TypeError, IOError): return def getsignaturefromtext(text, objname): """Get object signatures from text (object documentation) Return a list containing a single string in most cases Example of multiple signatures: PyQt4 objects""" if isinstance(text, dict): text = text.get('docstring', '') # Regexps oneline_re = objname + r'\([^\)].+?(?<=[\w\]\}\'"])\)(?!,)' multiline_re = objname + r'\([^\)]+(?<=[\w\]\}\'"])\)(?!,)' multiline_end_parenleft_re = r'(%s\([^\)]+(\),\n.+)+(?<=[\w\]\}\'"])\))' # Grabbing signatures if not text: text = '' sigs_1 = re.findall(oneline_re + '|' + multiline_re, text) sigs_2 = [g[0] for g in re.findall(multiline_end_parenleft_re % objname, text)] all_sigs = sigs_1 + sigs_2 # The most relevant signature is usually the first one. There could be # others in doctests but those are not so important if all_sigs: return all_sigs[0] else: return '' # Fix for Issue 1953 # TODO: Add more signatures and remove this hack in 2.4 getsignaturesfromtext = getsignaturefromtext def getargspecfromtext(text): """ Try to get the formatted argspec of a callable from the first block of its docstring This will return something like '(foo, bar, k=1)' """ blocks = text.split("\n\n") first_block = blocks[0].strip() return getsignaturefromtext(first_block, '') def getargsfromtext(text, objname): """Get arguments from text (object documentation)""" signature = getsignaturefromtext(text, objname) if signature: argtxt = signature[signature.find('(')+1:-1] return argtxt.split(',') def getargsfromdoc(obj): """Get arguments from object doc""" if obj.__doc__ is not None: return getargsfromtext(obj.__doc__, obj.__name__) def getargs(obj): """Get the names and default values of a function's arguments""" if inspect.isfunction(obj) or inspect.isbuiltin(obj): func_obj = obj elif inspect.ismethod(obj): func_obj = get_meth_func(obj) elif inspect.isclass(obj) and hasattr(obj, '__init__'): func_obj = getattr(obj, '__init__') else: return [] if not hasattr(func_obj, 'func_code'): # Builtin: try to extract info from doc args = getargsfromdoc(func_obj) if args is not None: return args else: # Example: PyQt4 return getargsfromdoc(obj) args, _, _ = inspect.getargs(func_obj.func_code) if not args: return getargsfromdoc(obj) # Supporting tuple arguments in def statement: for i_arg, arg in enumerate(args): if isinstance(arg, list): args[i_arg] = "(%s)" % ", ".join(arg) defaults = get_func_defaults(func_obj) if defaults is not None: for index, default in enumerate(defaults): args[index+len(args)-len(defaults)] += '='+repr(default) if inspect.isclass(obj) or inspect.ismethod(obj): if len(args) == 1: return None if 'self' in args: args.remove('self') return args def getargtxt(obj, one_arg_per_line=True): """ Get the names and default values of a function's arguments Return list with separators (', ') formatted for calltips """ args = getargs(obj) if args: sep = ', ' textlist = None for i_arg, arg in enumerate(args): if textlist is None: textlist = [''] textlist[-1] += arg if i_arg < len(args)-1: textlist[-1] += sep if len(textlist[-1]) >= 32 or one_arg_per_line: textlist.append('') if inspect.isclass(obj) or inspect.ismethod(obj): if len(textlist) == 1: return None if 'self'+sep in textlist: textlist.remove('self'+sep) return textlist def isdefined(obj, force_import=False, namespace=None): """Return True if object is defined in namespace If namespace is None --> namespace = locals()""" if namespace is None: namespace = locals() attr_list = obj.split('.') base = attr_list.pop(0) if len(base) == 0: return False if base not in builtins.__dict__ and base not in namespace: if force_import: try: module = __import__(base, globals(), namespace) if base not in globals(): globals()[base] = module namespace[base] = module except (ImportError, NameError, SyntaxError, SystemExit): return False else: return False for attr in attr_list: try: attr_not_found = not hasattr(eval(base, namespace), attr) except (SyntaxError, AttributeError): return False if attr_not_found: if force_import: try: __import__(base+'.'+attr, globals(), namespace) except (ImportError, SyntaxError): return False else: return False base += '.'+attr return True if __name__ == "__main__": class Test(object): def method(self, x, y=2): pass print(getargtxt(Test.__init__)) # spyder: test-skip print(getargtxt(Test.method)) # spyder: test-skip print(isdefined('numpy.take', force_import=True)) # spyder: test-skip print(isdefined('__import__')) # spyder: test-skip print(isdefined('.keys', force_import=True)) # spyder: test-skip print(getobj('globals')) # spyder: test-skip print(getobj('globals().keys')) # spyder: test-skip print(getobj('+scipy.signal.')) # spyder: test-skip print(getobj('4.')) # spyder: test-skip print(getdoc(sorted)) # spyder: test-skip print(getargtxt(sorted)) # spyder: test-skip spyder-3.2.6/spyder/utils/qthelpers.py0000664000175000017500000004722013224121062020647 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Qt utilities""" # Standard library imports import os import os.path as osp import re import sys # Third party imports from qtpy.compat import to_qvariant, from_qvariant from qtpy.QtCore import (QEvent, QLibraryInfo, QLocale, QObject, Qt, QTimer, QTranslator, Signal, Slot) from qtpy.QtGui import QIcon, QKeyEvent, QKeySequence, QPixmap from qtpy.QtWidgets import (QAction, QApplication, QHBoxLayout, QLabel, QLineEdit, QMenu, QStyle, QToolBar, QToolButton, QVBoxLayout, QWidget) # Local imports from spyder.config.base import get_image_path, running_in_mac_app from spyder.config.gui import get_shortcut from spyder.utils import programs from spyder.utils import icon_manager as ima from spyder.utils.icon_manager import get_icon, get_std_icon from spyder.py3compat import is_text_string, to_text_string # Note: How to redirect a signal from widget *a* to widget *b* ? # ---- # It has to be done manually: # * typing 'SIGNAL("clicked()")' works # * typing 'signalstr = "clicked()"; SIGNAL(signalstr)' won't work # Here is an example of how to do it: # (self.listwidget is widget *a* and self is widget *b*) # self.connect(self.listwidget, SIGNAL('option_changed'), # lambda *args: self.emit(SIGNAL('option_changed'), *args)) def get_image_label(name, default="not_found.png"): """Return image inside a QLabel object""" label = QLabel() label.setPixmap(QPixmap(get_image_path(name, default))) return label class MacApplication(QApplication): """Subclass to be able to open external files with our Mac app""" sig_open_external_file = Signal(str) def __init__(self, *args): QApplication.__init__(self, *args) def event(self, event): if event.type() == QEvent.FileOpen: fname = str(event.file()) self.sig_open_external_file.emit(fname) return QApplication.event(self, event) def qapplication(translate=True, test_time=3): """ Return QApplication instance Creates it if it doesn't already exist test_time: Time to maintain open the application when testing. It's given in seconds """ if running_in_mac_app(): SpyderApplication = MacApplication else: SpyderApplication = QApplication app = SpyderApplication.instance() if app is None: # Set Application name for Gnome 3 # https://groups.google.com/forum/#!topic/pyside/24qxvwfrRDs app = SpyderApplication(['Spyder']) # Set application name for KDE (See issue 2207) app.setApplicationName('Spyder') if translate: install_translator(app) test_ci = os.environ.get('TEST_CI_WIDGETS', None) if test_ci is not None: timer_shutdown = QTimer(app) timer_shutdown.timeout.connect(app.quit) timer_shutdown.start(test_time*1000) return app def file_uri(fname): """Select the right file uri scheme according to the operating system""" if os.name == 'nt': # Local file if re.search(r'^[a-zA-Z]:', fname): return 'file:///' + fname # UNC based path else: return 'file://' + fname else: return 'file://' + fname QT_TRANSLATOR = None def install_translator(qapp): """Install Qt translator to the QApplication instance""" global QT_TRANSLATOR if QT_TRANSLATOR is None: qt_translator = QTranslator() if qt_translator.load("qt_"+QLocale.system().name(), QLibraryInfo.location(QLibraryInfo.TranslationsPath)): QT_TRANSLATOR = qt_translator # Keep reference alive if QT_TRANSLATOR is not None: qapp.installTranslator(QT_TRANSLATOR) def keybinding(attr): """Return keybinding""" ks = getattr(QKeySequence, attr) return from_qvariant(QKeySequence.keyBindings(ks)[0], str) def _process_mime_path(path, extlist): if path.startswith(r"file://"): if os.name == 'nt': # On Windows platforms, a local path reads: file:///c:/... # and a UNC based path reads like: file://server/share if path.startswith(r"file:///"): # this is a local path path=path[8:] else: # this is a unc path path = path[5:] else: path = path[7:] path = path.replace('%5C' , os.sep) # Transforming backslashes if osp.exists(path): if extlist is None or osp.splitext(path)[1] in extlist: return path def mimedata2url(source, extlist=None): """ Extract url list from MIME data extlist: for example ('.py', '.pyw') """ pathlist = [] if source.hasUrls(): for url in source.urls(): path = _process_mime_path(to_text_string(url.toString()), extlist) if path is not None: pathlist.append(path) elif source.hasText(): for rawpath in to_text_string(source.text()).splitlines(): path = _process_mime_path(rawpath, extlist) if path is not None: pathlist.append(path) if pathlist: return pathlist def keyevent2tuple(event): """Convert QKeyEvent instance into a tuple""" return (event.type(), event.key(), event.modifiers(), event.text(), event.isAutoRepeat(), event.count()) def tuple2keyevent(past_event): """Convert tuple into a QKeyEvent instance""" return QKeyEvent(*past_event) def restore_keyevent(event): if isinstance(event, tuple): _, key, modifiers, text, _, _ = event event = tuple2keyevent(event) else: text = event.text() modifiers = event.modifiers() key = event.key() ctrl = modifiers & Qt.ControlModifier shift = modifiers & Qt.ShiftModifier return event, text, key, ctrl, shift def create_toolbutton(parent, text=None, shortcut=None, icon=None, tip=None, toggled=None, triggered=None, autoraise=True, text_beside_icon=False): """Create a QToolButton""" button = QToolButton(parent) if text is not None: button.setText(text) if icon is not None: if is_text_string(icon): icon = get_icon(icon) button.setIcon(icon) if text is not None or tip is not None: button.setToolTip(text if tip is None else tip) if text_beside_icon: button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) button.setAutoRaise(autoraise) if triggered is not None: button.clicked.connect(triggered) if toggled is not None: button.toggled.connect(toggled) button.setCheckable(True) if shortcut is not None: button.setShortcut(shortcut) return button def action2button(action, autoraise=True, text_beside_icon=False, parent=None): """Create a QToolButton directly from a QAction object""" if parent is None: parent = action.parent() button = QToolButton(parent) button.setDefaultAction(action) button.setAutoRaise(autoraise) if text_beside_icon: button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) return button def toggle_actions(actions, enable): """Enable/disable actions""" if actions is not None: for action in actions: if action is not None: action.setEnabled(enable) def create_action(parent, text, shortcut=None, icon=None, tip=None, toggled=None, triggered=None, data=None, menurole=None, context=Qt.WindowShortcut): """Create a QAction""" action = SpyderAction(text, parent) if triggered is not None: action.triggered.connect(triggered) if toggled is not None: action.toggled.connect(toggled) action.setCheckable(True) if icon is not None: if is_text_string(icon): icon = get_icon(icon) action.setIcon(icon) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if data is not None: action.setData(to_qvariant(data)) if menurole is not None: action.setMenuRole(menurole) # Workround for Mac because setting context=Qt.WidgetShortcut # there doesn't have any effect if sys.platform == 'darwin': action._shown_shortcut = None if context == Qt.WidgetShortcut: if shortcut is not None: action._shown_shortcut = shortcut else: # This is going to be filled by # main.register_shortcut action._shown_shortcut = 'missing' else: if shortcut is not None: action.setShortcut(shortcut) action.setShortcutContext(context) else: if shortcut is not None: action.setShortcut(shortcut) action.setShortcutContext(context) return action def add_shortcut_to_tooltip(action, context, name): """Add the shortcut associated with a given action to its tooltip""" action.setToolTip(action.toolTip() + ' (%s)' % get_shortcut(context=context, name=name)) def add_actions(target, actions, insert_before=None): """Add actions to a QMenu or a QToolBar.""" previous_action = None target_actions = list(target.actions()) if target_actions: previous_action = target_actions[-1] if previous_action.isSeparator(): previous_action = None for action in actions: if (action is None) and (previous_action is not None): if insert_before is None: target.addSeparator() else: target.insertSeparator(insert_before) elif isinstance(action, QMenu): if insert_before is None: target.addMenu(action) else: target.insertMenu(insert_before, action) elif isinstance(action, QAction): if isinstance(action, SpyderAction): if isinstance(target, QMenu) or not isinstance(target, QToolBar): try: action = action.no_icon_action except RuntimeError: continue if insert_before is None: # This is needed in order to ignore adding an action whose # wrapped C/C++ object has been deleted. See issue 5074 try: target.addAction(action) except RuntimeError: continue else: target.insertAction(insert_before, action) previous_action = action def get_item_user_text(item): """Get QTreeWidgetItem user role string""" return from_qvariant(item.data(0, Qt.UserRole), to_text_string) def set_item_user_text(item, text): """Set QTreeWidgetItem user role string""" item.setData(0, Qt.UserRole, to_qvariant(text)) def create_bookmark_action(parent, url, title, icon=None, shortcut=None): """Create bookmark action""" @Slot() def open_url(): return programs.start_file(url) return create_action( parent, title, shortcut=shortcut, icon=icon, triggered=open_url) def create_module_bookmark_actions(parent, bookmarks): """ Create bookmark actions depending on module installation: bookmarks = ((module_name, url, title), ...) """ actions = [] for key, url, title in bookmarks: # Create actions for scientific distros only if Spyder is installed # under them create_act = True if key == 'winpython': if not programs.is_module_installed(key): create_act = False if create_act: act = create_bookmark_action(parent, url, title) actions.append(act) return actions def create_program_action(parent, text, name, icon=None, nt_name=None): """Create action to run a program""" if is_text_string(icon): icon = get_icon(icon) if os.name == 'nt' and nt_name is not None: name = nt_name path = programs.find_program(name) if path is not None: return create_action(parent, text, icon=icon, triggered=lambda: programs.run_program(name)) def create_python_script_action(parent, text, icon, package, module, args=[]): """Create action to run a GUI based Python script""" if is_text_string(icon): icon = get_icon(icon) if programs.python_script_exists(package, module): return create_action(parent, text, icon=icon, triggered=lambda: programs.run_python_script(package, module, args)) class DialogManager(QObject): """ Object that keep references to non-modal dialog boxes for another QObject, typically a QMainWindow or any kind of QWidget """ def __init__(self): QObject.__init__(self) self.dialogs = {} 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 dialog_finished(self, dialog_id): """Manage non-modal dialog boxes""" return self.dialogs.pop(dialog_id) def close_all(self): """Close all opened dialog boxes""" for dlg in list(self.dialogs.values()): dlg.reject() def get_filetype_icon(fname): """Return file type icon""" ext = osp.splitext(fname)[1] if ext.startswith('.'): ext = ext[1:] return get_icon( "%s.png" % ext, ima.icon('FileIcon') ) class SpyderAction(QAction): """Spyder QAction class wrapper to handle cross platform patches.""" def __init__(self, *args, **kwargs): """Spyder QAction class wrapper to handle cross platform patches.""" super(SpyderAction, self).__init__(*args, **kwargs) self._action_no_icon = None if sys.platform == 'darwin': self._action_no_icon = QAction(*args, **kwargs) self._action_no_icon.setIcon(QIcon()) self._action_no_icon.triggered.connect(self.triggered) self._action_no_icon.toggled.connect(self.toggled) self._action_no_icon.changed.connect(self.changed) self._action_no_icon.hovered.connect(self.hovered) else: self._action_no_icon = self def __getattribute__(self, name): """Intercept method calls and apply to both actions, except signals.""" attr = super(SpyderAction, self).__getattribute__(name) if hasattr(attr, '__call__') and name not in ['triggered', 'toggled', 'changed', 'hovered']: def newfunc(*args, **kwargs): result = attr(*args, **kwargs) if name not in ['setIcon']: action_no_icon = self.__dict__['_action_no_icon'] attr_no_icon = super(QAction, action_no_icon).__getattribute__(name) attr_no_icon(*args, **kwargs) return result return newfunc else: return attr @property def no_icon_action(self): """Return the action without an Icon.""" return self._action_no_icon class ShowStdIcons(QWidget): """ Dialog showing standard icons """ def __init__(self, parent): QWidget.__init__(self, parent) layout = QHBoxLayout() row_nb = 14 cindex = 0 for child in dir(QStyle): if child.startswith('SP_'): if cindex == 0: col_layout = QVBoxLayout() icon_layout = QHBoxLayout() icon = get_std_icon(child) label = QLabel() label.setPixmap(icon.pixmap(32, 32)) icon_layout.addWidget( label ) icon_layout.addWidget( QLineEdit(child.replace('SP_', '')) ) col_layout.addLayout(icon_layout) cindex = (cindex+1) % row_nb if cindex == 0: layout.addLayout(col_layout) self.setLayout(layout) self.setWindowTitle('Standard Platform Icons') self.setWindowIcon(get_std_icon('TitleBarMenuButton')) def show_std_icons(): """ Show all standard Icons """ app = qapplication() dialog = ShowStdIcons(None) dialog.show() sys.exit(app.exec_()) def calc_tools_spacing(tools_layout): """ Return a spacing (int) or None if we don't have the appropriate metrics to calculate the spacing. We're trying to adapt the spacing below the tools_layout spacing so that the main_widget has the same vertical position as the editor widgets (which have tabs above). The required spacing is spacing = tabbar_height - tools_height + offset where the tabbar_heights were empirically determined for a combination of operating systems and styles. Offsets were manually adjusted, so that the heights of main_widgets and editor widgets match. This is probably caused by a still not understood element of the layout and style metrics. """ metrics = { # (tabbar_height, offset) 'nt.fusion': (32, 0), 'nt.windowsvista': (21, 3), 'nt.windowsxp': (24, 0), 'nt.windows': (21, 3), 'posix.breeze': (28, -1), 'posix.oxygen': (38, -2), 'posix.qtcurve': (27, 0), 'posix.windows': (26, 0), 'posix.fusion': (32, 0), } style_name = qapplication().style().property('name') key = '%s.%s' % (os.name, style_name) if key in metrics: tabbar_height, offset = metrics[key] tools_height = tools_layout.sizeHint().height() spacing = tabbar_height - tools_height + offset return max(spacing, 0) def create_plugin_layout(tools_layout, main_widget=None): """ Returns a layout for a set of controls above a main widget. This is a standard layout for many plugin panes (even though, it's currently more often applied not to the pane itself but with in the one widget contained in the pane. tools_layout: a layout containing the top toolbar main_widget: the main widget. Can be None, if you want to add this manually later on. """ layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) spacing = calc_tools_spacing(tools_layout) if spacing is not None: layout.setSpacing(spacing) layout.addLayout(tools_layout) if main_widget is not None: layout.addWidget(main_widget) return layout MENU_SEPARATOR = None if __name__ == "__main__": show_std_icons() spyder-3.2.6/spyder/utils/site/0000775000175000017500000000000013225025007017230 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/utils/site/sitecustomize.py0000664000175000017500000006542613224121062022523 0ustar carloscarlos00000000000000# # Copyright (c) Spyder Project Contributors) # Licensed under the terms of the MIT License) # (see spyder/__init__.py for details) # # IMPORTANT NOTE: Don't add a coding line here! It's not necessary for # site files # # Spyder consoles sitecustomize # import bdb from distutils.version import LooseVersion import io import os import os.path as osp import pdb import shlex import sys import time import warnings PY2 = sys.version[0] == '2' #============================================================================== # sys.argv can be missing when Python is embedded, taking care of it. # Fixes Issue 1473 and other crazy crashes with IPython 0.13 trying to # access it. #============================================================================== if not hasattr(sys, 'argv'): sys.argv = [''] #============================================================================== # Main constants #============================================================================== IS_EXT_INTERPRETER = os.environ.get('SPY_EXTERNAL_INTERPRETER') == "True" #============================================================================== # Important Note: # # We avoid importing spyder here, so we are handling Python 3 compatiblity # by hand. #============================================================================== def _print(*objects, **options): end = options.get('end', '\n') file = options.get('file', sys.stdout) sep = options.get('sep', ' ') string = sep.join([str(obj) for obj in objects]) if not PY2: # Python 3 local_dict = {} exec('printf = print', local_dict) # to avoid syntax error in Python 2 local_dict['printf'](string, file=file, end=end, sep=sep) else: # Python 2 if end: print >>file, string else: print >>file, string, #============================================================================== # Execfile functions # # The definitions for Python 2 on Windows were taken from the IPython project # Copyright (C) The IPython Development Team # Distributed under the terms of the modified BSD license #============================================================================== try: # Python 2 import __builtin__ as builtins if os.name == 'nt': def encode(u): return u.encode('utf8', 'replace') def execfile(fname, glob=None, loc=None): loc = loc if (loc is not None) else glob scripttext = builtins.open(fname).read()+ '\n' # compile converts unicode filename to str assuming # ascii. Let's do the conversion before calling compile if isinstance(fname, unicode): filename = encode(fname) else: filename = fname exec(compile(scripttext, filename, 'exec'), glob, loc) else: def execfile(fname, *where): if isinstance(fname, unicode): filename = fname.encode(sys.getfilesystemencoding()) else: filename = fname builtins.execfile(filename, *where) except ImportError: # Python 3 import builtins basestring = (str,) def execfile(filename, namespace): # Open a source file correctly, whatever its encoding is with open(filename, 'rb') as f: exec(compile(f.read(), filename, 'exec'), namespace) #============================================================================== # Prepending this spyder package's path to sys.path to be sure # that another version of spyder won't be imported instead: #============================================================================== spyder_path = osp.dirname(__file__) while not osp.isdir(osp.join(spyder_path, 'spyder')): spyder_path = osp.abspath(osp.join(spyder_path, os.pardir)) if not spyder_path.startswith(sys.prefix): # Spyder is not installed: moving its parent directory to the top of # sys.path to be sure that this spyder package will be imported in # the remote process (instead of another installed version of Spyder) while spyder_path in sys.path: sys.path.remove(spyder_path) sys.path.insert(0, spyder_path) os.environ['SPYDER_PARENT_DIR'] = spyder_path #============================================================================== # Setting console encoding (otherwise Python does not recognize encoding) # for Windows platforms #============================================================================== if os.name == 'nt' and PY2: try: import locale, ctypes _t, _cp = locale.getdefaultlocale('LANG') try: _cp = int(_cp[2:]) ctypes.windll.kernel32.SetConsoleCP(_cp) ctypes.windll.kernel32.SetConsoleOutputCP(_cp) except (ValueError, TypeError): # Code page number in locale is not valid pass except: pass #============================================================================== # Settings for our MacOs X app #============================================================================== # FIXME: If/when we create new apps we need to revisit this! if sys.platform == 'darwin': from spyder.config.base import MAC_APP_NAME if MAC_APP_NAME in __file__: if IS_EXT_INTERPRETER: # Add a minimal library (with spyder) at the end of sys.path to # be able to connect our monitor to the external console py_ver = '%s.%s' % (sys.version_info[0], sys.version_info[1]) app_pythonpath = '%s/Contents/Resources/lib/python%s' % (MAC_APP_NAME, py_ver) full_pythonpath = [p for p in sys.path if p.endswith(app_pythonpath)] if full_pythonpath: sys.path.remove(full_pythonpath[0]) sys.path.append(full_pythonpath[0] + osp.sep + 'minimal-lib') else: # Add missing variables and methods to the app's site module import site import osx_app_site osx_app_site.setcopyright() osx_app_site.sethelper() site._Printer = osx_app_site._Printer site.USER_BASE = osx_app_site.getuserbase() site.USER_SITE = osx_app_site.getusersitepackages() #============================================================================== # Add Cython files import and runfile support #============================================================================== try: # Import pyximport for enable Cython files support for import statement import pyximport HAS_PYXIMPORT = True pyx_setup_args = {} except: HAS_PYXIMPORT = False if HAS_PYXIMPORT: # Add Numpy include dir to pyximport/distutils try: import numpy pyx_setup_args['include_dirs'] = numpy.get_include() except: pass # Setup pyximport and enable Cython files reload pyximport.install(setup_args=pyx_setup_args, reload_support=True) try: # Import cython_inline for runfile function from Cython.Build.Inline import cython_inline HAS_CYTHON = True except: HAS_CYTHON = False #============================================================================== # Prevent subprocess.Popen calls to create visible console windows on Windows. # See issue #4932 #============================================================================== if os.name == 'nt': import subprocess creation_flag = 0x08000000 # CREATE_NO_WINDOW class SubprocessPopen(subprocess.Popen): def __init__(self, *args, **kwargs): kwargs['creationflags'] = creation_flag super(SubprocessPopen, self).__init__(*args, **kwargs) subprocess.Popen = SubprocessPopen #============================================================================== # Importing user's sitecustomize #============================================================================== try: import sitecustomize #analysis:ignore except: pass #============================================================================== # Add default filesystem encoding on Linux to avoid an error with # Matplotlib 1.5 in Python 2 (Fixes Issue 2793) #============================================================================== if PY2 and sys.platform.startswith('linux'): def _getfilesystemencoding_wrapper(): return 'utf-8' sys.getfilesystemencoding = _getfilesystemencoding_wrapper #============================================================================== # Set PyQt API to #2 #============================================================================== if os.environ["QT_API"] == 'pyqt': try: import sip for qtype in ('QString', 'QVariant', 'QDate', 'QDateTime', 'QTextStream', 'QTime', 'QUrl'): sip.setapi(qtype, 2) except: pass #============================================================================== # IPython kernel adjustments #============================================================================== # Use ipydb as the debugger to patch on IPython consoles from IPython.core.debugger import Pdb as ipyPdb pdb.Pdb = ipyPdb # Patch unittest.main so that errors are printed directly in the console. # See http://comments.gmane.org/gmane.comp.python.ipython.devel/10557 # Fixes Issue 1370 import unittest from unittest import TestProgram class IPyTesProgram(TestProgram): def __init__(self, *args, **kwargs): test_runner = unittest.TextTestRunner(stream=sys.stderr) kwargs['testRunner'] = kwargs.pop('testRunner', test_runner) kwargs['exit'] = False TestProgram.__init__(self, *args, **kwargs) unittest.main = IPyTesProgram # Patch ipykernel to avoid errors when setting the Qt5 Matplotlib # backemd # Fixes Issue 6091 import ipykernel import IPython if LooseVersion(ipykernel.__version__) <= LooseVersion('4.7.0'): if ((PY2 and LooseVersion(IPython.__version__) >= LooseVersion('5.5.0')) or (not PY2 and LooseVersion(IPython.__version__) >= LooseVersion('6.2.0')) ): from ipykernel import eventloops eventloops.loop_map['qt'] = eventloops.loop_map['qt5'] #============================================================================== # Pandas adjustments #============================================================================== try: import pandas as pd # Set Pandas output encoding pd.options.display.encoding = 'utf-8' # Filter warning that appears for DataFrames with np.nan values # Example: # >>> import pandas as pd, numpy as np # >>> pd.Series([np.nan,np.nan,np.nan],index=[1,2,3]) # Fixes Issue 2991 # For 0.18- warnings.filterwarnings(action='ignore', category=RuntimeWarning, module='pandas.core.format', message=".*invalid value encountered in.*") # For 0.18.1+ warnings.filterwarnings(action='ignore', category=RuntimeWarning, module='pandas.formats.format', message=".*invalid value encountered in.*") except: pass #============================================================================== # Pdb adjustments #============================================================================== class SpyderPdb(pdb.Pdb): send_initial_notification = True starting = True def set_spyder_breakpoints(self): self.clear_all_breaks() #------Really deleting all breakpoints: for bp in bdb.Breakpoint.bpbynumber: if bp: bp.deleteMe() bdb.Breakpoint.next = 1 bdb.Breakpoint.bplist = {} bdb.Breakpoint.bpbynumber = [None] #------ from spyder.config.main import CONF CONF.load_from_ini() if CONF.get('run', 'breakpoints/enabled', True): breakpoints = CONF.get('run', 'breakpoints', {}) i = 0 for fname, data in list(breakpoints.items()): for linenumber, condition in data: i += 1 self.set_break(self.canonic(fname), linenumber, cond=condition) def notify_spyder(self, frame): if not frame: return from IPython.core.getipython import get_ipython kernel = get_ipython().kernel # Get filename and line number of the current frame fname = self.canonic(frame.f_code.co_filename) if PY2: try: fname = unicode(fname, "utf-8") except TypeError: pass lineno = frame.f_lineno # Jump to first breakpoint. # Fixes issue 2034 if self.starting: # Only run this after a Pdb session is created self.starting = False # Get all breakpoints for the file we're going to debug breaks = self.get_file_breaks(frame.f_code.co_filename) # Do 'continue' if the first breakpoint is *not* placed # where the debugger is going to land. # Fixes issue 4681 if breaks and lineno != breaks[0] and osp.isfile(fname): kernel.pdb_continue() # Set step of the current frame (if any) step = {} if isinstance(fname, basestring) and isinstance(lineno, int): if osp.isfile(fname): step = dict(fname=fname, lineno=lineno) # Publish Pdb state so we can update the Variable Explorer # and the Editor on the Spyder side kernel._pdb_step = step kernel.publish_pdb_state() pdb.Pdb = SpyderPdb #XXX: I know, this function is now also implemented as is in utils/misc.py but # I'm kind of reluctant to import spyder in sitecustomize, even if this # import is very clean. def monkeypatch_method(cls, patch_name): # This function's code was inspired from the following thread: # "[Python-Dev] Monkeypatching idioms -- elegant or ugly?" # by Robert Brewer # (Tue Jan 15 19:13:25 CET 2008) """ Add the decorated method to the given class; replace as needed. If the named method already exists on the given class, it will be replaced, and a reference to the old method is created as cls._old. If the "_old__" attribute already exists, KeyError is raised. """ def decorator(func): fname = func.__name__ old_func = getattr(cls, fname, None) if old_func is not None: # Add the old func to a list of old funcs. old_ref = "_old_%s_%s" % (patch_name, fname) old_attr = getattr(cls, old_ref, None) if old_attr is None: setattr(cls, old_ref, old_func) else: raise KeyError("%s.%s already exists." % (cls.__name__, old_ref)) setattr(cls, fname, func) return func return decorator @monkeypatch_method(pdb.Pdb, 'Pdb') def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None, nosigint=False): self._old_Pdb___init__() @monkeypatch_method(pdb.Pdb, 'Pdb') def user_return(self, frame, return_value): """This function is called when a return trap is set here.""" # This is useful when debugging in an active interpreter (otherwise, # the debugger will stop before reaching the target file) if self._wait_for_mainpyfile: if (self.mainpyfile != self.canonic(frame.f_code.co_filename) or frame.f_lineno<= 0): return self._wait_for_mainpyfile = 0 self._old_Pdb_user_return(frame, return_value) @monkeypatch_method(pdb.Pdb, 'Pdb') def interaction(self, frame, traceback): if frame is not None and "sitecustomize.py" in frame.f_code.co_filename: self.run('exit') else: self.setup(frame, traceback) if self.send_initial_notification: self.notify_spyder(frame) self.print_stack_entry(self.stack[self.curindex]) self._cmdloop() self.forget() @monkeypatch_method(pdb.Pdb, 'Pdb') def _cmdloop(self): while True: try: # keyboard interrupts allow for an easy way to cancel # the current command, so allow them during interactive input self.allow_kbdint = True self.cmdloop() self.allow_kbdint = False break except KeyboardInterrupt: _print("--KeyboardInterrupt--\n" "For copying text while debugging, use Ctrl+Shift+C", file=self.stdout) @monkeypatch_method(pdb.Pdb, 'Pdb') def reset(self): self._old_Pdb_reset() from IPython.core.getipython import get_ipython kernel = get_ipython().kernel kernel._register_pdb_session(self) self.set_spyder_breakpoints() #XXX: notify spyder on any pdb command (is that good or too lazy? i.e. is more # specific behaviour desired?) @monkeypatch_method(pdb.Pdb, 'Pdb') def postcmd(self, stop, line): self.notify_spyder(self.curframe) return self._old_Pdb_postcmd(stop, line) # Breakpoints don't work for files with non-ascii chars in Python 2 # Fixes Issue 1484 if PY2: @monkeypatch_method(pdb.Pdb, 'Pdb') def break_here(self, frame): from bdb import effective filename = self.canonic(frame.f_code.co_filename) try: filename = unicode(filename, "utf-8") except TypeError: pass if not filename in self.breaks: return False lineno = frame.f_lineno if not lineno in self.breaks[filename]: # The line itself has no breakpoint, but maybe the line is the # first line of a function with breakpoint set by function name. lineno = frame.f_code.co_firstlineno if not lineno in self.breaks[filename]: return False # flag says ok to delete temp. bp (bp, flag) = effective(filename, lineno, frame) if bp: self.currentbp = bp.number if (flag and bp.temporary): self.do_clear(str(bp.number)) return True else: return False #============================================================================== # Restoring (almost) original sys.path: # # NOTE: do not remove spyder_path from sys.path because if Spyder has been # installed using python setup.py install, then this could remove the # 'site-packages' directory from sys.path! #============================================================================== try: sys.path.remove(osp.join(spyder_path, "spyder", "utils", "site")) except ValueError: pass #============================================================================== # User module reloader #============================================================================== class UserModuleReloader(object): """ User Module Reloader (UMR) aims at deleting user modules to force Python to deeply reload them during import pathlist [list]: blacklist in terms of module path namelist [list]: blacklist in terms of module name """ def __init__(self, namelist=None, pathlist=None): if namelist is None: namelist = [] spy_modules = ['sitecustomize', 'spyder', 'spyderplugins'] mpl_modules = ['matplotlib', 'tkinter', 'Tkinter'] self.namelist = namelist + spy_modules + mpl_modules if pathlist is None: pathlist = [] self.pathlist = pathlist self.previous_modules = list(sys.modules.keys()) def is_module_blacklisted(self, modname, modpath): if modname.startswith('_cython_inline'): # Don't return cached inline compiled .PYX files return True for path in [sys.prefix]+self.pathlist: if modpath.startswith(path): return True else: return set(modname.split('.')) & set(self.namelist) def run(self, verbose=False): """ Del user modules to force Python to deeply reload them Do not del modules which are considered as system modules, i.e. modules installed in subdirectories of Python interpreter's binary Do not del C modules """ log = [] for modname, module in list(sys.modules.items()): if modname not in self.previous_modules: modpath = getattr(module, '__file__', None) if modpath is None: # *module* is a C module that is statically linked into the # interpreter. There is no way to know its path, so we # choose to ignore it. continue if not self.is_module_blacklisted(modname, modpath): log.append(modname) del sys.modules[modname] if verbose and log: _print("\x1b[4;33m%s\x1b[24m%s\x1b[0m"\ % ("Reloaded modules", ": "+", ".join(log))) __umr__ = None #============================================================================== # Handle Post Mortem Debugging and Traceback Linkage to Spyder #============================================================================== def clear_post_mortem(): """ Remove the post mortem excepthook and replace with a standard one. """ from IPython.core.getipython import get_ipython ipython_shell = get_ipython() ipython_shell.set_custom_exc((), None) def post_mortem_excepthook(type, value, tb): """ For post mortem exception handling, print a banner and enable post mortem debugging. """ clear_post_mortem() from IPython.core.getipython import get_ipython ipython_shell = get_ipython() ipython_shell.showtraceback((type, value, tb)) p = pdb.Pdb(ipython_shell.colors) if not type == SyntaxError: # wait for stderr to print (stderr.flush does not work in this case) time.sleep(0.1) _print('*' * 40) _print('Entering post mortem debugging...') _print('*' * 40) # add ability to move between frames p.send_initial_notification = False p.reset() frame = tb.tb_frame prev = frame while frame.f_back: prev = frame frame = frame.f_back frame = prev # wait for stdout to print time.sleep(0.1) p.interaction(frame, tb) def set_post_mortem(): """ Enable the post mortem debugging excepthook. """ from IPython.core.getipython import get_ipython def ipython_post_mortem_debug(shell, etype, evalue, tb, tb_offset=None): post_mortem_excepthook(etype, evalue, tb) ipython_shell = get_ipython() ipython_shell.set_custom_exc((Exception,), ipython_post_mortem_debug) # Add post mortem debugging if requested and in a dedicated interpreter # existing interpreters use "runfile" below if "SPYDER_EXCEPTHOOK" in os.environ: set_post_mortem() #============================================================================== # runfile and debugfile commands #============================================================================== def _get_globals(): """Return current namespace""" from IPython.core.getipython import get_ipython ipython_shell = get_ipython() return ipython_shell.user_ns def runfile(filename, args=None, wdir=None, namespace=None, post_mortem=False): """ Run filename args: command line arguments (string) wdir: working directory post_mortem: boolean, whether to enter post-mortem mode on error """ try: filename = filename.decode('utf-8') except (UnicodeError, TypeError, AttributeError): # UnicodeError, TypeError --> eventually raised in Python 2 # AttributeError --> systematically raised in Python 3 pass global __umr__ if os.environ.get("SPY_UMR_ENABLED", "").lower() == "true": if __umr__ is None: namelist = os.environ.get("SPY_UMR_NAMELIST", None) if namelist is not None: namelist = namelist.split(',') __umr__ = UserModuleReloader(namelist=namelist) else: verbose = os.environ.get("SPY_UMR_VERBOSE", "").lower() == "true" __umr__.run(verbose=verbose) if args is not None and not isinstance(args, basestring): raise TypeError("expected a character buffer object") if namespace is None: namespace = _get_globals() namespace['__file__'] = filename sys.argv = [filename] if args is not None: for arg in shlex.split(args): sys.argv.append(arg) if wdir is not None: try: wdir = wdir.decode('utf-8') except (UnicodeError, TypeError, AttributeError): # UnicodeError, TypeError --> eventually raised in Python 2 # AttributeError --> systematically raised in Python 3 pass os.chdir(wdir) if post_mortem: set_post_mortem() if HAS_CYTHON and os.path.splitext(filename)[1].lower() == '.pyx': # Cython files with io.open(filename, encoding='utf-8') as f: from IPython.core.getipython import get_ipython ipython_shell = get_ipython() ipython_shell.run_cell_magic('cython', '', f.read()) else: execfile(filename, namespace) clear_post_mortem() sys.argv = [''] namespace.pop('__file__') builtins.runfile = runfile def debugfile(filename, args=None, wdir=None, post_mortem=False): """ Debug filename args: command line arguments (string) wdir: working directory post_mortem: boolean, included for compatiblity with runfile """ debugger = pdb.Pdb() filename = debugger.canonic(filename) debugger._wait_for_mainpyfile = 1 debugger.mainpyfile = filename debugger._user_requested_quit = 0 if os.name == 'nt': filename = filename.replace('\\', '/') debugger.run("runfile(%r, args=%r, wdir=%r)" % (filename, args, wdir)) builtins.debugfile = debugfile #============================================================================== # Restoring original PYTHONPATH #============================================================================== try: os.environ['PYTHONPATH'] = os.environ['OLD_PYTHONPATH'] del os.environ['OLD_PYTHONPATH'] except KeyError: if os.environ.get('PYTHONPATH') is not None: del os.environ['PYTHONPATH'] spyder-3.2.6/spyder/utils/site/osx_app_site.py0000664000175000017500000001135313156676663022331 0ustar carloscarlos00000000000000# # IMPORTANT NOTE: Don't add a coding line here! It's not necessary for # site files # # Spyder's MacOS X App site.py additions # # It includes missing variables and paths that are not added by # py2app to its own site.py # # These functions were taken verbatim from Python 2.7.3 site.py # import sys import os try: import __builtin__ as builtins except ImportError: # Python 3 import builtins # for distutils.commands.install # These values are initialized by the getuserbase() and getusersitepackages() # functions. USER_SITE = None USER_BASE = None def getuserbase(): """Returns the `user base` directory path. The `user base` directory can be used to store data. If the global variable ``USER_BASE`` is not initialized yet, this function will also set it. """ global USER_BASE if USER_BASE is not None: return USER_BASE from sysconfig import get_config_var USER_BASE = get_config_var('userbase') return USER_BASE def getusersitepackages(): """Returns the user-specific site-packages directory path. If the global variable ``USER_SITE`` is not initialized yet, this function will also set it. """ global USER_SITE user_base = getuserbase() # this will also set USER_BASE if USER_SITE is not None: return USER_SITE from sysconfig import get_path if sys.platform == 'darwin': from sysconfig import get_config_var if get_config_var('PYTHONFRAMEWORK'): USER_SITE = get_path('purelib', 'osx_framework_user') return USER_SITE USER_SITE = get_path('purelib', '%s_user' % os.name) return USER_SITE class _Printer(object): """interactive prompt objects for printing the license text, a list of contributors and the copyright notice.""" MAXLINES = 23 def __init__(self, name, data, files=(), dirs=()): self.__name = name self.__data = data self.__files = files self.__dirs = dirs self.__lines = None def __setup(self): if self.__lines: return data = None for dir in self.__dirs: for filename in self.__files: filename = os.path.join(dir, filename) try: fp = open(filename, "rU") data = fp.read() fp.close() break except IOError: pass if data: break if not data: data = self.__data self.__lines = data.split('\n') self.__linecnt = len(self.__lines) def __repr__(self): self.__setup() if len(self.__lines) <= self.MAXLINES: return "\n".join(self.__lines) else: return "Type %s() to see the full %s text" % ((self.__name,)*2) def __call__(self): self.__setup() prompt = 'Hit Return for more, or q (and Return) to quit: ' lineno = 0 while 1: try: for i in range(lineno, lineno + self.MAXLINES): print(self.__lines[i]) # spyder: test-skip except IndexError: break else: lineno += self.MAXLINES key = None while key is None: try: key = raw_input(prompt) except NameError: # Python 3 key = input(prompt) if key not in ('', 'q'): key = None if key == 'q': break def setcopyright(): """Set 'copyright' and 'credits' in builtins""" builtins.copyright = _Printer("copyright", sys.copyright) if sys.platform[:4] == 'java': builtins.credits = _Printer( "credits", "Jython is maintained by the Jython developers (www.jython.org).") else: builtins.credits = _Printer("credits", """\ Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands for supporting Python development. See www.python.org for more information.""") here = os.path.dirname(os.__file__) builtins.license = _Printer( "license", "See http://www.python.org/%.3s/license.html" % sys.version, ["LICENSE.txt", "LICENSE"], [os.path.join(here, os.pardir), here, os.curdir]) class _Helper(object): """Define the builtin 'help'. This is a wrapper around pydoc.help (with a twist). """ def __repr__(self): return "Type help() for interactive help, " \ "or help(object) for help about object." def __call__(self, *args, **kwds): import pydoc return pydoc.help(*args, **kwds) def sethelper(): builtins.help = _Helper() spyder-3.2.6/spyder/utils/site/__init__.py0000664000175000017500000000060313026261006021340 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ spyder.utils.site ================= Site packages for Spyder consoles NOTE: This package shouldn't be imported at **any** place. It's only used to set additional functionality for our consoles. """ spyder-3.2.6/spyder/utils/ipython/0000775000175000017500000000000013225025007017756 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/utils/ipython/kernelspec.py0000664000175000017500000001373513224121062022471 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Kernel spec for Spyder kernels """ import os import os.path as osp from jupyter_client.kernelspec import KernelSpec from spyder.config.base import get_module_source_path from spyder.config.main import CONF from spyder.utils.encoding import to_unicode_from_fs from spyder.py3compat import PY2, iteritems, to_text_string, to_binary_string from spyder.utils.misc import (add_pathlist_to_PYTHONPATH, get_python_executable) class SpyderKernelSpec(KernelSpec): """Kernel spec for Spyder kernels""" spy_path = get_module_source_path('spyder') def __init__(self, **kwargs): super(SpyderKernelSpec, self).__init__(**kwargs) self.display_name = 'Python 2 (Spyder)' if PY2 else 'Python 3 (Spyder)' self.language = 'python2' if PY2 else 'python3' self.resource_dir = '' @property def argv(self): """Command to start kernels""" # Python interpreter used to start kernels if CONF.get('main_interpreter', 'default'): pyexec = get_python_executable() else: # Avoid IPython adding the virtualenv on which Spyder is running # to the kernel sys.path os.environ.pop('VIRTUAL_ENV', None) pyexec = CONF.get('main_interpreter', 'executable') # Fixes Issue #3427 if os.name == 'nt': dir_pyexec = osp.dirname(pyexec) pyexec_w = osp.join(dir_pyexec, 'pythonw.exe') if osp.isfile(pyexec_w): pyexec = pyexec_w # Command used to start kernels utils_path = osp.join(self.spy_path, 'utils', 'ipython') kernel_cmd = [ pyexec, osp.join("%s" % utils_path, "start_kernel.py"), '-f', '{connection_file}' ] return kernel_cmd @property def env(self): """Env vars for kernels""" # Paths that we need to add to PYTHONPATH: # 1. sc_path: Path to our sitecustomize # 2. spy_path: Path to our main module, so we can use our config # system to configure kernels started by exterrnal interpreters # 3. spy_pythonpath: Paths saved by our users with our PYTHONPATH # manager sc_path = osp.join(self.spy_path, 'utils', 'site') spy_pythonpath = CONF.get('main', 'spyder_pythonpath', default=[]) default_interpreter = CONF.get('main_interpreter', 'default') if default_interpreter: pathlist = [sc_path] + spy_pythonpath else: pathlist = [sc_path, self.spy_path] + spy_pythonpath pypath = add_pathlist_to_PYTHONPATH([], pathlist, ipyconsole=True, drop_env=(not default_interpreter)) # Environment variables that we need to pass to our sitecustomize umr_namelist = CONF.get('main_interpreter', 'umr/namelist') if PY2: original_list = umr_namelist[:] for umr_n in umr_namelist: try: umr_n.encode('utf-8') except UnicodeDecodeError: umr_namelist.remove(umr_n) if original_list != umr_namelist: CONF.set('main_interpreter', 'umr/namelist', umr_namelist) env_vars = { 'SPY_EXTERNAL_INTERPRETER': not default_interpreter, 'SPY_UMR_ENABLED': CONF.get('main_interpreter', 'umr/enabled'), 'SPY_UMR_VERBOSE': CONF.get('main_interpreter', 'umr/verbose'), 'SPY_UMR_NAMELIST': ','.join(umr_namelist), 'SPY_RUN_LINES_O': CONF.get('ipython_console', 'startup/run_lines'), 'SPY_PYLAB_O': CONF.get('ipython_console', 'pylab'), 'SPY_BACKEND_O': CONF.get('ipython_console', 'pylab/backend'), 'SPY_AUTOLOAD_PYLAB_O': CONF.get('ipython_console', 'pylab/autoload'), 'SPY_FORMAT_O': CONF.get('ipython_console', 'pylab/inline/figure_format'), 'SPY_RESOLUTION_O': CONF.get('ipython_console', 'pylab/inline/resolution'), 'SPY_WIDTH_O': CONF.get('ipython_console', 'pylab/inline/width'), 'SPY_HEIGHT_O': CONF.get('ipython_console', 'pylab/inline/height'), 'SPY_USE_FILE_O': CONF.get('ipython_console', 'startup/use_run_file'), 'SPY_RUN_FILE_O': CONF.get('ipython_console', 'startup/run_file'), 'SPY_AUTOCALL_O': CONF.get('ipython_console', 'autocall'), 'SPY_GREEDY_O': CONF.get('ipython_console', 'greedy_completer'), 'SPY_SYMPY_O': CONF.get('ipython_console', 'symbolic_math') } # Add our PYTHONPATH to env_vars env_vars.update(pypath) # Making all env_vars strings for key,var in iteritems(env_vars): if PY2: # Try to convert vars first to utf-8. try: unicode_var = to_text_string(var) except UnicodeDecodeError: # If that fails, try to use the file system # encoding because one of our vars is our # PYTHONPATH, and that contains file system # directories try: unicode_var = to_unicode_from_fs(var) except: # If that also fails, make the var empty # to be able to start Spyder. # See https://stackoverflow.com/q/44506900/438386 # for details. unicode_var = '' env_vars[key] = to_binary_string(unicode_var, encoding='utf-8') else: env_vars[key] = to_text_string(var) return env_vars spyder-3.2.6/spyder/utils/ipython/templates/0000775000175000017500000000000013225025007021754 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/utils/ipython/templates/kernel_error.html0000664000175000017500000000131113026261006025327 0ustar carloscarlos00000000000000
    ${message}
    ${error}
    spyder-3.2.6/spyder/utils/ipython/templates/loading.html0000664000175000017500000000521313026261006024260 0ustar carloscarlos00000000000000
    ${message}
    spyder-3.2.6/spyder/utils/ipython/templates/blank.html0000664000175000017500000000061413026261006023732 0ustar carloscarlos00000000000000 spyder-3.2.6/spyder/utils/ipython/style.py0000664000175000017500000001445113224121062021472 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Style for IPython Console """ # Local imports from spyder.config.gui import get_color_scheme # Third party imports from pygments.style import Style from pygments.token import (Name, Keyword, Comment, String, Number, Punctuation, Operator) from qtconsole.styles import dark_color def create_qss_style(color_scheme): """Returns a QSS stylesheet with Spyder color scheme settings. The stylesheet can contain classes for: Qt: QPlainTextEdit, QFrame, QWidget, etc Pygments: .c, .k, .o, etc. (see PygmentsHighlighter) IPython: .error, .in-prompt, .out-prompt, etc """ def give_font_weight(is_bold): if is_bold: return 'bold' else: return 'normal' def give_font_style(is_italic): if is_italic: return 'italic' else: return 'normal' color_scheme = get_color_scheme(color_scheme) fon_c, fon_fw, fon_fs = color_scheme['normal'] font_color = fon_c if dark_color(font_color): in_prompt_color = 'navy' out_prompt_color = 'darkred' else: in_prompt_color = 'lime' out_prompt_color = 'red' background_color = color_scheme['background'] error_color = 'red' in_prompt_number_font_weight = 'bold' out_prompt_number_font_weight = 'bold' inverted_background_color = font_color inverted_font_color = background_color sheet = """QPlainTextEdit, QTextEdit, ControlWidget {{ color: {} ; background-color: {}; }} .error {{ color: {}; }} .in-prompt {{ color: {}; }} .in-prompt-number {{ color: {}; font-weight: {}; }} .out-prompt {{ color: {}; }} .out-prompt-number {{ color: {}; font-weight: {}; }} .inverted {{ color: {}; background-color: {}; }} """ sheet_formatted = sheet.format(font_color, background_color, error_color, in_prompt_color, in_prompt_color, in_prompt_number_font_weight, out_prompt_color, out_prompt_color, out_prompt_number_font_weight, inverted_background_color, inverted_font_color) return (sheet_formatted, dark_color(font_color)) def create_pygments_dict(color_scheme_name): """ Create a dictionary that saves the given color scheme as a Pygments style. """ def give_font_weight(is_bold): if is_bold: return 'bold' else: return '' def give_font_style(is_italic): if is_italic: return 'italic' else: return '' color_scheme = get_color_scheme(color_scheme_name) fon_c, fon_fw, fon_fs = color_scheme['normal'] font_color = fon_c font_font_weight = give_font_weight(fon_fw) font_font_style = give_font_style(fon_fs) key_c, key_fw, key_fs = color_scheme['keyword'] keyword_color = key_c keyword_font_weight = give_font_weight(key_fw) keyword_font_style = give_font_style(key_fs) bui_c, bui_fw, bui_fs = color_scheme['builtin'] builtin_color = bui_c builtin_font_weight = give_font_weight(bui_fw) builtin_font_style = give_font_style(bui_fs) str_c, str_fw, str_fs = color_scheme['string'] string_color = str_c string_font_weight = give_font_weight(str_fw) string_font_style = give_font_style(str_fs) num_c, num_fw, num_fs = color_scheme['number'] number_color = num_c number_font_weight = give_font_weight(num_fw) number_font_style = give_font_style(num_fs) com_c, com_fw, com_fs = color_scheme['comment'] comment_color = com_c comment_font_weight = give_font_weight(com_fw) comment_font_style = give_font_style(com_fs) def_c, def_fw, def_fs = color_scheme['definition'] definition_color = def_c definition_font_weight = give_font_weight(def_fw) definition_font_style = give_font_style(def_fs) ins_c, ins_fw, ins_fs = color_scheme['instance'] instance_color = ins_c instance_font_weight = give_font_weight(ins_fw) instance_font_style = give_font_style(ins_fs) font_token = font_font_style + ' ' + font_font_weight + ' ' + font_color definition_token = (definition_font_style + ' ' + definition_font_weight + ' ' + definition_color) builtin_token = (builtin_font_style + ' ' + builtin_font_weight + ' ' + builtin_color) instance_token = (instance_font_style + ' ' + instance_font_weight + ' ' + instance_color) keyword_token = (keyword_font_style + ' ' + keyword_font_weight + ' ' + keyword_color) comment_token = (comment_font_style + ' ' + comment_font_weight + ' ' + comment_color) string_token = (string_font_style + ' ' + string_font_weight + ' ' + string_color) number_token = (number_font_style + ' ' + number_font_weight + ' ' + number_color) syntax_style_dic = {Name: font_token.strip(), Name.Class: definition_token.strip(), Name.Function: definition_token.strip(), Name.Builtin: builtin_token.strip(), Name.Builtin.Pseudo: instance_token.strip(), Keyword: keyword_token.strip(), Keyword.Type: builtin_token.strip(), Comment: comment_token.strip(), String: string_token.strip(), Number: number_token.strip(), Punctuation: font_token.strip(), Operator.Word: keyword_token.strip()} return syntax_style_dic def create_style_class(color_scheme_name): """Create a Pygments Style class with the given color scheme.""" class StyleClass(Style): default_style = "" styles = create_pygments_dict(color_scheme_name) return StyleClass spyder-3.2.6/spyder/utils/ipython/tests/0000775000175000017500000000000013225025007021120 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/utils/ipython/tests/test_spyder_kernel.py0000664000175000017500000000227213212005255025401 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for the Spyder kernel """ import os import pytest from spyder.config.main import CONF from spyder.py3compat import PY2, is_binary_string from spyder.utils.encoding import to_fs_from_unicode from spyder.utils.ipython.kernelspec import SpyderKernelSpec @pytest.mark.skipif(os.name != 'nt' or not PY2, reason="It only makes sense on Windows and Python 2") def test_env_vars(): """Test that we are correctly encoding env vars in our kernel spec""" # Create a variable with the file system encoding and save it # in our PYTHONPATH env_var = to_fs_from_unicode(u'ñññ') CONF.set('main', 'spyder_pythonpath', [env_var]) # Create a kernel spec kernel_spec = SpyderKernelSpec() # Assert PYTHONPATH is in env vars and it's not empty assert kernel_spec.env['PYTHONPATH'] != '' # Assert all env vars are binary strings assert all([is_binary_string(v) for v in kernel_spec.env.values()]) # Remove our entry from PYTHONPATH CONF.set('main', 'spyder_pythonpath', []) if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/utils/ipython/tests/__init__.py0000664000175000017500000000050213211142273023226 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Copyright (c) Spyder Project Contributors # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Tests.""" spyder-3.2.6/spyder/utils/ipython/spyder_kernel.py0000664000175000017500000004101113224740762023206 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Spyder kernel for Jupyter """ # Standard library imports import os import os.path as osp import sys # Third-party imports from ipykernel.ipkernel import IPythonKernel PY2 = sys.version[0] == '2' # Check if we are running under an external interpreter # We add "spyder" to sys.path for external interpreters, # so relative imports work! IS_EXT_INTERPRETER = os.environ.get('SPY_EXTERNAL_INTERPRETER') == "True" # Excluded variables from the Variable Explorer (i.e. they are not # shown at all there) EXCLUDED_NAMES = ['In', 'Out', 'exit', 'get_ipython', 'quit'] # To be able to get and set variables between Python 2 and 3 PICKLE_PROTOCOL = 2 class SpyderKernel(IPythonKernel): """Spyder kernel for Jupyter""" def __init__(self, *args, **kwargs): super(SpyderKernel, self).__init__(*args, **kwargs) self.namespace_view_settings = {} self._pdb_obj = None self._pdb_step = None self._do_publish_pdb_state = True self._mpl_backend_error = None kernel_config = self.config.get('IPKernelApp', None) if kernel_config is not None: cf = kernel_config['connection_file'] json_file = osp.basename(cf) self._kernel_id = json_file.split('.json')[0] else: self._kernel_id = None @property def _pdb_frame(self): """Return current Pdb frame if there is any""" if self._pdb_obj is not None and self._pdb_obj.curframe is not None: return self._pdb_obj.curframe @property def _pdb_locals(self): """ Return current Pdb frame locals if available. Otherwise return an empty dictionary """ if self._pdb_frame: return self._pdb_obj.curframe_locals else: return {} # -- Public API --------------------------------------------------- # --- For the Variable Explorer def get_namespace_view(self): """ Return the namespace view This is a dictionary with the following structure {'a': {'color': '#800000', 'size': 1, 'type': 'str', 'view': '1'}} Here: * 'a' is the variable name * 'color' is the color used to show it * 'size' and 'type' are self-evident * and'view' is its value or the text shown in the last column """ if not IS_EXT_INTERPRETER: from spyder.widgets.variableexplorer.utils import make_remote_view else: from widgets.variableexplorer.utils import make_remote_view settings = self.namespace_view_settings if settings: ns = self._get_current_namespace() view = repr(make_remote_view(ns, settings, EXCLUDED_NAMES)) return view else: return repr(None) def get_var_properties(self): """ Get some properties of the variables in the current namespace """ if not IS_EXT_INTERPRETER: from spyder.widgets.variableexplorer.utils import get_remote_data else: from widgets.variableexplorer.utils import get_remote_data settings = self.namespace_view_settings if settings: ns = self._get_current_namespace() data = get_remote_data(ns, settings, mode='editable', more_excluded_names=EXCLUDED_NAMES) properties = {} for name, value in list(data.items()): properties[name] = { 'is_list': isinstance(value, (tuple, list)), 'is_dict': isinstance(value, dict), 'len': self._get_len(value), 'is_array': self._is_array(value), 'is_image': self._is_image(value), 'is_data_frame': self._is_data_frame(value), 'is_series': self._is_series(value), 'array_shape': self._get_array_shape(value), 'array_ndim': self._get_array_ndim(value) } return repr(properties) else: return repr(None) def send_spyder_msg(self, spyder_msg_type, content=None, data=None): """publish custom messages to the spyder frontend Parameters ---------- spyder_msg_type: str The spyder message type content: dict The (JSONable) content of the message data: any Any object that is serializable by cloudpickle (should be most things). Will arrive as cloudpickled bytes in `.buffers[0]`. """ import cloudpickle if content is None: content = {} content['spyder_msg_type'] = spyder_msg_type self.session.send( self.iopub_socket, 'spyder_msg', content=content, buffers=[cloudpickle.dumps(data, protocol=PICKLE_PROTOCOL)], parent=self._parent_header, ) def get_value(self, name): """Get the value of a variable""" ns = self._get_current_namespace() value = ns[name] try: self.send_spyder_msg('data', data=value) except: # * There is no need to inform users about # these errors. # * value = None makes Spyder to ignore # petitions to display a value self.send_spyder_msg('data', data=None) self._do_publish_pdb_state = False def set_value(self, name, value, PY2_frontend): """Set the value of a variable""" import cloudpickle ns = self._get_reference_namespace(name) # We send serialized values in a list of one element # from Spyder to the kernel, to be able to send them # at all in Python 2 svalue = value[0] # We need to convert svalue to bytes if the frontend # runs in Python 2 and the kernel runs in Python 3 if PY2_frontend and not PY2: svalue = bytes(svalue, 'latin-1') # Deserialize and set value in namespace dvalue = cloudpickle.loads(svalue) ns[name] = dvalue def remove_value(self, name): """Remove a variable""" ns = self._get_reference_namespace(name) ns.pop(name) def copy_value(self, orig_name, new_name): """Copy a variable""" ns = self._get_reference_namespace(orig_name) ns[new_name] = ns[orig_name] def load_data(self, filename, ext): """Load data from filename""" if not IS_EXT_INTERPRETER: from spyder.utils.iofuncs import iofunctions from spyder.utils.misc import fix_reference_name else: from utils.iofuncs import iofunctions from utils.misc import fix_reference_name glbs = self._mglobals() load_func = iofunctions.load_funcs[ext] data, error_message = load_func(filename) if error_message: return error_message for key in list(data.keys()): new_key = fix_reference_name(key, blacklist=list(glbs.keys())) if new_key != key: data[new_key] = data.pop(key) try: glbs.update(data) except Exception as error: return str(error) return None def save_namespace(self, filename): """Save namespace into filename""" if not IS_EXT_INTERPRETER: from spyder.utils.iofuncs import iofunctions from spyder.widgets.variableexplorer.utils import get_remote_data else: from utils.iofuncs import iofunctions from widgets.variableexplorer.utils import get_remote_data ns = self._get_current_namespace() settings = self.namespace_view_settings data = get_remote_data(ns, settings, mode='picklable', more_excluded_names=EXCLUDED_NAMES).copy() return iofunctions.save(data, filename) # --- For Pdb def publish_pdb_state(self): """ Publish Variable Explorer state and Pdb step through send_spyder_msg. """ if self._pdb_obj and self._do_publish_pdb_state: state = dict(namespace_view = self.get_namespace_view(), var_properties = self.get_var_properties(), step = self._pdb_step) self.send_spyder_msg('pdb_state', content={'pdb_state': state}) self._do_publish_pdb_state = True def pdb_continue(self): """ Tell the console to run 'continue' after entering a Pdb session to get to the first breakpoint. Fixes issue 2034 """ if self._pdb_obj: self.send_spyder_msg('pdb_continue') # --- For the Help plugin def is_defined(self, obj, force_import=False): """Return True if object is defined in current namespace""" if not IS_EXT_INTERPRETER: from spyder.utils.dochelpers import isdefined else: from utils.dochelpers import isdefined ns = self._get_current_namespace(with_magics=True) return isdefined(obj, force_import=force_import, namespace=ns) def get_doc(self, objtxt): """Get object documentation dictionary""" try: import matplotlib matplotlib.rcParams['docstring.hardcopy'] = True except: pass if not IS_EXT_INTERPRETER: from spyder.utils.dochelpers import getdoc else: from utils.dochelpers import getdoc obj, valid = self._eval(objtxt) if valid: return getdoc(obj) def get_source(self, objtxt): """Get object source""" if not IS_EXT_INTERPRETER: from spyder.utils.dochelpers import getsource else: from utils.dochelpers import getsource obj, valid = self._eval(objtxt) if valid: return getsource(obj) # --- Additional methods def set_cwd(self, dirname): """Set current working directory.""" os.chdir(dirname) def get_cwd(self): """Get current working directory.""" return os.getcwd() def get_syspath(self): """Return sys.path contents.""" return sys.path[:] def get_env(self): """Get environment variables.""" return os.environ.copy() def close_all_mpl_figures(self): """Close all Matplotlib figures.""" try: import matplotlib.pyplot as plt plt.close('all') del plt except: pass # -- Private API --------------------------------------------------- # --- For the Variable Explorer def _get_current_namespace(self, with_magics=False): """ Return current namespace This is globals() if not debugging, or a dictionary containing both locals() and globals() for current frame when debugging """ ns = {} glbs = self._mglobals() if self._pdb_frame is None: ns.update(glbs) else: ns.update(glbs) ns.update(self._pdb_locals) # Add magics to ns so we can show help about them on the Help # plugin if with_magics: line_magics = self.shell.magics_manager.magics['line'] cell_magics = self.shell.magics_manager.magics['cell'] ns.update(line_magics) ns.update(cell_magics) return ns def _get_reference_namespace(self, name): """ Return namespace where reference name is defined It returns the globals() if reference has not yet been defined """ glbs = self._mglobals() if self._pdb_frame is None: return glbs else: lcls = self._pdb_locals if name in lcls: return lcls else: return glbs def _mglobals(self): """Return current globals -- handles Pdb frames""" if self._pdb_frame is not None: return self._pdb_frame.f_globals else: return self.shell.user_ns def _get_len(self, var): """Return sequence length""" try: return len(var) except: return None def _is_array(self, var): """Return True if variable is a NumPy array""" try: import numpy return isinstance(var, numpy.ndarray) except: return False def _is_image(self, var): """Return True if variable is a PIL.Image image""" try: from PIL import Image return isinstance(var, Image.Image) except: return False def _is_data_frame(self, var): """Return True if variable is a DataFrame""" try: from pandas import DataFrame return isinstance(var, DataFrame) except: return False def _is_series(self, var): """Return True if variable is a Series""" try: from pandas import Series return isinstance(var, Series) except: return False def _get_array_shape(self, var): """Return array's shape""" try: if self._is_array(var): return var.shape else: return None except: return None def _get_array_ndim(self, var): """Return array's ndim""" try: if self._is_array(var): return var.ndim else: return None except: return None # --- For Pdb def _register_pdb_session(self, pdb_obj): """Register Pdb session to use it later""" self._pdb_obj = pdb_obj def _set_spyder_breakpoints(self): """Set all Spyder breakpoints in an active pdb session""" if not self._pdb_obj: return self._pdb_obj.set_spyder_breakpoints() # --- For the Help plugin def _eval(self, text): """ Evaluate text and return (obj, valid) where *obj* is the object represented by *text* and *valid* is True if object evaluation did not raise any exception """ if not IS_EXT_INTERPRETER: from spyder.py3compat import is_text_string else: from py3compat import is_text_string assert is_text_string(text) ns = self._get_current_namespace(with_magics=True) try: return eval(text, ns), True except: return None, False # --- For Matplotlib def _set_mpl_backend(self, backend, pylab=False): """ Set a backend for Matplotlib. backend: A parameter that can be passed to %matplotlib (e.g. inline or tk). """ import traceback from IPython.core.getipython import get_ipython generic_error = ("\n" "NOTE: The following error appeared when setting " "your Matplotlib backend\n\n" "{0}") magic = 'pylab' if pylab else 'matplotlib' error = None try: get_ipython().run_line_magic(magic, backend) except RuntimeError as err: # This catches errors generated by ipykernel when # trying to set a backend. See issue 5541 if "GUI eventloops" in str(err): import matplotlib previous_backend = matplotlib.get_backend() error = ("\n" "NOTE: Spyder *can't* set your selected Matplotlib " "backend because there is a previous backend already " "in use.\n\n" "Your backend will be {0}".format(previous_backend)) del matplotlib # This covers other RuntimeError's else: error = generic_error.format(traceback.format_exc()) except Exception: error = generic_error.format(traceback.format_exc()) self._mpl_backend_error = error def _show_mpl_backend_errors(self): """Show Matplotlib backend errors after the prompt is ready.""" if self._mpl_backend_error is not None: print(self._mpl_backend_error) # spyder: test-skip # --- Others def _load_autoreload_magic(self): """Load %autoreload magic.""" from IPython.core.getipython import get_ipython get_ipython().run_line_magic('reload_ext', 'autoreload') get_ipython().run_line_magic('autoreload', '2') spyder-3.2.6/spyder/utils/ipython/__init__.py0000664000175000017500000000031613026261006022067 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Utilities for the IPython console """ spyder-3.2.6/spyder/utils/ipython/start_kernel.py0000664000175000017500000002103513224121062023023 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ File used to start kernels for the IPython Console """ # Standard library imports from distutils.version import LooseVersion import os import os.path as osp import sys PY2 = sys.version[0] == '2' def is_module_installed(module_name): """ Simpler version of spyder.utils.programs.is_module_installed to improve startup time. """ try: __import__(module_name) return True except: # Module is not installed return False def sympy_config(mpl_backend): """Sympy configuration""" if mpl_backend is not None: lines = """ from sympy.interactive import init_session init_session() %matplotlib {0} """.format(mpl_backend) else: lines = """ from sympy.interactive import init_session init_session() """ return lines def kernel_config(): """Create a config object with IPython kernel options.""" import ipykernel from IPython.core.application import get_ipython_dir from traitlets.config.loader import Config, load_pyconfig_files # ---- IPython config ---- try: profile_path = osp.join(get_ipython_dir(), 'profile_default') cfg = load_pyconfig_files(['ipython_config.py', 'ipython_kernel_config.py'], profile_path) except: cfg = Config() # ---- Spyder config ---- spy_cfg = Config() # Until we implement Issue 1052 spy_cfg.InteractiveShell.xmode = 'Plain' # - Using Jedi slow completions a lot for objects with big repr's. # - Jedi completions are not available in Python 2. if not PY2: spy_cfg.IPCompleter.use_jedi = False # Run lines of code at startup run_lines_o = os.environ.get('SPY_RUN_LINES_O') if run_lines_o is not None: spy_cfg.IPKernelApp.exec_lines = [x.strip() for x in run_lines_o.split(',')] else: spy_cfg.IPKernelApp.exec_lines = [] # Clean terminal arguments input clear_argv = "import sys;sys.argv = [''];del sys" spy_cfg.IPKernelApp.exec_lines.append(clear_argv) # Load %autoreload magic spy_cfg.IPKernelApp.exec_lines.append( "get_ipython().kernel._load_autoreload_magic()") # Default inline backend configuration # This is useful to have when people doesn't # use our config system to configure the # inline backend but want to use # '%matplotlib inline' at runtime if LooseVersion(ipykernel.__version__) < LooseVersion('4.5'): dpi_option = 'savefig.dpi' else: dpi_option = 'figure.dpi' spy_cfg.InlineBackend.rc = {'figure.figsize': (6.0, 4.0), dpi_option: 72, 'font.size': 10, 'figure.subplot.bottom': .125, 'figure.facecolor': 'white', 'figure.edgecolor': 'white'} # Pylab configuration mpl_backend = None pylab_o = os.environ.get('SPY_PYLAB_O') if pylab_o == 'True' and is_module_installed('matplotlib'): # Set Matplotlib backend backend_o = os.environ.get('SPY_BACKEND_O') if backend_o is not None: if backend_o == '1': if is_module_installed('PyQt5'): auto_backend = 'qt5' elif is_module_installed('PyQt4'): auto_backend = 'qt4' elif is_module_installed('_tkinter'): auto_backend = 'tk' else: auto_backend = 'inline' else: auto_backend = '' backends = {'0': 'inline', '1': auto_backend, '2': 'qt5', '3': 'qt4', '4': 'osx', '5': 'gtk3', '6': 'gtk', '7': 'wx', '8': 'tk'} mpl_backend = backends[backend_o] # Automatically load Pylab and Numpy, or only set Matplotlib # backend autoload_pylab_o = os.environ.get('SPY_AUTOLOAD_PYLAB_O') == 'True' command = "get_ipython().kernel._set_mpl_backend('{0}', {1})" spy_cfg.IPKernelApp.exec_lines.append( command.format(mpl_backend, autoload_pylab_o)) # Inline backend configuration if mpl_backend == 'inline': # Figure format format_o = os.environ.get('SPY_FORMAT_O') formats = {'0': 'png', '1': 'svg'} if format_o is not None: spy_cfg.InlineBackend.figure_format = formats[format_o] # Resolution resolution_o = os.environ.get('SPY_RESOLUTION_O') if resolution_o is not None: spy_cfg.InlineBackend.rc[dpi_option] = float(resolution_o) # Figure size width_o = float(os.environ.get('SPY_WIDTH_O')) height_o = float(os.environ.get('SPY_HEIGHT_O')) if width_o is not None and height_o is not None: spy_cfg.InlineBackend.rc['figure.figsize'] = (width_o, height_o) # Enable Cython magic if is_module_installed('Cython'): spy_cfg.IPKernelApp.exec_lines.append('%load_ext Cython') # Run a file at startup use_file_o = os.environ.get('SPY_USE_FILE_O') run_file_o = os.environ.get('SPY_RUN_FILE_O') if use_file_o == 'True' and run_file_o is not None: spy_cfg.IPKernelApp.file_to_run = run_file_o # Autocall autocall_o = os.environ.get('SPY_AUTOCALL_O') if autocall_o is not None: spy_cfg.ZMQInteractiveShell.autocall = int(autocall_o) # To handle the banner by ourselves in IPython 3+ spy_cfg.ZMQInteractiveShell.banner1 = '' # Greedy completer greedy_o = os.environ.get('SPY_GREEDY_O') == 'True' spy_cfg.IPCompleter.greedy = greedy_o # Sympy loading sympy_o = os.environ.get('SPY_SYMPY_O') == 'True' if sympy_o and is_module_installed('sympy'): lines = sympy_config(mpl_backend) spy_cfg.IPKernelApp.exec_lines.append(lines) # Merge IPython and Spyder configs. Spyder prefs will have prevalence # over IPython ones cfg._merge(spy_cfg) return cfg def varexp(line): """ Spyder's variable explorer magic Used to generate plots, histograms and images of the variables displayed on it. """ ip = get_ipython() #analysis:ignore funcname, name = line.split() import spyder.pyplot __fig__ = spyder.pyplot.figure(); __items__ = getattr(spyder.pyplot, funcname[2:])(ip.user_ns[name]) spyder.pyplot.show() del __fig__, __items__ def main(): # Remove this module's path from sys.path: try: sys.path.remove(osp.dirname(__file__)) except ValueError: pass try: locals().pop('__file__') except KeyError: pass __doc__ = '' __name__ = '__main__' # Add current directory to sys.path (like for any standard Python interpreter # executed in interactive mode): sys.path.insert(0, '') # Fire up the kernel instance. from ipykernel.kernelapp import IPKernelApp if not os.environ.get('SPY_EXTERNAL_INTERPRETER') == "True": from spyder.utils.ipython.spyder_kernel import SpyderKernel else: # We add "spyder" to sys.path for external interpreters, # so this works! # See create_kernel_spec of plugins/ipythonconsole from utils.ipython.spyder_kernel import SpyderKernel kernel = IPKernelApp.instance() kernel.kernel_class = SpyderKernel try: kernel.config = kernel_config() except: pass kernel.initialize() # Set our own magics kernel.shell.register_magic_function(varexp) # Set Pdb class to be used by %debug and %pdb. # This makes IPython consoles to use the class defined in our # sitecustomize instead of their default one. import pdb kernel.shell.InteractiveTB.debugger_cls = pdb.Pdb # Start the (infinite) kernel event loop. kernel.start() if __name__ == '__main__': main() spyder-3.2.6/spyder/utils/workers.py0000664000175000017500000002630513211142273020340 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Copyright © Spyder Project Contributors # # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) # ----------------------------------------------------------------------------- """ Worker manager and workers for running files long processes in non GUI blocking threads. """ # Standard library imports from collections import deque import os import sys # Third party imports from qtpy.QtCore import (QByteArray, QObject, QProcess, QThread, QTimer, Signal) # Local imports from spyder.py3compat import PY2, to_text_string WIN = os.name == 'nt' def handle_qbytearray(obj, encoding): """Qt/Python2/3 compatibility helper.""" if isinstance(obj, QByteArray): obj = obj.data() return to_text_string(obj, encoding=encoding) class PythonWorker(QObject): """ Generic python worker for running python code on threads. For running processes (via QProcess) use the ProcessWorker. """ sig_started = Signal(object) sig_finished = Signal(object, object, object) # worker, stdout, stderr def __init__(self, func, args, kwargs): """Generic python worker for running python code on threads.""" super(PythonWorker, self).__init__() self.func = func self.args = args self.kwargs = kwargs self._is_finished = False self._started = False def is_finished(self): """Return True if worker status is finished otherwise return False.""" return self._is_finished def start(self): """Start the worker (emits sig_started signal with worker as arg).""" if not self._started: self.sig_started.emit(self) self._started = True def terminate(self): """Mark the worker as finished.""" self._is_finished = True def _start(self): """Start process worker for given method args and kwargs.""" error = None output = None try: output = self.func(*self.args, **self.kwargs) except Exception as err: error = err if not self._is_finished: self.sig_finished.emit(self, output, error) self._is_finished = True class ProcessWorker(QObject): """Process worker based on a QProcess for non blocking UI.""" sig_started = Signal(object) sig_finished = Signal(object, object, object) sig_partial = Signal(object, object, object) def __init__(self, cmd_list, environ=None): """ Process worker based on a QProcess for non blocking UI. Parameters ---------- cmd_list : list of str Command line arguments to execute. environ : dict Process environment, """ super(ProcessWorker, self).__init__() self._result = None self._cmd_list = cmd_list self._fired = False self._communicate_first = False self._partial_stdout = None self._started = False self._timer = QTimer() self._process = QProcess() self._set_environment(environ) self._timer.setInterval(150) self._timer.timeout.connect(self._communicate) self._process.readyReadStandardOutput.connect(self._partial) def _get_encoding(self): """Return the encoding/codepage to use.""" enco = 'utf-8' # Currently only cp1252 is allowed? if WIN: import ctypes codepage = to_text_string(ctypes.cdll.kernel32.GetACP()) # import locale # locale.getpreferredencoding() # Differences? enco = 'cp' + codepage return enco def _set_environment(self, environ): """Set the environment on the QProcess.""" if environ: q_environ = self._process.processEnvironment() for k, v in environ.items(): q_environ.insert(k, v) self._process.setProcessEnvironment(q_environ) def _partial(self): """Callback for partial output.""" raw_stdout = self._process.readAllStandardOutput() stdout = handle_qbytearray(raw_stdout, self._get_encoding()) if self._partial_stdout is None: self._partial_stdout = stdout else: self._partial_stdout += stdout self.sig_partial.emit(self, stdout, None) def _communicate(self): """Callback for communicate.""" if (not self._communicate_first and self._process.state() == QProcess.NotRunning): self.communicate() elif self._fired: self._timer.stop() def communicate(self): """Retrieve information.""" self._communicate_first = True self._process.waitForFinished() enco = self._get_encoding() if self._partial_stdout is None: raw_stdout = self._process.readAllStandardOutput() stdout = handle_qbytearray(raw_stdout, enco) else: stdout = self._partial_stdout raw_stderr = self._process.readAllStandardError() stderr = handle_qbytearray(raw_stderr, enco) result = [stdout.encode(enco), stderr.encode(enco)] if PY2: stderr = stderr.decode() result[-1] = '' self._result = result if not self._fired: self.sig_finished.emit(self, result[0], result[-1]) self._fired = True return result def close(self): """Close the running process.""" self._process.close() def is_finished(self): """Return True if worker has finished processing.""" return self._process.state() == QProcess.NotRunning and self._fired def _start(self): """Start process.""" if not self._fired: self._partial_ouput = None self._process.start(self._cmd_list[0], self._cmd_list[1:]) self._timer.start() def terminate(self): """Terminate running processes.""" if self._process.state() == QProcess.Running: try: self._process.terminate() except Exception: pass self._fired = True def start(self): """Start worker.""" if not self._started: self.sig_started.emit(self) self._started = True class WorkerManager(QObject): """Spyder Worker Manager for Generic Workers.""" def __init__(self, max_threads=10): """Spyder Worker Manager for Generic Workers.""" super(QObject, self).__init__() self._queue = deque() self._queue_workers = deque() self._threads = [] self._workers = [] self._timer = QTimer() self._timer_worker_delete = QTimer() self._running_threads = 0 self._max_threads = max_threads # Keeps references to old workers # Needed to avoud C++/python object errors self._bag_collector = deque() self._timer.setInterval(333) self._timer.timeout.connect(self._start) self._timer_worker_delete.setInterval(5000) self._timer_worker_delete.timeout.connect(self._clean_workers) def _clean_workers(self): """Delete periodically workers in workers bag.""" while self._bag_collector: self._bag_collector.popleft() self._timer_worker_delete.stop() def _start(self, worker=None): """Start threads and check for inactive workers.""" if worker: self._queue_workers.append(worker) if self._queue_workers and self._running_threads < self._max_threads: #print('Queue: {0} Running: {1} Workers: {2} ' # 'Threads: {3}'.format(len(self._queue_workers), # self._running_threads, # len(self._workers), # len(self._threads))) self._running_threads += 1 worker = self._queue_workers.popleft() thread = QThread() if isinstance(worker, PythonWorker): worker.moveToThread(thread) worker.sig_finished.connect(thread.quit) thread.started.connect(worker._start) thread.start() elif isinstance(worker, ProcessWorker): thread.quit() worker._start() self._threads.append(thread) else: self._timer.start() if self._workers: for w in self._workers: if w.is_finished(): self._bag_collector.append(w) self._workers.remove(w) if self._threads: for t in self._threads: if t.isFinished(): self._threads.remove(t) self._running_threads -= 1 if len(self._threads) == 0 and len(self._workers) == 0: self._timer.stop() self._timer_worker_delete.start() def create_python_worker(self, func, *args, **kwargs): """Create a new python worker instance.""" worker = PythonWorker(func, args, kwargs) self._create_worker(worker) return worker def create_process_worker(self, cmd_list, environ=None): """Create a new process worker instance.""" worker = ProcessWorker(cmd_list, environ=environ) self._create_worker(worker) return worker def terminate_all(self): """Terminate all worker processes.""" for worker in self._workers: worker.terminate() # for thread in self._threads: # try: # thread.terminate() # thread.wait() # except Exception: # pass self._queue_workers = deque() def _create_worker(self, worker): """Common worker setup.""" worker.sig_started.connect(self._start) self._workers.append(worker) # --- Local testing # ----------------------------------------------------------------------------- def ready_print(worker, output, error): # pragma: no cover """Print worker output for tests.""" print(worker, output, error) # spyder: test-skip def sleeping_func(arg, secs=10, result_queue=None): """This methods illustrates how the workers can be used.""" import time time.sleep(secs) if result_queue is not None: result_queue.put(arg) else: return arg def local_test(): # pragma: no cover """Main local test.""" from spyder.utils.qthelpers import qapplication app = qapplication() wm = WorkerManager(max_threads=3) for i in range(7): worker = wm.create_python_worker(sleeping_func, 'BOOM! {}'.format(i), secs=5) worker.sig_finished.connect(ready_print) worker.start() worker = wm.create_python_worker(sleeping_func, 'BOOM!', secs=5) worker.sig_finished.connect(ready_print) worker.start() worker = wm.create_process_worker(['conda', 'info', '--json']) worker.sig_finished.connect(ready_print) worker.start() # wm.terminate_all() # wm.terminate_all() sys.exit(app.exec_()) if __name__ == '__main__': # pragma: no cover local_test() spyder-3.2.6/spyder/utils/icon_manager.py0000664000175000017500000004011313224740762021272 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) # Standard library imports import os.path as osp # Third party imports from qtpy.QtGui import QIcon from qtpy.QtWidgets import QStyle, QWidget # Local imports from spyder.config.base import get_image_path from spyder.config.main import CONF import qtawesome as qta _resource = { 'directory': osp.join(osp.dirname(osp.realpath(__file__)), '../fonts'), 'loaded': False, } _qtaargs = { 'log': [('fa.file-text-o',), {}], 'configure': [('fa.wrench',), {}], 'bold': [('fa.bold',), {}], 'italic': [('fa.italic',), {}], 'genprefs': [('fa.cogs',), {}], 'exit': [('fa.power-off',), {}], 'run_small': [('fa.play',), {'color': 'green'}], 'stop': [('fa.stop',), {'color': 'darkred'}], 'syspath': [('fa.cogs',), {}], 'font': [('fa.font',), {}], 'keyboard': [('fa.keyboard-o',), {}], 'eyedropper': [('fa.eyedropper',), {}], 'tooloptions': [('fa.cog',), {'color': '#333333'}], 'edit24': [('fa.edit',), {}], 'edit': [('fa.edit',), {}], 'filenew': [('fa.file-o',), {}], 'fileopen': [('fa.folder-open',), {}], 'revert': [('fa.undo',), {}], 'filesave': [('fa.save',), {}], 'save_all': [('fa.save', 'fa.save'), {'options': [{'offset': (-0.2, -0.2), 'scale_factor': 0.6}, {'offset': (0.2, 0.2), 'scale_factor': 0.6}]}], 'filesaveas': [('fa.save', 'fa.pencil'), {'options': [{'offset': (-0.2, -0.2), 'scale_factor': 0.6}, {'offset': (0.2, 0.2), 'scale_factor': 0.6}]}], 'print': [('fa.print',), {}], 'fileclose': [('fa.close',), {}], 'filecloseall': [('fa.close', 'fa.close', 'fa.close'), {'options': [{'scale_factor': 0.6, 'offset': (0.3, -0.3)}, {'scale_factor': 0.6, 'offset': (-0.3, -0.3)}, {'scale_factor': 0.6, 'offset': (0.3, 0.3)}]}], 'breakpoint_big': [('fa.circle',), {'color': 'darkred'} ], 'breakpoint_cond_big': [('fa.question-circle',), {'color': 'darkred'},], 'debug': [('spyder.debug',), {'color': '#3775a9'}], 'arrow-step-over': [('spyder.step-forward',), {'color': '#3775a9'}], 'arrow-continue': [('spyder.continue',), {'color': '#3775a9'}], 'arrow-step-in': [('spyder.step-into',), {'color': '#3775a9'}], 'arrow-step-out': [('spyder.step-out',), {'color': '#3775a9'}], 'stop_debug': [('fa.stop',), {'color': '#3775a9'}], 'run': [('fa.play',), {'color': 'green'}], 'run_settings': [('fa.wrench', 'fa.play'), {'options': [{'offset':(0.0, -0.1)}, {'offset': (0.2, 0.125), 'color': 'green', 'scale_factor': 0.8}]}], 'run_again': [('fa.repeat', 'fa.play'), {'options': [{'offset':(0.0, -0.1)}, {'offset': (0.2, 0.125), 'color': 'green', 'scale_factor': 0.8}]}], 'run_selection': [('spyder.run-selection',), {}], 'run_cell': [('spyder.cell-code', 'spyder.cell-border', 'spyder.cell-play'), {'options': [{'color': '#fff683'}, {}, {'color': 'green'}]}], 'run_cell_advance': [('spyder.cell-code', 'spyder.cell-border', 'spyder.cell-play', 'spyder.cell-next'), {'options': [{'color': '#fff683'}, {}, {'color': 'green'}, {'color': 'red'}]}], 'todo_list': [('fa.th-list', 'fa.check'), {'options': [{'color': '#999999'}, {'offset': (0.0, 0.2), 'color': '#3775a9', 'color_disabled': '#748fa6'}]}], 'wng_list': [('fa.th-list', 'fa.warning'), {'options': [{'color': '#999999'}, {'offset': (0.0, 0.2), 'scale_factor': 0.75, 'color': 'orange', 'color_disabled': '#face7e'}]}], 'prev_wng': [('fa.arrow-left', 'fa.warning'), {'options': [{'color': '#999999'}, {'offset': (0.0, 0.2), 'scale_factor': 0.75, 'color': 'orange', 'color_disabled': '#face7e'}]}], 'next_wng': [('fa.arrow-right', 'fa.warning'), {'options': [{'color': '999999'}, {'offset': (0.0, 0.2), 'scale_factor': 0.75, 'color': 'orange', 'color_disabled': '#face7e'}]}], 'last_edit_location': [('fa.caret-up',), {}], 'prev_cursor': [('fa.hand-o-left',), {}], 'next_cursor': [('fa.hand-o-right',), {}], 'comment': [('fa.comment',), {}], 'indent': [('fa.indent',), {}], 'unindent': [('fa.outdent',), {}], 'gotoline': [('fa.sort-numeric-asc',), {}], 'error': [('fa.times-circle',), {'color': 'darkred'}], 'warning': [('fa.warning',), {'color': 'orange'}], 'todo': [('fa.check',), {'color': '#3775a9'}], 'ipython_console': [('spyder.ipython-logo-alt',), {}], 'ipython_console_t': [('spyder.ipython-logo-alt',), {'color':'gray'}], 'python': [('spyder.python-logo-up', 'spyder.python-logo-down'), {'options': [{'color': '#3775a9'}, {'color': '#ffd444'}]}], 'python_t': [('spyder.python-logo',), {'color':'gray'}], 'pythonpath': [('spyder.python-logo-up', 'spyder.python-logo-down'), {'options': [{'color': '#3775a9'}, {'color': '#ffd444'}]}], 'terminated': [('fa.circle',), {}], 'cmdprompt': [('fa.terminal',), {}], 'cmdprompt_t': [('fa.terminal',), {'color':'gray'}], 'console': [('spyder.python-logo-up', 'spyder.python-logo-down'), {'options': [{'color': '#3775a9'}, {'color': '#ffd444'}]}], 'findf': [('fa.file-o', 'fa.search'), {'options': [{'scale_factor': 1.0}, {'scale_factor': 0.6}]}], 'history24': [('fa.history',), {}], 'history': [('fa.history',), {}], 'help': [('fa.question-circle',), {}], 'lock': [('fa.lock',), {}], 'lock_open': [('fa.unlock-alt',), {}], 'outline_explorer': [('spyder.treeview',), {}], 'project_expanded': [('fa.plus',), {}], 'dictedit': [('fa.th-list',), {}], 'previous': [('fa.arrow-left',), {}], 'next': [('fa.arrow-right',), {}], 'set_workdir': [('fa.check',), {}], 'up': [('fa.arrow-up',), {}], 'down': [('fa.arrow-down',), {}], 'filesaveas2': [('fa.save', 'fa.close'), {'options': [{'scale_factor': 0.8, 'offset': (-0.1, -0.1)}, {'offset': (0.2, 0.2)}]}], # save_session_action 'spyder': [('spyder.spyder-logo-background', 'spyder.spyder-logo-web', 'spyder.spyder-logo-snake'), {'options': [{'color': '#414141'}, {'color': '#fafafa'}, {'color': '#ee0000'}]}], 'find': [('fa.search',), {}], 'findnext': [('fa.search', 'fa.long-arrow-down'), {'options':[{'scale_factor': 0.6, 'offset': (0.3, 0.0)}, {'offset': (-0.3, 0.0)}]}], 'findprevious': [('fa.search', 'fa.long-arrow-up'), {'options':[{'scale_factor': 0.6, 'offset': (0.3, 0.0)}, {'offset': (-0.3, 0.0)}]}], 'replace': [('fa.exchange',), {}], 'undo': [('fa.undo',), {}], 'redo': [('fa.repeat',), {}], 'restart': [('fa.repeat',), {'çolor': '#3775a9'}], 'editcopy': [('fa.copy',), {}], 'editcut': [('fa.scissors',), {}], 'editpaste': [('fa.clipboard',), {}], 'editdelete': [('fa.eraser',), {}], 'editclear': [('fa.times',), {}], 'selectall': [('spyder.text-select-all',), {}], 'pythonpath_mgr': [('spyder.python-logo-up', 'spyder.python-logo-down'), {'options': [{'color': '#3775a9'}, {'color': '#ffd444'}]}], 'exit': [('fa.power-off',), {'color': 'darkred'}], 'advanced': [('fa.gear',), {}], 'bug': [('fa.bug',), {}], 'maximize': [('spyder.maximize-pane',), {}], 'unmaximize': [('spyder.minimize-pane',), {}], 'window_nofullscreen': [('spyder.inward',), {}], 'window_fullscreen': [('fa.arrows-alt',), {}], 'MessageBoxWarning': [('fa.warning',), {}], 'arredit': [('fa.table',), {}], 'zoom_out': [('fa.search-minus',), {}], 'zoom_in': [('fa.search-plus',), {}], 'home': [('fa.home',), {}], 'find': [('fa.search',), {}], 'plot': [('fa.line-chart',), {}], 'hist': [('fa.bar-chart',), {}], 'imshow': [('fa.image',), {}], 'insert': [('fa.sign-in',), {}], 'rename': [('fa.pencil',), {}], 'edit_add': [('fa.plus',), {}], 'edit_remove': [('fa.minus',), {}], 'browse_tab': [('fa.folder-o',), {}], 'filelist': [('fa.list',), {}], 'newwindow': [('spyder.window',), {}], 'versplit': [('spyder.rows',), {}], 'horsplit': [('fa.columns',), {}], 'close_panel': [('fa.close',), {}], 'class': [('spyder.circle-letter-c',), {'color':'#3775a9'}], 'private2': [('spyder.circle-underscore',), {'color':'#e69c9c'}], 'private1': [('spyder.circle-underscore',), {'color':'#e69c9c'}], 'method': [('spyder.circle-letter-m',), {'color':'#7ea67e'}], 'function': [('spyder.circle-letter-f',), {'color':'orange'}], 'blockcomment': [('spyder.circle-hash',), {'color':'grey'}], 'cell': [('spyder.circle-percent',), {'color':'red'}], 'fromcursor': [('fa.hand-o-right',), {}], 'filter': [('fa.filter',), {}], 'folder_new': [('fa.folder-o', 'fa.plus'), {'options': [{}, {'scale_factor': 0.5, 'offset': (0.0, 0.1)}]}], 'package_new': [('fa.folder-o', 'spyder.python-logo'), {'options': [{'offset': (0.0, -0.125)}, {'offset': (0.0, 0.125)}]}], 'vcs_commit': [('fa.check',), {'color': 'green'}], 'vcs_browse': [('fa.search',), {'color': 'green'}], 'kill': [('fa.warning',), {}], 'reload': [('fa.repeat',), {}], 'auto_reload': [('fa.repeat', 'fa.clock-o'), {'options': [{'scale_factor': 0.75, 'offset': (-0.1, -0.1)}, {'scale_factor': 0.5, 'offset': (0.25, 0.25)}]}], 'fileimport': [('fa.download',), {}], 'environ': [('fa.th-list',), {}], 'options_less': [('fa.minus-square',), {}], 'options_more': [('fa.plus-square',), {}], 'ArrowDown': [('fa.arrow-circle-down',), {}], 'ArrowUp': [('fa.arrow-circle-up',), {}], 'ArrowBack': [('fa.arrow-circle-left',), {}], 'ArrowForward': [('fa.arrow-circle-right',), {}], 'DialogApplyButton': [('fa.check',), {}], 'DialogCloseButton': [('fa.close',), {}], 'DirClosedIcon': [('fa.folder-o',), {}], 'DialogHelpButton': [('fa.life-ring',), {'color': 'darkred'}], 'MessageBoxInformation': [('fa.info',), {'color': '3775a9'}], 'DirOpenIcon': [('fa.folder-open',), {}], 'FileIcon': [('fa.file-o',), {}], 'ExcelFileIcon': [('fa.file-excel-o',), {}], 'WordFileIcon': [('fa.file-word-o',), {}], 'PowerpointFileIcon': [('fa.file-powerpoint-o',), {}], 'PDFIcon': [('fa.file-pdf-o',), {}], 'AudioFileIcon': [('fa.file-audio-o',), {}], 'ImageFileIcon': [('fa.file-image-o',), {}], 'ArchiveFileIcon': [('fa.file-archive-o',), {}], 'VideoFileIcon': [('fa.file-video-o',), {}], 'TextFileIcon': [('fa.file-text-o',), {}], 'project': [('fa.folder-open-o',), {}], 'DriveHDIcon': [('fa.hdd-o',), {}], 'arrow': [('fa.arrow-right',), {}], 'collapse': [('spyder.inward',), {}], 'expand': [('fa.arrows-alt',), {}], 'restore': [('fa.level-up',), {}], 'collapse_selection': [('fa.minus-square-o',), {}], 'expand_selection': [('fa.plus-square-o',), {}], 'copywop': [('fa.terminal',), {}], 'editpaste': [('fa.paste',), {}], 'editcopy': [('fa.copy',), {}], 'edit': [('fa.edit',), {}], 'convention': [('spyder.circle-letter-c',), {'color':'#3775a9'}], 'refactor': [('spyder.circle-letter-r',), {'color':'#3775a9'}], '2uparrow': [('fa.angle-double-up',), {}], '1uparrow': [('fa.angle-up',), {}], '2downarrow': [('fa.angle-double-down',), {}], '1downarrow': [('fa.angle-down',), {}], 'attribute': [('spyder.circle-letter-a',), {'color': 'magenta'}], 'module': [('spyder.circle-letter-m',), {'color': '#daa520'}], 'no_match': [('fa.circle',), {'color': 'gray'}], 'no_match': [('fa.circle',), {'color': 'gray'}], # --- Third party plugins ------------------------------------------------ 'profiler': [('fa.clock-o',), {}], 'pylint': [('fa.search', 'fa.check'), {'options': [{}, {'offset': (0.125, 0.125), 'color': 'orange'}]}], 'condapackages': [('fa.archive',), {}], 'spyder.example': [('fa.eye',), {}], 'spyder.autopep8': [('fa.eye',), {}], 'spyder.memory_profiler': [('fa.eye',), {}], 'spyder.line_profiler': [('fa.eye',), {}], 'symbol_find': [('fa.at',), {}] } def get_std_icon(name, size=None): """Get standard platform icon Call 'show_std_icons()' for details""" if not name.startswith('SP_'): name = 'SP_' + name icon = QWidget().style().standardIcon(getattr(QStyle, name)) if size is None: return icon else: return QIcon(icon.pixmap(size, size)) def get_icon(name, default=None, resample=False): """Return image inside a QIcon object. default: default image name or icon resample: if True, manually resample icon pixmaps for usual sizes (16, 24, 32, 48, 96, 128, 256). This is recommended for QMainWindow icons created from SVG images on non-Windows platforms due to a Qt bug (see Issue 1314). """ icon_path = get_image_path(name, default=None) if icon_path is not None: icon = QIcon(icon_path) elif isinstance(default, QIcon): icon = default elif default is None: try: icon = get_std_icon(name[:-4]) except AttributeError: icon = QIcon(get_image_path(name, default)) else: icon = QIcon(get_image_path(name, default)) if resample: icon0 = QIcon() for size in (16, 24, 32, 48, 96, 128, 256, 512): icon0.addPixmap(icon.pixmap(size, size)) return icon0 else: return icon def icon(name, resample=False, icon_path=None): theme = CONF.get('main', 'icon_theme') if theme == 'spyder 3': if not _resource['loaded']: qta.load_font('spyder', 'spyder.ttf', 'spyder-charmap.json', directory=_resource['directory']) _resource['loaded'] = True args, kwargs = _qtaargs[name] return qta.icon(*args, **kwargs) elif theme == 'spyder 2': icon = get_icon(name + '.png', resample=resample) if icon_path: icon_path = osp.join(icon_path, name + '.png') if osp.isfile(icon_path): icon = QIcon(icon_path) return icon if icon is not None else QIcon() spyder-3.2.6/spyder/utils/system.py0000664000175000017500000000504313156676663020213 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Operating system utilities""" import os # Local imports from spyder.utils import programs def windows_memory_usage(): """Return physical memory usage (float) Works on Windows platforms only""" from ctypes import windll, Structure, c_uint64, sizeof, byref from ctypes.wintypes import DWORD class MemoryStatus(Structure): _fields_ = [('dwLength', DWORD), ('dwMemoryLoad',DWORD), ('ullTotalPhys', c_uint64), ('ullAvailPhys', c_uint64), ('ullTotalPageFile', c_uint64), ('ullAvailPageFile', c_uint64), ('ullTotalVirtual', c_uint64), ('ullAvailVirtual', c_uint64), ('ullAvailExtendedVirtual', c_uint64),] memorystatus = MemoryStatus() # MSDN documetation states that dwLength must be set to MemoryStatus # size before calling GlobalMemoryStatusEx # http://msdn.microsoft.com/en-us/library/aa366770(v=vs.85) memorystatus.dwLength = sizeof(memorystatus) windll.kernel32.GlobalMemoryStatusEx(byref(memorystatus)) return float(memorystatus.dwMemoryLoad) def psutil_phymem_usage(): """ Return physical memory usage (float) Requires the cross-platform psutil (>=v0.3) library (http://code.google.com/p/psutil/) """ import psutil # This is needed to avoid a deprecation warning error with # newer psutil versions try: percent = psutil.virtual_memory().percent except: percent = psutil.phymem_usage().percent return percent if programs.is_module_installed('psutil', '>=0.3.0'): # Function `psutil.phymem_usage` was introduced in psutil v0.3.0 memory_usage = psutil_phymem_usage elif os.name == 'nt': # Backup plan for Windows platforms memory_usage = windows_memory_usage else: raise ImportError("Feature requires psutil 0.3+ on non Windows platforms") if __name__ == '__main__': print("*"*80) # spyder: test-skip print(memory_usage.__doc__) # spyder: test-skip print(memory_usage()) # spyder: test-skip if os.name == 'nt': # windll can only be imported if os.name = 'nt' or 'ce' print("*"*80) # spyder: test-skip print(windows_memory_usage.__doc__) # spyder: test-skip print(windows_memory_usage()) # spyder: test-skipspyder-3.2.6/spyder/utils/iofuncs.py0000664000175000017500000004103513224121062020304 0ustar carloscarlos00000000000000# -*- coding:utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Input/Output Utilities Note: 'load' functions has to return a dictionary from which a globals() namespace may be updated """ from __future__ import print_function import sys import os import tarfile import tempfile import os.path as osp import shutil import warnings import json import inspect import dis # - If pandas fails to import here (for any reason), Spyder # will crash at startup (e.g. see Issue 2300) # - This also prevents Spyder to start IPython kernels # (see Issue 2456) try: import pandas as pd except: pd = None #analysis:ignore # Local imports from spyder.config.base import _, get_conf_path from spyder.py3compat import pickle, to_text_string, PY2 from spyder.utils.misc import getcwd_or_home class MatlabStruct(dict): """ Matlab style struct, enhanced. Supports dictionary and attribute style access. Can be pickled, and supports code completion in a REPL. Examples ======== >>> from spyder.utils.iofuncs import MatlabStruct >>> a = MatlabStruct() >>> a.b = 'spam' # a["b"] == 'spam' >>> a.c["d"] = 'eggs' # a.c.d == 'eggs' >>> print(a) {'c': {'d': 'eggs'}, 'b': 'spam'} """ def __getattr__(self, attr): """Access the dictionary keys for unknown attributes.""" try: return self[attr] except KeyError: msg = "'MatlabStruct' object has no attribute %s" % attr raise AttributeError(msg) def __getitem__(self, attr): """ Get a dict value; create a MatlabStruct if requesting a submember. Do not create a key if the attribute starts with an underscore. """ if attr in self.keys() or attr.startswith('_'): return dict.__getitem__(self, attr) frame = inspect.currentframe() # step into the function that called us if frame.f_back.f_back and self._is_allowed(frame.f_back.f_back): dict.__setitem__(self, attr, MatlabStruct()) elif self._is_allowed(frame.f_back): dict.__setitem__(self, attr, MatlabStruct()) return dict.__getitem__(self, attr) def _is_allowed(self, frame): """Check for allowed op code in the calling frame""" allowed = [dis.opmap['STORE_ATTR'], dis.opmap['LOAD_CONST'], dis.opmap.get('STOP_CODE', 0)] bytecode = frame.f_code.co_code instruction = bytecode[frame.f_lasti + 3] instruction = ord(instruction) if PY2 else instruction return instruction in allowed __setattr__ = dict.__setitem__ __delattr__ = dict.__delitem__ @property def __dict__(self): """Allow for code completion in a REPL""" return self.copy() def get_matlab_value(val): """ Extract a value from a Matlab file From the oct2py project, see http://pythonhosted.org/oct2py/conversions.html """ import numpy as np # Extract each item of a list. if isinstance(val, list): return [get_matlab_value(v) for v in val] # Ignore leaf objects. if not isinstance(val, np.ndarray): return val # Convert user defined classes. if hasattr(val, 'classname'): out = dict() for name in val.dtype.names: out[name] = get_matlab_value(val[name].squeeze().tolist()) cls = type(val.classname, (object,), out) return cls() # Extract struct data. elif val.dtype.names: out = MatlabStruct() for name in val.dtype.names: out[name] = get_matlab_value(val[name].squeeze().tolist()) val = out # Extract cells. elif val.dtype.kind == 'O': val = val.squeeze().tolist() if not isinstance(val, list): val = [val] val = get_matlab_value(val) # Compress singleton values. elif val.size == 1: val = val.item() # Compress empty values. elif val.size == 0: if val.dtype.kind in 'US': val = '' else: val = [] return val try: import numpy as np try: with warnings.catch_warnings(): warnings.simplefilter("ignore") import scipy.io as spio except AttributeError: # Python 2.5: warnings.catch_warnings was introduced in Python 2.6 import scipy.io as spio # analysis:ignore except: spio = None if spio is None: load_matlab = None save_matlab = None else: def load_matlab(filename): try: out = spio.loadmat(filename, struct_as_record=True) data = dict() for (key, value) in out.items(): data[key] = get_matlab_value(value) return data, None except Exception as error: return None, str(error) def save_matlab(data, filename): try: spio.savemat(filename, data, oned_as='row') except Exception as error: return str(error) except: load_matlab = None save_matlab = None try: import numpy as np # analysis:ignore def load_array(filename): try: name = osp.splitext(osp.basename(filename))[0] data = np.load(filename) if hasattr(data, 'keys'): return data, None else: return {name: data}, None except Exception as error: return None, str(error) def __save_array(data, basename, index): """Save numpy array""" fname = basename + '_%04d.npy' % index np.save(fname, data) return fname except: load_array = None try: from spyder.pil_patch import Image if sys.byteorder == 'little': _ENDIAN = '<' else: _ENDIAN = '>' DTYPES = { "1": ('|b1', None), "L": ('|u1', None), "I": ('%si4' % _ENDIAN, None), "F": ('%sf4' % _ENDIAN, None), "I;16": ('|u2', None), "I;16S": ('%si2' % _ENDIAN, None), "P": ('|u1', None), "RGB": ('|u1', 3), "RGBX": ('|u1', 4), "RGBA": ('|u1', 4), "CMYK": ('|u1', 4), "YCbCr": ('|u1', 4), } def __image_to_array(filename): img = Image.open(filename) try: dtype, extra = DTYPES[img.mode] except KeyError: raise RuntimeError("%s mode is not supported" % img.mode) shape = (img.size[1], img.size[0]) if extra is not None: shape += (extra,) return np.array(img.getdata(), dtype=np.dtype(dtype)).reshape(shape) def load_image(filename): try: name = osp.splitext(osp.basename(filename))[0] return {name: __image_to_array(filename)}, None except Exception as error: return None, str(error) except: load_image = None def load_pickle(filename): """Load a pickle file as a dictionary""" try: if pd: return pd.read_pickle(filename), None else: with open(filename, 'rb') as fid: data = pickle.load(fid) return data, None except Exception as err: return None, str(err) def load_json(filename): """Load a json file as a dictionary""" try: if PY2: args = 'rb' else: args = 'r' with open(filename, args) as fid: data = json.load(fid) return data, None except Exception as err: return None, str(err) def save_dictionary(data, filename): """Save dictionary in a single file .spydata file""" filename = osp.abspath(filename) old_cwd = getcwd_or_home() os.chdir(osp.dirname(filename)) error_message = None try: saved_arrays = {} if load_array is not None: # Saving numpy arrays with np.save arr_fname = osp.splitext(filename)[0] for name in list(data.keys()): if isinstance(data[name], np.ndarray) and data[name].size > 0: # Saving arrays at data root fname = __save_array(data[name], arr_fname, len(saved_arrays)) saved_arrays[(name, None)] = osp.basename(fname) data.pop(name) elif isinstance(data[name], (list, dict)): # Saving arrays nested in lists or dictionaries if isinstance(data[name], list): iterator = enumerate(data[name]) else: iterator = iter(list(data[name].items())) to_remove = [] for index, value in iterator: if isinstance(value, np.ndarray) and value.size > 0: fname = __save_array(value, arr_fname, len(saved_arrays)) saved_arrays[(name, index)] = osp.basename(fname) to_remove.append(index) for index in sorted(to_remove, reverse=True): data[name].pop(index) if saved_arrays: data['__saved_arrays__'] = saved_arrays pickle_filename = osp.splitext(filename)[0]+'.pickle' with open(pickle_filename, 'wb') as fdesc: pickle.dump(data, fdesc, 2) tar = tarfile.open(filename, "w") for fname in [pickle_filename]+[fn for fn in list(saved_arrays.values())]: tar.add(osp.basename(fname)) os.remove(fname) tar.close() if saved_arrays: data.pop('__saved_arrays__') except (RuntimeError, pickle.PicklingError, TypeError) as error: error_message = to_text_string(error) os.chdir(old_cwd) return error_message def load_dictionary(filename): """Load dictionary from .spydata file""" filename = osp.abspath(filename) old_cwd = getcwd_or_home() tmp_folder = tempfile.mkdtemp() os.chdir(tmp_folder) data = None error_message = None try: tar = tarfile.open(filename, "r") tar.extractall() data_file = osp.basename(filename) pickle_filename = osp.splitext(data_file)[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(tmp_folder, 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 except (EOFError, ValueError) as error: error_message = to_text_string(error) os.chdir(old_cwd) try: shutil.rmtree(tmp_folder) except OSError as error: error_message = to_text_string(error) return data, error_message class IOFunctions(object): def __init__(self): self.load_extensions = None self.save_extensions = None self.load_filters = None self.save_filters = None self.load_funcs = None self.save_funcs = None 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 get_internal_funcs(self): return [ ('.spydata', _("Spyder data files"), load_dictionary, save_dictionary), ('.npy', _("NumPy arrays"), load_array, None), ('.npz', _("NumPy zip arrays"), load_array, None), ('.mat', _("Matlab files"), load_matlab, save_matlab), ('.csv', _("CSV text files"), 'import_wizard', None), ('.txt', _("Text files"), 'import_wizard', None), ('.jpg', _("JPEG images"), load_image, None), ('.png', _("PNG images"), load_image, None), ('.gif', _("GIF images"), load_image, None), ('.tif', _("TIFF images"), load_image, None), ('.pkl', _("Pickle files"), load_pickle, None), ('.pickle', _("Pickle files"), load_pickle, None), ('.json', _("JSON files"), load_json, None), ] def get_3rd_party_funcs(self): other_funcs = [] from spyder.otherplugins import get_spyderplugins_mods for mod in get_spyderplugins_mods(io=True): try: other_funcs.append((mod.FORMAT_EXT, mod.FORMAT_NAME, mod.FORMAT_LOAD, mod.FORMAT_SAVE)) except AttributeError as error: print("%s: %s" % (mod, str(error)), file=STDERR) return other_funcs def save(self, data, filename): ext = osp.splitext(filename)[1].lower() if ext in self.save_funcs: return self.save_funcs[ext](data, filename) else: return _("Unsupported file type '%s'") % ext def load(self, filename): ext = osp.splitext(filename)[1].lower() if ext in self.load_funcs: return self.load_funcs[ext](filename) else: return None, _("Unsupported file type '%s'") % ext iofunctions = IOFunctions() iofunctions.setup() def save_auto(data, filename): """Save data into filename, depending on file extension""" pass 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), 'dict': testdict, 'float': 1.2233, 'array': np.random.rand(4000, 400), 'empty_array': np.array([]), 'date': testdate, 'datetime': datetime.datetime(1945, 5, 8), } import time t0 = time.time() save_dictionary(example, "test.spydata") print(" Data saved in %.3f seconds" % (time.time()-t0)) # spyder: test-skip t0 = time.time() example2, ok = load_dictionary("test.spydata") os.remove("test.spydata") print("Data loaded in %.3f seconds" % (time.time()-t0)) # spyder: test-skip spyder-3.2.6/spyder/utils/debug.py0000664000175000017500000001126613156676663017761 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Debug utilities that are independent of Spyder code. See spyder.config.base for other helpers. """ from __future__ import print_function import inspect import traceback import time from spyder.py3compat import PY2 def log_time(fd): timestr = "Logging time: %s" % time.ctime(time.time()) print("="*len(timestr), file=fd) print(timestr, file=fd) print("="*len(timestr), file=fd) print("", file=fd) def log_last_error(fname, context=None): """Log last error in filename *fname* -- *context*: string (optional)""" fd = open(fname, 'a') log_time(fd) if context: print("Context", file=fd) print("-------", file=fd) print("", file=fd) if PY2: print(u' '.join(context).encode('utf-8').strip(), file=fd) else: print(context, file=fd) print("", file=fd) print("Traceback", file=fd) print("---------", file=fd) print("", file=fd) traceback.print_exc(file=fd) print("", file=fd) print("", file=fd) def log_dt(fname, context, t0): fd = open(fname, 'a') log_time(fd) print("%s: %d ms" % (context, 10*round(1e2*(time.time()-t0))), file=fd) print("", file=fd) print("", file=fd) def caller_name(skip=2): """ Get name of a caller in the format module.class.method `skip` specifies how many levels of call stack to skip for caller's name. skip=1 means "who calls me", skip=2 "who calls my caller" etc. An empty string is returned if skipped levels exceed stack height """ stack = inspect.stack() start = 0 + skip if len(stack) < start + 1: return '' parentframe = stack[start][0] name = [] module = inspect.getmodule(parentframe) # `modname` can be None when frame is executed directly in console # TODO(techtonik): consider using __main__ if module: name.append(module.__name__) # detect classname if 'self' in parentframe.f_locals: # I don't know any way to detect call from the object method # XXX: there seems to be no way to detect static method call - it will # be just a function call name.append(parentframe.f_locals['self'].__class__.__name__) codename = parentframe.f_code.co_name if codename != '': # top level usually name.append( codename ) # function or a method del parentframe return ".".join(name) def get_class_that_defined(method): for cls in inspect.getmro(method.im_class): if method.__name__ in cls.__dict__: return cls.__name__ def log_methods_calls(fname, some_class, prefix=None): """ Hack `some_class` to log all method calls into `fname` file. If `prefix` format is not set, each log entry is prefixed with: --[ asked / called / defined ] -- asked - name of `some_class` called - name of class for which a method is called defined - name of class where method is defined Must be used carefully, because it monkeypatches __getattribute__ call. Example: log_methods_calls('log.log', ShellBaseWidget) """ # test if file is writable open(fname, 'a').close() FILENAME = fname CLASS = some_class PREFIX = "--[ %(asked)s / %(called)s / %(defined)s ]--" if prefix != None: PREFIX = prefix MAXWIDTH = {'o_O': 10} # hack with editable closure dict, to align names def format_prefix(method, methodobj): """ --[ ShellBase / Internal / BaseEdit ]------- get_position """ classnames = { 'asked': CLASS.__name__, 'called': methodobj.__class__.__name__, 'defined': get_class_that_defined(method) } line = PREFIX % classnames MAXWIDTH['o_O'] = max(len(line), MAXWIDTH['o_O']) return line.ljust(MAXWIDTH['o_O'], '-') import types def __getattribute__(self, name): attr = object.__getattribute__(self, name) if type(attr) is not types.MethodType: return attr else: def newfunc(*args, **kwargs): log = open(FILENAME, 'a') prefix = format_prefix(attr, self) log.write('%s %s\n' % (prefix, name)) log.close() result = attr(*args, **kwargs) return result return newfunc some_class.__getattribute__ = __getattribute__ spyder-3.2.6/spyder/utils/windows.py0000664000175000017500000000274713026261006020342 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Windows-specific utilities""" from ctypes import windll # --- Window control --- SW_SHOW = 5 # activate and display SW_SHOWNA = 8 # show without activation SW_HIDE = 0 GetConsoleWindow = windll.kernel32.GetConsoleWindow ShowWindow = windll.user32.ShowWindow IsWindowVisible = windll.user32.IsWindowVisible # Handle to console window associated with current Python # interpreter procss, 0 if there is no window console_window_handle = GetConsoleWindow() def set_attached_console_visible(state): """Show/hide system console window attached to current process. Return it's previous state. Availability: Windows""" flag = {True: SW_SHOW, False: SW_HIDE} return bool(ShowWindow(console_window_handle, flag[state])) def is_attached_console_visible(): """Return True if attached console window is visible""" return IsWindowVisible(console_window_handle) def set_windows_appusermodelid(): """Make sure correct icon is used on Windows 7 taskbar""" try: return windll.shell32.SetCurrentProcessExplicitAppUserModelID("spyder.Spyder") except AttributeError: return "SetCurrentProcessExplicitAppUserModelID not found" # [ ] the console state asks for a storage container # [ ] reopen console on exit - better die open than become a zombie spyder-3.2.6/spyder/utils/fixtures.py0000664000175000017500000000340113156676663020534 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Testing utilities to be used with pytest. """ # Standard library imports import shutil import tempfile try: from unittest.mock import Mock except ImportError: from mock import Mock # Python 2 # Third party imports import pytest # Local imports from spyder.widgets.editor import EditorStack from spyder.widgets.findreplace import FindReplace from spyder.config.user import UserConfig from spyder.config.main import CONF_VERSION, DEFAULTS @pytest.fixture def tmpconfig(request): """ Fixtures that returns a temporary CONF element. """ SUBFOLDER = tempfile.mkdtemp() CONF = UserConfig('spyder-test', defaults=DEFAULTS, version=CONF_VERSION, subfolder=SUBFOLDER, raw_mode=True, ) def fin(): """ Fixture finalizer to delete the temporary CONF element. """ shutil.rmtree(SUBFOLDER) request.addfinalizer(fin) return CONF @pytest.fixture def setup_editor(qtbot): """ Set up EditorStack with CodeEditor containing some Python code. The cursor is at the empty line below the code. Returns tuple with EditorStack and CodeEditor. """ text = ('a = 1\n' 'print(a)\n' '\n' 'x = 2') # a newline is added at end editorStack = EditorStack(None, []) editorStack.set_introspector(Mock()) editorStack.set_find_widget(FindReplace(editorStack)) editorStack.set_io_actions(Mock(), Mock(), Mock(), Mock()) finfo = editorStack.new('foo.py', 'utf-8', text) qtbot.addWidget(editorStack) return editorStack, finfo.editor spyder-3.2.6/spyder/utils/bsdsocket.py0000664000175000017500000001374513156676663020660 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """BSD socket interface communication utilities""" # Be extra careful here. The interface is used to communicate with subprocesses # by redirecting output streams through a socket. Any exception in this module # and failure to read out buffers will most likely lock up Spyder. import os import socket import struct import threading import errno import traceback # Local imports from spyder.config.base import DEBUG, STDERR DEBUG_EDITOR = DEBUG >= 3 from spyder.py3compat import pickle PICKLE_HIGHEST_PROTOCOL = 2 def temp_fail_retry(error, fun, *args): """Retry to execute function, ignoring EINTR error (interruptions)""" while 1: try: return fun(*args) except error as e: eintr = errno.WSAEINTR if os.name == 'nt' else errno.EINTR if e.args[0] == eintr: continue raise SZ = struct.calcsize("l") def write_packet(sock, data, already_pickled=False): """Write *data* to socket *sock*""" if already_pickled: sent_data = data else: sent_data = pickle.dumps(data, PICKLE_HIGHEST_PROTOCOL) sent_data = struct.pack("l", len(sent_data)) + sent_data nsend = len(sent_data) while nsend > 0: nsend -= temp_fail_retry(socket.error, sock.send, sent_data) def read_packet(sock, timeout=None): """ Read data from socket *sock* Returns None if something went wrong """ sock.settimeout(timeout) dlen, data = None, None try: if os.name == 'nt': # Windows implementation datalen = sock.recv(SZ) dlen, = struct.unpack("l", datalen) data = b'' while len(data) < dlen: data += sock.recv(dlen) else: # Linux/MacOSX implementation # Thanks to eborisch: # See issue 1106 datalen = temp_fail_retry(socket.error, sock.recv, SZ, socket.MSG_WAITALL) if len(datalen) == SZ: dlen, = struct.unpack("l", datalen) data = temp_fail_retry(socket.error, sock.recv, dlen, socket.MSG_WAITALL) except socket.timeout: raise except socket.error: data = None finally: sock.settimeout(None) if data is not None: try: return pickle.loads(data) except Exception: # Catch all exceptions to avoid locking spyder if DEBUG_EDITOR: traceback.print_exc(file=STDERR) return # Using a lock object to avoid communication issues described in Issue 857 COMMUNICATE_LOCK = threading.Lock() # * Old com implementation * # See solution (1) in Issue 434, comment 13: def communicate(sock, command, settings=[]): """Communicate with monitor""" try: COMMUNICATE_LOCK.acquire() write_packet(sock, command) for option in settings: write_packet(sock, option) return read_packet(sock) finally: COMMUNICATE_LOCK.release() ## new com implementation: ## See solution (2) in Issue 434, comment 13: #def communicate(sock, command, settings=[], timeout=None): # """Communicate with monitor""" # write_packet(sock, command) # for option in settings: # write_packet(sock, option) # if timeout == 0.: # # non blocking socket is not really supported: # # setting timeout to 0. here is equivalent (in current monitor's # # implementation) to say 'I don't need to receive anything in return' # return # while True: # output = read_packet(sock, timeout=timeout) # if output is None: # return # output_command, output_data = output # if command == output_command: # return output_data # elif DEBUG: # logging.debug("###### communicate/warning /Begin ######") # logging.debug("was expecting '%s', received '%s'" \ # % (command, output_command)) # logging.debug("###### communicate/warning /End ######") class PacketNotReceived(object): pass PACKET_NOT_RECEIVED = PacketNotReceived() if __name__ == '__main__': if not os.name == 'nt': # socket read/write testing - client and server in one thread # (techtonik): the stuff below is placed into public domain print("-- Testing standard Python socket interface --") # spyder: test-skip address = ("127.0.0.1", 9999) server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.setblocking(0) server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind( address ) server.listen(2) client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect( address ) client.send("data to be catched".encode('utf-8')) # accepted server socket is the one we can read from # note that it is different from server socket accsock, addr = server.accept() print('..got "%s" from %s' % (accsock.recv(4096), addr)) # spyder: test-skip # accsock.close() # client.send("more data for recv") #socket.error: [Errno 9] Bad file descriptor # accsock, addr = server.accept() #socket.error: [Errno 11] Resource temporarily unavailable print("-- Testing BSD socket write_packet/read_packet --") # spyder: test-skip write_packet(client, "a tiny piece of data") print('..got "%s" from read_packet()' % (read_packet(accsock))) # spyder: test-skip client.close() server.close() print("-- Done.") # spyder: test-skip spyder-3.2.6/spyder/utils/tests/0000775000175000017500000000000013225025007017426 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/utils/tests/test_system.py0000664000175000017500000000113013156676663022405 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for system.py """ # Standard library imports import os # Test library imports import pytest # Local imports from spyder.utils.system import (memory_usage, windows_memory_usage) def test_system(): """Test system physical memory usage.""" if os.name == 'nt': # windll can only be imported if os.name = 'nt' or 'ce' assert windows_memory_usage() > 0 else: assert memory_usage() > 0 if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/utils/tests/windows-1252.txt0000664000175000017500000000006613156676663022301 0ustar carloscarlos00000000000000This is a sample file with encoded in windows-1252 spyder-3.2.6/spyder/utils/tests/test_sourcecode.py0000664000175000017500000001044613211142273023177 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License """Tests for sourcecode.py""" import os import sys import pytest from spyder.utils import sourcecode def test_get_primary_at(): code = 'import functools\nfunctools.partial' assert sourcecode.get_primary_at(code, len(code)) == 'functools.partial' def test_get_identifiers(): code = 'import functools\nfunctools.partial' assert set(sourcecode.get_identifiers(code)) == set(['import', 'functools', 'functools.partial']) def test_split_source(): code = 'import functools\nfunctools.partial' assert sourcecode.split_source(code) == ['import functools', 'functools.partial'] code = code.replace('\n', '\r\n') assert sourcecode.split_source(code) == ['import functools', 'functools.partial'] def test_path_components(): if sys.platform.startswith('linux'): path_components0 = ['','','documents','test','test.py'] else: path_components0 = ['c:','','documents','test','test.py'] path0 = os.path.join(*path_components0) assert sourcecode.path_components(path0) == path_components0 def test_differentiate_prefix(): if sys.platform.startswith('linux'): path_components0 = ['','','documents','test','test.py'] path_components1 = ['','','documents','projects','test','test.py'] else: path_components0 = ['c:','','documents','test','test.py'] path_components1 = ['c:','','documents','projects','test','test.py'] diff_path0 = os.path.join(*['test']) diff_path1 = os.path.join(*['projects','test']) assert sourcecode.differentiate_prefix( path_components0, path_components1) == diff_path0 assert sourcecode.differentiate_prefix( path_components1, path_components0) == diff_path1 def test_get_same_name_files(): files_path_list = [] if sys.platform.startswith('linux'): fname0 = os.path.join(*['','','documents','test','test.py']) files_path_list.append(fname0) fname1 = os.path.join(*['','','documents','projects','test','test.py']) files_path_list.append(fname1) same_name_files = [['','','documents','test','test.py'], ['','','documents','projects','test','test.py']] else: fname0 = os.path.join(*['c:','','documents','test','test.py']) files_path_list.append(fname0) fname1 = os.path.join(*['c:','','documents','projects','test','test.py']) files_path_list.append(fname1) same_name_files = [['c:','','documents','test','test.py'], ['c:','','documents','projects','test','test.py']] assert sourcecode.get_same_name_files(files_path_list ,'test.py') == same_name_files def test_shortest_path(): if sys.platform.startswith('linux'): files_path_list =[['','','documents','test','test.py'], ['','','documents','projects','test','test.py']] shortest_path = os.path.join(*['','','documents','test','test.py']) else: files_path_list =[['c:','','documents','test','test.py'], ['c:','','documents','projects','test','test.py']] shortest_path = os.path.join(*['c:','','documents','test','test.py']) assert sourcecode.shortest_path(files_path_list) == shortest_path def test_disambiguate_fname(): files_path_list = [] if sys.platform.startswith('linux'): fname0 = os.path.join(*['','','documents','test','test.py']) files_path_list.append(fname0) fname1 = os.path.join(*['','','documents','projects','test','test.py']) files_path_list.append(fname1) else: fname0 = os.path.join(*['c:','','documents','test','test.py']) files_path_list.append(fname0) fname1 = os.path.join(*['c:','','documents','projects','test','test.py']) files_path_list.append(fname1) title0 = 'test.py - ' + os.path.join(*['test']) title1 = 'test.py - ' + os.path.join(*['projects','test']) assert sourcecode.disambiguate_fname(files_path_list, fname0) == title0 assert sourcecode.disambiguate_fname(files_path_list, fname1) == title1 if __name__ == '__main__': pytest.main() spyder-3.2.6/spyder/utils/tests/test_misc.py0000664000175000017500000000217613156676663022027 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for misc.py """ # Standard library imports import os # Test library imports import pytest # Local imports from spyder.utils.misc import get_common_path def test_get_common_path(): """Test getting the common path.""" if os.name == 'nt': assert get_common_path([ 'D:\\Python\\spyder-v21\\spyder\\widgets', 'D:\\Python\\spyder\\spyder\\utils', 'D:\\Python\\spyder\\spyder\\widgets', 'D:\\Python\\spyder-v21\\spyder\\utils', ]) == 'D:\\Python' else: assert get_common_path([ '/Python/spyder-v21/spyder.widgets', '/Python/spyder/spyder.utils', '/Python/spyder/spyder.widgets', '/Python/spyder-v21/spyder.utils', ]) == '/Python' if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/utils/tests/test_dochelpers.py0000664000175000017500000000751213211142273023174 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for dochelpers.py """ # Standard library imports import os import sys # Test library imports import pytest # Local imports from spyder.utils.dochelpers import getargtxt, getdoc, getobj, isdefined from spyder.py3compat import PY2 class Test(object): def method(self, x, y=2): pass @pytest.mark.skipif(not 'Continuum' in sys.version or not PY2, reason="It fails when not run in Anaconda and in " "Python 3") def test_dochelpers(): """Test dochelpers.""" assert not getargtxt(Test.__init__) if PY2: assert getargtxt(Test.method) == ['x, ', 'y=2'] assert getdoc(sorted) == {'note': 'Function of __builtin__ module', 'argspec': u'(iterable, cmp=None, key=None, ' 'reverse=False)', 'docstring': u'sorted(iterable, cmp=None, ' 'key=None, reverse=False) --> ' 'new sorted list', 'name': 'sorted'} assert getargtxt(sorted) == ['iterable, ', ' cmp=None, ', ' key=None, ', ' reverse=False'] else: assert not getargtxt(Test.method) if os.name == 'nt': assert getdoc(sorted) == {'note': 'Function of builtins module', 'argspec': '(...)', 'docstring': 'Return a new list ' 'containing ' 'all items from the ' 'iterable in ascending ' 'order.\n\nA custom ' 'key function can be ' 'supplied to customise the ' 'sort order, and ' 'the\nreverse flag can be ' 'set to request the result ' 'in descending order.', 'name': 'sorted'} else: assert getdoc(sorted) == {'note': 'Function of builtins module', 'argspec': '(...)', 'docstring': 'Return a new list ' 'containing ' 'all items from the ' 'iterable in ascending ' 'order.\n\nA custom ' 'key function can be ' 'supplied to customize the ' 'sort order, and ' 'the\nreverse flag can be ' 'set to request the result ' 'in descending order.', 'name': 'sorted'} assert not getargtxt(sorted) assert isdefined('numpy.take', force_import=True) assert isdefined('__import__') assert not isdefined('.keys', force_import=True) assert getobj('globals') == 'globals' assert not getobj('globals().keys') assert getobj('+scipy.signal.') == 'scipy.signal' assert getobj('4.') == '4' if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/utils/tests/test_programs.py0000664000175000017500000000734413224121062022676 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License """Tests for programs.py""" import os from flaky import flaky import pytest from spyder.utils.programs import (run_python_script_in_terminal, is_python_interpreter, is_python_interpreter_valid_name, find_program, shell_split, check_version, is_module_installed) if os.name == 'nt': python_dir = os.environ['PYTHON'] if os.environ.get('CI', None) else '' VALID_INTERPRETER = os.path.join(python_dir, 'python.exe') INVALID_INTERPRETER = os.path.join(python_dir, 'Scripts', 'ipython.exe') else: home_dir = os.environ['HOME'] VALID_INTERPRETER = os.path.join(home_dir, 'miniconda', 'bin', 'python') INVALID_INTERPRETER = os.path.join(home_dir, 'miniconda', 'bin', 'ipython') @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt' or os.environ.get('CI', None) is None, reason='gets stuck on Windows and fails sometimes locally') # FIXME def test_run_python_script_in_terminal(tmpdir, qtbot): scriptpath = tmpdir.join('write-done.py') outfilepath = tmpdir.join('out.txt') script = ("with open('out.txt', 'w') as f:\n" " f.write('done')\n") scriptpath.write(script) run_python_script_in_terminal(scriptpath.strpath, tmpdir.strpath, '', False, False, '') qtbot.wait(1000) # wait for script to finish res = outfilepath.read() assert res == 'done' @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt' or os.environ.get('CI', None) is None, reason='gets stuck on Windows and fails sometimes locally') # FIXME def test_run_python_script_in_terminal_with_wdir_empty(tmpdir, qtbot): scriptpath = tmpdir.join('write-done.py') outfilepath = tmpdir.join('out.txt') script = ("with open('{}', 'w') as f:\n" " f.write('done')\n").format(outfilepath.strpath) scriptpath.write(script) run_python_script_in_terminal(scriptpath.strpath, '', '', False, False, '') qtbot.wait(1000) # wait for script to finish res = outfilepath.read() assert res == 'done' @pytest.mark.skipif(os.environ.get('CI', None) is None, reason='It only runs in CI services.') def test_is_valid_interpreter(): assert is_python_interpreter(VALID_INTERPRETER) @pytest.mark.skipif(os.environ.get('CI', None) is None, reason='It only runs in CI services.') def test_is_invalid_interpreter(): assert not is_python_interpreter(INVALID_INTERPRETER) def test_is_valid_interpreter_name(): names = ['python', 'pythonw', 'python2.7', 'python3.5', 'python.exe', 'pythonw.exe'] assert all([is_python_interpreter_valid_name(n) for n in names]) def test_find_program(): """Test if can find the program.""" assert find_program('git') def test_shell_split(): """Test if the text can be split using shell-like sintax.""" assert shell_split('-q -o -a') == ['-q', '-o', '-a'] assert shell_split('-q "d:\\Python de xxxx\\t.txt" -o -a') == \ ['-q', 'd:\\Python de xxxx\\t.txt', '-o', '-a'] def test_check_version(): """Test the compare function for versions.""" assert check_version('0.9.4-1', '0.9.4', '>=') assert check_version('3.0.0rc1', '3.0.0', '<') assert check_version('1.0', '1.0b2', '>') def test_is_module_installed(): """Test if a module with the proper version is installed""" assert is_module_installed('qtconsole', '>=4.0') assert not is_module_installed('IPython', '>=1.0;<3.0') assert is_module_installed('jedi', '>=0.7.0') if __name__ == '__main__': pytest.main() spyder-3.2.6/spyder/utils/tests/Big5.txt0000664000175000017500000000003313156676663021000 0ustar carloscarlos00000000000000?O@?bbig5??ܨҤ spyder-3.2.6/spyder/utils/tests/test_stringmatching.py0000664000175000017500000003064313156676663024115 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for stringmatching.py """ # Standard library imports import os # Test library imports import pytest # Local imports from spyder.utils.stringmatching import get_search_scores TEST_FILE = os.path.join(os.path.dirname(__file__), 'data/example.py') def test_stringmatching_full(): """Test stringmatching full results.""" template = '{0}' names = ['close pane', 'debug continue', 'debug exit', 'debug step into', 'debug step over', 'debug step return', 'fullscreen mode', 'layout preferences', 'lock unlock panes', 'maximize pane', 'preferences', 'quit', 'restart', 'save current layout', 'switch to breakpoints', 'switch to console', 'switch to editor', 'switch to explorer', 'switch to find_in_files', 'switch to historylog', 'switch to help', 'switch to ipython_console', 'switch to onlinehelp', 'switch to outline_explorer', 'switch to project_explorer', 'switch to variable_explorer', 'use next layout', 'use previous layout', 'clear line', 'clear shell', 'inspect current object', 'blockcomment', 'breakpoint', 'close all', 'code completion', 'conditional breakpoint', 'configure', 'copy', 'copy line', 'cut', 'debug', 'debug with winpdb', 'delete', 'delete line', 'duplicate line', 'end of document', 'end of line', 'file list management', 'find next', 'find previous', 'find text', 'go to definition', 'go to line', 'go to next file', 'go to previous file', 'inspect current object', 'kill next word', 'kill previous word', 'kill to line end', 'kill to line start', 'last edit location', 'move line down', 'move line up', 'new file', 'next char', 'next cursor position', 'next line', 'next word', 'open file', 'paste', 'previous char', 'previous cursor position', 'previous line', 'previous word', 'print', 're-run last script', 'redo', 'replace text', 'rotate kill ring', 'run', 'run selection', 'save all', 'save as', 'save file', 'select all', 'show/hide outline', 'show/hide project explorer', 'start of document', 'start of line', 'toggle comment', 'unblockcomment', 'undo', 'yank', 'run profiler', 'run analysis'] full_results = get_search_scores('lay', names, template=template, ) assert full_results == [('close pane', 'close pane', -1), ('debug continue', 'debug continue', -1), ('debug exit', 'debug exit', -1), ('debug step into', 'debug step into', -1), ('debug step over', 'debug step over', -1), ('debug step return', 'debug step return', -1), ('fullscreen mode', 'fullscreen mode', -1), ('layout preferences', 'layout preferences', 400100), ('lock unlock panes', 'lock unlock panes', -1), ('maximize pane', 'maximize pane', -1), ('preferences', 'preferences', -1), ('quit', 'quit', -1), ('restart', 'restart', -1), ('save current layout', 'save current layout', 400113), ('switch to breakpoints', 'switch to breakpoints', -1), ('switch to console', 'switch to console', -1), ('switch to editor', 'switch to editor', -1), ('switch to explorer', 'switch to explorer', -1), ('switch to find_in_files', 'switch to find_in_files', -1), ('switch to historylog', 'switch to historylog', -1), ('switch to help', 'switch to help', -1), ('switch to ipython_console', 'switch to ipython_console', -1), ('switch to onlinehelp', 'switch to onlinehelp', -1), ('switch to outline_explorer', 'switch to outline_explorer', -1), ('switch to project_explorer', 'switch to project_explorer', -1), ('switch to variable_explorer', 'switch to variable_explorer', -1), ('use next layout', 'use next layout', 400109), ('use previous layout', 'use previous layout', 400113), ('clear line', 'clear line', -1), ('clear shell', 'clear shell', -1), ('inspect current object', 'inspect current object', -1), ('blockcomment', 'blockcomment', -1), ('breakpoint', 'breakpoint', -1), ('close all', 'close all', -1), ('code completion', 'code completion', -1), ('conditional breakpoint', 'conditional breakpoint', -1), ('configure', 'configure', -1), ('copy', 'copy', -1), ('copy line', 'copy line', -1), ('cut', 'cut', -1), ('debug', 'debug', -1), ('debug with winpdb', 'debug with winpdb', -1), ('delete', 'delete', -1), ('delete line', 'delete line', -1), ('duplicate line', 'duplicate line', -1), ('end of document', 'end of document', -1), ('end of line', 'end of line', -1), ('file list management', 'file list management', -1), ('find next', 'find next', -1), ('find previous', 'find previous', -1), ('find text', 'find text', -1), ('go to definition', 'go to definition', -1), ('go to line', 'go to line', -1), ('go to next file', 'go to next file', -1), ('go to previous file', 'go to previous file', -1), ('inspect current object', 'inspect current object', -1), ('kill next word', 'kill next word', -1), ('kill previous word', 'kill previous word', -1), ('kill to line end', 'kill to line end', -1), ('kill to line start', 'kill to line start', -1), ('last edit location', 'last edit location', -1), ('move line down', 'move line down', -1), ('move line up', 'move line up', -1), ('new file', 'new file', -1), ('next char', 'next char', -1), ('next cursor position', 'next cursor position', -1), ('next line', 'next line', -1), ('next word', 'next word', -1), ('open file', 'open file', -1), ('paste', 'paste', -1), ('previous char', 'previous char', -1), ('previous cursor position', 'previous cursor position', -1), ('previous line', 'previous line', -1), ('previous word', 'previous word', -1), ('print', 'print', -1), ('re-run last script', 're-run last script', -1), ('redo', 'redo', -1), ('replace text', 'replace text', -1), ('rotate kill ring', 'rotate kill ring', -1), ('run', 'run', -1), ('run selection', 'run selection', -1), ('save all', 'save all', -1), ('save as', 'save as', -1), ('save file', 'save file', -1), ('select all', 'select all', -1), ('show/hide outline', 'show/hide outline', -1), ('show/hide project explorer', 'show/hide project explorer', -1), ('start of document', 'start of document', -1), ('start of line', 'start of line', -1), ('toggle comment', 'toggle comment', -1), ('unblockcomment', 'unblockcomment', -1), ('undo', 'undo', -1), ('yank', 'yank', -1), ('run profiler', 'run profiler', -1), ('run analysis', 'run analysis', -1)] def test_stringmatching_order_filter(): """Test stringmatching ordered and filtered.""" template = '{0}' names = ['close pane', 'debug continue', 'debug exit', 'debug step into', 'debug step over', 'debug step return', 'fullscreen mode', 'layout preferences', 'lock unlock panes', 'maximize pane', 'preferences', 'quit', 'restart', 'save current layout', 'switch to breakpoints', 'switch to console', 'switch to editor', 'switch to explorer', 'switch to find_in_files', 'switch to historylog', 'switch to help', 'switch to ipython_console', 'switch to onlinehelp', 'switch to outline_explorer', 'switch to project_explorer', 'switch to variable_explorer', 'use next layout', 'use previous layout', 'clear line', 'clear shell', 'inspect current object', 'blockcomment', 'breakpoint', 'close all', 'code completion', 'conditional breakpoint', 'configure', 'copy', 'copy line', 'cut', 'debug', 'debug with winpdb', 'delete', 'delete line', 'duplicate line', 'end of document', 'end of line', 'file list management', 'find next', 'find previous', 'find text', 'go to definition', 'go to line', 'go to next file', 'go to previous file', 'inspect current object', 'kill next word', 'kill previous word', 'kill to line end', 'kill to line start', 'last edit location', 'move line down', 'move line up', 'new file', 'next char', 'next cursor position', 'next line', 'next word', 'open file', 'paste', 'previous char', 'previous cursor position', 'previous line', 'previous word', 'print', 're-run last script', 'redo', 'replace text', 'rotate kill ring', 'run', 'run selection', 'save all', 'save as', 'save file', 'select all', 'show/hide outline', 'show/hide project explorer', 'start of document', 'start of line', 'toggle comment', 'unblockcomment', 'undo', 'yank', 'run profiler', 'run analysis'] order_filter_results = get_search_scores('lay', names, template=template, valid_only=True, sort=True) assert order_filter_results == [('layout preferences', 'layout preferences', 400100), ('use next layout', 'use next layout', 400109), ('save current layout', 'save current layout', 400113), ('use previous layout', 'use previous layout', 400113)] if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/utils/tests/test_iofuncs.py0000664000175000017500000000660713211142273022516 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for iofuncs.py """ import io import os import pytest import numpy as np import spyder.utils.iofuncs as iofuncs LOCATION = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__))) @pytest.fixture def spydata_values(): """ Define spydata file ground truth values. The file test_export.spydata contains four variables to be loaded, this function declares those variables in a static way. """ A = 1 B = 'ham' C = np.eye(3) D = {'a':1} return {'A':A, 'B':B, 'C':C, 'D':D} @pytest.fixture def real_values(): """ Load a Numpy pickled file. The file numpy_data.npz contains six variables, each one represents the expected test values after a manual conversion of the same variables defined and evaluated in MATLAB. The manual type conversion was done over several variable types, such as: Matrices/Vectors, Scalar and Complex numbers, Structs, Strings and Cell Arrays. The set of variables was defined to allow and test the deep conversion of a compound type, i.e., a struct that contains other types that need to be converted, like other structs, matrices and Cell Arrays. """ path = os.path.join(LOCATION, 'numpy_data.npz') file_s = np.load(path) A = file_s['A'].item() B = file_s['B'] C = file_s['C'] D = file_s['D'].item() E = file_s['E'] return {'A':A, 'B':B, 'C':C, 'D':D, 'E':E} @pytest.mark.skipif(iofuncs.load_matlab is None, reason="SciPy required") def test_matlab_import(real_values): """ Test the automatic conversion and import of variables from MATLAB. This test loads a file stored in MATLAB, the variables defined are equivalent to the manually converted values done over Numpy. This test allows to evaluate the function which processes the conversion automa- tically. i.e., The automatic conversion results should be equal to the manual conversion of the variables. """ path = os.path.join(LOCATION, 'data.mat') inf, _ = iofuncs.load_matlab(path) valid = True for var in sorted(real_values.keys()): valid = valid and bool(np.mean(real_values[var] == inf[var])) assert valid def test_spydata_import(spydata_values): """ Test spydata handling and variable importing. This test loads all the variables contained inside a spydata tar container and compares them against their static values. """ path = os.path.join(LOCATION, 'test_export.spydata') data, error = iofuncs.load_dictionary(path) valid = True for var in sorted(spydata_values.keys()): valid = valid and bool(np.mean(spydata_values[var] == data[var])) assert valid @pytest.mark.skipif(iofuncs.load_matlab is None, reason="SciPy required") def test_matlabstruct(): """Test support for matlab stlye struct.""" a = iofuncs.MatlabStruct() a.b = 'spam' assert a["b"] == 'spam' a.c["d"] = 'eggs' assert a.c.d == 'eggs' assert a == {'c': {'d': 'eggs'}, 'b': 'spam'} a['d'] = [1, 2, 3] buf = io.BytesIO() iofuncs.save_matlab(a, buf) buf.seek(0) data, err = iofuncs.load_matlab(buf) assert data['b'] == 'spam' assert data['c'].d == 'eggs' assert data['d'].tolist() == [[1, 2, 3]] if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/utils/tests/test_get_words.py0000664000175000017500000001314413156676663023066 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License """Tests for programs.py.""" from os.path import dirname, abspath, splitext, join from spyder.utils.introspection.utils import get_words HERE = dirname(abspath(__file__)) TEST_DATA_PATH = join(HERE, 'data') # --- Fixtures # ----------------------------------------------------------------------------- def get_words_by_content(filename): """Test get_words from content in filename.""" f_in = join(TEST_DATA_PATH, filename) ext = splitext(f_in)[1] with open(f_in, 'r') as infile: content = infile.read() return get_words(content=content, extension=ext) def get_words_by_filename(filename): """Test get_words from filepath.""" filepath = join(TEST_DATA_PATH, filename) return get_words(filepath) # --- Tests # ----------------------------------------------------------------------------- def test_get_words_html(): """Test for get word from html file syntax.""" expected_words = ['DOCTYPE', 'Hello', 'Jamie', 'World', 'body', 'charset', 'en', 'h', 'head', 'here', 'html', 'lang', 'meta', 'p', 'title', 'utf', 'was'] assert sorted(expected_words) == sorted(get_words_by_filename("example.html")) assert sorted(expected_words) == sorted(get_words_by_content("example.html")) def test_get_words_r(): """Test for get word from R file syntax.""" expected_words = ['Hello', 'function', 'hello', 'name', 's', 'sprintf'] assert sorted(expected_words) == sorted(get_words_by_filename("example.R")) assert sorted(expected_words) == sorted(get_words_by_content("example.R")) def test_get_words_css(): """Test for get word from css file syntax.""" expected_words = ['DeepSkyBlue', 'nombre-valido', 'text', 'css', 'h', 'color', 'Hello', 'world', 'type', 'style'] assert sorted(expected_words) == sorted(get_words_by_filename("example.css")) assert sorted(expected_words) == sorted(get_words_by_content("example.css")) def test_get_words_python(): """Test for get word from html file syntax.""" expected_words = ['Apply', 'Browser', 'Count', 'Garcia', 'Juan', 'Make', 'Manuel', 'N', 'N_', 'Qt', 'QtWebKit', 'R', 'Set', 'Simple', 'This', 'Very', 'VerySimpleWebBrowser', 'Web', 'Z', 'Z_', '__file__', 'a', 'and', 'argwhere', 'array', 'as', 'author', 'birth', 'borders', 'com', 'def', 'for', 'gmail', 'home', 'i', 'implemented', 'import', 'in', 'int', 'is', 'iterate_', 'jmg', 'neighbours', 'new', 'np', 'null', 'numpy', 'over', 'print', 'range', 'ravel', 'return', 'rules', 'shape', 'stay', 'sure', 'survive', 'utn', 'values', 'zeros'] assert sorted(expected_words) == sorted(get_words_by_filename("example.py")) assert sorted(expected_words) == sorted(get_words_by_content("example.py")) def test_get_words_java(): """Test for get word from java file syntax.""" expected_words = ['Compilation', 'Execution', 'Hello', 'HelloWorld', 'Prints', 'String', 'System', 'World', 'args', 'class', 'java', 'javac', 'main', 'out', 'println', 'public', 'static', 'terminal', 'the', 'to', 'void', 'window'] assert sorted(expected_words) == sorted(get_words_by_filename("example.java")) assert sorted(expected_words) == sorted(get_words_by_content("example.java")) def test_get_words_cplusplus(): """Test for get word from C++ file syntax.""" expected_words = ['Consider', 'Create', 'Implement', 'Obj', 'ObjContainer', 'Postfix', 'Prefix', 'Return', 'SmartPointer', 'Static', 'Zero', 'a', 'above', 'access', 'actual', 'add', 'an', 'back', 'bool', 'call', 'class', 'const', 'container', 'cout', 'definitions', 'do', 'end', 'endl', 'f', 'false', 'for', 'friend', 'g', 'i', 'if', 'implement', 'include', 'index', 'indicates', 'int', 'iostream', 'iterator', 'j', 'list', 'main', 'member', 'method', 'namespace', 'o', 'obj', 'objc', 'oc', 'of', 'operator', 'overload', 'pointer', 'public', 'push', 'return', 's', 'size', 'smart', 'sp', 'standard', 'static', 'std', 'sz', 'the', 'to', 'true', 'using', 'value', 'vector', 'version', 'void', 'while'] assert sorted(expected_words) == sorted(get_words_by_filename("example.cpp")) assert sorted(expected_words) == sorted(get_words_by_content("example.cpp")) def test_get_words_markdown(): """Test for get word from markdown file syntax.""" expected_words = ['A', 'Blockquote', 'Bold', 'Heading', 'Horizontal', 'Image', 'Inline', 'Italic', 'Link', 'List', 'One', 'Rule', 'Three', 'Two', 'a', 'after', 'b', 'backticks', 'blank', 'block', 'code', 'com', 'http', 'indent', 'jpg', 'line', 'or', 'org', 'paragraph', 'png', 'print', 'spaces', 'url', 'with'] assert sorted(expected_words) == sorted(get_words_by_filename("example.md")) assert sorted(expected_words) == sorted(get_words_by_content("example.md")) def test_get_words_c(): """Test for get word from C file syntax.""" expected_words = ['f', 'float', 'foo', 'h', 'i', 'include', 'int', 'main', 'n', 'printf', 'pvar', 'return', 'stdio', 'struct', 'var', 'x', 'y'] assert sorted(expected_words) == sorted(get_words_by_filename("example.c")) assert sorted(expected_words) == sorted(get_words_by_content("example.c")) spyder-3.2.6/spyder/utils/tests/KOI8-R.txt0000664000175000017500000000004613156676663021127 0ustar carloscarlos00000000000000 KOI8-R spyder-3.2.6/spyder/utils/tests/test_environ.py0000664000175000017500000000172713156676663022555 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for environ.py """ # Standard library imports import os # Test library imports import pytest # Third party imports from qtpy.QtCore import QTimer # Local imports from spyder.utils.test import close_message_box @pytest.fixture def setup_environ(qtbot): "Setup the Environment variables Dialog taking into account the os." if os.name == 'nt': from spyder.utils.environ import WinUserEnvDialog dialog = WinUserEnvDialog() else: from spyder.utils.environ import EnvDialog dialog = EnvDialog() qtbot.addWidget(dialog) return dialog def test_environ(qtbot): """Test the environment variables dialog.""" QTimer.singleShot(1000, lambda: close_message_box(qtbot)) dialog = setup_environ(qtbot) dialog.show() assert dialog if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/utils/tests/test_codeanalysis.py0000664000175000017500000000156713211142273023526 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for codeanalysis.py """ # Standard library imports import os # Test library imports import pytest # Local imports from spyder.utils.codeanalysis import (check_with_pep8, check_with_pyflakes, find_tasks) from spyder.py3compat import PY2 TEST_FILE = os.path.join(os.path.dirname(__file__), 'data/example.py') def test_codeanalysis(): """Test codeanalysis with pyflakes and pep8.""" code = open(TEST_FILE).read() check_results = check_with_pyflakes(code, TEST_FILE) + \ check_with_pep8(code, TEST_FILE) + find_tasks(code) if PY2: num_results = 87 else: num_results = 88 assert len(check_results) == num_results if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/utils/tests/data/0000775000175000017500000000000013225025007020337 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/utils/tests/data/example.css0000664000175000017500000000015313156676663022532 0ustar carloscarlos00000000000000

    Hello, world! nombre-valido

    spyder-3.2.6/spyder/utils/tests/data/example.R0000664000175000017500000000010013156676663022133 0ustar carloscarlos00000000000000hello <- function( name ) { sprintf( "Hello, %s", name ); } spyder-3.2.6/spyder/utils/tests/data/example.java0000664000175000017500000000064213156676663022666 0ustar carloscarlos00000000000000/****************************************************************************** * Compilation: javac HelloWorld.java * Execution: java HelloWorld ******************************************************************************/ public class HelloWorld { public static void main(String[] args) { // Prints "Hello, World" to the terminal window. System.out.println("Hello, World"); } } spyder-3.2.6/spyder/utils/tests/data/example.c0000664000175000017500000000045613156676663022172 0ustar carloscarlos00000000000000#include int main() { struct foo { int x; float y; }; struct foo var; struct foo* pvar; pvar = &var; var.x = 5; (&var)->y = 14.3; printf("%i - %.02f\n", var.x, (&var)->y); pvar->x = 6; pvar->y = 22.4; printf("%i - %.02f\n", pvar->x, pvar->y); return 0; } spyder-3.2.6/spyder/utils/tests/data/example.md0000664000175000017500000000072213156676663022344 0ustar carloscarlos00000000000000*Italic* **Bold** # Heading 1 ========= ## Heading 2 --------- [Link](http://a.com) [Link][1] [1]: http://b.org ![Image](http://url/a.png) ![Image][1] [1]: http://url/b.jpg > Blockquote A paragraph. A paragraph after 1 blank line. * List * List * List - List - List - List 1. One 2. Two 3. Three 1) One 2) Two 3) Three --- Horizontal Rule *** Horizontal Rule `Inline code` with backticks ``` # code block print '3 backticks or' print 'indent 4 spaces' ``` spyder-3.2.6/spyder/utils/tests/data/example.cpp0000664000175000017500000000263013156676663022526 0ustar carloscarlos00000000000000#include #include using namespace std; // Consider an actual class. class Obj { static int i, j; public: void f() const { cout << i++ << endl; } void g() const { cout << j++ << endl; } }; // Static member definitions: int Obj::i = 10; int Obj::j = 12; // Implement a container for the above class class ObjContainer { vector a; public: void add(Obj* obj) { a.push_back(obj); // call vector's standard method. } friend class SmartPointer; }; // implement smart pointer to access member of Obj class. class SmartPointer { ObjContainer oc; int index; public: SmartPointer(ObjContainer& objc) { oc = objc; index = 0; } // Return value indicates end of list: bool operator++() // Prefix version { if(index >= oc.a.size()) return false; if(oc.a[++index] == 0) return false; return true; } bool operator++(int) // Postfix version { return operator++(); } // overload operator-> Obj* operator->() const { if(!oc.a[index]) { cout << "Zero value"; return (Obj*)0; } return oc.a[index]; } }; int main() { const int sz = 10; Obj o[sz]; ObjContainer oc; for(int i = 0; i < sz; i++) { oc.add(&o[i]); } SmartPointer sp(oc); // Create an iterator do { sp->f(); // smart pointer call sp->g(); } while(sp++); return 0; } spyder-3.2.6/spyder/utils/tests/data/example.html0000664000175000017500000000035313156676663022710 0ustar carloscarlos00000000000000 Hello World

    Hello World

    Jamie was here.

    spyder-3.2.6/spyder/utils/tests/ascii.txt0000664000175000017500000000005013156676663021301 0ustar carloscarlos00000000000000This is a sample file encoding in ascii spyder-3.2.6/spyder/utils/tests/test_syntaxhighlighters.py0000664000175000017500000000574613224740762025016 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License """Tests for syntaxhighlighters.py""" import pytest from qtpy.QtWidgets import QApplication from qtpy.QtGui import QTextDocument from spyder.utils.syntaxhighlighters import HtmlSH, PythonSH, MarkdownSH def compare_formats(actualFormats, expectedFormats, sh): assert len(actualFormats) == len(expectedFormats) for actual, expected in zip(actualFormats, expectedFormats): assert actual.start == expected[0] assert actual.length == expected[1] # compare formats by looking at foreground colours only assert (actual.format.foreground().color().name() == sh.formats[expected[2]].foreground().color().name()) def test_HtmlSH_basic(): txt = '

    Foo bar.

    ' doc = QTextDocument(txt) sh = HtmlSH(doc, color_scheme='Spyder') sh.rehighlightBlock(doc.firstBlock()) # Expected result as list of tuples (begin, length, format) res = [(0, 2, 'builtin'), # || (22, 4, 'normal'), # |Foo | (26, 14, 'comment'), # || (40, 5, 'normal'), # | bar.| (45, 4, 'builtin')] # |

    | compare_formats(doc.firstBlock().layout().additionalFormats(), res, sh) def test_HtmlSH_unclosed_commend(): txt = '-->' doc = QTextDocument(txt) sh = HtmlSH(doc, color_scheme='Spyder') sh.rehighlightBlock(doc.firstBlock()) res = [(0, 3, 'normal')] compare_formats(doc.firstBlock().layout().additionalFormats(), res, sh) def test_Markdown_basic(): txt = "Some __random__ **text** with ~~different~~ [styles](link_url)" doc = QTextDocument(txt) sh = MarkdownSH(doc, color_scheme='Spyder') sh.rehighlightBlock(doc.firstBlock()) res = [(0, 5, 'normal'), # |Some| (5, 10, 'italic'), # |__random__| (15, 1, 'normal'), # | | (16, 8, 'strong'), # |**text**| (24, 6, 'normal'), # |with| (30, 13, 'italic'), # |~~diferents~~| (43, 1, 'normal'), # | | (44, 8, 'string'), # |[styles]| (52, 1, 'normal'), # |(| (53, 8, 'string'), # |(link_url)| (61, 1, 'normal'), # || ] compare_formats(doc.firstBlock().layout().additionalFormats(), res, sh) @pytest.mark.parametrize('line', ['# --- First variant', '#------ 2nd variant', '### 3rd variant']) def test_python_outline_explorer_comment(line): assert PythonSH.OECOMMENT.match(line) @pytest.mark.parametrize('line', ['#---', '#--------', '#--- ', '# -------']) def test_python_not_an_outline_explorer_comment(line): assert not PythonSH.OECOMMENT.match(line) if __name__ == '__main__': pytest.main() spyder-3.2.6/spyder/utils/tests/test_encoding.py0000664000175000017500000000176313156676663022663 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License """Tests for encodings.py""" import pytest import os from spyder.utils.encoding import is_text_file, get_coding __location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__))) def test_is_text_file(tmpdir): p = tmpdir.mkdir("sub").join("random_text.txt") p.write("Some random text") assert is_text_file(str(p)) == True @pytest.mark.parametrize( 'expected_encoding, text_file', [('utf-8', 'utf-8.txt'), ('windows-1252', 'windows-1252.txt'), ('ascii', 'ascii.txt'), ('Big5', 'Big5.txt'), ('KOI8-R', 'KOI8-R.txt'), ]) def test_files_encodings(expected_encoding, text_file): with open(os.path.join(__location__, text_file), 'rb') as f: text = f.read() assert get_coding(text).lower() == expected_encoding.lower() if __name__ == '__main__': pytest.main() spyder-3.2.6/spyder/utils/tests/test_bsdsocket.py0000664000175000017500000000300313156676663023043 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for bsdsocket.py """ # Standard library imports import os import socket # Test library imports import pytest # Local imports from spyder.utils.bsdsocket import write_packet, read_packet @pytest.mark.skipif(os.name == 'nt', reason="A non-blocking socket operation cannot " "be completed in Windows immediately") def test_bsdsockets(): """Test write-read packet methods.""" # socket read/write testing - client and server in one thread # (techtonik): the stuff below is placed into public domain address = ("127.0.0.1", 9999) server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.setblocking(0) server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind( address ) server.listen(2) client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect( address ) client.send("data to be catched".encode('utf-8')) # accepted server socket is the one we can read from # note that it is different from server socket accsock, addr = server.accept() assert accsock.recv(4096) == b'data to be catched' # Testing BSD socket write_packet/read_packet write_packet(client, "a tiny piece of data") read = read_packet(accsock) assert read == "a tiny piece of data" client.close() server.close() if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/utils/tests/__init__.py0000664000175000017500000000050213156676663021563 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Copyright (c) Spyder Project Contributors # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Tests.""" spyder-3.2.6/spyder/utils/tests/utf-8.txt0000664000175000017500000000010113156676663021151 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- This is a sample file with utf-8 header spyder-3.2.6/spyder/utils/misc.py0000664000175000017500000002342513224121062017574 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Miscellaneous utilities""" import functools import os import os.path as osp import sys import stat from spyder.py3compat import is_text_string, getcwd from spyder.config.base import get_home_dir, debug_print def __remove_pyc_pyo(fname): """Eventually remove .pyc and .pyo files associated to a Python script""" if osp.splitext(fname)[1] == '.py': for ending in ('c', 'o'): if osp.exists(fname+ending): os.remove(fname+ending) def rename_file(source, dest): """ Rename file from *source* to *dest* If file is a Python script, also rename .pyc and .pyo files if any """ os.rename(source, dest) __remove_pyc_pyo(source) def remove_file(fname): """ Remove file *fname* If file is a Python script, also rename .pyc and .pyo files if any """ os.remove(fname) __remove_pyc_pyo(fname) def move_file(source, dest): """ Move file from *source* to *dest* If file is a Python script, also rename .pyc and .pyo files if any """ import shutil shutil.copy(source, dest) remove_file(source) def onerror(function, path, excinfo): """Error handler for `shutil.rmtree`. If the error is due to an access error (read-only file), it attempts to add write permission and then retries. If the error is for another reason, it re-raises the error. Usage: `shutil.rmtree(path, onerror=onerror)""" if not os.access(path, os.W_OK): # Is the error an access error? os.chmod(path, stat.S_IWUSR) function(path) else: raise def select_port(default_port=20128): """Find and return a non used port""" import socket while True: try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP) # sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind( ("127.0.0.1", default_port) ) except socket.error as _msg: # analysis:ignore default_port += 1 else: break finally: sock.close() sock = None return default_port def count_lines(path, extensions=None, excluded_dirnames=None): """Return number of source code lines for all filenames in subdirectories of *path* with names ending with *extensions* Directory names *excluded_dirnames* will be ignored""" if extensions is None: extensions = ['.py', '.pyw', '.ipy', '.enaml', '.c', '.h', '.cpp', '.hpp', '.inc', '.', '.hh', '.hxx', '.cc', '.cxx', '.cl', '.f', '.for', '.f77', '.f90', '.f95', '.f2k'] if excluded_dirnames is None: excluded_dirnames = ['build', 'dist', '.hg', '.svn'] def get_filelines(path): dfiles, dlines = 0, 0 if osp.splitext(path)[1] in extensions: dfiles = 1 with open(path, 'rb') as textfile: dlines = len(textfile.read().strip().splitlines()) return dfiles, dlines lines = 0 files = 0 if osp.isdir(path): for dirpath, dirnames, filenames in os.walk(path): for d in dirnames[:]: if d in excluded_dirnames: dirnames.remove(d) if excluded_dirnames is None or \ osp.dirname(dirpath) not in excluded_dirnames: for fname in filenames: dfiles, dlines = get_filelines(osp.join(dirpath, fname)) files += dfiles lines += dlines else: dfiles, dlines = get_filelines(path) files += dfiles lines += dlines return files, lines def fix_reference_name(name, blacklist=None): """Return a syntax-valid Python reference name from an arbitrary name""" import re name = "".join(re.split(r'[^0-9a-zA-Z_]', name)) while name and not re.match(r'([a-zA-Z]+[0-9a-zA-Z_]*)$', name): if not re.match(r'[a-zA-Z]', name[0]): name = name[1:] continue name = str(name) if not name: name = "data" if blacklist is not None and name in blacklist: get_new_name = lambda index: name+('%03d' % index) index = 0 while get_new_name(index) in blacklist: index += 1 name = get_new_name(index) return name def remove_backslashes(path): """Remove backslashes in *path* For Windows platforms only. Returns the path unchanged on other platforms. This is especially useful when formatting path strings on Windows platforms for which folder paths may contain backslashes and provoke unicode decoding errors in Python 3 (or in Python 2 when future 'unicode_literals' symbol has been imported).""" if os.name == 'nt': # Removing trailing single backslash if path.endswith('\\') and not path.endswith('\\\\'): path = path[:-1] # Replacing backslashes by slashes path = path.replace('\\', '/') path = path.replace('/\'', '\\\'') return path def get_error_match(text): """Return error match""" import re return re.match(r' File "(.*)", line (\d*)', text) def get_python_executable(): """Return path to Python executable""" executable = sys.executable.replace("pythonw.exe", "python.exe") if executable.endswith("spyder.exe"): # py2exe distribution executable = "python.exe" return executable def monkeypatch_method(cls, patch_name): # This function's code was inspired from the following thread: # "[Python-Dev] Monkeypatching idioms -- elegant or ugly?" # by Robert Brewer # (Tue Jan 15 19:13:25 CET 2008) """ Add the decorated method to the given class; replace as needed. If the named method already exists on the given class, it will be replaced, and a reference to the old method is created as cls._old. If the "_old__" attribute already exists, KeyError is raised. """ def decorator(func): fname = func.__name__ old_func = getattr(cls, fname, None) if old_func is not None: # Add the old func to a list of old funcs. old_ref = "_old_%s_%s" % (patch_name, fname) old_attr = getattr(cls, old_ref, None) if old_attr is None: setattr(cls, old_ref, old_func) else: raise KeyError("%s.%s already exists." % (cls.__name__, old_ref)) setattr(cls, fname, func) return func return decorator def is_python_script(fname): """Is it a valid Python script?""" return osp.isfile(fname) and fname.endswith(('.py', '.pyw', '.ipy')) def abspardir(path): """Return absolute parent dir""" return osp.abspath(osp.join(path, os.pardir)) def get_common_path(pathlist): """Return common path for all paths in pathlist""" common = osp.normpath(osp.commonprefix(pathlist)) if len(common) > 1: if not osp.isdir(common): return abspardir(common) else: for path in pathlist: if not osp.isdir(osp.join(common, path[len(common)+1:])): # `common` is not the real common prefix return abspardir(common) else: return osp.abspath(common) def add_pathlist_to_PYTHONPATH(env, pathlist, drop_env=False, ipyconsole=False): # PyQt API 1/2 compatibility-related tests: assert isinstance(env, list) assert all([is_text_string(path) for path in env]) pypath = "PYTHONPATH" pathstr = os.pathsep.join(pathlist) if os.environ.get(pypath) is not None and not drop_env: old_pypath = os.environ[pypath] if not ipyconsole: for index, var in enumerate(env[:]): if var.startswith(pypath+'='): env[index] = var.replace(pypath+'=', pypath+'='+pathstr+os.pathsep) env.append('OLD_PYTHONPATH='+old_pypath) else: pypath = {'PYTHONPATH': pathstr + os.pathsep + old_pypath, 'OLD_PYTHONPATH': old_pypath} return pypath else: if not ipyconsole: env.append(pypath+'='+pathstr) else: return {'PYTHONPATH': pathstr} def memoize(obj): """ Memoize objects to trade memory for execution speed Use a limited size cache to store the value, which takes into account The calling args and kwargs See https://wiki.python.org/moin/PythonDecoratorLibrary#Memoize """ cache = obj.cache = {} @functools.wraps(obj) def memoizer(*args, **kwargs): key = str(args) + str(kwargs) if key not in cache: cache[key] = obj(*args, **kwargs) # only keep the most recent 100 entries if len(cache) > 100: cache.popitem(last=False) return cache[key] return memoizer def getcwd_or_home(): """Safe version of getcwd that will fallback to home user dir. This will catch the error raised when the current working directory was removed for an external program. """ try: return getcwd() except OSError: debug_print("WARNING: Current working directory was deleted, " "falling back to home dirertory") return get_home_dir() spyder-3.2.6/spyder/utils/introspection/0000775000175000017500000000000013225025007021164 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/utils/introspection/module_completion.py0000664000175000017500000002265713156676663025317 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- """Module completion auxiliary functions""" #------------------------------------------------------------------------------ # # Most functions on this file were taken from the file core/completerlib, # which belongs to the IPython project (v0.13). They were added here because # a) IPython is not an Spyder runtime dependency, and b) we want to perfom # module completion not only on our Python console, but also on our source # code editor. # # Several of these functions were modified to make it work according to our # needs # # Distributed under the terms of the BSD License. # Copyright (C) 2010-2011 The IPython Development Team. # Copyright (C) Spyder Project Contributors # #------------------------------------------------------------------------------ import imp import inspect import os.path import pkgutil import re from time import time import sys from zipimport import zipimporter from spyder.config.base import get_conf_path, running_in_mac_app from spyder.py3compat import PY3 from pickleshare import PickleShareDB #----------------------------------------------------------------------------- # Globals and constants #----------------------------------------------------------------------------- # Path to the modules database MODULES_PATH = get_conf_path('db') # Time in seconds after which we give up if os.name == 'nt': TIMEOUT_GIVEUP = 30 else: TIMEOUT_GIVEUP = 20 # Py2app only uses .pyc files for the stdlib when optimize=0, # so we need to add it as another suffix here if running_in_mac_app(): suffixes = imp.get_suffixes() + [('.pyc', 'rb', '2')] else: suffixes = imp.get_suffixes() # Regular expression for the python import statement import_re = re.compile(r'(?P[a-zA-Z_][a-zA-Z0-9_]*?)' r'(?P[/\\]__init__)?' r'(?P%s)$' % r'|'.join(re.escape(s[0]) for s in suffixes)) # Modules database modules_db = PickleShareDB(MODULES_PATH) #----------------------------------------------------------------------------- # Utility functions #----------------------------------------------------------------------------- def module_list(path): """ Return the list containing the names of the modules available in the given folder. """ # sys.path has the cwd as an empty string, but isdir/listdir need it as '.' if path == '': path = '.' # A few local constants to be used in loops below pjoin = os.path.join if os.path.isdir(path): # Build a list of all files in the directory and all files # in its subdirectories. For performance reasons, do not # recurse more than one level into subdirectories. files = [] for root, dirs, nondirs in os.walk(path): subdir = root[len(path)+1:] if subdir: files.extend(pjoin(subdir, f) for f in nondirs) dirs[:] = [] # Do not recurse into additional subdirectories. else: files.extend(nondirs) else: try: files = list(zipimporter(path)._files.keys()) except: files = [] # Build a list of modules which match the import_re regex. modules = [] for f in files: m = import_re.match(f) if m: modules.append(m.group('name')) return list(set(modules)) def get_root_modules(paths): """ Returns list of names of all modules from PYTHONPATH folders. paths : list A list of additional paths that Spyder adds to PYTHONPATH. They are comming from our PYTHONPATH manager and from the currently selected project. """ modules = [] spy_modules = [] for path in paths: spy_modules += module_list(path) spy_modules = set(spy_modules) if '__init__' in spy_modules: spy_modules.remove('__init__') spy_modules = list(spy_modules) if 'rootmodules' in modules_db: return spy_modules + modules_db['rootmodules'] t = time() modules = list(sys.builtin_module_names) # TODO: Change this sys.path for console's interpreter sys.path for path in sys.path: modules += module_list(path) if time() - t > TIMEOUT_GIVEUP: print("Module list generation is taking too long, we give up.\n") # spyder: test-skip modules_db['rootmodules'] = [] return [] modules = set(modules) excluded_modules = ['__init__'] + spy_modules for mod in excluded_modules: if mod in modules: modules.remove(mod) modules = list(modules) modules_db['rootmodules'] = modules return spy_modules + modules def get_submodules(mod): """Get all submodules of a given module""" def catch_exceptions(module): pass try: m = __import__(mod) submodules = [mod] submods = pkgutil.walk_packages(m.__path__, m.__name__ + '.', catch_exceptions) for sm in submods: sm_name = sm[1] submodules.append(sm_name) except ImportError: return [] except: return [mod] return submodules def is_importable(module, attr, only_modules): if only_modules: return inspect.ismodule(getattr(module, attr)) else: return not(attr[:2] == '__' and attr[-2:] == '__') def try_import(mod, only_modules=False): try: m = __import__(mod) except: return [] mods = mod.split('.') for module in mods[1:]: m = getattr(m, module) m_is_init = hasattr(m, '__file__') and '__init__' in m.__file__ completions = [] if (not hasattr(m, '__file__')) or (not only_modules) or m_is_init: completions.extend([attr for attr in dir(m) if is_importable(m, attr, only_modules)]) completions.extend(getattr(m, '__all__', [])) if m_is_init: completions.extend(module_list(os.path.dirname(m.__file__))) completions = set(completions) if '__init__' in completions: completions.remove('__init__') return list(completions) def dot_completion(mod, paths): if len(mod) < 2: return [x for x in get_root_modules(paths) if x.startswith(mod[0])] completion_list = try_import('.'.join(mod[:-1]), True) completion_list = [x for x in completion_list if x.startswith(mod[-1])] completion_list = ['.'.join(mod[:-1] + [el]) for el in completion_list] return completion_list #----------------------------------------------------------------------------- # Main functions #----------------------------------------------------------------------------- def module_completion(line, paths=[]): """ Returns a list containing the completion possibilities for an import line. The line looks like this : 'import xml.d' 'from xml.dom import' """ words = line.split(' ') nwords = len(words) # from whatever -> 'import ' if nwords == 3 and words[0] == 'from': if words[2].startswith('i') or words[2] == '': return ['import '] else: return [] # 'import xy or import xy, ' if words[0] == 'import': if nwords == 2 and words[1] == '': return get_root_modules(paths) if ',' == words[-1][-1]: return [' '] mod = words[-1].split('.') return dot_completion(mod, paths) # 'from xy' if nwords < 3 and (words[0] == 'from'): if nwords == 1: return get_root_modules(paths) mod = words[1].split('.') return dot_completion(mod, paths) # 'from xyz import abc' if nwords >= 3 and words[0] == 'from': mod = words[1] completion_list = try_import(mod) if words[2] == 'import' and words[3] != '': if '(' in words[-1]: words = words[:-2] + words[-1].split('(') if ',' in words[-1]: words = words[:-2] + words[-1].split(',') return [x for x in completion_list if x.startswith(words[-1])] else: return completion_list return [] def reset(): """Clear root modules database""" if 'rootmodules' in modules_db: del modules_db['rootmodules'] def get_preferred_submodules(): """ Get all submodules of the main scientific modules and others of our interest """ if 'submodules' in modules_db: return modules_db['submodules'] mods = ['numpy', 'scipy', 'sympy', 'pandas', 'networkx', 'statsmodels', 'matplotlib', 'sklearn', 'skimage', 'mpmath', 'os', 'PIL', 'OpenGL', 'array', 'audioop', 'binascii', 'cPickle', 'cStringIO', 'cmath', 'collections', 'datetime', 'errno', 'exceptions', 'gc', 'imageop', 'imp', 'itertools', 'marshal', 'math', 'mmap', 'msvcrt', 'nt', 'operator', 'parser', 'rgbimg', 'signal', 'strop', 'sys', 'thread', 'time', 'wx', 'xxsubtype', 'zipimport', 'zlib', 'nose', 'PyQt4', 'PySide', 'os.path'] submodules = [] for m in mods: submods = get_submodules(m) submodules += submods modules_db['submodules'] = submodules return submodules spyder-3.2.6/spyder/utils/introspection/fallback_plugin.py0000664000175000017500000002564213156676663024713 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Introspection utilities used by Spyder """ from __future__ import print_function import imp import os import os.path as osp import re import time from pygments.token import Token from spyder.utils.debug import log_dt from spyder.utils import sourcecode, encoding from spyder.utils.introspection.manager import ( DEBUG_EDITOR, LOG_FILENAME, IntrospectionPlugin) from spyder.utils.introspection.utils import ( get_parent_until, memoize, find_lexer_for_filename, get_keywords) class FallbackPlugin(IntrospectionPlugin): """Basic Introspection Plugin for Spyder""" # ---- IntrospectionPlugin API -------------------------------------------- name = 'fallback' def get_completions(self, info): """Return a list of (completion, type) tuples Simple completion based on python-like identifiers and whitespace """ if not info['obj']: return items = [] obj = info['obj'] if info['context']: lexer = find_lexer_for_filename(info['filename']) # get a list of token matches for the current object tokens = lexer.get_tokens(info['source_code']) for (context, token) in tokens: token = token.strip() if (context in info['context'] and token.startswith(obj) and obj != token): items.append(token) # add in keywords if not in a string if context not in Token.Literal.String: try: keywords = get_keywords(lexer) items.extend(k for k in keywords if k.startswith(obj)) except Exception: pass else: tokens = set(re.findall(info['id_regex'], info['source_code'])) items = [item for item in tokens if item.startswith(obj) and len(item) > len(obj)] if '.' in obj: start = obj.rfind('.') + 1 else: start = 0 items = [i[start:len(obj)] + i[len(obj):].split('.')[0] for i in items] # get path completions # get last word back to a space or a quote character match = re.search('''[ "\']([\w\.\\\\/]+)\Z''', info['line']) if match: items += _complete_path(match.groups()[0]) return [(i, '') for i in sorted(items)] def get_definition(self, info): """ Find the definition for an object within a set of source code This is used to find the path of python-like modules (e.g. cython and enaml) for a goto definition """ if not info['is_python_like']: return token = info['obj'] lines = info['lines'] source_code = info['source_code'] filename = info['filename'] line_nr = None if token is None: return if '.' in token: token = token.split('.')[-1] line_nr = get_definition_with_regex(source_code, token, len(lines)) if line_nr is None: return line = info['line'] exts = python_like_exts() if not osp.splitext(filename)[-1] in exts: return filename, line_nr if line.startswith('import ') or line.startswith('from '): alt_path = osp.dirname(filename) source_file = python_like_mod_finder(line, alt_path=alt_path, stop_token=token) if (not source_file or not osp.splitext(source_file)[-1] in exts): line_nr = get_definition_with_regex(source_code, token, line_nr) return filename, line_nr mod_name = osp.basename(source_file).split('.')[0] if mod_name == token or mod_name == '__init__': return source_file, 1 else: with open(filename, 'rb') as fid: code = fid.read() code = encoding.decode(code)[0] line_nr = get_definition_with_regex(code, token) return filename, line_nr def get_info(self, info): """Get a formatted calltip and docstring from Fallback""" if info['docstring']: if info['filename']: filename = os.path.basename(info['filename']) filename = os.path.splitext(filename)[0] else: filename = '' resp = dict(docstring=info['docstring'], name=filename, note='', argspec='', calltip=None) return resp @memoize def python_like_mod_finder(import_line, alt_path=None, stop_token=None): """ Locate a module path based on an import line in an python-like file import_line is the line of source code containing the import alt_path specifies an alternate base path for the module stop_token specifies the desired name to stop on This is used to a find the path to python-like modules (e.g. cython and enaml) for a goto definition. """ if stop_token and '.' in stop_token: stop_token = stop_token.split('.')[-1] tokens = re.split(r'\W', import_line) if tokens[0] in ['from', 'import']: # find the base location try: _, path, _ = imp.find_module(tokens[1]) except ImportError: if alt_path: path = osp.join(alt_path, tokens[1]) else: path = None if path: path = osp.realpath(path) if not tokens[1] == stop_token: for part in tokens[2:]: if part in ['import', 'cimport', 'as']: break path = osp.join(path, part) if part == stop_token: break # from package import module if stop_token and not stop_token in path: for ext in python_like_exts(): fname = '%s%s' % (stop_token, ext) if osp.exists(osp.join(path, fname)): return osp.join(path, fname) # from module import name for ext in python_like_exts(): fname = '%s%s' % (path, ext) if osp.exists(fname): return fname # if it is a file, return it if osp.exists(path) and not osp.isdir(path): return path # default to the package file path = osp.join(path, '__init__.py') if osp.exists(path): return path def get_definition_with_regex(source, token, start_line=-1): """ Find the definition of an object within a source closest to a given line """ if not token: return None if DEBUG_EDITOR: t0 = time.time() patterns = [ # python / cython keyword definitions '^c?import.*\W{0}{1}', 'from.*\W{0}\W.*c?import ', 'from .* c?import.*\W{0}{1}', 'class\s*{0}{1}', 'c?p?def[^=]*\W{0}{1}', 'cdef.*\[.*\].*\W{0}{1}', # enaml keyword definitions 'enamldef.*\W{0}{1}', 'attr.*\W{0}{1}', 'event.*\W{0}{1}', 'id\s*:.*\W{0}{1}'] matches = get_matches(patterns, source, token, start_line) if not matches: patterns = ['.*\Wself.{0}{1}[^=!<>]*=[^=]', '.*\W{0}{1}[^=!<>]*=[^=]', 'self.{0}{1}[^=!<>]*=[^=]', '{0}{1}[^=!<>]*=[^=]'] matches = get_matches(patterns, source, token, start_line) # find the one closest to the start line (prefer before the start line) if matches: min_dist = len(source.splitlines()) best_ind = 0 for match in matches: dist = abs(start_line - match) if match <= start_line or not best_ind: if dist < min_dist: min_dist = dist best_ind = match if matches: if DEBUG_EDITOR: log_dt(LOG_FILENAME, 'regex definition match', t0) return best_ind else: if DEBUG_EDITOR: log_dt(LOG_FILENAME, 'regex definition failed match', t0) return None def get_matches(patterns, source, token, start_line): patterns = [pattern.format(token, r'[^0-9a-zA-Z.[]') for pattern in patterns] pattern = re.compile('|^'.join(patterns)) # add the trailing space to allow some regexes to match lines = [line.strip() + ' ' for line in source.splitlines()] if start_line == -1: start_line = len(lines) matches = [] for (index, line) in enumerate(lines): if re.match(pattern, line): matches.append(index + 1) return matches def python_like_exts(): """Return a list of all python-like extensions""" exts = [] for lang in sourcecode.PYTHON_LIKE_LANGUAGES: exts.extend(list(sourcecode.ALL_LANGUAGES[lang])) return ['.' + ext for ext in exts] def all_editable_exts(): """Return a list of all editable extensions""" exts = [] for (language, extensions) in sourcecode.ALL_LANGUAGES.items(): exts.extend(list(extensions)) return ['.' + ext for ext in exts] def _listdir(root): "List directory 'root' appending the path separator to subdirs." res = [] root = os.path.expanduser(root) try: for name in os.listdir(root): path = os.path.join(root, name) if os.path.isdir(path): name += os.sep res.append(name) except: pass # no need to report invalid paths return res def _complete_path(path=None): """Perform completion of filesystem path. http://stackoverflow.com/questions/5637124/tab-completion-in-pythons-raw-input """ if not path: return _listdir('.') dirname, rest = os.path.split(path) tmp = dirname if dirname else '.' res = [p for p in _listdir(tmp) if p.startswith(rest)] # more than one match, or single match which does not exist (typo) if len(res) > 1 or not os.path.exists(path): return res # resolved to a single directory, so return list of files below it if os.path.isdir(path): return [p for p in _listdir(path)] # exact file match terminates this completion return [path + ' '] spyder-3.2.6/spyder/utils/introspection/jedi_patch.py0000664000175000017500000001563713156676663023673 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Patching jedi: [1] Adding numpydoc type returns to docstrings [2] Adding type returns for compiled objects in jedi [3] Fixing introspection for matplotlib Axes objects [4] Fixing None for parents in matplotlib Figure objects """ def apply(): """Monkey patching jedi See [1] and [2] module docstring.""" from spyder.utils.programs import is_module_installed if (is_module_installed('jedi', '=0.9.0') or is_module_installed('jedi', '>=0.10.0;<0.11')): import jedi else: raise ImportError("jedi not =0.9.0 or 0.10.0, can't be patched") # [1] Adding numpydoc type returns to docstrings from spyder.utils.introspection import numpy_docstr jedi.evaluate.representation.docstrings._search_param_in_numpydocstr = \ numpy_docstr._search_param_in_numpydocstr jedi.evaluate.representation.docstrings.find_return_types = \ numpy_docstr.find_return_types # [2] Adding type returns for compiled objects in jedi # Patching jedi.evaluate.compiled.CompiledObject... if is_module_installed('jedi', '=0.9.0'): from jedi.evaluate.compiled import (builtin, _create_from_name, debug, CompiledObject) def _execute_function(self, evaluator, params): if self.type != 'funcdef': return # patching docstrings here from spyder.utils.introspection import numpy_docstr types = numpy_docstr.find_return_types(evaluator, self) if types: for result in types: debug.dbg('docstrings type return: %s in %s', result, self) yield result # end patch for name in self._parse_function_doc()[1].split(): try: bltn_obj = _create_from_name(builtin, builtin, name) except AttributeError: continue else: if (isinstance(bltn_obj, CompiledObject) and bltn_obj.obj is None): # We want everything except None. continue for result in evaluator.execute(bltn_obj, params): yield result else: # Code for Jedi 0.10.0 from jedi.evaluate.compiled import debug, create from jedi._compatibility import builtins as _builtins def _execute_function(self, params): from spyder.utils.introspection import numpy_docstr if self.type != 'funcdef': return types = set([]) types |= set(numpy_docstr.find_return_types(self.parent_context, self)) debug.dbg('docstrings type return: %s in %s', types, self) for name in self._parse_function_doc()[1].split(): try: bltn_obj = getattr(_builtins, name) except AttributeError: continue else: if bltn_obj is None: # We want to evaluate everything except None. continue bltn_obj = create(self.evaluator, bltn_obj) types |= set(self.evaluator.execute(bltn_obj, params)) for result in types: yield result jedi.evaluate.compiled.CompiledObject._execute_function = _execute_function if is_module_installed('jedi', '=0.9.0'): # [3] Fixing introspection for matplotlib Axes objects # Patching jedi.evaluate.precedence... from jedi.evaluate.precedence import tree, calculate def calculate_children(evaluator, children): """ Calculate a list of children with operators. """ iterator = iter(children) types = evaluator.eval_element(next(iterator)) for operator in iterator: try: # PATCH: Catches StopIteration error right = next(iterator) if tree.is_node(operator, 'comp_op'): # not in / is not operator = ' '.join(str(c.value) for c in operator.children) # handle lazy evaluation of and/or here. if operator in ('and', 'or'): left_bools = set([left.py__bool__() for left in types]) if left_bools == set([True]): if operator == 'and': types = evaluator.eval_element(right) elif left_bools == set([False]): if operator != 'and': types = evaluator.eval_element(right) # Otherwise continue, because of uncertainty. else: types = calculate(evaluator, types, operator, evaluator.eval_element(right)) except StopIteration: debug.warning('calculate_children StopIteration %s', types) debug.dbg('calculate_children types %s', types) return types jedi.evaluate.precedence.calculate_children = calculate_children # [4] Fixing introspection for matplotlib Axes objects # Patching jedi.evaluate.precedence... from jedi.evaluate.representation import (InstanceName, Instance, compiled, FunctionExecution, InstanceElement) def get_instance_el(evaluator, instance, var, is_class_var=False): """ Returns an InstanceElement if it makes sense, otherwise leaves the object untouched. Basically having an InstanceElement is context information. That is needed in quite a lot of cases, which includes Nodes like ``power``, that need to know where a self name comes from for example. """ if isinstance(var, tree.Name): parent = get_instance_el(evaluator, instance, var.parent, is_class_var) return InstanceName(var, parent) # PATCH: compiled objects can be None elif var is None: return var elif var.type != 'funcdef' \ and isinstance(var, (Instance, compiled.CompiledObject, tree.Leaf, tree.Module, FunctionExecution)): return var var = evaluator.wrap(var) return InstanceElement(evaluator, instance, var, is_class_var) jedi.evaluate.representation.get_instance_el = get_instance_el return jedi spyder-3.2.6/spyder/utils/introspection/numpy_docstr.py0000664000175000017500000001277013156676663024322 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) # Contents in this file are taken from # # https://github.com/davidhalter/jedi/pull/796 # # to patch Jedi 0.9.0 (it probably doesn't work with # higher versions) from ast import literal_eval import re from spyder.utils.programs import is_module_installed from jedi._compatibility import u, is_py3 from jedi.evaluate.cache import memoize_default from jedi.evaluate.docstrings import (_evaluate_for_statement_string, _strip_rst_role, DOCSTRING_RETURN_PATTERNS) from numpydoc.docscrape import NumpyDocString def _expand_typestr(p_type): """ Attempts to interpret the possible types """ # Check if alternative types are specified if re.search('\\bor\\b', p_type): types = [t.strip() for t in p_type.split('or')] # Check if type has a set of valid literal values elif p_type.startswith('{'): if not is_py3: # python2 does not support literal set evals # workaround this by using lists instead p_type = p_type.replace('{', '[').replace('}', ']') types = set(type(x).__name__ for x in literal_eval(p_type)) types = list(types) # Otherwise just return the typestr wrapped in a list else: types = [p_type] return types def _search_param_in_numpydocstr(docstr, param_str): r""" Search `docstr` (in numpydoc format) for type(-s) of `param_str`. >>> from jedi.evaluate.docstrings import * # NOQA >>> from jedi.evaluate.docstrings import _search_param_in_numpydocstr >>> docstr = ( ... 'Parameters\n' ... '----------\n' ... 'x : ndarray\n' ... 'y : int or str or list\n' ... 'z : {"foo", "bar", 100500}, optional\n' ... ) >>> _search_param_in_numpydocstr(docstr, 'x') ['ndarray'] >>> sorted(_search_param_in_numpydocstr(docstr, 'y')) ['int', 'list', 'str'] >>> sorted(_search_param_in_numpydocstr(docstr, 'z')) ['int', 'str'] """ params = NumpyDocString(docstr)._parsed_data['Parameters'] for p_name, p_type, p_descr in params: if p_name == param_str: m = re.match('([^,]+(,[^,]+)*?)(,[ ]*optional)?$', p_type) if m: p_type = m.group(1) return _expand_typestr(p_type) return [] def _search_return_in_numpydocstr(docstr): r""" Search `docstr` (in numpydoc format) for type(-s) of `param_str`. >>> from jedi.evaluate.docstrings import * # NOQA >>> from jedi.evaluate.docstrings import _search_return_in_numpydocstr >>> from jedi.evaluate.docstrings import _expand_typestr >>> docstr = ( ... 'Returns\n' ... '----------\n' ... 'int\n' ... ' can return an anoymous integer\n' ... 'out : ndarray\n' ... ' can return a named value\n' ... ) >>> _search_return_in_numpydocstr(docstr) ['int', 'ndarray'] """ doc = NumpyDocString(docstr) returns = doc._parsed_data['Returns'] returns += doc._parsed_data['Yields'] found = [] for p_name, p_type, p_descr in returns: if not p_type: p_type = p_name p_name = '' m = re.match('([^,]+(,[^,]+)*?)$', p_type) if m: p_type = m.group(1) found.extend(_expand_typestr(p_type)) return found # Caching disabled because jedi_patch breaks it # @memoize_default(None, evaluator_is_first_arg=True) def find_return_types(module_context, func): """ Determines a set of potential return types for `func` using docstring hints :type evaluator: jedi.evaluate.Evaluator :type param: jedi.parser.tree.Param :rtype: list >>> from jedi.evaluate.docstrings import * # NOQA >>> from jedi.evaluate.docstrings import _search_param_in_docstr >>> from jedi.evaluate.docstrings import _evaluate_for_statement_string >>> from jedi.evaluate.docstrings import _search_return_in_gooogledocstr >>> from jedi.evaluate.docstrings import _search_return_in_numpydocstr >>> from jedi._compatibility import builtins >>> source = open(jedi.evaluate.docstrings.__file__.replace('.pyc', '.py'), 'r').read() >>> script = jedi.Script(source) >>> evaluator = script._evaluator >>> func = script._get_module().names_dict['find_return_types'][0].parent >>> types = find_return_types(evaluator, func) >>> print('types = %r' % (types,)) >>> assert len(types) == 1 >>> assert types[0].base.obj is builtins.list """ def search_return_in_docstr(docstr): # Check for Sphinx/Epydoc return hint for p in DOCSTRING_RETURN_PATTERNS: match = p.search(docstr) if match: return [_strip_rst_role(match.group(1))] found = [] if not found: # Check for numpy style return hint found = _search_return_in_numpydocstr(docstr) return found try: docstr = u(func.raw_doc) except AttributeError: docstr = u(func.doc) types = [] for type_str in search_return_in_docstr(docstr): if is_module_installed('jedi', '>=0.10.0;<0.11'): type_ = _evaluate_for_statement_string(module_context, type_str) else: module = func.get_parent_until() type_ = _evaluate_for_statement_string(module_context, type_str, module) types.extend(type_) return types spyder-3.2.6/spyder/utils/introspection/jedi_plugin.py0000664000175000017500000002236213224121062024031 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Jedi Introspection Plugin """ import re import os.path as osp import sys import time from spyder.config.base import debug_print from spyder.utils import programs from spyder.utils.debug import log_last_error, log_dt from spyder.utils.dochelpers import getsignaturefromtext from spyder.utils.introspection.manager import ( DEBUG_EDITOR, LOG_FILENAME, IntrospectionPlugin) from spyder.utils.introspection.utils import get_parent_until from spyder.utils.introspection.manager import JEDI_REQVER try: try: from spyder.utils.introspection import jedi_patch jedi = jedi_patch.apply() except ImportError: import jedi except ImportError: jedi = None JEDI_010 = programs.is_module_installed('jedi', '>=0.10.0') class JediPlugin(IntrospectionPlugin): """ Jedi based introspection plugin for jedi Experimental Editor's code completion, go-to-definition and help """ # ---- IntrospectionPlugin API -------------------------------------------- name = 'jedi' def load_plugin(self): """Load the Jedi introspection plugin""" if not programs.is_module_installed('jedi', JEDI_REQVER): raise ImportError('Requires Jedi %s' % JEDI_REQVER) jedi.settings.case_insensitive_completion = False for lib in ['numpy', 'matplotlib']: jedi.preload_module(lib) def get_completions(self, info): """Return a list of (completion, type) tuples""" completions = self.get_jedi_object('completions', info) if DEBUG_EDITOR: log_last_error(LOG_FILENAME, str("comp: " + str(completions)[:100])) completions = [(c.name, c.type) for c in completions] debug_print(str(completions)[:100]) return completions def get_info(self, info): """ Find the calltip and docs Returns a dict like the following: {'note': 'Function of numpy.core.numeric...', 'argspec': "(shape, dtype=None, order='C')' 'docstring': 'Return an array of given...' 'name': 'ones', 'calltip': 'ones(shape, dtype=None, order='C')'} """ call_def = self.get_jedi_object('goto_definitions', info) for cd in call_def: # For compatibility with Jedi 0.11 try: cd.doc = cd.docstring() except AttributeError: pass if cd.doc and not cd.doc.rstrip().endswith(')'): call_def = cd break else: call_def = call_def[0] name = call_def.name if name is None: return if call_def.module_path: mod_name = get_parent_until(call_def.module_path) else: mod_name = None if not mod_name: mod_name = call_def.module_name if call_def.doc.startswith(name + '('): calltip = getsignaturefromtext(call_def.doc, name) argspec = calltip[calltip.find('('):] docstring = call_def.doc[call_def.doc.find(')') + 3:] elif '(' in call_def.doc.splitlines()[0]: calltip = call_def.doc.splitlines()[0] name = call_def.doc.split('(')[0] docstring = call_def.doc[call_def.doc.find(')') + 3:] argspec = calltip[calltip.find('('):] else: calltip = name + '(...)' argspec = '()' docstring = call_def.doc if call_def.type == 'module': note = 'Module %s' % mod_name argspec = '' calltip = name elif call_def.type == 'class': note = 'Class in %s module' % mod_name elif call_def.doc.startswith('%s(self' % name): class_name = call_def.full_name.split('.')[-2] note = 'Method of %s class in %s module' % ( class_name.capitalize(), mod_name) else: note = '%s in %s module' % (call_def.type.capitalize(), mod_name) argspec = argspec.replace(' = ', '=') calltip = calltip.replace(' = ', '=') debug_print(call_def.name) doc_info = dict(name=name, argspec=argspec, note=note, docstring=docstring, calltip=calltip) return doc_info def get_definition(self, info): """ Find a definition location using Jedi Follows gotos until a definition is found, or it reaches a builtin module. Falls back on token lookup if it is in an enaml file or does not find a match """ line, filename = info['line_num'], info['filename'] def_info, module_path, line_nr = None, None, None gotos = self.get_jedi_object('goto_assignments', info) if gotos: def_info = self.get_definition_info(gotos[0]) if def_info and def_info['goto_next']: defns = self.get_jedi_object('goto_definitions', info) if defns: new_info = self.get_definition_info(defns[0]) if not new_info['in_builtin']: def_info = new_info elif not def_info: return # handle builtins -> try and find the module if def_info and def_info['in_builtin']: module_path, line_nr = self.find_in_builtin(def_info) elif def_info: module_path = def_info['module_path'] line_nr = def_info['line_nr'] if module_path == filename and line_nr == line: return return module_path, line_nr # ---- Private API ------------------------------------------------------- def get_jedi_object(self, func_name, info, use_filename=True): """Call a desired function on a Jedi Script and return the result""" if not jedi: return if DEBUG_EDITOR: t0 = time.time() # override IPython qt_loaders ImportDenier behavior metas = sys.meta_path for meta in metas: if (meta.__class__.__name__ == 'ImportDenier' and hasattr(meta, 'forbid')): sys.meta_path.remove(meta) if use_filename: filename = info['filename'] else: filename = None try: if JEDI_010: script = jedi.api.Script(info['source_code'], info['line_num'], info['column'], filename, sys_path=info['sys_path']) else: script = jedi.api.Script(info['source_code'], info['line_num'], info['column'], filename) func = getattr(script, func_name) val = func() except Exception as e: val = None debug_print('Jedi error (%s)' % func_name) debug_print(str(e)) if DEBUG_EDITOR: log_last_error(LOG_FILENAME, str(e)) if DEBUG_EDITOR: log_dt(LOG_FILENAME, func_name, t0) if not val and filename: return self.get_jedi_object(func_name, info, False) else: return val @staticmethod def get_definition_info(defn): """Extract definition information from the Jedi definition object""" try: module_path = defn.module_path name = defn.name if hasattr(defn, 'line_nr'): line_nr = defn.line_nr else: line_nr = defn.line description = defn.description in_builtin = defn.in_builtin_module() except Exception as e: if DEBUG_EDITOR: log_last_error(LOG_FILENAME, 'Get Defintion: %s' % e) return None pattern = 'class\s+{0}|def\s+{0}|self.{0}\s*=|{0}\s*='.format(name) if not re.match(pattern, description): goto_next = True else: goto_next = False return dict(module_path=module_path, line_nr=line_nr, description=description, name=name, in_builtin=in_builtin, goto_next=goto_next) def find_in_builtin(self, info): """Find a definition in a builtin file""" module_path = info['module_path'] line_nr = info['line_nr'] ext = osp.splitext(info['module_path'])[1] desc = info['description'] name = info['name'] if ext in self.python_like_exts() and ( desc.startswith('import ') or desc.startswith('from ')): path = self.python_like_mod_finder(desc, osp.dirname(module_path), name) if path: info['module_path'] = module_path = path info['line_nr'] = line_nr = 1 if ext in self.all_editable_exts(): pattern = 'from.*\W{0}\W?.*c?import|import.*\W{0}' if not re.match(pattern.format(info['name']), desc): line_nr = self.get_definition_from_file(module_path, name, line_nr) if not line_nr: module_path = None if not ext in self.all_editable_exts(): line_nr = None return module_path, line_nr spyder-3.2.6/spyder/utils/introspection/README.md0000664000175000017500000000213313026261006022442 0ustar carloscarlos00000000000000 Introspection is handled by `manager.IntrospectionManger`, which in turn uses a `PluginManager` for each plugin. The plugin manager uses a `PluginClient`, which creates a `QProcess` managing a `PluginServer`. The plugin server instantiates the plugin and acts as a remote procedure call interface to the `PluginClient`. Data is passed between the server and client as pickled objects over bsd sockets. We pass a request from: `Editor -> IntrospectionManager -> Plugin Manager -> PluginClient -> PluginServer -> Plugin` The response bubbles back as: `Plugin -> PluginServer -> PluginClient -> PluginManager -> IntrospectionManager -> Editor` There can only be one active and one pending request at a time. There is a `LEAD_TIME_SEC` time where we wait for the primary response from a request. After that time, a secondary response can be used, or a pending request will be sent, if there is one. When a valid response reaches the `IntrospectionManager`, it checks for the current state versus the state when the request was sent, and decides how best to handle the response, to include ignoring it. spyder-3.2.6/spyder/utils/introspection/tests/0000775000175000017500000000000013225025007022326 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/utils/introspection/tests/test_jedi_plugin.py0000664000175000017500000000645013224121062026232 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License """Tests for jedi_plugin.py""" from textwrap import dedent import pytest import os import os.path as osp from spyder.utils.introspection.manager import CodeInfo from spyder.utils.introspection import jedi_plugin try: import numpydoc except ImportError: numpydoc = None try: import numpy except ImportError: numpy = None try: import matplotlib except ImportError: matplotlib = None LOCATION = osp.realpath(osp.join(os.getcwd(), osp.dirname(__file__))) p = jedi_plugin.JediPlugin() p.load_plugin() def test_get_info(): source_code = "import os; os.walk" docs = p.get_info(CodeInfo('info', source_code, len(source_code))) assert docs['calltip'].startswith('walk(') and docs['name'] == 'walk' def test_get_completions(): source_code = "import o" completions = p.get_completions(CodeInfo('completions', source_code, len(source_code))) assert ('os', 'module') in completions def test_get_definition(): source_code = "import os; os.walk" path, line_nr = p.get_definition(CodeInfo('definition', source_code, len(source_code))) assert 'os.py' in path def test_get_path(): source_code = 'from spyder.utils.introspection.manager import CodeInfo' path, line_nr = p.get_definition(CodeInfo('definition', source_code, len(source_code), __file__)) assert 'utils' in path and 'introspection' in path def test_get_docstring(): source_code = dedent(''' def test(a, b): """Test docstring""" pass test''') path, line = p.get_definition(CodeInfo('definition', source_code, len(source_code), 'dummy.txt', is_python_like=True)) assert line == 2 docs = p.get_info(CodeInfo('info', source_code, len(source_code), __file__)) assert 'Test docstring' in docs['docstring'] @pytest.mark.skipif(not(numpy and numpydoc), reason="numpy and numpydoc required") def test_numpy_returns(): source_code = dedent(''' import numpy as np x = np.array([1,2,3]) x.a''') completions = p.get_completions(CodeInfo('completions', source_code, len(source_code))) assert ('argmax', 'function') in completions @pytest.mark.skipif(not(matplotlib and numpydoc), reason="matplotlib required") def test_matplotlib_fig_returns(): source_code = dedent(''' import matplotlib.pyplot as plt fig = plt.figure() fig.''') completions = p.get_completions(CodeInfo('completions', source_code, len(source_code))) assert ('add_axes', 'function') in completions def test_completions_custom_path(): source_code = dedent('import test_') completions = p.get_completions(CodeInfo('completions', source_code, len(source_code), sys_path=[LOCATION])) assert ('test_jedi_plugin', 'module') in completions if __name__ == '__main__': pytest.main() spyder-3.2.6/spyder/utils/introspection/tests/test_manager.py0000664000175000017500000000226013224121062025346 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for manager.py """ # Standard library imports import sys # Test library imports import pytest # Local imports from spyder.utils.introspection.manager import IntrospectionManager @pytest.fixture def introspector_manager(): """Create a basic instrospection manager.""" introspector = IntrospectionManager() return introspector def test_introspector_manager_extra_path(introspector_manager): """Test adding of extra path. Extra path is used for adding spyder_path to plugin clients. """ introspector = introspector_manager extra_path = ['/some/dummy/path'] assert set(introspector.sys_path) == set(sys.path) # Add extra path introspector.change_extra_path(extra_path) assert set(sys.path).issubset(set(introspector.sys_path)) assert set(extra_path).issubset(set(introspector.sys_path)) # Remove extra path introspector.change_extra_path([]) print(introspector.sys_path) assert set(sys.path).issubset(set(introspector.sys_path)) assert not set(extra_path).issubset(set(introspector.sys_path)) spyder-3.2.6/spyder/utils/introspection/tests/test_utils.py0000664000175000017500000000127713156676663025135 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for utils.py """ # Standard library imports import pickle # Test library imports import pytest # Local imports from spyder.utils.introspection.utils import CodeInfo def test_codeinfo(): """Test CodeInfo.""" code = 'import numpy' test = CodeInfo('test', code, len(code) - 2) assert test.obj == 'num' assert test.full_obj == 'numpy' test2 = CodeInfo('test', code, len(code) - 2) assert test == test2 test3 = pickle.loads(pickle.dumps(test2.__dict__)) assert test3['full_obj'] == 'numpy' if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/utils/introspection/tests/test_rope_plugin.py0000664000175000017500000000471013224121062026261 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License """Tests for jedi_plugin.py""" from textwrap import dedent import pytest import os import os.path as osp from spyder.utils.introspection.manager import CodeInfo from spyder.utils.introspection import rope_plugin LOCATION = osp.realpath(osp.join(os.getcwd(), osp.dirname(__file__))) p = rope_plugin.RopePlugin() p.load_plugin() try: import numpy except ImportError: numpy = None @pytest.mark.skipif(not numpy, reason="Numpy required") def test_get_info(): source_code = "import numpy; numpy.ones" docs = p.get_info(CodeInfo('info', source_code, len(source_code), __file__)) assert docs['calltip'].startswith('ones(') and docs['name'] == 'ones' @pytest.mark.skipif(not numpy, reason="Numpy required") def test_get_completions_1(): source_code = "import numpy; n" completions = p.get_completions(CodeInfo('completions', source_code, len(source_code), __file__)) assert ('numpy', 'module') in completions def test_get_completions_2(): source_code = "import a" completions = p.get_completions(CodeInfo('completions', source_code, len(source_code), __file__)) assert not completions def test_get_completions_custom_path(): source_code = "import test_rope_plugin; test_" completions = p.get_completions(CodeInfo('completions', source_code, len(source_code), sys_path=[LOCATION])) assert ('test_rope_plugin', 'module') in completions def test_get_definition(): source_code = "import os; os.walk" path, line_nr = p.get_definition(CodeInfo('definition', source_code, len(source_code), __file__)) assert 'os.py' in path def test_get_docstring(): source_code = dedent(''' def test(a, b): """Test docstring""" pass test(1,''') path, line = p.get_definition(CodeInfo('definition', source_code, len(source_code), 'dummy.txt', is_python_like=True)) assert 'dummy' in path and line == 2 docs = p.get_info(CodeInfo('info', source_code, len(source_code), __file__, is_python_like=True)) assert 'Test docstring' in docs['docstring'] spyder-3.2.6/spyder/utils/introspection/tests/test_plugin_client.py0000664000175000017500000000112313224121062026565 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """Tests for plugin_client.py.""" # Test library imports import pytest # Local imports from spyder.utils.introspection.plugin_client import PluginClient from spyder.utils.introspection.manager import PLUGINS @pytest.mark.parametrize("plugin_name", PLUGINS) def test_plugin_client(qtbot, plugin_name): """Test creation of the diferent plugin clients.""" plugin = PluginClient(plugin_name=plugin_name) assert plugin if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/utils/introspection/tests/test_plugin_server.py0000664000175000017500000000112013156676663026644 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for plugin_server.py """ # Standard library imports import sys # Test library imports import pytest # Local imports from spyder.utils.introspection.plugin_server import PluginServer def test_plugin_server(qtbot): """Test creation of a separate process for interacting with a plugin.""" args = sys.argv[1:] if len(args) == 2: plugin = PluginServer(*args) plugin.run() assert plugin if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/utils/introspection/tests/test_fallback_plugin.py0000664000175000017500000001051113156676663027101 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for fallback_plugin.py """ # Standard library imports import os import os.path as osp # Test library imports import pytest # Local imports from spyder.utils.introspection.fallback_plugin import (FallbackPlugin, python_like_exts, all_editable_exts, get_parent_until, python_like_mod_finder ) from spyder.utils.introspection.manager import CodeInfo FALLBACK_PLUGIN_FILE = osp.join(os.path.dirname(__file__), '..', 'fallback_plugin.py') def test_fallback_plugin(): """Test the fallback plugin.""" p = FallbackPlugin() with open(FALLBACK_PLUGIN_FILE, 'rb') as fid: code = fid.read().decode('utf-8') code += '\nlog_dt' path, line = p.get_definition(CodeInfo('definition', code, len(code), __file__, is_python_like=True)) assert path.endswith('fallback_plugin.py') code += '\np.get_completions' path, line = p.get_definition(CodeInfo('definition', code, len(code), 'dummy.py', is_python_like=True)) assert path == 'dummy.py' assert 'def get_completions(' in code.splitlines()[line - 1] code += '\npython_like_mod_finder' path, line = p.get_definition(CodeInfo('definition', code, len(code), 'dummy.py', is_python_like=True)) assert path == 'dummy.py' # FIXME: we need to prioritize def over = assert 'def python_like_mod_finder' in code.splitlines()[line - 1] code += 'python_like_mod_finder' resp = p.get_definition(CodeInfo('definition', code, len(code), 'dummy.py')) assert resp is None def test_extensions(): """Test the extentions related methods from the fallback plugin.""" ext = python_like_exts() assert '.py' in ext and '.pyx' in ext ext = all_editable_exts() assert '.cpp' in ext and '.html' in ext path = get_parent_until(os.path.abspath(FALLBACK_PLUGIN_FILE)) assert path == 'spyder.utils.introspection.fallback_plugin' line = 'from spyder.widgets.sourcecode.codeeditor import CodeEditor' path = python_like_mod_finder(line) assert path.endswith('codeeditor.py') path = python_like_mod_finder(line, stop_token='sourcecode') assert path.endswith('__init__.py') and 'sourcecode' in path path = osp.expanduser(r'~/.spyder2/temp.py') if os.path.exists(path): path = get_parent_until(path) assert path == '.spyder2.temp', path def test_get_completions(): """Test the get_completions method from the Fallback plugin.""" p = FallbackPlugin() code = 'self.proxy.widget; self.p' comp = p.get_completions(CodeInfo('completions', code, len(code), 'dummy.py')) assert ('proxy', '') in comp, comp code = 'self.sigMessageReady.emit; self.s' comp = p.get_completions(CodeInfo('completions', code, len(code), 'dummy.py')) assert ('sigMessageReady', '') in comp code = 'bob = 1; bo' comp = p.get_completions(CodeInfo('completions', code, len(code), 'dummy.m')) assert ('bob', '') in comp code = 'functi' comp = p.get_completions(CodeInfo('completions', code, len(code), 'dummy.sh')) assert ('function', '') in comp, comp def test_get_definition_method(): """Test the get_definition method for methods.""" p = FallbackPlugin() code = ''' def test(a, b): pass test(1,''' path, line = p.get_definition(CodeInfo('definition', code, len(code), 'dummy.py', is_python_like=True)) assert line == 2 code = 'import re\n\nre' path, line = p.get_definition(CodeInfo('definition', code, len(code), 'dummy.py', is_python_like=True)) assert path == 'dummy.py' and line == 1 def test_get_definition_class(): """Test the get_definition method for classes.""" p = FallbackPlugin() code = """ class Test(object): def __init__(self): self.foo = bar t = Test() t.foo""" path, line = p.get_definition(CodeInfo('definition', code, len(code), 'dummy.py', is_python_like=True)) assert line == 4 if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/utils/introspection/tests/__init__.py0000664000175000017500000000050213156676663024463 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Copyright (c) Spyder Project Contributors # # Licensed under the terms of the MIT License # (see LICENSE.txt for details) # ----------------------------------------------------------------------------- """Tests.""" spyder-3.2.6/spyder/utils/introspection/tests/test_modulecompletion.py0000664000175000017500000000340213156676663027344 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # """ Tests for module_completion.py """ # Test library imports import pytest # Local imports from spyder.utils.introspection.module_completion import (module_completion, get_preferred_submodules) from spyder.py3compat import PY3 def test_module_completion(): """Test module_completion.""" # Some simple tests. # Sort operations are done by the completion widget, so we have to # replicate them here. # We've chosen to use xml on most tests because it's on the standard # library. This way we can ensure they work on all plataforms. assert sorted(module_completion('import xml.')) == \ ['xml.dom', 'xml.etree', 'xml.parsers', 'xml.sax'] assert sorted(module_completion('import xml.d')) == ['xml.dom'] assert module_completion('from xml.etree ') == ['import '] assert sorted(module_completion('from xml.etree import '), key=str.lower) ==\ ['cElementTree', 'ElementInclude', 'ElementPath', 'ElementTree'] assert module_completion('import sys, zl') == ['zlib'] s = 'from xml.etree.ElementTree import ' assert module_completion(s + 'V') == ['VERSION'] if PY3: assert sorted(module_completion(s + 'VERSION, XM')) == \ ['XML', 'XMLID', 'XMLParser', 'XMLPullParser'] else: assert sorted(module_completion(s + 'VERSION, XM')) == \ ['XML', 'XMLID', 'XMLParser', 'XMLTreeBuilder'] assert module_completion(s + '(dum') == ['dump'] assert module_completion(s + '(dump, Su') == ['SubElement'] assert 'os.path' in get_preferred_submodules() if __name__ == "__main__": pytest.main() spyder-3.2.6/spyder/utils/introspection/plugin_server.py0000664000175000017500000000762613156676663024464 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) import sys import time import traceback import zmq # Timeout in milliseconds TIMEOUT = 10000 class AsyncServer(object): """ Introspection server, provides a separate process for interacting with an object. """ def __init__(self, port, *args): self.port = port self.object = self.initialize(*args) self.context = zmq.Context() self.socket = self.context.socket(zmq.PAIR) self.socket.connect("tcp://localhost:%s" % port) self.socket.send_pyobj(port) def initialize(self, plugin_name): """Initialize the object and return it. """ return object() def run(self): """Handle requests from the client. """ t0 = time.time() initialized = False timed_out = False while 1: # Poll for events, handling a timeout. try: events = self.socket.poll(TIMEOUT) except KeyboardInterrupt: time.sleep(0.1) continue if events == 0 and initialized: if timed_out: delta = int(time.time() - t0) print('Timed out after %s sec' % delta) # spyder: test-skip return timed_out = True continue timed_out = False initialized = True # Drain all exising requests, handling quit and heartbeat. requests = [] while 1: try: request = self.socket.recv_pyobj() except KeyboardInterrupt: time.sleep(0.1) continue if request['func_name'] == 'server_quit': print('Quitting') # spyder: test-skip sys.stdout.flush() return elif request['func_name'] != 'server_heartbeat': requests.append(request) else: print('Got heartbeat') # spyder: test-skip try: events = self.socket.poll(0) except KeyboardInterrupt: time.sleep(0.1) continue if events == 0: break # Select the most recent request. if not requests: continue request = requests[-1] # Gather the response response = dict(func_name=request['func_name'], request_id=request['request_id']) try: func = getattr(self.object, request['func_name']) args = request.get('args', []) kwargs = request.get('kwargs', {}) response['result'] = func(*args, **kwargs) except Exception: response['error'] = traceback.format_exc() # Send the response to the client. self.socket.send_pyobj(response) class PluginServer(AsyncServer): """ Introspection plugin server, provides a separate process for interacting with a plugin. """ def initialize(self, plugin_name): """Initialize the object and return it. """ mod_name = plugin_name + '_plugin' mod = __import__('spyder.utils.introspection.' + mod_name, fromlist=[mod_name]) cls = getattr(mod, '%sPlugin' % plugin_name.capitalize()) plugin = cls() plugin.load_plugin() return plugin if __name__ == '__main__': args = sys.argv[1:] if not len(args) == 2: print('Usage: plugin_server.py client_port plugin_name') # spyder: test-skip sys.exit(0) plugin = PluginServer(*args) print('Started') # spyder: test-skip plugin.run() spyder-3.2.6/spyder/utils/introspection/manager.py0000664000175000017500000003151313224121062023150 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) # Standard library imports from __future__ import print_function from collections import OrderedDict import time import sys # Third party imports from qtpy.QtCore import QObject, QTimer, Signal from qtpy.QtWidgets import QApplication # Local imports from spyder import dependencies from spyder.config.base import _, DEBUG, debug_print, get_conf_path from spyder.utils import sourcecode from spyder.utils.introspection.plugin_client import PluginClient from spyder.utils.introspection.utils import CodeInfo PLUGINS = ['rope', 'jedi', 'fallback'] LOG_FILENAME = get_conf_path('introspection.log') DEBUG_EDITOR = DEBUG >= 3 LEAD_TIME_SEC = 0.25 ROPE_REQVER = '>=0.9.4' dependencies.add('rope', _("Editor's code completion, go-to-definition and help"), required_version=ROPE_REQVER) JEDI_REQVER = '>=0.9.0' dependencies.add('jedi', _("Editor's code completion, go-to-definition and help"), required_version=JEDI_REQVER) class PluginManager(QObject): introspection_complete = Signal(object) def __init__(self, executable): super(PluginManager, self).__init__() plugins = OrderedDict() for name in PLUGINS: try: plugin = PluginClient(name, executable) plugin.run() except Exception as e: debug_print('Introspection Plugin Failed: %s' % name) debug_print(str(e)) continue debug_print('Introspection Plugin Loaded: %s' % name) plugins[name] = plugin plugin.received.connect(self.handle_response) self.plugins = plugins self.timer = QTimer() self.desired = [] self.ids = dict() self.info = None self.request = None self.pending = None self.pending_request = None self.waiting = False def send_request(self, info): """Handle an incoming request from the user.""" if self.waiting: if info.serialize() != self.info.serialize(): self.pending_request = info else: debug_print('skipping duplicate request') return debug_print('%s request' % info.name) desired = None self.info = info editor = info.editor if (info.name == 'completion' and 'jedi' not in self.plugins and info.line.lstrip().startswith(('import ', 'from '))): desired = 'fallback' if ((not editor.is_python_like()) or sourcecode.is_keyword(info.obj) or (editor.in_comment_or_string() and info.name != 'info')): desired = 'fallback' plugins = self.plugins.values() if desired: plugins = [self.plugins[desired]] self.desired = [desired] elif (info.name == 'definition' and not info.editor.is_python() or info.name == 'info'): self.desired = list(self.plugins.keys()) else: # Use all but the fallback plugins = list(self.plugins.values())[:-1] self.desired = list(self.plugins.keys())[:-1] self._start_time = time.time() self.waiting = True method = 'get_%s' % info.name value = info.serialize() self.ids = dict() for plugin in plugins: request_id = plugin.request(method, value) self.ids[request_id] = plugin.name self.timer.stop() self.timer.singleShot(LEAD_TIME_SEC * 1000, self._handle_timeout) def validate(self): for plugin in self.plugins.values(): plugin.request('validate') def handle_response(self, response): name = self.ids.get(response['request_id'], None) if not name: return if response.get('error', None): debug_print('Response error:', response['error']) return if name == self.desired[0] or not self.waiting: if response.get('result', None): self._finalize(response) else: self.pending = response def close(self): for name, plugin in self.plugins.items(): plugin.close() debug_print("Introspection Plugin Closed: {}".format(name)) def _finalize(self, response): self.waiting = False self.pending = None if self.info: delta = time.time() - self._start_time debug_print('%s request from %s finished: "%s" in %.1f sec' % (self.info.name, response['name'], str(response['result'])[:100], delta)) response['info'] = self.info self.info = None self.introspection_complete.emit(response) if self.pending_request: info = self.pending_request self.pending_request = None self.send_request(info) def _handle_timeout(self): self.waiting = False if self.pending: self._finalize(self.pending) else: debug_print('No valid responses acquired') class IntrospectionManager(QObject): send_to_help = Signal(str, str, str, str, bool) edit_goto = Signal(str, int, str) def __init__(self, executable=None, extra_path=[]): super(IntrospectionManager, self).__init__() self.editor_widget = None self.pending = None self.sys_path = sys.path[:] self.extra_path = extra_path if self.extra_path: self.sys_path.extend(extra_path) self.executable = executable self.plugin_manager = PluginManager(executable) self.plugin_manager.introspection_complete.connect( self._introspection_complete) def change_executable(self, executable): self.executable = executable self._restart_plugin() def change_extra_path(self, extra_path): """Change extra_path and update sys_path.""" if extra_path != self.extra_path: self.extra_path = extra_path self.sys_path = sys.path[:] self.sys_path.extend(extra_path) def _restart_plugin(self): self.plugin_manager.close() self.plugin_manager = PluginManager(self.executable) self.plugin_manager.introspection_complete.connect( self._introspection_complete) def set_editor_widget(self, editor_widget): self.editor_widget = editor_widget def _get_code_info(self, name, position=None, **kwargs): editor = self.editor_widget.get_current_editor() finfo = self.editor_widget.get_current_finfo() in_comment_or_string = editor.in_comment_or_string() if position is None: position = editor.get_position('cursor') kwargs['editor'] = editor kwargs['finfo'] = finfo kwargs['editor_widget'] = self.editor_widget kwargs['sys_path'] = self.sys_path return CodeInfo(name, finfo.get_source_code(), position, finfo.filename, editor.is_python_like, in_comment_or_string, **kwargs) def get_completions(self, automatic): """Get code completion""" info = self._get_code_info('completions', automatic=automatic) self.plugin_manager.send_request(info) def go_to_definition(self, position): """Go to definition""" info = self._get_code_info('definition', position) self.plugin_manager.send_request(info) def show_object_info(self, position, auto=True): """Show signature calltip and/or docstring in the Help plugin""" # auto is True means that this method was called automatically, # i.e. the user has just entered an opening parenthesis -- in that # case, we don't want to force Help to be visible, to avoid polluting # the window layout info = self._get_code_info('info', position, auto=auto) self.plugin_manager.send_request(info) def validate(self): """Validate the plugins""" self.plugin_manager.validate() def is_editor_ready(self): """Check if the main app is starting up""" if self.editor_widget: window = self.editor_widget.window() if hasattr(window, 'is_starting_up') and not window.is_starting_up: return True def _introspection_complete(self, response): """ Handle an introspection response completion. Route the response to the correct handler. """ result = response.get('result', None) if result is None: return info = response['info'] current = self._get_code_info(response['info']['name']) if result and current.filename == info.filename: func = getattr(self, '_handle_%s_result' % info.name) try: func(result, current, info) except Exception as e: debug_print(e) def _handle_completions_result(self, comp_list, info, prev_info): """ Handle a `completions` result. Only handle the response if we are on the same line of text and on the same `obj` as the original request. """ if info.line_num != prev_info.line_num: return completion_text = info.obj prev_text = prev_info.obj if prev_info.obj is None: completion_text = '' prev_text = '' if not completion_text.startswith(prev_text): return if info.full_obj and len(info.full_obj) > len(info.obj): new_list = [(c, t) for (c, t) in comp_list if c.startswith(info.full_obj)] if new_list: pos = info.editor.get_position('cursor') new_pos = pos + len(info.full_obj) - len(info.obj) info.editor.set_cursor_position(new_pos) completion_text = info.full_obj comp_list = new_list if '.' in completion_text: completion_text = completion_text.split('.')[-1] comp_list = [(c.split('.')[-1], t) for (c, t) in comp_list] comp_list = [(c, t) for (c, t) in comp_list if c.startswith(completion_text)] info.editor.show_completion_list(comp_list, completion_text, prev_info.automatic) def _handle_info_result(self, resp, info, prev_info): """ Handle an `info` result, triggering a calltip and/or docstring. Only handle the response if we are on the same line of text as when the request was initiated. """ if info.line_num != prev_info.line_num: return if resp['calltip']: info.editor.show_calltip('Arguments', resp['calltip'], signature=True, at_position=prev_info.position) if resp['name']: self.send_to_help.emit( resp['name'], resp['argspec'], resp['note'], resp['docstring'] or resp['name'], not prev_info.auto) def _handle_definition_result(self, resp, info, prev_info): """Handle a `definition` result""" fname, lineno = resp self.edit_goto.emit(fname, lineno, "") def _post_message(self, message, timeout=60000): """ Post a message to the main window status bar with a timeout in ms """ if self.editor_widget: try: statusbar = self.editor_widget.window().statusBar() statusbar.showMessage(message, timeout) QApplication.processEvents() except AttributeError: pass class IntrospectionPlugin(object): def load_plugin(self): """Initialize the plugin""" pass def get_completions(self, info): """Get a list of completions""" pass def get_info(self, info): """ Find the calltip and docs Returns a dict like the following: {'note': 'Function of numpy.core.numeric...', 'argspec': "(shape, dtype=None, order='C')' 'docstring': 'Return an array of given...' 'name': 'ones', 'calltip': 'ones(shape, dtype=None, order='C')'} """ pass def get_definition(self, info): """Get a (filename, line_num) location for a definition""" pass def validate(self): """Validate the plugin""" pass spyder-3.2.6/spyder/utils/introspection/plugin_client.py0000664000175000017500000001654613224121062024403 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) # Local imports import imp import os import os.path as osp import sys import uuid # Third party imports from qtpy.QtCore import (QObject, QProcess, QProcessEnvironment, QSocketNotifier, QTimer, Signal) from qtpy.QtWidgets import QApplication import zmq # Local imports from spyder.config.base import debug_print, get_module_path # Heartbeat timer in milliseconds HEARTBEAT = 1000 class AsyncClient(QObject): """ A class which handles a connection to a client through a QProcess. """ # Emitted when the client has initialized. initialized = Signal() # Emitted when the client errors. errored = Signal() # Emitted when a request response is received. received = Signal(object) def __init__(self, target, executable=None, name=None, extra_args=None, libs=None, cwd=None, env=None): super(AsyncClient, self).__init__() self.executable = executable or sys.executable self.extra_args = extra_args self.target = target self.name = name or self self.libs = libs self.cwd = cwd self.env = env self.is_initialized = False self.closing = False self.notifier = None self.process = None self.context = zmq.Context() QApplication.instance().aboutToQuit.connect(self.close) # Set up the heartbeat timer. self.timer = QTimer(self) self.timer.timeout.connect(self._heartbeat) def run(self): """Handle the connection with the server. """ # Set up the zmq port. self.socket = self.context.socket(zmq.PAIR) self.port = self.socket.bind_to_random_port('tcp://*') # Set up the process. self.process = QProcess(self) if self.cwd: self.process.setWorkingDirectory(self.cwd) p_args = ['-u', self.target, str(self.port)] if self.extra_args is not None: p_args += self.extra_args # Set up environment variables. processEnvironment = QProcessEnvironment() env = self.process.systemEnvironment() if (self.env and 'PYTHONPATH' not in self.env) or self.env is None: python_path = osp.dirname(get_module_path('spyder')) # Add the libs to the python path. for lib in self.libs: try: path = osp.dirname(imp.find_module(lib)[1]) python_path = osp.pathsep.join([python_path, path]) except ImportError: pass env.append("PYTHONPATH=%s" % python_path) if self.env: env.update(self.env) for envItem in env: envName, separator, envValue = envItem.partition('=') processEnvironment.insert(envName, envValue) self.process.setProcessEnvironment(processEnvironment) # Start the process and wait for started. self.process.start(self.executable, p_args) self.process.finished.connect(self._on_finished) running = self.process.waitForStarted() if not running: raise IOError('Could not start %s' % self) # Set up the socket notifer. fid = self.socket.getsockopt(zmq.FD) self.notifier = QSocketNotifier(fid, QSocketNotifier.Read, self) self.notifier.activated.connect(self._on_msg_received) def request(self, func_name, *args, **kwargs): """Send a request to the server. The response will be a dictionary the 'request_id' and the 'func_name' as well as a 'result' field with the object returned by the function call or or an 'error' field with a traceback. """ if not self.is_initialized: return request_id = uuid.uuid4().hex request = dict(func_name=func_name, args=args, kwargs=kwargs, request_id=request_id) self._send(request) return request_id def close(self): """Cleanly close the connection to the server. """ self.closing = True self.is_initialized = False self.timer.stop() if self.notifier is not None: self.notifier.activated.disconnect(self._on_msg_received) self.notifier.setEnabled(False) self.notifier = None self.request('server_quit') if self.process is not None: self.process.waitForFinished(1000) self.process.close() self.context.destroy() def _on_finished(self): """Handle a finished signal from the process. """ if self.closing: return if self.is_initialized: debug_print('Restarting %s' % self.name) debug_print(self.process.readAllStandardOutput()) debug_print(self.process.readAllStandardError()) self.is_initialized = False self.notifier.setEnabled(False) self.run() else: debug_print('Errored %s' % self.name) debug_print(self.process.readAllStandardOutput()) debug_print(self.process.readAllStandardError()) self.errored.emit() def _on_msg_received(self): """Handle a message trigger from the socket. """ self.notifier.setEnabled(False) while 1: try: resp = self.socket.recv_pyobj(flags=zmq.NOBLOCK) except zmq.ZMQError: self.notifier.setEnabled(True) return if not self.is_initialized: self.is_initialized = True debug_print('Initialized %s' % self.name) self.initialized.emit() self.timer.start(HEARTBEAT) continue resp['name'] = self.name self.received.emit(resp) def _heartbeat(self): """Send a heartbeat to keep the server alive. """ self._send(dict(func_name='server_heartbeat')) def _send(self, obj): """Send an object to the server. """ try: self.socket.send_pyobj(obj, zmq.NOBLOCK) except Exception as e: debug_print(e) self.is_initialized = False self._on_finished() class PluginClient(AsyncClient): def __init__(self, plugin_name, executable=None, env=None, extra_path=None): cwd = os.path.dirname(__file__) super(PluginClient, self).__init__( 'plugin_server.py', executable=executable, cwd=cwd, env=env, extra_args=[plugin_name], libs=[plugin_name]) self.name = plugin_name if __name__ == '__main__': app = QApplication(sys.argv) plugin = PluginClient('jedi') plugin.run() def handle_return(value): print(value) # spyder: test-skip if value['func_name'] == 'foo': app.quit() else: plugin.request('foo') def handle_errored(): print('errored') # spyder: test-skip sys.exit(1) def start(): print('start') # spyder: test-skip plugin.request('validate') plugin.errored.connect(handle_errored) plugin.received.connect(handle_return) plugin.initialized.connect(start) app.exec_() spyder-3.2.6/spyder/utils/introspection/utils.py0000664000175000017500000002054213224121062022676 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Introspection utilities used by Spyder """ import imp import os import pickle import os.path as osp import re from spyder.utils.misc import memoize from spyder.utils.syntaxhighlighters import ( custom_extension_lexer_mapping ) from pygments.lexer import words from pygments.lexers import ( get_lexer_for_filename, get_lexer_by_name, TextLexer ) from pygments.util import ClassNotFound from pygments.token import Token class CodeInfo(object): id_regex = re.compile(r'[^\d\W][\w\.]*', re.UNICODE) func_call_regex = re.compile(r'([^\d\W][\w\.]*)\([^\)\()]*\Z', re.UNICODE) def __init__(self, name, source_code, position, filename=None, is_python_like=False, in_comment_or_string=False, sys_path=None, **kwargs): self.__dict__.update(kwargs) self.name = name self.filename = filename self.source_code = source_code self.is_python_like = is_python_like self.in_comment_or_string = in_comment_or_string self.sys_path = sys_path self.position = position # if in a comment, look for the previous definition if in_comment_or_string: # if this is a docstring, find it, set as our self.docstring = self._get_docstring() # backtrack and look for a line that starts with def or class if name != 'completions': while position: base = self.source_code[position: position + 6] if base.startswith('def ') or base.startswith('class '): position += base.index(' ') + 1 break position -= 1 else: self.docstring = '' self.position = position if position == 0: self.lines = [] self.column = 0 self.line_num = 0 self.line = '' self.obj = '' self.full_obj = '' else: self._get_info() def _get_info(self): self.lines = self.source_code[:self.position].splitlines() self.line_num = len(self.lines) self.line = self.lines[-1] self.column = len(self.lines[-1]) full_line = self.source_code.splitlines()[self.line_num - 1] lexer = find_lexer_for_filename(self.filename) # check for a text-based lexer that doesn't split tokens if len(list(lexer.get_tokens('a b'))) == 1: # Use regex to get the information tokens = re.findall(self.id_regex, self.line) if tokens and self.line.endswith(tokens[-1]): self.obj = tokens[-1] else: self.obj = None self.full_obj = self.obj if self.obj: full_line = self.source_code.splitlines()[self.line_num - 1] rest = full_line[self.column:] match = re.match(self.id_regex, rest) if match: self.full_obj = self.obj + match.group() self.context = None else: # Use lexer to get the information pos = 0 line_tokens = lexer.get_tokens(full_line) for (context, token) in line_tokens: pos += len(token) if pos >= self.column: self.obj = token[:len(token) - (pos - self.column)] self.full_obj = token if context in Token.Literal.String: context = Token.Literal.String self.context = context break if (self.name in ['info', 'definition'] and (not self.context in Token.Name) and self.is_python_like): func_call = re.findall(self.func_call_regex, self.line) if func_call: self.obj = func_call[-1] self.column = self.line.index(self.obj) + len(self.obj) self.position = self.position - len(self.line) + self.column def _get_docstring(self): """Find the docstring we are currently in.""" left = self.position while left: if self.source_code[left: left + 3] in ['"""', "'''"]: left += 3 break left -= 1 right = self.position while right < len(self.source_code): if self.source_code[right - 3: right] in ['"""', "'''"]: right -= 3 break right += 1 if left and right < len(self.source_code): return self.source_code[left: right] return '' def __eq__(self, other): try: return self.serialize() == other.serialize() except Exception: return False def __getitem__(self, item): """Allow dictionary-like access.""" return getattr(self, item) def serialize(self): state = {} for (key, value) in self.__dict__.items(): try: pickle.dumps(value) state[key] = value except Exception: pass state['id_regex'] = self.id_regex state['func_call_regex'] = self.func_call_regex return state def find_lexer_for_filename(filename): """Get a Pygments Lexer given a filename. """ filename = filename or '' root, ext = os.path.splitext(filename) if ext in custom_extension_lexer_mapping: lexer = get_lexer_by_name(custom_extension_lexer_mapping[ext]) else: try: lexer = get_lexer_for_filename(filename) except ClassNotFound: return TextLexer() return lexer def get_keywords(lexer): """Get the keywords for a given lexer. """ if not hasattr(lexer, 'tokens'): return [] if 'keywords' in lexer.tokens: try: return lexer.tokens['keywords'][0][0].words except: pass keywords = [] for vals in lexer.tokens.values(): for val in vals: try: if isinstance(val[0], words): keywords.extend(val[0].words) else: ini_val = val[0] if ')\\b' in val[0] or ')(\\s+)' in val[0]: val = re.sub(r'\\.', '', val[0]) val = re.sub('[^0-9a-zA-Z|]+', '', val) if '|' in ini_val: keywords.extend(val.split('|')) else: keywords.append(val) except Exception: continue return keywords def get_words(file_path=None, content=None, extension=None): """ Extract all words from a source code file to be used in code completion. Extract the list of words that contains the file in the editor, to carry out the inline completion similar to VSCode. """ if (file_path is None and (content is None or extension is None) or file_path and content and extension): error_msg = ('Must provide `file_path` or `content` and `extension`') raise Exception(error_msg) if file_path and content is None and extension is None: extension = os.path.splitext(file_path)[1] with open(file_path) as infile: content = infile.read() if extension in ['.css']: regex = re.compile(r'([^a-zA-Z-])') elif extension in ['.R', '.c', 'md', '.cpp, java', '.py']: regex = re.compile(r'([^a-zA-Z_])') else: regex = re.compile(r'([^a-zA-Z])') words = sorted(set(regex.sub(r' ', content).split())) return words @memoize def get_parent_until(path): """ Given a file path, determine the full module path. e.g. '/usr/lib/python2.7/dist-packages/numpy/core/__init__.pyc' yields 'numpy.core' """ dirname = osp.dirname(path) try: mod = osp.basename(path) mod = osp.splitext(mod)[0] imp.find_module(mod, [dirname]) except ImportError: return items = [mod] while 1: items.append(osp.basename(dirname)) try: dirname = osp.dirname(dirname) imp.find_module('__init__', [dirname + os.sep]) except ImportError: break return '.'.join(reversed(items)) spyder-3.2.6/spyder/utils/introspection/rope_plugin.py0000664000175000017500000002626713224121062024073 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Rope introspection plugin """ import time import imp from spyder.config.base import get_conf_path, STDERR from spyder.utils import encoding, programs from spyder.py3compat import PY2 from spyder.utils.dochelpers import getsignaturefromtext from spyder.utils import sourcecode from spyder.utils.debug import log_last_error, log_dt from spyder.utils.introspection.manager import ( DEBUG_EDITOR, LOG_FILENAME, IntrospectionPlugin) from spyder.utils.introspection.module_completion import ( get_preferred_submodules) from spyder.utils.introspection.manager import ROPE_REQVER try: try: from spyder.utils.introspection import rope_patch rope_patch.apply() except ImportError: # rope is not installed pass import rope.base.libutils import rope.contrib.codeassist except ImportError: pass #TODO: The following preferences should be customizable in the future ROPE_PREFS = {'ignore_syntax_errors': True, 'ignore_bad_imports': True, 'soa_followed_calls': 2, 'extension_modules': [], } class RopePlugin(IntrospectionPlugin): """ Rope based introspection plugin for jedi Editor's code completion, go-to-definition and help """ project = None # ---- IntrospectionPlugin API -------------------------------------------- name = 'rope' def load_plugin(self): """Load the Rope introspection plugin""" if not programs.is_module_installed('rope', ROPE_REQVER): raise ImportError('Requires Rope %s' % ROPE_REQVER) self.project = None self.create_rope_project(root_path=get_conf_path()) submods = get_preferred_submodules() actual = [] for submod in submods: try: imp.find_module(submod) actual.append(submod) except ImportError: pass if self.project is not None: self.project.prefs.set('extension_modules', actual) def get_completions(self, info): """Get a list of (completion, type) tuples using Rope""" if self.project is None: return [] filename = info['filename'] source_code = info['source_code'] offset = info['position'] # Set python path into rope project self.project.prefs.set('python_path', info['sys_path']) # Prevent Rope from returning import completions because # it can't handle them. Only Jedi can do it! lines = sourcecode.split_source(source_code[:offset]) last_line = lines[-1].lstrip() if (last_line.startswith('import ') or last_line.startswith('from ')) \ and not ';' in last_line: return [] if filename is not None: if PY2: filename = filename.encode('utf-8') else: # TODO: test if this is working without any further change in # Python 3 with a user account containing unicode characters pass try: resource = rope.base.libutils.path_to_resource(self.project, filename) except Exception as _error: if DEBUG_EDITOR: log_last_error(LOG_FILENAME, "path_to_resource: %r" % filename) resource = None try: if DEBUG_EDITOR: t0 = time.time() proposals = rope.contrib.codeassist.code_assist(self.project, source_code, offset, resource, maxfixes=3) proposals = rope.contrib.codeassist.sorted_proposals(proposals) if DEBUG_EDITOR: log_dt(LOG_FILENAME, "code_assist/sorted_proposals", t0) return [(proposal.name, proposal.type) for proposal in proposals] except Exception as _error: #analysis:ignore if DEBUG_EDITOR: log_last_error(LOG_FILENAME, "get_completion_list") return [] def get_info(self, info): """Get a formatted calltip and docstring from Rope""" if self.project is None: return filename = info['filename'] source_code = info['source_code'] offset = info['position'] # Set python path into rope project self.project.prefs.set('python_path', info['sys_path']) if filename is not None: if PY2: filename = filename.encode('utf-8') else: # TODO: test if this is working without any further change in # Python 3 with a user account containing unicode characters pass try: resource = rope.base.libutils.path_to_resource(self.project, filename) except Exception as _error: if DEBUG_EDITOR: log_last_error(LOG_FILENAME, "path_to_resource: %r" % filename) resource = None try: if DEBUG_EDITOR: t0 = time.time() cts = rope.contrib.codeassist.get_calltip( self.project, source_code, offset, resource, ignore_unknown=False, remove_self=True, maxfixes=3) if DEBUG_EDITOR: log_dt(LOG_FILENAME, "get_calltip", t0) if cts is not None: while '..' in cts: cts = cts.replace('..', '.') if '(.)' in cts: cts = cts.replace('(.)', '(...)') try: doc_text = rope.contrib.codeassist.get_doc(self.project, source_code, offset, resource, maxfixes=3) if DEBUG_EDITOR: log_dt(LOG_FILENAME, "get_doc", t0) except Exception as _error: doc_text = '' if DEBUG_EDITOR: log_last_error(LOG_FILENAME, "get_doc") return self.handle_info(cts, doc_text, source_code, offset) except Exception as _error: #analysis:ignore if DEBUG_EDITOR: log_last_error(LOG_FILENAME, "get_calltip_text") def handle_info(self, cts, doc_text, source_code, offset): obj_fullname = '' calltip = '' argspec = '' note = '' if cts: cts = cts.replace('.__init__', '') parpos = cts.find('(') if parpos: obj_fullname = cts[:parpos] obj_name = obj_fullname.split('.')[-1] cts = cts.replace(obj_fullname, obj_name) calltip = cts if ('()' in cts) or ('(...)' in cts): # Either inspected object has no argument, or it's # a builtin or an extension -- in this last case # the following attempt may succeed: calltip = getsignaturefromtext(doc_text, obj_name) if not obj_fullname: obj_fullname = sourcecode.get_primary_at(source_code, offset) if obj_fullname and not obj_fullname.startswith('self.'): # doc_text was generated by utils.dochelpers.getdoc if type(doc_text) is dict: obj_fullname = doc_text['name'] or obj_fullname argspec = doc_text['argspec'] note = doc_text['note'] doc_text = doc_text['docstring'] elif calltip: argspec_st = calltip.find('(') argspec = calltip[argspec_st:] module_end = obj_fullname.rfind('.') module = obj_fullname[:module_end] note = 'Present in %s module' % module if not doc_text and not calltip: return return dict(name=obj_fullname, argspec=argspec, note=note, docstring=doc_text, calltip=calltip) def get_definition(self, info): """Find a definition location using Rope""" if self.project is None: return filename = info['filename'] source_code = info['source_code'] offset = info['position'] # Set python path into rope project self.project.prefs.set('python_path', info['sys_path']) if filename is not None: if PY2: filename = filename.encode('utf-8') else: # TODO: test if this is working without any further change in # Python 3 with a user account containing unicode characters pass try: resource = rope.base.libutils.path_to_resource(self.project, filename) except Exception as _error: if DEBUG_EDITOR: log_last_error(LOG_FILENAME, "path_to_resource: %r" % filename) resource = None try: if DEBUG_EDITOR: t0 = time.time() resource, lineno = rope.contrib.codeassist.get_definition_location( self.project, source_code, offset, resource, maxfixes=3) if DEBUG_EDITOR: log_dt(LOG_FILENAME, "get_definition_location", t0) if resource is not None: filename = resource.real_path if filename and lineno: return filename, lineno except Exception as _error: #analysis:ignore if DEBUG_EDITOR: log_last_error(LOG_FILENAME, "get_definition_location") def validate(self): """Validate the Rope project""" if self.project is not None: try: self.project.validate(self.project.root) except RuntimeError: pass # ---- Private API ------------------------------------------------------- def create_rope_project(self, root_path): """Create a Rope project on a desired path""" if PY2: root_path = encoding.to_fs_from_unicode(root_path) else: #TODO: test if this is working without any further change in # Python 3 with a user account containing unicode characters pass try: import rope.base.project self.project = rope.base.project.Project(root_path, **ROPE_PREFS) except ImportError: print >>STDERR, 'project error' self.project = None if DEBUG_EDITOR: log_last_error(LOG_FILENAME, "create_rope_project: %r" % root_path) except TypeError: self.project = None if DEBUG_EDITOR: log_last_error(LOG_FILENAME, "create_rope_project: %r" % root_path) self.validate() def close_rope_project(self): """Close the Rope project""" if self.project is not None: self.project.close() spyder-3.2.6/spyder/utils/introspection/__init__.py0000664000175000017500000000032313026261006023273 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Introspection utilities used by Spyder """ spyder-3.2.6/spyder/utils/introspection/rope_patch.py0000664000175000017500000002271413156676663023717 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Patching rope: [1] For compatibility with Spyder's standalone version, built with py2exe or cx_Freeze [2] For better performance, see this thread: http://groups.google.com/group/rope-dev/browse_thread/thread/57de5731f202537a [3] To avoid considering folders without __init__.py as Python packages, thus avoiding side effects as non-working introspection features on a Python module or package when a folder in current directory has the same name. See this thread: http://groups.google.com/group/rope-dev/browse_thread/thread/924c4b5a6268e618 [4] To avoid rope adding a 2 spaces indent to every docstring it gets, because it breaks the work of Sphinx on the Help plugin. Also, to better control how to get calltips and docstrings of forced builtin objects. [5] To make matplotlib return its docstrings in proper rst, instead of a mix of rst and plain text. """ def apply(): """Monkey patching rope See [1], [2], [3], [4] and [5] in module docstring.""" from spyder.utils.programs import is_module_installed if is_module_installed('rope', '<0.9.4'): import rope raise ImportError("rope %s can't be patched" % rope.VERSION) # [1] Patching project.Project for compatibility with py2exe/cx_Freeze # distributions from spyder.config.base import is_py2exe_or_cx_Freeze if is_py2exe_or_cx_Freeze(): from rope.base import project class PatchedProject(project.Project): def _default_config(self): # py2exe/cx_Freeze distribution from spyder.config.base import get_module_source_path fname = get_module_source_path('spyder', 'default_config.py') return open(fname, 'rb').read() project.Project = PatchedProject # Patching pycore.PyCore... from rope.base import pycore class PatchedPyCore(pycore.PyCore): # [2] ...so that forced builtin modules (i.e. modules that were # declared as 'extension_modules' in rope preferences) will be indeed # recognized as builtins by rope, as expected # # This patch is included in rope 0.9.4+ but applying it anyway is ok def get_module(self, name, folder=None): """Returns a `PyObject` if the module was found.""" # check if this is a builtin module pymod = self._builtin_module(name) if pymod is not None: return pymod module = self.find_module(name, folder) if module is None: raise pycore.ModuleNotFoundError( 'Module %s not found' % name) return self.resource_to_pyobject(module) # [3] ...to avoid considering folders without __init__.py as Python # packages def _find_module_in_folder(self, folder, modname): module = folder packages = modname.split('.') for pkg in packages[:-1]: if module.is_folder() and module.has_child(pkg): module = module.get_child(pkg) else: return None if module.is_folder(): if module.has_child(packages[-1]) and \ module.get_child(packages[-1]).is_folder() and \ module.get_child(packages[-1]).has_child('__init__.py'): return module.get_child(packages[-1]) elif module.has_child(packages[-1] + '.py') and \ not module.get_child(packages[-1] + '.py').is_folder(): return module.get_child(packages[-1] + '.py') pycore.PyCore = PatchedPyCore # [2] Patching BuiltinName for the go to definition feature to simply work # with forced builtins from rope.base import builtins, libutils, pyobjects import inspect import os.path as osp class PatchedBuiltinName(builtins.BuiltinName): def _pycore(self): p = self.pyobject while p.parent is not None: p = p.parent if isinstance(p, builtins.BuiltinModule) and p.pycore is not None: return p.pycore def get_definition_location(self): if not inspect.isbuiltin(self.pyobject): _lines, lineno = inspect.getsourcelines(self.pyobject.builtin) path = inspect.getfile(self.pyobject.builtin) if path.endswith('pyc') and osp.isfile(path[:-1]): path = path[:-1] pycore = self._pycore() if pycore and pycore.project: resource = libutils.path_to_resource(pycore.project, path) module = pyobjects.PyModule(pycore, None, resource) return (module, lineno) return (None, None) builtins.BuiltinName = PatchedBuiltinName # [4] Patching several PyDocExtractor methods: # 1. get_doc: # To force rope to return the docstring of any object which has one, even # if it's not an instance of AbstractFunction, AbstractClass, or # AbstractModule. # Also, to use utils.dochelpers.getdoc to get docs from forced builtins. # # 2. _get_class_docstring and _get_single_function_docstring: # To not let rope add a 2 spaces indentation to every docstring, which was # breaking our rich text mode. The only value that we are modifying is the # 'indents' keyword of those methods, from 2 to 0. # # 3. get_calltip # To easily get calltips of forced builtins from rope.contrib import codeassist from spyder.utils.dochelpers import getdoc from rope.base import exceptions class PatchedPyDocExtractor(codeassist.PyDocExtractor): def get_builtin_doc(self, pyobject): buitin = pyobject.builtin return getdoc(buitin) def get_doc(self, pyobject): if hasattr(pyobject, 'builtin'): doc = self.get_builtin_doc(pyobject) return doc elif isinstance(pyobject, builtins.BuiltinModule): docstring = pyobject.get_doc() if docstring is not None: docstring = self._trim_docstring(docstring) else: docstring = '' # TODO: Add a module_name key, so that the name could appear # on the OI text filed but not be used by sphinx to render # the page doc = {'name': '', 'argspec': '', 'note': '', 'docstring': docstring } return doc elif isinstance(pyobject, pyobjects.AbstractFunction): return self._get_function_docstring(pyobject) elif isinstance(pyobject, pyobjects.AbstractClass): return self._get_class_docstring(pyobject) elif isinstance(pyobject, pyobjects.AbstractModule): return self._trim_docstring(pyobject.get_doc()) elif pyobject.get_doc() is not None: # Spyder patch return self._trim_docstring(pyobject.get_doc()) return None def get_calltip(self, pyobject, ignore_unknown=False, remove_self=False): if hasattr(pyobject, 'builtin'): doc = self.get_builtin_doc(pyobject) return doc['name'] + doc['argspec'] try: if isinstance(pyobject, pyobjects.AbstractClass): pyobject = pyobject['__init__'].get_object() if not isinstance(pyobject, pyobjects.AbstractFunction): pyobject = pyobject['__call__'].get_object() except exceptions.AttributeNotFoundError: return None if ignore_unknown and not isinstance(pyobject, pyobjects.PyFunction): return if isinstance(pyobject, pyobjects.AbstractFunction): result = self._get_function_signature(pyobject, add_module=True) if remove_self and self._is_method(pyobject): return result.replace('(self)', '()').replace('(self, ', '(') return result def _get_class_docstring(self, pyclass): contents = self._trim_docstring(pyclass.get_doc(), indents=0) supers = [super.get_name() for super in pyclass.get_superclasses()] doc = 'class %s(%s):\n\n' % (pyclass.get_name(), ', '.join(supers)) + contents if '__init__' in pyclass: init = pyclass['__init__'].get_object() if isinstance(init, pyobjects.AbstractFunction): doc += '\n\n' + self._get_single_function_docstring(init) return doc def _get_single_function_docstring(self, pyfunction): docs = pyfunction.get_doc() docs = self._trim_docstring(docs, indents=0) return docs codeassist.PyDocExtractor = PatchedPyDocExtractor # [5] Get the right matplotlib docstrings for Help try: import matplotlib as mpl mpl.rcParams['docstring.hardcopy'] = True except: pass spyder-3.2.6/spyder/utils/sourcecode.py0000664000175000017500000002010013224740762020775 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Source code text utilities """ import re import os import sys from spyder.py3compat import PY2 if PY2: from itertools import izip as zip # Order is important: EOL_CHARS = (("\r\n", 'nt'), ("\n", 'posix'), ("\r", 'mac')) ALL_LANGUAGES = { 'Python': ('py', 'pyw', 'python', 'ipy'), 'Cython': ('pyx', 'pxi', 'pxd'), 'Enaml': ('enaml',), 'Fortran77': ('f', 'for', 'f77'), 'Fortran': ('f90', 'f95', 'f2k'), 'Idl': ('pro',), 'Diff': ('diff', 'patch', 'rej'), 'GetText': ('po', 'pot'), 'Nsis': ('nsi', 'nsh'), 'Html': ('htm', 'html'), 'Cpp': ('c', 'cc', 'cpp', 'cxx', 'h', 'hh', 'hpp', 'hxx'), 'OpenCL': ('cl',), 'Yaml':('yaml','yml'), "Markdown": ('md', 'mdw'), } PYTHON_LIKE_LANGUAGES = ('Python', 'Cython', 'Enaml') CELL_LANGUAGES = {'Python': ('#%%', '# %%', '# ', '# In[')} def get_eol_chars(text): """Get text EOL characters""" for eol_chars, _os_name in EOL_CHARS: if text.find(eol_chars) > -1: return eol_chars def get_os_name_from_eol_chars(eol_chars): """Return OS name from EOL characters""" for chars, os_name in EOL_CHARS: if eol_chars == chars: return os_name def get_eol_chars_from_os_name(os_name): """Return EOL characters from OS name""" for eol_chars, name in EOL_CHARS: if name == os_name: return eol_chars def has_mixed_eol_chars(text): """Detect if text has mixed EOL characters""" eol_chars = get_eol_chars(text) if eol_chars is None: return False correct_text = eol_chars.join((text+eol_chars).splitlines()) return repr(correct_text) != repr(text) def fix_indentation(text): """Replace tabs by spaces""" return text.replace('\t', ' '*4) def is_builtin(text): """Test if passed string is the name of a Python builtin object""" from spyder.py3compat import builtins return text in [str(name) for name in dir(builtins) if not name.startswith('_')] def is_keyword(text): """Test if passed string is the name of a Python keyword""" import keyword return text in keyword.kwlist def get_primary_at(source_code, offset, retry=True): """Return Python object in *source_code* at *offset* Periods to the left of the cursor are carried forward e.g. 'functools.par^tial' would yield 'functools.partial' Retry prevents infinite recursion: retry only once """ obj = '' left = re.split(r"[^0-9a-zA-Z_.]", source_code[:offset]) if left and left[-1]: obj = left[-1] right = re.split(r"\W", source_code[offset:]) if right and right[0]: obj += right[0] if obj and obj[0].isdigit(): obj = '' # account for opening chars with no text to the right if not obj and retry and offset and source_code[offset - 1] in '([.': return get_primary_at(source_code, offset - 1, retry=False) return obj def split_source(source_code): '''Split source code into lines ''' eol_chars = get_eol_chars(source_code) if eol_chars: return source_code.split(eol_chars) else: return [source_code] def get_identifiers(source_code): '''Split source code into python identifier-like tokens''' tokens = set(re.split(r"[^0-9a-zA-Z_.]", source_code)) valid = re.compile(r'[a-zA-Z_]') return [token for token in tokens if re.match(valid, token)] def path_components(path): """ Return the individual components of a given file path string (for the local operating system). Taken from http://stackoverflow.com/q/21498939/438386 """ components = [] # The loop guarantees that the returned components can be # os.path.joined with the path separator and point to the same # location: while True: (new_path, tail) = os.path.split(path) # Works on any platform components.append(tail) if new_path == path: # Root (including drive, on Windows) reached break path = new_path components.append(new_path) components.reverse() # First component first return components def differentiate_prefix(path_components0, path_components1): """ Return the differentiated prefix of the given two iterables. Taken from http://stackoverflow.com/q/21498939/438386 """ longest_prefix = [] root_comparison = False common_elmt = None for index, (elmt0, elmt1) in enumerate(zip(path_components0, path_components1)): if elmt0 != elmt1: if index == 2: root_comparison = True break else: common_elmt = elmt0 longest_prefix.append(elmt0) file_name_length = len(path_components0[len(path_components0) - 1]) path_0 = os.path.join(*path_components0)[:-file_name_length - 1] if len(longest_prefix) > 0: longest_path_prefix = os.path.join(*longest_prefix) longest_prefix_length = len(longest_path_prefix) + 1 if path_0[longest_prefix_length:] != '' and not root_comparison: path_0_components = path_components(path_0[longest_prefix_length:]) if path_0_components[0] == ''and path_0_components[1] == ''and len( path_0[longest_prefix_length:]) > 20: path_0_components.insert(2, common_elmt) path_0 = os.path.join(*path_0_components) else: path_0 = path_0[longest_prefix_length:] elif not root_comparison: path_0 = common_elmt elif sys.platform.startswith('linux') and path_0 == '': path_0 = '/' return path_0 def disambiguate_fname(files_path_list, filename): """Get tab title without ambiguation.""" fname = os.path.basename(filename) same_name_files = get_same_name_files(files_path_list, fname) if len(same_name_files) > 1: compare_path = shortest_path(same_name_files) if compare_path == filename: same_name_files.remove(path_components(filename)) compare_path = shortest_path(same_name_files) diff_path = differentiate_prefix(path_components(filename), path_components(compare_path)) diff_path_length = len(diff_path) path_component = path_components(diff_path) if (diff_path_length > 20 and len(path_component) > 2): if path_component[0] != '/' and path_component[0] != '': path_component = [path_component[0], '...', path_component[-1]] else: path_component = [path_component[2], '...', path_component[-1]] diff_path = os.path.join(*path_component) fname = fname + " - " + diff_path return fname def get_same_name_files(files_path_list, filename): """Get a list of the path components of the files with the same name.""" same_name_files = [] for fname in files_path_list: if filename == os.path.basename(fname): same_name_files.append(path_components(fname)) return same_name_files def shortest_path(files_path_list): """Shortest path between files in the list.""" if len(files_path_list) > 0: shortest_path = files_path_list[0] shortest_path_length = len(files_path_list[0]) for path_elmts in files_path_list: if len(path_elmts) < shortest_path_length: shortest_path_length = len(path_elmts) shortest_path = path_elmts return os.path.join(*shortest_path) spyder-3.2.6/spyder/utils/help/0000775000175000017500000000000013225025007017214 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/utils/help/js/0000775000175000017500000000000013225025007017630 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/utils/help/js/copy_button.js0000664000175000017500000000556413026261006022545 0ustar carloscarlos00000000000000//---------------------------------------------------------------------------- // Copy Button // // Add a [>>>] button on the top-right corner of code samples to hide // the >>> and ... prompts and the output and thus make the code // copyable. // // Taken from http://docs.python.org/_static/copybutton.js //---------------------------------------------------------------------------- //============================================================================ // On document ready //============================================================================ $(document).ready(function() { var div = $('.highlight-python .highlight,' + '.highlight-python3 .highlight') var pre = div.find('pre'); // get the styles from the current theme pre.parent().parent().css('position', 'relative'); var hide_text = 'Hide the prompts and output'; var show_text = 'Show the prompts and output'; var border_width = pre.css('border-top-width'); var border_style = pre.css('border-top-style'); var border_color = pre.css('border-top-color'); var button_styles = { 'cursor':'pointer', 'position': 'absolute', 'top': '0', 'right': '0', 'border-color': border_color, 'border-style': border_style, 'border-width': border_width, 'color': border_color, 'text-size': '75%', 'font-family': 'monospace', 'padding-left': '0.2em', 'padding-right': '0.2em', 'margin-right': '10px', 'border-top-right-radius': '4px' } // create and add the button to all the code blocks that contain >>> div.each(function(index) { var jthis = $(this); if (jthis.find('.gp').length > 0) { var button = $('>>>'); button.css(button_styles) button.attr('title', hide_text); jthis.prepend(button); } // tracebacks (.gt) contain bare text elements that need to be // wrapped in a span to work with .nextUntil() (see later) jthis.find('pre:has(.gt)').contents().filter(function() { return ((this.nodeType == 3) && (this.data.trim().length > 0)); }).wrap(''); }); // define the behavior of the button when it's clicked $('.copybutton').toggle( function() { var button = $(this); button.parent().find('.go, .gp, .gt').hide(); button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'hidden'); button.css('text-decoration', 'line-through'); button.attr('title', show_text); }, function() { var button = $(this); button.parent().find('.go, .gp, .gt').show(); button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'visible'); button.css('text-decoration', 'none'); button.attr('title', hide_text); }); }); spyder-3.2.6/spyder/utils/help/js/fix_image_paths.js0000664000175000017500000000127113026261006023316 0ustar carloscarlos00000000000000//---------------------------------------------------------------------------- // Set absolute path for images // // Copyright (c) Spyder Project Contributors // // Distributed under the terms of the MIT License //---------------------------------------------------------------------------- //============================================================================ // On document ready //============================================================================ $(document).ready(function () { $('img').attr('src', function(index, attr){ var path = attr.split('/') var img_name = path.reverse()[0] return 'file:///{{img_path}}' + '/' + img_name }); }); spyder-3.2.6/spyder/utils/help/js/math_config.js0000664000175000017500000000447113026261006022452 0ustar carloscarlos00000000000000//---------------------------------------------------------------------------- // Math configuration options and hacks // // Copyright (C) Spyder Project Contributors // // Distributed under the terms of the MIT License. //---------------------------------------------------------------------------- //============================================================================ // On document ready //============================================================================ {% if right_sphinx_version and math_on %} $(document).ready(function () { // MathJax config // -------------- MathJax.Hub.Config({ // We are using SVG instead of HTML-CSS because the last one gives // troubles on QtWebkit. See this thread: // https://groups.google.com/forum/?fromgroups#!topic/mathjax-users/HKA2lNqv-OQ jax: ["input/TeX", "output/SVG"], // Menu options are not working. It would be useful to have 'Show TeX // commands', but it opens an external browser pointing to css_path. // I don't know why that's happening showMathMenu: false, messageStyle: "none", "SVG": { blacker: 1 }, {% if platform == 'win32' %} // Change math preview size so that it doesn't look too big while // redendered styles: { ".MathJax_Preview": { color: "#888", "font-size": "55%" } } {% endif %} }); // MathJax Hooks // ------------- // Put here any code that needs to be evaluated after MathJax has been // fully loaded MathJax.Hub.Register.StartupHook("End", function () { // Eliminate unnecessary margin-bottom for inline math $('span.math svg').css('margin-bottom', '0px'); }); {% if platform == 'win32' %} // Windows fix // ----------- // Increase font size of math elements because they appear too small // compared to the surrounding text. // Use this hack because MathJax 'scale' option seems to not be working // for SVG. $('.math').css("color", "transparent"); $('.math').css("fontSize", "213%"); {% endif %} }); {% else %} $(document).ready(function () { // Show math in monospace $('.math').css('font-family', 'monospace'); }); {% endif %} spyder-3.2.6/spyder/utils/help/js/utils.js0000664000175000017500000000266713026261006021341 0ustar carloscarlos00000000000000//---------------------------------------------------------------------------- // Several utility functions to modify docstring webpages while they are // rendered // // Copyright (C) Spyder Project Contributors // // Distributed under the terms of the MIT License. //---------------------------------------------------------------------------- //============================================================================ // On document ready //============================================================================ $(document).ready(function () { // Remove anchor header links. // They're used by Sphinx to create crossrefs, so we don't need them $('a.headerlink').remove(); // If the first child in the docstring div is a section, change its class // to title. This means that the docstring has a real title and we need // to use it. // This is really useful to show module docstrings. var first_doc_child = $('div.docstring').children(':first-child'); if( first_doc_child.is('div.section') && $('div.title').length == 0 ) { first_doc_child.removeClass('section').addClass('title'); }; // Change docstring headers from h1 to h2 // It can only be an h1 and that's the page title // Taken from http://forum.jquery.com/topic/how-to-replace-h1-h2 $('div.docstring').find('div.section h1').replaceWith(function () { return '

    ' + $(this).text() + '

    '; }); }); spyder-3.2.6/spyder/utils/help/js/collapse_sections.js0000664000175000017500000000421113026261006023675 0ustar carloscarlos00000000000000//---------------------------------------------------------------------------- // Toggleable sections // // Added expand/collapse functionality to RST sections. // Code from the Cloud Sphinx theme // // Copyright 2011-2012 by Assurance Technologies // // Distributed under the terms of the BSD License //---------------------------------------------------------------------------- //============================================================================ // On document ready //============================================================================ $(document).ready(function (){ function init(){ // get header & section, and add static classes var header = $(this); var section = header.parent(); header.addClass("html-toggle-button"); // helper to test if url hash is within this section function contains_hash(){ var hash = document.location.hash; return hash && (section[0].id == hash.substr(1) || section.find(hash.replace(/\./g,"\\.")).length>0); } // helper to control toggle state function set_state(expanded){ if(expanded){ section.addClass("expanded").removeClass("collapsed"); section.children().show(); }else{ section.addClass("collapsed").removeClass("expanded"); section.children().hide(); section.children("span:first-child:empty").show(); /* for :ref: span tag */ header.show(); } } // initialize state set_state(section.hasClass("expanded") || contains_hash()); // bind toggle callback header.click(function (){ section.children().next().slideToggle(300); set_state(!section.hasClass("expanded")); $(window).trigger('cloud-section-toggled', section[0]); }); // open section if user jumps to it from w/in page $(window).bind("hashchange", function () { if(contains_hash()) { var link = document.location.hash; $(link).parents().each(set_state, [true]); set_state(true); $('html, body').animate({ scrollTop: $(link).offset().top }, 'fast'); } }); } $(".section > h2, .section > h3, .section > h4").each(init); }); spyder-3.2.6/spyder/utils/help/js/move_outline.js0000664000175000017500000000116213026261006022673 0ustar carloscarlos00000000000000//---------------------------------------------------------------------------- // Move Outline section to be the first one // // Copyright (c) Spyder Project Contributors // // Distributed under the terms of the MIT License //---------------------------------------------------------------------------- //============================================================================ // On document ready //============================================================================ $(document).ready(function (){ var first_section_id = $(".section")[0].id; $("#outline").insertBefore("#" + first_section_id); }); spyder-3.2.6/spyder/utils/help/sphinxify.py0000664000175000017500000002074213026261006021614 0ustar carloscarlos00000000000000# -*- coding: utf-8 -* """ Process docstrings with Sphinx AUTHORS: - Tim Joseph Dumol (2009-09-29): initial version - The Spyder Project Contributors: Several changes to make it work with Spyder Copyright (C) 2009 Tim Dumol Copyright (C) Spyder Project Contributors Distributed under the terms of the BSD License Taken from the Sage project (www.sagemath.org). See here for the original version: www.sagemath.org/doc/reference/sagenb/misc/sphinxify.html """ # Stdlib imports import codecs import os import os.path as osp import shutil import sys from tempfile import mkdtemp from xml.sax.saxutils import escape # 3rd party imports from docutils.utils import SystemMessage as SystemMessage from jinja2 import Environment, FileSystemLoader import sphinx from sphinx.application import Sphinx # Local imports from spyder.config.base import (_, get_module_data_path, get_module_source_path) from spyder.utils import encoding #----------------------------------------------------------------------------- # Globals and constants #----------------------------------------------------------------------------- # Note: we do not use __file__ because it won't be working in the stand-alone # version of Spyder (i.e. the py2exe or cx_Freeze build) CONFDIR_PATH = get_module_source_path('spyder.utils.help') CSS_PATH = osp.join(CONFDIR_PATH, 'static', 'css') JS_PATH = osp.join(CONFDIR_PATH, 'js') # To let Debian packagers redefine the MathJax and JQuery locations so they can # use their own packages for them. See Issue 1230, comment #7. MATHJAX_PATH = get_module_data_path('spyder', relpath=osp.join('utils', 'help', JS_PATH, 'mathjax'), attr_name='MATHJAXPATH') JQUERY_PATH = get_module_data_path('spyder', relpath=osp.join('utils', 'help', JS_PATH), attr_name='JQUERYPATH') #----------------------------------------------------------------------------- # Utility functions #----------------------------------------------------------------------------- def is_sphinx_markup(docstring): """Returns whether a string contains Sphinx-style ReST markup.""" # this could be made much more clever return ("`" in docstring or "::" in docstring) def warning(message): """Print a warning message on the rich text view""" env = Environment() env.loader = FileSystemLoader(osp.join(CONFDIR_PATH, 'templates')) warning = env.get_template("warning.html") return warning.render(css_path=CSS_PATH, text=message) def usage(title, message, tutorial_message, tutorial): """Print a usage message on the rich text view""" env = Environment() env.loader = FileSystemLoader(osp.join(CONFDIR_PATH, 'templates')) usage = env.get_template("usage.html") return usage.render(css_path=CSS_PATH, title=title, intro_message=message, tutorial_message=tutorial_message, tutorial=tutorial) def generate_context(name='', argspec='', note='', math=False, collapse=False, img_path=''): """ Generate the html_context dictionary for our Sphinx conf file. This is a set of variables to be passed to the Jinja template engine and that are used to control how the webpage is rendered in connection with Sphinx Parameters ---------- name : str Object's name. note : str A note describing what type has the function or method being introspected argspec : str Argspec of the the function or method being introspected math : bool Turn on/off Latex rendering on the OI. If False, Latex will be shown in plain text. collapse : bool Collapse sections img_path : str Path for images relative to the file containing the docstring Returns ------- A dict of strings to be used by Jinja to generate the webpage """ if img_path and os.name == 'nt': img_path = img_path.replace('\\', '/') context = \ { # Arg dependent variables 'math_on': 'true' if math else '', 'name': name, 'argspec': argspec, 'note': note, 'collapse': collapse, 'img_path': img_path, # Static variables 'css_path': CSS_PATH, 'js_path': JS_PATH, 'jquery_path': JQUERY_PATH, 'mathjax_path': MATHJAX_PATH, 'right_sphinx_version': '' if sphinx.__version__ < "1.1" else 'true', 'platform': sys.platform } return context def sphinxify(docstring, context, buildername='html'): """ Runs Sphinx on a docstring and outputs the processed documentation. Parameters ---------- docstring : str a ReST-formatted docstring context : dict Variables to be passed to the layout template to control how its rendered (through the Sphinx variable *html_context*). buildername: str It can be either `html` or `text`. Returns ------- An Sphinx-processed string, in either HTML or plain text format, depending on the value of `buildername` """ srcdir = mkdtemp() srcdir = encoding.to_unicode_from_fs(srcdir) base_name = osp.join(srcdir, 'docstring') rst_name = base_name + '.rst' if buildername == 'html': suffix = '.html' else: suffix = '.txt' output_name = base_name + suffix # This is needed so users can type \\ on latex eqnarray envs inside raw # docstrings if context['right_sphinx_version'] and context['math_on']: docstring = docstring.replace('\\\\', '\\\\\\\\') # Add a class to several characters on the argspec. This way we can # highlight them using css, in a similar way to what IPython does. # NOTE: Before doing this, we escape common html chars so that they # don't interfere with the rest of html present in the page argspec = escape(context['argspec']) for char in ['=', ',', '(', ')', '*', '**']: argspec = argspec.replace(char, '' + char + '') context['argspec'] = argspec doc_file = codecs.open(rst_name, 'w', encoding='utf-8') doc_file.write(docstring) doc_file.close() temp_confdir = False if temp_confdir: # TODO: This may be inefficient. Find a faster way to do it. confdir = mkdtemp() confdir = encoding.to_unicode_from_fs(confdir) generate_configuration(confdir) else: confdir = osp.join(get_module_source_path('spyder.utils.help')) confoverrides = {'html_context': context} doctreedir = osp.join(srcdir, 'doctrees') sphinx_app = Sphinx(srcdir, confdir, srcdir, doctreedir, buildername, confoverrides, status=None, warning=None, freshenv=True, warningiserror=False, tags=None) try: sphinx_app.build(None, [rst_name]) except SystemMessage: output = _("It was not possible to generate rich text help for this " "object.
    " "Please see it in plain text.") return warning(output) # TODO: Investigate if this is necessary/important for us if osp.exists(output_name): output = codecs.open(output_name, 'r', encoding='utf-8').read() output = output.replace('
    ', '
    ')
        else:
            output = _("It was not possible to generate rich text help for this "
                        "object.
    " "Please see it in plain text.") return warning(output) if temp_confdir: shutil.rmtree(confdir, ignore_errors=True) shutil.rmtree(srcdir, ignore_errors=True) return output def generate_configuration(directory): """ Generates a Sphinx configuration in `directory`. Parameters ---------- directory : str Base directory to use """ # conf.py file for Sphinx conf = osp.join(get_module_source_path('spyder.utils.help'), 'conf.py') # Docstring layout page (in Jinja): layout = osp.join(osp.join(CONFDIR_PATH, 'templates'), 'layout.html') os.makedirs(osp.join(directory, 'templates')) os.makedirs(osp.join(directory, 'static')) shutil.copy(conf, directory) shutil.copy(layout, osp.join(directory, 'templates')) open(osp.join(directory, '__init__.py'), 'w').write('') open(osp.join(directory, 'static', 'empty'), 'w').write('') spyder-3.2.6/spyder/utils/help/conf.py0000664000175000017500000000757613224121062020527 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright (C) 2009 Tim Dumol # Copyright (C) Spyder Project Contributors # Distributed under the terms of the BSD License """Sphinx conf file for the Help plugin rich text mode""" # 3rd party imports from sphinx import __version__ as sphinx_version # Local imports from spyder.config.main import CONF #============================================================================== # General configuration #============================================================================== # If your extensions are in another directory, add it here. If the directory # is relative to the documentation root, use os.path.abspath to make it # absolute, like shown here. #sys.path.append(os.path.abspath('.')) # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. # We need jsmath to get pretty plain-text latex in docstrings math = CONF.get('help', 'math', '') if sphinx_version < "1.1" or not math: extensions = ['sphinx.ext.jsmath'] else: extensions = ['sphinx.ext.mathjax'] # For scipy and matplotlib docstrings, which need this extension to # be rendered correctly (see Issue 1138) extensions.append('sphinx.ext.autosummary') # Add any paths that contain templates here, relative to this directory. templates_path = ['templates'] # MathJax load path (doesn't have effect for sphinx 1.0-) mathjax_path = 'MathJax/MathJax.js' # JsMath load path (doesn't have effect for sphinx 1.1+) jsmath_path = 'easy/load.js' # The suffix of source filenames. source_suffix = '.rst' # The master toctree document. master_doc = 'docstring' # General information about the project. project = u"Spyder Help plugin" copyright = u'The Spyder Project Contributors' # List of directories, relative to source directory, that shouldn't be searched # for source files. exclude_trees = ['.build'] # The reST default role (used for this markup: `text`) to use for all documents. # # TODO: This role has to be set on a per project basis, i.e. numpy, sympy, # mpmath, etc, use different default_role's which give different rendered # docstrings. Setting this to None until it's solved. default_role = 'None' # If true, '()' will be appended to :func: etc. cross-reference text. add_function_parentheses = True # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' #============================================================================== # Options for HTML output #============================================================================== # The style sheet to use for HTML and HTML Help pages. A file of that name # must exist either in Sphinx' static/ path, or in one of the custom paths # given in html_static_path. html_style = 'default.css' # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". html_title = None # A shorter title for the navigation bar. Default is the same as html_title. html_short_title = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['static'] # A dictionary of values to pass into the template engine’s context for all # pages html_context = {} # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. # Spyder: Disabled to fix conflict with qtwebview and mathjax. See issue #5514 html_use_smartypants = False # If false, no module index is generated. html_use_modindex = False # If false, no index is generated. html_use_index = False # If true, the index is split into individual pages for each letter. html_split_index = False # If true, the reST sources are included in the HTML build as _sources/. html_copy_source = False spyder-3.2.6/spyder/utils/help/templates/0000775000175000017500000000000013225025007021212 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/utils/help/templates/usage.html0000664000175000017500000000163413026261006023210 0ustar carloscarlos00000000000000{# usage.html ~~~~~~~~~~ A simple page to inform users how to get help on the Help plugin :copyright: Copyright (c) Spyder Project Contributors. :license: MIT license #}
    {{title}}
    {{intro_message}}


    {{tutorial_message}} {{tutorial}}
    spyder-3.2.6/spyder/utils/help/templates/warning.html0000664000175000017500000000113613026261006023546 0ustar carloscarlos00000000000000{# warning.html ~~~~~~~~~~~ A simple page to emit a warning when no docstring text was found for the one a user was looking for :copyright: Copyright (c) Spyder Project Contributors :license: MIT license #}
    {{text}}
    spyder-3.2.6/spyder/utils/help/templates/layout.html0000664000175000017500000000465113026261006023423 0ustar carloscarlos00000000000000{# layout.html ~~~~~~~~~~~ Layout template for the Help plugin :copyright: Copyright (c) Spyder Project Contributors. :copyright: Copyright 2009 by Tim Dumol :license: BSD license #} {% if right_sphinx_version and math_on %} {# DON'T try to load MathJax from the net. It's slow and sometimes gives errors. See this thread for more info: http://tex.stackexchange.com/questions/2692/comparing-mathjax-and-mathml #} {% endif %} {% if collapse %} {% endif %} {% if img_path %} {% endif %} {# Docstring header #} {% if name %}

    {{name}}

    {% if argspec or note %} {% endif %} {% endif %} {# Docstring text #}
    {% block body %}{% endblock %} {% if collapse %}

    Outline

    {{ toc }}
    {% endif %}
    spyder-3.2.6/spyder/utils/help/static/0000775000175000017500000000000013225025007020503 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/utils/help/static/css/0000775000175000017500000000000013225025007021273 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/utils/help/static/css/pygments.css0000664000175000017500000000623013026261006023654 0ustar carloscarlos00000000000000.hll { background-color: #ffffcc } .c { color: #408090; font-style: italic } /* Comment */ .err { border: 1px solid #FF0000 } /* Error */ .k { color: #007020; font-weight: bold } /* Keyword */ .o { color: #666666 } /* Operator */ .cm { color: #408090; font-style: italic } /* Comment.Multiline */ .cp { color: #007020 } /* Comment.Preproc */ .c1 { color: #408090; font-style: italic } /* Comment.Single */ .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ .gd { color: #A00000 } /* Generic.Deleted */ .ge { font-style: italic } /* Generic.Emph */ .gr { color: #FF0000 } /* Generic.Error */ .gh { color: #000080; font-weight: bold } /* Generic.Heading */ .gi { color: #00A000 } /* Generic.Inserted */ .go { color: #303030 } /* Generic.Output */ .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ .gs { font-weight: bold } /* Generic.Strong */ .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ .gt { color: #0040D0 } /* Generic.Traceback */ .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ .kp { color: #007020 } /* Keyword.Pseudo */ .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ .kt { color: #902000 } /* Keyword.Type */ .m { color: #208050 } /* Literal.Number */ .s { color: #4070a0 } /* Literal.String */ .na { color: #4070a0 } /* Name.Attribute */ .nb { color: #007020 } /* Name.Builtin */ .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ .no { color: #60add5 } /* Name.Constant */ .nd { color: #555555; font-weight: bold } /* Name.Decorator */ .ni { color: #d55537; font-weight: bold } /* Name.Entity */ .ne { color: #007020 } /* Name.Exception */ .nf { color: #06287e } /* Name.Function */ .nl { color: #002070; font-weight: bold } /* Name.Label */ .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ .nt { color: #062873; font-weight: bold } /* Name.Tag */ .nv { color: #bb60d5 } /* Name.Variable */ .ow { color: #007020; font-weight: bold } /* Operator.Word */ .w { color: #bbbbbb } /* Text.Whitespace */ .mf { color: #208050 } /* Literal.Number.Float */ .mh { color: #208050 } /* Literal.Number.Hex */ .mi { color: #208050 } /* Literal.Number.Integer */ .mo { color: #208050 } /* Literal.Number.Oct */ .sb { color: #4070a0 } /* Literal.String.Backtick */ .sc { color: #4070a0 } /* Literal.String.Char */ .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ .s2 { color: #4070a0 } /* Literal.String.Double */ .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ .sh { color: #4070a0 } /* Literal.String.Heredoc */ .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ .sx { color: #c65d09 } /* Literal.String.Other */ .sr { color: #235388 } /* Literal.String.Regex */ .s1 { color: #4070a0 } /* Literal.String.Single */ .ss { color: #517918 } /* Literal.String.Symbol */ .bp { color: #007020 } /* Name.Builtin.Pseudo */ .vc { color: #bb60d5 } /* Name.Variable.Class */ .vg { color: #bb60d5 } /* Name.Variable.Global */ .vi { color: #bb60d5 } /* Name.Variable.Instance */ .il { color: #208050 } /* Literal.Number.Integer.Long */spyder-3.2.6/spyder/utils/help/static/css/default.css0000664000175000017500000001614413026261006023437 0ustar carloscarlos00000000000000body { background-color: white; color: rgb(51, 51, 51); margin: 0px 25px 15px 25px; } /* --- Title style --- */ div.title h1 { font-size: 180%; font-family: 'Trebuchet MS', sans-serif; background-color: #6487DC; background-image: -webkit-gradient( linear, 0 0, 0 100%, from(#54b4eb), color-stop(60%, #2fa4e7), to(#1d9ce5) ); text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.2); font-weight: normal; padding: 6px 0px 6px 20px; margin: 0px -25px; color: #FFFFFF; } /* * The next two styles are needed to * modify the anchors present on the * title of pages like scipy.stats or * scipy.io */ div.title h1 a { color: transparent; cursor: default; } div.title h1 tt { font-size: 95%; background-color: transparent; color: #FFFFFF; } /* --- Metadata style --- */ div.metadata { margin-top: 10px; margin-bottom: 15px; margin-right: 1px; padding: 1px; background-color: #EEEEEE; border: 1px solid #C9C9C9; border-radius: 6px 6px 6px 6px; box-shadow: 1px 1px 7px #CACACA; } div.metadata p { margin: 7px 0px 7px 10px; } span.def { font-family: monospace; font-size: 90%; } span.argspec-highlight { color: red; font-size: 110%; font-weight: 900; } /* --- Docstring div style --- */ div.docstring { margin-top: -1px; } div.docstring p { padding: 0px 2px 0px; } /* --- Headers style --- */ h2, h3, h4 { font-family: 'Helvetica', sans-serif; color: rgb(49, 126, 172); margin-top: 20px; margin-bottom: 10px; } h2 { font-size: 140%; font-weight: normal; border-bottom: 1px solid rgb(220, 220, 220); padding: 4px 0px 4px 0px; } h3 { font-size: 115%; } h4 { font-size: 100%; margin-top: 14px; font-weight: normal; } h2.html-toggle-button, h3.html-toggle-button, h4.html-toggle-button { padding-left: 20px; } .collapsed > h2, .collapsed > h3, .collapsed > h4, .expanded > h2, .expanded > h3, .expanded > h4 { background-color: transparent; background-image: url(../images/collapse_expand.png); background-repeat: no-repeat; background-attachment: scroll; cursor: pointer; } .collapsed > h2 { background-position: 2px 7px; } .collapsed > h3 { background-position: 2px 2px; } .collapsed > h4 { background-position: 2px 0px; } .expanded > h2 { background-position: 0px -31px; } .expanded > h3 { background-position: 0px -38px; } .expanded > h4 { background-position: 0px -39px; } dl.docutils { padding: 0px 10px 0px; } div.section p { padding: 0px 2px 0px; } #warning { margin-top: 5px; background-color: #FFE4E4; border: 1px solid #F66; padding: 4px 8px 4px 8px; text-align: center; } #doc-warning { margin-top: 16px; width: 45%; margin-left: auto; margin-right: auto; color: rgb(185, 74, 72); background-color: rgb(242, 222, 222); border: 1px solid rgb(238, 211, 215); border-radius: 4px 4px 4px 4px; padding: 15px; text-align: center; font-weight: bold; font-size: 105%; } /* --- Links --- */ a { text-decoration: none; color: rgba(40, 130, 180, 1); } a:hover { text-decoration: underline; } /* --- Images --- */ img { box-shadow: 0px 2px 6px #cacaca; border: 1px solid #c9c9c9; } img.align-center { display: block; margin-left: auto; margin-right: auto; } /* --- Lists style --- */ ol.arabic { margin-left: -10px; } ul { margin-left: -5px; } /* --- Literal blocks style --- */ pre.literal-block { padding-left: 35px; font-size: 95%; } /* --- Docutils table style --- */ table.docutils { border-collapse: collapse; border-spacing: 0; border: #DDDDDD; margin-left: auto; margin-right: auto; margin-top: 17px; margin-bottom: 17px; width: 90%; } table.docutils td { padding: 5px; } table.docutils tr.row-odd { background-color: rgb(249, 249, 249); } /* --- Docutils table headers --- */ table.docutils th { background-color: #EEEEEE; border-bottom-color: #DDDDDD; border-bottom-style: solid; border-bottom-width: 1px; border-top-color: #DDDDDD; border-top-style: solid; border-top-width: 1px; font-weight: bold; text-align: center; padding: 6px 0px 6px 8px; color: rgb(65, 65, 65); } /* --- Field-list table style --- */ table.docutils.field-list { font-size: 80%; border-collapse: collapse; border-left: transparent; border-right: transparent; margin-top: 15px; margin-left: 40px; width: 83%; } /* --- Field-list table headers --- */ table.docutils.field-list th { background-color: transparent; border-top: transparent; border-bottom: transparent; color: black; font-weight: bold; text-align: left; padding: 4px 0px 4px 8px; } /* --- Spacing around example code --- */ div.highlight pre { padding: 9px 14px; background-color: rgb(247, 247, 249); border-radius: 4px 4px 4px 4px; border: 1px solid rgb(225, 225, 232); } div.highlight { padding: 0px 10px 0px; } dt { font-weight: bold; /*font-size: 16px;*/ } .classifier { /*font-size: 10pt;*/ font-weight: normal; } tt { background-color: #ECF0F3; /*font-size: 95%;*/ padding: 0px 1px; } div.admonition.note { font-size: 0.95em; margin: 1.3em; border: 1px solid #BCE8F1; background-color: #D9EDF7; padding: 0px 5px 0 5px; color: #3A87AD; } div.admonition p.admonition-title { font-size: 1em; margin-top: 7px; font-weight: bold; } /* ----------- Panels ----------- */ .panel { margin-top: 15px; background-color: #ffffff; border: 1px solid transparent; border-radius: 4px; box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); } .panel-heading { padding: 10px 15px; border-bottom: 1px solid transparent; border-top-right-radius: 3px; border-top-left-radius: 3px; } .panel-title { margin-top: 0; margin-bottom: 0; font-size: 110%; color: rgb(255,255,255); } .panel-body { padding: 15px; } .panel-usage { border-color: #2fa4e7; margin-top: 15px; width: 60%; margin-left: auto; margin-right: auto; } .panel-usage > .panel-heading { color: #ffffff; background-color: #2fa4e7; border-color: #2fa4e7; } .panel-usage > .panel-body > br { display: block; margin: 12px 0; content: ""; } .hr { background-color: rgb(200, 200, 200); height: 1px; } /* ----------- IPython console styles ----------- */ /* --- Loading --- */ .loading { position: absolute; margin: -20px 0 0 -95px; width: 180px; height: auto; left: 50%; top: 50%; background-color: #EEEEEE; border: 1px solid #C9C9C9; border-radius: 6px; box-shadow: 0px 0px 7px #CACACA; color: #333333; padding: 12px; text-align: center; } #loading-image { float: left; } #loading-message { margin-left: 23px; } /* --- Kernel error messages --- */ .panel-danger { border-color: #eed3d7; } .panel-danger > .panel-heading { color: #b94a48; background-color: #f2dede; border-color: #eed3d7; background-color: rgb(199, 28, 34); } spyder-3.2.6/spyder/utils/help/static/images/0000775000175000017500000000000013225025007021750 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/utils/help/static/images/debug-step-in.png0000664000175000017500000000132213026261006025117 0ustar carloscarlos00000000000000PNG  IHDRש cHRMz&u0`:pQ<PLTEa|^Z߁o|VzgxRԉjWW]mNwEDfGdC_ޱ=|T5qnFjZNS:y=)c5)`2n.#tRNSP]G .C (Y=F7?  bKGDH pHYsodIDAT1NUQе;bbei8^- !LjuԤA`R#E(@`fbgv5Q7Fw.4ߢTN=1ś>PWI"gG(xcC{@{w]}l,ǏwWu>$I$قda}I[lIvhI:IA' $jn~$/__@&`IENDB`spyder-3.2.6/spyder/utils/help/static/images/collapse_expand.png0000664000175000017500000000054113026261006025617 0ustar carloscarlos00000000000000PNG  IHDR 2-Ι cHRMz&u0`:pQ<bKGD̿IDAT8?n07q#"C[tԕ;dfb; ܂؈!bĢ7gy%[ h4tĈW$,R+0fZqg -]8s&fMFKGW(8֠F5QzX˄RK6tV} = 'RBD ɂZ*Ҩ@ɉ_[]JA n&OM%SS>,>$UrfvZ 3:v] 57 fJ閥OjL0v; "wrZ=WK0NPTI)9 &O*u*oW^n?QJ}(8n9C[rW+:~OlpkׇO>x}7Niwwgj^W٣Sv[@Vj7ʐU4`:(EwQY$IzQh>tR7o޾;4E6` NedWj|6K\0 إ{nn}{^}ׇWW wΜL֝>qqi:aZQp?,IjRz9UAC.zFgYh$Y>3hm!vTV}w_?(z޿]yUR:ͩ,)Y1a{YJ^$vsȿ9n~.A#e%9[~.> WըjRjSӥ̜.۷.~af2s>DItK?c.ڟSόX=3S.kL̢wH3yKU-v2;KŹJ2_?\:h[]cExw>S+M6ZXA8fkky[u2/w+_"?P_g_&I) j,eU F4\˔Xhp)k>."l긎eXio)3_ousTc8zTQ΍qlڴ6 CWo-ݹ%Ugw) x]@fwvٝ[=1\~'a{tˬIίis>lfunYyF^tz4Eثk弙ڡv#KkhtT0q3~xf&qḊr#`*C?݆+0 (UNu6ǞӜBr}m1]8=gYg癜(0پ02l%KlePM^{f;BfwiLX ŻDsN׾gs:+ 1il{zӛU&sSQ{ di&MfRʼn4]* ס4 Ṷ;D;zkgfR2xb >^K}*fS:3ɃXJ)롏VF#@̯W145?Z?ci23YSbt[a jbf"inWQLxO2b90x>Ƽ1rk8fV9GrOs^4773f9*8frC'kt e;CHwE&=ljf"kP6*i0s!KyozɟY`ff4?x$|dŜ "Gff&f30 L`&f303 L`ٓ . ϟ?ǩ0͓f_y~9Z3L9)*I̜?KyZ3ja[m9/NREKyfN v9 *L 0pv1sccc WӶ] 3Q̤vw$d'3=4qfZfo7i&ijMT8yLy Y)Z3a&400@8"K$E8o2%m863K?S"ӻT3d;e}$]WacCf )XzKEn!3z23y+ UIɎ 3JLoD3Iq$p*9UfAɉϯ%SZ*UscJ  [˰v*VqZI)(TyUedF D*n|N-n-f)R8fY!K!1ߒ%bCRE-׏bfkz׻̴Z e1\Cj%j~>֢.WuO$xNN˱jINPTI)ڳh(h%Ģ~ITe."FG:fZZ&/oiScSZz]C Ո2s/+ڋXgͫ|L^_#QYVT&NFZ㍱kzDR|2*NA4kmT]ZU&)+%WX檎Xoeڛe>ȃܾ}9K~=ݍ|@#Wz+̪Ek{a5KZ|-07v$3uNiڙg}1|㆛t/?Y瓜_cGa+f#i{]0^3F@^ ̥Shj-h(ҭYtp>F{iW3:kJYgP٠I'9xg?W)`fw&co8( xT$C~՜F0w3`QIOXR ˋoGk*쎽DD± 9El4'H/d.bY3lh 3irӶ#lصߵۋm{5aWhD^x&Qq L`f<ˢ/2G pCU[E ^}n}.~_x.XUuT33ZId׫|?[Sx.HeXVj:'_\e^wukfX@i&Ε?q$>%eA.uw+ު? Wj\7587`&f>*g$ٮSb8KMsF5-}Et(y wU6c[n暟}5V9Ϊ"T|RhhY>9;i :_o|U_od&4-<3N_itk-+5vu8T ?=0?QfE=]o,LII~CdF<9,}-Ͳ;L`F:TM_Y`fo03:|"W 3_*-DRo5 X*13>Js`g e3ɗX 0į\>1rصβ=eFF7hzSF#ZNΊ;L.^#V{L>#}A*Φܐ=9dBYΐ.(|IO6 8~Ɓ ̜ qki;Fw  ffnNQ$|dŜ {fg&f30 L`&f303 L`>s…B@?{Tl6{9w΋zv 3a&t֯_yN`kƆxNUw9ZΞr̤J m۝j6c~vՐӖͦ<zΝ;9US"?Os^CN~@aPe=#m9ٓUCNtĩ}OB%{''}gOb 9mL]hCPp*=ڗVC``DOÌ*Ut Zo|#TD9 zƯa; )9'i*0t <ǿ/CLk8zL0~OUT:LJAm(b1LwP2n&ՀNRR;}NIjjU#1˼8S9s =- J%i=c^y_&,e%t:TR#fqW *>NE* }Sܗ 6zG;tLg<鮅 JˈTqm_&/e%Ccf:=Gr¢v>N+Lǹ/vZ2뒀=@k gtF{^6IBUvؑJ͹]lbm`J~ijIuJ(֐0򉟧ٕј"l> 9Y4 X:|~o*}JjJqOG9 aG 3rsHXK8>yzm^7O`cN]WN raTJOU4KqRM|E$%2bNjUNMrbj"#WJ$-`x[[%L{3[JN; /oܒ26įK lH {Ep^H$$KBBA(9T3y8 SN"|;׍qah$FaXR;MM2׶xrrwXA};/s🿽_Zp,xwu0/~"L&nff˹c׿\N_;;yTU[|juҤO||YLƌkĎZ :01ftp/Ϧiy5W:vJiiqObn,־}XZǹsnVsҍX%/qӕc4W65WE~3JCzQ͛VyQiΓgS}9_mG7p}kUjRB@@c?c! X_EgC@@@|JaeLOOwvvv$}}}" 4JHMX###L( y<{_NokkO  gaa62t8E&-!ىV6)YǒqsxGSH5F /\. Ybr=vn?Ϛ1?.ALR?7t}3ٌOtvc9Hy< U Ǚ$48LK[`3B8p aWFu->L:aNYm}MADBIE*i>)d xB{Mu3Y|`PTDcЇ; $4L1 ˒t:m r|!SF|ђ@_g3[J$>k*ӄm;ӗ+Jr>„^rgg5Qp*Ls6P1߮zGNq@CKн*^6֚ps\~5IKOMNMLQBWT6D)mUTN)xa~|tG !;.'''4"K'T<~A^ bkV/MT6C^5$Lg?AjtsoG4E Qb^ZP,92w,êl,Rt~MMyT7WDQQsꚟ{S][YU=NOqYP=-U K4u4=#ROu3=DpCZ}/^/xY.FSlE3%agv]G^v7ٸn0G@_cd۶wcd3>罧̓U<0bP^ݻ᝞;Z˾NpAO wxit57=xۚjo-}}Qi [KmtXF o=-#3-a4"Mbh-=A @X@X 6%'V_'--]Gl6TNnehaޚkGª QSzR>#OuF-)٣XCU9&{MдzN0nN" *9d}3{Pwb U ) ssҝ?;K18>CjvW NY.Ҙ얜{bPATa>멽+":LcTk昫KL~Q~Y؀oގgN(=`*>FȓB>c-+ѽZOY%Kq?!,bs7Si{<h_6\!gء JJJJյ7?L--PW;]ڷ凵444T[W+iFWOʅek*6 k|G$ a*9!PJc5֭3=UISjIGwSoTTUӺHMuWn^V2ukY?pbSCw(k:m^nuJ/NF ClsCގzZƏkNm"(,eM][0L[Xi,i^[WW__ee$b1.VY %XX%Wo%=ѧtZhhmno2FIWÍBsG)T|ֻg;aTO(dѩ4&%d1b<1AYA Ks/yKb(_X? 1Է PQqwit_$F}P-]$B9IcUuk`r<6+ /ǰQG4._f\>俻+Y<.Zk%@ݹDc2Btnsh#hv@1"! /?׳gX\ l$FS?$Wi|'O@r5^}Bm@e7?6ʏg)0HӱwC=swfJcR]"K^N' 2Z)^H9‚!dtߏ'PO gHg_&PT$  , , ,@X ,@X'/34 2K`P7,ƿ5rPx&?ٱ}F1褦ya2RS6I+'k FC\XJ)Ix*~bgV ˝3{lPQWWSv=Tcۍ46lPv}FP<^łVa3\4{C#XGⰗ+VlQ{~'ѳ\6g 9Rul('.?NCYlLx2CaQS9TܘAGUU^&._=Lg1:b/Fuԇ }v%=DR8xb:s$|djS绒 R_ܽ=2sH,6_svr>eDcFrn:r z_OYӑx~cM^$s؄7nff~wH\E"zx6ϝGC' w\\#YiN2!=1Ku\`8Y4yA^;|pIݽ"%Ș˲58[*4:chRmϞ^J&=| 1{dX};|޷R**Ea=;w 0a7X0lNNs:<&\oNX"N9.˅uoI44p,BGEMMC@GKԢHt#t]/8|oʮX)S7,V񝽚n&K[֭SR9U7ѝfJO}o'EKY{?, іLKYHC7k}KSQsB_52N.އeF%Ñx_\,D.c|5ݳU&wEdozr`\(|t@פ`m4mX\}^56ObSk[5/hBuLQ7ݸqͨ"*Eƍ$ 2޸)dLMw7_Id;Xl>wW)7i E[Z6H˓/޵pθ_,hGk0;/1zo'p\$^v';kzp=yΡ/i-uƖ1=QU4̄s=*Eةmw#78<͢Nha "w%,<uoݼq^*?bmبcHX6FVie[, -X2Hoϡdf OVV Oު/[5/6˛N|֥F#ksM/d*_mcR1G}vFw2id2YLX.K!}HX^!-^e,W ֎2i}&_Ji0<d zA+֞b,#АljNԷ??r.|g/,O!:V$6s {%h]nRvm#v^q>92M &qwVT Q k]WεR OҺ/7*7oZxꁺK3l5\O.i(xt/;W}5R#[QF_t ևF7`%,}fOF3 <{A"8mdpD#lF[͍(<$q`$R{ґs3DE;&ZIeva*zj|4]F*IXaۡ^^.kWM=9u <,Q Wʻ~{k${.{F:ӣcm(ڄ-V/jV-ϝ(]~]0Xꖭl+?;lNOœh&[wr2RS|di{f]Ajw\,e X 92* I?pW t{0~x!o A2QahgS]]cPR>1[WU]]W7X aw@ZjԢM tLږ3%p#M5(I"uu5Ó4yĹVQ4?q~\Rhoyik$+bPF{gy*f&GgV֙ThOGUyEHO<7TsMvVU5 ṆCC8lal)!K~]aE)d|ww1@\WDל]')>@<a1>A~04{y?۟mw͒q^9]MRʓCW{EWd2Sz +sgvLakǃJulc+@KK{Gd{GŖ_[CO3Aq {h"y`A~%cHgoSӍ +咶ǵԧg׮熢 Om\f\"3Ϲmg٠;ciw0n µNZ&V}Gp#罬54 6И,krhږZAك V{J*F[ 7AOUd JO[} U6l~s@q|yvxeX}gۙ1'OP&5Gww9hjZnMb"a]K8ZMCFN@2P@G,y], 1}lXAB:wVse3m%+D?s=]{uky[_Ž{-e+vTֺ\EWFU|o$.;cջY nayR(}svKjn6b+L.vKmX@>b_ysc[UMcu&*?no*V-miLA !i(3ƶy%3J \F_(Y^y&7= Ϡ?9Zdnwg]`zAc_*xdCsr`]Lw}]ϧ03s{_Xfkn?-h:d}Yw6;~y`N&𴸃bw8?O}187ۘorF^Nf:Zzos3&}!xkcoy[$(/qO{j_ʤjfO+ny$pdCL c }U )#jl;Z5k Z7F k63dګ:#9cXiwh,AZj=tDwV[$t2!git_YI?.uʇm+nQV_/'&ejbHRXL6V7ko*;6)[mja 5SwX$k?+5}_!C$h~NlPGŠao`y֭56EN^Wav6ce{2!9d;֛v d:(Ov2_YKԴ_r}z_-߈j6{ɅgiU7 s> F{ `Ji}GhA;ϋbf&WI/ԏߪZxms \߃Pw')=Okx: SdYigcr2}R2|9kT~P%6/mNJ-OZVa ѴԬ7oP6ͨɸmtb5f[^d;YLۚZ}n$T۸rAͷjZ]ldŝu:vv[6[^}gN9Y#&>8Ǖ3nI [1Ski<~?64q!RFM LA1\WRX afQ)0&rzŦd|(cJ075\`bzـl\z6Sb~:ŮnY`rA=G;{87ᠹ9' LWJzxQgv_%"(vJ9\Ӈ’ۥy%K3=MoЯgz_*mذ|P 5ӂ)₷^$,y +~ʶ ݁7 ;a ]\XiWuLvT |JG0ۣVjCw DjQ )!5iCaKmf{*a/^zJ4k=ol|߾uVa\pWwJ∄<4}}"t9wl*UwV(8jJxzG iaa' dz/I$D/ u͐A9aal&M5]CSS5vPu{WvZly۲ACHWX JGq/iyZZ+bG~nk͔YQA.Qk5S#C͞8a%٢mbyцoתl<祃 I(|-0a 85?U-aNPYk宭b9wcM]ϱ*S5*6!PFb;5zZ#.魵{h}9#^)#gJ$ iԝnU\mQ9:X!kB_g9,Y)ȵ_Xi:w`ʘ L͞^%6i>xP/}Lކe?gIXݶ';m~̠4o]FIóudۚc䊩7@DUpWOO`͑Y>liSF*->,a\_yRN"yqMbMaoVO߽=zqŘ(c{8䜡zQrmu|Et/MD.ez7 C(N j:޻/]c6+4zvt&4M{ivW׫d$ Vnt'Lg{]N[{!& H)#i^Rw糞wĴCXzx~4O&EøEaIsf˅34v˃}9[%!". KzXyjV{b'zq)IDQi 5AS’MOb L=\NS*djLyV5B2Ӎ w 7LZQݢcwP#4ӻW3dJxc$,mPҮ,Ⱥt,lN}5J`CHvDvXƹ:R3$*q@&KhBXRqr1^Z%&aa~_ab> ?*,*A@X@X ,@X , ,IXB.ƆEk]p,Pd#%~R?37@b0?=>&NOTWgH0=Je u=}FLJGKsJ3`)q2M[&pjN v7vՐg't ZY<d>Wcc^jou%^.O3Dzoݱ}NSccWYWKFtG4Rv6wO/S;#:{.Ub uWtr޹EWn_8&g.^[ >c(tնw ,.+ ߍ)+2BzqW+ӗzh͠Yf4 zp~ k#@$%ګj$6d"᝛DOvS ZQiw~ 8a9ylmxW^ 9Id,XkĦ+ Ǫ z>=j%hYuX=1:>x&!*=0$z!3ghcg_mNaHK%ehRB"_##1dmh$~o҈&ȡ(LvTY SsH4=c-T nd`pr ~W|O  ,O†S@X ,@X_DmVœt]uݚU3 'oɘԛӺM_~o1Ha[Xn +-󃙋;F&'ea{F$%&&=sZjauP9oge85)5->tgR||VI@~ϑč7 nRHRU\\ms+=הkn}VzyN͞4:]m>[\χWSʪEk}nttO`*mٻy'|>Fc+l,7LKX5NfZO߄c}G] Þ 5P$Epz^u*a'P)щ-9B/Y8*t?S1j~X=|7X`~1Z?zs @'} 9tAr=V|uX/p +JFrVW5hg_>c˒Lsѧ_,) _eUT6=݋6ERŘZoU,> }q\E'LlGJe (Sf󷝘 ۞z@L}Xg.]>G_"ό|0;z{6?[.7hn̦Q$-F5"v6) ->>;vu86U 5 ~)2}x,F]ձiuʮuU<y>'zp..W kto[[ȅ|ﰡʄG*#ywlJXi a˅5ךcd"o=(a]b[6il'_tzavv;mŕǞ9rq,ѳ+řu73-D| X*U4:@s3eGE/B SX~C ۂ1sƤH!{'&db75n4?xroo.&,R[;MGYlذP<& & aZ*w\X1p=Vu'pX4>^l;k͕XYU8 >a1qC+j-~U#r RHI҉QW\rHʝs#4,#c_B ]| y+/_X)lYzG+"̈jΔb[%7Y._]XP2{W%ŽƦ&x 1d xI_=JKEK]BhW \@OGSUaaa@X@X ,@X , ,    )ϥp.e텴iݓ %\|p 2g6[{6yO%.KÎ?),|cú8Tc4%\_n yB98cJd& hl._$y'=.FHޟ8)aݬ+Z%0tE&s's&9y% sC3Ҿ;Z;!YLEIT[7'Kn2|U[\ùEg?}u;LgM"ҿOl8aeNΞ=?ي9DVSgv7yZdu&7dn}Tn$ E6Ƣ܈{j2UC cvŝ% WK7Ži28l0T|ڱT8ehGd^ՋZrM-.f>,'-RC2i2}B%$@JRwcaEbC Mw~'^"ףLp Ȥ/Ҋ~8^05b81ae:FU*V Jߙٯkd0"K%83IߝMB+eDse !,*#۷ČT#K Gd>=ρ# fi@)Aor !}p0"qSQtaǤ"2['g&VdVHZX=’IV=Z^RNL=ʭ;: @GuYQOF1A.q̃UBGڗ[º}S$,qCm^@ʩ Ta}$wB/T Nݑ=Zb|ir$[Xӵo5Ys権*)k/aW W \XJSgz:u瓏PCjZo&+4̜Ix]r&/'Ȃ֥6SI~˖qHdx~Vú5״;NXըE-y@^TdeߟN CH"DDnTpqd&z}JWh<%PH$TH剥RD*/(sŘ(KRJ;OfЂa@X@X6a|* JX@ aaa@X`,RNA)[ uZ ݗx?tV= X?9 ||P&.ڝoս&' 45]JUBu5qvfВ'zf/~(MʖbldGboK^e\4sq7{7ZڕM__ܥipNP"O99j)VQQ->em1\eq!~ Zi a1{{{!VULܞwSqs%S[byy'rܵk"3VXY}W|SnT7TMc,S]oe^{ؼw=by) TRR;Z2 )n火Qp(OK[jwTmO}e#b 7Z<QO`^<=JUSvT>9ax{K<յ5b(,=$>"Z[vu{Kx|yi~^nNae?Tb#N ojg{]uk$216r;iF.~l$,n}3 >VL[Uf{^@ nTSd-N HD42b-T*7)bQh| HHyb&HcP>aA=.JD"X"HUjo]eGOg~8Q[X dS«ǣC~y7}sϊ _^pQuO}m{vѼ^/KUfu E?O]}<993ԥDπݛmvH>r =y닆8y?<Ic0Euh/\qwB{~R1G{u='4Yb!e edgN Z9e97 rCXR`y/aZ3Qb.rYGt]w+:OzU2Vg2;GWn_jjJsm<)$/}͉3 &ilh\a}9yY a9=fdeyQ>O"C]s*,z[=mv2U;$ϹZU`Je"\?[W7{o{a䀗k O²}ֺV>\c 49KX\LʢDȺ}@ePJ>eu߉wWciw{WW)K/phyWEo3On2542~XUŬ =}=5ԕ} .Gow]g8#IRC=wl:@&k\nޱ`SrU8w&[}Ӟxm\~q#I]gsۨt ]Qzz tPV ]bĴ=wa՜t3wuݢDb!,O uWF5A~]A:`/V6F1hknrۻ}fXgH~::!xŮlo35RXZmx%HgGC9Ox;۹>Y2br"uWil:v:aedyszA8cnV,7 b+{<Β1{L/u WFgƺ*u6֠1:A5;5Լq6C阰\b;u2GLls41n9V8|ZB¢>غT>yg)p; Hl‡ʄT}ϻKpO"+aG>}?֚=)m -fK52-6MM4ut5 ̣:}T%|y- +G_[x1xbe6kfsu^lR )j ֦z=% n<`<먯}bW qGx4O’pWWx˪6kȷ\KCy[+Nl$/bqm̊ MX*ea&*omp>;6=3===3Oܕw~oul}Q'Lؓ;X޽ 2|u[O(%$R6qb,Cn=Ѹ҆siw-bZf3p͞Ih_r&Mol=DBwO\. kN]tZW ZkZaN j4*/a6)e.VU)hca(U '1Pq]1R\mX-@q [z \w! k&ShZ*G=I1wm;3b4.V3Mц琰X>'DT~ᐣ 6usFHwW׊z_Xw5o`j a8luzeyQ!,K.zP. +%ZjVfZ5cqg>}>jnwv;}wQ{MO"mvvBVgԏdq8}e?@IS~+Všg ی )Mw$ [S}{)F^ޮy,0'|L9OSZZ(\!h͚Z7k^]VU;k9m~d"3&}M98J59 Ukꆨ{3/Z_?wcqb'.%)k^wM$+lZWVi̸lviT 5-\K3ihVqeD?9sUńj̾m쥒' L̬t)yBؕ{|מ+ f_u|SC采ߺO3/rLUe_ܧnIۇT3}Ǥ}gǞR6W'%M >rbil?8vIlav+W b0oMf7s?X+?9 ,@X ,@X , ,   aaa|H @X?EOu#ngF+q.gYOQX1$Sb k'%6xEq> =reKw KՈQQX[T+NJiFw1&,Ԇ>?oyQ$;jƕ)-U6ϸKQz὚&fj<6OLOJ0a9&]P8QLixLyW H^t> 2Vn2!9tlJpچ Q"=i\9az&>Ԯhj L)r_d] "a$<^~J%ܓa/dW5² 2[鯉@XXV0Sw=ȼmesV yIX/ {z,6<"ֱ%aq6_ԾX'PLòveaɅ5xRIz7~8t!+=~yN!{:P\H/.@t>6yH& K؜2eDeqVG@X K 5ώ-Π OSPClGQxݣj2~Z#,S=3O;hFȐET%|M +j~\XAI 'D }\d;ʡYrEg5qp%+N*Y?g_ǒC3cijT?d^LnD\MvoSK\RbSqXdޓEamS?6(7̓֬*u 6r@B?N'te8’g E=3%+ Gr*:izrfiRLoM)%ѩ)yithnhgQho痺v NUM$R] α^twntf{S&z? _0S3 ^׽e\ڸ7WIʎBea%a$nAխC.sT*Kv홡d 7>UR3b;TG GX.tzꆄ5FJ2\A*su%|TFHn޵u:Anͯ}[Y}ܹhZՓ75Jfd5=㜷5(hj2N=k;}-vԻ039ލ |Ǒpvaw(S>jYȋ:{7eM=::UnfV225:<8:5{Bwpzy#BD2Lvq&ǫb{"ooHlGB=otfy|ϕayR'}\vQ[%\c4(y&T$UEMEROzGȫ XiCN=v}m ܝk}4@0T}h8L("$^\h!aa5jo~Rx#GNʮ;}4bTe|Rde&N2Q;ZԽQH=_ʸs4rO:;R~Uoʽ"\6+㱻|˭ %H+T1wDB!DWPdutXFabywP4c@yņz9 :bz9(=$tXt~X"CB:F5ĶBJybkit2(B$P&B"D /mlt6EBaJKWR [XO@,o?j\LX,|gI- ,XC"$K=E?,\%tTpZC\aVˉP<a~B"?|68$$8(ҝ82H*}vX`hXȹW3,Vsݩəyo08;G{8*]t9P[]^ZXÇچ%ڱef9}\"a{\z;B0Qn<.u*~{Jƞ8샦np?ccS#m< =%O[j^xIDK,qQryRbp\O}u֤T,gV @X^Tq ŊAgJ1zuMMI Qg}9! 8w|4'芎eqYgϼEe⅓6'px WVvP=p %zOL*W 2‚ , ‚a @X ,ğQXx #r_g*ϓ TE     aaa@X@X ,@X , ,  @X ,@X , ,   aaa@X@X ,@X ,@X , ,?q>yIENDB`spyder-3.2.6/spyder/utils/help/static/images/debug-continue.png0000664000175000017500000000253013026261006025366 0ustar carloscarlos00000000000000PNG  IHDR cHRMz&u0`:pQ< pHYs+tIME 3!!!bKGDIDAT8ˍkLWKbm >? aJq 9E&*rQT Ee(!2(E(@)*E,R[K[hBۗ #B9O?^Z. rS!8[3%ʘ%4C[Lr~kH5ֈ Mpq2>nwvetٌ-Բ3Uq~)DcL㹞̱&{"7aU1hCu1)2oĆ7k-  mUZ\M- dɪ𼣽 7Ui/UH@f!e*[R-sb%RD2\Yb:k}}k E>.zZ:+ȣB~j]IN#cprC uZ ӎ9:Cӫ_!BN%R,@;Z Xcw_R $n<_@"'tWnK!Xr Ϭvʉ2$uT"kIH\}Y=$C-: &sU3n;2"v?. &+]VDq],NV#MLu%Pޙ݈U!3&n F5Ѡ~"rӑ;86!+qrySsO48< |r%ΗyKo^Xܟ.®k}_F'.4!-~ꐼ^ۍڍ[++EPX*KΤ<-ѯ; mNMoSۋ_#?H*=HKTT>uNz æ1C8kta`*^\l pp/-T.iy4>LjDp x>[¡NPco'aţl;Il\}~XQS= =}"կ26`V(I3"c9Nղ?`ʕ;] DZ*dHgुΨ:= ϸZfm=](Dir2{>blgB*&iA\vc{s=(q쥏2q:ρw<{2ӫyrazIJUՌޱtuւUTcXۣYՄGMYf#o`כ<~73( w[XS)ե|dWdIENDB`spyder-3.2.6/spyder/utils/help/static/images/spyder-hello-docstring.png0000664000175000017500000001244513026261006027065 0ustar carloscarlos00000000000000PNG  IHDRj cHRMz&u0`:pQ< pHYs  tIME2 |bKGDIDATxw|uwvfPCQM@"H5("rT)x"Dr z<ܝHGHPF)b3DA.O|xm%kevK7y2Kx xb,p<₂:,rߙ¯ "fUL$00+wGuBKe\AvӶN_ޝ"Y4t;?- VyD,+vB7tY"bĸqn+ WuUb *2 ""bDBqb^`uV62!_9, 4X{'\&"!v]p,|NH;g;TWc׼ZXcHnEџ+/A1Vf6/=-b$FkH FUUjȝ}wd^'OeQ2;*Y'$m˙ (>qFnuJD"Y:7t]{ϯ` *(vCz %>ԆͥΨX=L^&գ{Fkaﳿ侊DQB"ӈfV" e{䃬svqO*K$z*'=#l(\;6Bl25U7V✑,\b `].^I.U(Nd2+[ bw960H͋tnrCD7yQ+W۞+9CT/BDDF Lab(!ݭ鼿~"" \Ι5gcÁnzʑ7g%V nIF>{_3ApeYxlm7Z(納)VITҳ8E;Ip+r;&L&mҪzU @'XDDL"ƈ|#>3z#&ɲ~r-4MSn L2 ]02t He?s7&a'Of|W.a0${B6/\b] A H4K_|(m&^n X$?J81` ,2`` X` X Xc +$x⢸B8zQ"Iz͞c#?y`_GQjsN{e"q#كC,edH@YjCh//Wo0i;IHb:-:سQ$-oт~[#gΞ'}i_׭k7V%F/IdT)Uo$N1HaD_$_пkIB%+(^9ׯK?<|pܬ{p`~~ď_ G);sZ6YZ+zsNC&/-Ԉ||{ER8}9b>Ʀm2wZY5ID)=zMգ=^j:t0/bü=NZvGv{[]{=v{=iTrЦ߷aag^/rC0);u[&1:/:xȌ5`A[SD>E=_E=.Q;Myjk~|N| QMRڥYR񒤔ФӤjDD$K͑#GM_3ٹǽ>ڥ ͹Ӿw4{l~gW6X֍C'_kmV952v|^V Iˀ;o9w O[q r,u׳C*YtS^L k\vSUکSfe3y~j$t:bAǟ2k"lz6d͜33qVfb],3(eΐ7Xix,Z,jx|IF vL2GRnM'[fڵEub\{0ŜWU-g:Np`&=&קvU%vka?S{ػlݖ(ssN[~۸30L#Re<ճW& XUg^ټ}7sZuzzPcOAaUmDDdX7s#\@O%ut;yxܵbçOS+e$-R_ZٲwWLbs97g T~TgLqɏMMMMڪ.|zuPWAu " @/YڴmQ?=wN.>QV|hаώٮזfX:^pnADQ# "yC'NT;=R_[^$׭f4h݀4 ߎ~!;o;倩K\&)[>-R C7d^?`J^9ʯ;ݛ?Vseim(j\לe瞺GlUz:{5w'<0'kqO;7~eÛZD%9!(#"~.J;瑈" cw|u٬o {NvboOJdpͫt*1}c>xgM{0ooW"Yn*n#"-䋐aK~ _l3Pvv>]*9 nQMD$DNDGCYYarǹf# h&]5".*EdK3+?Hp6l"AݥƮ"ܼ@4$[l#@P;g zuf6._Jq[m6Xq N{>KTO"B>M-2-vI"#̺xYW=⬺lZ$N{^<)6OS%tɕX瞿Pi\T⴩DD!f El(%wdDB!8,Eoca6* 慴b2F܈Ba%@+6*Q4q;J-,g @@,@,@, ,  @@,@, ,  @@,@, , ,  @@,@, ,  @@,@, ,   @@,@, ,  @@,@, ,_r;WIENDB`spyder-3.2.6/spyder/utils/help/static/images/debug-step-over.png0000664000175000017500000000137713026261006025476 0ustar carloscarlos00000000000000PNG  IHDR(-S cHRMz&u0`:pQ<qPLTE8:=54,0s2%z$z1ln u"w"xdj ZaS YN@@@@:GWLB{B02,"7_tRNS5 yy9̃&&5&&3HHHHHU{bKGDHIDATjQ{g]fJB; Ey0iDa}6Ix?}qyf.Ay7ܒߠ?'$G;:W?Rzr d Ɉ"ji/2IG}^5-,+-`u0rj]F4~Y,qIENDB`spyder-3.2.6/spyder/utils/help/tutorial.rst0000664000175000017500000010210013156676663021632 0ustar carloscarlos00000000000000====================================================== Spyder - the Scientific PYthon Development EnviRonment ====================================================== *Spyder* is an Integrated Development Environment (IDE) for scientific computing using the Python programming language. It comes with an Editor to write code, a Console to evaluate it and see its results at any time, a Variable Explorer to see what variables have been defined during evaluation, and several other facilities to help you to effectively develop the programs you need as a scientist. This tutorial is authored by `Hans Fangohr `__ from the University of Southampton (UK) (see `historical note`_ for more detail). First steps with Spyder ####################### This section is aimed at Python and Spyder beginners. If you find it too simple, please continue to the next section. Execute a given program ----------------------- * We are going to use this program as a first example: .. code-block:: python # Demo file for Spyder Tutorial # Hans Fangohr, University of Southampton, UK def hello(): """Print "Hello World" and return None""" print("Hello World") # main program starts here hello() * To use this program, please create a new file in the Spyder editor pane. Then copy and paste the code inside the box above on the file, and the save it with the name ``hello.py``. * To execute the program, select ``Run > Run`` from the menu (or press F5), and confirm the ``Run settings`` if required. If this is your first time, you should see an output like this:: In [1]: runfile('/Users/fangohr/Desktop/hello.py', wdir=r'/Users/fangohr/Desktop') Hello World In [2]: If so, then you have just run your first Python program - well done. .. note:: The particular path shown next to ``runfile`` will depend on where you have saved the file, but this is inserted by Spyder automatically. Use the IPython Console ~~~~~~~~~~~~~~~~~~~~~~~ Before we proceed, we recommend you to use the IPython console. This console can do a little more than the standard Python console, and we suggest to use it as the default console here. What happens when you execute the program? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Python reads the file line by line, ignoring comments (i.e. lines starting with the ``#`` symbol). * When it comes across the ``def`` keyword, it knows that a function is DEFined in this and the next (one or more) lines. All *indented* lines following ``def hello():`` belong to the function body. Note that the function object is just created at this point in the file, but the function is not yet called (i.e. not executed). * When Python comes across commands (other than ``def ...`` and a few other keywords) that are written in the left-most column, it will execute these immediately. In the ``hello.py`` file this is only the line reading ``hello()`` which will actually call (i.e. *execute*) the function with name ``hello``. If you comment or remove the line ``hello()`` from the program and run the whole file again (by pressing F5, or selecting ``Run > Run``), nothing will be printed (because the function ``hello`` is defined, but not called, i.e. not executed). Now you should know how to execute a Python program that you have in the editor pane in Spyder using the IPython console. If you are just starting to learn Python, this is probably a good point to return to your text book / course and look at more basic examples. The next section gives more detailed information how you can execute *parts* of the code in the editor in the IPython console, and thus update parts of your definitions in the editor. This is a more advanced technique but can be very useful. (You may also be interested in the option to execute chunks (so-called "cells") of code that are separated by delimiters -- see `Shortcuts for useful functions`_.) Call existing functions in the console -------------------------------------- Once you have executed the ``hello.py`` program, the function object ``hello`` is defined and known to the IPython console. We can thus call the function from the console like this: * Type ``hello()`` in the console (next to ``In [?]`` prompt, where the question mark can be any positive integer number), and press the ``Enter`` key. You should find that the ``hello()`` function is executed again, i.e. ``Hello World`` is printed again. Your function call at the console together with the output should look like this:: In [ ]: hello() Hello World * Can you see how this differs from executing the whole program again? When we execute the whole program (by pressing F5), Python goes through the file, creates the ``hello`` function object (overriding the previous object), reaches the ``hello()`` line and calls the function. When we call ``hello()`` in the console, we only call the function object ``hello`` that has been defined in the IPython console when we executed the whole ``hello.py`` file earlier (by pressing F5). This will become clearer over time and also when we work with slightly larger examples. You may want to return to this tutorial at a slightly later stage. Inspecting objects defined in the console ----------------------------------------- * Python provides a function that displays all known objects in the current name space of the console. It is called ``dir()``: when you type ``dir()`` at the console, you get a list of known objects. Ignore everything starting with an underscore for now. Can you see ``hello`` in the list? .. note:: If you get a long list of defined objects, then Spyder may have done some convenience imports for you already. To address this you may want to: - `Reset the name space`_ - Execute ``hello.py`` again by pressing F5 Then run ``dir()`` as suggested above. * Once an object is visible in the current name space (as is ``hello`` in this example), we can use the ``help`` function as follows to learn about it: typing ``help(hello)`` at the console prompt, you should see an output like this:: In [ ]: help(hello) Help on function hello in module __main__: hello() Print "Hello World" and return None Where does Python take the information from? Some of it (like the number of input arguments and names of those variables; here we have no input arguments) Python can find through inspecting its objects, additional information comes from the documentation string provided for the function object ``hello``. The documentation string is the first string immediately below the line ``def hello():``. These strings are special, and they are called *docstrings* which is short for *documentation strings*. As they usually extend over multiple lines, there are enclosed by triple single quotes (``'''``) or triple double quotes (``"""``). * The Spyder environment also provides a ``Help`` pane which by default is located in the top right corner. While the cursor is on the name of an object, press ``CTRL+i`` (or ``CMD+i`` on Mac), and you should find that the same information as we obtained from ``help(hello)`` is provided automatically in the Help: .. image:: images/spyder-hello-docstring.png :align: center This works in the console and in the editor. Updating objects ---------------- Simple strategy: re-execute whole program ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * In the Editor window, change the function ``hello`` so that it prints ``Good Bye World`` rather than ``Hello World``. * Press F5 (to execute the whole program) and check that the output of the program is now:: Good Bye World What has happened when you pressed F5 is this: Python has gone through the ``hello.py`` file and created a new function object ``hello`` (overriding the function object ``hello`` we had defined before) and then executed the function. Looking at the details ~~~~~~~~~~~~~~~~~~~~~~ We need to start with a clearly defined state. To do this, please change the function ``hello()`` back so that it prints ``Hello World``, then press F5 to run the whole program and check that it prints ``Hello World``. * Call the function ``hello()`` from the command prompt (as described in `Call existing functions in the console`_). You should see ``Hello World`` printed. * Now change the function definition so that it would print ``Laters World``, and save the file (but do NOT execute the program, i.e. do NOT press F5 yet). * Call the function ``hello()`` in the console again. You should find that the text printed reads ``Hello World``, like here :: In [ ]: hello() Hello World Why is this so? Because the ``hello`` function object in the console is the old one which prints ``Hello World``. So far, we have changed the file ``hello.py`` (and replaced ``Hello World`` in there with ``Laters World``) in the editor but this has not affected the objects that have previously been created in the console. Here are two possibilities to use our modified version of the ``hello`` function: * Option 1: execute the whole file ``hello.py`` again by pressing F5: this creates a new function object ``hello`` (and overrides the old one). You should find that if you press F5, and then call ``hello()`` at the prompt, the new text ``Laters World`` is printed. * Option 2: select the region you have changed (in this case the whole function ``hello``, starting from the line ``def hello():`` down to ``print("Laters Wold")``, and then select ``Run > Run selection``. This will update the ``hello`` object in the console without having to execute the whole ``hello.py`` file:: In [ ]: def hello(): ...: """Print "Hello World" and return None""" ...: print("Laters world") ...: If we now type ``hello()``, we see the update response:: In [ ]: hello() Laters world The ability to execute *parts of the code* to update some objects in the console (in the example above, we updated the function object ``hello``), is of great use when developing and debugging more complex codes, and when creating objects/data in the console session take time. For example, by modifying only the functions (or classes/objects, etc.) that we are actually developing or debugging, we can keep re-using the data and other objects that are defined in the console session. Recommended first steps for Python beginners ############################################ To teach and learn Python programming, we recommend here to use IPython instead of the normal Python console. This accepts IPython as the de-facto standard in the scientific Python community. Switch to an IPython console ---------------------------- If you already have an IPython console active, you can ignore this section, and make it visible by clicking on the "IPython console" rider. In the console window (lower right corner by default), you see by default a prompt with three greater than signs, i.e. ``>>>``. This shows that we are using the ``console`` -- basically a normal Python console session (with some added functionality from Spyder). Instead, we would like to use an *Interactive Python* console, short *IPython* from the `IPython project `__. To do this, select ``Consoles > Open an IPython Console``. You should see in the consolse window a new shell appearing, and the IPython prompt ``In [1]:`` should be displayed. Reset the name space -------------------- The `name space `__ (i.e. the collection of objects defined in the console at any given time) can be cleared in IPython using the ``%reset`` command. Type ``%reset`` and press return, then confirm with ``y``:: In [1]: %reset Once deleted, variables cannot be recovered. Proceed (y/[n])? y In [2]: That's all. We discuss this a little further, but you can skip the following if you are not interested: after issuing the ``%reset`` command, we should have only a few objects defined in the name space of that session. We can list all of them using the ``dir()`` command:: In [2]: dir() Out[2]: ['In', 'Out', '__builtin__', '__builtins__', '__name__', '_dh', '_i', '_i2', '_ih', '_ii', '_iii', '_oh', '_sh', 'exit', 'get_ipython', 'help', 'quit'] Finally, if you like to skip the confirmation step of the ``reset`` command, use can use ``%reset -f`` instead of ``%reset``. Strive for PEP8 Compliance -------------------------- In addition to the syntax that is enforced by the Python programming language, there are additional conventions regarding the layout of the source code, in particular the `Style Guide for Python source code `__ known as "PEP8". By following this guide and writing code in the same style as almost all Python programmers do, it becomes easier to read, and thus easier to debug and re-use -- both for the original author and others. You should change Spyders settings to `Warn if PEP8 coding guidelines are violated`_. Selected Preferences #################### Where are the preferences? -------------------------- A lot of Spyder's behaviour can be configured through its Preferences. Where this is located in the menu depends on your operating system: * On Windows and Linux, go to ``Tools > Preferences`` * On Mac OS, go to ``Python/Spyder > Preferences`` Warn if PEP8 coding guidelines are violated ------------------------------------------- Go to ``Preferences > Editor > Code Introspection/Analysis`` and select the tickbox next to ``Style analysis (PEP8)`` Automatic Symbolic Python ------------------------- Through ``Preferences > IPython console > Advanced Settings > Use symbolic math`` we can activate IPython's SYMbolic PYthon (sympy) mode that is provided by the `sympy `__ module. This mode in Spyder allows nicely rendered mathematical output (LaTeX style) and also imports some sympy objects automatically when the IPython console starts, and reports what it has done. .. code-block:: python These commands were executed: >>> from __future__ import division >>> from sympy import * >>> x, y, z, t = symbols('x y z t') >>> k, m, n = symbols('k m n', integer=True) >>> f, g, h = symbols('f g h', cls=Function) We can then use the variables ``x``, ``y``, for example like this: .. image:: images/spyder-sympy-example.png :align: center Shortcuts for useful functions ############################## - ``F5`` executes the current file - ``F9`` executes the currently highlighted chunk of code: this is very useful to update definitions of functions (say) in the console session without having to run the whole file again. If nothing is selected ``F9`` executes the current line. - ``Tab`` auto-completes commands, function names, variable names, methods in the Console (both Python and IPython) and in the Editor. This feature is very useful, and should be used routinely. Do try it now if auto-completion is new to you. Assume you have defined a variable:: mylongvariablename = 42 Suppose we need to write code that computes ``mylongvariablename + 100``, we can simply type ``my`` and then press the ``Tab`` key. The full variable name will be completed and inserted at the cursor position if the name is unique, and then we can carry on and type ``+ 100``. If the name is not uniquely identifiable given the letters ``my``, a list field will be displayed from which the right variable can be chosen. Choosing from the list can be done with the ```` key and ```` key and the ``Enter`` key to select, or by typing more letters of the name in question (the selection will update automatically) and confirming by pressing ``Enter`` when the right name is identified. - ``Ctrl+Enter`` executes the current cell (menu entry ``Run > Run cell``). A cell is defined as the code between two lines which start with the agreed tag ``#%%``. - ``Shift+Enter`` executes the current cell and advances the cursor to the next cell (menu entry ``Run > Run cell and advance``). Cells are useful to execute a large file/code segment in smaller units. (It is a little bit like a cell in an IPython notebook, in that chunks of code can be run independently.) - ``Alt+`` moves the current line up. If multiple lines are highlighted, they are moved up together. ``Alt+`` works correspondingly moving line(s) down. - ``Ctrl+Left Mouse Click`` on a function/method in the source, opens a new editor windows showing the definition of that function. - ``Shift+Ctrl+Alt+M`` maximizes the current window (or changes the size back to normal if pressed in a maximized window) - ``Ctrl+Shift+F`` activates the search pane across all files. - ``Cmd + +`` (On MacOS X) or ``Ctrl + +`` (otherwise) will increase the font size in the Editor, whereas ``Cmd + -`` (``Ctrl + -``) will decrease it. Also works in the IPython Console. The font size for the Help, the Python console etc. can be set individually via ``Preferences > Help`` etc. I couldn't find a way of changing the font size in the variable explorer. - ``Cmd+S`` (on MacOS X) and ``Ctrl+S`` (otherwise) *in the Editor* pane saves the file currently being edited. This also forces various warning triangles in the left column of the Editor to be updated (otherwise they update every 2 to 3 seconds by default). - ``Cmd+S`` (on MacOS X) and ``Ctrl+S`` (otherwise) *in the IPython console* pane saves the current IPython session as an HTML file, including any figures that may be displayed inline. This is useful as a quick way of recording what has been done in a session. (It is not possible to load this saved record back into the session - if you need functionality like this, look for the IPython Notebook.) - ``Cmd+I`` (on Mac OS X) and ``Ctrl+I`` (otherwise) when pressed while the cursor is on an object, opens documentation for that object in the help pane. Run Settings ############ These are the settings that define how the code in the editor is executed if we select ``Run > Run`` or press F5. By default, the settings box will appear the first time we try to execute a file. If we want to change the settings at any other time, they can be found under ``Run > Configure`` or by pressing F6. There are three choices for the console to use, of which I'll discuss the first two. Let's assume we have a program ``hello.py`` in the editor which reads .. code-block:: python def hello(name): """Given an object 'name', print 'Hello ' and the object.""" print("Hello {}".format(name)) i = 42 if __name__ == "__main__": hello(i) Execute in current Python or IPython console -------------------------------------------- This is the default suggestion, and also generally a good choice. Persistence of objects I (after code execution) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Choosing ``Execute in current Python or IPython console`` setting under ``Run > Configure`` means that 1. When the execution of ``hello.py`` is completed, we can interact with the console in which the program ran, and we can use the convenient IPython console for this (rather than the default Python console). In particular, 2. we can inspect and interact with objects that the execution of our program created, such as ``i`` and ``hello()``. This is generally very useful for incremental coding, testing and debugging: we can call ``hello()`` directly from the console prompt, and don't need to execute the whole ``hello.py`` for this (although if we change the function ``hello()``, we need to execute the file, or at least the function definition, to make the new version of ``hello()`` visible at the console; either by executing the whole buffer or via ``Run > Run Selection``.) Persistence of objects II (from before code execution) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ However, executing the code in the editor in the current console also means that 3. the code that executes can see other (global) objects that were defined in the console session. *This* persistence of objects is easily forgotten and usually not required when working on small programs (although it can be of great value occasionally). These objects could come from previous execution of code, from interactive work in the console, or from convenience imports such as ``from pylab import *`` (Spyder may do some of those convenience imports automatically). This visibility of objects in the console name space to the code we execute may also result in coding mistakes if the code inadvertently relies on these objects. Here is an example: imagine that * we run the code ``hello.py``. Subsequently, the variable ``i`` is known in the console as a global variable. * we edit the ``hello.py`` source and accidentally delete the line ``i = 42`` * we execute the buffer containing ``hello.py`` again. At this point, the call of ``hello(i)`` will *not* fail because the console has an object of name ``i`` defined, although this is not defined in the source of ``hello.py``. At this point, we could save ``hello.py`` and (falsely) think it would execute correctly. However, running it in a new (I)Python console session (or via ``python hello.py`` in a terminal, say) would result in an error, because ``i`` is not defined. The problem arises because the code makes use of an object (here ``i``) without creating it. This also affects importing of modules: if we had imported ``pylab`` at the IPython prompt, then our program will see that when executed in this IPython console session. To learn how we can double check that our code does not depend on such existing objects, see `How to double check your code executes correctly "on its own"`_ . Execute in new dedicated Python console --------------------------------------- Choosing ``Execute in new dedicated Python console`` under ``Run > Configure`` will start *a new Python console every time* the ``hello.py`` program is executed. The major advantage of this mode over `Execute in current Python or IPython console`_ is that we can be certain that there are no global objects defined in this console which originate from debugging and repeated execution of our code: every time we run the code in the editor, the python console in which the code runs is restarted. This is a safe option, but provides less flexibility and cannot use the IPython console. How to double check your code executes correctly "on its own" ------------------------------------------------------------- Assuming you have chosen for your code to `Execute in current Python or IPython console`_, then you have two options to check that your code does work on its own (i.e. it does not depend on undefined variables, unimported modules and commands etc.) (i) Switch from `Execute in current Python or IPython console`_ to `Execute in new dedicated Python console`_, and execute the code in the editor in this dedicated Python console. Alternatively, if you want to stay with the current IPython console, you can (ii) Use IPython's magic ``%reset`` command which will remove all objects (such as ``i`` in the example above) from the current name space, and then execute the code in the editor. Recommendation -------------- My recommendation for beginners would be to `Execute in current Python or IPython console`_, *and* to choose the IPython console for this. Once you have completed a piece of code, double check that it executes independently using one of the options explained in `How to double check your code executes correctly "on its own"`_\ . Other observations ################## Multiple files -------------- When multiple files are opened in the Editor, the corresponding tabs at the top of the window area are arranged in alphabetical order of the filename from left to right. On the left of the tabs, there is as icon that shows ``Browse tabs`` if the mouse hovers over it. It is useful to jump to a particular file directly, if many files are open. Environment variables --------------------- Environment variables can be displayed from the Python Console window (bottom right window in default layout). Click on the ``Options`` icon (the tooltip is ``Options``), then select ``Environment variables``. Reset all customization ----------------------- All customization saved on disk can be reset by calling Spyder from the command line with the switch ``--reset``, i.e. a command like ``spyder --reset``. Objects in the variable explorer -------------------------------- Right-clicking on arrays in the variable explorer gives options to plot and analyze these further. Double clicking on a dictionary object opens a new window that displays the dictionary nicely. You can also show and edit the contents of numpy arrays, lists, numbers and strings. Documentation string formatting ############################### If you want to add documentation for the code you are developing, we recommend you to write documentation strings (or *docstrings*) for it, using a special format called reStructuredText (`quick reference `__). This format also needs to follow a set of conventions called the `Numpydoc standard `__ If you follow those guidelines, you can obtain beautifully formatted docstrings in Spyder. For example, to get an ``average()`` function look like this in the Spyder Help pane: .. image:: images/spyder-nice-docstring-rendering.png :align: center you need to format the documentation string as follows .. code-block:: python def average(a, b): """ Given two numbers a and b, return their average value. Parameters ---------- a : number A number b : number Another number Returns ------- res : number The average of a and b, computed using 0.5*(a + b) Example ------- >>> average(5, 10) 7.5 """ return (a + b) * 0.5 What matters here, is that the word ``Parameters`` is used, and underlined. The line ``a : number`` shows us that the type of the parameter ``a`` is ``number``. In the next line, which is indented, we can write a more extended explanation of what this variable represents, what conditions the allowed types have to fulfill, etc. The same for all Parameters, and also for the returned value. Often it is a good idea to include an example too, as shown. Debugging ######### Line by line step execution of code ----------------------------------- Activating the debug mode (with the ``Debug > Debug`` menu option or Ctrl+F5) starts the Python debugger (Pdb) if the Python console is active, or the IPython debugger (ipdb) if the IPython console is active. After doing that, the Editor pane will highlight the line that is about to be executed, and the Variable Explorer will display variables in the current context of the point of program execution. (It only displays 'numerical' and array type of variables, i.e. not function or class objects) After entering debug mode, you can execute the code line by line using the ``Step`` button of the Debug toolbar: .. image:: images/debug-step-over.png :align: center or the shortcut Ctrl+F10. You can also inspect how a particular function is working by stepping into it with the ``Step into`` button .. image:: images/debug-step-in.png :align: center or the shortcut Ctrl+F11. Finally, to get out of a function and continue with the next line you need to use the ``Step return`` button .. image:: images/debug-step-out.png :align: center or the shortcut Ctrl+F12. If you prefer to inspect your program at a specific point, you need to insert a *breakpoint* by pressing F12 on the line on which you want to stop. After that a red dot will be placed next to the line and you can press the ``Continue`` button .. image:: images/debug-continue.png :align: center (after entering debug mode) to stop the execution at that line. .. note:: You can also control the debugging process by issuing these commands in the console prompt: * ``n`` to move to the Next statement. * ``s`` to Step into the current statement. If this is a function call, step into that function. * ``r`` to complete all statements in the current function and Return from that function before returning control. * ``p`` to print values of variables, for example ``p x`` will print the value of the variable ``x``. At the debugger prompt, you can also *change* values of variables. For example, to modify a variable ``x`` at the IPython debugger prompt, you can say ``ipdb > x = 42`` and the debugger will carry on with ``x`` being bound to ``42``. You can also call functions, and do many others things. Try this example:: def demo(x): for i in range(5): print("i={}, x={}".format(i, x)) x = x + 1 demo(0) If we execute this (``Run > Run``), we should see the output:: i=0, x=0 i=1, x=1 i=2, x=2 i=3, x=3 i=4, x=4 Now execute this using the debugger (``Debug > Debug``), press the ``Step button`` until the highlighted line reaches the ``demo(0)`` function call, then press the ``Step into`` to inspect this function. Keep pressing the ``Step button`` to execute the next lines. Then, modify ``x`` by typing ``x=10`` in the debugger prompt. You see x changing in the Variable Explorer. You should also see ``x`` changing when its value is printed as part of the ``demo()`` function. (The printed output appears between your debugger commands and responses.) This debugging ability to execute code line by line, to inspect variables as they change, and to modify them manually is a powerful tool to understand what a piece of code is doing (and to correct it if desired). To leave the debugging mode, you can type ``exit`` or select from the menu ``Debug > Debugging Control > Exit`` Debugging once an exception has occurred with IPython ----------------------------------------------------- In the IPython console, we can call ``%debug`` straight after an exception has been raised: this will start the IPython debug mode, which allows inspection of local variables at the point where the exception occurred as described above. This is a lot more efficient than adding ``print`` statements to the code an running it again. If you use this, you may also want to use the commands ``up`` (i.e. press ``u`` at the debugger) and ``down`` (i.e. press ``d``) which navigate the inspection point up and down the stack. (Up the stack means to the functions that have called the current function; down is the opposite direction.) Plotting ######## Plotting with the IPython console --------------------------------- Assuming we use an IPython console with version >= 1.0.0, we can decide whether figures created with matplotlib/pylab will show 1. *inline*, i.e. inside the IPython console, or whether they should 2. appear inside a new window. Option 1 is convenient to save a record of the interactive session (section `Shortcuts for useful functions`_ lists a shortcut to save the IPython console to an html file). Option 2 allows to interactively zoom into the figure, manipulate it a little, and save the figure to different file formats via a menu the window it contains has. The command to get the figures to appear *inline* in the IPython console is:: In [3]: %matplotlib inline The command to get figures appear in their own window (which technically is a Qt window) is:: In [4]: %matplotlib qt The Spyder preferences can be used to customize the default behavior (in particular ``Preferences > IPython Console > Graphics > Activate Support`` to switch into inline plotting). Here are two lines you can use to quickly create a plot and test this:: In [5]: import pylab In [6]: pylab.plot(range(10), 'o') Plotting with the Python console -------------------------------- If we use the Python console, all plots will appear in a new window (there is no way of making it appear inline inside the Python console - this only works for the IPython Console). Here is a brief example that you can use to create and display a plot:: >>> import pylab >>> pylab.plot(range(10), 'o') If you execute your code in a dedicated console, you need to use matplotlib's or pylab's ``show()`` command in your code to make a plot appear, like this: ``pylab.show()``. Note that the ``show()`` command will bind the focus to new window that has appeared, and that you will need to close that window before Spyder can accept any further commands or respond to interaction. If you cannot see the new window, check whether it may have appeared behind the Spyder window, or be partly hidden. Historical note ############### This tutorial is based on `notes `__ by `Hans Fangohr `__, that are used at the `University of Southampton `__ to `teach Python for computational modelling `__ to undergraduate engineers and postgraduate PhD students for the `Next Generation Computational Modelling `__ doctoral training centre. spyder-3.2.6/spyder/utils/help/__init__.py0000664000175000017500000000061213026261006021324 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT or BSD Licenses # (See every file for its license) """ spyder.utils.help ================= Configuration files for the Help plugin rich text mode """ import sys from spyder.config.base import get_module_source_path sys.path.insert(0, get_module_source_path(__name__)) spyder-3.2.6/spyder/utils/environ.py0000664000175000017500000001176713211142272020331 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Environment variable utilities """ # Standard library imports import os # Third party imports from qtpy.QtWidgets import QDialog, QMessageBox # Local imports from spyder.config.base import _ from spyder.utils import icon_manager as ima from spyder.widgets.variableexplorer.collectionseditor import CollectionsEditor def envdict2listdict(envdict): """Dict --> Dict of lists""" sep = os.path.pathsep for key in envdict: if sep in envdict[key]: envdict[key] = [path.strip() for path in envdict[key].split(sep)] return envdict def listdict2envdict(listdict): """Dict of lists --> Dict""" for key in listdict: if isinstance(listdict[key], list): listdict[key] = os.path.pathsep.join(listdict[key]) return listdict class RemoteEnvDialog(CollectionsEditor): """Remote process environment variables dialog.""" def __init__(self, environ, parent=None): super(RemoteEnvDialog, self).__init__(parent) self.setup(envdict2listdict(environ), title=_("Environment variables"), width=700, readonly=True, icon=ima.icon('environ')) class EnvDialog(RemoteEnvDialog): """Environment variables Dialog""" def __init__(self): RemoteEnvDialog.__init__(self, dict(os.environ)) # For Windows only try: from spyder.py3compat import winreg def get_user_env(): """Return HKCU (current user) environment variables""" reg = dict() key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Environment") for index in range(0, winreg.QueryInfoKey(key)[1]): try: value = winreg.EnumValue(key, index) reg[value[0]] = value[1] except: break return envdict2listdict(reg) def set_user_env(reg, parent=None): """Set HKCU (current user) environment variables""" reg = listdict2envdict(reg) types = dict() key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Environment") for name in reg: try: _x, types[name] = winreg.QueryValueEx(key, name) except WindowsError: types[name] = winreg.REG_EXPAND_SZ key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Environment", 0, winreg.KEY_SET_VALUE) for name in reg: winreg.SetValueEx(key, name, 0, types[name], reg[name]) try: from win32gui import SendMessageTimeout from win32con import (HWND_BROADCAST, WM_SETTINGCHANGE, SMTO_ABORTIFHUNG) SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, "Environment", SMTO_ABORTIFHUNG, 5000) except ImportError: QMessageBox.warning(parent, _("Warning"), _("Module pywin32 was not found.
    " "Please restart this Windows session " "(not the computer) for changes to take effect.")) class WinUserEnvDialog(CollectionsEditor): """Windows User Environment Variables Editor""" def __init__(self, parent=None): super(WinUserEnvDialog, self).__init__(parent) self.setup(get_user_env(), title="HKEY_CURRENT_USER\Environment", width=600) if parent is None: parent = self QMessageBox.warning(parent, _("Warning"), _("If you accept changes, " "this will modify the current user environment " "variables directly in Windows registry. " "Use it with precautions, at your own risks.
    " "
    Note that for changes to take effect, you will " "need to restart the parent process of this applica" "tion (simply restart Spyder if you have executed it " "from a Windows shortcut, otherwise restart any " "application from which you may have executed it, " "like Python(x,y) Home for example)")) def accept(self): """Reimplement Qt method""" set_user_env(listdict2envdict(self.get_value()), parent=self) QDialog.accept(self) except ImportError: pass def main(): """Run Windows environment variable editor""" from spyder.utils.qthelpers import qapplication app = qapplication() if os.name == 'nt': dialog = WinUserEnvDialog() else: dialog = EnvDialog() dialog.show() app.exec_() if __name__ == "__main__": main() spyder-3.2.6/spyder/utils/stringmatching.py0000664000175000017500000002371113156676663021712 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ String search and match utilities usefull when filtering a list of texts. """ import re NOT_FOUND_SCORE = -1 NO_SCORE = 0 def get_search_regex(query, ignore_case=True): """Returns a compiled regex pattern to search for query letters in order. Parameters ---------- query : str String to search in another string (in order of character occurrence). ignore_case : True Optional value perform a case insensitive search (True by default). Returns ------- pattern : SRE_Pattern Notes ----- This function adds '.*' between the query characters and compiles the resulting regular expression. """ regex_text = [char for char in query if char != ' '] regex_text = '.*'.join(regex_text) regex = '({0})'.format(regex_text) if ignore_case: pattern = re.compile(regex, re.IGNORECASE) else: pattern = re.compile(regex) return pattern def get_search_score(query, choice, ignore_case=True, apply_regex=True, template='{}'): """Returns a tuple with the enriched text (if a template is provided) and a score for the match. Parameters ---------- query : str String with letters to search in choice (in order of appearance). choice : str Sentence/words in which to search for the 'query' letters. ignore_case : bool, optional Optional value perform a case insensitive search (True by default). apply_regex : bool, optional Optional value (True by default) to perform a regex search. Useful when this function is called directly. template : str, optional Optional template string to surround letters found in choices. This is useful when using a rich text editor ('{}' by default). Examples: '{}', '{}', '{}' Returns ------- results : tuple Tuples where the first item is the text (enriched if a template was used) and the second item is a search score. Notes ----- The score is given according the following precedence (high to low): - Letters in one word and no spaces with exact match. Example: 'up' in 'up stroke' - Letters in one word and no spaces with partial match. Example: 'up' in 'upstream stroke' - Letters in one word but with skip letters. Example: 'cls' in 'close up' - Letters in two or more words Example: 'cls' in 'car lost' """ original_choice = choice result = (original_choice, NOT_FOUND_SCORE) # Handle empty string case if not query: return result if ignore_case: query = query.lower() choice = choice.lower() if apply_regex: pattern = get_search_regex(query, ignore_case=ignore_case) r = re.search(pattern, choice) if r is None: return result else: sep = u'-' # Matches will be replaced by this character let = u'x' # Nonmatches (except spaed) will be replaced by this score = 0 exact_words = [query == word for word in choice.split(u' ')] partial_words = [query in word for word in choice.split(u' ')] if any(exact_words) or any(partial_words): pos_start = choice.find(query) pos_end = pos_start + len(query) score += pos_start text = choice.replace(query, sep*len(query), 1) enriched_text = original_choice[:pos_start] +\ template.format(original_choice[pos_start:pos_end]) +\ original_choice[pos_end:] if any(exact_words): # Check if the query words exists in a word with exact match score += 1 elif any(partial_words): # Check if the query words exists in a word with partial match score += 100 else: # Check letter by letter text = [l for l in original_choice] if ignore_case: temp_text = [l.lower() for l in original_choice] else: temp_text = text[:] # Give points to start of string score += temp_text.index(query[0]) # Find the query letters and replace them by `sep`, also apply # template as needed for enricching the letters in the text enriched_text = text[:] for char in query: if char != u'' and char in temp_text: index = temp_text.index(char) enriched_text[index] = template.format(text[index]) text[index] = sep temp_text = [u' ']*(index + 1) + temp_text[index+1:] enriched_text = u''.join(enriched_text) patterns_text = [] for i, char in enumerate(text): if char != u' ' and char != sep: new_char = let else: new_char = char patterns_text.append(new_char) patterns_text = u''.join(patterns_text) for i in reversed(range(1, len(query) + 1)): score += (len(query) - patterns_text.count(sep*i))*100000 temp = patterns_text.split(sep) while u'' in temp: temp.remove(u'') if not patterns_text.startswith(sep): temp = temp[1:] if not patterns_text.endswith(sep): temp = temp[:-1] for pat in temp: score += pat.count(u' ')*10000 score += pat.count(let)*100 return original_choice, enriched_text, score def get_search_scores(query, choices, ignore_case=True, template='{}', valid_only=False, sort=False): """Search for query inside choices and return a list of tuples. Returns a list of tuples of text with the enriched text (if a template is provided) and a score for the match. Lower scores imply a better match. Parameters ---------- query : str String with letters to search in each choice (in order of appearance). choices : list of str List of sentences/words in which to search for the 'query' letters. ignore_case : bool, optional Optional value perform a case insensitive search (True by default). template : str, optional Optional template string to surround letters found in choices. This is useful when using a rich text editor ('{}' by default). Examples: '{}', '{}', '{}' Returns ------- results : list of tuples List of tuples where the first item is the text (enriched if a template was used) and a search score. Lower scores means better match. """ # First remove spaces from query query = query.replace(' ', '') pattern = get_search_regex(query, ignore_case) results = [] for choice in choices: r = re.search(pattern, choice) if query and r: result = get_search_score(query, choice, ignore_case=ignore_case, apply_regex=False, template=template) else: if query: result = (choice, choice, NOT_FOUND_SCORE) else: result = (choice, choice, NO_SCORE) if valid_only: if result[-1] != NOT_FOUND_SCORE: results.append(result) else: results.append(result) if sort: results = sorted(results, key=lambda row: row[-1]) return results def test(): template = '{0}' names = ['close pane', 'debug continue', 'debug exit', 'debug step into', 'debug step over', 'debug step return', 'fullscreen mode', 'layout preferences', 'lock unlock panes', 'maximize pane', 'preferences', 'quit', 'restart', 'save current layout', 'switch to breakpoints', 'switch to console', 'switch to editor', 'switch to explorer', 'switch to find_in_files', 'switch to historylog', 'switch to help', 'switch to ipython_console', 'switch to onlinehelp', 'switch to outline_explorer', 'switch to project_explorer', 'switch to variable_explorer', 'use next layout', 'use previous layout', 'clear line', 'clear shell', 'inspect current object', 'blockcomment', 'breakpoint', 'close all', 'code completion', 'conditional breakpoint', 'configure', 'copy', 'copy line', 'cut', 'debug', 'debug with winpdb', 'delete', 'delete line', 'duplicate line', 'end of document', 'end of line', 'file list management', 'find next', 'find previous', 'find text', 'go to definition', 'go to line', 'go to next file', 'go to previous file', 'inspect current object', 'kill next word', 'kill previous word', 'kill to line end', 'kill to line start', 'last edit location', 'move line down', 'move line up', 'new file', 'next char', 'next cursor position', 'next line', 'next word', 'open file', 'paste', 'previous char', 'previous cursor position', 'previous line', 'previous word', 'print', 're-run last script', 'redo', 'replace text', 'rotate kill ring', 'run', 'run selection', 'save all', 'save as', 'save file', 'select all', 'show/hide outline', 'show/hide project explorer', 'start of document', 'start of line', 'toggle comment', 'unblockcomment', 'undo', 'yank', 'run profiler', 'run analysis'] a = get_search_scores('lay', names, template=template, ) b = get_search_scores('lay', names, template=template, valid_only=True, sort=True) # Full results for r in a: print(r) # spyder: test-skip # Ordered and filtered results print('\n') # spyder: test-skip for r in b: print(r) # spyder: test-skip if __name__ == '__main__': test() spyder-3.2.6/spyder/utils/codeanalysis.py0000664000175000017500000001657213211142272021326 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Source code analysis utilities """ import sys import re import os import tempfile import traceback # Local import from spyder.config.base import _, DEBUG from spyder.utils import programs, encoding from spyder.py3compat import to_text_string, to_binary_string, PY3 from spyder import dependencies DEBUG_EDITOR = DEBUG >= 3 #============================================================================== # Pyflakes/pep8 code analysis #============================================================================== TASKS_PATTERN = r"(^|#)[ ]*(TODO|FIXME|XXX|HINT|TIP|@todo|" \ r"HACK|BUG|OPTIMIZE|!!!|\?\?\?)([^#]*)" #TODO: this is a test for the following function def find_tasks(source_code): """Find tasks in source code (TODO, FIXME, XXX, ...)""" results = [] for line, text in enumerate(source_code.splitlines()): for todo in re.findall(TASKS_PATTERN, text): results.append((todo[-1].strip().capitalize(), line+1)) return results def check_with_pyflakes(source_code, filename=None): """Check source code with pyflakes Returns an empty list if pyflakes is not installed""" try: if filename is None: filename = '' try: source_code += '\n' except TypeError: # Python 3 source_code += to_binary_string('\n') import _ast from pyflakes.checker import Checker # First, compile into an AST and handle syntax errors. try: tree = compile(source_code, filename, "exec", _ast.PyCF_ONLY_AST) except SyntaxError as value: # If there's an encoding problem with the file, the text is None. if value.text is None: results = [] else: results = [(value.args[0], value.lineno)] except (ValueError, TypeError): # Example of ValueError: file contains invalid \x escape character # (see http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=674797) # Example of TypeError: file contains null character # (see http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=674796) results = [] else: # Okay, it's syntactically valid. Now check it. w = Checker(tree, filename) w.messages.sort(key=lambda x: x.lineno) results = [] coding = encoding.get_coding(source_code) lines = source_code.splitlines() for warning in w.messages: if 'analysis:ignore' not in \ to_text_string(lines[warning.lineno-1], coding): results.append((warning.message % warning.message_args, warning.lineno)) except Exception: # Never return None to avoid lock in spyder/widgets/editor.py # See Issue 1547 results = [] if DEBUG_EDITOR: traceback.print_exc() # Print exception in internal console return results # Required version: # Why 0.5 (Python2)? Because it's based on _ast (thread-safe) PYFLAKES_REQVER = '>=0.6.0' if PY3 else '>=0.5.0' dependencies.add("pyflakes", _("Real-time code analysis on the Editor"), required_version=PYFLAKES_REQVER) PYCODESTYLE_REQVER = '>=2.3' dependencies.add("pycodestyle", _("Real-time code style analysis on the Editor"), required_version=PYCODESTYLE_REQVER) def is_pyflakes_installed(): """Return True if pyflakes required version is installed""" return programs.is_module_installed('pyflakes', PYFLAKES_REQVER) def get_checker_executable(name): """Return checker executable in the form of a list of arguments for subprocess.Popen""" if programs.is_program_installed(name): # Checker is properly installed return [name] else: path1 = programs.python_script_exists(package=None, module=name+'_script') path2 = programs.python_script_exists(package=None, module=name) if path1 is not None: # checker_script.py is available # Checker script is available but has not been installed # (this may work with pyflakes) return [sys.executable, path1] elif path2 is not None: # checker.py is available # Checker package is available but its script has not been # installed (this works with pycodestyle but not with pyflakes) return [sys.executable, path2] def check(args, source_code, filename=None, options=None): """Check source code with checker defined with *args* (list) Returns an empty list if checker is not installed""" if args is None: return [] if options is not None: args += options if any(['pyflakes' in arg for arg in args]): # Pyflakes requires an ending new line (pycodestyle don't! -- see Issue 1123) # Note: this code is not used right now as it is faster to invoke # pyflakes in current Python interpreter (see `check_with_pyflakes` # function above) than calling it through a subprocess source_code += '\n' if filename is None: # Creating a temporary file because file does not exist yet # or is not up-to-date tempfd = tempfile.NamedTemporaryFile(suffix=".py", delete=False) tempfd.write(source_code) tempfd.close() args.append(tempfd.name) else: args.append(filename) cmd = args[0] cmdargs = args[1:] proc = programs.run_program(cmd, cmdargs) output = proc.communicate()[0].strip().decode().splitlines() if filename is None: os.unlink(tempfd.name) results = [] coding = encoding.get_coding(source_code) lines = source_code.splitlines() for line in output: lineno = int(re.search(r'(\:[\d]+\:)', line).group()[1:-1]) try: text = to_text_string(lines[lineno-1], coding) except TypeError: text = to_text_string(lines[lineno-1]) if 'analysis:ignore' not in text: message = line[line.find(': ')+2:] results.append((message, lineno)) return results def check_with_pep8(source_code, filename=None): """Check source code with pycodestyle""" try: args = get_checker_executable('pycodestyle') results = check(args, source_code, filename=filename, options=['-r']) except Exception: # Never return None to avoid lock in spyder/widgets/editor.py # See Issue 1547 results = [] if DEBUG_EDITOR: traceback.print_exc() # Print exception in internal console return results if __name__ == '__main__': # fname = __file__ fname = os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, 'bootstrap.py') code = open(fname).read() check_results = check_with_pyflakes(code, fname)+\ check_with_pep8(code, fname)+find_tasks(code) # check_results = check_with_pep8(code, fname) for message, line in check_results: sys.stdout.write("Message: %s -- Line: %s\n" % (message, line)) spyder-3.2.6/spyder/utils/programs.py0000664000175000017500000004275013224121062020475 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Running programs utilities""" from __future__ import print_function from distutils.version import LooseVersion from getpass import getuser import imp import inspect import os import os.path as osp import re import subprocess import sys import tempfile # Local imports from spyder.utils import encoding from spyder.utils.misc import get_python_executable from spyder.py3compat import PY2, is_text_string, to_text_string class ProgramError(Exception): pass if os.name == 'nt': TEMPDIR = tempfile.gettempdir() + osp.sep + 'spyder' else: username = encoding.to_unicode_from_fs(getuser()) TEMPDIR = tempfile.gettempdir() + osp.sep + 'spyder-' + username def is_program_installed(basename): """ Return program absolute path if installed in PATH. Otherwise, return None """ for path in os.environ["PATH"].split(os.pathsep): abspath = osp.join(path, basename) if osp.isfile(abspath): return abspath def find_program(basename): """ Find program in PATH and return absolute path Try adding .exe or .bat to basename on Windows platforms (return None if not found) """ names = [basename] if os.name == 'nt': # Windows platforms extensions = ('.exe', '.bat', '.cmd') if not basename.endswith(extensions): names = [basename+ext for ext in extensions]+[basename] for name in names: path = is_program_installed(name) if path: return path def alter_subprocess_kwargs_by_platform(**kwargs): """ Given a dict, populate kwargs to create a generally useful default setup for running subprocess processes on different platforms. For example, `close_fds` is set on posix and creation of a new console window is disabled on Windows. This function will alter the given kwargs and return the modified dict. """ kwargs.setdefault('close_fds', os.name == 'posix') if os.name == 'nt': CONSOLE_CREATION_FLAGS = 0 # Default value # See: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863%28v=vs.85%29.aspx CREATE_NO_WINDOW = 0x08000000 # We "or" them together CONSOLE_CREATION_FLAGS |= CREATE_NO_WINDOW kwargs.setdefault('creationflags', CONSOLE_CREATION_FLAGS) return kwargs def run_shell_command(cmdstr, **subprocess_kwargs): """ Execute the given shell command. Note that *args and **kwargs will be passed to the subprocess call. If 'shell' is given in subprocess_kwargs it must be True, otherwise ProgramError will be raised. . If 'executable' is not given in subprocess_kwargs, it will be set to the value of the SHELL environment variable. Note that stdin, stdout and stderr will be set by default to PIPE unless specified in subprocess_kwargs. :str cmdstr: The string run as a shell command. :subprocess_kwargs: These will be passed to subprocess.Popen. """ if 'shell' in subprocess_kwargs and not subprocess_kwargs['shell']: raise ProgramError( 'The "shell" kwarg may be omitted, but if ' 'provided it must be True.') else: subprocess_kwargs['shell'] = True if 'executable' not in subprocess_kwargs: subprocess_kwargs['executable'] = os.getenv('SHELL') for stream in ['stdin', 'stdout', 'stderr']: subprocess_kwargs.setdefault(stream, subprocess.PIPE) subprocess_kwargs = alter_subprocess_kwargs_by_platform( **subprocess_kwargs) return subprocess.Popen(cmdstr, **subprocess_kwargs) def run_program(program, args=None, **subprocess_kwargs): """ Run program in a separate process. NOTE: returns the process object created by `subprocess.Popen()`. This can be used with `proc.communicate()` for example. If 'shell' appears in the kwargs, it must be False, otherwise ProgramError will be raised. If only the program name is given and not the full path, a lookup will be performed to find the program. If the lookup fails, ProgramError will be raised. Note that stdin, stdout and stderr will be set by default to PIPE unless specified in subprocess_kwargs. :str program: The name of the program to run. :list args: The program arguments. :subprocess_kwargs: These will be passed to subprocess.Popen. """ if 'shell' in subprocess_kwargs and subprocess_kwargs['shell']: raise ProgramError( "This function is only for non-shell programs, " "use run_shell_command() instead.") fullcmd = find_program(program) if not fullcmd: raise ProgramError("Program %s was not found" % program) # As per subprocess, we make a complete list of prog+args fullcmd = [fullcmd] + (args or []) for stream in ['stdin', 'stdout', 'stderr']: subprocess_kwargs.setdefault(stream, subprocess.PIPE) subprocess_kwargs = alter_subprocess_kwargs_by_platform( **subprocess_kwargs) return subprocess.Popen(fullcmd, **subprocess_kwargs) def start_file(filename): """ Generalized os.startfile for all platforms supported by Qt This function is simply wrapping QDesktopServices.openUrl Returns True if successfull, otherwise returns False. """ from qtpy.QtCore import QUrl from qtpy.QtGui import QDesktopServices # We need to use setUrl instead of setPath because this is the only # cross-platform way to open external files. setPath fails completely on # Mac and doesn't open non-ascii files on Linux. # Fixes Issue 740 url = QUrl() url.setUrl(filename) return QDesktopServices.openUrl(url) def python_script_exists(package=None, module=None): """ Return absolute path if Python script exists (otherwise, return None) package=None -> module is in sys.path (standard library modules) """ assert module is not None try: if package is None: path = imp.find_module(module)[1] else: path = osp.join(imp.find_module(package)[1], module)+'.py' except ImportError: return if not osp.isfile(path): path += 'w' if osp.isfile(path): return path def run_python_script(package=None, module=None, args=[], p_args=[]): """ Run Python script in a separate process package=None -> module is in sys.path (standard library modules) """ assert module is not None assert isinstance(args, (tuple, list)) and isinstance(p_args, (tuple, list)) path = python_script_exists(package, module) run_program(sys.executable, p_args + [path] + args) def shell_split(text): """ Split the string `text` using shell-like syntax This avoids breaking single/double-quoted strings (e.g. containing strings with spaces). This function is almost equivalent to the shlex.split function (see standard library `shlex`) except that it is supporting unicode strings (shlex does not support unicode until Python 2.7.3). """ assert is_text_string(text) # in case a QString is passed... pattern = r'(\s+|(?': return LooseVersion(actver) > LooseVersion(version) elif cmp_op == '>=': return LooseVersion(actver) >= LooseVersion(version) elif cmp_op == '=': return LooseVersion(actver) == LooseVersion(version) elif cmp_op == '<': return LooseVersion(actver) < LooseVersion(version) elif cmp_op == '<=': return LooseVersion(actver) <= LooseVersion(version) else: return False except TypeError: return True def get_module_version(module_name): """Return module version or None if version can't be retrieved.""" mod = __import__(module_name) return getattr(mod, '__version__', getattr(mod, 'VERSION', None)) def is_module_installed(module_name, version=None, installed_version=None, interpreter=None): """ Return True if module *module_name* is installed If version is not None, checking module version (module must have an attribute named '__version__') version may starts with =, >=, > or < to specify the exact requirement ; multiple conditions may be separated by ';' (e.g. '>=0.13;<1.0') interpreter: check if a module is installed with a given version in a determined interpreter """ if interpreter: if osp.isfile(interpreter) and ('python' in interpreter): checkver = inspect.getsource(check_version) get_modver = inspect.getsource(get_module_version) stable_ver = inspect.getsource(is_stable_version) ismod_inst = inspect.getsource(is_module_installed) fd, script = tempfile.mkstemp(suffix='.py', dir=TEMPDIR) with os.fdopen(fd, 'w') as f: f.write("# -*- coding: utf-8 -*-" + "\n\n") f.write("from distutils.version import LooseVersion" + "\n") f.write("import re" + "\n\n") f.write(stable_ver + "\n") f.write(checkver + "\n") f.write(get_modver + "\n") f.write(ismod_inst + "\n") if version: f.write("print(is_module_installed('%s','%s'))"\ % (module_name, version)) else: f.write("print(is_module_installed('%s'))" % module_name) try: proc = run_program(interpreter, [script]) output, _err = proc.communicate() except subprocess.CalledProcessError: return True if output: # TODO: Check why output could be empty! return eval(output.decode()) else: return False else: # Try to not take a wrong decision if there is no interpreter # available (needed for the change_pystartup method of ExtConsole # config page) return True else: if installed_version is None: try: actver = get_module_version(module_name) except: # Module is not installed return False else: actver = installed_version if actver is None and version is not None: return False elif version is None: return True else: if ';' in version: output = True for ver in version.split(';'): output = output and is_module_installed(module_name, ver) return output match = re.search('[0-9]', version) assert match is not None, "Invalid version number" symb = version[:match.start()] if not symb: symb = '=' assert symb in ('>=', '>', '=', '<', '<='),\ "Invalid version condition '%s'" % symb version = version[match.start():] return check_version(actver, version, symb) def is_python_interpreter_valid_name(filename): """Check that the python interpreter file has a valid name.""" pattern = r'.*python(\d\.?\d*)?(w)?(.exe)?$' if re.match(pattern, filename, flags=re.I) is None: return False else: return True def is_python_interpreter(filename): """Evaluate wether a file is a python interpreter or not.""" real_filename = os.path.realpath(filename) # To follow symlink if existent if (not osp.isfile(real_filename) or encoding.is_text_file(real_filename) or not is_python_interpreter_valid_name(filename)): return False try: proc = run_program(filename, ["-h"]) output = to_text_string(proc.communicate()[0]) valid = ("Options and arguments (and corresponding environment " "variables)") if 'usage:' in output and valid in output: return True else: return False except: return False spyder-3.2.6/spyder/utils/vcs.py0000664000175000017500000001162413156676663017464 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Utilities for version control systems""" from __future__ import print_function import sys import os.path as osp import subprocess # Local imports from spyder.utils import programs from spyder.utils.misc import abspardir from spyder.py3compat import PY3 SUPPORTED = [ { 'name': 'Mercurial', 'rootdir': '.hg', 'actions': dict( commit=( ('thg', ['commit']), ('hgtk', ['commit']) ), browse=( ('thg', ['log']), ('hgtk', ['log']) )) }, { 'name': 'Git', 'rootdir': '.git', 'actions': dict( commit=( ('git', ['gui']), ), browse=( ('gitk', []), )) }] class ActionToolNotFound(RuntimeError): """Exception to transmit information about supported tools for failed attempt to execute given action""" def __init__(self, vcsname, action, tools): RuntimeError.__init__(self) self.vcsname = vcsname self.action = action self.tools = tools def get_vcs_info(path): """Return support status dict if path is under VCS root""" for info in SUPPORTED: vcs_path = osp.join(path, info['rootdir']) if osp.isdir(vcs_path): return info def get_vcs_root(path): """Return VCS root directory path Return None if path is not within a supported VCS repository""" previous_path = path while get_vcs_info(path) is None: path = abspardir(path) if path == previous_path: return else: previous_path = path return osp.abspath(path) def is_vcs_repository(path): """Return True if path is a supported VCS repository""" return get_vcs_root(path) is not None def run_vcs_tool(path, action): """If path is a valid VCS repository, run the corresponding VCS tool Supported VCS actions: 'commit', 'browse' Return False if the VCS tool is not installed""" info = get_vcs_info(get_vcs_root(path)) tools = info['actions'][action] for tool, args in tools: if programs.find_program(tool): programs.run_program(tool, args, cwd=path) return else: cmdnames = [name for name, args in tools] raise ActionToolNotFound(info['name'], action, cmdnames) def is_hg_installed(): """Return True if Mercurial is installed""" return programs.find_program('hg') is not None def get_hg_revision(repopath): """Return Mercurial revision for the repository located at repopath Result is a tuple (global, local, branch), with None values on error For example: >>> get_hg_revision(".") ('eba7273c69df+', '2015+', 'default') """ try: assert osp.isdir(osp.join(repopath, '.hg')) proc = programs.run_program('hg', ['id', '-nib', repopath]) output, _err = proc.communicate() # output is now: ('eba7273c69df+ 2015+ default\n', None) # Split 2 times max to allow spaces in branch names. return tuple(output.decode().strip().split(None, 2)) except (subprocess.CalledProcessError, AssertionError, AttributeError): return (None, None, None) def get_git_revision(repopath): """ Return Git revision for the repository located at repopath Result is a tuple (latest commit hash, branch), with None values on error """ try: git = programs.find_program('git') assert git is not None and osp.isdir(osp.join(repopath, '.git')) commit = programs.run_program(git, ['rev-parse', '--short', 'HEAD'], cwd=repopath).communicate() commit = commit[0].strip() if PY3: commit = commit.decode(sys.getdefaultencoding()) # Branch branches = programs.run_program(git, ['branch'], cwd=repopath).communicate() branches = branches[0] if PY3: branches = branches.decode(sys.getdefaultencoding()) branches = branches.split('\n') active_branch = [b for b in branches if b.startswith('*')] if len(active_branch) != 1: branch = None else: branch = active_branch[0].split(None, 1)[1] return commit, branch except (subprocess.CalledProcessError, AssertionError, AttributeError): return None, None if __name__ == '__main__': print(get_vcs_root(osp.dirname(__file__))) # spyder: test-skip print(get_vcs_root(r'D:\Python\ipython\IPython\kernel')) # spyder: test-skip #run_vcs_tool(r'D:\Python\userconfig\userconfig', 'commit') print(get_git_revision(osp.dirname(__file__)+"/../..")) # spyder: test-skip print(get_git_revision('/')) # spyder: test-skip spyder-3.2.6/spyder/utils/syntaxhighlighters.py0000664000175000017500000022575013224740762022614 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Editor widget syntax highlighters based on QtGui.QSyntaxHighlighter (Python syntax highlighting rules are inspired from idlelib) """ # Standard library imports from __future__ import print_function import keyword import os import re # Third party imports from qtpy.QtCore import Qt from qtpy.QtGui import (QColor, QCursor, QFont, QSyntaxHighlighter, QTextCharFormat, QTextOption) from qtpy.QtWidgets import QApplication # Local imports from spyder import dependencies from spyder.config.base import _ from spyder.config.main import CONF from spyder.py3compat import builtins, is_text_string, to_text_string from spyder.utils.sourcecode import CELL_LANGUAGES from spyder.utils.workers import WorkerManager PYGMENTS_REQVER = '>=2.0' dependencies.add("pygments", _("Syntax highlighting for Matlab, Julia and " "other file types"), required_version=PYGMENTS_REQVER) # ============================================================================= # Constants # ============================================================================= COLOR_SCHEME_KEYS = { "background": _("Background:"), "currentline": _("Current line:"), "currentcell": _("Current cell:"), "occurrence": _("Occurrence:"), "ctrlclick": _("Link:"), "sideareas": _("Side areas:"), "matched_p": _("Matched
    parens:"), "unmatched_p": _("Unmatched
    parens:"), "normal": _("Normal text:"), "keyword": _("Keyword:"), "builtin": _("Builtin:"), "definition": _("Definition:"), "comment": _("Comment:"), "string": _("String:"), "number": _("Number:"), "instance": _("Instance:"), } COLOR_SCHEME_NAMES = CONF.get('color_schemes', 'names') # Mapping for file extensions that use Pygments highlighting but should use # different lexers than Pygments' autodetection suggests. Keys are file # extensions or tuples of extensions, values are Pygments lexer names. CUSTOM_EXTENSION_LEXER = {'.ipynb': 'json', '.txt': 'text', '.nt': 'bat', '.m': 'matlab', ('.properties', '.session', '.inf', '.reg', '.url', '.cfg', '.cnf', '.aut', '.iss'): 'ini'} # Convert custom extensions into a one-to-one mapping for easier lookup. custom_extension_lexer_mapping = {} for key, value in CUSTOM_EXTENSION_LEXER.items(): # Single key is mapped unchanged. if is_text_string(key): custom_extension_lexer_mapping[key] = value # Tuple of keys is iterated over and each is mapped to value. else: for k in key: custom_extension_lexer_mapping[k] = value #============================================================================== # Auxiliary functions #============================================================================== def get_color_scheme(name): """Get a color scheme from config using its name""" name = name.lower() scheme = {} for key in COLOR_SCHEME_KEYS: try: scheme[key] = CONF.get('color_schemes', name+'/'+key) except: scheme[key] = CONF.get('color_schemes', 'spyder/'+key) return scheme #============================================================================== # Syntax highlighting color schemes #============================================================================== class BaseSH(QSyntaxHighlighter): """Base Syntax Highlighter Class""" # Syntax highlighting rules: PROG = None BLANKPROG = re.compile("\s+") # Syntax highlighting states (from one text block to another): NORMAL = 0 # Syntax highlighting parameters. BLANK_ALPHA_FACTOR = 0.31 def __init__(self, parent, font=None, color_scheme='Spyder'): QSyntaxHighlighter.__init__(self, parent) self.outlineexplorer_data = {} self.font = font if is_text_string(color_scheme): self.color_scheme = get_color_scheme(color_scheme) else: self.color_scheme = color_scheme self.background_color = None self.currentline_color = None self.currentcell_color = None self.occurrence_color = None self.ctrlclick_color = None self.sideareas_color = None self.matched_p_color = None self.unmatched_p_color = None self.formats = None self.setup_formats(font) self.cell_separators = None def get_background_color(self): return QColor(self.background_color) def get_foreground_color(self): """Return foreground ('normal' text) color""" return self.formats["normal"].foreground().color() def get_currentline_color(self): return QColor(self.currentline_color) def get_currentcell_color(self): return QColor(self.currentcell_color) def get_occurrence_color(self): return QColor(self.occurrence_color) def get_ctrlclick_color(self): return QColor(self.ctrlclick_color) def get_sideareas_color(self): return QColor(self.sideareas_color) def get_matched_p_color(self): return QColor(self.matched_p_color) def get_unmatched_p_color(self): return QColor(self.unmatched_p_color) def get_comment_color(self): """ Return color for the comments """ return self.formats['comment'].foreground().color() def get_color_name(self, fmt): """Return color name assigned to a given format""" return self.formats[fmt].foreground().color().name() def setup_formats(self, font=None): base_format = QTextCharFormat() if font is not None: self.font = font if self.font is not None: base_format.setFont(self.font) self.formats = {} colors = self.color_scheme.copy() self.background_color = colors.pop("background") self.currentline_color = colors.pop("currentline") self.currentcell_color = colors.pop("currentcell") self.occurrence_color = colors.pop("occurrence") self.ctrlclick_color = colors.pop("ctrlclick") self.sideareas_color = colors.pop("sideareas") self.matched_p_color = colors.pop("matched_p") self.unmatched_p_color = colors.pop("unmatched_p") for name, (color, bold, italic) in list(colors.items()): format = QTextCharFormat(base_format) format.setForeground(QColor(color)) format.setBackground(QColor(self.background_color)) if bold: format.setFontWeight(QFont.Bold) format.setFontItalic(italic) self.formats[name] = format def set_color_scheme(self, color_scheme): if is_text_string(color_scheme): self.color_scheme = get_color_scheme(color_scheme) else: self.color_scheme = color_scheme self.setup_formats() self.rehighlight() def highlightBlock(self, text): raise NotImplementedError def highlight_spaces(self, text, offset=0): """ Make blank space less apparent by setting the foreground alpha. This only has an effect when 'Show blank space' is turned on. Derived classes could call this function at the end of highlightBlock(). """ flags_text = self.document().defaultTextOption().flags() show_blanks = flags_text & QTextOption.ShowTabsAndSpaces if show_blanks: format_leading = self.formats.get("leading", None) format_trailing = self.formats.get("trailing", None) match = self.BLANKPROG.search(text, offset) while match: start, end = match.span() start = max([0, start+offset]) end = max([0, end+offset]) # Format trailing spaces at the end of the line. if end == len(text) and format_trailing is not None: self.setFormat(start, end, format_trailing) # Format leading spaces, e.g. indentation. if start == 0 and format_leading is not None: self.setFormat(start, end, format_leading) format = self.format(start) color_foreground = format.foreground().color() alpha_new = self.BLANK_ALPHA_FACTOR * color_foreground.alphaF() color_foreground.setAlphaF(alpha_new) self.setFormat(start, end-start, color_foreground) match = self.BLANKPROG.search(text, match.end()) def get_outlineexplorer_data(self): return self.outlineexplorer_data def rehighlight(self): self.outlineexplorer_data = {} QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QSyntaxHighlighter.rehighlight(self) QApplication.restoreOverrideCursor() class TextSH(BaseSH): """Simple Text Syntax Highlighter Class (only highlight spaces)""" def highlightBlock(self, text): self.highlight_spaces(text) class GenericSH(BaseSH): """Generic Syntax Highlighter""" # Syntax highlighting rules: PROG = None # to be redefined in child classes def highlightBlock(self, text): text = to_text_string(text) self.setFormat(0, len(text), self.formats["normal"]) match = self.PROG.search(text) index = 0 while match: for key, value in list(match.groupdict().items()): if value: start, end = match.span(key) index += end-start self.setFormat(start, end-start, self.formats[key]) match = self.PROG.search(text, match.end()) self.highlight_spaces(text) #============================================================================== # Python syntax highlighter #============================================================================== def any(name, alternates): "Return a named group pattern matching list of alternates." return "(?P<%s>" % name + "|".join(alternates) + ")" def make_python_patterns(additional_keywords=[], additional_builtins=[]): "Strongly inspired from idlelib.ColorDelegator.make_pat" kwlist = keyword.kwlist + additional_keywords builtinlist = [str(name) for name in dir(builtins) if not name.startswith('_')] + additional_builtins repeated = set(kwlist) & set(builtinlist) for repeated_element in repeated: kwlist.remove(repeated_element) kw = r"\b" + any("keyword", kwlist) + r"\b" builtin = r"([^.'\"\\#]\b|^)" + any("builtin", builtinlist) + r"\b" comment = any("comment", [r"#[^\n]*"]) instance = any("instance", [r"\bself\b", (r"^\s*@([a-zA-Z_][a-zA-Z0-9_]*)" r"(\.[a-zA-Z_][a-zA-Z0-9_]*)*")]) number = any("number", [r"\b[+-]?[0-9]+[lLjJ]?\b", r"\b[+-]?0[xX][0-9A-Fa-f]+[lL]?\b", r"\b[+-]?0[oO][0-7]+[lL]?\b", r"\b[+-]?0[bB][01]+[lL]?\b", r"\b[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?[jJ]?\b"]) sqstring = r"(\b[rRuU])?'[^'\\\n]*(\\.[^'\\\n]*)*'?" dqstring = r'(\b[rRuU])?"[^"\\\n]*(\\.[^"\\\n]*)*"?' uf_sqstring = r"(\b[rRuU])?'[^'\\\n]*(\\.[^'\\\n]*)*(\\)$(?!')$" uf_dqstring = r'(\b[rRuU])?"[^"\\\n]*(\\.[^"\\\n]*)*(\\)$(?!")$' sq3string = r"(\b[rRuU])?'''[^'\\]*((\\.|'(?!''))[^'\\]*)*(''')?" dq3string = r'(\b[rRuU])?"""[^"\\]*((\\.|"(?!""))[^"\\]*)*(""")?' uf_sq3string = r"(\b[rRuU])?'''[^'\\]*((\\.|'(?!''))[^'\\]*)*(\\)?(?!''')$" uf_dq3string = r'(\b[rRuU])?"""[^"\\]*((\\.|"(?!""))[^"\\]*)*(\\)?(?!""")$' string = any("string", [sq3string, dq3string, sqstring, dqstring]) ufstring1 = any("uf_sqstring", [uf_sqstring]) ufstring2 = any("uf_dqstring", [uf_dqstring]) ufstring3 = any("uf_sq3string", [uf_sq3string]) ufstring4 = any("uf_dq3string", [uf_dq3string]) return "|".join([instance, kw, builtin, comment, ufstring1, ufstring2, ufstring3, ufstring4, string, number, any("SYNC", [r"\n"])]) class OutlineExplorerData(object): CLASS, FUNCTION, STATEMENT, COMMENT, CELL = list(range(5)) FUNCTION_TOKEN = 'def' CLASS_TOKEN = 'class' def __init__(self): self.text = None self.fold_level = None self.def_type = None self.def_name = None def is_not_class_nor_function(self): return self.def_type not in (self.CLASS, self.FUNCTION) def is_class_or_function(self): return self.def_type in (self.CLASS, self.FUNCTION) def is_comment(self): return self.def_type in (self.COMMENT, self.CELL) def get_class_name(self): if self.def_type == self.CLASS: return self.def_name def get_function_name(self): if self.def_type == self.FUNCTION: return self.def_name def get_token(self): if self.def_type == self.FUNCTION: token = self.FUNCTION_TOKEN elif self.def_type == self.CLASS: token = self.CLASS_TOKEN return token class PythonSH(BaseSH): """Python Syntax Highlighter""" # Syntax highlighting rules: add_kw = ['async', 'await'] PROG = re.compile(make_python_patterns(additional_keywords=add_kw), re.S) IDPROG = re.compile(r"\s+(\w+)", re.S) ASPROG = re.compile(r".*?\b(as)\b") # Syntax highlighting states (from one text block to another): (NORMAL, INSIDE_SQ3STRING, INSIDE_DQ3STRING, INSIDE_SQSTRING, INSIDE_DQSTRING) = list(range(5)) DEF_TYPES = {"def": OutlineExplorerData.FUNCTION, "class": OutlineExplorerData.CLASS} # Comments suitable for Outline Explorer OECOMMENT = re.compile('^(# ?--[-]+|##[#]+ )[ -]*[^- ]+') def __init__(self, parent, font=None, color_scheme='Spyder'): BaseSH.__init__(self, parent, font, color_scheme) self.import_statements = {} self.found_cell_separators = False self.cell_separators = CELL_LANGUAGES['Python'] def highlightBlock(self, text): text = to_text_string(text) prev_state = self.previousBlockState() if prev_state == self.INSIDE_DQ3STRING: offset = -4 text = r'""" '+text elif prev_state == self.INSIDE_SQ3STRING: offset = -4 text = r"''' "+text elif prev_state == self.INSIDE_DQSTRING: offset = -2 text = r'" '+text elif prev_state == self.INSIDE_SQSTRING: offset = -2 text = r"' "+text else: offset = 0 prev_state = self.NORMAL oedata = None import_stmt = None self.setFormat(0, len(text), self.formats["normal"]) state = self.NORMAL match = self.PROG.search(text) while match: for key, value in list(match.groupdict().items()): if value: start, end = match.span(key) start = max([0, start+offset]) end = max([0, end+offset]) if key == "uf_sq3string": self.setFormat(start, end-start, self.formats["string"]) state = self.INSIDE_SQ3STRING elif key == "uf_dq3string": self.setFormat(start, end-start, self.formats["string"]) state = self.INSIDE_DQ3STRING elif key == "uf_sqstring": self.setFormat(start, end-start, self.formats["string"]) state = self.INSIDE_SQSTRING elif key == "uf_dqstring": self.setFormat(start, end-start, self.formats["string"]) state = self.INSIDE_DQSTRING else: self.setFormat(start, end-start, self.formats[key]) if key == "comment": if text.lstrip().startswith(self.cell_separators): self.found_cell_separators = True oedata = OutlineExplorerData() oedata.text = to_text_string(text).strip() oedata.fold_level = start oedata.def_type = OutlineExplorerData.CELL oedata.def_name = text.strip() elif self.OECOMMENT.match(text.lstrip()): oedata = OutlineExplorerData() oedata.text = to_text_string(text).strip() oedata.fold_level = start oedata.def_type = OutlineExplorerData.COMMENT oedata.def_name = text.strip() elif key == "keyword": if value in ("def", "class"): match1 = self.IDPROG.match(text, end) if match1: start1, end1 = match1.span(1) self.setFormat(start1, end1-start1, self.formats["definition"]) oedata = OutlineExplorerData() oedata.text = to_text_string(text) oedata.fold_level = start oedata.def_type = self.DEF_TYPES[ to_text_string(value)] oedata.def_name = text[start1:end1] oedata.color = self.formats["definition"] elif value in ("elif", "else", "except", "finally", "for", "if", "try", "while", "with"): if text.lstrip().startswith(value): oedata = OutlineExplorerData() oedata.text = to_text_string(text).strip() oedata.fold_level = start oedata.def_type = \ OutlineExplorerData.STATEMENT oedata.def_name = text.strip() elif value == "import": import_stmt = text.strip() # color all the "as" words on same line, except # if in a comment; cheap approximation to the # truth if '#' in text: endpos = text.index('#') else: endpos = len(text) while True: match1 = self.ASPROG.match(text, end, endpos) if not match1: break start, end = match1.span(1) self.setFormat(start, end-start, self.formats["keyword"]) match = self.PROG.search(text, match.end()) self.setCurrentBlockState(state) # Use normal format for indentation and trailing spaces. self.formats['leading'] = self.formats['normal'] self.formats['trailing'] = self.formats['normal'] self.highlight_spaces(text, offset) if oedata is not None: block_nb = self.currentBlock().blockNumber() self.outlineexplorer_data[block_nb] = oedata self.outlineexplorer_data['found_cell_separators'] = self.found_cell_separators if import_stmt is not None: block_nb = self.currentBlock().blockNumber() self.import_statements[block_nb] = import_stmt def get_import_statements(self): return list(self.import_statements.values()) def rehighlight(self): self.import_statements = {} self.found_cell_separators = False BaseSH.rehighlight(self) #============================================================================== # Cython syntax highlighter #============================================================================== C_TYPES = 'bool char double enum float int long mutable short signed struct unsigned void' class CythonSH(PythonSH): """Cython Syntax Highlighter""" ADDITIONAL_KEYWORDS = [ "cdef", "ctypedef", "cpdef", "inline", "cimport", "extern", "include", "begin", "end", "by", "gil", "nogil", "const", "public", "readonly", "fused", "static", "api", "DEF", "IF", "ELIF", "ELSE"] ADDITIONAL_BUILTINS = C_TYPES.split() + [ "array", "bint", "Py_ssize_t", "intern", "reload", "sizeof", "NULL"] PROG = re.compile(make_python_patterns(ADDITIONAL_KEYWORDS, ADDITIONAL_BUILTINS), re.S) IDPROG = re.compile(r"\s+([\w\.]+)", re.S) #============================================================================== # Enaml syntax highlighter #============================================================================== class EnamlSH(PythonSH): """Enaml Syntax Highlighter""" ADDITIONAL_KEYWORDS = ["enamldef", "template", "attr", "event", "const", "alias", "func"] ADDITIONAL_BUILTINS = [] PROG = re.compile(make_python_patterns(ADDITIONAL_KEYWORDS, ADDITIONAL_BUILTINS), re.S) IDPROG = re.compile(r"\s+([\w\.]+)", re.S) #============================================================================== # C/C++ syntax highlighter #============================================================================== C_KEYWORDS1 = 'and and_eq bitand bitor break case catch const const_cast continue default delete do dynamic_cast else explicit export extern for friend goto if inline namespace new not not_eq operator or or_eq private protected public register reinterpret_cast return sizeof static static_cast switch template throw try typedef typeid typename union using virtual while xor xor_eq' C_KEYWORDS2 = 'a addindex addtogroup anchor arg attention author b brief bug c class code date def defgroup deprecated dontinclude e em endcode endhtmlonly ifdef endif endlatexonly endlink endverbatim enum example exception f$ file fn hideinitializer htmlinclude htmlonly if image include ingroup internal invariant interface latexonly li line link mainpage name namespace nosubgrouping note overload p page par param post pre ref relates remarks return retval sa section see showinitializer since skip skipline subsection test throw todo typedef union until var verbatim verbinclude version warning weakgroup' C_KEYWORDS3 = 'asm auto class compl false true volatile wchar_t' def make_generic_c_patterns(keywords, builtins, instance=None, define=None, comment=None): "Strongly inspired from idlelib.ColorDelegator.make_pat" kw = r"\b" + any("keyword", keywords.split()) + r"\b" builtin = r"\b" + any("builtin", builtins.split()+C_TYPES.split()) + r"\b" if comment is None: comment = any("comment", [r"//[^\n]*", r"\/\*(.*?)\*\/"]) comment_start = any("comment_start", [r"\/\*"]) comment_end = any("comment_end", [r"\*\/"]) if instance is None: instance = any("instance", [r"\bthis\b"]) number = any("number", [r"\b[+-]?[0-9]+[lL]?\b", r"\b[+-]?0[xX][0-9A-Fa-f]+[lL]?\b", r"\b[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\b"]) sqstring = r"(\b[rRuU])?'[^'\\\n]*(\\.[^'\\\n]*)*'?" dqstring = r'(\b[rRuU])?"[^"\\\n]*(\\.[^"\\\n]*)*"?' string = any("string", [sqstring, dqstring]) if define is None: define = any("define", [r"#[^\n]*"]) return "|".join([instance, kw, comment, string, number, comment_start, comment_end, builtin, define, any("SYNC", [r"\n"])]) def make_cpp_patterns(): return make_generic_c_patterns(C_KEYWORDS1+' '+C_KEYWORDS2, C_KEYWORDS3) class CppSH(BaseSH): """C/C++ Syntax Highlighter""" # Syntax highlighting rules: PROG = re.compile(make_cpp_patterns(), re.S) # Syntax highlighting states (from one text block to another): NORMAL = 0 INSIDE_COMMENT = 1 def __init__(self, parent, font=None, color_scheme=None): BaseSH.__init__(self, parent, font, color_scheme) def highlightBlock(self, text): text = to_text_string(text) inside_comment = self.previousBlockState() == self.INSIDE_COMMENT self.setFormat(0, len(text), self.formats["comment" if inside_comment else "normal"]) match = self.PROG.search(text) index = 0 while match: for key, value in list(match.groupdict().items()): if value: start, end = match.span(key) index += end-start if key == "comment_start": inside_comment = True self.setFormat(start, len(text)-start, self.formats["comment"]) elif key == "comment_end": inside_comment = False self.setFormat(start, end-start, self.formats["comment"]) elif inside_comment: self.setFormat(start, end-start, self.formats["comment"]) elif key == "define": self.setFormat(start, end-start, self.formats["number"]) else: self.setFormat(start, end-start, self.formats[key]) match = self.PROG.search(text, match.end()) self.highlight_spaces(text) last_state = self.INSIDE_COMMENT if inside_comment else self.NORMAL self.setCurrentBlockState(last_state) def make_opencl_patterns(): # Keywords: kwstr1 = 'cl_char cl_uchar cl_short cl_ushort cl_int cl_uint cl_long cl_ulong cl_half cl_float cl_double cl_platform_id cl_device_id cl_context cl_command_queue cl_mem cl_program cl_kernel cl_event cl_sampler cl_bool cl_bitfield cl_device_type cl_platform_info cl_device_info cl_device_address_info cl_device_fp_config cl_device_mem_cache_type cl_device_local_mem_type cl_device_exec_capabilities cl_command_queue_properties cl_context_properties cl_context_info cl_command_queue_info cl_channel_order cl_channel_type cl_mem_flags cl_mem_object_type cl_mem_info cl_image_info cl_addressing_mode cl_filter_mode cl_sampler_info cl_map_flags cl_program_info cl_program_build_info cl_build_status cl_kernel_info cl_kernel_work_group_info cl_event_info cl_command_type cl_profiling_info cl_image_format' # Constants: kwstr2 = 'CL_FALSE, CL_TRUE, CL_PLATFORM_PROFILE, CL_PLATFORM_VERSION, CL_PLATFORM_NAME, CL_PLATFORM_VENDOR, CL_PLATFORM_EXTENSIONS, CL_DEVICE_TYPE_DEFAULT , CL_DEVICE_TYPE_CPU, CL_DEVICE_TYPE_GPU, CL_DEVICE_TYPE_ACCELERATOR, CL_DEVICE_TYPE_ALL, CL_DEVICE_TYPE, CL_DEVICE_VENDOR_ID, CL_DEVICE_MAX_COMPUTE_UNITS, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, CL_DEVICE_MAX_WORK_GROUP_SIZE, CL_DEVICE_MAX_WORK_ITEM_SIZES, CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT, CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE, CL_DEVICE_MAX_CLOCK_FREQUENCY, CL_DEVICE_ADDRESS_BITS, CL_DEVICE_MAX_READ_IMAGE_ARGS, CL_DEVICE_MAX_WRITE_IMAGE_ARGS, CL_DEVICE_MAX_MEM_ALLOC_SIZE, CL_DEVICE_IMAGE2D_MAX_WIDTH, CL_DEVICE_IMAGE2D_MAX_HEIGHT, CL_DEVICE_IMAGE3D_MAX_WIDTH, CL_DEVICE_IMAGE3D_MAX_HEIGHT, CL_DEVICE_IMAGE3D_MAX_DEPTH, CL_DEVICE_IMAGE_SUPPORT, CL_DEVICE_MAX_PARAMETER_SIZE, CL_DEVICE_MAX_SAMPLERS, CL_DEVICE_MEM_BASE_ADDR_ALIGN, CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE, CL_DEVICE_SINGLE_FP_CONFIG, CL_DEVICE_GLOBAL_MEM_CACHE_TYPE, CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE, CL_DEVICE_GLOBAL_MEM_CACHE_SIZE, CL_DEVICE_GLOBAL_MEM_SIZE, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, CL_DEVICE_MAX_CONSTANT_ARGS, CL_DEVICE_LOCAL_MEM_TYPE, CL_DEVICE_LOCAL_MEM_SIZE, CL_DEVICE_ERROR_CORRECTION_SUPPORT, CL_DEVICE_PROFILING_TIMER_RESOLUTION, CL_DEVICE_ENDIAN_LITTLE, CL_DEVICE_AVAILABLE, CL_DEVICE_COMPILER_AVAILABLE, CL_DEVICE_EXECUTION_CAPABILITIES, CL_DEVICE_QUEUE_PROPERTIES, CL_DEVICE_NAME, CL_DEVICE_VENDOR, CL_DRIVER_VERSION, CL_DEVICE_PROFILE, CL_DEVICE_VERSION, CL_DEVICE_EXTENSIONS, CL_DEVICE_PLATFORM, CL_FP_DENORM, CL_FP_INF_NAN, CL_FP_ROUND_TO_NEAREST, CL_FP_ROUND_TO_ZERO, CL_FP_ROUND_TO_INF, CL_FP_FMA, CL_NONE, CL_READ_ONLY_CACHE, CL_READ_WRITE_CACHE, CL_LOCAL, CL_GLOBAL, CL_EXEC_KERNEL, CL_EXEC_NATIVE_KERNEL, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, CL_QUEUE_PROFILING_ENABLE, CL_CONTEXT_REFERENCE_COUNT, CL_CONTEXT_DEVICES, CL_CONTEXT_PROPERTIES, CL_CONTEXT_PLATFORM, CL_QUEUE_CONTEXT, CL_QUEUE_DEVICE, CL_QUEUE_REFERENCE_COUNT, CL_QUEUE_PROPERTIES, CL_MEM_READ_WRITE, CL_MEM_WRITE_ONLY, CL_MEM_READ_ONLY, CL_MEM_USE_HOST_PTR, CL_MEM_ALLOC_HOST_PTR, CL_MEM_COPY_HOST_PTR, CL_R, CL_A, CL_RG, CL_RA, CL_RGB, CL_RGBA, CL_BGRA, CL_ARGB, CL_INTENSITY, CL_LUMINANCE, CL_SNORM_INT8, CL_SNORM_INT16, CL_UNORM_INT8, CL_UNORM_INT16, CL_UNORM_SHORT_565, CL_UNORM_SHORT_555, CL_UNORM_INT_101010, CL_SIGNED_INT8, CL_SIGNED_INT16, CL_SIGNED_INT32, CL_UNSIGNED_INT8, CL_UNSIGNED_INT16, CL_UNSIGNED_INT32, CL_HALF_FLOAT, CL_FLOAT, CL_MEM_OBJECT_BUFFER, CL_MEM_OBJECT_IMAGE2D, CL_MEM_OBJECT_IMAGE3D, CL_MEM_TYPE, CL_MEM_FLAGS, CL_MEM_SIZECL_MEM_HOST_PTR, CL_MEM_HOST_PTR, CL_MEM_MAP_COUNT, CL_MEM_REFERENCE_COUNT, CL_MEM_CONTEXT, CL_IMAGE_FORMAT, CL_IMAGE_ELEMENT_SIZE, CL_IMAGE_ROW_PITCH, CL_IMAGE_SLICE_PITCH, CL_IMAGE_WIDTH, CL_IMAGE_HEIGHT, CL_IMAGE_DEPTH, CL_ADDRESS_NONE, CL_ADDRESS_CLAMP_TO_EDGE, CL_ADDRESS_CLAMP, CL_ADDRESS_REPEAT, CL_FILTER_NEAREST, CL_FILTER_LINEAR, CL_SAMPLER_REFERENCE_COUNT, CL_SAMPLER_CONTEXT, CL_SAMPLER_NORMALIZED_COORDS, CL_SAMPLER_ADDRESSING_MODE, CL_SAMPLER_FILTER_MODE, CL_MAP_READ, CL_MAP_WRITE, CL_PROGRAM_REFERENCE_COUNT, CL_PROGRAM_CONTEXT, CL_PROGRAM_NUM_DEVICES, CL_PROGRAM_DEVICES, CL_PROGRAM_SOURCE, CL_PROGRAM_BINARY_SIZES, CL_PROGRAM_BINARIES, CL_PROGRAM_BUILD_STATUS, CL_PROGRAM_BUILD_OPTIONS, CL_PROGRAM_BUILD_LOG, CL_BUILD_SUCCESS, CL_BUILD_NONE, CL_BUILD_ERROR, CL_BUILD_IN_PROGRESS, CL_KERNEL_FUNCTION_NAME, CL_KERNEL_NUM_ARGS, CL_KERNEL_REFERENCE_COUNT, CL_KERNEL_CONTEXT, CL_KERNEL_PROGRAM, CL_KERNEL_WORK_GROUP_SIZE, CL_KERNEL_COMPILE_WORK_GROUP_SIZE, CL_KERNEL_LOCAL_MEM_SIZE, CL_EVENT_COMMAND_QUEUE, CL_EVENT_COMMAND_TYPE, CL_EVENT_REFERENCE_COUNT, CL_EVENT_COMMAND_EXECUTION_STATUS, CL_COMMAND_NDRANGE_KERNEL, CL_COMMAND_TASK, CL_COMMAND_NATIVE_KERNEL, CL_COMMAND_READ_BUFFER, CL_COMMAND_WRITE_BUFFER, CL_COMMAND_COPY_BUFFER, CL_COMMAND_READ_IMAGE, CL_COMMAND_WRITE_IMAGE, CL_COMMAND_COPY_IMAGE, CL_COMMAND_COPY_IMAGE_TO_BUFFER, CL_COMMAND_COPY_BUFFER_TO_IMAGE, CL_COMMAND_MAP_BUFFER, CL_COMMAND_MAP_IMAGE, CL_COMMAND_UNMAP_MEM_OBJECT, CL_COMMAND_MARKER, CL_COMMAND_ACQUIRE_GL_OBJECTS, CL_COMMAND_RELEASE_GL_OBJECTS, command execution status, CL_COMPLETE, CL_RUNNING, CL_SUBMITTED, CL_QUEUED, CL_PROFILING_COMMAND_QUEUED, CL_PROFILING_COMMAND_SUBMIT, CL_PROFILING_COMMAND_START, CL_PROFILING_COMMAND_END, CL_CHAR_BIT, CL_SCHAR_MAX, CL_SCHAR_MIN, CL_CHAR_MAX, CL_CHAR_MIN, CL_UCHAR_MAX, CL_SHRT_MAX, CL_SHRT_MIN, CL_USHRT_MAX, CL_INT_MAX, CL_INT_MIN, CL_UINT_MAX, CL_LONG_MAX, CL_LONG_MIN, CL_ULONG_MAX, CL_FLT_DIG, CL_FLT_MANT_DIG, CL_FLT_MAX_10_EXP, CL_FLT_MAX_EXP, CL_FLT_MIN_10_EXP, CL_FLT_MIN_EXP, CL_FLT_RADIX, CL_FLT_MAX, CL_FLT_MIN, CL_FLT_EPSILON, CL_DBL_DIG, CL_DBL_MANT_DIG, CL_DBL_MAX_10_EXP, CL_DBL_MAX_EXP, CL_DBL_MIN_10_EXP, CL_DBL_MIN_EXP, CL_DBL_RADIX, CL_DBL_MAX, CL_DBL_MIN, CL_DBL_EPSILON, CL_SUCCESS, CL_DEVICE_NOT_FOUND, CL_DEVICE_NOT_AVAILABLE, CL_COMPILER_NOT_AVAILABLE, CL_MEM_OBJECT_ALLOCATION_FAILURE, CL_OUT_OF_RESOURCES, CL_OUT_OF_HOST_MEMORY, CL_PROFILING_INFO_NOT_AVAILABLE, CL_MEM_COPY_OVERLAP, CL_IMAGE_FORMAT_MISMATCH, CL_IMAGE_FORMAT_NOT_SUPPORTED, CL_BUILD_PROGRAM_FAILURE, CL_MAP_FAILURE, CL_INVALID_VALUE, CL_INVALID_DEVICE_TYPE, CL_INVALID_PLATFORM, CL_INVALID_DEVICE, CL_INVALID_CONTEXT, CL_INVALID_QUEUE_PROPERTIES, CL_INVALID_COMMAND_QUEUE, CL_INVALID_HOST_PTR, CL_INVALID_MEM_OBJECT, CL_INVALID_IMAGE_FORMAT_DESCRIPTOR, CL_INVALID_IMAGE_SIZE, CL_INVALID_SAMPLER, CL_INVALID_BINARY, CL_INVALID_BUILD_OPTIONS, CL_INVALID_PROGRAM, CL_INVALID_PROGRAM_EXECUTABLE, CL_INVALID_KERNEL_NAME, CL_INVALID_KERNEL_DEFINITION, CL_INVALID_KERNEL, CL_INVALID_ARG_INDEX, CL_INVALID_ARG_VALUE, CL_INVALID_ARG_SIZE, CL_INVALID_KERNEL_ARGS, CL_INVALID_WORK_DIMENSION, CL_INVALID_WORK_GROUP_SIZE, CL_INVALID_WORK_ITEM_SIZE, CL_INVALID_GLOBAL_OFFSET, CL_INVALID_EVENT_WAIT_LIST, CL_INVALID_EVENT, CL_INVALID_OPERATION, CL_INVALID_GL_OBJECT, CL_INVALID_BUFFER_SIZE, CL_INVALID_MIP_LEVEL, CL_INVALID_GLOBAL_WORK_SIZE' # Functions: builtins = 'clGetPlatformIDs, clGetPlatformInfo, clGetDeviceIDs, clGetDeviceInfo, clCreateContext, clCreateContextFromType, clReleaseContext, clGetContextInfo, clCreateCommandQueue, clRetainCommandQueue, clReleaseCommandQueue, clGetCommandQueueInfo, clSetCommandQueueProperty, clCreateBuffer, clCreateImage2D, clCreateImage3D, clRetainMemObject, clReleaseMemObject, clGetSupportedImageFormats, clGetMemObjectInfo, clGetImageInfo, clCreateSampler, clRetainSampler, clReleaseSampler, clGetSamplerInfo, clCreateProgramWithSource, clCreateProgramWithBinary, clRetainProgram, clReleaseProgram, clBuildProgram, clUnloadCompiler, clGetProgramInfo, clGetProgramBuildInfo, clCreateKernel, clCreateKernelsInProgram, clRetainKernel, clReleaseKernel, clSetKernelArg, clGetKernelInfo, clGetKernelWorkGroupInfo, clWaitForEvents, clGetEventInfo, clRetainEvent, clReleaseEvent, clGetEventProfilingInfo, clFlush, clFinish, clEnqueueReadBuffer, clEnqueueWriteBuffer, clEnqueueCopyBuffer, clEnqueueReadImage, clEnqueueWriteImage, clEnqueueCopyImage, clEnqueueCopyImageToBuffer, clEnqueueCopyBufferToImage, clEnqueueMapBuffer, clEnqueueMapImage, clEnqueueUnmapMemObject, clEnqueueNDRangeKernel, clEnqueueTask, clEnqueueNativeKernel, clEnqueueMarker, clEnqueueWaitForEvents, clEnqueueBarrier' # Qualifiers: qualifiers = '__global __local __constant __private __kernel' keyword_list = C_KEYWORDS1+' '+C_KEYWORDS2+' '+kwstr1+' '+kwstr2 builtin_list = C_KEYWORDS3+' '+builtins+' '+qualifiers return make_generic_c_patterns(keyword_list, builtin_list) class OpenCLSH(CppSH): """OpenCL Syntax Highlighter""" PROG = re.compile(make_opencl_patterns(), re.S) #============================================================================== # Fortran Syntax Highlighter #============================================================================== def make_fortran_patterns(): "Strongly inspired from idlelib.ColorDelegator.make_pat" kwstr = 'access action advance allocatable allocate apostrophe assign assignment associate asynchronous backspace bind blank blockdata call case character class close common complex contains continue cycle data deallocate decimal delim default dimension direct do dowhile double doubleprecision else elseif elsewhere encoding end endassociate endblockdata enddo endfile endforall endfunction endif endinterface endmodule endprogram endselect endsubroutine endtype endwhere entry eor equivalence err errmsg exist exit external file flush fmt forall form format formatted function go goto id if implicit in include inout integer inquire intent interface intrinsic iomsg iolength iostat kind len logical module name named namelist nextrec nml none nullify number only open opened operator optional out pad parameter pass pause pending pointer pos position precision print private program protected public quote read readwrite real rec recl recursive result return rewind save select selectcase selecttype sequential sign size stat status stop stream subroutine target then to type unformatted unit use value volatile wait where while write' bistr1 = 'abs achar acos acosd adjustl adjustr aimag aimax0 aimin0 aint ajmax0 ajmin0 akmax0 akmin0 all allocated alog alog10 amax0 amax1 amin0 amin1 amod anint any asin asind associated atan atan2 atan2d atand bitest bitl bitlr bitrl bjtest bit_size bktest break btest cabs ccos cdabs cdcos cdexp cdlog cdsin cdsqrt ceiling cexp char clog cmplx conjg cos cosd cosh count cpu_time cshift csin csqrt dabs dacos dacosd dasin dasind datan datan2 datan2d datand date date_and_time dble dcmplx dconjg dcos dcosd dcosh dcotan ddim dexp dfloat dflotk dfloti dflotj digits dim dimag dint dlog dlog10 dmax1 dmin1 dmod dnint dot_product dprod dreal dsign dsin dsind dsinh dsqrt dtan dtand dtanh eoshift epsilon errsns exp exponent float floati floatj floatk floor fraction free huge iabs iachar iand ibclr ibits ibset ichar idate idim idint idnint ieor ifix iiabs iiand iibclr iibits iibset iidim iidint iidnnt iieor iifix iint iior iiqint iiqnnt iishft iishftc iisign ilen imax0 imax1 imin0 imin1 imod index inint inot int int1 int2 int4 int8 iqint iqnint ior ishft ishftc isign isnan izext jiand jibclr jibits jibset jidim jidint jidnnt jieor jifix jint jior jiqint jiqnnt jishft jishftc jisign jmax0 jmax1 jmin0 jmin1 jmod jnint jnot jzext kiabs kiand kibclr kibits kibset kidim kidint kidnnt kieor kifix kind kint kior kishft kishftc kisign kmax0 kmax1 kmin0 kmin1 kmod knint knot kzext lbound leadz len len_trim lenlge lge lgt lle llt log log10 logical lshift malloc matmul max max0 max1 maxexponent maxloc maxval merge min min0 min1 minexponent minloc minval mod modulo mvbits nearest nint not nworkers number_of_processors pack popcnt poppar precision present product radix random random_number random_seed range real repeat reshape rrspacing rshift scale scan secnds selected_int_kind selected_real_kind set_exponent shape sign sin sind sinh size sizeof sngl snglq spacing spread sqrt sum system_clock tan tand tanh tiny transfer transpose trim ubound unpack verify' bistr2 = 'cdabs cdcos cdexp cdlog cdsin cdsqrt cotan cotand dcmplx dconjg dcotan dcotand decode dimag dll_export dll_import doublecomplex dreal dvchk encode find flen flush getarg getcharqq getcl getdat getenv gettim hfix ibchng identifier imag int1 int2 int4 intc intrup invalop iostat_msg isha ishc ishl jfix lacfar locking locnear map nargs nbreak ndperr ndpexc offset ovefl peekcharqq precfill prompt qabs qacos qacosd qasin qasind qatan qatand qatan2 qcmplx qconjg qcos qcosd qcosh qdim qexp qext qextd qfloat qimag qlog qlog10 qmax1 qmin1 qmod qreal qsign qsin qsind qsinh qsqrt qtan qtand qtanh ran rand randu rewrite segment setdat settim system timer undfl unlock union val virtual volatile zabs zcos zexp zlog zsin zsqrt' kw = r"\b" + any("keyword", kwstr.split()) + r"\b" builtin = r"\b" + any("builtin", bistr1.split()+bistr2.split()) + r"\b" comment = any("comment", [r"\![^\n]*"]) number = any("number", [r"\b[+-]?[0-9]+[lL]?\b", r"\b[+-]?0[xX][0-9A-Fa-f]+[lL]?\b", r"\b[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\b"]) sqstring = r"(\b[rRuU])?'[^'\\\n]*(\\.[^'\\\n]*)*'?" dqstring = r'(\b[rRuU])?"[^"\\\n]*(\\.[^"\\\n]*)*"?' string = any("string", [sqstring, dqstring]) return "|".join([kw, comment, string, number, builtin, any("SYNC", [r"\n"])]) class FortranSH(BaseSH): """Fortran Syntax Highlighter""" # Syntax highlighting rules: PROG = re.compile(make_fortran_patterns(), re.S|re.I) IDPROG = re.compile(r"\s+(\w+)", re.S) # Syntax highlighting states (from one text block to another): NORMAL = 0 def __init__(self, parent, font=None, color_scheme=None): BaseSH.__init__(self, parent, font, color_scheme) def highlightBlock(self, text): text = to_text_string(text) self.setFormat(0, len(text), self.formats["normal"]) match = self.PROG.search(text) index = 0 while match: for key, value in list(match.groupdict().items()): if value: start, end = match.span(key) index += end-start self.setFormat(start, end-start, self.formats[key]) if value.lower() in ("subroutine", "module", "function"): match1 = self.IDPROG.match(text, end) if match1: start1, end1 = match1.span(1) self.setFormat(start1, end1-start1, self.formats["definition"]) match = self.PROG.search(text, match.end()) self.highlight_spaces(text) class Fortran77SH(FortranSH): """Fortran 77 Syntax Highlighter""" def highlightBlock(self, text): text = to_text_string(text) if text.startswith(("c", "C")): self.setFormat(0, len(text), self.formats["comment"]) self.highlight_spaces(text) else: FortranSH.highlightBlock(self, text) self.setFormat(0, 5, self.formats["comment"]) self.setFormat(73, max([73, len(text)]), self.formats["comment"]) #============================================================================== # IDL highlighter # # Contribution from Stuart Mumford (Littlemumford) - 02/02/2012 # See Issue #850 #============================================================================== def make_idl_patterns(): "Strongly inspired from idlelib.ColorDelegator.make_pat" kwstr = 'begin of pro function endfor endif endwhile endrep endcase endswitch end if then else for do while repeat until break case switch common continue exit return goto help message print read retall stop' bistr1 = 'a_correlate abs acos adapt_hist_equal alog alog10 amoeba arg_present arra_equal array_indices ascii_template asin assoc atan beseli beselj besel k besely beta bilinear bin_date binary_template dinfgen dinomial blk_con broyden bytarr byte bytscl c_correlate call_external call_function ceil chebyshev check_math chisqr_cvf chisqr_pdf choldc cholsol cindgen clust_wts cluster color_quan colormap_applicable comfit complex complexarr complexround compute_mesh_normals cond congrid conj convert_coord convol coord2to3 correlate cos cosh cramer create_struct crossp crvlength ct_luminance cti_test curvefit cv_coord cvttobm cw_animate cw_arcball cw_bgroup cw_clr_index cw_colorsel cw_defroi cw_field cw_filesel cw_form cw_fslider cw_light_editor cw_orient cw_palette_editor cw_pdmenu cw_rgbslider cw_tmpl cw_zoom dblarr dcindgen dcomplexarr defroi deriv derivsig determ diag_matrix dialog_message dialog_pickfile pialog_printersetup dialog_printjob dialog_read_image dialog_write_image digital_filter dilate dindgen dist double eigenql eigenvec elmhes eof erode erf erfc erfcx execute exp expand_path expint extrac extract_slice f_cvf f_pdf factorial fft file_basename file_dirname file_expand_path file_info file_same file_search file_test file_which filepath findfile findgen finite fix float floor fltarr format_axis_values fstat fulstr fv_test fx_root fz_roots gamma gauss_cvf gauss_pdf gauss2dfit gaussfit gaussint get_drive_list get_kbrd get_screen_size getenv grid_tps grid3 griddata gs_iter hanning hdf_browser hdf_read hilbert hist_2d hist_equal histogram hough hqr ibeta identity idl_validname idlitsys_createtool igamma imaginary indgen int_2d int_3d int_tabulated intarr interpol interpolate invert ioctl ishft julday keword_set krig2d kurtosis kw_test l64indgen label_date label_region ladfit laguerre la_cholmprove la_cholsol la_Determ la_eigenproblem la_eigenql la_eigenvec la_elmhes la_gm_linear_model la_hqr la_invert la_least_square_equality la_least_squares la_linear_equation la_lumprove la_lusol la_trimprove la_trisol leefit legendre linbcg lindgen linfit ll_arc_distance lmfit lmgr lngamma lnp_test locale_get logical_and logical_or logical_true lon64arr lonarr long long64 lsode lu_complex lumprove lusol m_correlate machar make_array map_2points map_image map_patch map_proj_forward map_proj_init map_proj_inverse matrix_multiply matrix_power max md_test mean meanabsdev median memory mesh_clip mesh_decimate mesh_issolid mesh_merge mesh_numtriangles mesh_smooth mesh_surfacearea mesh_validate mesh_volume min min_curve_surf moment morph_close morph_distance morph_gradient morph_histormiss morph_open morph_thin morph_tophat mpeg_open msg_cat_open n_elements n_params n_tags newton norm obj_class obj_isa obj_new obj_valid objarr p_correlate path_sep pcomp pnt_line polar_surface poly poly_2d poly_area poly_fit polyfillv ployshade primes product profile profiles project_vol ptr_new ptr_valid ptrarr qgrid3 qromb qromo qsimp query_bmp query_dicom query_image query_jpeg query_mrsid query_pict query_png query_ppm query_srf query_tiff query_wav r_correlate r_test radon randomn randomu ranks read_ascii read_binary read_bmp read_dicom read_image read_mrsid read_png read_spr read_sylk read_tiff read_wav read_xwd real_part rebin recall_commands recon3 reform region_grow regress replicate reverse rk4 roberts rot rotate round routine_info rs_test s_test savgol search2d search3d sfit shift shmdebug shmvar simplex sin sindgen sinh size skewness smooth sobel sort sph_scat spher_harm spl_init spl_interp spline spline_p sprsab sprsax sprsin sprstp sqrt standardize stddev strarr strcmp strcompress stregex string strjoin strlen strlowcase strmatch strmessage strmid strpos strsplit strtrim strupcase svdfit svsol swap_endian systime t_cvf t_pdf tag_names tan tanh temporary tetra_clip tetra_surface tetra_volume thin timegen tm_test total trace transpose tri_surf trigrid trisol ts_coef ts_diff ts_fcast ts_smooth tvrd uindgen unit uintarr ul64indgen ulindgen ulon64arr ulonarr ulong ulong64 uniq value_locate variance vert_t3d voigt voxel_proj warp_tri watershed where widget_actevix widget_base widget_button widget_combobox widget_draw widget_droplist widget_event widget_info widget_label widget_list widget_propertsheet widget_slider widget_tab widget_table widget_text widget_tree write_sylk wtn xfont xregistered xsq_test' bistr2 = 'annotate arrow axis bar_plot blas_axpy box_cursor breakpoint byteorder caldata calendar call_method call_procedure catch cd cir_3pnt close color_convert compile_opt constrained_min contour copy_lun cpu create_view cursor cw_animate_getp cw_animate_load cw_animate_run cw_light_editor_get cw_light_editor_set cw_palette_editor_get cw_palette_editor_set define_key define_msgblk define_msgblk_from_file defsysv delvar device dfpmin dissolve dlm_load doc_librar draw_roi efont empty enable_sysrtn erase errplot expand file_chmod file_copy file_delete file_lines file_link file_mkdir file_move file_readlink flick flow3 flush forward_function free_lun funct gamma_ct get_lun grid_input h_eq_ct h_eq_int heap_free heap_gc hls hsv icontour iimage image_cont image_statistics internal_volume iplot isocontour isosurface isurface itcurrent itdelete itgetcurrent itregister itreset ivolume journal la_choldc la_ludc la_svd la_tridc la_triql la_trired linkimage loadct ludc make_dll map_continents map_grid map_proj_info map_set mesh_obj mk_html_help modifyct mpeg_close mpeg_put mpeg_save msg_cat_close msg_cat_compile multi obj_destroy on_error on_ioerror online_help openr openw openu oplot oploterr particle_trace path_cache plot plot_3dbox plot_field ploterr plots point_lun polar_contour polyfill polywarp popd powell printf printd ps_show_fonts psafm pseudo ptr_free pushd qhull rdpix readf read_interfile read_jpeg read_pict read_ppm read_srf read_wave read_x11_bitmap reads readu reduce_colors register_cursor replicate_inplace resolve_all resolve_routine restore save scale3 scale3d set_plot set_shading setenv setup_keys shade_surf shade_surf_irr shade_volume shmmap show3 showfont skip_lun slicer3 slide_image socket spawn sph_4pnt streamline stretch strput struct_assign struct_hide surface surfr svdc swap_enian_inplace t3d tek_color threed time_test2 triangulate triql trired truncate_lun tv tvcrs tvlct tvscl usersym vector_field vel velovect voronoi wait wdelete wf_draw widget_control widget_displaycontextmenu window write_bmp write_image write_jpeg write_nrif write_pict write_png write_ppm write_spr write_srf write_tiff write_wav write_wave writeu wset wshow xbm_edit xdisplayfile xdxf xinteranimate xloadct xmanager xmng_tmpl xmtool xobjview xobjview_rotate xobjview_write_image xpalette xpcolo xplot3d xroi xsurface xvaredit xvolume xyouts zoom zoom_24' kw = r"\b" + any("keyword", kwstr.split()) + r"\b" builtin = r"\b" + any("builtin", bistr1.split()+bistr2.split()) + r"\b" comment = any("comment", [r"\;[^\n]*"]) number = any("number", [r"\b[+-]?[0-9]+[lL]?\b", r"\b[+-]?0[xX][0-9A-Fa-f]+[lL]?\b", r"\b\.[0-9]d0|\.d0+[lL]?\b", r"\b[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\b"]) sqstring = r"(\b[rRuU])?'[^'\\\n]*(\\.[^'\\\n]*)*'?" dqstring = r'(\b[rRuU])?"[^"\\\n]*(\\.[^"\\\n]*)*"?' string = any("string", [sqstring, dqstring]) return "|".join([kw, comment, string, number, builtin, any("SYNC", [r"\n"])]) class IdlSH(GenericSH): """IDL Syntax Highlighter""" PROG = re.compile(make_idl_patterns(), re.S|re.I) #============================================================================== # Diff/Patch highlighter #============================================================================== class DiffSH(BaseSH): """Simple Diff/Patch Syntax Highlighter Class""" def highlightBlock(self, text): text = to_text_string(text) if text.startswith("+++"): self.setFormat(0, len(text), self.formats["keyword"]) elif text.startswith("---"): self.setFormat(0, len(text), self.formats["keyword"]) elif text.startswith("+"): self.setFormat(0, len(text), self.formats["string"]) elif text.startswith("-"): self.setFormat(0, len(text), self.formats["number"]) elif text.startswith("@"): self.setFormat(0, len(text), self.formats["builtin"]) self.highlight_spaces(text) #============================================================================== # NSIS highlighter #============================================================================== def make_nsis_patterns(): "Strongly inspired from idlelib.ColorDelegator.make_pat" kwstr1 = 'Abort AddBrandingImage AddSize AllowRootDirInstall AllowSkipFiles AutoCloseWindow BGFont BGGradient BrandingText BringToFront Call CallInstDLL Caption ClearErrors CompletedText ComponentText CopyFiles CRCCheck CreateDirectory CreateFont CreateShortCut Delete DeleteINISec DeleteINIStr DeleteRegKey DeleteRegValue DetailPrint DetailsButtonText DirText DirVar DirVerify EnableWindow EnumRegKey EnumRegValue Exec ExecShell ExecWait Exch ExpandEnvStrings File FileBufSize FileClose FileErrorText FileOpen FileRead FileReadByte FileSeek FileWrite FileWriteByte FindClose FindFirst FindNext FindWindow FlushINI Function FunctionEnd GetCurInstType GetCurrentAddress GetDlgItem GetDLLVersion GetDLLVersionLocal GetErrorLevel GetFileTime GetFileTimeLocal GetFullPathName GetFunctionAddress GetInstDirError GetLabelAddress GetTempFileName Goto HideWindow ChangeUI CheckBitmap Icon IfAbort IfErrors IfFileExists IfRebootFlag IfSilent InitPluginsDir InstallButtonText InstallColors InstallDir InstallDirRegKey InstProgressFlags InstType InstTypeGetText InstTypeSetText IntCmp IntCmpU IntFmt IntOp IsWindow LangString LicenseBkColor LicenseData LicenseForceSelection LicenseLangString LicenseText LoadLanguageFile LogSet LogText MessageBox MiscButtonText Name OutFile Page PageCallbacks PageEx PageExEnd Pop Push Quit ReadEnvStr ReadINIStr ReadRegDWORD ReadRegStr Reboot RegDLL Rename ReserveFile Return RMDir SearchPath Section SectionEnd SectionGetFlags SectionGetInstTypes SectionGetSize SectionGetText SectionIn SectionSetFlags SectionSetInstTypes SectionSetSize SectionSetText SendMessage SetAutoClose SetBrandingImage SetCompress SetCompressor SetCompressorDictSize SetCtlColors SetCurInstType SetDatablockOptimize SetDateSave SetDetailsPrint SetDetailsView SetErrorLevel SetErrors SetFileAttributes SetFont SetOutPath SetOverwrite SetPluginUnload SetRebootFlag SetShellVarContext SetSilent ShowInstDetails ShowUninstDetails ShowWindow SilentInstall SilentUnInstall Sleep SpaceTexts StrCmp StrCpy StrLen SubCaption SubSection SubSectionEnd UninstallButtonText UninstallCaption UninstallIcon UninstallSubCaption UninstallText UninstPage UnRegDLL Var VIAddVersionKey VIProductVersion WindowIcon WriteINIStr WriteRegBin WriteRegDWORD WriteRegExpandStr WriteRegStr WriteUninstaller XPStyle' kwstr2 = 'all alwaysoff ARCHIVE auto both bzip2 components current custom details directory false FILE_ATTRIBUTE_ARCHIVE FILE_ATTRIBUTE_HIDDEN FILE_ATTRIBUTE_NORMAL FILE_ATTRIBUTE_OFFLINE FILE_ATTRIBUTE_READONLY FILE_ATTRIBUTE_SYSTEM FILE_ATTRIBUTE_TEMPORARY force grey HIDDEN hide IDABORT IDCANCEL IDIGNORE IDNO IDOK IDRETRY IDYES ifdiff ifnewer instfiles instfiles lastused leave left level license listonly lzma manual MB_ABORTRETRYIGNORE MB_DEFBUTTON1 MB_DEFBUTTON2 MB_DEFBUTTON3 MB_DEFBUTTON4 MB_ICONEXCLAMATION MB_ICONINFORMATION MB_ICONQUESTION MB_ICONSTOP MB_OK MB_OKCANCEL MB_RETRYCANCEL MB_RIGHT MB_SETFOREGROUND MB_TOPMOST MB_YESNO MB_YESNOCANCEL nevershow none NORMAL off OFFLINE on READONLY right RO show silent silentlog SYSTEM TEMPORARY text textonly true try uninstConfirm windows zlib' kwstr3 = 'MUI_ABORTWARNING MUI_ABORTWARNING_CANCEL_DEFAULT MUI_ABORTWARNING_TEXT MUI_BGCOLOR MUI_COMPONENTSPAGE_CHECKBITMAP MUI_COMPONENTSPAGE_NODESC MUI_COMPONENTSPAGE_SMALLDESC MUI_COMPONENTSPAGE_TEXT_COMPLIST MUI_COMPONENTSPAGE_TEXT_DESCRIPTION_INFO MUI_COMPONENTSPAGE_TEXT_DESCRIPTION_TITLE MUI_COMPONENTSPAGE_TEXT_INSTTYPE MUI_COMPONENTSPAGE_TEXT_TOP MUI_CUSTOMFUNCTION_ABORT MUI_CUSTOMFUNCTION_GUIINIT MUI_CUSTOMFUNCTION_UNABORT MUI_CUSTOMFUNCTION_UNGUIINIT MUI_DESCRIPTION_TEXT MUI_DIRECTORYPAGE_BGCOLOR MUI_DIRECTORYPAGE_TEXT_DESTINATION MUI_DIRECTORYPAGE_TEXT_TOP MUI_DIRECTORYPAGE_VARIABLE MUI_DIRECTORYPAGE_VERIFYONLEAVE MUI_FINISHPAGE_BUTTON MUI_FINISHPAGE_CANCEL_ENABLED MUI_FINISHPAGE_LINK MUI_FINISHPAGE_LINK_COLOR MUI_FINISHPAGE_LINK_LOCATION MUI_FINISHPAGE_NOAUTOCLOSE MUI_FINISHPAGE_NOREBOOTSUPPORT MUI_FINISHPAGE_REBOOTLATER_DEFAULT MUI_FINISHPAGE_RUN MUI_FINISHPAGE_RUN_FUNCTION MUI_FINISHPAGE_RUN_NOTCHECKED MUI_FINISHPAGE_RUN_PARAMETERS MUI_FINISHPAGE_RUN_TEXT MUI_FINISHPAGE_SHOWREADME MUI_FINISHPAGE_SHOWREADME_FUNCTION MUI_FINISHPAGE_SHOWREADME_NOTCHECKED MUI_FINISHPAGE_SHOWREADME_TEXT MUI_FINISHPAGE_TEXT MUI_FINISHPAGE_TEXT_LARGE MUI_FINISHPAGE_TEXT_REBOOT MUI_FINISHPAGE_TEXT_REBOOTLATER MUI_FINISHPAGE_TEXT_REBOOTNOW MUI_FINISHPAGE_TITLE MUI_FINISHPAGE_TITLE_3LINES MUI_FUNCTION_DESCRIPTION_BEGIN MUI_FUNCTION_DESCRIPTION_END MUI_HEADER_TEXT MUI_HEADER_TRANSPARENT_TEXT MUI_HEADERIMAGE MUI_HEADERIMAGE_BITMAP MUI_HEADERIMAGE_BITMAP_NOSTRETCH MUI_HEADERIMAGE_BITMAP_RTL MUI_HEADERIMAGE_BITMAP_RTL_NOSTRETCH MUI_HEADERIMAGE_RIGHT MUI_HEADERIMAGE_UNBITMAP MUI_HEADERIMAGE_UNBITMAP_NOSTRETCH MUI_HEADERIMAGE_UNBITMAP_RTL MUI_HEADERIMAGE_UNBITMAP_RTL_NOSTRETCH MUI_HWND MUI_ICON MUI_INSTALLCOLORS MUI_INSTALLOPTIONS_DISPLAY MUI_INSTALLOPTIONS_DISPLAY_RETURN MUI_INSTALLOPTIONS_EXTRACT MUI_INSTALLOPTIONS_EXTRACT_AS MUI_INSTALLOPTIONS_INITDIALOG MUI_INSTALLOPTIONS_READ MUI_INSTALLOPTIONS_SHOW MUI_INSTALLOPTIONS_SHOW_RETURN MUI_INSTALLOPTIONS_WRITE MUI_INSTFILESPAGE_ABORTHEADER_SUBTEXT MUI_INSTFILESPAGE_ABORTHEADER_TEXT MUI_INSTFILESPAGE_COLORS MUI_INSTFILESPAGE_FINISHHEADER_SUBTEXT MUI_INSTFILESPAGE_FINISHHEADER_TEXT MUI_INSTFILESPAGE_PROGRESSBAR MUI_LANGDLL_ALLLANGUAGES MUI_LANGDLL_ALWAYSSHOW MUI_LANGDLL_DISPLAY MUI_LANGDLL_INFO MUI_LANGDLL_REGISTRY_KEY MUI_LANGDLL_REGISTRY_ROOT MUI_LANGDLL_REGISTRY_VALUENAME MUI_LANGDLL_WINDOWTITLE MUI_LANGUAGE MUI_LICENSEPAGE_BGCOLOR MUI_LICENSEPAGE_BUTTON MUI_LICENSEPAGE_CHECKBOX MUI_LICENSEPAGE_CHECKBOX_TEXT MUI_LICENSEPAGE_RADIOBUTTONS MUI_LICENSEPAGE_RADIOBUTTONS_TEXT_ACCEPT MUI_LICENSEPAGE_RADIOBUTTONS_TEXT_DECLINE MUI_LICENSEPAGE_TEXT_BOTTOM MUI_LICENSEPAGE_TEXT_TOP MUI_PAGE_COMPONENTS MUI_PAGE_CUSTOMFUNCTION_LEAVE MUI_PAGE_CUSTOMFUNCTION_PRE MUI_PAGE_CUSTOMFUNCTION_SHOW MUI_PAGE_DIRECTORY MUI_PAGE_FINISH MUI_PAGE_HEADER_SUBTEXT MUI_PAGE_HEADER_TEXT MUI_PAGE_INSTFILES MUI_PAGE_LICENSE MUI_PAGE_STARTMENU MUI_PAGE_WELCOME MUI_RESERVEFILE_INSTALLOPTIONS MUI_RESERVEFILE_LANGDLL MUI_SPECIALINI MUI_STARTMENU_GETFOLDER MUI_STARTMENU_WRITE_BEGIN MUI_STARTMENU_WRITE_END MUI_STARTMENUPAGE_BGCOLOR MUI_STARTMENUPAGE_DEFAULTFOLDER MUI_STARTMENUPAGE_NODISABLE MUI_STARTMENUPAGE_REGISTRY_KEY MUI_STARTMENUPAGE_REGISTRY_ROOT MUI_STARTMENUPAGE_REGISTRY_VALUENAME MUI_STARTMENUPAGE_TEXT_CHECKBOX MUI_STARTMENUPAGE_TEXT_TOP MUI_UI MUI_UI_COMPONENTSPAGE_NODESC MUI_UI_COMPONENTSPAGE_SMALLDESC MUI_UI_HEADERIMAGE MUI_UI_HEADERIMAGE_RIGHT MUI_UNABORTWARNING MUI_UNABORTWARNING_CANCEL_DEFAULT MUI_UNABORTWARNING_TEXT MUI_UNCONFIRMPAGE_TEXT_LOCATION MUI_UNCONFIRMPAGE_TEXT_TOP MUI_UNFINISHPAGE_NOAUTOCLOSE MUI_UNFUNCTION_DESCRIPTION_BEGIN MUI_UNFUNCTION_DESCRIPTION_END MUI_UNGETLANGUAGE MUI_UNICON MUI_UNPAGE_COMPONENTS MUI_UNPAGE_CONFIRM MUI_UNPAGE_DIRECTORY MUI_UNPAGE_FINISH MUI_UNPAGE_INSTFILES MUI_UNPAGE_LICENSE MUI_UNPAGE_WELCOME MUI_UNWELCOMEFINISHPAGE_BITMAP MUI_UNWELCOMEFINISHPAGE_BITMAP_NOSTRETCH MUI_UNWELCOMEFINISHPAGE_INI MUI_WELCOMEFINISHPAGE_BITMAP MUI_WELCOMEFINISHPAGE_BITMAP_NOSTRETCH MUI_WELCOMEFINISHPAGE_CUSTOMFUNCTION_INIT MUI_WELCOMEFINISHPAGE_INI MUI_WELCOMEPAGE_TEXT MUI_WELCOMEPAGE_TITLE MUI_WELCOMEPAGE_TITLE_3LINES' bistr = 'addincludedir addplugindir AndIf cd define echo else endif error execute If ifdef ifmacrodef ifmacrondef ifndef include insertmacro macro macroend onGUIEnd onGUIInit onInit onInstFailed onInstSuccess onMouseOverSection onRebootFailed onSelChange onUserAbort onVerifyInstDir OrIf packhdr system undef verbose warning' instance = any("instance", [r'\$\{.*?\}', r'\$[A-Za-z0-9\_]*']) define = any("define", [r"\![^\n]*"]) comment = any("comment", [r"\;[^\n]*", r"\#[^\n]*", r"\/\*(.*?)\*\/"]) return make_generic_c_patterns(kwstr1+' '+kwstr2+' '+kwstr3, bistr, instance=instance, define=define, comment=comment) class NsisSH(CppSH): """NSIS Syntax Highlighter""" # Syntax highlighting rules: PROG = re.compile(make_nsis_patterns(), re.S) #============================================================================== # gettext highlighter #============================================================================== def make_gettext_patterns(): "Strongly inspired from idlelib.ColorDelegator.make_pat" kwstr = 'msgid msgstr' kw = r"\b" + any("keyword", kwstr.split()) + r"\b" fuzzy = any("builtin", [r"#,[^\n]*"]) links = any("normal", [r"#:[^\n]*"]) comment = any("comment", [r"#[^\n]*"]) number = any("number", [r"\b[+-]?[0-9]+[lL]?\b", r"\b[+-]?0[xX][0-9A-Fa-f]+[lL]?\b", r"\b[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\b"]) sqstring = r"(\b[rRuU])?'[^'\\\n]*(\\.[^'\\\n]*)*'?" dqstring = r'(\b[rRuU])?"[^"\\\n]*(\\.[^"\\\n]*)*"?' string = any("string", [sqstring, dqstring]) return "|".join([kw, string, number, fuzzy, links, comment, any("SYNC", [r"\n"])]) class GetTextSH(GenericSH): """gettext Syntax Highlighter""" # Syntax highlighting rules: PROG = re.compile(make_gettext_patterns(), re.S) #============================================================================== # yaml highlighter #============================================================================== def make_yaml_patterns(): "Strongly inspired from sublime highlighter " kw = any("keyword", [r":|>|-|\||\[|\]|[A-Za-z][\w\s\-\_ ]+(?=:)"]) links = any("normal", [r"#:[^\n]*"]) comment = any("comment", [r"#[^\n]*"]) number = any("number", [r"\b[+-]?[0-9]+[lL]?\b", r"\b[+-]?0[xX][0-9A-Fa-f]+[lL]?\b", r"\b[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\b"]) sqstring = r"(\b[rRuU])?'[^'\\\n]*(\\.[^'\\\n]*)*'?" dqstring = r'(\b[rRuU])?"[^"\\\n]*(\\.[^"\\\n]*)*"?' string = any("string", [sqstring, dqstring]) return "|".join([kw, string, number, links, comment, any("SYNC", [r"\n"])]) class YamlSH(GenericSH): """yaml Syntax Highlighter""" # Syntax highlighting rules: PROG = re.compile(make_yaml_patterns(), re.S) #============================================================================== # HTML highlighter #============================================================================== class BaseWebSH(BaseSH): """Base class for CSS and HTML syntax highlighters""" NORMAL = 0 COMMENT = 1 def __init__(self, parent, font=None, color_scheme=None): BaseSH.__init__(self, parent, font, color_scheme) def highlightBlock(self, text): text = to_text_string(text) previous_state = self.previousBlockState() if previous_state == self.COMMENT: self.setFormat(0, len(text), self.formats["comment"]) else: previous_state = self.NORMAL self.setFormat(0, len(text), self.formats["normal"]) self.setCurrentBlockState(previous_state) match = self.PROG.search(text) match_count = 0 n_characters = len(text) # There should never be more matches than characters in the text. while match and match_count < n_characters: match_dict = match.groupdict() for key, value in list(match_dict.items()): if value: start, end = match.span(key) if previous_state == self.COMMENT: if key == "multiline_comment_end": self.setCurrentBlockState(self.NORMAL) self.setFormat(end, len(text), self.formats["normal"]) else: self.setCurrentBlockState(self.COMMENT) self.setFormat(0, len(text), self.formats["comment"]) else: if key == "multiline_comment_start": self.setCurrentBlockState(self.COMMENT) self.setFormat(start, len(text), self.formats["comment"]) else: self.setCurrentBlockState(self.NORMAL) try: self.setFormat(start, end-start, self.formats[key]) except KeyError: # happens with unmatched end-of-comment; # see issue 1462 pass match = self.PROG.search(text, match.end()) match_count += 1 self.highlight_spaces(text) def make_html_patterns(): """Strongly inspired from idlelib.ColorDelegator.make_pat """ tags = any("builtin", [r"<", r"[\?/]?>", r"(?<=<).*?(?=[ >])"]) keywords = any("keyword", [r" [\w:-]*?(?==)"]) string = any("string", [r'".*?"']) comment = any("comment", [r""]) multiline_comment_start = any("multiline_comment_start", [r""]) return "|".join([comment, multiline_comment_start, multiline_comment_end, tags, keywords, string]) class HtmlSH(BaseWebSH): """HTML Syntax Highlighter""" PROG = re.compile(make_html_patterns(), re.S) # ============================================================================= # Markdown highlighter # ============================================================================= def make_md_patterns(): h1 = '^#[^#]+' h2 = '^##[^#]+' h3 = '^###[^#]+' h4 = '^####[^#]+' h5 = '^#####[^#]+' h6 = '^######[^#]+' titles = any('title', [h1, h2, h3, h4, h5, h6]) html_tags = any("builtin", [r"<", r"[\?/]?>", r"(?<=<).*?(?=[ >])"]) html_symbols = '&[^; ].+;' html_comment = '' strikethrough = any('strikethrough', [r'(~~)(.*?)~~']) strong = any('strong', [r'(\*\*)(.*?)\*\*']) italic = r'(__)(.*?)__' emphasis = r'(//)(.*?)//' italic = any('italic', [italic, emphasis]) # links - (links) after [] or links after []: link_html = (r'(?<=(\]\())[^\(\)]*(?=\))|' '(]+>)|' '(<[^ >]+@[^ >]+>)') # link/image references - [] or ![] link = r'!?\[[^\[\]]*\]' links = any('link', [link_html, link]) # blockquotes and lists - > or - or * or 0. blockquotes = (r'(^>+.*)' r'|(^(?: |\t)*[0-9]+\. )' r'|(^(?: |\t)*- )' r'|(^(?: |\t)*\* )') # code code = any('code', ['^`{3,}.*$']) inline_code = any('inline_code', ['`[^`]*`']) # math - $$ math = any('number', [r'^(?:\${2}).*$', html_symbols]) comment = any('comment', [blockquotes, html_comment]) return '|'.join([titles, comment, html_tags, math, links, italic, strong, strikethrough, code, inline_code]) class MarkdownSH(BaseSH): """Markdown Syntax Highlighter""" # Syntax highlighting rules: PROG = re.compile(make_md_patterns(), re.S) NORMAL = 0 CODE = 1 def highlightBlock(self, text): text = to_text_string(text) previous_state = self.previousBlockState() if previous_state == self.CODE: self.setFormat(0, len(text), self.formats["code"]) else: previous_state = self.NORMAL self.setFormat(0, len(text), self.formats["normal"]) self.setCurrentBlockState(previous_state) match = self.PROG.search(text) match_count = 0 n_characters = len(text) while match and match_count< n_characters: for key, value in list(match.groupdict().items()): start, end = match.span(key) if value: previous_state = self.previousBlockState() if previous_state == self.CODE: if key == "code": # Change to normal self.setFormat(0, len(text), self.formats["normal"]) self.setCurrentBlockState(self.NORMAL) else: continue else: if key == "code": # Change to code self.setFormat(0, len(text), self.formats["code"]) self.setCurrentBlockState(self.CODE) continue self.setFormat(start, end - start, self.formats[key]) match = self.PROG.search(text, match.end()) match_count += 1 self.highlight_spaces(text) def setup_formats(self, font=None): super(MarkdownSH, self).setup_formats(font) font = QTextCharFormat(self.formats['normal']) font.setFontItalic(True) self.formats['italic'] = font self.formats['strong'] = self.formats['definition'] font = QTextCharFormat(self.formats['normal']) font.setFontStrikeOut(True) self.formats['strikethrough'] = font font = QTextCharFormat(self.formats['string']) font.setUnderlineStyle(True) self.formats['link'] = font self.formats['code'] = self.formats['string'] self.formats['inline_code'] = self.formats['string'] font = QTextCharFormat(self.formats['keyword']) font.setFontWeight(QFont.Bold) self.formats['title'] = font #============================================================================== # Pygments based omni-parser #============================================================================== # IMPORTANT NOTE: # -------------- # Do not be tempted to generalize the use of PygmentsSH (that is tempting # because it would lead to more generic and compact code, and not only in # this very module) because this generic syntax highlighter is far slower # than the native ones (all classes above). For example, a Python syntax # highlighter based on PygmentsSH would be 2 to 3 times slower than the # current native PythonSH syntax highlighter. class PygmentsSH(BaseSH): """ Generic Pygments syntax highlighter """ # Store the language name and a ref to the lexer _lang_name = None _lexer = None # Syntax highlighting states (from one text block to another): NORMAL = 0 def __init__(self, parent, font=None, color_scheme=None): # Warning: do not move out those import statements # (pygments is an optional dependency) from pygments.lexers import get_lexer_by_name from pygments.token import (Text, Other, Keyword, Name, String, Number, Comment, Generic, Token) # Map Pygments tokens to Spyder tokens self._tokmap = {Text: "normal", Generic: "normal", Other: "normal", Keyword: "keyword", Token.Operator: "normal", Name.Builtin: "builtin", Name: "normal", Comment: "comment", String: "string", Number: "number"} # Load Pygments' Lexer if self._lang_name is not None: self._lexer = get_lexer_by_name(self._lang_name) BaseSH.__init__(self, parent, font, color_scheme) # This worker runs in a thread to avoid blocking when doing full file # parsing self._worker_manager = WorkerManager() # Store the format for all the tokens after Pygments parsing self._charlist = [] # Flag variable to avoid unnecessary highlights if the worker has not # yet finished processing self._allow_highlight = True def make_charlist(self): """Parses the complete text and stores format for each character.""" def worker_output(worker, output, error): """Worker finished callback.""" self._charlist = output if error is None and output: self._allow_highlight = True self.rehighlight() self._allow_highlight = False text = to_text_string(self.document().toPlainText()) tokens = self._lexer.get_tokens(text) # Before starting a new worker process make sure to end previous # incarnations self._worker_manager.terminate_all() worker = self._worker_manager.create_python_worker( self._make_charlist, tokens, self._tokmap, self.formats, ) worker.sig_finished.connect(worker_output) worker.start() def _make_charlist(self, tokens, tokmap, formats): """ Parses the complete text and stores format for each character. Uses the attached lexer to parse into a list of tokens and Pygments token types. Then breaks tokens into individual letters, each with a Spyder token type attached. Stores this list as self._charlist. It's attached to the contentsChange signal of the parent QTextDocument so that the charlist is updated whenever the document changes. """ def _get_fmt(typ): """Get the Spyder format code for the given Pygments token type.""" # Exact matches first if typ in tokmap: return tokmap[typ] # Partial (parent-> child) matches for key, val in tokmap.items(): if typ in key: # Checks if typ is a subtype of key. return val return 'normal' charlist = [] for typ, token in tokens: fmt = formats[_get_fmt(typ)] for letter in token: charlist.append((fmt, letter)) return charlist def highlightBlock(self, text): """ Actually highlight the block""" # Note that an undefined blockstate is equal to -1, so the first block # will have the correct behaviour of starting at 0. if self._allow_highlight: start = self.previousBlockState() + 1 end = start + len(text) for i, (fmt, letter) in enumerate(self._charlist[start:end]): self.setFormat(i, 1, fmt) self.setCurrentBlockState(end) self.highlight_spaces(text) def guess_pygments_highlighter(filename): """Factory to generate syntax highlighter for the given filename. If a syntax highlighter is not available for a particular file, this function will attempt to generate one based on the lexers in Pygments. If Pygments is not available or does not have an appropriate lexer, TextSH will be returned instead. """ try: from pygments.lexers import get_lexer_for_filename, get_lexer_by_name from pygments.util import ClassNotFound except ImportError: return TextSH root, ext = os.path.splitext(filename) if ext in custom_extension_lexer_mapping: lexer = get_lexer_by_name(custom_extension_lexer_mapping[ext]) else: try: lexer = get_lexer_for_filename(filename) except ClassNotFound: return TextSH class GuessedPygmentsSH(PygmentsSH): _lexer = lexer return GuessedPygmentsSH spyder-3.2.6/spyder/utils/encoding.py0000664000175000017500000002034713224121062020427 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Text encoding utilities, text file I/O Functions 'get_coding', 'decode', 'encode' and 'to_unicode' come from Eric4 source code (Utilities/__init___.py) Copyright © 2003-2009 Detlev Offenbach """ import re import os import locale import sys from codecs import BOM_UTF8, BOM_UTF16, BOM_UTF32, getincrementaldecoder from chardet.universaldetector import UniversalDetector # Local imports from spyder.py3compat import (is_string, to_text_string, is_binary_string, is_unicode) from spyder.utils.external.binaryornot.check import is_binary PREFERRED_ENCODING = locale.getpreferredencoding() def transcode(text, input=PREFERRED_ENCODING, output=PREFERRED_ENCODING): """Transcode a text string""" try: return text.decode("cp437").encode("cp1252") except UnicodeError: try: return text.decode("cp437").encode(output) except UnicodeError: return text #------------------------------------------------------------------------------ # Functions for encoding and decoding bytes that come from # the *file system*. #------------------------------------------------------------------------------ # The default encoding for file paths and environment variables should be set # to match the default encoding that the OS is using. def getfilesystemencoding(): """ Query the filesystem for the encoding used to encode filenames and environment variables. """ encoding = sys.getfilesystemencoding() if encoding is None: # Must be Linux or Unix and nl_langinfo(CODESET) failed. encoding = PREFERRED_ENCODING return encoding FS_ENCODING = getfilesystemencoding() def to_unicode_from_fs(string): """ Return a unicode version of string decoded using the file system encoding. """ if not is_string(string): # string is a QString string = to_text_string(string.toUtf8(), 'utf-8') else: if is_binary_string(string): try: unic = string.decode(FS_ENCODING) except (UnicodeError, TypeError): pass else: return unic return string def to_fs_from_unicode(unic): """ Return a byte string version of unic encoded using the file system encoding. """ if is_unicode(unic): try: string = unic.encode(FS_ENCODING) except (UnicodeError, TypeError): pass else: return string return unic #------------------------------------------------------------------------------ # Functions for encoding and decoding *text data* itself, usually originating # from or destined for the *contents* of a file. #------------------------------------------------------------------------------ # Codecs for working with files and text. CODING_RE = re.compile(r"coding[:=]\s*([-\w_.]+)") CODECS = ['utf-8', 'iso8859-1', 'iso8859-15', 'ascii', 'koi8-r', 'cp1251', 'koi8-u', 'iso8859-2', 'iso8859-3', 'iso8859-4', 'iso8859-5', 'iso8859-6', 'iso8859-7', 'iso8859-8', 'iso8859-9', 'iso8859-10', 'iso8859-13', 'iso8859-14', 'latin-1', 'utf-16'] def get_coding(text): """ Function to get the coding of a text. @param text text to inspect (string) @return coding string """ for line in text.splitlines()[:2]: try: result = CODING_RE.search(to_text_string(line)) except UnicodeDecodeError: # This could fail because to_text_string assume the text is utf8-like # and we don't know the encoding to give it to to_text_string pass else: if result: codec = result.group(1) # sometimes we find a false encoding that can result in errors if codec in CODECS: return codec # Fallback using chardet if is_binary_string(text): detector = UniversalDetector() for line in text.splitlines()[:2]: detector.feed(line) if detector.done: break detector.close() return detector.result['encoding'] return None def decode(text): """ Function to decode a text. @param text text to decode (string) @return decoded text and encoding """ try: if text.startswith(BOM_UTF8): # UTF-8 with BOM return to_text_string(text[len(BOM_UTF8):], 'utf-8'), 'utf-8-bom' elif text.startswith(BOM_UTF16): # UTF-16 with BOM return to_text_string(text[len(BOM_UTF16):], 'utf-16'), 'utf-16' elif text.startswith(BOM_UTF32): # UTF-32 with BOM return to_text_string(text[len(BOM_UTF32):], 'utf-32'), 'utf-32' coding = get_coding(text) if coding: return to_text_string(text, coding), coding except (UnicodeError, LookupError): pass # Assume UTF-8 try: return to_text_string(text, 'utf-8'), 'utf-8-guessed' except (UnicodeError, LookupError): pass # Assume Latin-1 (behaviour before 3.7.1) return to_text_string(text, "latin-1"), 'latin-1-guessed' def encode(text, orig_coding): """ Function to encode a text. @param text text to encode (string) @param orig_coding type of the original coding (string) @return encoded text and encoding """ if orig_coding == 'utf-8-bom': return BOM_UTF8 + text.encode("utf-8"), 'utf-8-bom' # Try saving with original encoding if orig_coding: try: return text.encode(orig_coding), orig_coding except (UnicodeError, LookupError): pass # Try declared coding spec coding = get_coding(text) if coding: try: return text.encode(coding), coding except (UnicodeError, LookupError): raise RuntimeError("Incorrect encoding (%s)" % coding) if orig_coding and orig_coding.endswith('-default') or \ orig_coding.endswith('-guessed'): coding = orig_coding.replace("-default", "") coding = orig_coding.replace("-guessed", "") try: return text.encode(coding), coding except (UnicodeError, LookupError): pass # Try saving as ASCII try: return text.encode('ascii'), 'ascii' except UnicodeError: pass # Save as UTF-8 without BOM return text.encode('utf-8'), 'utf-8' def to_unicode(string): """Convert a string to unicode""" if not is_unicode(string): for codec in CODECS: try: unic = to_text_string(string, codec) except UnicodeError: pass except TypeError: break else: return unic return string def write(text, filename, encoding='utf-8', mode='wb'): """ Write 'text' to file ('filename') assuming 'encoding' Return (eventually new) encoding """ text, encoding = encode(text, encoding) with open(filename, mode) as textfile: textfile.write(text) return encoding def writelines(lines, filename, encoding='utf-8', mode='wb'): """ Write 'lines' to file ('filename') assuming 'encoding' Return (eventually new) encoding """ return write(os.linesep.join(lines), filename, encoding, mode) def read(filename, encoding='utf-8'): """ Read text from file ('filename') Return text and encoding """ text, encoding = decode( open(filename, 'rb').read() ) return text, encoding def readlines(filename, encoding='utf-8'): """ Read lines from file ('filename') Return lines and encoding """ text, encoding = read(filename, encoding) return text.split(os.linesep), encoding def is_text_file(filename): """ Test if the given path is a text-like file. """ try: return not is_binary(filename) except (OSError, IOError): return False spyder-3.2.6/spyder/utils/__init__.py0000664000175000017500000000033313026261005020373 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ spyder.utils ============ Spyder utilities """ spyder-3.2.6/spyder/utils/external/0000775000175000017500000000000013225025007020106 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/utils/external/lockfile.py0000664000175000017500000002105213224121062022245 0ustar carloscarlos00000000000000# Copyright (c) 2005 Divmod, Inc. # Copyright (c) Twisted Matrix Laboratories. # Copyright (c) Spyder Project Contributors # Twisted is distributed under the MIT license. """ Filesystem-based interprocess mutex. Taken from the Twisted project. Distributed under the MIT license. Changes by the Spyder Team to the original module: * Rewrite kill Windows function to make it more reliable. * Detect if the process that owns the lock is an Spyder one. """ __metaclass__ = type import errno, os from time import time as _uniquefloat import psutil from spyder.py3compat import PY2, to_binary_string def unique(): if PY2: return str(long(_uniquefloat() * 1000)) else: return str(int(_uniquefloat() * 1000)) from os import rename if not os.name == 'nt': from os import kill from os import symlink from os import readlink from os import remove as rmlink _windows = False else: _windows = True import ctypes from ctypes import wintypes # http://msdn.microsoft.com/en-us/library/windows/desktop/ms684880(v=vs.85).aspx PROCESS_QUERY_INFORMATION = 0x400 # GetExitCodeProcess uses a special exit code to indicate that the # process is still running. STILL_ACTIVE = 259 def _is_pid_running(pid): """Taken from http://www.madebuild.org/blog/?p=30""" kernel32 = ctypes.windll.kernel32 handle = kernel32.OpenProcess(PROCESS_QUERY_INFORMATION, 0, pid) if handle == 0: return False # If the process exited recently, a pid may still exist for the # handle. So, check if we can get the exit code. exit_code = wintypes.DWORD() retval = kernel32.GetExitCodeProcess(handle, ctypes.byref(exit_code)) is_running = (retval == 0) kernel32.CloseHandle(handle) # See if we couldn't get the exit code or the exit code indicates # that the process is still running. return is_running or exit_code.value == STILL_ACTIVE def kill(pid, signal): # analysis:ignore if not _is_pid_running(pid): raise OSError(errno.ESRCH, None) else: return _open = open # XXX Implement an atomic thingamajig for win32 def symlink(value, filename): #analysis:ignore newlinkname = filename+"."+unique()+'.newlink' newvalname = os.path.join(newlinkname, "symlink") os.mkdir(newlinkname) f = _open(newvalname, 'wb') f.write(to_binary_string(value)) f.flush() f.close() try: rename(newlinkname, filename) except: os.remove(newvalname) os.rmdir(newlinkname) raise def readlink(filename): #analysis:ignore try: fObj = _open(os.path.join(filename, 'symlink'), 'rb') except IOError as e: if e.errno == errno.ENOENT or e.errno == errno.EIO: raise OSError(e.errno, None) raise else: result = fObj.read().decode() fObj.close() return result def rmlink(filename): #analysis:ignore os.remove(os.path.join(filename, 'symlink')) os.rmdir(filename) class FilesystemLock: """ A mutex. This relies on the filesystem property that creating a symlink is an atomic operation and that it will fail if the symlink already exists. Deleting the symlink will release the lock. @ivar name: The name of the file associated with this lock. @ivar clean: Indicates whether this lock was released cleanly by its last owner. Only meaningful after C{lock} has been called and returns True. @ivar locked: Indicates whether the lock is currently held by this object. """ clean = None locked = False def __init__(self, name): self.name = name def lock(self): """ Acquire this lock. @rtype: C{bool} @return: True if the lock is acquired, false otherwise. @raise: Any exception os.symlink() may raise, other than EEXIST. """ clean = True while True: try: symlink(str(os.getpid()), self.name) except OSError as e: if _windows and e.errno in (errno.EACCES, errno.EIO): # The lock is in the middle of being deleted because we're # on Windows where lock removal isn't atomic. Give up, we # don't know how long this is going to take. return False if e.errno == errno.EEXIST: try: pid = readlink(self.name) except OSError as e: if e.errno == errno.ENOENT: # The lock has vanished, try to claim it in the # next iteration through the loop. continue raise except IOError as e: if _windows and e.errno == errno.EACCES: # The lock is in the middle of being # deleted because we're on Windows where # lock removal isn't atomic. Give up, we # don't know how long this is going to # take. return False raise try: if kill is not None: kill(int(pid), 0) # Verify that the running process corresponds to # a Spyder one p = psutil.Process(int(pid)) if os.name == 'nt': conditions = ['spyder' in c.lower() for c in p.cmdline()] else: # Valid names for main script names = set(['spyder', 'spyder3', 'bootstrap.py']) # Check the first three command line arguments arguments = set(os.path.basename(arg) for arg in p.cmdline()[:3]) conditions = [names & arguments] if not any(conditions): raise(OSError(errno.ESRCH, 'No such process')) except OSError as e: if e.errno == errno.ESRCH: # The owner has vanished, try to claim it in the # next iteration through the loop. try: rmlink(self.name) except OSError as e: if e.errno == errno.ENOENT: # Another process cleaned up the lock. # Race them to acquire it in the next # iteration through the loop. continue raise clean = False continue raise return False raise self.locked = True self.clean = clean return True def unlock(self): """ Release this lock. This deletes the directory with the given name. @raise: Any exception os.readlink() may raise, or ValueError if the lock is not owned by this process. """ pid = readlink(self.name) if int(pid) != os.getpid(): raise ValueError("Lock %r not owned by this process" % (self.name,)) rmlink(self.name) self.locked = False def isLocked(name): """Determine if the lock of the given name is held or not. @type name: C{str} @param name: The filesystem path to the lock to test @rtype: C{bool} @return: True if the lock is held, False otherwise. """ l = FilesystemLock(name) result = None try: result = l.lock() finally: if result: l.unlock() return not result __all__ = ['FilesystemLock', 'isLocked'] spyder-3.2.6/spyder/utils/external/binaryornot/0000775000175000017500000000000013225025007022454 5ustar carloscarlos00000000000000spyder-3.2.6/spyder/utils/external/binaryornot/check.py0000664000175000017500000000144713211142272024110 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- """ binaryornot.check ----------------- Main code for checking if a file is binary or text. """ import logging from spyder.utils.external.binaryornot.helpers import get_starting_chunk, is_binary_string logger = logging.getLogger(__name__) def is_binary(filename): """ :param filename: File to check. :returns: True if it's a binary file, otherwise False. """ logger.debug('is_binary: %(filename)r', locals()) # Check if the file extension is in a list of known binary types binary_extensions = ['pyc', 'iso', 'zip', 'pdf'] for ext in binary_extensions: if filename.endswith(ext): return True # Check if the starting chunk is a binary string chunk = get_starting_chunk(filename) return is_binary_string(chunk) spyder-3.2.6/spyder/utils/external/binaryornot/LICENSE.txt0000664000175000017500000000270713156676663024334 0ustar carloscarlos00000000000000Copyright (c) 2013, Audrey Roy All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of BinaryOrNot nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. spyder-3.2.6/spyder/utils/external/binaryornot/helpers.py0000664000175000017500000001110213156676663024512 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- """ binaryornot.helpers ------------------- Helper utilities used by BinaryOrNot. """ import chardet import logging logger = logging.getLogger(__name__) def print_as_hex(s): """ Print a string as hex bytes. """ print(":".join("{0:x}".format(ord(c)) for c in s)) def get_starting_chunk(filename, length=1024): """ :param filename: File to open and get the first little chunk of. :param length: Number of bytes to read, default 1024. :returns: Starting chunk of bytes. """ # Ensure we open the file in binary mode with open(filename, 'rb') as f: chunk = f.read(length) return chunk _control_chars = b'\n\r\t\f\b' if bytes is str: # Python 2 means we need to invoke chr() explicitly _printable_ascii = _control_chars + b''.join(map(chr, range(32, 127))) _printable_high_ascii = b''.join(map(chr, range(127, 256))) else: # Python 3 means bytes accepts integer input directly _printable_ascii = _control_chars + bytes(range(32, 127)) _printable_high_ascii = bytes(range(127, 256)) def is_binary_string(bytes_to_check): """ Uses a simplified version of the Perl detection algorithm, based roughly on Eli Bendersky's translation to Python: http://eli.thegreenplace.net/2011/10/19/perls-guess-if-file-is-text-or-binary-implemented-in-python/ This is biased slightly more in favour of deeming files as text files than the Perl algorithm, since all ASCII compatible character sets are accepted as text, not just utf-8. :param bytes: A chunk of bytes to check. :returns: True if appears to be a binary, otherwise False. """ # Empty files are considered text files if not bytes_to_check: return False # Now check for a high percentage of ASCII control characters # Binary if control chars are > 30% of the string low_chars = bytes_to_check.translate(None, _printable_ascii) nontext_ratio1 = float(len(low_chars)) / float(len(bytes_to_check)) logger.debug('nontext_ratio1: %(nontext_ratio1)r', locals()) # and check for a low percentage of high ASCII characters: # Binary if high ASCII chars are < 5% of the string # From: https://en.wikipedia.org/wiki/UTF-8 # If the bytes are random, the chances of a byte with the high bit set # starting a valid UTF-8 character is only 6.64%. The chances of finding 7 # of these without finding an invalid sequence is actually lower than the # chance of the first three bytes randomly being the UTF-8 BOM. high_chars = bytes_to_check.translate(None, _printable_high_ascii) nontext_ratio2 = float(len(high_chars)) / float(len(bytes_to_check)) logger.debug('nontext_ratio2: %(nontext_ratio2)r', locals()) is_likely_binary = ( (nontext_ratio1 > 0.3 and nontext_ratio2 < 0.05) or (nontext_ratio1 > 0.8 and nontext_ratio2 > 0.8) ) logger.debug('is_likely_binary: %(is_likely_binary)r', locals()) # then check for binary for possible encoding detection with chardet detected_encoding = chardet.detect(bytes_to_check) logger.debug('detected_encoding: %(detected_encoding)r', locals()) # finally use all the check to decide binary or text decodable_as_unicode = False if (detected_encoding['confidence'] > 0.9 and detected_encoding['encoding'] != 'ascii'): try: try: bytes_to_check.decode(encoding=detected_encoding['encoding']) except TypeError: # happens only on Python 2.6 unicode(bytes_to_check, encoding=detected_encoding['encoding']) # noqa decodable_as_unicode = True logger.debug('success: decodable_as_unicode: ' '%(decodable_as_unicode)r', locals()) except LookupError: logger.debug('failure: could not look up encoding %(encoding)s', detected_encoding) except UnicodeDecodeError: logger.debug('failure: decodable_as_unicode: ' '%(decodable_as_unicode)r', locals()) logger.debug('failure: decodable_as_unicode: ' '%(decodable_as_unicode)r', locals()) if is_likely_binary: if decodable_as_unicode: return False else: return True else: if decodable_as_unicode: return False else: if b'\x00' in bytes_to_check or b'\xff' in bytes_to_check: # Check for NULL bytes last logger.debug('has nulls:' + repr(b'\x00' in bytes_to_check)) return True return False spyder-3.2.6/spyder/utils/external/binaryornot/__init__.py0000664000175000017500000000012013156676663024605 0ustar carloscarlos00000000000000__author__ = 'Audrey Roy' __email__ = 'audreyr@gmail.com' __version__ = '0.4.0' spyder-3.2.6/spyder/utils/external/__init__.py0000664000175000017500000000075213156676663022252 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ spyder.utils.external ===================== * Libraries or modules taken from external projects verbatim. * Spyder developers can modify these modules to make them work better for the project. So there's no guarantee that we will maintain compatibility with the upstream project the code was taken from. """ spyder-3.2.6/PKG-INFO0000664000175000017500000000231013225025007014707 0ustar carloscarlos00000000000000Metadata-Version: 1.1 Name: spyder Version: 3.2.6 Summary: Scientific PYthon Development EnviRonment Home-page: https://github.com/spyder-ide/spyder Author: The Spyder Project Contributors Author-email: UNKNOWN License: MIT Download-URL: https://github.com/spyder-ide/spyder/files/spyder-3.2.6.zip Description: Spyder is an interactive Python development environment providing MATLAB-like features in a simple and light-weighted software. It also provides ready-to-use pure-Python widgets to your PyQt5 or PyQt4 application: source code editor with syntax highlighting and code introspection/analysis features, NumPy array editor, dictionary editor, Python console, etc. Keywords: PyQt5 PyQt4 editor shell console widgets IDE Platform: any Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: MacOS Classifier: Operating System :: Microsoft :: Windows Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Development Status :: 5 - Production/Stable Classifier: Topic :: Scientific/Engineering Classifier: Topic :: Software Development :: Widget Sets spyder-3.2.6/setup.py0000664000175000017500000003006113224121062015325 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Spyder ====== The Scientific PYthon Development EnviRonment """ from __future__ import print_function import os import os.path as osp import subprocess import sys import shutil from distutils.core import setup from distutils.command.build import build from distutils.command.install import install from distutils.command.install_data import install_data #============================================================================== # Check for Python 3 #============================================================================== PY3 = sys.version_info[0] == 3 #============================================================================== # Minimal Python version sanity check # Taken from the notebook setup.py -- Modified BSD License #============================================================================== v = sys.version_info if v[:2] < (2,7) or (v[0] >= 3 and v[:2] < (3,3)): error = "ERROR: Spyder requires Python version 2.7 or 3.3 or above." print(error, file=sys.stderr) sys.exit(1) #============================================================================== # Constants #============================================================================== NAME = 'spyder' LIBNAME = 'spyder' from spyder import __version__, __project_url__ #============================================================================== # Auxiliary functions #============================================================================== def get_package_data(name, extlist): """Return data files for package *name* with extensions in *extlist*""" flist = [] # Workaround to replace os.path.relpath (not available until Python 2.6): offset = len(name)+len(os.pathsep) for dirpath, _dirnames, filenames in os.walk(name): for fname in filenames: if not fname.startswith('.') and osp.splitext(fname)[1] in extlist: flist.append(osp.join(dirpath, fname)[offset:]) return flist def get_subpackages(name): """Return subpackages of package *name*""" splist = [] for dirpath, _dirnames, _filenames in os.walk(name): if osp.isfile(osp.join(dirpath, '__init__.py')): splist.append(".".join(dirpath.split(os.sep))) return splist def get_data_files(): """Return data_files in a platform dependent manner""" if sys.platform.startswith('linux'): if PY3: data_files = [('share/applications', ['scripts/spyder3.desktop']), ('share/pixmaps', ['img_src/spyder3.png']), ('share/metainfo', ['scripts/spyder3.appdata.xml'])] else: data_files = [('share/applications', ['scripts/spyder.desktop']), ('share/pixmaps', ['img_src/spyder.png'])] elif os.name == 'nt': data_files = [('scripts', ['img_src/spyder.ico', 'img_src/spyder_reset.ico'])] else: data_files = [] return data_files def get_packages(): """Return package list""" packages = ( get_subpackages(LIBNAME) + get_subpackages('spyder_breakpoints') + get_subpackages('spyder_profiler') + get_subpackages('spyder_pylint') + get_subpackages('spyder_io_dcm') + get_subpackages('spyder_io_hdf5') ) return packages #============================================================================== # Make Linux detect Spyder desktop file #============================================================================== class MyInstallData(install_data): def run(self): install_data.run(self) if sys.platform.startswith('linux'): try: subprocess.call(['update-desktop-database']) except: print("ERROR: unable to update desktop database", file=sys.stderr) CMDCLASS = {'install_data': MyInstallData} #============================================================================== # Sphinx build (documentation) #============================================================================== def get_html_help_exe(): """Return HTML Help Workshop executable path (Windows only)""" if os.name == 'nt': hhc_base = r'C:\Program Files%s\HTML Help Workshop\hhc.exe' for hhc_exe in (hhc_base % '', hhc_base % ' (x86)'): if osp.isfile(hhc_exe): return hhc_exe else: return try: from sphinx import setup_command class MyBuild(build): user_options = [('no-doc', None, "Don't build Spyder documentation")] \ + build.user_options def __init__(self, *args, **kwargs): build.__init__(self, *args, **kwargs) self.no_doc = False def with_doc(self): setup_dir = os.path.dirname(os.path.abspath(__file__)) is_doc_dir = os.path.isdir(os.path.join(setup_dir, 'doc')) install_obj = self.distribution.get_command_obj('install') return (is_doc_dir and not self.no_doc and not install_obj.no_doc) sub_commands = build.sub_commands + [('build_doc', with_doc)] CMDCLASS['build'] = MyBuild class MyInstall(install): user_options = [('no-doc', None, "Don't build Spyder documentation")] \ + install.user_options def __init__(self, *args, **kwargs): install.__init__(self, *args, **kwargs) self.no_doc = False CMDCLASS['install'] = MyInstall class MyBuildDoc(setup_command.BuildDoc): def run(self): build = self.get_finalized_command('build') sys.path.insert(0, os.path.abspath(build.build_lib)) dirname = self.distribution.get_command_obj('build').build_purelib self.builder_target_dir = osp.join(dirname, 'spyder', 'doc') if not osp.exists(self.builder_target_dir): os.mkdir(self.builder_target_dir) hhc_exe = get_html_help_exe() self.builder = "html" if hhc_exe is None else "htmlhelp" try: setup_command.BuildDoc.run(self) except UnicodeDecodeError: print("ERROR: unable to build documentation because Sphinx "\ "do not handle source path with non-ASCII characters. "\ "Please try to move the source package to another "\ "location (path with *only* ASCII characters).", file=sys.stderr) sys.path.pop(0) # Building chm doc, if HTML Help Workshop is installed if hhc_exe is not None: fname = osp.join(self.builder_target_dir, 'Spyderdoc.chm') subprocess.call('"%s" %s' % (hhc_exe, fname), shell=True) if osp.isfile(fname): dest = osp.join(dirname, 'spyder') try: shutil.move(fname, dest) except shutil.Error: print("Unable to replace %s" % dest) shutil.rmtree(self.builder_target_dir) CMDCLASS['build_doc'] = MyBuildDoc except ImportError: print('WARNING: unable to build documentation because Sphinx '\ 'is not installed', file=sys.stderr) #============================================================================== # Main scripts #============================================================================== # NOTE: the '[...]_win_post_install.py' script is installed even on non-Windows # platforms due to a bug in pip installation process (see Issue 1158) SCRIPTS = ['%s_win_post_install.py' % NAME] if PY3 and sys.platform.startswith('linux'): SCRIPTS.append('spyder3') else: SCRIPTS.append('spyder') #============================================================================== # Files added to the package #============================================================================== EXTLIST = ['.mo', '.svg', '.png', '.css', '.html', '.js', '.chm', '.ini', '.txt', '.rst', '.qss', '.ttf', '.json', '.c', '.cpp', '.java', '.md', '.R', '.csv', '.pyx', '.ipynb'] if os.name == 'nt': SCRIPTS += ['spyder.bat'] EXTLIST += ['.ico'] #============================================================================== # Setup arguments #============================================================================== setup_args = dict(name=NAME, version=__version__, description='Scientific PYthon Development EnviRonment', long_description= """Spyder is an interactive Python development environment providing MATLAB-like features in a simple and light-weighted software. It also provides ready-to-use pure-Python widgets to your PyQt5 or PyQt4 application: source code editor with syntax highlighting and code introspection/analysis features, NumPy array editor, dictionary editor, Python console, etc.""", download_url='%s/files/%s-%s.zip' % (__project_url__, NAME, __version__), author="The Spyder Project Contributors", url=__project_url__, license='MIT', keywords='PyQt5 PyQt4 editor shell console widgets IDE', platforms=['any'], packages=get_packages(), package_data={LIBNAME: get_package_data(LIBNAME, EXTLIST), 'spyder_breakpoints': get_package_data('spyder_breakpoints', EXTLIST), 'spyder_profiler': get_package_data('spyder_profiler', EXTLIST), 'spyder_pylint': get_package_data('spyder_pylint', EXTLIST), 'spyder_io_dcm': get_package_data('spyder_io_dcm', EXTLIST), 'spyder_io_hdf5': get_package_data('spyder_io_hdf5', EXTLIST), }, scripts=[osp.join('scripts', fname) for fname in SCRIPTS], data_files=get_data_files(), classifiers=['License :: OSI Approved :: MIT License', 'Operating System :: MacOS', 'Operating System :: Microsoft :: Windows', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Development Status :: 5 - Production/Stable', 'Topic :: Scientific/Engineering', 'Topic :: Software Development :: Widget Sets'], cmdclass=CMDCLASS) #============================================================================== # Setuptools deps #============================================================================== if any(arg == 'bdist_wheel' for arg in sys.argv): import setuptools # analysis:ignore install_requires = [ 'cloudpickle', 'rope>=0.10.5', 'jedi>=0.9.0', 'pyflakes', 'pygments>=2.0', 'qtconsole>=4.2.0', 'nbconvert', 'sphinx', 'pycodestyle', 'pylint', 'psutil', 'qtawesome>=0.4.1', 'qtpy>=1.2.0', 'pickleshare', 'pyzmq', 'chardet>=2.0.0', 'numpydoc', # Packages for pyqt5 are only available in # Python 3 'pyqt5;python_version>="3"', # This is only needed for our wheels on Linux. # See issue #3332 'pyopengl;platform_system=="Linux"' ] extras_require = { 'test:python_version == "2.7"': ['mock'], 'test': ['pytest', 'pytest-qt', 'pytest-mock', 'pytest-cov', 'pytest-xvfb', 'pytest-timeout', 'mock', 'flaky', 'pandas', 'scipy', 'sympy', 'pillow', 'matplotlib', 'cython'], } if 'setuptools' in sys.modules: setup_args['install_requires'] = install_requires setup_args['extras_require'] = extras_require setup_args['entry_points'] = { 'gui_scripts': [ '{} = spyder.app.start:main'.format( 'spyder3' if PY3 else 'spyder') ] } setup_args.pop('scripts', None) #============================================================================== # Main setup #============================================================================== setup(**setup_args) spyder-3.2.6/bootstrap.py0000775000175000017500000001357413224740762016235 0ustar carloscarlos00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Bootstrapping Spyder Detect environment and execute Spyder from source checkout See Issue 741 """ # pylint: disable=C0103 import time time_start = time.time() import os import os.path as osp import sys import optparse # --- Parse command line parser = optparse.OptionParser( usage="python bootstrap.py [options] [-- spyder_options]", epilog="""\ Arguments for Spyder's main script are specified after the -- symbol (example: `python bootstrap.py -- --hide-console`). Type `python bootstrap.py -- --help` to read about Spyder options.""") parser.add_option('--gui', default=None, help="GUI toolkit: pyqt5 (for PyQt5), pyqt (for PyQt4) or " "pyside (for PySide, deprecated)") parser.add_option('--show-console', action='store_true', default=False, help="(Deprecated) Does nothing, now the default behavior " "is to show the console") parser.add_option('--hide-console', action='store_true', default=False, help="Hide parent console window (Windows only)") parser.add_option('--test', dest="test", action='store_true', default=False, help="Test Spyder with a clean settings dir") parser.add_option('--no-apport', action='store_true', default=False, help="Disable Apport exception hook (Ubuntu)") parser.add_option('--debug', action='store_true', default=False, help="Run Spyder in debug mode") options, args = parser.parse_args() # Store variable to be used in self.restart (restart spyder instance) os.environ['SPYDER_BOOTSTRAP_ARGS'] = str(sys.argv[1:]) assert options.gui in (None, 'pyqt5', 'pyqt', 'pyside'), \ "Invalid GUI toolkit option '%s'" % options.gui # For testing purposes if options.test: os.environ['SPYDER_TEST'] = 'True' # Prepare arguments for Spyder's main script sys.argv = [sys.argv[0]] + args print("Executing Spyder from source checkout") DEVPATH = osp.dirname(osp.abspath(__file__)) # To activate/deactivate certain things for development os.environ['SPYDER_DEV'] = 'True' # --- Test environment for surprises # Warn if Spyder is located on non-ASCII path # See Issue 812 try: osp.join(DEVPATH, 'test') except UnicodeDecodeError: print("STOP: Spyder is located in the path with non-ASCII characters,") print(" which is known to cause problems (see issue #812).") try: input = raw_input except NameError: pass input("Press Enter to continue or Ctrl-C to abort...") # Warn if we're running under 3rd party exception hook, such as # apport_python_hook.py from Ubuntu if sys.excepthook != sys.__excepthook__: if sys.excepthook.__name__ != 'apport_excepthook': print("WARNING: 3rd party Python exception hook is active: '%s'" % sys.excepthook.__name__) else: if not options.no_apport: print("WARNING: Ubuntu Apport exception hook is detected") print(" Use --no-apport option to disable it") else: sys.excepthook = sys.__excepthook__ print("NOTICE: Ubuntu Apport exception hook is disabed") # --- Continue if options.debug: # safety check - Spyder config should not be imported at this point if "spyder.config.base" in sys.modules: sys.exit("ERROR: Can't enable debug mode - Spyder is already imported") print("0x. Switching debug mode on") os.environ["SPYDER_DEBUG"] = "True" # this way of interaction suxx, because there is no feedback # if operation is successful from spyder.utils.vcs import get_git_revision print("Revision %s, Branch: %s" % get_git_revision(DEVPATH)) sys.path.insert(0, DEVPATH) print("01. Patched sys.path with %s" % DEVPATH) # Selecting the GUI toolkit: PyQt5 if installed, otherwise PySide or PyQt4 # (Note: PyQt4 is still the officially supported GUI toolkit for Spyder) if options.gui is None: try: import PyQt5 # analysis:ignore print("02. PyQt5 is detected, selecting") os.environ['QT_API'] = 'pyqt5' except ImportError: try: import PyQt4 # analysis:ignore print("02. PyQt4 is detected, selecting") os.environ['QT_API'] = 'pyqt' except ImportError: print("02. No PyQt5 or PyQt4 detected, using PySide if available " "(deprecated)") else: print ("02. Skipping GUI toolkit detection") os.environ['QT_API'] = options.gui # Checking versions (among other things, this has the effect of setting the # QT_API environment variable if this has not yet been done just above) from spyder import get_versions versions = get_versions(reporev=False) print("03. Imported Spyder %s" % versions['spyder']) print(" [Python %s %dbits, Qt %s, %s %s on %s]" % \ (versions['python'], versions['bitness'], versions['qt'], versions['qt_api'], versions['qt_api_ver'], versions['system'])) # Check that we have the right qtpy version from spyder.utils import programs if not programs.is_module_installed('qtpy', '>=1.1.0'): print("") sys.exit("ERROR: Your qtpy version is outdated. Please install qtpy " "1.1.0 or higher to be able to work with Spyder!") # --- Executing Spyder if options.show_console: print("(Deprecated) --show console does nothing, now the default behavior " "is to show the console, use --hide-console if you want to hide it") if options.hide_console and os.name == 'nt': print("0x. Hiding parent console (Windows only)") sys.argv.append("--hide-console") # Windows only: show parent console print("04. Running Spyder") from spyder.app import start time_lapse = time.time()-time_start print("Bootstrap completed in " + time.strftime("%H:%M:%S.", time.gmtime(time_lapse)) + # gmtime() converts float into tuple, but loses milliseconds ("%.4f" % time_lapse).split('.')[1]) start.main() spyder-3.2.6/spyder_pylint/0000775000175000017500000000000013225025007016523 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_pylint/locale/0000775000175000017500000000000013225025007017762 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_pylint/locale/ru/0000775000175000017500000000000013225025007020410 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_pylint/locale/ru/LC_MESSAGES/0000775000175000017500000000000013225025007022175 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_pylint/locale/ru/LC_MESSAGES/pylint.po0000664000175000017500000001102413224121062024047 0ustar carloscarlos00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR ORGANIZATION # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: 2017-12-14 15:40+-05\n" "PO-Revision-Date: 2016-04-18 20:29+0300\n" "Last-Translator: Roman Kulagin \n" "Language-Team: \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "X-Generator: Poedit 1.5.4\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" #: spyder_pylint/pylint.py:36 msgid "Settings" msgstr "Настройки" #: spyder_pylint/pylint.py:37 msgid "Save file before analyzing it" msgstr "Сохранить файл перед его анализом" #: spyder_pylint/pylint.py:40 spyder_pylint/pylint.py:161 msgid "History" msgstr "История" #: spyder_pylint/pylint.py:41 msgid "The following option will be applied at next startup." msgstr "Следующая опция будет применена при следующем запуске." #: spyder_pylint/pylint.py:44 msgid "History: " msgstr "История:" #: spyder_pylint/pylint.py:45 msgid " results" msgstr " результаты" #: spyder_pylint/pylint.py:48 msgid "Results" msgstr "Результаты" #: spyder_pylint/pylint.py:49 msgid "Results are stored here:" msgstr "Результаты хранятся здесь:" #: spyder_pylint/pylint.py:99 spyder_pylint/widgets/pylintgui.py:52 msgid "Static code analysis" msgstr "Статический анализ кода" #: spyder_pylint/pylint.py:116 msgid "History..." msgstr "История..." #: spyder_pylint/pylint.py:118 msgid "Set history maximum entries" msgstr "Установить максимальное число записей истории" #: spyder_pylint/pylint.py:134 msgid "Run static code analysis" msgstr "Запустить статический анализ кода" #: spyder_pylint/pylint.py:162 msgid "Maximum entries" msgstr "Максимум записей" #: spyder_pylint/widgets/pylintgui.py:86 msgid "Results for " msgstr "Результаты для" # Соглашения, Конвенции #: spyder_pylint/widgets/pylintgui.py:91 msgid "Convention" msgstr "Договорённости" #: spyder_pylint/widgets/pylintgui.py:93 msgid "Refactor" msgstr "Рефакторинг" #: spyder_pylint/widgets/pylintgui.py:95 msgid "Warning" msgstr "Предупреждения" #: spyder_pylint/widgets/pylintgui.py:97 spyder_pylint/widgets/pylintgui.py:318 #: spyder_pylint/widgets/pylintgui.py:346 msgid "Error" msgstr "Ошибки" #: spyder_pylint/widgets/pylintgui.py:172 msgid "Analyze" msgstr "Анализ" #: spyder_pylint/widgets/pylintgui.py:173 msgid "Run analysis" msgstr "Запустить анализ" #: spyder_pylint/widgets/pylintgui.py:177 msgid "Stop" msgstr "Остановить" #: spyder_pylint/widgets/pylintgui.py:178 msgid "Stop current analysis" msgstr "Остановить текущий анализ" #: spyder_pylint/widgets/pylintgui.py:184 #: spyder_pylint/widgets/pylintgui.py:242 msgid "Select Python file" msgstr "Выбрать файл Python" #: spyder_pylint/widgets/pylintgui.py:190 msgid "Output" msgstr "Вывод" #: spyder_pylint/widgets/pylintgui.py:192 msgid "Complete output" msgstr "Детальный вывод:" #: spyder_pylint/widgets/pylintgui.py:243 msgid "Python files" msgstr "Файлы Python" #: spyder_pylint/widgets/pylintgui.py:280 msgid "Pylint output" msgstr "Вывод pylint" #: spyder_pylint/widgets/pylintgui.py:319 msgid "Process failed to start" msgstr "Процесс не удалось запустить" #: spyder_pylint/widgets/pylintgui.py:420 msgid "Source code has not been rated yet." msgstr "Исходный код еще не был оценен." #: spyder_pylint/widgets/pylintgui.py:426 msgid "Analysis did not succeed (see output for more details)." msgstr "Анализ не удался (смотрите подробности в выводе)." #: spyder_pylint/widgets/pylintgui.py:439 msgid "Global evaluation:" msgstr "Общая оценка:" #: spyder_pylint/widgets/pylintgui.py:443 msgid "previous run:" msgstr "предыдущий запуск:" #~ msgid "Pylint script was not found. Please add \"%s\" to PATH." #~ msgstr "Скрипт pylint не найден. Пожалуйста добавьте \"%s\" в PATH." #~ msgid "Please install pylint:" #~ msgstr "Пожалуйста, установите pylint:" spyder-3.2.6/spyder_pylint/locale/ru/LC_MESSAGES/pylint.mo0000664000175000017500000000555413224121062024057 0ustar carloscarlos00000000000000!$/,7*2 BMSf n y    *H[w#5   Y S`  5Tfx1? >R  V  8 ,S  0 e , "I  !     resultsAnalysis did not succeed (see output for more details).AnalyzeComplete outputConventionErrorGlobal evaluation:HistoryHistory...History: Maximum entriesOutputProcess failed to startPylint outputPython filesRefactorResultsResults are stored here:Results for Run analysisRun static code analysisSave file before analyzing itSelect Python fileSet history maximum entriesSettingsSource code has not been rated yet.Static code analysisStopStop current analysisThe following option will be applied at next startup.Warningprevious run:Project-Id-Version: POT-Creation-Date: 2017-07-11 13:28+COT PO-Revision-Date: 2016-04-18 20:29+0300 Last-Translator: Roman Kulagin Language-Team: Language: ru MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generated-By: pygettext.py 1.5 X-Generator: Poedit 1.5.4 Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2); результатыАнализ не удался (смотрите подробности в выводе).АнализДетальный вывод:ДоговорённостиОшибкиОбщая оценка:ИсторияИстория...История:Максимум записейВыводПроцесс не удалось запуститьВывод pylintФайлы PythonРефакторингРезультатыРезультаты хранятся здесь:Результаты дляЗапустить анализЗапустить статический анализ кодаСохранить файл перед его анализомВыбрать файл PythonУстановить максимальное число записей историиНастройкиИсходный код еще не был оценен.Статический анализ кодаОстановитьОстановить текущий анализСледующая опция будет применена при следующем запуске.Предупрежденияпредыдущий запуск:spyder-3.2.6/spyder_pylint/locale/pt_BR/0000775000175000017500000000000013225025007020770 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_pylint/locale/pt_BR/LC_MESSAGES/0000775000175000017500000000000013225025007022555 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_pylint/locale/pt_BR/LC_MESSAGES/pylint.po0000664000175000017500000000770613224121062024443 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # Spyder's brazilian portuguese translation file # Valter Nazianzeno , 2014. # msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: 2017-12-14 15:40+-05\n" "PO-Revision-Date: 2015-02-25 22:08-0400\n" "Last-Translator: Valter Nazianzeno \n" "Language-Team: \n" "Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "X-Generator: Poedit 1.7.4\n" #: spyder_pylint/pylint.py:36 msgid "Settings" msgstr "Configurações" #: spyder_pylint/pylint.py:37 msgid "Save file before analyzing it" msgstr "Salvar arquivo antes de analisá-lo" #: spyder_pylint/pylint.py:40 spyder_pylint/pylint.py:161 msgid "History" msgstr "Histórico" #: spyder_pylint/pylint.py:41 msgid "The following option will be applied at next startup." msgstr "" "A seguinte opção será aplicada na próxima vez que o Spyder for iniciado." #: spyder_pylint/pylint.py:44 msgid "History: " msgstr "Histórico:" #: spyder_pylint/pylint.py:45 msgid " results" msgstr " resultados" #: spyder_pylint/pylint.py:48 msgid "Results" msgstr "Resultados" #: spyder_pylint/pylint.py:49 msgid "Results are stored here:" msgstr "Os resultados são armazenados aqui:" #: spyder_pylint/pylint.py:99 spyder_pylint/widgets/pylintgui.py:52 msgid "Static code analysis" msgstr "Análise de código" #: spyder_pylint/pylint.py:116 msgid "History..." msgstr "Histórico..." #: spyder_pylint/pylint.py:118 msgid "Set history maximum entries" msgstr "Definir número máximo de entradas para o histórico" #: spyder_pylint/pylint.py:134 msgid "Run static code analysis" msgstr "Executar análise de código" #: spyder_pylint/pylint.py:162 msgid "Maximum entries" msgstr "Número máximo de entradas" #: spyder_pylint/widgets/pylintgui.py:86 msgid "Results for " msgstr "Resultados para " #: spyder_pylint/widgets/pylintgui.py:91 msgid "Convention" msgstr "Convention" #: spyder_pylint/widgets/pylintgui.py:93 msgid "Refactor" msgstr "Refatoração" #: spyder_pylint/widgets/pylintgui.py:95 msgid "Warning" msgstr "Aviso" #: spyder_pylint/widgets/pylintgui.py:97 spyder_pylint/widgets/pylintgui.py:318 #: spyder_pylint/widgets/pylintgui.py:346 msgid "Error" msgstr "Erro" #: spyder_pylint/widgets/pylintgui.py:172 msgid "Analyze" msgstr "Analisar" #: spyder_pylint/widgets/pylintgui.py:173 msgid "Run analysis" msgstr "Executar análise" #: spyder_pylint/widgets/pylintgui.py:177 msgid "Stop" msgstr "Parar" #: spyder_pylint/widgets/pylintgui.py:178 msgid "Stop current analysis" msgstr "Parar análise atual" #: spyder_pylint/widgets/pylintgui.py:184 #: spyder_pylint/widgets/pylintgui.py:242 msgid "Select Python file" msgstr "Selecionar arquivo Python" #: spyder_pylint/widgets/pylintgui.py:190 msgid "Output" msgstr "Saída" #: spyder_pylint/widgets/pylintgui.py:192 msgid "Complete output" msgstr "Saída completa" #: spyder_pylint/widgets/pylintgui.py:243 msgid "Python files" msgstr "Arquivos Python" #: spyder_pylint/widgets/pylintgui.py:280 msgid "Pylint output" msgstr "Saída do Pylint" #: spyder_pylint/widgets/pylintgui.py:319 msgid "Process failed to start" msgstr "O processo falhou ao iniciar" #: spyder_pylint/widgets/pylintgui.py:420 msgid "Source code has not been rated yet." msgstr "O código fonte não foi avaliado ainda." #: spyder_pylint/widgets/pylintgui.py:426 msgid "Analysis did not succeed (see output for more details)." msgstr "A análise não foi bem sucedida (veja a saída para mais detalhes)." #: spyder_pylint/widgets/pylintgui.py:439 msgid "Global evaluation:" msgstr "Avaliação global:" #: spyder_pylint/widgets/pylintgui.py:443 msgid "previous run:" msgstr "análise anterior:" #~ msgid "Pylint script was not found. Please add \"%s\" to PATH." #~ msgstr "" #~ "O script do Pylint não foi encontrada. Por favor adicione \"%s\" ao PATH." #~ msgid "Please install pylint:" #~ msgstr "Por favor instale o pylint:" spyder-3.2.6/spyder_pylint/locale/pt_BR/LC_MESSAGES/pylint.mo0000664000175000017500000000451713224121062024435 0ustar carloscarlos00000000000000!$/,7*2 BMSf n y    *H[w#5  Z  {D    ".JQn  $# 15K(L6 <  !     resultsAnalysis did not succeed (see output for more details).AnalyzeComplete outputConventionErrorGlobal evaluation:HistoryHistory...History: Maximum entriesOutputProcess failed to startPylint outputPython filesRefactorResultsResults are stored here:Results for Run analysisRun static code analysisSave file before analyzing itSelect Python fileSet history maximum entriesSettingsSource code has not been rated yet.Static code analysisStopStop current analysisThe following option will be applied at next startup.Warningprevious run:Project-Id-Version: POT-Creation-Date: 2017-07-11 13:28+COT PO-Revision-Date: 2015-02-25 22:08-0400 Last-Translator: Valter Nazianzeno Language-Team: Language: pt_BR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generated-By: pygettext.py 1.5 X-Generator: Poedit 1.7.4 resultadosA análise não foi bem sucedida (veja a saída para mais detalhes).AnalisarSaída completaConventionErroAvaliação global:HistóricoHistórico...Histórico:Número máximo de entradasSaídaO processo falhou ao iniciarSaída do PylintArquivos PythonRefatoraçãoResultadosOs resultados são armazenados aqui:Resultados para Executar análiseExecutar análise de códigoSalvar arquivo antes de analisá-loSelecionar arquivo PythonDefinir número máximo de entradas para o históricoConfiguraçõesO código fonte não foi avaliado ainda.Análise de códigoPararParar análise atualA seguinte opção será aplicada na próxima vez que o Spyder for iniciado.Avisoanálise anterior:spyder-3.2.6/spyder_pylint/locale/ja/0000775000175000017500000000000013225025007020354 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_pylint/locale/ja/LC_MESSAGES/0000775000175000017500000000000013225025007022141 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_pylint/locale/ja/LC_MESSAGES/pylint.po0000664000175000017500000001027313224121062024020 0ustar carloscarlos00000000000000# Japanese translations for Spyder package # Spyder-ide パッケージに対する英訳. # Copyright (C) 2016 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the Spyder package. # Ohnishi Seiki , 2016. # msgid "" msgstr "" "Project-Id-Version: Spyder\n" "POT-Creation-Date: 2017-12-14 15:40+-05\n" "PO-Revision-Date: 2017-04-23 17:21+0900\n" "Last-Translator: sohnishi \n" "Language-Team: Japanese\n" "Language: ja\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Poedit 1.8.11\n" #: spyder_pylint/pylint.py:36 msgid "Settings" msgstr "セッティング" #: spyder_pylint/pylint.py:37 msgid "Save file before analyzing it" msgstr "分析前にファイルを保存" #: spyder_pylint/pylint.py:40 spyder_pylint/pylint.py:161 msgid "History" msgstr "ヒストリ" #: spyder_pylint/pylint.py:41 msgid "The following option will be applied at next startup." msgstr "以下のオプションは次回起動時に適用されます。" #: spyder_pylint/pylint.py:44 msgid "History: " msgstr "ヒストリ:" #: spyder_pylint/pylint.py:45 msgid " results" msgstr "結果" #: spyder_pylint/pylint.py:48 msgid "Results" msgstr "結果" #: spyder_pylint/pylint.py:49 msgid "Results are stored here:" msgstr "結果は以下に保存されます:" #: spyder_pylint/pylint.py:99 spyder_pylint/widgets/pylintgui.py:52 msgid "Static code analysis" msgstr "静的コード分析" #: spyder_pylint/pylint.py:116 msgid "History..." msgstr "ヒストリ..." #: spyder_pylint/pylint.py:118 msgid "Set history maximum entries" msgstr "ヒストリに最大エントリ数を適用" #: spyder_pylint/pylint.py:134 msgid "Run static code analysis" msgstr "静的コード分析を実行" #: spyder_pylint/pylint.py:162 msgid "Maximum entries" msgstr "最大エントリ数" #: spyder_pylint/widgets/pylintgui.py:86 msgid "Results for " msgstr "結果" #: spyder_pylint/widgets/pylintgui.py:91 msgid "Convention" msgstr "規約" #: spyder_pylint/widgets/pylintgui.py:93 msgid "Refactor" msgstr "リファクター" #: spyder_pylint/widgets/pylintgui.py:95 msgid "Warning" msgstr "警告" #: spyder_pylint/widgets/pylintgui.py:97 spyder_pylint/widgets/pylintgui.py:318 #: spyder_pylint/widgets/pylintgui.py:346 msgid "Error" msgstr "エラー" #: spyder_pylint/widgets/pylintgui.py:172 msgid "Analyze" msgstr "分析" #: spyder_pylint/widgets/pylintgui.py:173 msgid "Run analysis" msgstr "分析を実行" #: spyder_pylint/widgets/pylintgui.py:177 msgid "Stop" msgstr "停止" #: spyder_pylint/widgets/pylintgui.py:178 msgid "Stop current analysis" msgstr "現在の分析を停止" #: spyder_pylint/widgets/pylintgui.py:184 #: spyder_pylint/widgets/pylintgui.py:242 msgid "Select Python file" msgstr "Pythonファイルを選択" #: spyder_pylint/widgets/pylintgui.py:190 msgid "Output" msgstr "出力" #: spyder_pylint/widgets/pylintgui.py:192 msgid "Complete output" msgstr "出力を完了" #: spyder_pylint/widgets/pylintgui.py:243 msgid "Python files" msgstr "Pythonファイル" #: spyder_pylint/widgets/pylintgui.py:280 msgid "Pylint output" msgstr "Pylint出力" #: spyder_pylint/widgets/pylintgui.py:319 msgid "Process failed to start" msgstr "プロセスの開始に失敗しました" #: spyder_pylint/widgets/pylintgui.py:420 msgid "Source code has not been rated yet." msgstr "ソースコードはまだ評価されていません。" #: spyder_pylint/widgets/pylintgui.py:426 msgid "Analysis did not succeed (see output for more details)." msgstr "分析に失敗しました(詳細は出力を見てください)" #: spyder_pylint/widgets/pylintgui.py:439 msgid "Global evaluation:" msgstr "全体評価:" #: spyder_pylint/widgets/pylintgui.py:443 msgid "previous run:" msgstr "前回の実行:" #~ msgid "Pylint script was not found. Please add \"%s\" to PATH." #~ msgstr "" #~ "Pylintスクリプトが見つかりいませんでした。\"%s\" をPATHに追加してくださ" #~ "い。" #~ msgid "Please install pylint:" #~ msgstr "pylintを再インストールしてください:" spyder-3.2.6/spyder_pylint/locale/ja/LC_MESSAGES/pylint.mo0000664000175000017500000000457413224121062024024 0ustar carloscarlos00000000000000!$/,7*2 BMSf n y    *H[w#5   A  #0@Pf*m '!0R-n9 B b i  !     resultsAnalysis did not succeed (see output for more details).AnalyzeComplete outputConventionErrorGlobal evaluation:HistoryHistory...History: Maximum entriesOutputProcess failed to startPylint outputPython filesRefactorResultsResults are stored here:Results for Run analysisRun static code analysisSave file before analyzing itSelect Python fileSet history maximum entriesSettingsSource code has not been rated yet.Static code analysisStopStop current analysisThe following option will be applied at next startup.Warningprevious run:Project-Id-Version: Spyder POT-Creation-Date: 2017-07-11 13:28+COT PO-Revision-Date: 2017-04-23 17:21+0900 Last-Translator: sohnishi Language-Team: Japanese Language: ja MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generated-By: pygettext.py 1.5 Plural-Forms: nplurals=1; plural=0; X-Generator: Poedit 1.8.11 結果分析に失敗しました(詳細は出力を見てください)分析出力を完了規約エラー全体評価:ヒストリヒストリ...ヒストリ:最大エントリ数出力プロセスの開始に失敗しましたPylint出力Pythonファイルリファクター結果結果は以下に保存されます:結果分析を実行静的コード分析を実行分析前にファイルを保存Pythonファイルを選択ヒストリに最大エントリ数を適用セッティングソースコードはまだ評価されていません。静的コード分析停止現在の分析を停止以下のオプションは次回起動時に適用されます。警告前回の実行:spyder-3.2.6/spyder_pylint/locale/es/0000775000175000017500000000000013225025007020371 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_pylint/locale/es/LC_MESSAGES/0000775000175000017500000000000013225025007022156 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_pylint/locale/es/LC_MESSAGES/pylint.po0000664000175000017500000000671013224121062024036 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # Spyder Profiler's spanish translation file # Copyright (C) 2011 Spyder Development team # msgid "" msgstr "" "Project-Id-Version: 2.1\n" "POT-Creation-Date: 2017-12-14 15:40+-05\n" "PO-Revision-Date: 2014-05-18 16:44-0500\n" "Last-Translator: Carlos Cordoba \n" "Language-Team: Python\n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "X-Poedit-SourceCharset: utf-8\n" "X-Poedit-Basepath: ../../../../\n" "X-Generator: Poedit 1.5.4\n" #: spyder_pylint/pylint.py:36 msgid "Settings" msgstr "Ajustes" #: spyder_pylint/pylint.py:37 msgid "Save file before analyzing it" msgstr "Guardar archivo antes de analizarlo" #: spyder_pylint/pylint.py:40 spyder_pylint/pylint.py:161 msgid "History" msgstr "Historial" #: spyder_pylint/pylint.py:41 msgid "The following option will be applied at next startup." msgstr "La siguiente opción será aplicada la próxima vez que se inicie Spyder" #: spyder_pylint/pylint.py:44 msgid "History: " msgstr "Guardar" #: spyder_pylint/pylint.py:45 msgid " results" msgstr " resultados" #: spyder_pylint/pylint.py:48 msgid "Results" msgstr "Resultados" #: spyder_pylint/pylint.py:49 msgid "Results are stored here:" msgstr "Los resultados se guardan en:" #: spyder_pylint/pylint.py:99 spyder_pylint/widgets/pylintgui.py:52 msgid "Static code analysis" msgstr "Análisis estático del código" #: spyder_pylint/pylint.py:116 msgid "History..." msgstr "" #: spyder_pylint/pylint.py:118 msgid "Set history maximum entries" msgstr "" #: spyder_pylint/pylint.py:134 msgid "Run static code analysis" msgstr "Realizar análisis estático del código" #: spyder_pylint/pylint.py:162 msgid "Maximum entries" msgstr "" #: spyder_pylint/widgets/pylintgui.py:86 msgid "Results for " msgstr "" #: spyder_pylint/widgets/pylintgui.py:91 msgid "Convention" msgstr "" #: spyder_pylint/widgets/pylintgui.py:93 msgid "Refactor" msgstr "" #: spyder_pylint/widgets/pylintgui.py:95 msgid "Warning" msgstr "" #: spyder_pylint/widgets/pylintgui.py:97 spyder_pylint/widgets/pylintgui.py:318 #: spyder_pylint/widgets/pylintgui.py:346 msgid "Error" msgstr "" #: spyder_pylint/widgets/pylintgui.py:172 msgid "Analyze" msgstr "" #: spyder_pylint/widgets/pylintgui.py:173 msgid "Run analysis" msgstr "" #: spyder_pylint/widgets/pylintgui.py:177 msgid "Stop" msgstr "" #: spyder_pylint/widgets/pylintgui.py:178 msgid "Stop current analysis" msgstr "" #: spyder_pylint/widgets/pylintgui.py:184 #: spyder_pylint/widgets/pylintgui.py:242 msgid "Select Python file" msgstr "" #: spyder_pylint/widgets/pylintgui.py:190 msgid "Output" msgstr "" #: spyder_pylint/widgets/pylintgui.py:192 msgid "Complete output" msgstr "" #: spyder_pylint/widgets/pylintgui.py:243 msgid "Python files" msgstr "" #: spyder_pylint/widgets/pylintgui.py:280 msgid "Pylint output" msgstr "" #: spyder_pylint/widgets/pylintgui.py:319 msgid "Process failed to start" msgstr "" #: spyder_pylint/widgets/pylintgui.py:420 msgid "Source code has not been rated yet." msgstr "" #: spyder_pylint/widgets/pylintgui.py:426 msgid "Analysis did not succeed (see output for more details)." msgstr "" #: spyder_pylint/widgets/pylintgui.py:439 msgid "Global evaluation:" msgstr "" #: spyder_pylint/widgets/pylintgui.py:443 msgid "previous run:" msgstr "" #~ msgid "Pylint" #~ msgstr "Análisis del código" #~ msgid "Run pylint code analysis" #~ msgstr "Realizar un análisis del código" spyder-3.2.6/spyder_pylint/locale/es/LC_MESSAGES/pylint.mo0000664000175000017500000000216113224121062024027 0ustar carloscarlos00000000000000 t ",4Mf5 l x (#H(    resultsHistoryHistory: ResultsResults are stored here:Run static code analysisSave file before analyzing itSettingsStatic code analysisThe following option will be applied at next startup.Project-Id-Version: 2.1 POT-Creation-Date: 2017-07-11 13:28+COT PO-Revision-Date: 2014-05-18 16:44-0500 Last-Translator: Carlos Cordoba Language-Team: Python Language: es MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generated-By: pygettext.py 1.5 X-Poedit-SourceCharset: utf-8 X-Poedit-Basepath: ../../../../ X-Generator: Poedit 1.5.4 resultadosHistorialGuardarResultadosLos resultados se guardan en:Realizar análisis estático del códigoGuardar archivo antes de analizarloAjustesAnálisis estático del códigoLa siguiente opción será aplicada la próxima vez que se inicie Spyderspyder-3.2.6/spyder_pylint/locale/pylint.pot0000664000175000017500000000573113224121062022030 0ustar carloscarlos00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR ORGANIZATION # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2017-12-14 15:40+-05\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: ENCODING\n" "Generated-By: pygettext.py 1.5\n" #: spyder_pylint/pylint.py:36 msgid "Settings" msgstr "" #: spyder_pylint/pylint.py:37 msgid "Save file before analyzing it" msgstr "" #: spyder_pylint/pylint.py:40 spyder_pylint/pylint.py:161 msgid "History" msgstr "" #: spyder_pylint/pylint.py:41 msgid "The following option will be applied at next startup." msgstr "" #: spyder_pylint/pylint.py:44 msgid "History: " msgstr "" #: spyder_pylint/pylint.py:45 msgid " results" msgstr "" #: spyder_pylint/pylint.py:48 msgid "Results" msgstr "" #: spyder_pylint/pylint.py:49 msgid "Results are stored here:" msgstr "" #: spyder_pylint/pylint.py:99 spyder_pylint/widgets/pylintgui.py:52 msgid "Static code analysis" msgstr "" #: spyder_pylint/pylint.py:116 msgid "History..." msgstr "" #: spyder_pylint/pylint.py:118 msgid "Set history maximum entries" msgstr "" #: spyder_pylint/pylint.py:134 msgid "Run static code analysis" msgstr "" #: spyder_pylint/pylint.py:162 msgid "Maximum entries" msgstr "" #: spyder_pylint/widgets/pylintgui.py:86 msgid "Results for " msgstr "" #: spyder_pylint/widgets/pylintgui.py:91 msgid "Convention" msgstr "" #: spyder_pylint/widgets/pylintgui.py:93 msgid "Refactor" msgstr "" #: spyder_pylint/widgets/pylintgui.py:95 msgid "Warning" msgstr "" #: spyder_pylint/widgets/pylintgui.py:97 #: spyder_pylint/widgets/pylintgui.py:318 #: spyder_pylint/widgets/pylintgui.py:346 msgid "Error" msgstr "" #: spyder_pylint/widgets/pylintgui.py:172 msgid "Analyze" msgstr "" #: spyder_pylint/widgets/pylintgui.py:173 msgid "Run analysis" msgstr "" #: spyder_pylint/widgets/pylintgui.py:177 msgid "Stop" msgstr "" #: spyder_pylint/widgets/pylintgui.py:178 msgid "Stop current analysis" msgstr "" #: spyder_pylint/widgets/pylintgui.py:184 #: spyder_pylint/widgets/pylintgui.py:242 msgid "Select Python file" msgstr "" #: spyder_pylint/widgets/pylintgui.py:190 msgid "Output" msgstr "" #: spyder_pylint/widgets/pylintgui.py:192 msgid "Complete output" msgstr "" #: spyder_pylint/widgets/pylintgui.py:243 msgid "Python files" msgstr "" #: spyder_pylint/widgets/pylintgui.py:280 msgid "Pylint output" msgstr "" #: spyder_pylint/widgets/pylintgui.py:319 msgid "Process failed to start" msgstr "" #: spyder_pylint/widgets/pylintgui.py:420 msgid "Source code has not been rated yet." msgstr "" #: spyder_pylint/widgets/pylintgui.py:426 msgid "Analysis did not succeed (see output for more details)." msgstr "" #: spyder_pylint/widgets/pylintgui.py:439 msgid "Global evaluation:" msgstr "" #: spyder_pylint/widgets/pylintgui.py:443 msgid "previous run:" msgstr "" spyder-3.2.6/spyder_pylint/locale/fr/0000775000175000017500000000000013225025007020371 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_pylint/locale/fr/LC_MESSAGES/0000775000175000017500000000000013225025007022156 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_pylint/locale/fr/LC_MESSAGES/pylint.po0000664000175000017500000001002613224121062024031 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # Spyder Pylint plugin's french translation file # Copyright (C) 2009-2011 Pierre Raybaut # msgid "" msgstr "" "Project-Id-Version: 2.1\n" "POT-Creation-Date: 2017-12-14 15:40+-05\n" "PO-Revision-Date: 2011-04-11 21:41+2\n" "Last-Translator: Pierre Raybaut\n" "Language-Team: Python\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: utf-8\n" "Generated-By: pygettext.py 1.5\n" #: spyder_pylint/pylint.py:36 msgid "Settings" msgstr "Options" #: spyder_pylint/pylint.py:37 msgid "Save file before analyzing it" msgstr "Enregistrer le fichier avant de l'analyser" #: spyder_pylint/pylint.py:40 spyder_pylint/pylint.py:161 msgid "History" msgstr "Historique" #: spyder_pylint/pylint.py:41 msgid "The following option will be applied at next startup." msgstr "L'option suivante ne sera appliquée qu'au prochain démarrage." #: spyder_pylint/pylint.py:44 msgid "History: " msgstr "Historique : " #: spyder_pylint/pylint.py:45 msgid " results" msgstr " résultats" #: spyder_pylint/pylint.py:48 msgid "Results" msgstr "Résultats" #: spyder_pylint/pylint.py:49 msgid "Results are stored here:" msgstr "Les résultats sont stockés ici :" #: spyder_pylint/pylint.py:99 spyder_pylint/widgets/pylintgui.py:52 msgid "Static code analysis" msgstr "Analyse de code statique" #: spyder_pylint/pylint.py:116 msgid "History..." msgstr "Historique..." #: spyder_pylint/pylint.py:118 msgid "Set history maximum entries" msgstr "Modifier le nombre d'entrées maximum de l'historique" #: spyder_pylint/pylint.py:134 msgid "Run static code analysis" msgstr "Démarrer l'analyse de code statique" #: spyder_pylint/pylint.py:162 msgid "Maximum entries" msgstr "Nombre maximum d'entrées" #: spyder_pylint/widgets/pylintgui.py:86 msgid "Results for " msgstr "Résultats pour " #: spyder_pylint/widgets/pylintgui.py:91 msgid "Convention" msgstr "Convention" #: spyder_pylint/widgets/pylintgui.py:93 msgid "Refactor" msgstr "Factorisation" #: spyder_pylint/widgets/pylintgui.py:95 msgid "Warning" msgstr "Avertissement" #: spyder_pylint/widgets/pylintgui.py:97 spyder_pylint/widgets/pylintgui.py:318 #: spyder_pylint/widgets/pylintgui.py:346 msgid "Error" msgstr "Erreur" #: spyder_pylint/widgets/pylintgui.py:172 msgid "Analyze" msgstr "Analyser" #: spyder_pylint/widgets/pylintgui.py:173 msgid "Run analysis" msgstr "Analyser le code source" #: spyder_pylint/widgets/pylintgui.py:177 msgid "Stop" msgstr "Arrêter" #: spyder_pylint/widgets/pylintgui.py:178 msgid "Stop current analysis" msgstr "Arrêter l'analyse en cours" #: spyder_pylint/widgets/pylintgui.py:184 #: spyder_pylint/widgets/pylintgui.py:242 msgid "Select Python file" msgstr "Sélectionner un fichier Python" #: spyder_pylint/widgets/pylintgui.py:190 msgid "Output" msgstr "Sortie" #: spyder_pylint/widgets/pylintgui.py:192 msgid "Complete output" msgstr "Sortie complète" #: spyder_pylint/widgets/pylintgui.py:243 msgid "Python files" msgstr "Fichiers Python" #: spyder_pylint/widgets/pylintgui.py:280 msgid "Pylint output" msgstr "Analyse Pylint" #: spyder_pylint/widgets/pylintgui.py:319 msgid "Process failed to start" msgstr "Le processus n'a pas pu démarrer" #: spyder_pylint/widgets/pylintgui.py:420 msgid "Source code has not been rated yet." msgstr "Le code source n'a pas encore été analysé." #: spyder_pylint/widgets/pylintgui.py:426 msgid "Analysis did not succeed (see output for more details)." msgstr "L'analyse n'a pas réussi (voir la sortie pour plus de détails)." #: spyder_pylint/widgets/pylintgui.py:439 msgid "Global evaluation:" msgstr "Évaluation globale :" #: spyder_pylint/widgets/pylintgui.py:443 msgid "previous run:" msgstr "analyse précédente :" #~ msgid "Pylint script was not found. Please add \"%s\" to PATH." #~ msgstr "Le script pylint est introuvable. Merci d'ajouter \"%s\" au PATH." #~ msgid "Please install pylint:" #~ msgstr "Merci d'installer au préalable pylint :" #~ msgid "Pylint" #~ msgstr "Pylint" #~ msgid "Run pylint code analysis" #~ msgstr "Analyser le code source avec pylint" spyder-3.2.6/spyder_pylint/locale/fr/LC_MESSAGES/pylint.mo0000664000175000017500000000447613224121062024042 0ustar carloscarlos00000000000000!$/,7*2 BMSf n y    *H[w#5     AAM    !;J Z h"s$*5/e-m?  '  !     resultsAnalysis did not succeed (see output for more details).AnalyzeComplete outputConventionErrorGlobal evaluation:HistoryHistory...History: Maximum entriesOutputProcess failed to startPylint outputPython filesRefactorResultsResults are stored here:Results for Run analysisRun static code analysisSave file before analyzing itSelect Python fileSet history maximum entriesSettingsSource code has not been rated yet.Static code analysisStopStop current analysisThe following option will be applied at next startup.Warningprevious run:Project-Id-Version: 2.1 POT-Creation-Date: 2017-07-11 13:28+COT PO-Revision-Date: 2011-04-11 21:41+2 Last-Translator: Pierre Raybaut Language-Team: Python Language: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: utf-8 Generated-By: pygettext.py 1.5 résultatsL'analyse n'a pas réussi (voir la sortie pour plus de détails).AnalyserSortie complèteConventionErreurÉvaluation globale :HistoriqueHistorique...Historique : Nombre maximum d'entréesSortieLe processus n'a pas pu démarrerAnalyse PylintFichiers PythonFactorisationRésultatsLes résultats sont stockés ici :Résultats pour Analyser le code sourceDémarrer l'analyse de code statiqueEnregistrer le fichier avant de l'analyserSélectionner un fichier PythonModifier le nombre d'entrées maximum de l'historiqueOptionsLe code source n'a pas encore été analysé.Analyse de code statiqueArrêterArrêter l'analyse en coursL'option suivante ne sera appliquée qu'au prochain démarrage.Avertissementanalyse précédente :spyder-3.2.6/spyder_pylint/images/0000775000175000017500000000000013225025007017770 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_pylint/images/pylint.png0000664000175000017500000000225413003520703022015 0ustar carloscarlos00000000000000PNG  IHDRw= cHRMz&u0`:pQ<bKGD5IDAT}P/oGL4ÀˈzH%&/^,^De( n`1ln}NENʱ؁Z_~`~==ĤV^A/pc%_dOu?#/G_u]ĦJKII=6""#x#q )hˉ7΢rB؜5(m? zPvAAiMDHDc;nc9WS,dBglZ݋l9Dr;`􈍻U-^Jh_L;7oPَd.włr[.ڗ.s]}t3:bf0yTӞڑUþp+YhȒq(eI|7wj2| S#P'n֙,Av'۶zS,vJqd,|qtO*qs4=.*Nikz+ð h UOmΥ'y%c4b0uhlL-EI{Qu8;F"z8G9i$oXerݓ2zУmr-WPŜA9s%]X&/DEFfЬXQQF9NZp(/z+*Wk8ҥu,9:w2BnVBfVC/?zN4lniTE,Q|fwoj# M :|4i62^qZ4nhZ垢YZZ665b@j@qAT 44\Dpp&|>[\祀Pj3Ceew;4_dkCVv="Rk븊(@Wi\țh/rX)4 341YM䔔 B/5bJZN؆QQa:%Rgz<xwUjMo46s&&&_V3,++E@vH)RIENDB`spyder-3.2.6/spyder_pylint/widgets/0000775000175000017500000000000013225025007020171 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_pylint/widgets/pylintgui.py0000664000175000017500000004344013224740762022607 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Pylint widget""" # pylint: disable=C0103 # pylint: disable=R0903 # pylint: disable=R0911 # pylint: disable=R0201 # Standard library imports from __future__ import print_function, with_statement import os.path as osp import re import sys import time # Third party imports import pylint from qtpy.compat import getopenfilename from qtpy.QtCore import QByteArray, QProcess, QTextCodec, Signal, Slot from qtpy.QtWidgets import (QHBoxLayout, QLabel, QMessageBox, QTreeWidgetItem, QVBoxLayout, QWidget) # Local imports from spyder import dependencies from spyder.config.base import get_conf_path, get_translation from spyder.py3compat import pickle, to_text_string from spyder.utils import icon_manager as ima from spyder.utils.encoding import to_unicode_from_fs from spyder.utils.qthelpers import create_toolbutton from spyder.utils.misc import getcwd_or_home from spyder.widgets.comboboxes import (is_module_or_package, PythonModulesComboBox) from spyder.widgets.onecolumntree import OneColumnTree from spyder.widgets.variableexplorer.texteditor import TextEditor # This is needed for testing this module as a stand alone script try: _ = get_translation("pylint", "spyder_pylint") except KeyError as error: import gettext _ = gettext.gettext locale_codec = QTextCodec.codecForLocale() PYLINT_REQVER = '>=0.25' PYLINT_VER = pylint.__version__ dependencies.add("pylint", _("Static code analysis"), required_version=PYLINT_REQVER, installed_version=PYLINT_VER) #TODO: display results on 3 columns instead of 1: msg_id, lineno, message class ResultsTree(OneColumnTree): def __init__(self, parent): OneColumnTree.__init__(self, parent) self.filename = None self.results = None self.data = None self.set_title('') def activated(self, item): """Double-click event""" data = self.data.get(id(item)) if data is not None: fname, lineno = data self.parent().edit_goto.emit(fname, lineno, '') def clicked(self, item): """Click event""" self.activated(item) def clear_results(self): self.clear() self.set_title('') def set_results(self, filename, results): self.filename = filename self.results = results self.refresh() def refresh(self): title = _('Results for ')+self.filename self.set_title(title) self.clear() self.data = {} # Populating tree results = ((_('Convention'), ima.icon('convention'), self.results['C:']), (_('Refactor'), ima.icon('refactor'), self.results['R:']), (_('Warning'), ima.icon('warning'), self.results['W:']), (_('Error'), ima.icon('error'), self.results['E:'])) for title, icon, messages in results: title += ' (%d message%s)' % (len(messages), 's' if len(messages)>1 else '') title_item = QTreeWidgetItem(self, [title], QTreeWidgetItem.Type) title_item.setIcon(0, icon) if not messages: title_item.setDisabled(True) modules = {} for module, lineno, message, msg_id in messages: basename = osp.splitext(osp.basename(self.filename))[0] if not module.startswith(basename): # Pylint bug i_base = module.find(basename) module = module[i_base:] dirname = osp.dirname(self.filename) if module.startswith('.') or module == basename: modname = osp.join(dirname, module) else: modname = osp.join(dirname, *module.split('.')) if osp.isdir(modname): modname = osp.join(modname, '__init__') for ext in ('.py', '.pyw'): if osp.isfile(modname+ext): modname = modname + ext break if osp.isdir(self.filename): parent = modules.get(modname) if parent is None: item = QTreeWidgetItem(title_item, [module], QTreeWidgetItem.Type) item.setIcon(0, ima.icon('python')) modules[modname] = item parent = item else: parent = title_item if len(msg_id) > 1: text = "[%s] %d : %s" % (msg_id, lineno, message) else: text = "%d : %s" % (lineno, message) msg_item = QTreeWidgetItem(parent, [text], QTreeWidgetItem.Type) msg_item.setIcon(0, ima.icon('arrow')) self.data[id(msg_item)] = (modname, lineno) class PylintWidget(QWidget): """ Pylint widget """ DATAPATH = get_conf_path('pylint.results') VERSION = '1.1.0' redirect_stdio = Signal(bool) def __init__(self, parent, max_entries=100): QWidget.__init__(self, parent) self.setWindowTitle("Pylint") self.output = None self.error_output = None self.max_entries = max_entries self.rdata = [] if osp.isfile(self.DATAPATH): try: data = pickle.loads(open(self.DATAPATH, 'rb').read()) if data[0] == self.VERSION: self.rdata = data[1:] except (EOFError, ImportError): pass self.filecombo = PythonModulesComboBox(self) self.start_button = create_toolbutton(self, icon=ima.icon('run'), text=_("Analyze"), tip=_("Run analysis"), triggered=self.start, text_beside_icon=True) self.stop_button = create_toolbutton(self, icon=ima.icon('stop'), text=_("Stop"), tip=_("Stop current analysis"), text_beside_icon=True) self.filecombo.valid.connect(self.start_button.setEnabled) self.filecombo.valid.connect(self.show_data) browse_button = create_toolbutton(self, icon=ima.icon('fileopen'), tip=_('Select Python file'), triggered=self.select_file) self.ratelabel = QLabel() self.datelabel = QLabel() self.log_button = create_toolbutton(self, icon=ima.icon('log'), text=_("Output"), text_beside_icon=True, tip=_("Complete 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) self.show_data() if self.rdata: self.remove_obsolete_items() self.filecombo.addItems(self.get_filenames()) else: self.start_button.setEnabled(False) def analyze(self, filename): filename = to_text_string(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(self.filecombo.findText(filename)) self.filecombo.selected() if self.filecombo.is_valid(): self.start() @Slot() def select_file(self): self.redirect_stdio.emit(False) filename, _selfilter = getopenfilename( self, _("Select Python file"), getcwd_or_home(), _("Python files")+" (*.py ; *.pyw)") self.redirect_stdio.emit(True) if filename: self.analyze(filename) def remove_obsolete_items(self): """Removing obsolete items""" self.rdata = [(filename, data) for filename, data in self.rdata if is_module_or_package(filename)] def get_filenames(self): return [filename for filename, _data in self.rdata] def get_data(self, filename): filename = osp.abspath(filename) for index, (fname, data) in enumerate(self.rdata): 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.rdata.pop(index) self.rdata.insert(0, (filename, data)) self.save() def save(self): while len(self.rdata) > self.max_entries: self.rdata.pop(-1) pickle.dump([self.VERSION]+self.rdata, open(self.DATAPATH, 'wb'), 2) @Slot() def show_log(self): if self.output: TextEditor(self.output, title=_("Pylint output"), readonly=True, size=(700, 500)).exec_() @Slot() 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: p_args = ['-m', 'pylint', '--output-format=text'] 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(sys.executable, p_args) running = self.process.waitForStarted() self.set_running_state(running) if not running: QMessageBox.critical(self, _("Error"), _("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) qba = QByteArray() while self.process.bytesAvailable(): if error: qba += self.process.readAllStandardError() else: qba += self.process.readAllStandardOutput() text = to_text_string( locale_codec.toUnicode(qba.data()) ) if error: self.error_output += text else: self.output += text def finished(self, exit_code, exit_status): self.set_running_state(False) if not self.output: if self.error_output: QMessageBox.critical(self, _("Error"), self.error_output) print("pylint error:\n\n" + self.error_output, file=sys.stderr) 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 # Supporting option include-ids: ('R3873:' instead of 'R:') if not re.match('^[CRWE]+([0-9]{4})?:', line): continue i1 = line.find(':') if i1 == -1: continue msg_id = line[:i1] 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.split(',')[0]) message = line[i2+1:] item = (module, line_nb, message, msg_id) results[line[0]+':'].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 = to_text_string(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 = to_text_string(self.filecombo.currentText()) if not filename: return _index, data = self.get_data(filename) if data is None: text = _('Source code has not been rated yet.') self.treewidget.clear_results() date_text = '' else: datetime, rate, previous_rate, results = data if rate is None: text = _('Analysis did not succeed ' '(see output for more details).') self.treewidget.clear_results() date_text = '' else: text_style = "%s " rate_style = "%s" prevrate_style = "%s" color = "#FF0000" if float(rate) > 5.: color = "#22AA22" elif float(rate) > 3.: color = "#EE5500" text = _('Global evaluation:') text = (text_style % text)+(rate_style % (color, ('%s/10' % rate))) if previous_rate: text_prun = _('previous run:') text_prun = ' (%s %s/10)' % (text_prun, previous_rate) text += prevrate_style % text_prun self.treewidget.set_results(filename, results) date = to_text_string(time.strftime("%d %b %Y %H:%M", datetime), encoding='utf8') date_text = text_style % date self.ratelabel.setText(text) self.datelabel.setText(date_text) #============================================================================== # Tests #============================================================================== def test(): """Run pylint widget test""" from spyder.utils.qthelpers import qapplication app = qapplication(test_time=20) widget = PylintWidget(None) widget.resize(640, 480) widget.show() widget.analyze(__file__) sys.exit(app.exec_()) if __name__ == '__main__': test() spyder-3.2.6/spyder_pylint/widgets/__init__.py0000664000175000017500000000000013003520703022265 0ustar carloscarlos00000000000000spyder-3.2.6/spyder_pylint/__init__.py0000664000175000017500000000045513003520703020635 0ustar carloscarlos00000000000000# -*- coding: utf-8 -*- #============================================================================== # The following statement is required to register this 3rd party plugin: #============================================================================== from .pylint import Pylint as PLUGIN_CLASS spyder-3.2.6/spyder_pylint/pylint.py0000664000175000017500000001541613224740762020436 0ustar carloscarlos00000000000000# -*- coding:utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """Pylint Code Analysis Plugin.""" # pylint: disable=C0103 # pylint: disable=R0903 # pylint: disable=R0911 # pylint: disable=R0201 # Standard library imports import os.path as osp # Third party imports from qtpy.QtCore import Qt, Signal, Slot from qtpy.QtWidgets import QGroupBox, QInputDialog, QLabel, QVBoxLayout # Local imports from spyder.config.base import get_translation from spyder.plugins import SpyderPluginMixin from spyder.plugins.configdialog import PluginConfigPage from spyder.utils import icon_manager as ima from spyder.utils.programs import is_module_installed from spyder.utils.qthelpers import create_action, MENU_SEPARATOR from .widgets.pylintgui import PylintWidget _ = get_translation("pylint", "spyder_pylint") class PylintConfigPage(PluginConfigPage): def setup_page(self): settings_group = QGroupBox(_("Settings")) save_box = self.create_checkbox(_("Save file before analyzing it"), 'save_before', default=True) hist_group = QGroupBox(_("History")) hist_label1 = QLabel(_("The following option will be applied at next " "startup.")) hist_label1.setWordWrap(True) hist_spin = self.create_spinbox(_("History: "), _(" results"), 'max_entries', default=50, min_=10, max_=1000000, step=10) results_group = QGroupBox(_("Results")) results_label1 = QLabel(_("Results are stored here:")) results_label1.setWordWrap(True) # Warning: do not try to regroup the following QLabel contents with # widgets above -- this string was isolated here in a single QLabel # on purpose: to fix Issue 863 results_label2 = QLabel(PylintWidget.DATAPATH) results_label2.setTextInteractionFlags(Qt.TextSelectableByMouse) results_label2.setWordWrap(True) settings_layout = QVBoxLayout() settings_layout.addWidget(save_box) settings_group.setLayout(settings_layout) hist_layout = QVBoxLayout() hist_layout.addWidget(hist_label1) hist_layout.addWidget(hist_spin) hist_group.setLayout(hist_layout) results_layout = QVBoxLayout() results_layout.addWidget(results_label1) results_layout.addWidget(results_label2) results_group.setLayout(results_layout) vlayout = QVBoxLayout() vlayout.addWidget(settings_group) vlayout.addWidget(hist_group) vlayout.addWidget(results_group) vlayout.addStretch(1) self.setLayout(vlayout) class Pylint(PylintWidget, SpyderPluginMixin): """Python source code analysis based on pylint""" CONF_SECTION = 'pylint' CONFIGWIDGET_CLASS = PylintConfigPage edit_goto = Signal(str, int, str) def __init__(self, parent=None): PylintWidget.__init__(self, parent=parent, max_entries=self.get_option('max_entries', 50)) SpyderPluginMixin.__init__(self, parent) # Initialize plugin self.initialize_plugin() #------ SpyderPluginWidget API -------------------------------------------- def get_plugin_title(self): """Return widget title""" return _("Static code analysis") def get_plugin_icon(self): """Return widget icon""" path = osp.join(self.PLUGIN_PATH, self.IMG_PATH) return ima.icon('pylint', icon_path=path) def get_focus_widget(self): """ Return the widget to give focus to when this plugin's dockwidget is raised on top-level """ return self.treewidget def get_plugin_actions(self): """Return a list of actions related to plugin""" # Font history_action = create_action(self, _("History..."), None, ima.icon('history'), _("Set history maximum entries"), triggered=self.change_history_depth) self.treewidget.common_actions += (None, history_action) return [] def on_first_registration(self): """Action to be performed on first plugin registration""" self.main.tabify_plugins(self.main.help, self) self.dockwidget.hide() def register_plugin(self): """Register plugin in Spyder's main window""" self.edit_goto.connect(self.main.editor.load) self.redirect_stdio.connect(self.main.redirect_internalshell_stdio) self.main.add_dockwidget(self) pylint_act = create_action(self, _("Run static code analysis"), triggered=self.run_pylint) pylint_act.setEnabled(is_module_installed('pylint')) self.register_shortcut(pylint_act, context="Pylint", name="Run analysis") self.main.source_menu_actions += [MENU_SEPARATOR, pylint_act] self.main.editor.pythonfile_dependent_actions += [pylint_act] def refresh_plugin(self): """Refresh pylint widget""" self.remove_obsolete_items() def closing_plugin(self, cancelable=False): """Perform actions before parent main window is closed""" return True def apply_plugin_settings(self, options): """Apply configuration file's plugin settings""" # The history depth option will be applied at # next Spyder startup, which is soon enough pass #------ Public API -------------------------------------------------------- @Slot() def change_history_depth(self): "Change history max entries""" depth, valid = QInputDialog.getInt(self, _('History'), _('Maximum entries'), self.get_option('max_entries'), 10, 10000) if valid: self.set_option('max_entries', depth) @Slot() def run_pylint(self): """Run pylint code analysis""" if self.get_option('save_before', True)\ and not self.main.editor.save(): return self.analyze( self.main.editor.get_current_filename() ) def analyze(self, filename): """Reimplement analyze method""" if self.dockwidget and not self.ismaximized: self.dockwidget.setVisible(True) self.dockwidget.setFocus() self.dockwidget.raise_() PylintWidget.analyze(self, filename) spyder-3.2.6/spyder_io_dcm/0000775000175000017500000000000013225025007016436 5ustar carloscarlos00000000000000spyder-3.2.6/spyder_io_dcm/dcm.py0000664000175000017500000000134413003520703017552 0ustar carloscarlos00000000000000# -*- coding:utf-8 -*- """Example of I/O plugin for loading DICOM files""" import os.path as osp try: try: # pydicom 0.9 import dicom as dicomio except ImportError: # pydicom 1.0 from pydicom import dicomio def load_dicom(filename): try: name = osp.splitext(osp.basename(filename))[0] try: data = dicomio.read_file(filename, force=True) except TypeError: data = dicomio.read_file(filename) arr = data.pixel_array return {name: arr}, None except Exception as error: return None, str(error) except ImportError: load_dicom = None spyder-3.2.6/spyder_io_dcm/__init__.py0000664000175000017500000000053713003520703020551 0ustar carloscarlos00000000000000# ============================================================================= # The following statements are required to register this I/O plugin: # ============================================================================= from .dcm import load_dicom FORMAT_NAME = "DICOM images" FORMAT_EXT = ".dcm" FORMAT_LOAD = load_dicom FORMAT_SAVE = None