Repository: spyder-ide/spyder

Issue:
Spyder crashes when attempting to define function named setup in IPython console
## Description of your problem

If I try to define a function named setup in the IPython console, it will instantly crash Spyder

**What steps will reproduce the problem?**

1. In IPython console type:
``` python
def setup(
```

**What is the expected output? What do you see instead?**
Should let me define the function. Worst case it should error, but it shouldn't bring down the whole IDE.


## Versions and main components

* Spyder Version: 3.2.0
* Python Version: 3.6.2
* Qt Version: 5.7.1
* PyQt Version: 5.8.1
* Operating system: Fedora 26

## Dependencies

IPython >=4.0 : 6.1.0 (OK)
cython >=0.21 : None (NOK)
jedi >=0.9.0 : 0.10.2 (OK)
nbconvert >=4.0 : 5.2.1 (OK)
numpy >=1.7 : 1.12.1 (OK)
pandas >=0.13.1 : 0.20.1 (OK)
psutil >=0.3 : 5.0.1 (OK)
pycodestyle >=2.3: 2.3.1 (OK)
pyflakes >=0.6.0 : 1.5.0 (OK)
pygments >=2.0 : 2.2.0 (OK)
pylint >=0.25 : 1.7.1 (OK)
qtconsole >=4.2.0: 4.3.0 (OK)
rope >=0.9.4 : 0.10.5 (OK)
sphinx >=0.6.6 : 1.5.2 (OK)
sympy >=0.7.3 : None (NOK)



Discussion:
I'm unable to reproduce this one

![captura de pantalla de 2017-07-25 11-44-26](https://user-images.githubusercontent.com/1878982/28583459-d3d3ac78-712e-11e7-9418-87bd5a0ac5b0.png)

## Version and main components

* Spyder Version: 3.2.1.dev0 f38444a
* Python Version: 3.6.1
* Qt Versions: 5.8.0, PyQt5 5.8.2 on Linux

## Dependencies
```
pyflakes >=0.6.0 :  1.5.0 (OK)
pycodestyle >=2.3:  2.3.1 (OK)
pygments >=2.0   :  2.2.0 (OK)
pandas >=0.13.1  :  None (NOK)
numpy >=1.7      :  None (NOK)
sphinx >=0.6.6   :  1.6.3 (OK)
rope >=0.9.4     :  0.10.5 (OK)
jedi >=0.9.0     :  0.10.2 (OK)
psutil >=0.3     :  5.2.2 (OK)
nbconvert >=4.0  :  5.2.1 (OK)
sympy >=0.7.3    :  None (NOK)
cython >=0.21    :  None (NOK)
qtconsole >=4.2.0:  4.3.0 (OK)
IPython >=4.0    :  6.1.0 (OK)
pylint >=0.25    :  1.7.2 (OK)

```

Did you type the commands or copy and paste? I can paste it in without an issue, but typing it in, once I put in the open parentheses it attempts to lookup setup in the Help widget, which seems to cause it to call the function, which returns empty usage info for distutils.core.setup().

Setting SPYDER_DEBUG=3, I get this when it crashes:

``` console
usage:  [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
   or:  --help [cmd1 cmd2 ...]
   or:  --help-commands
   or:  cmd --help

error: no commands supplied
```

I'm guessing distutils is killing Spyder with os._exit() or help isn't catching the SystemExit exception. I'd have to look more to sure. If the first, I think the only way to protect against that would be to do the lookups in subprocess. If the second, a try block would work. But I'm not sure why anything is being invoked in the first place.

I see two issues.
1.) I'm not sure help should be called for user defined functions
2.) Help should protect itself and Spyder from side effects of it's lookups


Actually, I'm typing in the function definition and it works without any problems, even after importing ``distutils`` and ``setuptools``. However, as you mentioned, we should isolate our signature help functions to prevent such crashes
I suspect it has to do with me having a setup.py file in the root of my current working directory.
Let me try that scenario
@andfoy, please take a look at this one ASAP.
I tried to define the function inside a folder that contains a distutils/setuptools ``setup.py`` file, and it works without any problem

![captura de pantalla de 2017-07-28 13-03-33](https://user-images.githubusercontent.com/1878982/28730343-637eedc0-7395-11e7-9f3a-283ed6ca2f02.png)

It works also with Python 3.6:
![captura de pantalla de 2017-07-28 13-07-13](https://user-images.githubusercontent.com/1878982/28730461-ec266aae-7395-11e7-9ab9-d875bcb01273.png)

Did you restart Spyder after populating setup.py? Otherwise it will be in the modules cache.

I can recreate it with an new project and a setup.py file like so:

``` python
from setuptools import setup

setup()
```

@avylove I'll try to do it as you suggest
Did you execute the file before trying to define the function?
Even under this scenario, I'm able to define the function
![captura de pantalla de 2017-07-28 13-31-38](https://user-images.githubusercontent.com/1878982/28731401-5edccac2-7399-11e7-8b17-3ff79ef15b7f.png)

Do you have the Help widget enabled? And Help -> "Automatic connections" enabled for the IPython console? I actually don't need to define setup, just type `setup(` but I think you can cut through all that and just search for setup in Help.

@avylove Finally I can reproduce this one! Thanks for the help
@ccordoba12 It seems that we're not importing modules only if they raise ImportError or SyntaxError, however, on this case, the module setup.py raises SystemExit. Shouldn't we prevent modules from import if they raise any exception?
Sorry but where in our sourcecode is that happening?

El 28/07/17 a las 16:54, Edgar Andrés Margffoy Tuay escribió:
>
> @ccordoba12 <https://github.com/ccordoba12> It seems that we're not 
> importing modules only if they raise ImportError or SyntaxError, 
> however, on this case, the module setup.py raises SystemExit. 
> Shouldn't we prevent modules from import if they raise any exception?
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub 
> <https://github.com/spyder-ide/spyder/issues/4810#issuecomment-318770723>, 
> or mute the thread 
> <https://github.com/notifications/unsubscribe-auth/AAWS7bbkQwPvP34v_HdbMKVh1PA6JONwks5sSliYgaJpZM4OiteH>.
>


See [spyder/utils/dochelpers.py#L309](https://github.com/spyder-ide/spyder/blob/master/spyder/utils/dochelpers.py#L309)
If we catch ``SystemExit`` also, the issue reported by @avylove disappears.

Resolving patch:
diff --git a/spyder/utils/dochelpers.py b/spyder/utils/dochelpers.py
--- a/spyder/utils/dochelpers.py
+++ b/spyder/utils/dochelpers.py
@@ -306,7 +306,7 @@ def isdefined(obj, force_import=False, namespace=None):
                 if base not in globals():
                     globals()[base] = module
                 namespace[base] = module
-            except (ImportError, SyntaxError):
+            except (ImportError, SyntaxError, SystemExit):
                 return False
         else:
             return False


Test patch: