Repository: xonsh/xonsh

Issue:
AttributeError: 'BaseShell' object has no attribute 'cmdloop'
My installed xonsh (from [AUR](https://aur.archlinux.org/packages/xonsh/)) suddenly broke?

``` console
$ xonsh
The most exciting phrase to hear in science, the one that heralds new
discoveries, is not "Eureka!" (I found it!) but "That's funny ..."
        -- Isaac Asimov
Traceback (most recent call last):
  File "/bin/xonsh", line 3, in <module>
    main()
  File "/usr/lib/python3.5/site-packages/xonsh/__amalgam__.py", line 16531, in main
    shell.shell.cmdloop()
AttributeError: 'BaseShell' object has no attribute 'cmdloop'
$ xonsh --version
('xonsh/0.4.4',)
$ XONSH_DEBUG=1 xonsh
Today is the first day of the rest of your lossage.
Traceback (most recent call last):
  File "/bin/xonsh", line 3, in <module>
    main()
  File "/usr/lib/python3.5/site-packages/xonsh/main.py", line 222, in main
    shell.shell.cmdloop()
AttributeError: 'BaseShell' object has no attribute 'cmdloop'
```

(Ignore the output of `fortune`.)



Discussion:
This is happening on `master`, too.

Do you have set shell variable SHELL_TYPE?

It's not set manually, no.

Sure? I get the same error if I do this:

```
$ export SHELL_TYPE="none"
$ xonsh 
Traceback (most recent call last):
  File "/usr/bin/xonsh", line 3, in <module>
    main()
  File "/usr/lib/python3.5/site-packages/xonsh/__amalgam__.py", line 16531, in main
    shell.shell.cmdloop()
AttributeError: 'BaseShell' object has no attribute 'cmdloop'
```

Try to set it correctly:

```
unset SHELL_TYPE
```

or

```
export SHELL_TYPE="best"
```

Shell should never be None, we must prolly add a fallback with try except to set the shell if its None

and BaseShell should raise NotImplemented for cmdloop

Actually shell type should be none for a headless shell.  Does this happen on master @astronouth7303? I though that this was fixed...

Also thanks for reporting!

i can reproduce this too with just setting `$SHELL_TYPE='none'` maybe we should at least throw a more explicit error?

Nope. I do not set `SHELL_TYPE` in my `.xonshrc` and I do not have a xonfig file.

It is somehow coming from my environment, though? I'm not sure where or how it got there. It looks like this is not an immediate bug in xonsh initialization, though.

There is an argument to be made that `SHELL_TYPE='none'` should never be allowed from the environment, or at all.

Actually, what is the use case for `SHELL_TYPE=none`? All I can figure is completeness.

Well when you run a command with `xonsh -c` or when running a .xsh script i think there is no shell involved. Maybe we should not allow shell being 'none' if we go into interactive mode?

I'm thinking specifically if loaded from the environment, because it somehow got set for my whole X session...

OHHHHHH

`slim` calls my login shell (xonsh) with `-c`. There's a whole bunch of ways for for `premain()` to set `shell_type` to `'none'`, one of which is if `args.command` (`-c`) is set. This is then passed back to `__xonsh_env__` in `Shell.__init__()`, which is then passes it to `os.environ`. The process environment is inherited, so this propagates through my entire session, through my window manager, through my terminal emulator, and finally to the interactive xonsh.

I think there's a few things that could be done here:
1. Don't except `SHELL_TYPE=none` from the environment
2. Don't write `SHELL_TYPE` to the `__xonsh_env__` if it didn't come from the environment
3. If interactive, override `SHELL_TYPE=none`

I think 2 is the wrong thing, because there's probably some script that uses `SHELL_TYPE` to check for things. I would like 3 to be done, but I'm not seeing an interactive flag in `Shell.__init__()`.

So I think 1 is the right way. I can submit a PR pretty quickly.

Not accepting `SHELL_TYPE` from the environment does mean that `env SHELL_TYPE=none xonsh ...` won't work, but I'm not sure a situation where you would need to do that, and you could pass it in `-D`.


Resolving patch:
diff --git a/xonsh/shell.py b/xonsh/shell.py
--- a/xonsh/shell.py
+++ b/xonsh/shell.py
@@ -48,6 +48,10 @@ def __init__(self, ctx=None, shell_type=None, config=None, rc=None,
         # shell type is pulled from env
         if shell_type is None:
             shell_type = env.get('SHELL_TYPE')
+            if shell_type == 'none':
+                # This bricks interactive xonsh
+                # Can happen from the use of .xinitrc, .xsession, etc
+                shell_type = 'best'
         if shell_type == 'best' or shell_type is None:
             shell_type = best_shell_type()
         elif shell_type == 'random':


Test patch: