Repository: spyder-ide/spyder

Issue:
Errors running or importing code because sys.argv is empty
Hi,
Upgraded to spyder 3.1. and tried to import tensorflow and got these errors on the ipython console
```
import tensorflow
Traceback (most recent call last):

  File "<ipython-input-1-a649b509054f>", line 1, in <module>
    import tensorflow

  File "/usr/local/lib/python2.7/dist-packages/tensorflow/__init__.py", line 24, in <module>
    from tensorflow.python import *

  File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/__init__.py", line 100, in <module>
    from tensorflow.python.platform import app

  File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/platform/app.py", line 23, in <module>
    from tensorflow.python.platform import flags

  File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/platform/flags.py", line 25, in <module>
    _global_parser = _argparse.ArgumentParser()

  File "/usr/lib/python2.7/argparse.py", line 1586, in __init__
    prog = _os.path.basename(_sys.argv[0])

IndexError: list index out of range
```

It was working before in spyder3.0.2. tensorflow and ipython (5.1.0) versions have not changed. It also works on spyder's python console tab:

```
Python 2.7.12 (default, Nov 19 2016, 06:48:10) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import tensorflow
>>> tensorflow.__version__
'0.12.1'
```
OS is Ubuntu 16.04 64 bit
P.S same issue with spyder git master.


Discussion:
@andfoy, this one is for you because you changed that. `sys.argv` has to be equal to `['']` but you left it equal to `[]`. This is a very simple change :-)

And please don't forget to do the PR against the `3.1.x` branch, not `3.x`.
@ccordoba12 Actually, the line that restarts the ``sys.argv`` argument is defined as follows (As per PR #3918):
```python
clear_argv = 'import sys;sys.argv = [''];del sys'
```
In that case, I don't know exactly where the reinitialization of arguments fails.
 
@ccordoba12  If I try the following setting, then the import will work, but it is correct to make this modification?
```python
clear_argv = 'import sys;sys.argv = ["", ""];del sys'
```
I think the original problem is that you were using single quotes for the `clear_argv` code and for the contents of `sys.argv` itself, so this should work:

    clear_argv = "import sys;sys.argv = [''];del sys"

(notice the double outside quotes :-)

Resolving patch:
diff --git a/spyder/plugins/ipythonconsole.py b/spyder/plugins/ipythonconsole.py
--- a/spyder/plugins/ipythonconsole.py
+++ b/spyder/plugins/ipythonconsole.py
@@ -586,7 +586,8 @@ class IPythonConsole(SpyderPluginWidget):
     focus_changed = Signal()
     edit_goto = Signal((str, int, str), (str, int, str, bool))
 
-    def __init__(self, parent):
+    def __init__(self, parent, testing=False):
+        """Ipython Console constructor."""
         if PYQT5:
             SpyderPluginWidget.__init__(self, parent, main = parent)
         else:
@@ -605,9 +606,11 @@ def __init__(self, parent):
         self.clients = []
         self.mainwindow_close = False
         self.create_new_client_if_empty = True
+        self.testing = testing
 
         # Initialize plugin
-        self.initialize_plugin()
+        if not self.testing:
+            self.initialize_plugin()
 
         layout = QVBoxLayout()
         self.tabwidget = Tabs(self, self.menu_actions)
@@ -619,7 +622,7 @@ def __init__(self, parent):
             self.tabwidget.setDocumentMode(True)
         self.tabwidget.currentChanged.connect(self.refresh_plugin)
         self.tabwidget.move_data.connect(self.move_tab)
-                     
+
         self.tabwidget.set_close_function(self.close_client)
 
         if sys.platform == 'darwin':
@@ -635,7 +638,8 @@ def __init__(self, parent):
         # Find/replace widget
         self.find_widget = FindReplace(self)
         self.find_widget.hide()
-        self.register_widget_shortcuts(self.find_widget)
+        if not self.testing:
+            self.register_widget_shortcuts(self.find_widget)
         layout.addWidget(self.find_widget)
 
         self.setLayout(layout)
@@ -721,11 +725,12 @@ def refresh_plugin(self):
             widgets = []
         self.find_widget.set_editor(control)
         self.tabwidget.set_corner_widgets({Qt.TopRightCorner: widgets})
-        if client:
+        if client and not self.testing:
             sw = client.shellwidget
             self.variableexplorer.set_shellwidget_from_id(id(sw))
             self.help.set_shell(sw)
-        self.main.last_console_plugin_focus_was_python = False
+        if not self.testing:
+            self.main.last_console_plugin_focus_was_python = False
         self.update_plugin_title.emit()
 
     def get_plugin_actions(self):
@@ -1233,7 +1238,9 @@ def create_kernel_spec(self):
         #    manager
         spy_path = get_module_source_path('spyder')
         sc_path = osp.join(spy_path, 'utils', 'site')
-        spy_pythonpath = self.main.get_spyder_pythonpath()
+        spy_pythonpath = []
+        if not self.testing:
+            spy_pythonpath = self.main.get_spyder_pythonpath()
 
         default_interpreter = CONF.get('main_interpreter', 'default')
         if default_interpreter:
@@ -1319,8 +1326,11 @@ def create_kernel_manager_and_kernel_client(self, connection_file,
         kernel_manager._kernel_spec = self.create_kernel_spec()
 
         # Save stderr in a file to read it later in case of errors
-        stderr = codecs.open(stderr_file, 'w', encoding='utf-8')
-        kernel_manager.start_kernel(stderr=stderr)
+        if not self.testing:
+            stderr = codecs.open(stderr_file, 'w', encoding='utf-8')
+            kernel_manager.start_kernel(stderr=stderr)
+        else:
+            kernel_manager.start_kernel()
 
         # Kernel client
         kernel_client = kernel_manager.client()
diff --git a/spyder/utils/ipython/start_kernel.py b/spyder/utils/ipython/start_kernel.py
--- a/spyder/utils/ipython/start_kernel.py
+++ b/spyder/utils/ipython/start_kernel.py
@@ -72,7 +72,7 @@ def kernel_config():
         spy_cfg.IPKernelApp.exec_lines = []
 
     # Clean terminal arguments input
-    clear_argv = 'import sys;sys.argv = [''];del sys'
+    clear_argv = "import sys;sys.argv = [''];del sys"
     spy_cfg.IPKernelApp.exec_lines.append(clear_argv)
 
     # Pylab configuration


Test patch:
diff --git a/continuous_integration/appveyor/modules_test.bat b/continuous_integration/appveyor/modules_test.bat
--- a/continuous_integration/appveyor/modules_test.bat
+++ b/continuous_integration/appveyor/modules_test.bat
@@ -5,6 +5,12 @@ setlocal enableextensions enabledelayedexpansion
 set SPYDER=%APPVEYOR_BUILD_FOLDER%\spyder
 set TEST_CI_WIDGETS=True
 
+:: These tests are failing intermittently in Python 2.
+:: Disabling them for now.
+if %PYTHON_VERSION%==2.7 (
+    exit 0
+)
+
 :: Spyder
 for /r "%SPYDER%" %%f in (*.py) do (
     set file=%%f
@@ -51,9 +57,6 @@ for /r "%SPYDER%" %%f in (*.py) do (
     ) else if not "!file:utils\help=!"=="!file!" (
         echo --- NOT testing %%f ---
         echo.
-    ) else if not "!file:utils\introspection=!"=="!file!" (
-        echo --- NOT testing %%f ---
-        echo.
     ) else if "%%f"=="%SPYDER%\utils\bsdsocket.py" (
         echo --- NOT testing %%f ---
         echo.
@@ -61,6 +64,14 @@ for /r "%SPYDER%" %%f in (*.py) do (
         :: It can't be tested outside of a Python console
         echo --- NOT testing %%f ---
         echo.
+    ) else if "%%f"=="%SPYDER%\utils\introspection\module_completion.py" (
+        :: This is failing randomly
+        echo --- NOT testing %%f ---
+        echo.
+    ) else if "%%f"=="%SPYDER%\utils\introspection\plugin_client.py" (
+        :: We have to investigate this failure!
+        echo --- NOT testing %%f ---
+        echo.
     ) else if "%%f"=="%SPYDER%\widgets\editor.py" (
         :: This is making AppVeyor to time out!
         echo --- NOT testing %%f ---
diff --git a/spyder/plugins/tests/__init__.py b/spyder/plugins/tests/__init__.py
new file mode 100644
diff --git a/spyder/plugins/tests/test_ipythonconsole.py b/spyder/plugins/tests/test_ipythonconsole.py
new file mode 100644
--- /dev/null
+++ b/spyder/plugins/tests/test_ipythonconsole.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright © Spyder Project Contributors
+# Licensed under the terms of the MIT License
+#
+
+import pytest
+from qtpy.QtCore import Qt
+from pytestqt import qtbot
+from spyder.py3compat import to_text_string
+from spyder.plugins.ipythonconsole import IPythonConsole
+
+
+# Qt Test Fixtures
+#--------------------------------
+@pytest.fixture
+def ipyconsole_bot(qtbot):
+    widget = IPythonConsole(None, testing=True)
+    widget.create_new_client()
+    qtbot.addWidget(widget)
+    return qtbot, widget
+
+
+# Tests
+#-------------------------------
+def test_sys_argv_clear(ipyconsole_bot):
+    qtbot, ipyconsole = ipyconsole_bot
+    shell = ipyconsole.get_current_shellwidget()
+    client = ipyconsole.get_current_client()
+
+    qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=6000)
+    shell.execute('import sys; A = sys.argv')
+    argv = shell.get_value("A")
+    assert argv == ['']
diff --git a/spyder/utils/tests/test_programs.py b/spyder/utils/tests/test_programs.py
--- a/spyder/utils/tests/test_programs.py
+++ b/spyder/utils/tests/test_programs.py
@@ -50,13 +50,13 @@ def test_run_python_script_in_terminal_with_wdir_empty(tmpdir, qtbot):
     assert res == 'done'
 
 
-@pytest.mark.skipif(os.environ.get('CI', None) == True,
+@pytest.mark.skipif(os.environ.get('CI', None) is None,
                     reason='It only runs in CI services.')
 def test_is_valid_interpreter():
     assert is_python_interpreter(VALID_INTERPRETER)
 
 
-@pytest.mark.skipif(os.environ.get('CI', None) == True,
+@pytest.mark.skipif(os.environ.get('CI', None) is None,
                     reason='It only runs in CI services.')
 def test_is_invalid_interpreter():
     assert not is_python_interpreter(INVALID_INTERPRETER)
diff --git a/spyder/widgets/variableexplorer/tests/test_dataframeeditor.py b/spyder/widgets/variableexplorer/tests/test_dataframeeditor.py
--- a/spyder/widgets/variableexplorer/tests/test_dataframeeditor.py
+++ b/spyder/widgets/variableexplorer/tests/test_dataframeeditor.py
@@ -23,6 +23,7 @@
 import pytest
 
 # Local imports
+from spyder.utils.programs import is_module_installed
 from spyder.widgets.variableexplorer import dataframeeditor
 from spyder.widgets.variableexplorer.dataframeeditor import (
     DataFrameEditor, DataFrameModel)
@@ -186,6 +187,8 @@ def test_header_bom():
     model = editor.dataModel
     assert model.headerData(1, orientation=Qt.Horizontal) == "Date (MMM-YY)"
 
+@pytest.mark.skipif(is_module_installed('pandas', '<0.19'),
+                    reason="It doesn't work for Pandas 0.19-")
 def test_header_encoding():
     df = read_csv(os.path.join(FILES_PATH, 'issue_3896.csv'))
     editor = DataFrameEditor(None)