Repository: spyder-ide/spyder

Issue:
Can't use pythonw as interpreter when needed on Mac
<!--- **PLEASE READ:** Before submitting here, please carefully consult our *Troubleshooting Guide* at https://github.com/spyder-ide/spyder/wiki/Troubleshooting-Guide-and-FAQ and search the issues page for your error/problem, as most posted bugs are duplicates or easy fixes.

If you don't find anything, please provide a detailed step-by-step description (in English) of the problem and what led up to it below. Issue reports without a clear way to reproduce them will be closed. Thanks! --->

## Problem Description
When I try to run a wxPython script (such as the example below) from within spyder, I get this error: 

> SystemExit: This program needs access to the screen. Please run with a
> Framework build of python, and only when you are logged in
> on the main display of your Mac.

The normal solution is to run the script in pythonw (from anaconda python.app package). FWIW, the shell script to start spyder itself is running pythonw via the shebang. 

When I try to use the "Preferences/Python interpreter" command to change to pythonw, it will not accept that change with error message:

> You selected an invalid Python interpreter for the console so the previous interpreter will stay. 
 Please make sure to select a valid one.

```
import wx
app = wx.PySimpleApp() # create the App
frm = wx.Frame(None) # create a frame
btn = wx.StaticText(frm,-1,'An MT frame is boring')
frm.Show()
app.MainLoop()

```


## Package Versions

* Spyder: 3.2.8
* Python: 3.6.5 (64 bit)
* Qt: 5.9.4
* PyQt: 5.9.2
* Operating System: Mac OS X 10.12.6

### Dependencies
<!--- Please go to the menu entry Help > Dependencies,
press the Copy to clipboard button and paste below --->

```
IPython >=4.0    :  6.3.1 (OK)
cython >=0.21    :  None (NOK)
jedi >=0.9.0     :  0.12.0 (OK)
nbconvert >=4.0  :  5.3.1 (OK)
numpy >=1.7      :  1.13.3 (OK)
pandas >=0.13.1  :  None (NOK)
psutil >=0.3     :  5.4.5 (OK)
pycodestyle >=2.3:  2.4.0 (OK)
pyflakes >=0.6.0 :  1.6.0 (OK)
pygments >=2.0   :  2.2.0 (OK)
pylint >=0.25    :  1.8.4 (OK)
qtconsole >=4.2.0:  4.3.1 (OK)
rope >=0.9.4     :  0.10.7 (OK)
sphinx >=0.6.6   :  1.7.4 (OK)
sympy >=0.7.3    :  None (NOK)
```



Discussion:
Thanks for reporting. We'll try to fix this in our next release.
@dalthviz, please work on this one. Users should be able to use `pythonw` or `pythonw.exe` as a valid interpreter.

Resolving patch:
diff --git a/spyder/utils/programs.py b/spyder/utils/programs.py
--- a/spyder/utils/programs.py
+++ b/spyder/utils/programs.py
@@ -474,6 +474,23 @@ def is_python_interpreter(filename):
     if (not osp.isfile(real_filename) or encoding.is_text_file(real_filename)
         or not is_python_interpreter_valid_name(filename)):
         return False
+    elif is_pythonw(filename):
+        return True
+    else:
+        return check_python_help(filename)
+
+
+def is_pythonw(filename):
+    """Check that the python interpreter has 'pythonw'."""
+    pattern = r'.*python(\d\.?\d*)?w(.exe)?$'
+    if re.match(pattern, filename, flags=re.I) is None:
+        return False
+    else:
+        return True
+
+
+def check_python_help(filename):
+    """Check that the python interpreter can execute help."""
     try:
         proc = run_program(filename, ["-h"])
         output = to_text_string(proc.communicate()[0])


Test patch:
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
@@ -20,6 +20,7 @@
 if os.name == 'nt':
     python_dir = os.environ['PYTHON'] if os.environ.get('CI', None) else ''
     VALID_INTERPRETER = os.path.join(python_dir, 'python.exe')
+    VALID_W_INTERPRETER = os.path.join(python_dir, 'pythonw.exe')
     INVALID_INTERPRETER = os.path.join(python_dir, 'Scripts', 'ipython.exe')
 else:
     home_dir = os.environ['HOME']
@@ -27,6 +28,13 @@
     INVALID_INTERPRETER = os.path.join(home_dir, 'miniconda', 'bin', 'ipython')
 
 
+@pytest.mark.skipif(not os.name == 'nt' or os.environ.get('CI', None) is None,
+                    reason='It only runs in CI services.'
+                           'Linux does not have pythonw executables.')
+def test_is_valid_w_interpreter():
+    assert is_python_interpreter(VALID_W_INTERPRETER)
+
+
 @flaky(max_runs=3)
 @pytest.mark.skipif(os.name == 'nt' or os.environ.get('CI', None) is None,
                     reason='gets stuck on Windows and fails sometimes locally') # FIXME