[spyder] 02/08: Imported Upstream version 2.3.0~beta3+dfsg
Frédéric-Emmanuel Picca
picca at moszumanska.debian.org
Thu Apr 10 21:06:28 UTC 2014
This is an automated email from the git hooks/post-receive script.
picca pushed a commit to branch experimental
in repository spyder.
commit 036378918c92c1fd9c18c4a736b40acbf484466e
Author: Picca Frédéric-Emmanuel <picca at debian.org>
Date: Sat Feb 1 07:45:40 2014 +0100
Imported Upstream version 2.3.0~beta3+dfsg
---
PKG-INFO | 4 +-
setup.py | 5 +-
spyderlib/__init__.py | 2 +-
spyderlib/locale/fr/LC_MESSAGES/spyderlib.mo | Bin 85312 -> 85560 bytes
spyderlib/locale/fr/LC_MESSAGES/spyderlib.po | 564 +++++++++++----------
spyderlib/locale/spyderlib.pot | 503 +++++++++---------
spyderlib/plugins/__init__.py | 26 +-
spyderlib/plugins/externalconsole.py | 19 +-
spyderlib/plugins/inspector.py | 18 +-
spyderlib/plugins/ipythonconsole.py | 10 +-
spyderlib/spyder.py | 297 +++++++----
spyderlib/utils/inspector/static/css/default.css | 4 -
spyderlib/utils/introspection/__init__.py | 11 +
spyderlib/utils/introspection/base.py | 453 +++++++++++++++++
.../utils/{ => introspection}/module_completion.py | 0
spyderlib/utils/introspection/rope_plugin.py | 241 +++++++++
spyderlib/utils/programs.py | 4 +
spyderlib/utils/qthelpers.py | 2 +-
spyderlib/utils/sourcecode.py | 72 +++
spyderlib/widgets/calltip.py | 82 ++-
spyderlib/widgets/dependencies.py | 1 +
spyderlib/widgets/editor.py | 141 ++++--
spyderlib/widgets/externalshell/monitor.py | 2 +-
spyderlib/widgets/externalshell/pythonshell.py | 4 +-
spyderlib/widgets/findreplace.py | 2 +-
spyderlib/widgets/ipython.py | 25 +-
spyderlib/widgets/mixins.py | 35 +-
spyderlib/widgets/sourcecode/base.py | 6 +-
spyderlib/widgets/sourcecode/codeeditor.py | 360 +++++--------
spyderplugins/p_pylint.py | 8 +-
spyderplugins/widgets/pylintgui.py | 8 +-
31 files changed, 1877 insertions(+), 1032 deletions(-)
diff --git a/PKG-INFO b/PKG-INFO
index f930a7b..80dc915 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,12 +1,12 @@
Metadata-Version: 1.1
Name: spyder
-Version: 2.3.0beta2
+Version: 2.3.0beta3
Summary: Scientific PYthon Development EnviRonment
Home-page: http://code.google.com/p/spyderlib
Author: Pierre Raybaut
Author-email: UNKNOWN
License: MIT
-Download-URL: http://code.google.com/p/spyderlib/files/spyder-2.3.0beta2.zip
+Download-URL: http://code.google.com/p/spyderlib/files/spyder-2.3.0beta3.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 PyQt4 or
diff --git a/setup.py b/setup.py
index dcbe881..e3efe5a 100644
--- a/setup.py
+++ b/setup.py
@@ -34,7 +34,7 @@ if 'USE_SETUPTOOLS' in os.environ or 'pip' in __file__:
except:
with_setuptools = False
-if with_setuptools is False:
+if not with_setuptools:
from distutils.command.install import install # analysis:ignore
@@ -128,6 +128,9 @@ try:
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, 'spyderlib', '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"
diff --git a/spyderlib/__init__.py b/spyderlib/__init__.py
index d1ff089..bd7a029 100644
--- a/spyderlib/__init__.py
+++ b/spyderlib/__init__.py
@@ -27,7 +27,7 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
"""
-__version__ = '2.3.0beta2'
+__version__ = '2.3.0beta3'
__license__ = __doc__
__project_url__ = 'http://code.google.com/p/spyderlib'
__forum_url__ = 'http://groups.google.com/group/spyderlib'
diff --git a/spyderlib/locale/fr/LC_MESSAGES/spyderlib.mo b/spyderlib/locale/fr/LC_MESSAGES/spyderlib.mo
index aa1c63b..f974d65 100644
Binary files a/spyderlib/locale/fr/LC_MESSAGES/spyderlib.mo and b/spyderlib/locale/fr/LC_MESSAGES/spyderlib.mo differ
diff --git a/spyderlib/locale/fr/LC_MESSAGES/spyderlib.po b/spyderlib/locale/fr/LC_MESSAGES/spyderlib.po
index 11a5ec5..ca89ccc 100644
--- a/spyderlib/locale/fr/LC_MESSAGES/spyderlib.po
+++ b/spyderlib/locale/fr/LC_MESSAGES/spyderlib.po
@@ -5,7 +5,7 @@
msgid ""
msgstr ""
"Project-Id-Version: 2.1\n"
-"POT-Creation-Date: 2013-11-09 14:09+Paris, Madrid\n"
+"POT-Creation-Date: 2014-01-04 15:22+Paris, Madrid\n"
"PO-Revision-Date: 2011-04-11 21:41+2\n"
"Last-Translator: Pierre Raybaut\n"
"Language-Team: Python\n"
@@ -223,7 +223,7 @@ msgid "Background:"
msgstr "Fond :"
#: spyderlib\plugins\configdialog.py:768
-#: spyderlib\widgets\sourcecode\codeeditor.py:280
+#: spyderlib\widgets\sourcecode\codeeditor.py:90
msgid "Current line:"
msgstr "Ligne actuelle :"
@@ -291,12 +291,12 @@ msgstr "Rétablir les valeurs par défaut"
msgid "Internal console"
msgstr "Console interne"
-#: spyderlib\plugins\console.py:125 spyderlib\spyder.py:810
-#: spyderlib\widgets\ipython.py:473
+#: spyderlib\plugins\console.py:125 spyderlib\spyder.py:800
+#: spyderlib\widgets\ipython.py:515
msgid "&Quit"
msgstr "&Quitter"
-#: spyderlib\plugins\console.py:126 spyderlib\spyder.py:811
+#: spyderlib\plugins\console.py:126 spyderlib\spyder.py:801
msgid "Quit"
msgstr "Quitter"
@@ -335,7 +335,7 @@ msgid "Set maximum line count"
msgstr "Modifier le nombre maximum de lignes"
#: spyderlib\plugins\console.py:148 spyderlib\plugins\explorer.py:60
-#: spyderlib\plugins\history.py:153 spyderlib\plugins\inspector.py:349
+#: spyderlib\plugins\history.py:153 spyderlib\plugins\inspector.py:350
#: spyderlib\plugins\projectexplorer.py:58
msgid "&Font..."
msgstr "&Police..."
@@ -354,15 +354,16 @@ msgstr "Modifier le chemin d'accès de l'éditeur externe"
#: spyderlib\plugins\console.py:156 spyderlib\plugins\editor.py:134
#: spyderlib\plugins\externalconsole.py:95 spyderlib\plugins\history.py:41
-#: spyderlib\plugins\history.py:156 spyderlib\plugins\inspector.py:170
-#: spyderlib\plugins\inspector.py:352
+#: spyderlib\plugins\history.py:156 spyderlib\plugins\inspector.py:171
+#: spyderlib\plugins\inspector.py:353
msgid "Wrap lines"
msgstr "Retour à la ligne automatique"
#: spyderlib\plugins\console.py:159 spyderlib\plugins\editor.py:164
#: spyderlib\plugins\externalconsole.py:144
-msgid "Balloon tips"
-msgstr "Info-bulles"
+#: spyderlib\plugins\ipythonconsole.py:84
+msgid "Display balloon tips"
+msgstr "Afficher des info-bulles"
#: spyderlib\plugins\console.py:163 spyderlib\plugins\editor.py:156
#: spyderlib\plugins\externalconsole.py:136
@@ -388,7 +389,7 @@ msgid "Python scripts"
msgstr "Scripts Python"
#: spyderlib\plugins\console.py:269 spyderlib\plugins\explorer.py:111
-#: spyderlib\plugins\history.py:271 spyderlib\plugins\inspector.py:643
+#: spyderlib\plugins\history.py:271 spyderlib\plugins\inspector.py:645
#: spyderlib\plugins\projectexplorer.py:120
msgid "Select a new font"
msgstr "Sélectionner une police d'écriture"
@@ -411,9 +412,9 @@ msgstr "Chemin d'accès de l'exécutable :"
#: spyderlib\plugins\editor.py:87 spyderlib\plugins\editor.py:505
#: spyderlib\plugins\editor.py:1570 spyderlib\plugins\inspector.py:133
-#: spyderlib\plugins\inspector.py:380 spyderlib\widgets\editor.py:574
-#: spyderlib\widgets\sourcecode\codeeditor.py:270
-#: spyderlib\widgets\sourcecode\codeeditor.py:2558
+#: spyderlib\plugins\inspector.py:381 spyderlib\widgets\editor.py:589
+#: spyderlib\widgets\sourcecode\codeeditor.py:80
+#: spyderlib\widgets\sourcecode\codeeditor.py:2378
msgid "Editor"
msgstr "Éditeur"
@@ -436,7 +437,7 @@ msgstr "Afficher la barre d'onglets"
#: spyderlib\plugins\editor.py:110 spyderlib\plugins\editor.py:178
#: spyderlib\plugins\externalconsole.py:90
#: spyderlib\plugins\externalconsole.py:135 spyderlib\plugins\history.py:40
-#: spyderlib\plugins\inspector.py:169 spyderlib\plugins\ipythonconsole.py:108
+#: spyderlib\plugins\inspector.py:170 spyderlib\plugins\ipythonconsole.py:108
msgid "Source code"
msgstr "Code source"
@@ -461,13 +462,13 @@ msgid "Highlight occurences after"
msgstr "Surligner les occurences après"
#: spyderlib\plugins\editor.py:137 spyderlib\plugins\history.py:49
-#: spyderlib\plugins\inspector.py:173
+#: spyderlib\plugins\inspector.py:174
msgid "Syntax color scheme: "
msgstr "Thème de coloration syntaxique : "
#: spyderlib\plugins\editor.py:149 spyderlib\plugins\runconfig.py:304
#: spyderlib\plugins\runconfig.py:426 spyderlib\plugins\runconfig.py:431
-#: spyderlib\spyder.py:1795 spyderlib\widgets\explorer.py:230
+#: spyderlib\spyder.py:1829 spyderlib\widgets\explorer.py:230
#: spyderlib\widgets\externalshell\baseshell.py:138
msgid "Run"
msgstr "Exécuter"
@@ -596,7 +597,7 @@ msgstr ""
"veuillez visiter la page de la %s."
#: spyderlib\plugins\editor.py:219
-#: spyderlib\widgets\sourcecode\codeeditor.py:1607
+#: spyderlib\widgets\sourcecode\codeeditor.py:1422
msgid "Code analysis"
msgstr "Analyse de code"
@@ -779,7 +780,7 @@ msgstr "Points d'arrêt"
msgid "Debug with winpdb"
msgstr "Déboguer avec winpdb"
-#: spyderlib\plugins\editor.py:663 spyderlib\spyder.py:609
+#: spyderlib\plugins\editor.py:663 spyderlib\spyder.py:606
msgid "&Debug"
msgstr "&Déboguer"
@@ -834,7 +835,7 @@ msgid "Debugging control"
msgstr "Contrôle du débogage"
#: spyderlib\plugins\editor.py:722 spyderlib\plugins\editor.py:1222
-#: spyderlib\spyder.py:604
+#: spyderlib\spyder.py:601
msgid "&Run"
msgstr "E&xécution"
@@ -860,7 +861,7 @@ msgid "Run again last file"
msgstr "Exécuter de nouveau le dernier fichier"
#: spyderlib\plugins\editor.py:748
-#: spyderlib\widgets\sourcecode\codeeditor.py:2243
+#: spyderlib\widgets\sourcecode\codeeditor.py:2058
msgid "Run &selection"
msgstr "Exécuter la &sélection"
@@ -948,12 +949,12 @@ msgid "Go to next cursor position"
msgstr "Aller à la position suivante du curseur"
#: spyderlib\plugins\editor.py:823
-#: spyderlib\widgets\sourcecode\codeeditor.py:2237
+#: spyderlib\widgets\sourcecode\codeeditor.py:2052
msgid "Comment"
msgstr "Commenter"
#: spyderlib\plugins\editor.py:823
-#: spyderlib\widgets\sourcecode\codeeditor.py:2237
+#: spyderlib\widgets\sourcecode\codeeditor.py:2052
msgid "Uncomment"
msgstr "Décommenter"
@@ -1056,47 +1057,47 @@ msgstr "Effacer cette liste"
msgid "Open &recent"
msgstr "Fichiers &récents"
-#: spyderlib\plugins\editor.py:1210 spyderlib\spyder.py:585
+#: spyderlib\plugins\editor.py:1210 spyderlib\spyder.py:582
msgid "File toolbar"
msgstr "Barre d'outil fichiers"
-#: spyderlib\plugins\editor.py:1211 spyderlib\spyder.py:595
+#: spyderlib\plugins\editor.py:1211 spyderlib\spyder.py:592
msgid "Search toolbar"
msgstr "Barre d'outil de recherche"
-#: spyderlib\plugins\editor.py:1212 spyderlib\spyder.py:600
+#: spyderlib\plugins\editor.py:1212 spyderlib\spyder.py:597
msgid "Source toolbar"
msgstr "Barre d'outils code source"
-#: spyderlib\plugins\editor.py:1213 spyderlib\spyder.py:605
+#: spyderlib\plugins\editor.py:1213 spyderlib\spyder.py:602
msgid "Run toolbar"
msgstr "Barre d'outil exécution"
-#: spyderlib\plugins\editor.py:1214 spyderlib\spyder.py:610
+#: spyderlib\plugins\editor.py:1214 spyderlib\spyder.py:607
msgid "Debug toolbar"
msgstr "Barre d'outil de débogage"
-#: spyderlib\plugins\editor.py:1215 spyderlib\spyder.py:590
+#: spyderlib\plugins\editor.py:1215 spyderlib\spyder.py:587
msgid "Edit toolbar"
msgstr "Barre d'outil édition"
-#: spyderlib\plugins\editor.py:1218 spyderlib\spyder.py:582
+#: spyderlib\plugins\editor.py:1218 spyderlib\spyder.py:579
msgid "&File"
msgstr "&Fichier"
-#: spyderlib\plugins\editor.py:1219 spyderlib\spyder.py:589
+#: spyderlib\plugins\editor.py:1219 spyderlib\spyder.py:586
msgid "&Edit"
msgstr "&Édition"
-#: spyderlib\plugins\editor.py:1220 spyderlib\spyder.py:594
+#: spyderlib\plugins\editor.py:1220 spyderlib\spyder.py:591
msgid "&Search"
msgstr "&Recherche"
-#: spyderlib\plugins\editor.py:1221 spyderlib\spyder.py:599
+#: spyderlib\plugins\editor.py:1221 spyderlib\spyder.py:596
msgid "Sour&ce"
msgstr "Sour&ce"
-#: spyderlib\plugins\editor.py:1223 spyderlib\spyder.py:617
+#: spyderlib\plugins\editor.py:1223 spyderlib\spyder.py:614
msgid "&Tools"
msgstr "Ou&tils"
@@ -1128,7 +1129,7 @@ msgstr "Impression en cours..."
msgid "File explorer"
msgstr "Explorateur de fichiers"
-#: spyderlib\plugins\explorer.py:61 spyderlib\plugins\inspector.py:350
+#: spyderlib\plugins\explorer.py:61 spyderlib\plugins\inspector.py:351
#: spyderlib\plugins\projectexplorer.py:59
msgid "Set font style"
msgstr "Changer la police d'écriture"
@@ -1139,9 +1140,9 @@ msgstr "Visualisation interactive de données"
#: spyderlib\plugins\externalconsole.py:60
#: spyderlib\plugins\externalconsole.py:1083
-#: spyderlib\plugins\inspector.py:380
+#: spyderlib\plugins\inspector.py:381
#: spyderlib\widgets\externalshell\baseshell.py:106
-#: spyderlib\widgets\ipython.py:412
+#: spyderlib\widgets\ipython.py:454
msgid "Console"
msgstr "Console"
@@ -1495,8 +1496,8 @@ msgstr ""
"sur le bouton à l'extrême droite pour tuer le processus du noyau."
#: spyderlib\plugins\externalconsole.py:686
-#: spyderlib\plugins\ipythonconsole.py:480 spyderlib\spyder.py:1327
-#: spyderlib\spyder.py:1345 spyderlib\utils\environ.py:95
+#: spyderlib\plugins\ipythonconsole.py:480 spyderlib\spyder.py:1323
+#: spyderlib\spyder.py:1341 spyderlib\utils\environ.py:95
#: spyderlib\utils\environ.py:108
msgid "Warning"
msgstr "Attention"
@@ -1629,11 +1630,11 @@ msgstr "Taille de l'historique : "
msgid "Scroll automatically to last entry"
msgstr "Défiler automatiquement jusqu'à la dernière ligne"
-#: spyderlib\plugins\history.py:102 spyderlib\plugins\inspector.py:433
-#: spyderlib\widgets\editor.py:661 spyderlib\widgets\explorer.py:990
+#: spyderlib\plugins\history.py:102 spyderlib\plugins\inspector.py:435
+#: spyderlib\widgets\editor.py:677 spyderlib\widgets\explorer.py:990
#: spyderlib\widgets\externalshell\baseshell.py:151
#: spyderlib\widgets\externalshell\namespacebrowser.py:231
-#: spyderlib\widgets\ipython.py:449
+#: spyderlib\widgets\ipython.py:491
msgid "Options"
msgstr "Options"
@@ -1670,104 +1671,107 @@ msgid "Rich text font style"
msgstr "Police d'écriture du texte enrichi"
#: spyderlib\plugins\inspector.py:125
-#, fuzzy
msgid "Automatic connections"
-msgstr "Complétion de code automatique"
+msgstr "Connexions automatiques"
#: spyderlib\plugins\inspector.py:126
msgid ""
"The Object Inspector 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 ""
+msgstr "L'inspecteur d'objet peut automatiquement afficher l'aide sur un objet dès l'ouverture d'une parenthèse."
-#: spyderlib\plugins\inspector.py:136
+#: spyderlib\plugins\inspector.py:137
msgid "Python Console"
msgstr "Console Python"
-#: spyderlib\plugins\inspector.py:138
+#: spyderlib\plugins\inspector.py:139
msgid "IPython Console"
msgstr "Console IPython"
-#: spyderlib\plugins\inspector.py:151
+#: spyderlib\plugins\inspector.py:152
msgid "Additional features"
msgstr "Options supplémentaires"
-#: spyderlib\plugins\inspector.py:152
+#: spyderlib\plugins\inspector.py:153
msgid "Render mathematical equations"
msgstr "Styliser les équations mathématiques"
-#: spyderlib\plugins\inspector.py:158
+#: spyderlib\plugins\inspector.py:159
msgid "This feature requires Sphinx 1.1 or superior."
msgstr "Cette fonctionnalité nécessite l'installation de Sphinx 1.1+."
-#: spyderlib\plugins\inspector.py:160
+#: spyderlib\plugins\inspector.py:161
msgid "Sphinx %s is currently installed."
msgstr "Sphinx %s n'est pas installé."
-#: spyderlib\plugins\inspector.py:334
+#: spyderlib\plugins\inspector.py:335
msgid "No documentation available"
msgstr "Aucune documentation disponible"
-#: spyderlib\plugins\inspector.py:373
+#: spyderlib\plugins\inspector.py:374
msgid "Source"
msgstr "Source"
-#: spyderlib\plugins\inspector.py:388 spyderlib\widgets\dicteditor.py:162
+#: spyderlib\plugins\inspector.py:390 spyderlib\widgets\dicteditor.py:162
msgid "Object"
msgstr "Objet"
-#: spyderlib\plugins\inspector.py:403
+#: spyderlib\plugins\inspector.py:405
msgid "Plain Text"
msgstr "Texte brut"
-#: spyderlib\plugins\inspector.py:407
+#: spyderlib\plugins\inspector.py:409
msgid "Show Source"
msgstr "Afficher les sources"
-#: spyderlib\plugins\inspector.py:411
+#: spyderlib\plugins\inspector.py:413
msgid "Rich Text"
msgstr "Texte enrichi"
-#: spyderlib\plugins\inspector.py:421
+#: spyderlib\plugins\inspector.py:423
msgid "Automatic import"
msgstr "Import automatique"
-#: spyderlib\plugins\inspector.py:476 spyderlib\plugins\inspector.py:885
+#: spyderlib\plugins\inspector.py:478 spyderlib\plugins\inspector.py:887
msgid "Object inspector"
msgstr "Inspecteur d'objets"
-#: spyderlib\plugins\inspector.py:599
+#: spyderlib\plugins\inspector.py:601
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."
+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."
-#: spyderlib\plugins\inspector.py:605
+#: spyderlib\plugins\inspector.py:607
msgid "Preferences > Object Inspector"
msgstr "Préférences > Inspecteur d'objets"
-#: spyderlib\plugins\inspector.py:607
+#: spyderlib\plugins\inspector.py:609
msgid "Usage"
msgstr "Utilisation"
-#: spyderlib\plugins\inspector.py:613
+#: spyderlib\plugins\inspector.py:615
msgid ""
"Please consider installing Sphinx to get documentation rendered in rich text."
msgstr ""
"Merci d'installer Sphinx pour obtenir la documentation en texte enrichi."
-#: spyderlib\plugins\inspector.py:846
+#: spyderlib\plugins\inspector.py:848
msgid "Lock"
msgstr "Verrouiller"
-#: spyderlib\plugins\inspector.py:846
+#: spyderlib\plugins\inspector.py:848
msgid "Unlock"
msgstr "Déverrouiller"
-#: spyderlib\plugins\inspector.py:886
+#: spyderlib\plugins\inspector.py:888
msgid ""
"The following error occured when calling <b>Sphinx %s</b>. <br>Incompatible "
"Sphinx version or doc string decoding failed.<br><br>Error message:<br>%s"
@@ -1776,7 +1780,7 @@ msgstr ""
"<br>Veuillez vérifier si cette version de Sphinx est bien prise en charge "
"par Spyder. <br><br>Message d'erreur :<br>%s"
-#: spyderlib\plugins\inspector.py:930
+#: spyderlib\plugins\inspector.py:932
msgid "No source code available."
msgstr "Aucun code source disponible."
@@ -1822,10 +1826,6 @@ msgstr ""
"Le pager permet d'éviter de remplir la console de texte d'aide.\n"
"Note : utiliser la touche Q pour quitter le pager."
-#: spyderlib\plugins\ipythonconsole.py:84
-msgid "Display balloon tips"
-msgstr "Afficher des info-bulles"
-
#: spyderlib\plugins\ipythonconsole.py:85
msgid "Ask for confirmation before closing"
msgstr "Demander confirmation avant de fermer une console"
@@ -2516,11 +2516,10 @@ msgid "Global working directory"
msgstr "Répertoire de travail global"
#: spyderlib\spyder.py:48
-#, fuzzy
msgid "IPython Console integration"
msgstr "Intégration de la console IPython"
-#: spyderlib\spyder.py:125 spyderlib\spyder.py:455
+#: spyderlib\spyder.py:125
msgid "Initializing..."
msgstr "Initialisation..."
@@ -2544,7 +2543,7 @@ msgstr "WinPython"
msgid "Numpy and Scipy documentation"
msgstr "Documentation de Numpy et Scipy"
-#: spyderlib\spyder.py:297 spyderlib\spyder.py:989
+#: spyderlib\spyder.py:297 spyderlib\spyder.py:971
msgid "Matplotlib documentation"
msgstr "Documentation de Matplotlib"
@@ -2568,106 +2567,106 @@ msgstr "Enregistrer la session et quitter..."
msgid "Save current session and quit application"
msgstr "Enregistrer la session en cours et quitter l'application"
-#: spyderlib\spyder.py:516
-msgid "Close current dockwidget"
-msgstr "Fermer le panneau actif"
+#: spyderlib\spyder.py:513
+msgid "Close current plugin"
+msgstr "Fermer la fenêtre courante"
-#: spyderlib\spyder.py:522
+#: spyderlib\spyder.py:519
msgid "&Find text"
msgstr "Rec&hercher"
-#: spyderlib\spyder.py:528
+#: spyderlib\spyder.py:525
msgid "Find &next"
msgstr "Rechercher le &suivant"
-#: spyderlib\spyder.py:534
+#: spyderlib\spyder.py:531
msgid "Find &previous"
msgstr "Rechercher le &précédent"
-#: spyderlib\spyder.py:539
+#: spyderlib\spyder.py:536
msgid "&Replace text"
msgstr "&Remplacer"
-#: spyderlib\spyder.py:554 spyderlib\widgets\sourcecode\codeeditor.py:2213
+#: spyderlib\spyder.py:551 spyderlib\widgets\sourcecode\codeeditor.py:2028
msgid "Undo"
msgstr "Annuler"
-#: spyderlib\spyder.py:556 spyderlib\widgets\sourcecode\codeeditor.py:2216
+#: spyderlib\spyder.py:553 spyderlib\widgets\sourcecode\codeeditor.py:2031
msgid "Redo"
msgstr "Répéter"
-#: spyderlib\spyder.py:557 spyderlib\widgets\arrayeditor.py:327
-#: spyderlib\widgets\dicteditor.py:563 spyderlib\widgets\shell.py:121
-#: spyderlib\widgets\sourcecode\codeeditor.py:2222
+#: spyderlib\spyder.py:554 spyderlib\widgets\arrayeditor.py:327
+#: spyderlib\widgets\dicteditor.py:563 spyderlib\widgets\shell.py:122
+#: spyderlib\widgets\sourcecode\codeeditor.py:2037
msgid "Copy"
msgstr "Copier"
-#: spyderlib\spyder.py:559 spyderlib\widgets\shell.py:117
-#: spyderlib\widgets\sourcecode\codeeditor.py:2219
+#: spyderlib\spyder.py:556 spyderlib\widgets\shell.py:118
+#: spyderlib\widgets\sourcecode\codeeditor.py:2034
msgid "Cut"
msgstr "Couper"
-#: spyderlib\spyder.py:560 spyderlib\widgets\dicteditor.py:560
-#: spyderlib\widgets\shell.py:125
-#: spyderlib\widgets\sourcecode\codeeditor.py:2225
+#: spyderlib\spyder.py:557 spyderlib\widgets\dicteditor.py:560
+#: spyderlib\widgets\shell.py:126
+#: spyderlib\widgets\sourcecode\codeeditor.py:2040
msgid "Paste"
msgstr "Coller"
-#: spyderlib\spyder.py:562 spyderlib\widgets\explorer.py:453
-#: spyderlib\widgets\projectexplorer.py:1002 spyderlib\widgets\shell.py:134
-#: spyderlib\widgets\sourcecode\codeeditor.py:2228
+#: spyderlib\spyder.py:559 spyderlib\widgets\explorer.py:453
+#: spyderlib\widgets\projectexplorer.py:1002 spyderlib\widgets\shell.py:135
+#: spyderlib\widgets\sourcecode\codeeditor.py:2043
msgid "Delete"
msgstr "Supprimer"
-#: spyderlib\spyder.py:565 spyderlib\widgets\shell.py:138
-#: spyderlib\widgets\sourcecode\codeeditor.py:2232
+#: spyderlib\spyder.py:562 spyderlib\widgets\shell.py:139
+#: spyderlib\widgets\sourcecode\codeeditor.py:2047
msgid "Select All"
msgstr "Sélectionner tout"
-#: spyderlib\spyder.py:614
+#: spyderlib\spyder.py:611
msgid "C&onsoles"
msgstr "C&onsoles"
-#: spyderlib\spyder.py:620
+#: spyderlib\spyder.py:617
msgid "&View"
msgstr "&Affichage"
-#: spyderlib\spyder.py:623
+#: spyderlib\spyder.py:620
msgid "&Help"
msgstr "A&ide"
-#: spyderlib\spyder.py:628
+#: spyderlib\spyder.py:625
msgid "Welcome to Spyder!"
msgstr "Bienvenue dans Spyder !"
-#: spyderlib\spyder.py:633
+#: spyderlib\spyder.py:630
msgid "Pre&ferences"
msgstr "Pré&férences"
-#: spyderlib\spyder.py:641 spyderlib\widgets\pathmanager.py:45
+#: spyderlib\spyder.py:638 spyderlib\widgets\pathmanager.py:45
#: spyderlib\widgets\projectexplorer.py:593
msgid "PYTHONPATH manager"
msgstr "Gestionnaire de PYTHONPATH"
-#: spyderlib\spyder.py:644
+#: spyderlib\spyder.py:641
msgid "Python Path Manager"
msgstr "Gestionnaire de chemins d'accès Python"
-#: spyderlib\spyder.py:647
+#: spyderlib\spyder.py:644
msgid "Update module names list"
msgstr "Mise à jour de la liste des modules"
-#: spyderlib\spyder.py:649
+#: spyderlib\spyder.py:646
msgid "Refresh list of module names available in PYTHONPATH"
msgstr ""
"Mise à jour de la liste des modules disponibles notamment à travers "
"PYTHONPATH"
-#: spyderlib\spyder.py:655
+#: spyderlib\spyder.py:651
msgid "Current user environment variables..."
msgstr "Variables d'environnement de l'utilisateur..."
-#: spyderlib\spyder.py:657
+#: spyderlib\spyder.py:653
msgid ""
"Show and edit current user environment variables in Windows registry (i.e. "
"for all sessions)"
@@ -2675,199 +2674,207 @@ msgstr ""
"Afficher et modifier les variables d'environnement de l'utilisateur courant "
"dans Windows (c'est-à-dire directement dans la base de registre)"
-#: spyderlib\spyder.py:664 spyderlib\spyder.py:1064
+#: spyderlib\spyder.py:661 spyderlib\spyder.py:1063
msgid "External Tools"
msgstr "Outils externes"
-#: spyderlib\spyder.py:668
+#: spyderlib\spyder.py:665
msgid "Python(x,y) launcher"
msgstr "Accueil de Python(x,y)"
-#: spyderlib\spyder.py:679
+#: spyderlib\spyder.py:672
msgid "WinPython control panel"
msgstr "Panneau de contrôle WinPython"
-#: spyderlib\spyder.py:692
+#: spyderlib\spyder.py:681
msgid "Qt Designer"
msgstr "Qt Designer"
-#: spyderlib\spyder.py:697
+#: spyderlib\spyder.py:686
msgid "Qt Linguist"
msgstr "Qt Linguist"
-#: spyderlib\spyder.py:703
+#: spyderlib\spyder.py:692
msgid "Qt examples"
msgstr "Exemples Qt"
-#: spyderlib\spyder.py:721
+#: spyderlib\spyder.py:710
msgid "guidata examples"
msgstr "Exemples guidata"
-#: spyderlib\spyder.py:729
+#: spyderlib\spyder.py:718
msgid "guiqwt examples"
msgstr "Exemples guiqwt"
-#: spyderlib\spyder.py:734
+#: spyderlib\spyder.py:723
msgid "Sift"
msgstr "Sift"
-#: spyderlib\spyder.py:742
+#: spyderlib\spyder.py:731
msgid "ViTables"
msgstr "ViTables"
-#: spyderlib\spyder.py:756
+#: spyderlib\spyder.py:745
msgid "Fullscreen mode"
msgstr "Mode plein écran"
-#: spyderlib\spyder.py:768
+#: spyderlib\spyder.py:757
msgid "Main toolbar"
msgstr "Barre d'outil principale"
-#: spyderlib\spyder.py:789
+#: spyderlib\spyder.py:779
msgid "Loading object inspector..."
msgstr "Chargement de l'inspecteur d'objet..."
-#: spyderlib\spyder.py:796
+#: spyderlib\spyder.py:786
msgid "Loading outline explorer..."
msgstr "Chargement de l'explorateur de structure..."
-#: spyderlib\spyder.py:804
+#: spyderlib\spyder.py:794
msgid "Loading editor..."
msgstr "Chargement de l'éditeur..."
-#: spyderlib\spyder.py:829
+#: spyderlib\spyder.py:819
msgid "Loading file explorer..."
msgstr "Chargement de l'explorateur de fichiers..."
-#: spyderlib\spyder.py:836
+#: spyderlib\spyder.py:826
msgid "Loading history plugin..."
msgstr "Chargement du journal d'historique..."
-#: spyderlib\spyder.py:847
+#: spyderlib\spyder.py:837
msgid "Loading online help..."
msgstr "Chargement de l'aide en ligne..."
-#: spyderlib\spyder.py:853
+#: spyderlib\spyder.py:843
msgid "Loading project explorer..."
msgstr "Chargement de l'explorateur de projet..."
-#: spyderlib\spyder.py:864
+#: spyderlib\spyder.py:854
msgid "Loading external console..."
msgstr "Chargement de la console externe..."
-#: spyderlib\spyder.py:873
+#: spyderlib\spyder.py:863
msgid "Loading namespace browser..."
msgstr "Chargement de l'explorateur d'espace de noms..."
-#: spyderlib\spyder.py:880
+#: spyderlib\spyder.py:870
msgid "Loading IPython console..."
msgstr "Chargement de la console IPython..."
-#: spyderlib\spyder.py:891
+#: spyderlib\spyder.py:881
msgid "Setting up main window..."
msgstr "Configuration de la fenêtre principale..."
-#: spyderlib\spyder.py:895
-msgid "About %s..."
-msgstr "À propos de %s..."
-
-#: spyderlib\spyder.py:898
-msgid "Optional dependencies..."
-msgstr "Dépendances optionnelles..."
+#: spyderlib\spyder.py:900
+msgid "Spyder documentation"
+msgstr "Documentation de Spyder"
-#: spyderlib\spyder.py:901
+#: spyderlib\spyder.py:904
msgid "Report issue..."
msgstr "Rapport d'erreur..."
-#: spyderlib\spyder.py:922
-msgid "Spyder documentation"
-msgstr "Documentation de Spyder"
+#: spyderlib\spyder.py:908
+msgid "Spyder support..."
+msgstr "Support technique de Spyder..."
-#: spyderlib\spyder.py:928
+#: spyderlib\spyder.py:910
+msgid "Optional dependencies..."
+msgstr "Dépendances optionnelles..."
+
+#: spyderlib\spyder.py:917
msgid "Python documentation"
msgstr "Documentation de Python"
-#: spyderlib\spyder.py:935
-msgid "IPython Help"
-msgstr "Aide IPython"
+#: spyderlib\spyder.py:923 spyderlib\spyder.py:963
+msgid "IPython documentation"
+msgstr "Documentation de IPython"
-#: spyderlib\spyder.py:936
+#: spyderlib\spyder.py:924
msgid "Intro to IPython"
msgstr "Introduction à IPython"
-#: spyderlib\spyder.py:938
-msgid "Quick Reference"
-msgstr "Documentation de IPython"
+#: spyderlib\spyder.py:926
+msgid "Quick reference"
+msgstr "Référence rapide"
-#: spyderlib\spyder.py:940
+#: spyderlib\spyder.py:928
msgid "Console help"
msgstr "Aide sur la console"
-#: spyderlib\spyder.py:946
-msgid "Qt Help"
-msgstr "Aide Qt"
-
-#: spyderlib\spyder.py:950
-msgid "Web Resources"
-msgstr "Documentation en ligne"
-
-#: spyderlib\spyder.py:979
+#: spyderlib\spyder.py:961
msgid "Python(x,y) documentation folder"
msgstr "Dossier de documentation Python(x,y)"
-#: spyderlib\spyder.py:981
-msgid "IPython documentation"
-msgstr "Documentation de IPython"
-
-#: spyderlib\spyder.py:983
+#: spyderlib\spyder.py:965
msgid "guidata documentation"
msgstr "Documentation de guidata"
-#: spyderlib\spyder.py:986
+#: spyderlib\spyder.py:968
msgid "guiqwt documentation"
msgstr "Documentation de guiqwt"
-#: spyderlib\spyder.py:992
+#: spyderlib\spyder.py:974
msgid "NumPy documentation"
msgstr "Documentation de NumPy"
-#: spyderlib\spyder.py:994
+#: spyderlib\spyder.py:976
msgid "NumPy reference guide"
msgstr "Manuel de référence de NumPy"
-#: spyderlib\spyder.py:996
+#: spyderlib\spyder.py:978
msgid "NumPy user guide"
msgstr "Manuel de l'utilisateur de NumPy"
-#: spyderlib\spyder.py:998
+#: spyderlib\spyder.py:980
msgid "SciPy documentation"
msgstr "Documentation de SciPy"
-#: spyderlib\spyder.py:1026
-msgid "Windows and toolbars"
-msgstr "Fenêtres et barres d'outils"
+#: spyderlib\spyder.py:987
+msgid "Installed Python modules"
+msgstr "Modules Python installés"
+
+#: spyderlib\spyder.py:991
+msgid "Online documentation"
+msgstr "Documentation en ligne"
+
+#: spyderlib\spyder.py:996
+msgid "Qt documentation"
+msgstr "Documentation de Qt"
+
+#: spyderlib\spyder.py:1002
+msgid "About %s..."
+msgstr "À propos de %s..."
+
+#: spyderlib\spyder.py:1023
+msgid "Windows"
+msgstr "Fenêtres"
+
+#: spyderlib\spyder.py:1024
+msgid "Toolbars"
+msgstr "Barres d'outils"
-#: spyderlib\spyder.py:1030
+#: spyderlib\spyder.py:1027
msgid "Reset window layout"
msgstr "Réinitialiser la disposition des fenêtres"
-#: spyderlib\spyder.py:1032
+#: spyderlib\spyder.py:1029
msgid "Custom window layouts"
msgstr "Dispositions de fenêtres personnalisées"
-#: spyderlib\spyder.py:1038
+#: spyderlib\spyder.py:1035
msgid "Switch to/from layout %d"
msgstr "Basculer vers/depuis la disposition %d"
-#: spyderlib\spyder.py:1044
+#: spyderlib\spyder.py:1041
msgid "Set layout %d"
msgstr "Définir la disposition %d"
-#: spyderlib\spyder.py:1054
+#: spyderlib\spyder.py:1051
msgid "Attached console window (debugging)"
msgstr "Invite de commandes attaché (débogage)"
-#: spyderlib\spyder.py:1328
+#: spyderlib\spyder.py:1324
msgid ""
"Window layout will be reset to default settings: this affects window "
"position, size and dockwidgets.\n"
@@ -2877,46 +2884,46 @@ msgstr ""
"défaut.\n"
"Souhaitez-vous continuer ?"
-#: spyderlib\spyder.py:1346
+#: spyderlib\spyder.py:1342
msgid "Quick switch layout #%d has not yet been defined."
msgstr ""
"La disposition de fenêtre personnalisée n°%d n'a pas encore été définie."
-#: spyderlib\spyder.py:1537 spyderlib\spyder.py:1538
+#: spyderlib\spyder.py:1568 spyderlib\spyder.py:1569
msgid "Maximize current plugin"
msgstr "Agrandir la fenêtre courante"
-#: spyderlib\spyder.py:1541
+#: spyderlib\spyder.py:1572
msgid "Restore current plugin"
msgstr "Réduire la fenêtre courante"
-#: spyderlib\spyder.py:1542
+#: spyderlib\spyder.py:1573
msgid "Restore plugin to its original size"
msgstr "Restaurer la fenêtre à sa taille d'origine"
-#: spyderlib\spyder.py:1613
+#: spyderlib\spyder.py:1644
msgid "(not installed)"
msgstr "(non installé)"
-#: spyderlib\spyder.py:1631
+#: spyderlib\spyder.py:1662
msgid "About %s"
msgstr "À propos de %s"
-#: spyderlib\spyder.py:1796
+#: spyderlib\spyder.py:1830
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."
-#: spyderlib\spyder.py:1997
+#: spyderlib\spyder.py:2031
msgid "Open session"
msgstr "Ouvrir une session"
-#: spyderlib\spyder.py:1998 spyderlib\spyder.py:2009
+#: spyderlib\spyder.py:2032 spyderlib\spyder.py:2043
msgid "Spyder sessions"
msgstr "Sessions Spyder"
-#: spyderlib\spyder.py:2008
+#: spyderlib\spyder.py:2042
msgid "Save session"
msgstr "Enregistrer la session"
@@ -2966,6 +2973,10 @@ msgstr ""
"Le processus de génération de l'aide sous la forme de texte enrichi a échoué."
"</br>Merci d'activer le mode d'affichage en texte brut."
+#: spyderlib\utils\introspection\rope_plugin.py:34
+msgid "Editor's code completion, go-to-definition and help"
+msgstr "Editeur : complétion de code, aller à la définition, etc."
+
#: spyderlib\utils\iofuncs.py:331
msgid "Supported files"
msgstr "Fichiers compatibles"
@@ -3103,12 +3114,12 @@ msgstr ""
"réciproquement)."
#: spyderlib\widgets\browser.py:30
-#: spyderlib\widgets\sourcecode\codeeditor.py:2248
+#: spyderlib\widgets\sourcecode\codeeditor.py:2063
msgid "Zoom out"
msgstr "Réduire"
#: spyderlib\widgets\browser.py:33
-#: spyderlib\widgets\sourcecode\codeeditor.py:2245
+#: spyderlib\widgets\sourcecode\codeeditor.py:2060
msgid "Zoom in"
msgstr "Agrandir"
@@ -3170,7 +3181,7 @@ msgstr "Fonctionnalités associées"
msgid "Optional Dependencies"
msgstr "Dépendances optionnelles"
-#: spyderlib\widgets\dependencies.py:133
+#: spyderlib\widgets\dependencies.py:134
msgid ""
"Spyder depends on several Python modules to provide additional functionality "
"for its plugins. The table below shows the required and installed versions "
@@ -3185,7 +3196,7 @@ msgstr ""
"ces modules, il est néanmoins fortement recommandé d'installer au minimum <b>"
"%s</b> et <b>%s</b> afin de bénéficier des fonctionnalités les plus avancées."
-#: spyderlib\widgets\dependencies.py:148
+#: spyderlib\widgets\dependencies.py:149
msgid "Copy to clipboard"
msgstr "Copier dans le presse-papier"
@@ -3338,86 +3349,86 @@ msgstr "Presse-papiers vide"
msgid "Nothing to be imported from clipboard."
msgstr "Aucune donnée ne peut être importée depuis le presse-papiers."
-#: spyderlib\widgets\editor.py:69 spyderlib\widgets\editor.py:557
+#: spyderlib\widgets\editor.py:70 spyderlib\widgets\editor.py:572
msgid "File list management"
msgstr "Gestionnaire de fichiers"
-#: spyderlib\widgets\editor.py:73
+#: spyderlib\widgets\editor.py:74
msgid "Filter:"
msgstr "Filtre :"
-#: spyderlib\widgets\editor.py:78
+#: spyderlib\widgets\editor.py:79
msgid "(press <b>Enter</b> to edit file)"
msgstr "(appuyer sur <b>Entrée</b> pour modifier le fichier)"
-#: spyderlib\widgets\editor.py:93
+#: spyderlib\widgets\editor.py:94
msgid "&Edit file"
msgstr "Modifi&er le fichier"
-#: spyderlib\widgets\editor.py:102
+#: spyderlib\widgets\editor.py:103
msgid "&Close file"
msgstr "&Fermer le fichier"
-#: spyderlib\widgets\editor.py:110
+#: spyderlib\widgets\editor.py:111
msgid "Hint: press <b>Alt</b> to show accelerators"
msgstr "Astuce : la touche <b>Alt</b> affiche les accélérateurs"
-#: spyderlib\widgets\editor.py:560
+#: spyderlib\widgets\editor.py:575
msgid "Copy path to clipboard"
msgstr "Copier le chemin d'accès dans le presse-papier"
-#: spyderlib\widgets\editor.py:1099
+#: spyderlib\widgets\editor.py:1115
msgid "Temporary file"
msgstr "Fichier temporaire"
-#: spyderlib\widgets\editor.py:1196
+#: spyderlib\widgets\editor.py:1212
msgid "New window"
msgstr "Nouvelle fenêtre"
-#: spyderlib\widgets\editor.py:1197
+#: spyderlib\widgets\editor.py:1213
msgid "Create a new editor window"
msgstr "Créer une nouvelle fenêtre d'édition"
-#: spyderlib\widgets\editor.py:1200
+#: spyderlib\widgets\editor.py:1216
msgid "Split vertically"
msgstr "Séparation verticale"
-#: spyderlib\widgets\editor.py:1202
+#: spyderlib\widgets\editor.py:1218
msgid "Split vertically this editor window"
msgstr "Séparer en deux verticalement cette fenêtre d'édition"
-#: spyderlib\widgets\editor.py:1204
+#: spyderlib\widgets\editor.py:1220
msgid "Split horizontally"
msgstr "Séparation horizontale"
-#: spyderlib\widgets\editor.py:1206
+#: spyderlib\widgets\editor.py:1222
msgid "Split horizontally this editor window"
msgstr "Séparer en deux horizontalement cette fenêtre d'édition"
-#: spyderlib\widgets\editor.py:1208
+#: spyderlib\widgets\editor.py:1224
msgid "Close this panel"
msgstr "Fermer ce panneau"
-#: spyderlib\widgets\editor.py:1340
+#: spyderlib\widgets\editor.py:1356
msgid "<b>%s</b> has been modified.<br>Do you want to save changes?"
msgstr ""
"<b>%s</b> a été modifié.<br>Souhaitez-vous enregistrer ces changements ?"
-#: spyderlib\widgets\editor.py:1403
+#: spyderlib\widgets\editor.py:1419
msgid "Save"
msgstr "Enregistrer"
-#: spyderlib\widgets\editor.py:1404
+#: spyderlib\widgets\editor.py:1420
msgid "<b>Unable to save script '%s'</b><br><br>Error message:<br>%s"
msgstr ""
"<b>Impossible d'enregistrer le script '%s'</b><br><br>Message d'erreur :<br>%"
"s"
-#: spyderlib\widgets\editor.py:1426
+#: spyderlib\widgets\editor.py:1442
msgid "Save Python script"
msgstr "Enregistrer le script Python"
-#: spyderlib\widgets\editor.py:1647
+#: spyderlib\widgets\editor.py:1663
msgid ""
"<b>%s</b> is unavailable (this file may have been removed, moved or renamed "
"outside Spyder).<br>Do you want to close it?"
@@ -3425,7 +3436,7 @@ msgstr ""
"<b>%s</b> n'est pas accessible (ce fichier a peut-être été supprimé, déplacé "
"ou renommé en dehors de Spyder).<br>Souhaitez-vous le fermer ?"
-#: spyderlib\widgets\editor.py:1667
+#: spyderlib\widgets\editor.py:1683
msgid ""
"<b>%s</b> has been modified outside Spyder.<br>Do you want to reload it and "
"lose all your changes?"
@@ -3433,7 +3444,7 @@ msgstr ""
"<b>%s</b> a été modifié en dehors de Spyder.<br>Souhaitez-vous le recharger "
"et perdre ainsi vos modifications ?"
-#: spyderlib\widgets\editor.py:1763
+#: spyderlib\widgets\editor.py:1779
msgid ""
"All changes to <b>%s</b> will be lost.<br>Do you want to revert file from "
"disk?"
@@ -3442,11 +3453,11 @@ msgstr ""
"<br>Souhaitez-vous revenir à la version du fichier enregistrée sur le "
"disque ?"
-#: spyderlib\widgets\editor.py:1902
+#: spyderlib\widgets\editor.py:1919
msgid "Loading %s..."
msgstr "Chargement de \"%s\" en cours..."
-#: spyderlib\widgets\editor.py:1912
+#: spyderlib\widgets\editor.py:1929
msgid ""
"<b>%s</b> contains mixed end-of-line characters.<br>Spyder will fix this "
"automatically."
@@ -3454,11 +3465,11 @@ msgstr ""
"<b>%s</b> contient des caractères de fin de ligne mélangés.<br>Spyder va "
"corriger ceci automatiquement."
-#: spyderlib\widgets\editor.py:2260
+#: spyderlib\widgets\editor.py:2277
msgid "Close window"
msgstr "Fermer la fenêtre"
-#: spyderlib\widgets\editor.py:2262
+#: spyderlib\widgets\editor.py:2279
msgid "Close this window"
msgstr "Fermer cette fenêtre d'édition"
@@ -3690,7 +3701,7 @@ msgid "Terminated."
msgstr "Terminé."
#: spyderlib\widgets\externalshell\baseshell.py:235
-#: spyderlib\widgets\mixins.py:511
+#: spyderlib\widgets\ipython.py:336 spyderlib\widgets\mixins.py:599
msgid "Arguments"
msgstr "Arguments"
@@ -3825,9 +3836,10 @@ msgid "No argument"
msgstr "Aucun argument"
#: spyderlib\widgets\externalshell\pythonshell.py:524
+#, fuzzy
msgid ""
-"The console failed to start! That's all we know :(<br>Please close it and "
-"open a new one."
+"The kernel failed to start!! That's all we know... Please close this console "
+"and open a new one."
msgstr ""
"Le démarrage de la console a échoué !<br>C'est malheureusement tout ce que "
"nous savons...<br>Merci de fermer la console et d'en réouvrir une autre."
@@ -4078,71 +4090,71 @@ msgstr ""
"<b>Impossible de passer à l'étape suivante</b><br><br>Merci de vérifier "
"votre saisie.<br><br>Message d'erreur :<br>%s"
-#: spyderlib\widgets\internalshell.py:248
+#: spyderlib\widgets\internalshell.py:250
msgid "Help..."
msgstr "Aide..."
-#: spyderlib\widgets\internalshell.py:255
+#: spyderlib\widgets\internalshell.py:257
msgid "Help"
msgstr "Aide"
-#: spyderlib\widgets\internalshell.py:264
+#: spyderlib\widgets\internalshell.py:266
msgid "Shell special commands:"
msgstr "Commandes spéciales de la console :"
-#: spyderlib\widgets\internalshell.py:265
+#: spyderlib\widgets\internalshell.py:267
msgid "Internal editor:"
msgstr "Éditeur interne :"
-#: spyderlib\widgets\internalshell.py:266
+#: spyderlib\widgets\internalshell.py:268
msgid "External editor:"
msgstr "Éditeur externe :"
-#: spyderlib\widgets\internalshell.py:267
+#: spyderlib\widgets\internalshell.py:269
msgid "Run script:"
msgstr "Exécuter un script :"
-#: spyderlib\widgets\internalshell.py:268
+#: spyderlib\widgets\internalshell.py:270
msgid "Remove references:"
msgstr "Supprimer des références :"
-#: spyderlib\widgets\internalshell.py:269
+#: spyderlib\widgets\internalshell.py:271
msgid "System commands:"
msgstr "Commandes systèmes :"
-#: spyderlib\widgets\internalshell.py:270
+#: spyderlib\widgets\internalshell.py:272
msgid "Python help:"
msgstr "Aide Python :"
-#: spyderlib\widgets\internalshell.py:271
+#: spyderlib\widgets\internalshell.py:273
msgid "GUI-based editor:"
msgstr "Éditeur graphique :"
-#: spyderlib\widgets\ipython.py:398
+#: spyderlib\widgets\ipython.py:440
msgid "An error ocurred while starting the kernel!"
msgstr "Une erreur est survenue lors du démarrage du noyau !"
-#: spyderlib\widgets\ipython.py:426
+#: spyderlib\widgets\ipython.py:468
msgid "Interrupt kernel"
msgstr "Interrompre le noyau"
-#: spyderlib\widgets\ipython.py:429
+#: spyderlib\widgets\ipython.py:471
msgid "Restart kernel"
msgstr "Redémarrer le noyau"
-#: spyderlib\widgets\ipython.py:461
+#: spyderlib\widgets\ipython.py:503
msgid "Inspect current object"
msgstr "Inspecter l'onglet courant"
-#: spyderlib\widgets\ipython.py:465
+#: spyderlib\widgets\ipython.py:507
msgid "Clear line or block"
msgstr "Effacer la ligne ou le bloc"
-#: spyderlib\widgets\ipython.py:469
+#: spyderlib\widgets\ipython.py:511
msgid "Clear console"
msgstr "Effacer la console"
-#: spyderlib\widgets\ipython.py:512
+#: spyderlib\widgets\ipython.py:555
msgid ""
"It seems the kernel died unexpectedly. Use 'Restart kernel' to continue "
"using this console."
@@ -4150,26 +4162,22 @@ msgstr ""
"Le noyau a été arrêté de façon inattendue. Redémarrez le noyau pour "
"continuer d'utiliser cette console."
-#: spyderlib\widgets\ipython.py:524
+#: spyderlib\widgets\ipython.py:567
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."
-#: spyderlib\widgets\ipython.py:533
+#: spyderlib\widgets\ipython.py:576
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."
-#: spyderlib\widgets\ipython.py:550
+#: spyderlib\widgets\ipython.py:593
msgid "Connecting to kernel..."
msgstr "Connexion à un noyau existant..."
-#: spyderlib\widgets\mixins.py:516
-msgid "Documentation"
-msgstr "Documentation"
-
#: spyderlib\widgets\onecolumntree.py:63
msgid "Collapse all"
msgstr "Replier tout"
@@ -4494,71 +4502,67 @@ msgstr ""
msgid "Module or package:"
msgstr "Module ou paquet :"
-#: spyderlib\widgets\shell.py:129
+#: spyderlib\widgets\shell.py:130
msgid "Save history log..."
msgstr "Enregistrer l'historique..."
-#: spyderlib\widgets\shell.py:131
+#: spyderlib\widgets\shell.py:132
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"
-#: spyderlib\widgets\shell.py:251
+#: spyderlib\widgets\shell.py:252
msgid "Save history log"
msgstr "Enregistrer l'historique"
-#: spyderlib\widgets\shell.py:254
+#: spyderlib\widgets\shell.py:255
msgid "History logs"
msgstr "Fichiers d'historique"
-#: spyderlib\widgets\shell.py:265
+#: spyderlib\widgets\shell.py:266
msgid "<b>Unable to save file '%s'</b><br><br>Error message:<br>%s"
msgstr ""
"<b>Impossible d'enregistrer le fichier '%s'</b><br><br>Message d'erreur :<br>"
"%s"
-#: spyderlib\widgets\shell.py:690
+#: spyderlib\widgets\shell.py:691
msgid "Copy without prompts"
msgstr "Copier sans les préfixes"
-#: spyderlib\widgets\shell.py:693 spyderlib\widgets\shell.py:696
+#: spyderlib\widgets\shell.py:694 spyderlib\widgets\shell.py:697
msgid "Clear line"
msgstr "Effacer la ligne"
-#: spyderlib\widgets\shell.py:698
+#: spyderlib\widgets\shell.py:699
msgid "Clear shell"
msgstr "Effacer la console"
-#: spyderlib\widgets\shell.py:701
+#: spyderlib\widgets\shell.py:702
msgid "Clear shell contents ('cls' command)"
msgstr "Effacer le contenu de la console"
-#: spyderlib\widgets\sourcecode\codeeditor.py:69
-msgid "Editor's code completion, go-to-definition and help"
-msgstr "Editeur : complétion de code, aller à la définition, etc."
-
-#: spyderlib\widgets\sourcecode\codeeditor.py:273
+#: spyderlib\widgets\sourcecode\codeeditor.py:83
msgid "Go to line:"
msgstr "Aller à la ligne :"
-#: spyderlib\widgets\sourcecode\codeeditor.py:282
+#: spyderlib\widgets\sourcecode\codeeditor.py:92
msgid "Line count:"
msgstr "Nombre de lignes :"
-#: spyderlib\widgets\sourcecode\codeeditor.py:1224
+#: spyderlib\widgets\sourcecode\codeeditor.py:1027
msgid "Breakpoint"
msgstr "Point d'arrêt"
-#: spyderlib\widgets\sourcecode\codeeditor.py:1225
+#: spyderlib\widgets\sourcecode\codeeditor.py:1028
msgid "Condition:"
msgstr "Condition :"
-#: spyderlib\widgets\sourcecode\codeeditor.py:1661
+#: spyderlib\widgets\sourcecode\codeeditor.py:1476
msgid "To do"
msgstr "À faire"
-#: spyderlib\widgets\sourcecode\codeeditor.py:2240
+#: spyderlib\widgets\sourcecode\codeeditor.py:2055
msgid "Go to definition"
msgstr "Aller à la définition de l'objet"
@@ -4614,6 +4618,36 @@ msgstr "Fermer l'onglet"
msgid "Text editor"
msgstr "Éditeur de texte"
+#, 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 "Documentation"
+#~ msgstr "Documentation"
+
#~ msgid "Automatic notification to object inspector"
#~ msgstr "Notification automatique à l'inspecteur d'objets"
diff --git a/spyderlib/locale/spyderlib.pot b/spyderlib/locale/spyderlib.pot
index 49b5c00..2277e8d 100755
--- a/spyderlib/locale/spyderlib.pot
+++ b/spyderlib/locale/spyderlib.pot
@@ -5,7 +5,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2013-11-09 14:09+Paris, Madrid\n"
+"POT-Creation-Date: 2014-01-04 15:22+Paris, Madrid\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
"Language-Team: LANGUAGE <LL at li.org>\n"
@@ -219,7 +219,7 @@ msgid "Background:"
msgstr ""
#: spyderlib\plugins\configdialog.py:768
-#: spyderlib\widgets\sourcecode\codeeditor.py:280
+#: spyderlib\widgets\sourcecode\codeeditor.py:90
msgid "Current line:"
msgstr ""
@@ -287,12 +287,12 @@ msgstr ""
msgid "Internal console"
msgstr ""
-#: spyderlib\plugins\console.py:125 spyderlib\spyder.py:810
-#: spyderlib\widgets\ipython.py:473
+#: spyderlib\plugins\console.py:125 spyderlib\spyder.py:800
+#: spyderlib\widgets\ipython.py:515
msgid "&Quit"
msgstr ""
-#: spyderlib\plugins\console.py:126 spyderlib\spyder.py:811
+#: spyderlib\plugins\console.py:126 spyderlib\spyder.py:801
msgid "Quit"
msgstr ""
@@ -330,7 +330,7 @@ msgid "Set maximum line count"
msgstr ""
#: spyderlib\plugins\console.py:148 spyderlib\plugins\explorer.py:60
-#: spyderlib\plugins\history.py:153 spyderlib\plugins\inspector.py:349
+#: spyderlib\plugins\history.py:153 spyderlib\plugins\inspector.py:350
#: spyderlib\plugins\projectexplorer.py:58
msgid "&Font..."
msgstr ""
@@ -349,14 +349,15 @@ msgstr ""
#: spyderlib\plugins\console.py:156 spyderlib\plugins\editor.py:134
#: spyderlib\plugins\externalconsole.py:95 spyderlib\plugins\history.py:41
-#: spyderlib\plugins\history.py:156 spyderlib\plugins\inspector.py:170
-#: spyderlib\plugins\inspector.py:352
+#: spyderlib\plugins\history.py:156 spyderlib\plugins\inspector.py:171
+#: spyderlib\plugins\inspector.py:353
msgid "Wrap lines"
msgstr ""
#: spyderlib\plugins\console.py:159 spyderlib\plugins\editor.py:164
#: spyderlib\plugins\externalconsole.py:144
-msgid "Balloon tips"
+#: spyderlib\plugins\ipythonconsole.py:84
+msgid "Display balloon tips"
msgstr ""
#: spyderlib\plugins\console.py:163 spyderlib\plugins\editor.py:156
@@ -383,7 +384,7 @@ msgid "Python scripts"
msgstr ""
#: spyderlib\plugins\console.py:269 spyderlib\plugins\explorer.py:111
-#: spyderlib\plugins\history.py:271 spyderlib\plugins\inspector.py:643
+#: spyderlib\plugins\history.py:271 spyderlib\plugins\inspector.py:645
#: spyderlib\plugins\projectexplorer.py:120
msgid "Select a new font"
msgstr ""
@@ -406,9 +407,9 @@ msgstr ""
#: spyderlib\plugins\editor.py:87 spyderlib\plugins\editor.py:505
#: spyderlib\plugins\editor.py:1570 spyderlib\plugins\inspector.py:133
-#: spyderlib\plugins\inspector.py:380 spyderlib\widgets\editor.py:574
-#: spyderlib\widgets\sourcecode\codeeditor.py:270
-#: spyderlib\widgets\sourcecode\codeeditor.py:2558
+#: spyderlib\plugins\inspector.py:381 spyderlib\widgets\editor.py:589
+#: spyderlib\widgets\sourcecode\codeeditor.py:80
+#: spyderlib\widgets\sourcecode\codeeditor.py:2378
msgid "Editor"
msgstr ""
@@ -431,7 +432,7 @@ msgstr ""
#: spyderlib\plugins\editor.py:110 spyderlib\plugins\editor.py:178
#: spyderlib\plugins\externalconsole.py:90
#: spyderlib\plugins\externalconsole.py:135 spyderlib\plugins\history.py:40
-#: spyderlib\plugins\inspector.py:169 spyderlib\plugins\ipythonconsole.py:108
+#: spyderlib\plugins\inspector.py:170 spyderlib\plugins\ipythonconsole.py:108
msgid "Source code"
msgstr ""
@@ -456,13 +457,13 @@ msgid "Highlight occurences after"
msgstr ""
#: spyderlib\plugins\editor.py:137 spyderlib\plugins\history.py:49
-#: spyderlib\plugins\inspector.py:173
+#: spyderlib\plugins\inspector.py:174
msgid "Syntax color scheme: "
msgstr ""
#: spyderlib\plugins\editor.py:149 spyderlib\plugins\runconfig.py:304
#: spyderlib\plugins\runconfig.py:426 spyderlib\plugins\runconfig.py:431
-#: spyderlib\spyder.py:1795 spyderlib\widgets\explorer.py:230
+#: spyderlib\spyder.py:1829 spyderlib\widgets\explorer.py:230
#: spyderlib\widgets\externalshell\baseshell.py:138
msgid "Run"
msgstr ""
@@ -568,7 +569,7 @@ msgid "<u>Note</u>: add <b>analysis:ignore</b> in a comment to ignore code/style
msgstr ""
#: spyderlib\plugins\editor.py:219
-#: spyderlib\widgets\sourcecode\codeeditor.py:1607
+#: spyderlib\widgets\sourcecode\codeeditor.py:1422
msgid "Code analysis"
msgstr ""
@@ -738,7 +739,7 @@ msgstr ""
msgid "Debug with winpdb"
msgstr ""
-#: spyderlib\plugins\editor.py:663 spyderlib\spyder.py:609
+#: spyderlib\plugins\editor.py:663 spyderlib\spyder.py:606
msgid "&Debug"
msgstr ""
@@ -791,7 +792,7 @@ msgid "Debugging control"
msgstr ""
#: spyderlib\plugins\editor.py:722 spyderlib\plugins\editor.py:1222
-#: spyderlib\spyder.py:604
+#: spyderlib\spyder.py:601
msgid "&Run"
msgstr ""
@@ -817,7 +818,7 @@ msgid "Run again last file"
msgstr ""
#: spyderlib\plugins\editor.py:748
-#: spyderlib\widgets\sourcecode\codeeditor.py:2243
+#: spyderlib\widgets\sourcecode\codeeditor.py:2058
msgid "Run &selection"
msgstr ""
@@ -900,12 +901,12 @@ msgid "Go to next cursor position"
msgstr ""
#: spyderlib\plugins\editor.py:823
-#: spyderlib\widgets\sourcecode\codeeditor.py:2237
+#: spyderlib\widgets\sourcecode\codeeditor.py:2052
msgid "Comment"
msgstr ""
#: spyderlib\plugins\editor.py:823
-#: spyderlib\widgets\sourcecode\codeeditor.py:2237
+#: spyderlib\widgets\sourcecode\codeeditor.py:2052
msgid "Uncomment"
msgstr ""
@@ -1001,47 +1002,47 @@ msgstr ""
msgid "Open &recent"
msgstr ""
-#: spyderlib\plugins\editor.py:1210 spyderlib\spyder.py:585
+#: spyderlib\plugins\editor.py:1210 spyderlib\spyder.py:582
msgid "File toolbar"
msgstr ""
-#: spyderlib\plugins\editor.py:1211 spyderlib\spyder.py:595
+#: spyderlib\plugins\editor.py:1211 spyderlib\spyder.py:592
msgid "Search toolbar"
msgstr ""
-#: spyderlib\plugins\editor.py:1212 spyderlib\spyder.py:600
+#: spyderlib\plugins\editor.py:1212 spyderlib\spyder.py:597
msgid "Source toolbar"
msgstr ""
-#: spyderlib\plugins\editor.py:1213 spyderlib\spyder.py:605
+#: spyderlib\plugins\editor.py:1213 spyderlib\spyder.py:602
msgid "Run toolbar"
msgstr ""
-#: spyderlib\plugins\editor.py:1214 spyderlib\spyder.py:610
+#: spyderlib\plugins\editor.py:1214 spyderlib\spyder.py:607
msgid "Debug toolbar"
msgstr ""
-#: spyderlib\plugins\editor.py:1215 spyderlib\spyder.py:590
+#: spyderlib\plugins\editor.py:1215 spyderlib\spyder.py:587
msgid "Edit toolbar"
msgstr ""
-#: spyderlib\plugins\editor.py:1218 spyderlib\spyder.py:582
+#: spyderlib\plugins\editor.py:1218 spyderlib\spyder.py:579
msgid "&File"
msgstr ""
-#: spyderlib\plugins\editor.py:1219 spyderlib\spyder.py:589
+#: spyderlib\plugins\editor.py:1219 spyderlib\spyder.py:586
msgid "&Edit"
msgstr ""
-#: spyderlib\plugins\editor.py:1220 spyderlib\spyder.py:594
+#: spyderlib\plugins\editor.py:1220 spyderlib\spyder.py:591
msgid "&Search"
msgstr ""
-#: spyderlib\plugins\editor.py:1221 spyderlib\spyder.py:599
+#: spyderlib\plugins\editor.py:1221 spyderlib\spyder.py:596
msgid "Sour&ce"
msgstr ""
-#: spyderlib\plugins\editor.py:1223 spyderlib\spyder.py:617
+#: spyderlib\plugins\editor.py:1223 spyderlib\spyder.py:614
msgid "&Tools"
msgstr ""
@@ -1073,7 +1074,7 @@ msgstr ""
msgid "File explorer"
msgstr ""
-#: spyderlib\plugins\explorer.py:61 spyderlib\plugins\inspector.py:350
+#: spyderlib\plugins\explorer.py:61 spyderlib\plugins\inspector.py:351
#: spyderlib\plugins\projectexplorer.py:59
msgid "Set font style"
msgstr ""
@@ -1084,9 +1085,9 @@ msgstr ""
#: spyderlib\plugins\externalconsole.py:60
#: spyderlib\plugins\externalconsole.py:1083
-#: spyderlib\plugins\inspector.py:380
+#: spyderlib\plugins\inspector.py:381
#: spyderlib\widgets\externalshell\baseshell.py:106
-#: spyderlib\widgets\ipython.py:412
+#: spyderlib\widgets\ipython.py:454
msgid "Console"
msgstr ""
@@ -1337,8 +1338,8 @@ msgid "You can't close this kernel because it has one or more consoles connected
msgstr ""
#: spyderlib\plugins\externalconsole.py:686
-#: spyderlib\plugins\ipythonconsole.py:480 spyderlib\spyder.py:1327
-#: spyderlib\spyder.py:1345 spyderlib\utils\environ.py:95
+#: spyderlib\plugins\ipythonconsole.py:480 spyderlib\spyder.py:1323
+#: spyderlib\spyder.py:1341 spyderlib\utils\environ.py:95
#: spyderlib\utils\environ.py:108
msgid "Warning"
msgstr ""
@@ -1447,11 +1448,11 @@ msgstr ""
msgid "Scroll automatically to last entry"
msgstr ""
-#: spyderlib\plugins\history.py:102 spyderlib\plugins\inspector.py:433
-#: spyderlib\widgets\editor.py:661 spyderlib\widgets\explorer.py:990
+#: spyderlib\plugins\history.py:102 spyderlib\plugins\inspector.py:435
+#: spyderlib\widgets\editor.py:677 spyderlib\widgets\explorer.py:990
#: spyderlib\widgets\externalshell\baseshell.py:151
#: spyderlib\widgets\externalshell\namespacebrowser.py:231
-#: spyderlib\widgets\ipython.py:449
+#: spyderlib\widgets\ipython.py:491
msgid "Options"
msgstr ""
@@ -1495,91 +1496,91 @@ msgstr ""
msgid "The Object Inspector 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 ""
-#: spyderlib\plugins\inspector.py:136
+#: spyderlib\plugins\inspector.py:137
msgid "Python Console"
msgstr ""
-#: spyderlib\plugins\inspector.py:138
+#: spyderlib\plugins\inspector.py:139
msgid "IPython Console"
msgstr ""
-#: spyderlib\plugins\inspector.py:151
+#: spyderlib\plugins\inspector.py:152
msgid "Additional features"
msgstr ""
-#: spyderlib\plugins\inspector.py:152
+#: spyderlib\plugins\inspector.py:153
msgid "Render mathematical equations"
msgstr ""
-#: spyderlib\plugins\inspector.py:158
+#: spyderlib\plugins\inspector.py:159
msgid "This feature requires Sphinx 1.1 or superior."
msgstr ""
-#: spyderlib\plugins\inspector.py:160
+#: spyderlib\plugins\inspector.py:161
msgid "Sphinx %s is currently installed."
msgstr ""
-#: spyderlib\plugins\inspector.py:334
+#: spyderlib\plugins\inspector.py:335
msgid "No documentation available"
msgstr ""
-#: spyderlib\plugins\inspector.py:373
+#: spyderlib\plugins\inspector.py:374
msgid "Source"
msgstr ""
-#: spyderlib\plugins\inspector.py:388 spyderlib\widgets\dicteditor.py:162
+#: spyderlib\plugins\inspector.py:390 spyderlib\widgets\dicteditor.py:162
msgid "Object"
msgstr ""
-#: spyderlib\plugins\inspector.py:403
+#: spyderlib\plugins\inspector.py:405
msgid "Plain Text"
msgstr ""
-#: spyderlib\plugins\inspector.py:407
+#: spyderlib\plugins\inspector.py:409
msgid "Show Source"
msgstr ""
-#: spyderlib\plugins\inspector.py:411
+#: spyderlib\plugins\inspector.py:413
msgid "Rich Text"
msgstr ""
-#: spyderlib\plugins\inspector.py:421
+#: spyderlib\plugins\inspector.py:423
msgid "Automatic import"
msgstr ""
-#: spyderlib\plugins\inspector.py:476 spyderlib\plugins\inspector.py:885
+#: spyderlib\plugins\inspector.py:478 spyderlib\plugins\inspector.py:887
msgid "Object inspector"
msgstr ""
-#: spyderlib\plugins\inspector.py:599
+#: spyderlib\plugins\inspector.py:601
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 ""
-#: spyderlib\plugins\inspector.py:605
+#: spyderlib\plugins\inspector.py:607
msgid "Preferences > Object Inspector"
msgstr ""
-#: spyderlib\plugins\inspector.py:607
+#: spyderlib\plugins\inspector.py:609
msgid "Usage"
msgstr ""
-#: spyderlib\plugins\inspector.py:613
+#: spyderlib\plugins\inspector.py:615
msgid "Please consider installing Sphinx to get documentation rendered in rich text."
msgstr ""
-#: spyderlib\plugins\inspector.py:846
+#: spyderlib\plugins\inspector.py:848
msgid "Lock"
msgstr ""
-#: spyderlib\plugins\inspector.py:846
+#: spyderlib\plugins\inspector.py:848
msgid "Unlock"
msgstr ""
-#: spyderlib\plugins\inspector.py:886
+#: spyderlib\plugins\inspector.py:888
msgid "The following error occured when calling <b>Sphinx %s</b>. <br>Incompatible Sphinx version or doc string decoding failed.<br><br>Error message:<br>%s"
msgstr ""
-#: spyderlib\plugins\inspector.py:930
+#: spyderlib\plugins\inspector.py:932
msgid "No source code available."
msgstr ""
@@ -1620,10 +1621,6 @@ msgid ""
"Note: Use the Q key to get out of the pager."
msgstr ""
-#: spyderlib\plugins\ipythonconsole.py:84
-msgid "Display balloon tips"
-msgstr ""
-
#: spyderlib\plugins\ipythonconsole.py:85
msgid "Ask for confirmation before closing"
msgstr ""
@@ -2237,7 +2234,7 @@ msgstr ""
msgid "IPython Console integration"
msgstr ""
-#: spyderlib\spyder.py:125 spyderlib\spyder.py:455
+#: spyderlib\spyder.py:125
msgid "Initializing..."
msgstr ""
@@ -2261,7 +2258,7 @@ msgstr ""
msgid "Numpy and Scipy documentation"
msgstr ""
-#: spyderlib\spyder.py:297 spyderlib\spyder.py:989
+#: spyderlib\spyder.py:297 spyderlib\spyder.py:971
msgid "Matplotlib documentation"
msgstr ""
@@ -2285,342 +2282,350 @@ msgstr ""
msgid "Save current session and quit application"
msgstr ""
-#: spyderlib\spyder.py:516
-msgid "Close current dockwidget"
+#: spyderlib\spyder.py:513
+msgid "Close current plugin"
msgstr ""
-#: spyderlib\spyder.py:522
+#: spyderlib\spyder.py:519
msgid "&Find text"
msgstr ""
-#: spyderlib\spyder.py:528
+#: spyderlib\spyder.py:525
msgid "Find &next"
msgstr ""
-#: spyderlib\spyder.py:534
+#: spyderlib\spyder.py:531
msgid "Find &previous"
msgstr ""
-#: spyderlib\spyder.py:539
+#: spyderlib\spyder.py:536
msgid "&Replace text"
msgstr ""
-#: spyderlib\spyder.py:554 spyderlib\widgets\sourcecode\codeeditor.py:2213
+#: spyderlib\spyder.py:551 spyderlib\widgets\sourcecode\codeeditor.py:2028
msgid "Undo"
msgstr ""
-#: spyderlib\spyder.py:556 spyderlib\widgets\sourcecode\codeeditor.py:2216
+#: spyderlib\spyder.py:553 spyderlib\widgets\sourcecode\codeeditor.py:2031
msgid "Redo"
msgstr ""
-#: spyderlib\spyder.py:557 spyderlib\widgets\arrayeditor.py:327
-#: spyderlib\widgets\dicteditor.py:563 spyderlib\widgets\shell.py:121
-#: spyderlib\widgets\sourcecode\codeeditor.py:2222
+#: spyderlib\spyder.py:554 spyderlib\widgets\arrayeditor.py:327
+#: spyderlib\widgets\dicteditor.py:563 spyderlib\widgets\shell.py:122
+#: spyderlib\widgets\sourcecode\codeeditor.py:2037
msgid "Copy"
msgstr ""
-#: spyderlib\spyder.py:559 spyderlib\widgets\shell.py:117
-#: spyderlib\widgets\sourcecode\codeeditor.py:2219
+#: spyderlib\spyder.py:556 spyderlib\widgets\shell.py:118
+#: spyderlib\widgets\sourcecode\codeeditor.py:2034
msgid "Cut"
msgstr ""
-#: spyderlib\spyder.py:560 spyderlib\widgets\dicteditor.py:560
-#: spyderlib\widgets\shell.py:125
-#: spyderlib\widgets\sourcecode\codeeditor.py:2225
+#: spyderlib\spyder.py:557 spyderlib\widgets\dicteditor.py:560
+#: spyderlib\widgets\shell.py:126
+#: spyderlib\widgets\sourcecode\codeeditor.py:2040
msgid "Paste"
msgstr ""
-#: spyderlib\spyder.py:562 spyderlib\widgets\explorer.py:453
-#: spyderlib\widgets\projectexplorer.py:1002 spyderlib\widgets\shell.py:134
-#: spyderlib\widgets\sourcecode\codeeditor.py:2228
+#: spyderlib\spyder.py:559 spyderlib\widgets\explorer.py:453
+#: spyderlib\widgets\projectexplorer.py:1002 spyderlib\widgets\shell.py:135
+#: spyderlib\widgets\sourcecode\codeeditor.py:2043
msgid "Delete"
msgstr ""
-#: spyderlib\spyder.py:565 spyderlib\widgets\shell.py:138
-#: spyderlib\widgets\sourcecode\codeeditor.py:2232
+#: spyderlib\spyder.py:562 spyderlib\widgets\shell.py:139
+#: spyderlib\widgets\sourcecode\codeeditor.py:2047
msgid "Select All"
msgstr ""
-#: spyderlib\spyder.py:614
+#: spyderlib\spyder.py:611
msgid "C&onsoles"
msgstr ""
-#: spyderlib\spyder.py:620
+#: spyderlib\spyder.py:617
msgid "&View"
msgstr ""
-#: spyderlib\spyder.py:623
+#: spyderlib\spyder.py:620
msgid "&Help"
msgstr ""
-#: spyderlib\spyder.py:628
+#: spyderlib\spyder.py:625
msgid "Welcome to Spyder!"
msgstr ""
-#: spyderlib\spyder.py:633
+#: spyderlib\spyder.py:630
msgid "Pre&ferences"
msgstr ""
-#: spyderlib\spyder.py:641 spyderlib\widgets\pathmanager.py:45
+#: spyderlib\spyder.py:638 spyderlib\widgets\pathmanager.py:45
#: spyderlib\widgets\projectexplorer.py:593
msgid "PYTHONPATH manager"
msgstr ""
-#: spyderlib\spyder.py:644
+#: spyderlib\spyder.py:641
msgid "Python Path Manager"
msgstr ""
-#: spyderlib\spyder.py:647
+#: spyderlib\spyder.py:644
msgid "Update module names list"
msgstr ""
-#: spyderlib\spyder.py:649
+#: spyderlib\spyder.py:646
msgid "Refresh list of module names available in PYTHONPATH"
msgstr ""
-#: spyderlib\spyder.py:655
+#: spyderlib\spyder.py:651
msgid "Current user environment variables..."
msgstr ""
-#: spyderlib\spyder.py:657
+#: spyderlib\spyder.py:653
msgid "Show and edit current user environment variables in Windows registry (i.e. for all sessions)"
msgstr ""
-#: spyderlib\spyder.py:664 spyderlib\spyder.py:1064
+#: spyderlib\spyder.py:661 spyderlib\spyder.py:1063
msgid "External Tools"
msgstr ""
-#: spyderlib\spyder.py:668
+#: spyderlib\spyder.py:665
msgid "Python(x,y) launcher"
msgstr ""
-#: spyderlib\spyder.py:679
+#: spyderlib\spyder.py:672
msgid "WinPython control panel"
msgstr ""
-#: spyderlib\spyder.py:692
+#: spyderlib\spyder.py:681
msgid "Qt Designer"
msgstr ""
-#: spyderlib\spyder.py:697
+#: spyderlib\spyder.py:686
msgid "Qt Linguist"
msgstr ""
-#: spyderlib\spyder.py:703
+#: spyderlib\spyder.py:692
msgid "Qt examples"
msgstr ""
-#: spyderlib\spyder.py:721
+#: spyderlib\spyder.py:710
msgid "guidata examples"
msgstr ""
-#: spyderlib\spyder.py:729
+#: spyderlib\spyder.py:718
msgid "guiqwt examples"
msgstr ""
-#: spyderlib\spyder.py:734
+#: spyderlib\spyder.py:723
msgid "Sift"
msgstr ""
-#: spyderlib\spyder.py:742
+#: spyderlib\spyder.py:731
msgid "ViTables"
msgstr ""
-#: spyderlib\spyder.py:756
+#: spyderlib\spyder.py:745
msgid "Fullscreen mode"
msgstr ""
-#: spyderlib\spyder.py:768
+#: spyderlib\spyder.py:757
msgid "Main toolbar"
msgstr ""
-#: spyderlib\spyder.py:789
+#: spyderlib\spyder.py:779
msgid "Loading object inspector..."
msgstr ""
-#: spyderlib\spyder.py:796
+#: spyderlib\spyder.py:786
msgid "Loading outline explorer..."
msgstr ""
-#: spyderlib\spyder.py:804
+#: spyderlib\spyder.py:794
msgid "Loading editor..."
msgstr ""
-#: spyderlib\spyder.py:829
+#: spyderlib\spyder.py:819
msgid "Loading file explorer..."
msgstr ""
-#: spyderlib\spyder.py:836
+#: spyderlib\spyder.py:826
msgid "Loading history plugin..."
msgstr ""
-#: spyderlib\spyder.py:847
+#: spyderlib\spyder.py:837
msgid "Loading online help..."
msgstr ""
-#: spyderlib\spyder.py:853
+#: spyderlib\spyder.py:843
msgid "Loading project explorer..."
msgstr ""
-#: spyderlib\spyder.py:864
+#: spyderlib\spyder.py:854
msgid "Loading external console..."
msgstr ""
-#: spyderlib\spyder.py:873
+#: spyderlib\spyder.py:863
msgid "Loading namespace browser..."
msgstr ""
-#: spyderlib\spyder.py:880
+#: spyderlib\spyder.py:870
msgid "Loading IPython console..."
msgstr ""
-#: spyderlib\spyder.py:891
+#: spyderlib\spyder.py:881
msgid "Setting up main window..."
msgstr ""
-#: spyderlib\spyder.py:895
-msgid "About %s..."
+#: spyderlib\spyder.py:900
+msgid "Spyder documentation"
msgstr ""
-#: spyderlib\spyder.py:898
-msgid "Optional dependencies..."
+#: spyderlib\spyder.py:904
+msgid "Report issue..."
msgstr ""
-#: spyderlib\spyder.py:901
-msgid "Report issue..."
+#: spyderlib\spyder.py:908
+msgid "Spyder support..."
msgstr ""
-#: spyderlib\spyder.py:922
-msgid "Spyder documentation"
+#: spyderlib\spyder.py:910
+msgid "Optional dependencies..."
msgstr ""
-#: spyderlib\spyder.py:928
+#: spyderlib\spyder.py:917
msgid "Python documentation"
msgstr ""
-#: spyderlib\spyder.py:935
-msgid "IPython Help"
+#: spyderlib\spyder.py:923 spyderlib\spyder.py:963
+msgid "IPython documentation"
msgstr ""
-#: spyderlib\spyder.py:936
+#: spyderlib\spyder.py:924
msgid "Intro to IPython"
msgstr ""
-#: spyderlib\spyder.py:938
-msgid "Quick Reference"
+#: spyderlib\spyder.py:926
+msgid "Quick reference"
msgstr ""
-#: spyderlib\spyder.py:940
+#: spyderlib\spyder.py:928
msgid "Console help"
msgstr ""
-#: spyderlib\spyder.py:946
-msgid "Qt Help"
-msgstr ""
-
-#: spyderlib\spyder.py:950
-msgid "Web Resources"
-msgstr ""
-
-#: spyderlib\spyder.py:979
+#: spyderlib\spyder.py:961
msgid "Python(x,y) documentation folder"
msgstr ""
-#: spyderlib\spyder.py:981
-msgid "IPython documentation"
-msgstr ""
-
-#: spyderlib\spyder.py:983
+#: spyderlib\spyder.py:965
msgid "guidata documentation"
msgstr ""
-#: spyderlib\spyder.py:986
+#: spyderlib\spyder.py:968
msgid "guiqwt documentation"
msgstr ""
-#: spyderlib\spyder.py:992
+#: spyderlib\spyder.py:974
msgid "NumPy documentation"
msgstr ""
-#: spyderlib\spyder.py:994
+#: spyderlib\spyder.py:976
msgid "NumPy reference guide"
msgstr ""
-#: spyderlib\spyder.py:996
+#: spyderlib\spyder.py:978
msgid "NumPy user guide"
msgstr ""
-#: spyderlib\spyder.py:998
+#: spyderlib\spyder.py:980
msgid "SciPy documentation"
msgstr ""
-#: spyderlib\spyder.py:1026
-msgid "Windows and toolbars"
+#: spyderlib\spyder.py:987
+msgid "Installed Python modules"
+msgstr ""
+
+#: spyderlib\spyder.py:991
+msgid "Online documentation"
+msgstr ""
+
+#: spyderlib\spyder.py:996
+msgid "Qt documentation"
+msgstr ""
+
+#: spyderlib\spyder.py:1002
+msgid "About %s..."
msgstr ""
-#: spyderlib\spyder.py:1030
+#: spyderlib\spyder.py:1023
+msgid "Windows"
+msgstr ""
+
+#: spyderlib\spyder.py:1024
+msgid "Toolbars"
+msgstr ""
+
+#: spyderlib\spyder.py:1027
msgid "Reset window layout"
msgstr ""
-#: spyderlib\spyder.py:1032
+#: spyderlib\spyder.py:1029
msgid "Custom window layouts"
msgstr ""
-#: spyderlib\spyder.py:1038
+#: spyderlib\spyder.py:1035
msgid "Switch to/from layout %d"
msgstr ""
-#: spyderlib\spyder.py:1044
+#: spyderlib\spyder.py:1041
msgid "Set layout %d"
msgstr ""
-#: spyderlib\spyder.py:1054
+#: spyderlib\spyder.py:1051
msgid "Attached console window (debugging)"
msgstr ""
-#: spyderlib\spyder.py:1328
+#: spyderlib\spyder.py:1324
msgid ""
"Window layout will be reset to default settings: this affects window position, size and dockwidgets.\n"
"Do you want to continue?"
msgstr ""
-#: spyderlib\spyder.py:1346
+#: spyderlib\spyder.py:1342
msgid "Quick switch layout #%d has not yet been defined."
msgstr ""
-#: spyderlib\spyder.py:1537 spyderlib\spyder.py:1538
+#: spyderlib\spyder.py:1568 spyderlib\spyder.py:1569
msgid "Maximize current plugin"
msgstr ""
-#: spyderlib\spyder.py:1541
+#: spyderlib\spyder.py:1572
msgid "Restore current plugin"
msgstr ""
-#: spyderlib\spyder.py:1542
+#: spyderlib\spyder.py:1573
msgid "Restore plugin to its original size"
msgstr ""
-#: spyderlib\spyder.py:1613
+#: spyderlib\spyder.py:1644
msgid "(not installed)"
msgstr ""
-#: spyderlib\spyder.py:1631
+#: spyderlib\spyder.py:1662
msgid "About %s"
msgstr ""
-#: spyderlib\spyder.py:1796
+#: spyderlib\spyder.py:1830
msgid "Running an external system terminal is not supported on platform %s."
msgstr ""
-#: spyderlib\spyder.py:1997
+#: spyderlib\spyder.py:2031
msgid "Open session"
msgstr ""
-#: spyderlib\spyder.py:1998 spyderlib\spyder.py:2009
+#: spyderlib\spyder.py:2032 spyderlib\spyder.py:2043
msgid "Spyder sessions"
msgstr ""
-#: spyderlib\spyder.py:2008
+#: spyderlib\spyder.py:2042
msgid "Save session"
msgstr ""
@@ -2645,6 +2650,10 @@ msgstr ""
msgid "It was not possible to generate rich text help for this object.</br>Please see it in plain text."
msgstr ""
+#: spyderlib\utils\introspection\rope_plugin.py:34
+msgid "Editor's code completion, go-to-definition and help"
+msgstr ""
+
#: spyderlib\utils\iofuncs.py:331
msgid "Supported files"
msgstr ""
@@ -2772,12 +2781,12 @@ msgid "For performance reasons, changes applied to masked array won't be reflect
msgstr ""
#: spyderlib\widgets\browser.py:30
-#: spyderlib\widgets\sourcecode\codeeditor.py:2248
+#: spyderlib\widgets\sourcecode\codeeditor.py:2063
msgid "Zoom out"
msgstr ""
#: spyderlib\widgets\browser.py:33
-#: spyderlib\widgets\sourcecode\codeeditor.py:2245
+#: spyderlib\widgets\sourcecode\codeeditor.py:2060
msgid "Zoom in"
msgstr ""
@@ -2836,11 +2845,11 @@ msgstr ""
msgid "Optional Dependencies"
msgstr ""
-#: spyderlib\widgets\dependencies.py:133
+#: spyderlib\widgets\dependencies.py:134
msgid "Spyder depends on several Python modules to provide additional functionality for its plugins. The table below shows the required and installed versions (if any) of all of them.<br><br>Although Spyder can work without any of these modules, it's strongly recommended that at least you try to install <b>%s</b> and <b>%s</b> to have a much better experience."
msgstr ""
-#: spyderlib\widgets\dependencies.py:148
+#: spyderlib\widgets\dependencies.py:149
msgid "Copy to clipboard"
msgstr ""
@@ -2988,107 +2997,107 @@ msgstr ""
msgid "Nothing to be imported from clipboard."
msgstr ""
-#: spyderlib\widgets\editor.py:69 spyderlib\widgets\editor.py:557
+#: spyderlib\widgets\editor.py:70 spyderlib\widgets\editor.py:572
msgid "File list management"
msgstr ""
-#: spyderlib\widgets\editor.py:73
+#: spyderlib\widgets\editor.py:74
msgid "Filter:"
msgstr ""
-#: spyderlib\widgets\editor.py:78
+#: spyderlib\widgets\editor.py:79
msgid "(press <b>Enter</b> to edit file)"
msgstr ""
-#: spyderlib\widgets\editor.py:93
+#: spyderlib\widgets\editor.py:94
msgid "&Edit file"
msgstr ""
-#: spyderlib\widgets\editor.py:102
+#: spyderlib\widgets\editor.py:103
msgid "&Close file"
msgstr ""
-#: spyderlib\widgets\editor.py:110
+#: spyderlib\widgets\editor.py:111
msgid "Hint: press <b>Alt</b> to show accelerators"
msgstr ""
-#: spyderlib\widgets\editor.py:560
+#: spyderlib\widgets\editor.py:575
msgid "Copy path to clipboard"
msgstr ""
-#: spyderlib\widgets\editor.py:1099
+#: spyderlib\widgets\editor.py:1115
msgid "Temporary file"
msgstr ""
-#: spyderlib\widgets\editor.py:1196
+#: spyderlib\widgets\editor.py:1212
msgid "New window"
msgstr ""
-#: spyderlib\widgets\editor.py:1197
+#: spyderlib\widgets\editor.py:1213
msgid "Create a new editor window"
msgstr ""
-#: spyderlib\widgets\editor.py:1200
+#: spyderlib\widgets\editor.py:1216
msgid "Split vertically"
msgstr ""
-#: spyderlib\widgets\editor.py:1202
+#: spyderlib\widgets\editor.py:1218
msgid "Split vertically this editor window"
msgstr ""
-#: spyderlib\widgets\editor.py:1204
+#: spyderlib\widgets\editor.py:1220
msgid "Split horizontally"
msgstr ""
-#: spyderlib\widgets\editor.py:1206
+#: spyderlib\widgets\editor.py:1222
msgid "Split horizontally this editor window"
msgstr ""
-#: spyderlib\widgets\editor.py:1208
+#: spyderlib\widgets\editor.py:1224
msgid "Close this panel"
msgstr ""
-#: spyderlib\widgets\editor.py:1340
+#: spyderlib\widgets\editor.py:1356
msgid "<b>%s</b> has been modified.<br>Do you want to save changes?"
msgstr ""
-#: spyderlib\widgets\editor.py:1403
+#: spyderlib\widgets\editor.py:1419
msgid "Save"
msgstr ""
-#: spyderlib\widgets\editor.py:1404
+#: spyderlib\widgets\editor.py:1420
msgid "<b>Unable to save script '%s'</b><br><br>Error message:<br>%s"
msgstr ""
-#: spyderlib\widgets\editor.py:1426
+#: spyderlib\widgets\editor.py:1442
msgid "Save Python script"
msgstr ""
-#: spyderlib\widgets\editor.py:1647
+#: spyderlib\widgets\editor.py:1663
msgid "<b>%s</b> is unavailable (this file may have been removed, moved or renamed outside Spyder).<br>Do you want to close it?"
msgstr ""
-#: spyderlib\widgets\editor.py:1667
+#: spyderlib\widgets\editor.py:1683
msgid "<b>%s</b> has been modified outside Spyder.<br>Do you want to reload it and lose all your changes?"
msgstr ""
-#: spyderlib\widgets\editor.py:1763
+#: spyderlib\widgets\editor.py:1779
msgid "All changes to <b>%s</b> will be lost.<br>Do you want to revert file from disk?"
msgstr ""
-#: spyderlib\widgets\editor.py:1902
+#: spyderlib\widgets\editor.py:1919
msgid "Loading %s..."
msgstr ""
-#: spyderlib\widgets\editor.py:1912
+#: spyderlib\widgets\editor.py:1929
msgid "<b>%s</b> contains mixed end-of-line characters.<br>Spyder will fix this automatically."
msgstr ""
-#: spyderlib\widgets\editor.py:2260
+#: spyderlib\widgets\editor.py:2277
msgid "Close window"
msgstr ""
-#: spyderlib\widgets\editor.py:2262
+#: spyderlib\widgets\editor.py:2279
msgid "Close this window"
msgstr ""
@@ -3305,7 +3314,7 @@ msgid "Terminated."
msgstr ""
#: spyderlib\widgets\externalshell\baseshell.py:235
-#: spyderlib\widgets\mixins.py:511
+#: spyderlib\widgets\ipython.py:336 spyderlib\widgets\mixins.py:599
msgid "Arguments"
msgstr ""
@@ -3425,7 +3434,7 @@ msgid "No argument"
msgstr ""
#: spyderlib\widgets\externalshell\pythonshell.py:524
-msgid "The console failed to start! That's all we know :(<br>Please close it and open a new one."
+msgid "The kernel failed to start!! That's all we know... Please close this console and open a new one."
msgstr ""
#: spyderlib\widgets\externalshell\pythonshell.py:528
@@ -3666,90 +3675,86 @@ msgstr ""
msgid "<b>Unable to proceed to next step</b><br><br>Please check your entries.<br><br>Error message:<br>%s"
msgstr ""
-#: spyderlib\widgets\internalshell.py:248
+#: spyderlib\widgets\internalshell.py:250
msgid "Help..."
msgstr ""
-#: spyderlib\widgets\internalshell.py:255
+#: spyderlib\widgets\internalshell.py:257
msgid "Help"
msgstr ""
-#: spyderlib\widgets\internalshell.py:264
+#: spyderlib\widgets\internalshell.py:266
msgid "Shell special commands:"
msgstr ""
-#: spyderlib\widgets\internalshell.py:265
+#: spyderlib\widgets\internalshell.py:267
msgid "Internal editor:"
msgstr ""
-#: spyderlib\widgets\internalshell.py:266
+#: spyderlib\widgets\internalshell.py:268
msgid "External editor:"
msgstr ""
-#: spyderlib\widgets\internalshell.py:267
+#: spyderlib\widgets\internalshell.py:269
msgid "Run script:"
msgstr ""
-#: spyderlib\widgets\internalshell.py:268
+#: spyderlib\widgets\internalshell.py:270
msgid "Remove references:"
msgstr ""
-#: spyderlib\widgets\internalshell.py:269
+#: spyderlib\widgets\internalshell.py:271
msgid "System commands:"
msgstr ""
-#: spyderlib\widgets\internalshell.py:270
+#: spyderlib\widgets\internalshell.py:272
msgid "Python help:"
msgstr ""
-#: spyderlib\widgets\internalshell.py:271
+#: spyderlib\widgets\internalshell.py:273
msgid "GUI-based editor:"
msgstr ""
-#: spyderlib\widgets\ipython.py:398
+#: spyderlib\widgets\ipython.py:440
msgid "An error ocurred while starting the kernel!"
msgstr ""
-#: spyderlib\widgets\ipython.py:426
+#: spyderlib\widgets\ipython.py:468
msgid "Interrupt kernel"
msgstr ""
-#: spyderlib\widgets\ipython.py:429
+#: spyderlib\widgets\ipython.py:471
msgid "Restart kernel"
msgstr ""
-#: spyderlib\widgets\ipython.py:461
+#: spyderlib\widgets\ipython.py:503
msgid "Inspect current object"
msgstr ""
-#: spyderlib\widgets\ipython.py:465
+#: spyderlib\widgets\ipython.py:507
msgid "Clear line or block"
msgstr ""
-#: spyderlib\widgets\ipython.py:469
+#: spyderlib\widgets\ipython.py:511
msgid "Clear console"
msgstr ""
-#: spyderlib\widgets\ipython.py:512
+#: spyderlib\widgets\ipython.py:555
msgid "It seems the kernel died unexpectedly. Use 'Restart kernel' to continue using this console."
msgstr ""
-#: spyderlib\widgets\ipython.py:524
+#: spyderlib\widgets\ipython.py:567
msgid "Kernel process is either remote or unspecified. Cannot interrupt"
msgstr ""
-#: spyderlib\widgets\ipython.py:533
+#: spyderlib\widgets\ipython.py:576
msgid "Kernel process is either remote or unspecified. Cannot restart."
msgstr ""
-#: spyderlib\widgets\ipython.py:550
+#: spyderlib\widgets\ipython.py:593
msgid "Connecting to kernel..."
msgstr ""
-#: spyderlib\widgets\mixins.py:516
-msgid "Documentation"
-msgstr ""
-
#: spyderlib\widgets\onecolumntree.py:63
msgid "Collapse all"
msgstr ""
@@ -4005,67 +4010,63 @@ msgstr ""
msgid "Module or package:"
msgstr ""
-#: spyderlib\widgets\shell.py:129
+#: spyderlib\widgets\shell.py:130
msgid "Save history log..."
msgstr ""
-#: spyderlib\widgets\shell.py:131
+#: spyderlib\widgets\shell.py:132
msgid "Save current history log (i.e. all inputs and outputs) in a text file"
msgstr ""
-#: spyderlib\widgets\shell.py:251
+#: spyderlib\widgets\shell.py:252
msgid "Save history log"
msgstr ""
-#: spyderlib\widgets\shell.py:254
+#: spyderlib\widgets\shell.py:255
msgid "History logs"
msgstr ""
-#: spyderlib\widgets\shell.py:265
+#: spyderlib\widgets\shell.py:266
msgid "<b>Unable to save file '%s'</b><br><br>Error message:<br>%s"
msgstr ""
-#: spyderlib\widgets\shell.py:690
+#: spyderlib\widgets\shell.py:691
msgid "Copy without prompts"
msgstr ""
-#: spyderlib\widgets\shell.py:693 spyderlib\widgets\shell.py:696
+#: spyderlib\widgets\shell.py:694 spyderlib\widgets\shell.py:697
msgid "Clear line"
msgstr ""
-#: spyderlib\widgets\shell.py:698
+#: spyderlib\widgets\shell.py:699
msgid "Clear shell"
msgstr ""
-#: spyderlib\widgets\shell.py:701
+#: spyderlib\widgets\shell.py:702
msgid "Clear shell contents ('cls' command)"
msgstr ""
-#: spyderlib\widgets\sourcecode\codeeditor.py:69
-msgid "Editor's code completion, go-to-definition and help"
-msgstr ""
-
-#: spyderlib\widgets\sourcecode\codeeditor.py:273
+#: spyderlib\widgets\sourcecode\codeeditor.py:83
msgid "Go to line:"
msgstr ""
-#: spyderlib\widgets\sourcecode\codeeditor.py:282
+#: spyderlib\widgets\sourcecode\codeeditor.py:92
msgid "Line count:"
msgstr ""
-#: spyderlib\widgets\sourcecode\codeeditor.py:1224
+#: spyderlib\widgets\sourcecode\codeeditor.py:1027
msgid "Breakpoint"
msgstr ""
-#: spyderlib\widgets\sourcecode\codeeditor.py:1225
+#: spyderlib\widgets\sourcecode\codeeditor.py:1028
msgid "Condition:"
msgstr ""
-#: spyderlib\widgets\sourcecode\codeeditor.py:1661
+#: spyderlib\widgets\sourcecode\codeeditor.py:1476
msgid "To do"
msgstr ""
-#: spyderlib\widgets\sourcecode\codeeditor.py:2240
+#: spyderlib\widgets\sourcecode\codeeditor.py:2055
msgid "Go to definition"
msgstr ""
diff --git a/spyderlib/plugins/__init__.py b/spyderlib/plugins/__init__.py
index f33af3e..99d81eb 100644
--- a/spyderlib/plugins/__init__.py
+++ b/spyderlib/plugins/__init__.py
@@ -23,7 +23,8 @@ from spyderlib.qt.QtGui import (QDockWidget, QWidget, QShortcut, QCursor,
from spyderlib.qt.QtCore import SIGNAL, Qt, QObject, Signal
# Local imports
-from spyderlib.utils.qthelpers import toggle_actions, get_icon
+from spyderlib.utils.qthelpers import toggle_actions, get_icon, create_action
+from spyderlib.baseconfig import _
from spyderlib.config import CONF
from spyderlib.userconfig import NoDefault
from spyderlib.guiconfig import get_font, set_font
@@ -80,6 +81,10 @@ class SpyderPluginMixin(object):
self.mainwindow = None
self.ismaximized = False
self.isvisible = False
+ # 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, ..."""
@@ -91,6 +96,7 @@ class SpyderPluginMixin(object):
if self.sig_option_changed is not None:
self.sig_option_changed.connect(self.set_option)
self.setWindowTitle(self.get_plugin_title())
+ self.create_toggle_view_action()
def on_first_registration(self):
"""Action to be performed on first plugin registration"""
@@ -225,6 +231,8 @@ class SpyderPluginMixin(object):
self.isvisible = enable and visible
if self.isvisible:
self.refresh_plugin() # To give focus to the plugin's widget
+ if self.dockwidget.isHidden():
+ self.toggle_view_action.setChecked(False)
def set_option(self, option, value):
"""
@@ -276,6 +284,22 @@ class SpyderPluginMixin(object):
if name not in names:
name = names[0]
self.set_option('color_scheme_name', name)
+
+ 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')
+ action = create_action(self, title, toggled=self.toggle_view)
+ self.toggle_view_action = action
+
+ def toggle_view(self, checked):
+ """Toggle view"""
+ if checked:
+ self.dockwidget.show()
+ self.dockwidget.raise_()
+ else:
+ self.dockwidget.hide()
class SpyderPluginWidget(QWidget, SpyderPluginMixin):
diff --git a/spyderlib/plugins/externalconsole.py b/spyderlib/plugins/externalconsole.py
index 887c552..ae58f62 100644
--- a/spyderlib/plugins/externalconsole.py
+++ b/spyderlib/plugins/externalconsole.py
@@ -732,7 +732,8 @@ class ExternalConsole(SpyderPluginWidget):
shellwidget.shell.set_spyder_breakpoints()
def start(self, fname, wdir=None, args='', interact=False, debug=False,
- python=True, ipykernel=False, ipyclient=None, python_args=''):
+ python=True, ipykernel=False, ipyclient=None,
+ give_ipyclient_focus=True, python_args=''):
"""
Start new console
@@ -936,8 +937,9 @@ class ExternalConsole(SpyderPluginWidget):
self.connect(shellwidget,
SIGNAL('create_ipython_client(QString)'),
lambda cf: self.register_ipyclient(cf,
- ipyclient,
- shellwidget))
+ ipyclient,
+ shellwidget,
+ give_focus=give_ipyclient_focus))
else:
shellwidget.emit(
SIGNAL("ipython_kernel_start_error(QString)"),
@@ -1024,7 +1026,8 @@ class ExternalConsole(SpyderPluginWidget):
name = "%s %s" % (text, kernel_id)
self.tabwidget.setTabText(index, name)
- def register_ipyclient(self, connection_file, ipyclient, kernel_widget):
+ def register_ipyclient(self, connection_file, ipyclient, kernel_widget,
+ give_focus=True):
"""
Register `ipyclient` to be connected to `kernel_widget`
"""
@@ -1047,7 +1050,9 @@ class ExternalConsole(SpyderPluginWidget):
ipyconsole = self.main.ipyconsole
ipyclient.connection_file = connection_file
ipyclient.kernel_widget_id = id(kernel_widget)
- ipyconsole.register_client(ipyclient, client_name, restart_kernel)
+ ipyconsole.register_client(ipyclient, client_name,
+ restart=restart_kernel,
+ give_focus=give_focus)
def open_file_in_spyder(self, fname, lineno):
"""Open file in Spyder's editor from remote process"""
@@ -1260,7 +1265,7 @@ class ExternalConsole(SpyderPluginWidget):
self.start(fname=None, wdir=to_text_string(wdir), args='',
interact=True, debug=False, python=True)
- def start_ipykernel(self, client, wdir=None):
+ def start_ipykernel(self, client, wdir=None, give_focus=True):
"""Start new IPython kernel"""
if not self.get_option('monitor/enabled'):
QMessageBox.warning(self, _('Open an IPython console'),
@@ -1273,7 +1278,7 @@ class ExternalConsole(SpyderPluginWidget):
self.main.ipyconsole.visibility_changed(True)
self.start(fname=None, wdir=to_text_string(wdir), args='',
interact=True, debug=False, python=True, ipykernel=True,
- ipyclient=client)
+ ipyclient=client, give_ipyclient_focus=give_focus)
def open_terminal(self, wdir=None):
"""Open terminal"""
diff --git a/spyderlib/plugins/inspector.py b/spyderlib/plugins/inspector.py
index 072f454..e436c3a 100644
--- a/spyderlib/plugins/inspector.py
+++ b/spyderlib/plugins/inspector.py
@@ -132,7 +132,8 @@ class ObjectInspectorConfigPage(PluginConfigPage):
connections_label.setWordWrap(True)
editor_box = self.create_checkbox(_("Editor"), 'connect/editor')
rope_installed = programs.is_module_installed('rope')
- editor_box.setEnabled(rope_installed)
+ jedi_installed = programs.is_module_installed('jedi', '>=0.7.0')
+ editor_box.setEnabled(rope_installed or jedi_installed)
python_box = self.create_checkbox(_("Python Console"),
'connect/python_console')
ipython_box = self.create_checkbox(_("IPython Console"),
@@ -365,7 +366,7 @@ class ObjectInspector(SpyderPluginWidget):
# locked = disable link with Console
self.locked = False
self._last_texts = [None, None]
- self._last_rope_doc = None
+ self._last_editor_doc = None
# Object name
layout_edit = QHBoxLayout()
@@ -380,7 +381,8 @@ class ObjectInspector(SpyderPluginWidget):
self.source_combo.addItems([_("Console"), _("Editor")])
self.connect(self.source_combo, SIGNAL('currentIndexChanged(int)'),
self.source_changed)
- if not programs.is_module_installed('rope'):
+ if (not programs.is_module_installed('rope') and
+ not programs.is_module_installed('jedi', '>=0.7.0')):
self.source_combo.hide()
source_label.hide()
layout_edit.addWidget(self.source_combo)
@@ -720,8 +722,8 @@ class ObjectInspector(SpyderPluginWidget):
def force_refresh(self):
if self.source_is_console():
self.set_object_text(None, force_refresh=True)
- elif self._last_rope_doc is not None:
- self.set_rope_doc(self._last_rope_doc, 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 Object Inspector"""
@@ -749,15 +751,15 @@ class ObjectInspector(SpyderPluginWidget):
if self.dockwidget is not None:
self.dockwidget.blockSignals(False)
- def set_rope_doc(self, doc, force_refresh=False):
+ def set_editor_doc(self, doc, force_refresh=False):
"""
Use the object inspector to show docstring dictionary computed
- with rope from the Editor plugin
+ with introspection plugin from the Editor plugin
"""
if (self.locked and not force_refresh):
return
self.switch_to_editor_source()
- self._last_rope_doc = doc
+ self._last_editor_doc = doc
self.object_edit.setText(doc['obj_text'])
if self.rich_help:
diff --git a/spyderlib/plugins/ipythonconsole.py b/spyderlib/plugins/ipythonconsole.py
index 01cbd63..ed3bffc 100644
--- a/spyderlib/plugins/ipythonconsole.py
+++ b/spyderlib/plugins/ipythonconsole.py
@@ -494,12 +494,12 @@ class IPythonConsole(SpyderPluginWidget):
if client is not None:
client.shellwidget.write_to_stdin(line)
- def create_new_client(self):
+ def create_new_client(self, give_focus=True):
"""Create a new client"""
client = IPythonClient(self, history_filename='history.py',
menu_actions=self.menu_actions)
self.add_tab(client, name=client.get_name())
- self.main.extconsole.start_ipykernel(client)
+ self.main.extconsole.start_ipykernel(client, give_focus=give_focus)
def get_plugin_actions(self):
"""Return a list of actions related to plugin"""
@@ -798,10 +798,10 @@ class IPythonConsole(SpyderPluginWidget):
ip_cfg._merge(spy_cfg)
return ip_cfg
- def register_client(self, client, name, restart=False):
+ def register_client(self, client, name, restart=False, give_focus=True):
"""Register new IPython client"""
self.connect_client_to_kernel(client)
- client.show_shellwidget()
+ client.show_shellwidget(give_focus=give_focus)
client.name = name
# If we are restarting the kernel we just need to rename the client tab
@@ -892,7 +892,7 @@ class IPythonConsole(SpyderPluginWidget):
def open_client_at_startup(self):
if self.get_option('open_ipython_at_startup', False):
- self.create_new_client()
+ self.create_new_client(give_focus=False)
def close_related_ipyclients(self, client):
"""Close all IPython clients related to *client*, except itself"""
diff --git a/spyderlib/spyder.py b/spyderlib/spyder.py
index 8123b14..76316ce 100644
--- a/spyderlib/spyder.py
+++ b/spyderlib/spyder.py
@@ -140,7 +140,7 @@ from spyderlib.userconfig import NoDefault
from spyderlib.utils import encoding, programs
from spyderlib.utils.iofuncs import load_session, save_session, reset_session
from spyderlib.utils.programs import is_module_installed
-from spyderlib.utils import module_completion
+from spyderlib.utils.introspection import module_completion
from spyderlib.utils.misc import select_port
from spyderlib.py3compat import (PY3, to_text_string, is_text_string, getcwd,
u, qbytearray_to_str, configparser as cp)
@@ -281,6 +281,10 @@ class MainWindow(QMainWindow):
DOCKOPTIONS = QMainWindow.AllowTabbedDocks|QMainWindow.AllowNestedDocks
SPYDER_PATH = get_conf_path('path')
BOOKMARKS = (
+ ('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")),
@@ -290,11 +294,7 @@ class MainWindow(QMainWindow):
('xy', "http://code.google.com/p/pythonxy/",
_("Python(x,y)")),
('winpython', "http://code.google.com/p/winpython/",
- _("WinPython")),
- ('numpy', "http://docs.scipy.org/doc/",
- _("Numpy and Scipy documentation")),
- ('matplotlib', "http://matplotlib.sourceforge.net/contents.html",
- _("Matplotlib documentation")),
+ _("WinPython"))
)
def __init__(self, options=None):
@@ -405,7 +405,8 @@ class MainWindow(QMainWindow):
# otherwise the external tools menu is lost after leaving setup method
self.external_tools_menu_actions = []
self.view_menu = None
- self.windows_toolbars_menu = None
+ self.plugins_menu = None
+ self.toolbars_menu = None
self.help_menu = None
self.help_menu_actions = []
@@ -414,6 +415,7 @@ class MainWindow(QMainWindow):
self.cpu_status = None
# Toolbars
+ self.toolbarslist = []
self.main_toolbar = None
self.main_toolbar_actions = []
self.file_toolbar = None
@@ -445,14 +447,8 @@ class MainWindow(QMainWindow):
self.setWindowIcon(get_icon(icon_name, resample=os.name != 'nt'))
# Showing splash screen
- pixmap = QPixmap(get_image_path('splash.png'), 'png')
- self.splash = QSplashScreen(pixmap)
- font = self.splash.font()
- font.setPixelSize(10)
- self.splash.setFont(font)
+ self.splash = SPLASH
if not self.light:
- self.splash.show()
- self.set_splash(_("Initializing..."))
if CONF.get('main', 'current_version', '') != __version__:
CONF.set('main', 'current_version', __version__)
# Execute here the actions to be performed only once after
@@ -487,6 +483,9 @@ class MainWindow(QMainWindow):
# False: IPython console plugin
self.last_console_plugin_focus_was_python = True
+ # To keep track of the last focused widget
+ self.last_focused_widget = None
+
# Server to open external files on a single instance
self.open_files_server = socket.socket(socket.AF_INET,
socket.SOCK_STREAM,
@@ -505,6 +504,7 @@ class MainWindow(QMainWindow):
toolbar = self.addToolBar(title)
toolbar.setObjectName(object_name)
toolbar.setIconSize( QSize(iconsize, iconsize) )
+ self.toolbarslist.append(toolbar)
return toolbar
def setup(self):
@@ -513,11 +513,11 @@ class MainWindow(QMainWindow):
if not self.light:
self.debug_print(" ..core actions")
self.close_dockwidget_action = create_action(self,
- _("Close current dockwidget"),
+ _("Close current plugin"),
triggered=self.close_current_dockwidget,
context=Qt.ApplicationShortcut)
self.register_shortcut(self.close_dockwidget_action,
- "_", "Close dockwidget", "Shift+Ctrl+F4")
+ "_", "Close plugin", "Shift+Ctrl+F4")
_text = _("&Find text")
self.find_action = create_action(self, _text, icon='find.png',
@@ -649,7 +649,6 @@ class MainWindow(QMainWindow):
tip=_("Refresh list of module names "
"available in PYTHONPATH"))
self.tools_menu_actions = [prefs_action, spyder_path_action]
- self.tools_menu_actions += [update_modules_action, None]
if WinUserEnvDialog is not None:
winenv_action = create_action(self,
_("Current user environment variables..."),
@@ -659,6 +658,7 @@ class MainWindow(QMainWindow):
"(i.e. for all sessions)"),
triggered=self.win_env)
self.tools_menu_actions.append(winenv_action)
+ self.tools_menu_actions += [None, update_modules_action]
# External Tools submenu
self.external_tools_menu = QMenu(_("External Tools"))
@@ -668,26 +668,18 @@ class MainWindow(QMainWindow):
_("Python(x,y) launcher"),
icon=get_icon('pythonxy.png'),
triggered=lambda:
- programs.run_python_script('xy', 'xyhome'))
- self.external_tools_menu_actions.append(self.xy_action)
- if not is_module_installed('xy'):
- self.xy_action.setDisabled(True)
- self.xy_action.setToolTip(self.xy_action.toolTip() + \
- '\nPlease install Python(x,y) to '
- 'enable this feature')
+ programs.run_python_script('xy', 'xyhome'))
+ if os.name == 'nt' and is_module_installed('xy'):
+ self.external_tools_menu_actions.append(self.xy_action)
# 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'))
- self.external_tools_menu_actions.append(self.wp_action)
- if not is_module_installed('winpython'):
- self.wp_action.setDisabled(True)
- self.wp_action.setToolTip(self.wp_action.toolTip() + \
- '\nPlease install WinPython to '
- 'enable this feature')
+ if os.name == 'nt' and is_module_installed('winpython'):
+ self.external_tools_menu_actions.append(self.wp_action)
# Qt-related tools
- additact = [None]
+ additact = []
for name in ("designer-qt4", "designer"):
qtdact = create_program_action(self, _("Qt Designer"),
name, 'qtdesigner.png')
@@ -706,11 +698,11 @@ class MainWindow(QMainWindow):
for act in (qtdact, qtlact, qteact):
if act:
additact.append(act)
- if len(additact) > 1 and (is_module_installed('winpython') or \
+ if additact and (is_module_installed('winpython') or \
is_module_installed('xy')):
- self.external_tools_menu_actions += additact
+ self.external_tools_menu_actions += [None] + additact
- # Sift
+ # Guidata and Sift
self.debug_print(" ..sift?")
gdgq_act = []
if is_module_installed('guidata'):
@@ -748,7 +740,7 @@ class MainWindow(QMainWindow):
self.maximize_action = create_action(self, '',
triggered=self.maximize_dockwidget)
self.register_shortcut(self.maximize_action, "_",
- "Maximize dockwidget", "Ctrl+Alt+Shift+M")
+ "Maximize plugin", "Ctrl+Alt+Shift+M")
self.__update_maximize_action()
# Fullscreen mode
@@ -768,8 +760,8 @@ class MainWindow(QMainWindow):
self.main_toolbar = self.create_toolbar(_("Main toolbar"),
"main_toolbar")
- self.debug_print(" ..plugin: internal console")
# Internal console plugin
+ self.debug_print(" ..plugin: internal console")
from spyderlib.plugins.console import Console
self.console = Console(self, namespace, exitfunc=self.closing,
profile=self.profile,
@@ -778,11 +770,12 @@ class MainWindow(QMainWindow):
' spy.app, spy.window, dir(spy)')
self.console.register_plugin()
- self.debug_print(" ..plugin: working directory")
# Working directory plugin
+ self.debug_print(" ..plugin: working directory")
from spyderlib.plugins.workingdirectory import WorkingDirectory
self.workingdirectory = WorkingDirectory(self, self.init_workdir)
self.workingdirectory.register_plugin()
+ self.toolbarslist.append(self.workingdirectory)
# Object inspector plugin
if CONF.get('inspector', 'enable'):
@@ -890,74 +883,69 @@ class MainWindow(QMainWindow):
self.set_splash(_("Setting up main window..."))
- # ? menu
- about_action = create_action(self,
- _("About %s...") % "Spyder",
- icon=get_std_icon('MessageBoxInformation'),
- triggered=self.about)
+ # Help menu
dep_action = create_action(self, _("Optional dependencies..."),
- triggered=self.show_dependencies)
+ triggered=self.show_dependencies,
+ icon='advanced.png')
report_action = create_action(self,
- _("Report issue..."),
- icon=get_icon('bug.png'),
- triggered=self.report_issue
- )
+ _("Report issue..."),
+ icon=get_icon('bug.png'),
+ triggered=self.report_issue)
+ support_action = create_action(self,
+ _("Spyder support..."),
+ triggered=self.google_group)
# Spyder documentation
doc_path = get_module_data_path('spyderlib', 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, os.pardir,
- "Spyderdoc.chm")
+ 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")
- if not osp.isfile(spyder_doc): # development version
- spyder_doc = osp.join(get_module_source_path('spyderlib'),
- os.pardir, 'build', 'lib',
- 'spyderlib', 'doc', "index.html")
- spyder_doc = file_uri(spyder_doc)
+ # * Trying to find the development-version html doc
+ if not osp.isfile(spyder_doc):
+ spyder_doc = osp.join(get_module_source_path('spyderlib'),
+ os.pardir, 'build', 'lib', 'spyderlib',
+ '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_bookmark_action(self, spyder_doc,
_("Spyder documentation"), shortcut="F1",
icon=get_std_icon('DialogHelpButton'))
- self.help_menu_actions = [doc_action, report_action, dep_action,
- None]
+ self.help_menu_actions = [doc_action, report_action,
+ dep_action, support_action, None]
# Python documentation
if get_python_doc_path() is not None:
pydoc_act = create_action(self, _("Python documentation"),
- icon=get_icon('python.png'),
triggered=lambda:
programs.start_file(get_python_doc_path()))
self.help_menu_actions.append(pydoc_act)
# IPython documentation
if self.ipyconsole is not None:
- ipython_menu = QMenu(_("IPython Help"), self)
+ 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"),
+ 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)
- # Qt assistant link
- qta_act = create_program_action(self, _("Qt Help"), "assistant")
- if qta_act:
- self.help_menu_actions.append(qta_act)
- # Online documentation
- web_resources = QMenu(_("Web Resources"))
- add_actions(web_resources,
- create_module_bookmark_actions(self, self.BOOKMARKS))
- self.help_menu_actions += [web_resources, None]
# Windows-only: documentation located in sys.prefix/Doc
- def add_doc_action(text, path):
- """Add doc action to help menu"""
+ ipm_actions = []
+ def add_ipm_action(text, path):
+ """Add installed Python module doc action to help submenu"""
path = file_uri(path)
- action = create_action(self, text, icon=None,
+ action = create_action(self, text,
+ icon='%s.png' % osp.splitext(path)[1][1:],
triggered=lambda path=path: programs.start_file(path))
- self.help_menu_actions.append(action)
+ 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):
@@ -966,7 +954,7 @@ class MainWindow(QMainWindow):
if match is not None:
pname = match.groups()[0]
if pname not in ('Python', ):
- add_doc_action(pname, osp.join(sysdocpth, docfn))
+ add_ipm_action(pname, osp.join(sysdocpth, docfn))
# Documentation provided by Python(x,y), if available
try:
from xy.config import DOC_PATH as xy_doc_path
@@ -974,7 +962,7 @@ class MainWindow(QMainWindow):
def add_xydoc(text, pathlist):
for path in pathlist:
if osp.exists(path):
- add_doc_action(text, path)
+ add_ipm_action(text, path)
break
add_xydoc(_("Python(x,y) documentation folder"),
[xy_doc_path])
@@ -998,14 +986,32 @@ class MainWindow(QMainWindow):
add_xydoc(_("SciPy documentation"),
[osp.join(xydoc, "SciPy", "scipy.chm"),
osp.join(xydoc, "SciPy", "scipy-ref.pdf")])
- self.help_menu_actions.append(None)
except (ImportError, KeyError, RuntimeError):
pass
- if self.help_menu_actions[-1] is None:
- last_action = [about_action]
- else:
- last_action = [None, about_action]
- self.help_menu_actions += last_action
+ # 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)
+ add_actions(web_resources, webres_actions)
+ self.help_menu_actions.append(web_resources)
+ # Qt assistant link
+ qta_act = create_program_action(self, _("Qt documentation"),
+ "assistant")
+ if qta_act:
+ self.help_menu_actions += [qta_act, None]
+ # About Spyder
+ about_action = create_action(self,
+ _("About %s...") % "Spyder",
+ icon=get_std_icon('MessageBoxInformation'),
+ triggered=self.about)
+ self.help_menu_actions += [None, about_action]
# Status bar widgets
from spyderlib.widgets.status import MemoryStatus, CPUStatus
@@ -1023,10 +1029,10 @@ class MainWindow(QMainWindow):
print("%s: %s" % (mod, str(error)), file=STDERR)
# View menu
- self.windows_toolbars_menu = QMenu(_("Windows and toolbars"), self)
- self.connect(self.windows_toolbars_menu, SIGNAL("aboutToShow()"),
- self.update_windows_toolbars_menu)
- self.view_menu.addMenu(self.windows_toolbars_menu)
+ self.plugins_menu = QMenu(_("Windows"), self)
+ self.toolbars_menu = QMenu(_("Toolbars"), self)
+ self.view_menu.addMenu(self.plugins_menu)
+ self.view_menu.addMenu(self.toolbars_menu)
reset_layout_action = create_action(self, _("Reset window layout"),
triggered=self.reset_window_layout)
quick_layout_menu = QMenu(_("Custom window layouts"), self)
@@ -1055,21 +1061,18 @@ class MainWindow(QMainWindow):
toggled=set_attached_console_visible)
cmd_act.setChecked(is_attached_console_visible())
add_actions(self.view_menu, (None, cmd_act))
- add_actions(self.view_menu, (None, self.maximize_action,
- self.fullscreen_action, None,
- reset_layout_action, quick_layout_menu,
- None, self.close_dockwidget_action))
+ add_actions(self.view_menu, (None, self.fullscreen_action,
+ self.maximize_action,
+ self.close_dockwidget_action, None,
+ reset_layout_action,
+ quick_layout_menu))
# Adding external tools action to "Tools" menu
- external_tools_act = create_action(self, _("External Tools"),
- icon="ext_tools.png")
- external_tools_act.setMenu(self.external_tools_menu)
- add_ext_tools = False
- for et in self.external_tools_menu_actions:
- if et and et.isEnabled():
- add_ext_tools = True
- if add_ext_tools:
- self.tools_menu_actions.append(external_tools_act)
+ if self.external_tools_menu_actions:
+ external_tools_act = create_action(self, _("External Tools"),
+ icon="ext_tools.png")
+ external_tools_act.setMenu(self.external_tools_menu)
+ self.tools_menu_actions += [None, external_tools_act]
self.main_toolbar_actions.append(external_tools_act)
# Filling out menu/toolbar entries:
@@ -1105,7 +1108,6 @@ class MainWindow(QMainWindow):
self.debug_print("Setting up window...")
self.setup_layout(default=False)
- SPLASH.hide()
self.splash.hide()
# Enabling tear off for all menus except help menu
@@ -1127,7 +1129,7 @@ class MainWindow(QMainWindow):
"""Actions to be performed only after the main window's `show` method
was triggered"""
self.emit(SIGNAL('restore_scrollbar_position()'))
-
+
if self.projectexplorer is not None:
self.projectexplorer.check_for_io_errors()
@@ -1170,9 +1172,6 @@ class MainWindow(QMainWindow):
lambda fname: self.open_external_file(fname))
# Open a Python or IPython console at startup
- # NOTE: Leave this at the end of post_visible_setup because
- # it seems to avoid being unable to start a console at
- # startup *sometimes* if using PySide
if self.light:
self.extconsole.open_interpreter()
else:
@@ -1181,6 +1180,25 @@ class MainWindow(QMainWindow):
self.ipyconsole.open_client_at_startup()
self.extconsole.setMinimumHeight(0)
+ # Hide Internal Console so that people doesn't use it instead of
+ # the External or IPython ones
+ if self.console.dockwidget.isVisible() and DEV is None:
+ self.console.dockwidget.hide()
+
+ # Create Plugins and toolbars submenus
+ if not self.light:
+ self.create_plugins_menu()
+ self.create_toolbars_menu()
+
+ # Show the Object Inspector and Consoles by default
+ for plugin in (self.inspector, self.extconsole, self.ipyconsole):
+ if plugin is not None and plugin.dockwidget.isVisible():
+ plugin.dockwidget.raise_()
+
+ # Give focus to the Editor
+ if self.editor.dockwidget.isVisible():
+ self.editor.get_focus_widget().setFocus()
+
def load_window_settings(self, prefix, default=False, section='main'):
"""Load window layout settings from userconfig-based configuration
with *prefix*, under *section*
@@ -1462,12 +1480,47 @@ class MainWindow(QMainWindow):
action.setEnabled(True)
self.replace_action.setEnabled(readwrite_editor)
self.replace_action.setEnabled(readwrite_editor)
-
- def update_windows_toolbars_menu(self):
- """Update windows&toolbars menu"""
- self.windows_toolbars_menu.clear()
- popmenu = self.createPopupMenu()
- add_actions(self.windows_toolbars_menu, popmenu.actions())
+
+ def create_plugins_menu(self):
+ order = ['editor', 'outline_explorer', 'project_explorer',
+ 'breakpoints', 'pylint', None, 'ipython_console', 'console',
+ 'historylog', 'profiler', None, 'variable_explorer',
+ 'inspector', 'explorer', 'find_in_files', 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)
+ add_actions(self.plugins_menu, actions)
+
+ def create_toolbars_menu(self):
+ actions = []
+ for toolbar in self.toolbarslist:
+ action = toolbar.toggleViewAction()
+ actions.append(action)
+ add_actions(self.toolbars_menu, actions)
+
+ def createPopupMenu(self):
+ if self.light:
+ menu = self.createPopupMenu()
+ else:
+ 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"""
@@ -1500,7 +1553,22 @@ class MainWindow(QMainWindow):
if not self.isMaximized() and not self.fullscreen_flag:
self.window_position = self.pos()
QMainWindow.moveEvent(self, event)
-
+
+ def hideEvent(self, event):
+ """Reimplement Qt method"""
+ for plugin in self.widgetlist:
+ if plugin.isAncestorOf(self.last_focused_widget):
+ plugin.visibility_changed(True)
+ 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
+
def closing(self, cancelable=False):
"""Exit tasks"""
if self.already_closed or self.is_starting_up:
@@ -1718,7 +1786,11 @@ Please provide any additional information below.
url = QUrl("http://code.google.com/p/spyderlib/issues/entry")
url.addEncodedQueryItem("comment", quote(issue_template))
- QDesktopServices.openUrl(url)
+ QDesktopServices.openUrl(url)
+
+ def google_group(self):
+ url = QUrl("http://groups.google.com/group/spyderlib")
+ QDesktopServices.openUrl(url)
#---- Global callbacks (called from plugins)
def get_current_editor_plugin(self):
@@ -2159,6 +2231,11 @@ def run_spyder(app, options, args):
if sys.platform == "darwin" and 'Spyder.app' in __file__:
main.connect(app, SIGNAL('open_external_file(QString)'),
lambda fname: main.open_external_file(fname))
+
+ # To give focus again to the last focused widget after restoring
+ # the window
+ main.connect(app, SIGNAL('focusChanged(QWidget*, QWidget*)'),
+ main.change_last_focused_widget)
app.exec_()
return main
diff --git a/spyderlib/utils/inspector/static/css/default.css b/spyderlib/utils/inspector/static/css/default.css
index 4e694f8..f236b48 100644
--- a/spyderlib/utils/inspector/static/css/default.css
+++ b/spyderlib/utils/inspector/static/css/default.css
@@ -303,7 +303,3 @@ tt {
border-color: #eed3d7;
background-color: rgb(199, 28, 34);
}
-
-.panel-danger > .panel-heading > .panel-title {
- text-align: center;
-}
diff --git a/spyderlib/utils/introspection/__init__.py b/spyderlib/utils/introspection/__init__.py
new file mode 100644
index 0000000..095df41
--- /dev/null
+++ b/spyderlib/utils/introspection/__init__.py
@@ -0,0 +1,11 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright © 2013 The Spyder Development Team
+# Licensed under the terms of the MIT License
+# (see spyderlib/__init__.py for details)
+
+"""
+Introspection utilities used by Spyder
+"""
+from .base import get_plugin
+from . import module_completion
diff --git a/spyderlib/utils/introspection/base.py b/spyderlib/utils/introspection/base.py
new file mode 100644
index 0000000..3fbb96a
--- /dev/null
+++ b/spyderlib/utils/introspection/base.py
@@ -0,0 +1,453 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright © 2013 The Spyder Development Team
+# Licensed under the terms of the MIT License
+# (see spyderlib/__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
+import functools
+from collections import OrderedDict
+
+from spyderlib.baseconfig import DEBUG, get_conf_path, debug_print
+from spyderlib.py3compat import PY2
+from spyderlib.utils.debug import log_dt, log_last_error
+from spyderlib.utils import sourcecode
+
+from spyderlib.qt.QtGui import QApplication
+
+
+PLUGINS = ['jedi', 'rope', 'fallback']
+LOG_FILENAME = get_conf_path('introspection.log')
+DEBUG_EDITOR = DEBUG >= 3
+
+
+def get_plugin(editor_widget):
+ """Get and load a plugin, checking in order of PLUGINS"""
+ plugin = None
+ for plugin_name in PLUGINS:
+ mod_name = plugin_name + '_plugin'
+ try:
+ mod = __import__('spyderlib.utils.introspection.' + mod_name,
+ fromlist=[mod_name])
+ cls = getattr(mod, '%sPlugin' % plugin_name.capitalize())
+ plugin = cls()
+ plugin.load_plugin()
+ except Exception:
+ if DEBUG_EDITOR:
+ log_last_error(LOG_FILENAME)
+ else:
+ break
+ if not plugin:
+ plugin = IntrospectionPlugin()
+ debug_print('Instropection Plugin Loaded: %s' % plugin.name)
+ plugin.editor_widget = editor_widget
+ return plugin
+
+
+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 = OrderedDict()
+
+ @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 fallback(func):
+ """
+ Call the super method if the method throws an error.
+
+ Handles all exceptions and input that evaluates to False.
+ """
+ @functools.wraps(func)
+ def inner(self, *args, **kwargs):
+ try:
+ return func(self, *args, **kwargs)
+ except Exception:
+ super_cls = super(self.__class__, self)
+ if PY2:
+ super_method = getattr(super_cls, func.func_name)
+ else:
+ super_method = getattr(super_cls, func.__name__)
+ return super_method(*args, **kwargs)
+ return inner
+
+
+class IntrospectionPlugin(object):
+ """Basic Introspection Plugin for Spyder"""
+
+ editor_widget = None
+
+ # ---- IntrospectionPlugin API --------------------------------------------
+ name = 'fallback'
+
+ def load_plugin(self):
+ """Load the plugin"""
+ pass
+
+ def get_completion_list(self, source_code, offset, filename):
+ """Return a list of completion strings"""
+ return self.get_token_completion_list(source_code, offset, filename)
+
+ def get_calltip_and_docs(self, source_code, offset, filename):
+ """
+ Find the calltip and docs
+
+ Calltip is a string with the function or class and its arguments
+ e.g. 'match(patern, string, flags=0)'
+ 'ones(shape, dtype=None, order='C')'
+ Docs is a a string or a dict with the following keys:
+ e.g. 'Try to apply the pattern at the start of the string...'
+ or {'note': 'Function of numpy.core.numeric...',
+ 'argspec': "(shape, dtype=None, order='C')'
+ 'docstring': 'Return an array of given...'
+ 'name': 'ones'}
+ """
+ return None
+
+ def get_definition_location(self, source_code, offset, filename):
+ """Find a path and line number for a definition"""
+ return self.get_definition_location_regex(source_code, offset,
+ filename)
+
+ def get_definition_location_regex(self, source_code, offset, filename):
+ """Find a path and line number for a definition using regex"""
+ ret = None, None
+ try:
+ ret = self._get_definition_location_regex(source_code, offset,
+ filename)
+ debug_print('get regex definition: ' + str(ret))
+ except Exception as e:
+ debug_print('Regex error: %s' % e)
+ if DEBUG_EDITOR:
+ log_last_error(LOG_FILENAME)
+ return ret
+
+ def get_token_completion_list(self, source_code, offset, filename):
+ """Return a list of completion strings using token matching"""
+ ret = None
+ try:
+ ret = self._token_based_completion(source_code, offset)
+ debug_print('token completion: %s ...(%s)' % (ret[:2], len(ret)))
+ except Exception:
+ if DEBUG_EDITOR:
+ log_last_error(LOG_FILENAME)
+ return ret or []
+
+ def set_pref(self, name, value):
+ """Set a plugin preference to a value"""
+ pass
+
+ def validate(self):
+ """Validate the plugin"""
+ pass
+
+ # ---- Private API -------------------------------------------------------
+
+ @staticmethod
+ def _token_based_completion(script, offset):
+ """Simple completion based on python-like identifiers and whitespace"""
+ base_tokens = split_words(script[:offset])
+ base = base_tokens[-1]
+ tokens = set(split_words(script))
+ items = [item for item in tokens if
+ item.startswith(base) and len(item) > len(base)]
+ if '.' in base:
+ start = base.rfind('.') + 1
+ else:
+ start = 0
+ items = [i[start:len(base)] + i[len(base):].split('.')[0] for i in items]
+ return list(sorted(items))
+
+ 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 get_current_source(self):
+ """Get the source code in the current file"""
+ if self.editor_widget:
+ finfo = self.editor_widget.get_current_finfo()
+ if finfo:
+ return finfo.get_source_code()
+
+ 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:
+ statusbar = self.editor_widget.window().statusBar()
+ statusbar.showMessage(message, timeout)
+ QApplication.processEvents()
+
+ @memoize
+ def python_like_mod_finder(self, 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 self.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 self.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_location_regex(self, source_code, offset, filename):
+ """
+ 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
+ """
+ token = sourcecode.get_primary_at(source_code, offset)
+ eol = sourcecode.get_eol_chars(source_code) or '\n'
+ lines = source_code[:offset].split(eol)
+ line_nr = self.get_definition_with_regex(source_code, token,
+ len(lines))
+ line = source_code.split(eol)[line_nr - 1].strip()
+ exts = self.python_like_exts()
+ if not osp.splitext(filename)[-1] in exts:
+ line_nr = self.get_definition_with_regex(source_code, token,
+ line_nr)
+ return filename, line_nr
+ if line.startswith('import ') or line.startswith('from '):
+ alt_path = osp.dirname(filename)
+ source_file = self.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 = self.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:
+ line_nr = self.get_definition_from_file(source_file, token)
+ return source_file, line_nr
+ return filename, line_nr
+
+ @memoize
+ def get_definition_from_file(self, filename, name, line_nr=-1):
+ """Find the definition for an object in a filename"""
+ with open(filename, 'rb') as fid:
+ code = fid.read()
+ return self.get_definition_with_regex(code, name, line_nr)
+
+ @staticmethod
+ 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}',
+ # "self.item =" or "item ="
+ '.*\Wself.{0}{1}[^=!<>]*=[^=]',
+ '.*\W{0}{1}[^=!<>]*=[^=]',
+ 'self.{0}{1}[^=!<>]*=[^=]',
+ '{0}{1}[^=!<>]*=[^=]',
+ # enaml keyword definitions
+ 'enamldef.*\W{0}{1}',
+ 'attr.*\W{0}{1}',
+ 'event.*\W{0}{1}',
+ 'id\s*:.*\W{0}{1}']
+ 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
+ eol = sourcecode.get_eol_chars(source) or '\n'
+ lines = source.split(eol)
+ lines = [line.strip() + ' ' for line in lines]
+ if start_line == -1:
+ start_line = len(lines)
+ matches = []
+ for (index, line) in enumerate(lines):
+ if re.match(pattern, line):
+ matches.append(index + 1)
+ # find the one closest to the start line (prefer before the start line)
+ if matches:
+ min_dist = len(lines)
+ 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
+
+ @staticmethod
+ @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))
+
+ @staticmethod
+ 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]
+
+ @staticmethod
+ 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 split_words(string):
+ """Split a string into unicode-aware words"""
+ return re.findall(r"[\w.]+", string, re.UNICODE)
+
+
+if __name__ == '__main__':
+ p = IntrospectionPlugin()
+
+ with open(__file__) as fid:
+ code = fid.read()
+ code += '\nget_conf_path'
+ path, line = p.get_definition_location_regex(code, len(code), __file__)
+ assert path.endswith('baseconfig.py')
+
+ comp = p.get_token_completion_list(code[:-2], len(code) - 2, None)
+ assert comp == ['get_conf_path']
+
+ ext = p.python_like_exts()
+ assert '.py' in ext and '.pyx' in ext
+
+ ext = p.all_editable_exts()
+ assert '.cfg' in ext and '.iss' in ext
+
+ path = p.get_parent_until(__file__)
+ assert path == 'spyderlib.utils.introspection.base'
+
+ line = 'from spyderlib.widgets.sourcecode.codeeditor import CodeEditor'
+ path = p.python_like_mod_finder(line)
+ assert path.endswith('codeeditor.py')
+ path = p.python_like_mod_finder(line, stop_token='sourcecode')
+ assert path.endswith('__init__.py') and 'sourcecode' in path
+
+ path = p.get_parent_until(osp.expanduser(r'~/.spyder2/temp.py'))
+ assert path == '.spyder2.temp'
+
+ code = 'import re\n\nre'
+ path, line = p.get_definition_location_regex(code, len(code), 'dummy.txt')
+ assert path == 'dummy.txt' and line == 1
+
+ code = 'self.proxy.widget; self.'
+ comp = p.get_token_completion_list(code, len(code), None)
+ assert comp == ['proxy']
+
+ code = 'self.sigMessageReady.emit; self.'
+ comp = p.get_token_completion_list(code, len(code), None)
+ assert comp == ['sigMessageReady']
+
+ code = u'álfa;á'
+ comp = p.get_token_completion_list(code, len(code), None)
+ assert comp == [u'álfa']
+
\ No newline at end of file
diff --git a/spyderlib/utils/module_completion.py b/spyderlib/utils/introspection/module_completion.py
similarity index 100%
rename from spyderlib/utils/module_completion.py
rename to spyderlib/utils/introspection/module_completion.py
diff --git a/spyderlib/utils/introspection/rope_plugin.py b/spyderlib/utils/introspection/rope_plugin.py
new file mode 100644
index 0000000..584c195
--- /dev/null
+++ b/spyderlib/utils/introspection/rope_plugin.py
@@ -0,0 +1,241 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright © 2013 The Spyder Development Team
+# Licensed under the terms of the MIT License
+# (see spyderlib/__init__.py for details)
+
+"""
+Rope introspection plugin
+"""
+import time
+
+from spyderlib import dependencies
+from spyderlib.baseconfig import get_conf_path, _, STDERR
+from spyderlib.utils import encoding, programs
+from spyderlib.py3compat import PY2
+from spyderlib.utils.debug import log_last_error, log_dt
+from spyderlib.utils.introspection.base import (
+ DEBUG_EDITOR, LOG_FILENAME, IntrospectionPlugin, fallback)
+try:
+ try:
+ from spyderlib import rope_patch
+ rope_patch.apply()
+ except ImportError:
+ # rope 0.9.2/0.9.3 is not installed
+ pass
+ import rope.base.libutils
+ import rope.contrib.codeassist
+except ImportError:
+ pass
+
+
+ROPE_REQVER = '>=0.9.2'
+dependencies.add('rope',
+ _("Editor's code completion, go-to-definition and help"),
+ required_version=ROPE_REQVER)
+
+#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())
+
+ @fallback
+ def get_completion_list(self, source_code, offset, filename):
+ """Get a list of completions using Rope"""
+ if self.project is None:
+ raise ValueError
+ 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)
+ if not proposals:
+ raise ValueError
+ return [proposal.name for proposal in proposals]
+ except Exception as _error: #analysis:ignore
+ if DEBUG_EDITOR:
+ log_last_error(LOG_FILENAME, "get_completion_list")
+ raise ValueError
+
+ @fallback
+ def get_calltip_and_docs(self, source_code, offset, filename):
+ """Get a formatted calltip and docstring from Rope"""
+ if self.project is None:
+ raise ValueError
+ 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 [cts, doc_text]
+ except Exception as _error: #analysis:ignore
+ if DEBUG_EDITOR:
+ log_last_error(LOG_FILENAME, "get_calltip_text")
+ raise ValueError
+
+ @fallback
+ def get_definition_location(self, source_code, offset, filename):
+ """Find a definition location using Rope"""
+ if self.project is None:
+ raise ValueError
+ 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
+ else:
+ raise ValueError
+ return filename, lineno
+ except Exception as _error: #analysis:ignore
+ if DEBUG_EDITOR:
+ log_last_error(LOG_FILENAME, "get_definition_location")
+ raise ValueError
+
+ def validate(self):
+ """Validate the Rope project"""
+ if self.project is not None:
+ self.project.validate(self.project.root)
+
+ def set_pref(self, key, value):
+ """Set a Rope preference"""
+ if self.project is not None:
+ self.project.prefs.set(key, value)
+
+ # ---- 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:
+ # Compatibility with new Mercurial API (>= 1.3).
+ # New versions of rope (> 0.9.2) already handle this issue
+ 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()
+
+
+if __name__ == '__main__':
+
+ p = RopePlugin()
+ p.load_plugin()
+
+ source_code = "import numpy; numpy.ones"
+ calltip, docs = p.get_calltip_and_docs(source_code, len(source_code),
+ __file__)
+ assert 'ones(' in calltip and 'ones(' in docs
+
+ source_code = "import numpy; n"
+ completions = p.get_completion_list(source_code, len(source_code),
+ __file__)
+ assert 'numpy' in completions
+
+ source_code = "import matplotlib.pyplot as plt; plt.imsave"
+ path, line_nr = p.get_definition_location(source_code, len(source_code),
+ __file__)
+ assert 'pyplot.py' in path
diff --git a/spyderlib/utils/programs.py b/spyderlib/utils/programs.py
index 8d6e227..6eca7f1 100644
--- a/spyderlib/utils/programs.py
+++ b/spyderlib/utils/programs.py
@@ -194,6 +194,8 @@ def check_version(actver, version, cmp_op):
Distributed under the terms of the BSD License.
"""
+ if isinstance(actver, tuple):
+ actver = '.'.join([str(i) for i in actver])
try:
if cmp_op == '>':
return LooseVersion(actver) > LooseVersion(version)
@@ -289,6 +291,7 @@ def is_module_installed(module_name, version=None, installed_version=None,
assert symb in ('>=', '>', '=', '<'),\
"Invalid version condition '%s'" % symb
version = version[match.start():]
+
return check_version(actver, version, symb)
@@ -298,3 +301,4 @@ if __name__ == '__main__':
print(shell_split('-q "d:\\Python de xxxx\\t.txt" -o -a'))
print(is_module_installed('IPython', '>=0.12'))
print(is_module_installed('IPython', '>=0.13;<1.0'))
+ print(is_module_installed('jedi', '>=0.7.0'))
diff --git a/spyderlib/utils/qthelpers.py b/spyderlib/utils/qthelpers.py
index c7dc787..fb22898 100644
--- a/spyderlib/utils/qthelpers.py
+++ b/spyderlib/utils/qthelpers.py
@@ -328,7 +328,7 @@ def create_module_bookmark_actions(parent, bookmarks):
create_act = False
if create_act:
act = create_bookmark_action(parent, url, title)
- actions.append(act)
+ actions.append(act)
return actions
diff --git a/spyderlib/utils/sourcecode.py b/spyderlib/utils/sourcecode.py
index 9714385..2f7c421 100644
--- a/spyderlib/utils/sourcecode.py
+++ b/spyderlib/utils/sourcecode.py
@@ -7,10 +7,34 @@
"""
Source code text utilities
"""
+import re
# Order is important:
EOL_CHARS = (("\r\n", 'nt'), ("\n", 'posix'), ("\r", 'mac'))
+ALL_LANGUAGES = {
+ 'Python': ('py', 'pyw', 'python', 'ipy'),
+ 'Cython': ('pyx', 'pxi', 'pxd'),
+ 'Fortran77': ('f', 'for', 'f77'),
+ 'Fortran': ('f90', 'f95', 'f2k'),
+ 'Idl': ('pro',),
+ 'Matlab': ('m',),
+ 'Diff': ('diff', 'patch', 'rej'),
+ 'GetText': ('po', 'pot'),
+ 'Nsis': ('nsi', 'nsh'),
+ 'Html': ('htm', 'html'),
+ 'Css': ('css',),
+ 'Xml': ('xml',),
+ 'Js': ('js',),
+ 'Cpp': ('c', 'cc', 'cpp', 'cxx', 'h', 'hh', 'hpp', 'hxx'),
+ 'OpenCL': ('cl',),
+ 'Batch': ('bat', 'cmd', 'nt'),
+ 'Ini': ('properties', 'session', 'ini', 'inf', 'reg', 'url',
+ 'cfg', 'cnf', 'aut', 'iss'),
+ }
+
+PYTHON_LIKE_LANGUAGES = ('Python', 'Cython')
+
def get_eol_chars(text):
"""Get text EOL characters"""
for eol_chars, _os_name in EOL_CHARS:
@@ -52,3 +76,51 @@ 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)]
+
+
+if __name__ == '__main__':
+ code = 'import functools\nfunctools.partial'
+ assert get_primary_at(code, len(code)) == 'functools.partial'
+ assert get_identifiers(code) == ['import', 'functools',
+ 'functools.partial']
+ assert split_source(code) == ['import functools', 'functools.partial']
+ code = code.replace('\n', '\r\n')
+ assert split_source(code) == ['import functools', 'functools.partial']
diff --git a/spyderlib/widgets/calltip.py b/spyderlib/widgets/calltip.py
index f3cab6f..9b6b51b 100644
--- a/spyderlib/widgets/calltip.py
+++ b/spyderlib/widgets/calltip.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
#-----------------------------------------------------------------------------
# Copyright (c) 2010, IPython Development Team.
#
@@ -11,7 +12,6 @@ Calltip widget used only to show signatures
"""
# Standard library imports
-import re
from unicodedata import category
# System library imports
@@ -26,7 +26,7 @@ class CallTipWidget(QtGui.QLabel):
# 'QObject' interface
#--------------------------------------------------------------------------
- def __init__(self, text_edit):
+ def __init__(self, text_edit, hide_timer_on=False):
""" Create a call tip manager that is attached to the specified Qt
text edit widget.
"""
@@ -34,6 +34,7 @@ class CallTipWidget(QtGui.QLabel):
super(CallTipWidget, self).__init__(None, QtCore.Qt.ToolTip)
self.app = QtCore.QCoreApplication.instance()
+ self.hide_timer_on = hide_timer_on
self._hide_timer = QtCore.QBasicTimer()
self._text_edit = text_edit
@@ -47,8 +48,6 @@ class CallTipWidget(QtGui.QLabel):
self.setFrameStyle(QtGui.QFrame.NoFrame)
self.setMargin(1 + self.style().pixelMetric(
QtGui.QStyle.PM_ToolTipLabelFrameWidth, None, self))
- self.setWindowOpacity(self.style().styleHint(
- QtGui.QStyle.SH_ToolTipLabel_Opacity, None, self, None) / 255.0)
def eventFilter(self, obj, event):
""" Reimplemented to hide on certain key presses and on text edit focus
@@ -70,7 +69,9 @@ class CallTipWidget(QtGui.QLabel):
self.hide()
elif etype == QtCore.QEvent.Enter:
- self._hide_timer.stop()
+ if (self._hide_timer.isActive() and
+ self.app.topLevelAt(QtGui.QCursor.pos()) == self):
+ self._hide_timer.stop()
elif etype == QtCore.QEvent.Leave:
self._leave_event_hide()
@@ -92,7 +93,9 @@ class CallTipWidget(QtGui.QLabel):
""" Reimplemented to cancel the hide timer.
"""
super(CallTipWidget, self).enterEvent(event)
- self._hide_timer.stop()
+ if (self._hide_timer.isActive() and
+ self.app.topLevelAt(QtGui.QCursor.pos()) == self):
+ self._hide_timer.stop()
def hideEvent(self, event):
""" Reimplemented to disconnect signal handlers and event filter.
@@ -140,25 +143,7 @@ class CallTipWidget(QtGui.QLabel):
# 'CallTipWidget' interface
#--------------------------------------------------------------------------
- def show_call_info(self, point, call_line, doc=None, maxlines=20):
- """ Attempts to show the specified call line and docstring at the
- current cursor location. The docstring is possibly truncated for
- length.
- """
- if doc:
- match = re.match("(?:[^\n]*\n){%i}" % maxlines, doc)
- if match:
- doc = doc[:match.end()] + '\n[Documentation continues...]'
- else:
- doc = ''
-
- if doc:
- doc = '\n\n'.join([call_line, doc])
- else:
- doc = call_line
- return self.show_tip(point, doc)
-
- def show_tip(self, point, tip):
+ def show_tip(self, point, tip, wrapped_tiplines):
""" Attempts to show the specified tip at the current cursor location.
"""
# Attempt to find the cursor position at which to show the call tip.
@@ -170,6 +155,30 @@ class CallTipWidget(QtGui.QLabel):
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.setText(tip)
self.resize(self.sizeHint())
@@ -263,21 +272,7 @@ class CallTipWidget(QtGui.QLabel):
# this check. But on Mac OS, it sometimes happens the other way
# around when the tooltip is created.
self.app.topLevelAt(QtGui.QCursor.pos()) != self):
- self._hide_timer.start(300, self)
-
- def _format_tooltip(self,doc):
- import textwrap
-
- # make sure a long argument list does not make
- # the first row overflow the width of the actual tip body
- rows = doc.split("\n")
- # An object which is not a callable has '<no docstring>' as doc
- if len(rows) == 1:
- return doc
- max_text_width = max(80, max([len(x) for x in rows[1:]]))
- rows= textwrap.wrap(rows[0],max_text_width) + rows[1:]
- doc = "\n".join(rows)
- return doc
+ self._hide_timer.start(800, self)
#------ Signal handlers ----------------------------------------------------
@@ -288,6 +283,7 @@ class CallTipWidget(QtGui.QLabel):
if cursor.position() <= self._start_position:
self.hide()
else:
- position, commas = self._find_parenthesis(self._start_position + 1)
- if position != -1:
- self.hide()
+ if not self.hide_timer_on:
+ position, commas = self._find_parenthesis(self._start_position + 1)
+ if position != -1:
+ self.hide()
diff --git a/spyderlib/widgets/dependencies.py b/spyderlib/widgets/dependencies.py
index 1344501..baf4dd7 100644
--- a/spyderlib/widgets/dependencies.py
+++ b/spyderlib/widgets/dependencies.py
@@ -125,6 +125,7 @@ class DependenciesDialog(QDialog):
QDialog.__init__(self, parent)
self.setWindowTitle("Spyder %s: %s" % (__version__,
_("Optional Dependencies")))
+ self.setWindowIcon(get_icon('advanced.png'))
self.setModal(True)
self.view = DependenciesTableView(self, [])
diff --git a/spyderlib/widgets/editor.py b/spyderlib/widgets/editor.py
index 4c309c9..b7e0269 100644
--- a/spyderlib/widgets/editor.py
+++ b/spyderlib/widgets/editor.py
@@ -29,10 +29,11 @@ import re
import os.path as osp
# Local imports
-from spyderlib.utils import encoding, sourcecode, programs, codeanalysis
+from spyderlib.utils import encoding, sourcecode, codeanalysis
from spyderlib.utils.dochelpers import getsignaturefromtext
-from spyderlib.utils.module_completion import (module_completion,
- get_preferred_submodules)
+from spyderlib.utils import introspection
+from spyderlib.utils.introspection.module_completion import (module_completion,
+ get_preferred_submodules)
from spyderlib.baseconfig import _, DEBUG, STDOUT, STDERR
from spyderlib.config import EDIT_FILTERS, EDIT_EXT, get_filter, EDIT_FILETYPES
from spyderlib.utils.qthelpers import (get_icon, create_action, add_actions,
@@ -283,7 +284,8 @@ class ThreadManager(QObject):
class FileInfo(QObject):
"""File properties"""
- def __init__(self, filename, encoding, editor, new, threadmanager):
+ def __init__(self, filename, encoding, editor, new, threadmanager,
+ introspection_plugin):
QObject.__init__(self)
self.threadmanager = threadmanager
self.filename = filename
@@ -292,19 +294,23 @@ class FileInfo(QObject):
self.editor = editor
self.path = []
self.submods_thread = GetSubmodulesThread()
- self.rope_project = codeeditor.get_rope_project()
+ self.introspection_plugin = introspection_plugin
+
self.classes = (filename, None, None)
self.analysis_results = []
self.todo_results = []
self.lastmodified = QFileInfo(filename).lastModified()
- self.connect(editor, SIGNAL('trigger_code_completion(bool)'),
+ self.connect(editor, SIGNAL('trigger_code_completion(bool)'),
self.trigger_code_completion)
- self.connect(editor, SIGNAL('show_object_info(int)'),
+ self.connect(editor, SIGNAL('trigger_token_completion(bool)'),
+ self.trigger_token_completion)
+ self.connect(editor, SIGNAL('show_object_info(int)'),
self.show_object_info)
self.connect(editor, SIGNAL("go_to_definition(int)"),
self.go_to_definition)
-
+ self.connect(editor, SIGNAL("go_to_definition_regex(int)"),
+ self.go_to_definition_regex)
self.connect(editor, SIGNAL('textChanged()'),
self.text_changed)
@@ -319,32 +325,31 @@ class FileInfo(QObject):
self.submods_thread.start()
def update_extension_modules(self):
- self.rope_project.set_pref('extension_modules',
+ self.introspection_plugin.set_pref('extension_modules',
self.submods_thread.submods)
def text_changed(self):
"""Editor's text has changed"""
self.emit(SIGNAL('text_changed_at(QString,int)'),
self.filename, self.editor.get_position('cursor'))
-
- def trigger_code_completion(self, automatic):
+
+ def trigger_code_completion(self, automatic, token_based=False):
"""Trigger code completion"""
source_code = self.get_source_code()
offset = self.editor.get_position('cursor')
text = self.editor.get_text('sol', 'cursor')
-
- if text.lstrip().startswith('import '):
+
+ jedi = self.introspection_plugin.name == 'jedi'
+
+ comp_list = ''
+ if not jedi and text.lstrip().startswith('import '):
text = text.lstrip()
comp_list = module_completion(text, self.path)
words = text.split(' ')
if ',' in words[-1]:
words = words[-1].split(',')
- if comp_list:
- self.editor.show_completion_list(comp_list,
- completion_text=words[-1],
- automatic=automatic)
- return
- elif text.lstrip().startswith('from '):
+ completion_text = words[-1]
+ elif not jedi and text.lstrip().startswith('from '):
text = text.lstrip()
comp_list = module_completion(text, self.path)
words = text.split(' ')
@@ -352,20 +357,49 @@ class FileInfo(QObject):
words = words[:-2] + words[-1].split('(')
if ',' in words[-1]:
words = words[:-2] + words[-1].split(',')
- self.editor.show_completion_list(comp_list,
- completion_text=words[-1],
- automatic=automatic)
- return
+ completion_text = words[-1]
else:
- textlist = self.rope_project.get_completion_list(source_code,
- offset,
- self.filename)
- if textlist:
- completion_text = re.split(r"[^a-zA-Z0-9_]", text)[-1]
- self.editor.show_completion_list(textlist, completion_text,
- automatic)
- return
+ if token_based:
+ func = self.introspection_plugin.get_token_completion_list
+ else:
+ func = self.introspection_plugin.get_completion_list
+ comp_list = func(source_code, offset, self.filename)
+ if comp_list:
+ completion_text = re.findall(r"[\w.]+", text, re.UNICODE)[-1]
+ if '.' in completion_text:
+ completion_text = completion_text.split('.')[-1]
+ if comp_list:
+ self.editor.show_completion_list(comp_list, completion_text,
+ automatic)
+
+ def trigger_token_completion(self, automatic):
+ """Trigger a completion using tokens only"""
+ self.trigger_code_completion(automatic, token_based=True)
+
+ def find_nearest_function_call(self, position):
+ """Find the nearest function call at or prior to current position"""
+ source_code = self.get_source_code()
+ position = min(len(source_code) - 1, position)
+ orig_pos = position
+ # find the first preceding opening parens (keep track of closing parens)
+ if not position or not source_code[position] == '(':
+ close_parens = 0
+ position -= 1
+ while position and not (source_code[position] == '(' and close_parens == 0):
+ if source_code[position] == ')':
+ close_parens += 1
+ elif source_code[position] == '(' and close_parens:
+ close_parens -= 1
+ position -= 1
+ if source_code[position] in ['\n', '\r']:
+ position = orig_pos
+ break
+ if position and source_code[position] == '(':
+ position -= 1
+
+ return position
+
def show_object_info(self, position, auto=True):
"""Show signature calltip and/or docstring in the Object Inspector"""
# auto is True means that this method was called automatically,
@@ -373,10 +407,11 @@ class FileInfo(QObject):
# case, we don't want to force the object inspector to be visible,
# to avoid polluting the window layout
source_code = self.get_source_code()
- offset = position
+ offset = self.find_nearest_function_call(position)
- helplist = self.rope_project.get_calltip_and_docs(source_code, offset,
- self.filename)
+ # Get calltip and docs
+ helplist = self.introspection_plugin.get_calltip_and_docs(source_code,
+ offset, self.filename)
if not helplist:
return
obj_fullname = ''
@@ -396,7 +431,7 @@ class FileInfo(QObject):
# the following attempt may succeed:
signature = getsignaturefromtext(doc_text, obj_name)
if not obj_fullname:
- obj_fullname = codeeditor.get_primary_at(source_code, offset)
+ obj_fullname = sourcecode.get_primary_at(source_code, offset)
if obj_fullname and not obj_fullname.startswith('self.') and doc_text:
# doc_text was generated by utils.dochelpers.getdoc
if type(doc_text) is dict:
@@ -423,17 +458,24 @@ class FileInfo(QObject):
if signature:
self.editor.show_calltip('Arguments', signature, signature=True,
at_position=position)
-
- def go_to_definition(self, position):
+
+ def go_to_definition(self, position, regex=False):
"""Go to definition"""
source_code = self.get_source_code()
offset = position
- fname, lineno = self.rope_project.get_definition_location(source_code,
- offset, self.filename)
+ if regex:
+ func = self.introspection_plugin.get_definition_location_regex
+ else:
+ func = self.introspection_plugin.get_definition_location
+ fname, lineno = func(source_code, offset, self.filename)
if fname is not None and lineno is not None:
self.emit(SIGNAL("edit_goto(QString,int,QString)"),
fname, lineno, "")
-
+
+ def go_to_definition_regex(self, position):
+ """Go to definition using regex lookups"""
+ self.go_to_definition(position, regex=True)
+
def get_source_code(self):
"""Return associated editor source code"""
return to_text_string(self.editor.toPlainText())
@@ -605,6 +647,7 @@ class EditorStack(QWidget):
if ccs not in syntaxhighlighters.COLOR_SCHEME_NAMES:
ccs = syntaxhighlighters.COLOR_SCHEME_NAMES[0]
self.color_scheme = ccs
+ self.introspection_plugin = introspection.get_plugin(self)
self.__file_status_flag = False
@@ -636,7 +679,7 @@ class EditorStack(QWidget):
lambda: self.emit(SIGNAL('zoom_in()')))
self.zoomoutsc = newsc(QKeySequence.ZoomOut,
lambda: self.emit(SIGNAL('zoom_out()')))
-
+
def get_shortcut_data(self):
"""
Returns shortcut data, a list of tuples (shortcut, text, default)
@@ -756,7 +799,7 @@ class EditorStack(QWidget):
def inspect_current_object(self):
"""Inspect current object in Object Inspector"""
- if programs.is_module_installed('rope'):
+ if self.introspection_plugin:
editor = self.get_current_editor()
position = editor.get_position('cursor')
finfo = self.get_current_finfo()
@@ -917,7 +960,7 @@ class EditorStack(QWidget):
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
@@ -1293,6 +1336,9 @@ class EditorStack(QWidget):
self._refresh_outlineexplorer()
self.emit(SIGNAL('refresh_file_dependent_actions()'))
self.emit(SIGNAL('update_plugin_title()'))
+ editor = self.get_current_editor()
+ if editor:
+ editor.setFocus()
if new_index is not None:
if index < new_index:
@@ -1385,7 +1431,7 @@ class EditorStack(QWidget):
finfo.editor.document().setModified(False)
self.modification_changed(index=index)
self.analyze_script(index)
- codeeditor.validate_rope_project()
+ self.introspection_plugin.validate()
#XXX CodeEditor-only: re-scan the whole text to rebuild outline
# explorer data from scratch (could be optimized because
@@ -1739,7 +1785,7 @@ class EditorStack(QWidget):
finfo.editor.set_text(txt)
finfo.editor.document().setModified(False)
finfo.editor.set_cursor_position(position)
- codeeditor.validate_rope_project()
+ self.introspection_plugin.validate()
#XXX CodeEditor-only: re-scan the whole text to rebuild outline
# explorer data from scratch (could be optimized because
@@ -1772,7 +1818,8 @@ class EditorStack(QWidget):
Returns finfo object (instead of editor as in previous releases)
"""
editor = codeeditor.CodeEditor(self)
- finfo = FileInfo(fname, enc, editor, new, self.threadmanager)
+ finfo = FileInfo(fname, enc, editor, new, self.threadmanager,
+ self.introspection_plugin)
self.add_to_data(finfo, set_current)
self.connect(finfo, SIGNAL(
"send_to_inspector(QString,QString,QString,QString,bool)"),
@@ -1873,7 +1920,7 @@ class EditorStack(QWidget):
docstring = to_text_string(qstr4)
doc = {'obj_text': objtxt, 'name': name, 'argspec': argspec,
'note': note, 'docstring': docstring}
- self.inspector.set_rope_doc(doc, force_refresh=force)
+ self.inspector.set_editor_doc(doc, force_refresh=force)
editor = self.get_current_editor()
editor.setFocus()
diff --git a/spyderlib/widgets/externalshell/monitor.py b/spyderlib/widgets/externalshell/monitor.py
index fbf3418..9f72481 100644
--- a/spyderlib/widgets/externalshell/monitor.py
+++ b/spyderlib/widgets/externalshell/monitor.py
@@ -18,7 +18,7 @@ from spyderlib.utils.dochelpers import (getargtxt, getdoc, getsource,
getobjdir, isdefined)
from spyderlib.utils.bsdsocket import (communicate, read_packet, write_packet,
PACKET_NOT_RECEIVED)
-from spyderlib.utils.module_completion import module_completion
+from spyderlib.utils.introspection.module_completion import module_completion
from spyderlib.baseconfig import get_conf_path, get_supported_types, DEBUG
from spyderlib.py3compat import getcwd, is_text_string, pickle, _thread
diff --git a/spyderlib/widgets/externalshell/pythonshell.py b/spyderlib/widgets/externalshell/pythonshell.py
index 17f8bc7..26abfce 100644
--- a/spyderlib/widgets/externalshell/pythonshell.py
+++ b/spyderlib/widgets/externalshell/pythonshell.py
@@ -521,8 +521,8 @@ The process may not exit as a result of clicking this button
if not running:
if self.is_ipykernel:
self.emit(SIGNAL("ipython_kernel_start_error(QString)"),
- _("The console failed to start! That's all we know "
- ":(<br>Please close it and open a new one."))
+ _("The kernel failed to start!! That's all we know... "
+ "Please close this console and open a new one."))
else:
QMessageBox.critical(self, _("Error"),
_("A Python console failed to start!"))
diff --git a/spyderlib/widgets/findreplace.py b/spyderlib/widgets/findreplace.py
index fe68092..4cf68b1 100644
--- a/spyderlib/widgets/findreplace.py
+++ b/spyderlib/widgets/findreplace.py
@@ -158,7 +158,7 @@ class FindReplace(QWidget):
self.toggle_replace_widgets)
self.togglereplace_sc.setContext(Qt.WidgetWithChildrenShortcut)
- escape_sc = QShortcut(QKeySequence("Escape"), parent, self.hide)
+ escape_sc = QShortcut(QKeySequence("Escape"), self, self.hide)
escape_sc.setContext(Qt.WidgetWithChildrenShortcut)
self.highlight_timer = QTimer(self)
diff --git a/spyderlib/widgets/ipython.py b/spyderlib/widgets/ipython.py
index 49b4bb3..904bd26 100644
--- a/spyderlib/widgets/ipython.py
+++ b/spyderlib/widgets/ipython.py
@@ -38,7 +38,7 @@ from spyderlib.utils.dochelpers import getargspecfromtext, getsignaturefromtext
from spyderlib.utils.qthelpers import (get_std_icon, create_toolbutton,
add_actions, create_action, get_icon,
restore_keyevent)
-from spyderlib.utils import programs
+from spyderlib.utils import programs, sourcecode
from spyderlib.widgets.browser import WebView
from spyderlib.widgets.calltip import CallTipWidget
from spyderlib.widgets.mixins import (BaseEditMixin, InspectObjectMixin,
@@ -110,7 +110,7 @@ class IPythonControlWidget(TracebackLinksMixin, InspectObjectMixin, QTextEdit,
TracebackLinksMixin.__init__(self)
InspectObjectMixin.__init__(self)
self.found_results = []
- self.signature_widget = CallTipWidget(self)
+ self.calltip_widget = CallTipWidget(self, hide_timer_on=True)
# To not use Spyder calltips obtained through the monitor
self.calltips = False
@@ -223,8 +223,7 @@ class IPythonShellWidget(RichIPythonWidget):
#---- Public API ----------------------------------------------------------
def set_ipyclient(self, ipyclient):
- """Bind this IPython widget to an IPython client widget
- (see spyderlib/plugins/ipythonconsole.py)"""
+ """Bind this shell widget to an IPython client one"""
self.ipyclient = ipyclient
self.exit_requested.connect(ipyclient.exit_callback)
@@ -323,7 +322,7 @@ These commands were executed:
call_info, doc = None, None
else:
call_info, doc = call_tip(content, format_call=True)
- if not call_info:
+ if call_info is None and doc is not None:
name = content['name'].split('.')[-1]
argspec = getargspecfromtext(doc)
if argspec:
@@ -399,12 +398,13 @@ class IPythonClient(QWidget, SaveHistoryMixin):
self.exit_callback = lambda: plugin.close_console(client=self)
#------ Public API --------------------------------------------------------
- def show_shellwidget(self):
+ def show_shellwidget(self, give_focus=True):
"""Show shellwidget and configure it"""
self.infowidget.hide()
self.shellwidget.show()
self.infowidget.setHtml(BLANK)
- self.get_control().setFocus()
+ if give_focus:
+ self.get_control().setFocus()
# Connect shellwidget to the client
self.shellwidget.set_ipyclient(self)
@@ -420,12 +420,13 @@ class IPythonClient(QWidget, SaveHistoryMixin):
self.shellwidget.executed.connect(self.auto_refresh_namespacebrowser)
def show_kernel_error(self, error):
- """Show kernel initialization errors in the client"""
- # Remove explanation about how to kill the kernel
- # (doesn't apply to us)
+ """Show kernel initialization errors in infowidget"""
+ # Remove explanation about how to kill the kernel (doesn't apply to us)
error = error.split('issues/2049')[-1]
- error = error.replace('\n', '<br>')
# Remove unneeded blank lines at the beginning
+ eol = sourcecode.get_eol_chars(error)
+ if eol:
+ error = error.replace(eol, '<br>')
while error.startswith('<br>'):
error = error[4:]
# Remove connection message
@@ -437,7 +438,7 @@ class IPythonClient(QWidget, SaveHistoryMixin):
# From http://stackoverflow.com/q/7691569/438386
error = error.replace('-', '‑')
- message = _("An error ocurred while starting the kernel!")
+ 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,
diff --git a/spyderlib/widgets/mixins.py b/spyderlib/widgets/mixins.py
index b5d1d4a..33d8f9f 100644
--- a/spyderlib/widgets/mixins.py
+++ b/spyderlib/widgets/mixins.py
@@ -15,6 +15,7 @@ import os
import re
import sre_constants
import textwrap
+from xml.sax.saxutils import escape
from spyderlib.qt.QtGui import (QTextCursor, QTextDocument, QApplication,
QCursor, QToolTip)
@@ -47,31 +48,43 @@ class BaseEditMixin(object):
#------Calltips
def _format_signature(self, text):
- lines = []
+ formatted_lines = []
name = text.split('(')[0]
- rows = textwrap.wrap(text, 50)
+ 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,
'<span style=\'color: red; font-weight: bold\'>' + \
char + '</span>')
- lines.append(r)
- concat_str = '<br>' + ' '*(len(name)+1)
- signature = concat_str.join(lines)
- return signature
+ formatted_lines.append(r)
+ signature = '<br>'.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 = self._format_signature(text)
+ text, wrapped_textlines = self._format_signature(text)
+ else:
+ if isinstance(text, list):
+ text = "\n ".join(text)
+ text = text.replace('\n', '<br>')
+ if len(text) > self.calltip_size:
+ text = text[:self.calltip_size] + " ..."
+
+ # Formatting text
font = self.font()
size = font.pointSize()
family = font.family()
@@ -79,13 +92,9 @@ class BaseEditMixin(object):
% (family, size, color)
format2 = '<div style=\'font-family: "%s"; font-size: %spt\'>'\
% (family, size-1 if size > 9 else size)
- if isinstance(text, list):
- text = "\n ".join(text)
- text = text.replace('\n', '<br>')
- if len(text) > self.calltip_size and not signature:
- text = text[:self.calltip_size] + " ..."
tiptext = format1 + ('<b>%s</b></div>' % title) + '<hr>' + \
format2 + text + "</div>"
+
# Showing tooltip at cursor position:
cx, cy = self.get_coordinates('cursor')
if at_line is not None:
@@ -96,7 +105,7 @@ class BaseEditMixin(object):
point.setX(point.x()+self.get_linenumberarea_width())
point.setY(point.y()+font.pointSize()+5)
if signature:
- self.signature_widget.show_call_info(point, tiptext)
+ self.calltip_widget.show_tip(point, tiptext, wrapped_textlines)
else:
QToolTip.showText(point, tiptext)
diff --git a/spyderlib/widgets/sourcecode/base.py b/spyderlib/widgets/sourcecode/base.py
index 8aa94f3..9e76184 100644
--- a/spyderlib/widgets/sourcecode/base.py
+++ b/spyderlib/widgets/sourcecode/base.py
@@ -212,7 +212,7 @@ class TextEditBaseWidget(QPlainTextEdit, BaseEditMixin):
self.calltip_position = None
self.calltip_font = QFont()
self.completion_text = ""
- self.signature_widget = CallTipWidget(self)
+ self.calltip_widget = CallTipWidget(self, hide_timer_on=True)
# Highlight current line color
self.currentline_color = QColor(Qt.red).lighter(190)
@@ -849,7 +849,7 @@ class TextEditBaseWidget(QPlainTextEdit, BaseEditMixin):
def mousePressEvent(self, event):
"""Reimplement Qt method"""
if os.name != 'posix' and event.button() == Qt.MidButton:
- self.signature_widget.hide()
+ self.calltip_widget.hide()
self.setFocus()
event = QMouseEvent(QEvent.MouseButtonPress, event.pos(),
Qt.LeftButton, Qt.LeftButton, Qt.NoModifier)
@@ -857,7 +857,7 @@ class TextEditBaseWidget(QPlainTextEdit, BaseEditMixin):
QPlainTextEdit.mouseReleaseEvent(self, event)
self.paste()
else:
- self.signature_widget.hide()
+ self.calltip_widget.hide()
QPlainTextEdit.mousePressEvent(self, event)
def focusInEvent(self, event):
diff --git a/spyderlib/widgets/sourcecode/codeeditor.py b/spyderlib/widgets/sourcecode/codeeditor.py
index 183bb99..8ce894c 100644
--- a/spyderlib/widgets/sourcecode/codeeditor.py
+++ b/spyderlib/widgets/sourcecode/codeeditor.py
@@ -47,6 +47,7 @@ from spyderlib.utils.qthelpers import (add_actions, create_action, keybinding,
mimedata2url, get_icon)
from spyderlib.utils.dochelpers import getobj
from spyderlib.utils import encoding, sourcecode
+from spyderlib.utils.sourcecode import ALL_LANGUAGES
from spyderlib.utils.debug import log_last_error, log_dt
from spyderlib.widgets.editortools import PythonCFM
from spyderlib.widgets.sourcecode.base import TextEditBaseWidget
@@ -56,202 +57,11 @@ from spyderlib import dependencies
#%% This line is for cell execution testing
# For debugging purpose:
-LOG_FILENAME = get_conf_path('rope.log')
-
+LOG_FILENAME = get_conf_path('codeeditor.log')
DEBUG_EDITOR = DEBUG >= 3
#===============================================================================
-# Code introspection features: rope integration
-#===============================================================================
-ROPE_REQVER = '>=0.9.2'
-dependencies.add('rope',
- _("Editor's code completion, go-to-definition and help"),
- required_version=ROPE_REQVER)
-
-try:
- try:
- from spyderlib import rope_patch
- rope_patch.apply()
- except ImportError:
- # rope 0.9.2/0.9.3 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 RopeProject(object):
- def __init__(self):
- self.project = None
- self.create_rope_project(root_path=get_conf_path())
-
- #------rope integration
- def create_rope_project(self, root_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:
- self.project = None
- if DEBUG_EDITOR:
- log_last_error(LOG_FILENAME,
- "create_rope_project: %r" % root_path)
- except TypeError:
- # Compatibility with new Mercurial API (>= 1.3).
- # New versions of rope (> 0.9.2) already handle this issue
- self.project = None
- if DEBUG_EDITOR:
- log_last_error(LOG_FILENAME,
- "create_rope_project: %r" % root_path)
- self.validate_rope_project()
-
- def close_rope_project(self):
- if self.project is not None:
- self.project.close()
-
- def validate_rope_project(self):
- if self.project is not None:
- self.project.validate(self.project.root)
-
- def set_pref(self, key, value):
- if self.project is not None:
- self.project.prefs.set(key, value)
-
- def get_completion_list(self, source_code, offset, filename):
- if self.project is None:
- return []
- 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 for proposal in proposals]
- except Exception as _error: #analysis:ignore
- if DEBUG_EDITOR:
- log_last_error(LOG_FILENAME, "get_completion_list")
- return []
-
- def get_calltip_and_docs(self, source_code, offset, filename):
- if self.project is None:
- return []
- 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 [cts, doc_text]
- except Exception as _error: #analysis:ignore
- if DEBUG_EDITOR:
- log_last_error(LOG_FILENAME, "get_calltip_text")
- return []
-
- def get_definition_location(self, source_code, offset, filename):
- if self.project is None:
- return (None, 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
- return filename, lineno
- except Exception as _error: #analysis:ignore
- if DEBUG_EDITOR:
- log_last_error(LOG_FILENAME, "get_definition_location")
- return (None, None)
-
-
-ROPE_PROJECT = None
-def get_rope_project():
- """Create a single rope project"""
- global ROPE_PROJECT
- if ROPE_PROJECT is None:
- ROPE_PROJECT = RopeProject()
- return ROPE_PROJECT
-
-def validate_rope_project():
- """Validate rope project"""
- get_rope_project().validate_rope_project()
-
-
-#===============================================================================
# Go to line dialog box
#===============================================================================
class GoToLineDialog(QDialog):
@@ -449,16 +259,6 @@ class BlockUserData(QTextBlockUserData):
bud_list.pop(bud_list.index(self))
-def get_primary_at(source_code, offset):
- """Return Python object in *source_code* at *offset*"""
- try:
- import rope.base.worder
- word_finder = rope.base.worder.Worder(source_code, True)
- return word_finder.get_primary_at(offset)
- except ImportError:
- return
-
-
def set_scrollflagarea_painter(painter, light_color):
"""Set scroll flag area painter pen and brush colors"""
painter.setPen(QColor(light_color).darker(120))
@@ -487,26 +287,23 @@ def get_file_language(filename, text=None):
class CodeEditor(TextEditBaseWidget):
"""Source Code Editor Widget based exclusively on Qt"""
- LANGUAGES = {
- ('py', 'pyw', 'python', 'ipy'): (sh.PythonSH, '#', PythonCFM),
- ('pyx', 'pxi', 'pxd'): (sh.CythonSH, '#', PythonCFM),
- ('f', 'for', 'f77'): (sh.Fortran77SH, 'c', None),
- ('f90', 'f95', 'f2k'): (sh.FortranSH, '!', None),
- ('pro',): (sh.IdlSH, ';', None),
- ('m',): (sh.MatlabSH, '%', None),
- ('diff', 'patch', 'rej'): (sh.DiffSH, '', None),
- ('po', 'pot'): (sh.GetTextSH, '#', None),
- ('nsi', 'nsh'): (sh.NsisSH, '#', None),
- ('htm', 'html'): (sh.HtmlSH, '', None),
- ('css',): (sh.CssSH, '', None),
- ('xml',): (sh.XmlSH, '', None),
- ('js',): (sh.JsSH, '', None),
- ('c', 'cc', 'cpp', 'cxx', 'h', 'hh', 'hpp', 'hxx',
- ): (sh.CppSH, '//', None),
- ('cl',): (sh.OpenCLSH, '//', None),
- ('bat', 'cmd', 'nt'): (sh.BatchSH, 'rem ', None),
- ('properties', 'session', 'ini', 'inf', 'reg', 'url',
- 'cfg', 'cnf', 'aut', 'iss'): (sh.IniSH, '#', None),
+ LANGUAGES ={ 'Python': (sh.PythonSH, '#', PythonCFM),
+ 'Cython': (sh.Fortran77SH, 'c', PythonCFM),
+ 'Fortran77': (sh.Fortran77SH, 'c', None),
+ 'Fortran': (sh.FortranSH, '!', None),
+ 'Idl': (sh.IdlSH, ';', None),
+ 'Matlab': (sh.MatlabSH, '%', None),
+ 'Diff': (sh.DiffSH, '', None),
+ 'GetText': (sh.GetTextSH, '#', None),
+ 'Nsis': (sh.NsisSH, '#', None),
+ 'Html': (sh.HtmlSH, '', None),
+ 'Css': (sh.CssSH, '', None),
+ 'Xml': (sh.XmlSH, '', None),
+ 'Js': (sh.JsSH, '', None),
+ 'Cpp': (sh.CppSH, '//', None),
+ 'OpenCL': (sh.OpenCLSH, '//', None),
+ 'Batch': (sh.BatchSH, 'rem ', None),
+ 'Ini': (sh.IniSH, '#', None),
}
try:
import pygments # analysis:ignore
@@ -520,6 +317,7 @@ class CodeEditor(TextEditBaseWidget):
def __init__(self, parent=None):
TextEditBaseWidget.__init__(self, parent)
+ self.setFocusPolicy(Qt.StrongFocus)
# Calltips
calltip_size = CONF.get('editor_appearance', 'calltips/size')
@@ -848,8 +646,8 @@ class CodeEditor(TextEditBaseWidget):
self.comment_string = ''
sh_class = sh.TextSH
if language is not None:
- for key in self.LANGUAGES:
- if language.lower() in key:
+ 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
@@ -878,6 +676,52 @@ class CodeEditor(TextEditBaseWidget):
def is_cython(self):
return self.highlighter_class is sh.CythonSH
+ def is_python_like(self):
+ return self.is_python() or self.is_cython()
+
+ def intelligent_tab(self):
+ """Provide intelligent behavoir for Tab key press"""
+ leading_text = self.get_text('sol', 'cursor')
+ if not leading_text.strip():
+ # blank line
+ self.indent_or_replace()
+ elif self.in_comment_or_string() and not leading_text.endswith(' '):
+ # in a word in a comment
+ self.do_token_completion()
+ elif leading_text.endswith('import ') or leading_text[-1] == '.':
+ # blank import or dot completion
+ self.do_code_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_code_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_code_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
@@ -927,10 +771,10 @@ class CodeEditor(TextEditBaseWidget):
self.document().setModified(True)
def get_current_object(self):
- """Return current object (string) -- requires 'rope'"""
+ """Return current object (string) """
source_code = to_text_string(self.toPlainText())
offset = self.get_position('cursor')
- return get_primary_at(source_code, offset)
+ return sourcecode.get_primary_at(source_code, offset)
#------Find occurences
def __find_first(self, text):
@@ -1006,7 +850,7 @@ class CodeEditor(TextEditBaseWidget):
if self.has_selected_text() and self.get_selected_text() != text:
return
- if (self.is_python() or self.is_cython()) and \
+ if (self.is_python_like()) and \
(sourcecode.is_keyword(to_text_string(text)) or \
to_text_string(text) == 'self'):
return
@@ -1200,7 +1044,7 @@ class CodeEditor(TextEditBaseWidget):
def add_remove_breakpoint(self, line_number=None, condition=None,
edit_condition=False):
"""Add/remove breakpoint"""
- if not self.is_python() and not self.is_cython():
+ if not self.is_python_like():
return
if line_number is None:
block = self.textCursor().block()
@@ -1275,12 +1119,23 @@ class CodeEditor(TextEditBaseWidget):
def do_code_completion(self):
"""Trigger code completion"""
if not self.is_completion_widget_visible():
- self.emit(SIGNAL('trigger_code_completion(bool)'), False)
+ if self.is_python_like() and not self.in_comment_or_string():
+ self.emit(SIGNAL('trigger_code_completion(bool)'), False)
+ else:
+ self.do_token_completion()
+
+ def do_token_completion(self):
+ """Trigger a token-based completion"""
+ if not self.is_completion_widget_visible():
+ self.emit(SIGNAL('trigger_token_completion(bool)'), False)
def do_go_to_definition(self):
"""Trigger go-to-definition"""
self.emit(SIGNAL("go_to_definition(int)"), self.textCursor().position())
+ def show_object_info(self, position):
+ """Trigger a calltip"""
+ self.emit(SIGNAL('show_object_info(int)'), position)
#-----edge line
def set_edge_line_enabled(self, state):
@@ -1805,7 +1660,7 @@ class CodeEditor(TextEditBaseWidget):
Returns True if indent needed to be fixed
"""
- if not self.is_python() and not self.is_cython():
+ if not self.is_python_like():
return
cursor = self.textCursor()
block_nb = cursor.blockNumber()
@@ -1814,6 +1669,7 @@ class CodeEditor(TextEditBaseWidget):
prevtext = to_text_string(cursor.block().text()).rstrip()
if not prevtext.strip().startswith('#'):
break
+
indent = self.get_block_indentation(block_nb)
correct_indent = self.get_block_indentation(prevline)
@@ -1868,7 +1724,7 @@ class CodeEditor(TextEditBaseWidget):
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() or self.is_cython():
+ if self.is_python_like():
if not self.fix_indent(forward=True):
self.add_prefix(self.indent_chars)
else:
@@ -1911,7 +1767,7 @@ class CodeEditor(TextEditBaseWidget):
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() or self.is_cython():
+ if self.is_python_like():
if not self.fix_indent(forward=False):
self.remove_prefix(self.indent_chars)
elif leading_text.endswith('\t'):
@@ -2260,7 +2116,8 @@ class CodeEditor(TextEditBaseWidget):
# Read-only context-menu
self.readonly_menu = QMenu(self)
add_actions(self.readonly_menu,
- (self.copy_action, None, selectall_action))
+ (self.copy_action, None, selectall_action,
+ self.gotodef_action))
def keyPressEvent(self, event):
"""Reimplement Qt method"""
@@ -2274,7 +2131,7 @@ class CodeEditor(TextEditBaseWidget):
self.hide_tooltip_if_necessary(key)
if key in (Qt.Key_Enter, Qt.Key_Return):
if not shift and not ctrl:
- if self.add_colons_enabled and self.is_python() and \
+ if self.add_colons_enabled and self.is_python_like() and \
self.autoinsert_colons():
self.insert_text(':' + self.get_line_separator())
self.fix_indent()
@@ -2321,12 +2178,12 @@ class CodeEditor(TextEditBaseWidget):
self.completion_text = self.completion_text[:-1]
elif key == Qt.Key_Period:
self.insert_text(text)
- if (self.is_python() or self.is_cython()) and not \
+ 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.emit(SIGNAL('trigger_code_completion(bool)'), True)
+ self.do_code_completion()
elif key == Qt.Key_Home:
self.stdkey_home(shift, ctrl)
elif key == Qt.Key_End:
@@ -2338,16 +2195,16 @@ class CodeEditor(TextEditBaseWidget):
position = self.get_position('cursor')
s_trailing_text = self.get_text('cursor', 'eol').strip()
if self.close_parentheses_enabled and \
- (len(s_trailing_text) == 0 or \
- s_trailing_text[0] in (',', ')', ']', '}')):
+ (len(s_trailing_text) == 0 or \
+ s_trailing_text[0] in (',', ')', ']', '}')):
self.insert_text('()')
cursor = self.textCursor()
cursor.movePosition(QTextCursor.PreviousCharacter)
self.setTextCursor(cursor)
else:
self.insert_text(text)
- if (self.is_python() or self.is_cython()) and \
- self.get_text('sol', 'cursor') and self.calltips:
+ if self.is_python_like() and self.get_text('sol', 'cursor') and \
+ self.calltips:
self.emit(SIGNAL('show_object_info(int)'), position)
elif text in ('[', '{') and not self.has_selected_text() \
and self.close_parentheses_enabled:
@@ -2363,7 +2220,8 @@ class CodeEditor(TextEditBaseWidget):
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)\
+ elif ((key in (Qt.Key_ParenRight, Qt.Key_BraceRight, Qt.Key_BracketRight)) or (
+ shift and key == Qt.Key_0)) \
and not self.has_selected_text() and self.close_parentheses_enabled \
and not self.textCursor().atBlockEnd():
cursor = self.textCursor()
@@ -2371,7 +2229,7 @@ class CodeEditor(TextEditBaseWidget):
QTextCursor.KeepAnchor)
text = to_text_string(cursor.selectedText())
if text == {Qt.Key_ParenRight: ')', Qt.Key_BraceRight: '}',
- Qt.Key_BracketRight: ']'}[key]:
+ Qt.Key_BracketRight: ']', Qt.Key_0: ')'}[key]:
cursor.clearSelection()
self.setTextCursor(cursor)
else:
@@ -2399,11 +2257,19 @@ class CodeEditor(TextEditBaseWidget):
elif key == Qt.Key_Tab:
# Important note: <TAB> can't be called with a QShortcut because
# of its singular role with respect to widget focus management
- self.indent_or_replace()
+ if not self.has_selected_text() 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+<TAB>, could be treated as a QShortcut but
# there is no point since <TAB> can't (see above)
- self.unindent()
+ if not self.has_selected_text() 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:
@@ -2417,7 +2283,7 @@ class CodeEditor(TextEditBaseWidget):
if self.go_to_definition_enabled and \
event.modifiers() & Qt.ControlModifier:
text = self.get_word_at(event.pos())
- if text and (self.is_python() or self.is_cython())\
+ if text and (self.is_python_like())\
and not sourcecode.is_keyword(to_text_string(text)):
if not self.__cursor_changed:
QApplication.setOverrideCursor(
@@ -2456,9 +2322,11 @@ class CodeEditor(TextEditBaseWidget):
cursor.select(QTextCursor.WordUnderCursor)
text = to_text_string(cursor.selectedText())
if self.go_to_definition_enabled and text is not None\
- and (self.is_python() or self.is_cython())\
+ and (self.is_python_like())\
and not sourcecode.is_keyword(text):
self.emit(SIGNAL("go_to_definition(int)"), position)
+ else:
+ self.emit(SIGNAL("go_to_definition_regex(int)"), position)
def mousePressEvent(self, event):
"""Reimplement Qt method"""
diff --git a/spyderplugins/p_pylint.py b/spyderplugins/p_pylint.py
index 76dc7ad..3167efe 100644
--- a/spyderplugins/p_pylint.py
+++ b/spyderplugins/p_pylint.py
@@ -26,7 +26,7 @@ from spyderplugins.widgets.pylintgui import PylintWidget, PYLINT_PATH
class PylintConfigPage(PluginConfigPage):
def setup_page(self):
settings_group = QGroupBox(_("Settings"))
- save_box = self.create_checkbox(_("Save script before analyzing it"),
+ save_box = self.create_checkbox(_("Save file before analyzing it"),
'save_before', default=True)
hist_group = QGroupBox(_("History"))
@@ -38,7 +38,7 @@ class PylintConfigPage(PluginConfigPage):
min_=10, max_=1000000, step=10)
results_group = QGroupBox(_("Results"))
- results_label1 = QLabel(_("Pylint plugin results are stored here:"))
+ results_label1 = QLabel(_("Results are stored here:"))
results_label1.setWordWrap(True)
# Warning: do not try to regroup the following QLabel contents with
@@ -86,7 +86,7 @@ class Pylint(PylintWidget, SpyderPluginMixin):
#------ SpyderPluginWidget API --------------------------------------------
def get_plugin_title(self):
"""Return widget title"""
- return _("Pylint")
+ return _("Static code analysis")
def get_plugin_icon(self):
"""Return widget icon"""
@@ -122,7 +122,7 @@ class Pylint(PylintWidget, SpyderPluginMixin):
self.main.redirect_internalshell_stdio)
self.main.add_dockwidget(self)
- pylint_act = create_action(self, _("Run pylint code analysis"),
+ pylint_act = create_action(self, _("Run static code analysis"),
triggered=self.run_pylint)
pylint_act.setEnabled(PYLINT_PATH is not None)
self.register_shortcut(pylint_act, context="Pylint",
diff --git a/spyderplugins/widgets/pylintgui.py b/spyderplugins/widgets/pylintgui.py
index a69c7c3..877c053 100644
--- a/spyderplugins/widgets/pylintgui.py
+++ b/spyderplugins/widgets/pylintgui.py
@@ -198,7 +198,7 @@ class PylintWidget(QWidget):
self.connect(self.filecombo, SIGNAL('valid(bool)'), self.show_data)
browse_button = create_toolbutton(self, icon=get_icon('fileopen.png'),
- tip=_('Select Python script'),
+ tip=_('Select Python file'),
triggered=self.select_file)
self.ratelabel = QLabel()
@@ -206,7 +206,7 @@ class PylintWidget(QWidget):
self.log_button = create_toolbutton(self, icon=get_icon('log.png'),
text=_("Output"),
text_beside_icon=True,
- tip=_("Complete Pylint output"),
+ tip=_("Complete output"),
triggered=self.show_log)
self.treewidget = ResultsTree(self)
@@ -267,8 +267,8 @@ class PylintWidget(QWidget):
def select_file(self):
self.emit(SIGNAL('redirect_stdio(bool)'), False)
- filename, _selfilter = getopenfilename(self, _("Select Python script"),
- getcwd(), _("Python scripts")+" (*.py ; *.pyw)")
+ filename, _selfilter = getopenfilename(self, _("Select Python file"),
+ getcwd(), _("Python files")+" (*.py ; *.pyw)")
self.emit(SIGNAL('redirect_stdio(bool)'), False)
if filename:
self.analyze(filename)
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/spyder.git
More information about the debian-science-commits
mailing list