Editor: "Re-run last script" action was disabled when current file was not Python

Update Issue 1382
Status: Fixed
Merge "Re-run last script" bugfix from 2.2
Removed debug print accidently committed with revision c55356dabdfa
Merge from 2.2 (removed debug print accidently committed)
Added support for Google TODO comments: "TODO(username@domain.com): blabla"

Update Issue 1386
Status: Fixed
Merge from 2.2 (added support for Google TODO comments)
Windows installers: adding pyflakes and rope to spyderlib\utils\external instead
of Python packages root directory (Lib\site-packages). This is much cleaner and
avoids removing accidently previously installed versions of pyflakes and rope
when uninstalling Spyder.
Merge from 2.2 (Windows installers: adding pyflakes and rope to spyderlib\utils\external)
Python 3 compatibility. As rope and pyflakes have specific versions for Python 3,
we must add a target version for the Windows installers if we want to continue
including rope and pyflakes in our Windows binary installers. This will force us
to publish at least 4 installers for 1 release: Python 2.7 and 3.3, 32 and 64bit.

In time, when building Spyder 2.3 installers, this option will have to be
overriden using the --target-version=X.Y command line option when building
installers for Python versions different from the version executing setup.py.
Spyder GUI: all toolbars are now located at top-left corner of widgets

Update Issue 1385
Status: Fixed
IPython Console: Update to make it work with the new 1.0 API

- "Kernel died" message is not printed anymore, probably a side effect of the
new API.
Spyder GUI: main toolbar is now the first toolbar shown in the main window's
toolbar area, as the user would expect it to be. This requires to reset Spyder
settings to defaults.
Merge from 2.2 (main toolbar was not shown as the first toolbar)
Backed out changeset: 984a3f6cfe2c (fixed conflict with revision 8d97e69090d9)
Merge from 2.2 (backout changeset 984a3f6cfe2c)
Python 3 compatibility. First step towards Python 3 support. Still unstable.
Needs more testing:
  * see internal console for issues with module_completion
  * try to open Preferences dialog box (it crashes Spyder on Windows)
  * ...
Python 3 compatibility. Added 'from __future__ import print_function' statements
accidently removed in revision 0943fd32156a
Python 3 compatibility. Fixed remaining bytes/str conflicts in Popen string outputs.
Python 3 compatibility. Fixed execfile in sitecustomize and replaced remaining os.getcwdu
Python 3 compatibility. Result of running the following `2to3` command line:
2to3 -w -n -f apply -f dict -f except -f exitfunc -f filter -f has_key -f map
-f ne -f raise -f ws_comma -f xrange -f xreadlines -f zip spyderlib

Here is the raw diff generated by 2to3:

--- spyderlib\spyder.py	(original)
+++ spyderlib\spyder.py	(refactored)
@@ -1205,7 +1205,7 @@
             for plugin in (self.projectexplorer, self.outlineexplorer):
                 plugin.dockwidget.close()

-        self.set_window_settings(hexstate,window_size, prefs_dialog_size, pos,
+        self.set_window_settings(hexstate, window_size, prefs_dialog_size, pos,
                                  is_maximized, is_fullscreen)

         for plugin in self.widgetlist:
@@ -1975,7 +1975,7 @@
         self.app = app
         self.window = window
     def __dir__(self):
-        return self.__dict__.keys() +\
+        return list(self.__dict__.keys()) +\
                  [x for x in dir(self.__class__) if x[0] != '_']
     def versions(self):
         return get_versions()
--- spyderlib\plugins\editor.py	(original)
+++ spyderlib\plugins\editor.py	(refactored)
@@ -1438,8 +1438,8 @@
             username = encoding.to_unicode_from_fs(os.environ.get('USER',
                                                                   '-'))
         VARS = {
-            'date':time.ctime(),
-            'username':username,
+            'date': time.ctime(),
+            'username': username,
         }
         try:
             text = text % VARS
--- spyderlib\plugins\externalconsole.py	(original)
+++ spyderlib\plugins\externalconsole.py	(refactored)
@@ -702,7 +702,7 @@
         # prevent keyboard input from accidentally entering the editor
         # during repeated, rapid entry of debugging commands.
         self.emit(SIGNAL("edit_goto(QString,int,QString,bool)"),
-                  fname, lineno, '',False)
+                  fname, lineno, '', False)
         if shellwidget.is_ipykernel:
             # Focus client widget, not kernel
             ipw = self.main.ipyconsole.get_focus_widget()
@@ -1059,7 +1059,7 @@
                          self.main.editor.load)
             self.connect(self, SIGNAL("edit_goto(QString,int,QString,bool)"),
                          lambda fname, lineno, word, processevents:
-                         self.main.editor.load(fname,lineno,word,
+                         self.main.editor.load(fname, lineno, word,
                                                processevents=processevents))
             self.connect(self.main.editor,
                          SIGNAL('run_in_current_extconsole(QString,QString,QString,bool)'),
--- spyderlib\utils\classparser.py	(original)
+++ spyderlib\utils\classparser.py	(refactored)
@@ -89,7 +89,7 @@
         return self._lineno

     def get_class_names(self):
-        return self._class_info.keys()
+        return list(self._class_info.keys())

     def get_class_info(self, name):
         return self._class_info[name]
@@ -105,7 +105,7 @@
     #  Mixin class providing access to function names and info.

     def get_function_names(self):
-        return self._function_info.keys()
+        return list(self._function_info.keys())

     def get_function_info(self, name):
         return self._function_info[name]
@@ -130,7 +130,7 @@
         SuiteInfoBase.__init__(self, tree and tree[-1] or None)

     def get_method_names(self):
-        return self._function_info.keys()
+        return list(self._function_info.keys())

     def get_method_info(self, name):
         return self._function_info[name]
--- spyderlib\utils\module_completion.py	(original)
+++ spyderlib\utils\module_completion.py	(refactored)
@@ -118,7 +118,7 @@
         spy_modules.remove('__init__')
     spy_modules = list(spy_modules)

-    if modules_db.has_key('rootmodules'):
+    if 'rootmodules' in modules_db:
         return spy_modules + modules_db['rootmodules']

     t = time()
@@ -196,9 +196,9 @@

 def dot_completion(mod, paths):
     if len(mod) < 2:
-        return filter(lambda x: x.startswith(mod[0]), get_root_modules(paths))
+        return [x for x in get_root_modules(paths) if x.startswith(mod[0])]
     completion_list = try_import('.'.join(mod[:-1]), True)
-    completion_list = filter(lambda x: x.startswith(mod[-1]), completion_list)
+    completion_list = [x for x in completion_list if x.startswith(mod[-1])]
     completion_list = ['.'.join(mod[:-1] + [el]) for el in completion_list]
     return completion_list

@@ -250,7 +250,7 @@
                 words = words[:-2] + words[-1].split('(')
             if ',' in words[-1]:
                 words = words[:-2] + words[-1].split(',')
-            return filter(lambda x: x.startswith(words[-1]), completion_list)
+            return [x for x in completion_list if x.startswith(words[-1])]
         else:
             return completion_list

@@ -259,7 +259,7 @@

 def reset():
     """Clear root modules database"""
-    if modules_db.has_key('rootmodules'):
+    if 'rootmodules' in modules_db:
         del modules_db['rootmodules']


@@ -268,7 +268,7 @@
     Get all submodules of the main scientific modules and others of our
     interest
     """
-    if modules_db.has_key('submodules'):
+    if 'submodules' in modules_db:
         return modules_db['submodules']

     mods = ['numpy', 'scipy', 'sympy', 'pandas', 'networkx', 'statsmodels',
--- spyderlib\utils\vcs.py	(original)
+++ spyderlib\utils\vcs.py	(refactored)
@@ -70,7 +70,7 @@
         raise RuntimeError(_("For %s support, please install one of the<br/> "
                              "following tools:<br/><br/>  %s")
                            % (infos['name'],
-                              ', '.join([name for name,cmd in infos['commit']])
+                              ', '.join([name for name, cmd in infos['commit']])
                               ))


--- spyderlib\utils\external\lockfile.py	(original)
+++ spyderlib\utils\external\lockfile.py	(refactored)
@@ -76,7 +76,7 @@
     # XXX Implement an atomic thingamajig for win32
     def symlink(value, filename):    #analysis:ignore
         newlinkname = filename+"."+unique()+'.newlink'
-        newvalname = os.path.join(newlinkname,"symlink")
+        newvalname = os.path.join(newlinkname, "symlink")
         os.mkdir(newlinkname)
         f = _open(newvalname, 'wb')
         f.write(to_binary_string(value))
@@ -91,7 +91,7 @@

     def readlink(filename):   #analysis:ignore
         try:
-            fObj = _open(os.path.join(filename,'symlink'), 'rb')
+            fObj = _open(os.path.join(filename, 'symlink'), 'rb')
         except IOError as e:
             if e.errno == errno.ENOENT or e.errno == errno.EIO:
                 raise OSError(e.errno, None)
--- spyderlib\widgets\dicteditor.py	(original)
+++ spyderlib\widgets\dicteditor.py	(refactored)
@@ -619,7 +619,7 @@
                         self.imshow_action, self.save_array_action,
                         self.insert_action, self.remove_action,
                         self.copy_action, self.paste_action,
-                        None, self.rename_action,self.duplicate_action,
+                        None, self.rename_action, self.duplicate_action,
                         None, resize_action, None, self.truncate_action,
                         self.inplace_action, self.collvalue_action]
         if ndarray is not FakeObject:
--- spyderlib\widgets\importwizard.py	(original)
+++ spyderlib\widgets\importwizard.py	(refactored)
@@ -11,7 +11,7 @@
 from __future__ import print_function

 from spyderlib.qt.QtGui import (QTableView, QVBoxLayout, QHBoxLayout,
-                                QGridLayout, QWidget,QDialog, QTextEdit,
+                                QGridLayout, QWidget, QDialog, QTextEdit,
                                 QTabWidget, QPushButton, QLabel, QSpacerItem,
                                 QSizePolicy, QCheckBox, QColor, QRadioButton,
                                 QLineEdit, QFrame, QMenu, QIntValidator,
--- spyderlib\widgets\externalshell\sitecustomize.py	(original)
+++ spyderlib\widgets\externalshell\sitecustomize.py	(refactored)
@@ -132,8 +132,7 @@
         # Add a minimal library (with spyderlib) at the end of sys.path to
         # be able to connect our monitor to the external console
         app_pythonpath = 'Spyder.app/Contents/Resources/lib/python2.7'
-        full_pythonpath = filter(lambda p: p.endswith(app_pythonpath),
-                                 sys.path)
+        full_pythonpath = [p for p in sys.path if p.endswith(app_pythonpath)]
         if full_pythonpath:
             sys.path.remove(full_pythonpath[0])
             sys.path.append(full_pythonpath[0] + osp.sep + 'minimal-lib')
--- spyderlib\widgets\externalshell\start_ipython_kernel.py	(original)
+++ spyderlib\widgets\externalshell\start_ipython_kernel.py	(refactored)
@@ -92,8 +92,7 @@
     # Run lines of code at startup
     run_lines_o = CONF.get('ipython_console', 'startup/run_lines')
     if run_lines_o:
-        spy_cfg.IPKernelApp.exec_lines = map(lambda x: x.strip(),
-                                         run_lines_o.split(','))
+        spy_cfg.IPKernelApp.exec_lines = [x.strip() for x in run_lines_o.split(',')]

     # Run a file at startup
     use_file_o = CONF.get('ipython_console', 'startup/use_run_file')
--- spyderlib\widgets\sourcecode\base.py	(original)
+++ spyderlib\widgets\sourcecode\base.py	(refactored)
@@ -660,7 +660,7 @@
             before = self.is_cursor_before(self.calltip_position,
                                            char_offset=1)
             other = key in (Qt.Key_ParenRight, Qt.Key_Period, Qt.Key_Tab)
-            if calltip_char not in ('?','(') or before or other:
+            if calltip_char not in ('?', '(') or before or other:
                 QToolTip.hideText()
         except (IndexError, TypeError):
             QToolTip.hideText()
--- spyderlib\widgets\sourcecode\codeeditor.py	(original)
+++ spyderlib\widgets\sourcecode\codeeditor.py	(refactored)
@@ -500,7 +500,7 @@
         import pygments  # analysis:ignore
     except ImportError:
         # Removing all syntax highlighters requiring pygments to be installed
-        for key, (sh_class, comment_string, CFMatch) in LANGUAGES.items():
+        for key, (sh_class, comment_string, CFMatch) in list(LANGUAGES.items()):
             if issubclass(sh_class, sh.PygmentsSH):
                 LANGUAGES.pop(key)

@@ -2084,7 +2084,7 @@
     def __unmatched_braces_in_line(self, text):
         block = self.textCursor().block()
         line_pos = block.position()
-        for pos,char in enumerate(text):
+        for pos, char in enumerate(text):
             if char in ['(', '[', '{']:
                 match = self.find_brace_match(line_pos+pos, char, forward=True)
                 if (match is None) or (match > line_pos+len(text)):
--- spyderlib\widgets\sourcecode\syntaxhighlighters.py	(original)
+++ spyderlib\widgets\sourcecode\syntaxhighlighters.py	(refactored)
@@ -268,7 +268,7 @@
         match = self.PROG.search(text)
         index = 0
         while match:
-            for key, value in match.groupdict().items():
+            for key, value in list(match.groupdict().items()):
                 if value:
                     start, end = match.span(key)
                     index += end-start
@@ -500,7 +500,7 @@
     kw = r"\b" + any("keyword", keywords.split()) + r"\b"
     builtin = r"\b" + any("builtin", builtins.split()+C_TYPES.split()) + r"\b"
     if comment is None:
-        comment = any("comment", [r"//[^\n]*",r"\/\*(.*?)\*\/"])
+        comment = any("comment", [r"//[^\n]*", r"\/\*(.*?)\*\/"])
     comment_start = any("comment_start", [r"\/\*"])
     comment_end = any("comment_end", [r"\*\/"])
     if instance is None:
@@ -808,7 +808,7 @@

 def make_html_patterns():
     """Strongly inspired from idlelib.ColorDelegator.make_pat """
-    tags = any("builtin", [r"<",r"[\?/]?>", r"(?<=<).*?(?=[ >])"])
+    tags = any("builtin", [r"<", r"[\?/]?>", r"(?<=<).*?(?=[ >])"])
     keywords = any("keyword", [r" [\w:-]*?(?==)"])
     string = any("string", [r'".*?"'])
     comment = any("comment", [r"<!--.*?-->"])
@@ -864,7 +864,7 @@
             self._lexer = get_lexer_by_name(self._lang_name)
         BaseSH.__init__(self, parent, font, color_scheme)

-    def get_fmt(self,typ):
+    def get_fmt(self, typ):
         """ Get the format code for this type """
         # Exact matches first
         for key in self._tokmap: