Repository: xonsh/xonsh

Issue:
cmd && othercmd throws an exception
```
➤ ls &&Exception in thread Thread-35:
Traceback (most recent call last):
  File "/usr/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.6/threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/lib/python3.6/site-packages/prompt_toolkit/interface.py", line 860, in run
    completions = list(buffer.completer.get_completions(document, complete_event))
  File "/usr/lib/python3.6/site-packages/xonsh/ptk/completer.py", line 49, in get_completions
    self.ctx)
  File "/usr/lib/python3.6/site-packages/xonsh/__amalgam__.py", line 124, in complete
    out = func(prefix, line, begidx, endidx, ctx)
  File "/usr/lib/python3.6/site-packages/xonsh/completers/__amalgam__.py", line 831, in complete_skipper
    ctx)
  File "/usr/lib/python3.6/site-packages/xonsh/__amalgam__.py", line 124, in complete
    out = func(prefix, line, begidx, endidx, ctx)
  File "/usr/lib/python3.6/site-packages/xonsh/completers/__amalgam__.py", line 1427, in complete_base
    complete_command(prefix, line, start, end, ctx))
TypeError: unsupported operand type(s) for |: 'tuple' and 'set'
```

```
➤ y -Q | egrep 'toolkit|xon'
community/python-prompt_toolkit 1.0.14-1
local/xonsh 0.5.9-1
```

Let me know if you need anything else.


Discussion:
Thanks for reporting @OneOfOne -- can you confirm that you get this exception when you hit tab? 
I get it by typing the second `&`, before hitting tab/space.
Ok, that's much weirder. Can you please post the output of `xonfig` and also your `.xonshrc`? 
It's a mess right now but https://gist.github.com/OneOfOne/97b03541ddee193407c9445c2d77689a

```
┏━oneofone@Ava ❨~❩
┗━━➤ xonfig 
+------------------+-----------------+
| xonsh            | 0.5.9           |
| Python           | 3.6.1           |
| PLY              | 3.9             |
| have readline    | True            |
| prompt toolkit   | 1.0.14          |
| shell type       | prompt_toolkit  |
| pygments         | 2.2.0           |
| on posix         | True            |
| on linux         | True            |
| distro           | arch            |
| on darwin        | False           |
| on windows       | False           |
| on cygwin        | False           |
| is superuser     | False           |
| default encoding | utf-8           |
| xonsh encoding   | utf-8           |
| encoding errors  | surrogateescape |
+------------------+-----------------+
```
Try disabling the update on keypress envvar and see if it still throws that
error.

On May 15, 2017 5:32 PM, "Ahmed W." <notifications@github.com> wrote:

> It's a mess right now but https://gist.github.com/OneOfOne/
> 97b03541ddee193407c9445c2d77689a
>
> ┏━oneofone@Ava ❨~❩
> ┗━━➤ xonfig
> +------------------+-----------------+
> | xonsh            | 0.5.9           |
> | Python           | 3.6.1           |
> | PLY              | 3.9             |
> | have readline    | True            |
> | prompt toolkit   | 1.0.14          |
> | shell type       | prompt_toolkit  |
> | pygments         | 2.2.0           |
> | on posix         | True            |
> | on linux         | True            |
> | distro           | arch            |
> | on darwin        | False           |
> | on windows       | False           |
> | on cygwin        | False           |
> | is superuser     | False           |
> | default encoding | utf-8           |
> | xonsh encoding   | utf-8           |
> | encoding errors  | surrogateescape |
> +------------------+-----------------+
>
> —
> You are receiving this because you commented.
> Reply to this email directly, view it on GitHub
> <https://github.com/xonsh/xonsh/issues/2380#issuecomment-301611167>, or mute
> the thread
> <https://github.com/notifications/unsubscribe-auth/ADbix7__1UlymOMGRbfpBObDMIICzUOIks5r6MRsgaJpZM4Nbhpu>
> .
>

That actually fixed it @gforsyth.
Thanks, @OneOfOne -- this is definitely a bug in the completer framework. It was getting triggered by the update on keypress envvar, but it also happens if you press tab after the `&&`
Let me know if you need me to test anything.
I can confirm this happening.
This happens when typing `||` as well.

I'm working around this bug by using `and` and `or` instead of `&&` and `||`. I guess that's more Pythonic anyways.
@gerardlouw - can you post the output of `xonfig`? I wonder if this only happens on PTKv1.
I can confirm that it also happens with PTK2. The trick is to press the <kbd>TAB</kbd> key immediately after typing the second `|` or `&` character (without the trailing space). Un-amalgamated backtrace follows:
```
str@str ~ $ xonfig                                                                                                                                                                                                                                                          
+------------------+---------------------+
| xonsh            | 0.8.8               |
| Git SHA          | 67db1fa8            |
| Commit Date      | Oct 3 02:58:28 2018 |
| Python           | 3.7.1               |
| PLY              | 3.11                |
| have readline    | True                |
| prompt toolkit   | 2.0.7               |
| shell type       | prompt_toolkit2     |
| pygments         | 2.3.1               |
| on posix         | True                |
| on linux         | True                |
| distro           | arch                |
| on darwin        | False               |
| on windows       | False               |
| on cygwin        | False               |
| on msys2         | False               |
| is superuser     | False               |
| default encoding | utf-8               |
| xonsh encoding   | utf-8               |
| encoding errors  | surrogateescape     |
+------------------+---------------------+

str@str ~ $ ls &&
Unhandled exception in event loop:
  File "/usr/lib/python3.7/site-packages/prompt_toolkit/eventloop/coroutine.py", line 90, in step_next
    new_f = coroutine.throw(exc)
  File "/usr/lib/python3.7/site-packages/prompt_toolkit/buffer.py", line 1648, in new_coroutine
    yield From(coroutine(*a, **kw))
  File "/usr/lib/python3.7/site-packages/prompt_toolkit/eventloop/coroutine.py", line 90, in step_next
    new_f = coroutine.throw(exc)
  File "/usr/lib/python3.7/site-packages/prompt_toolkit/buffer.py", line 1500, in async_completer
    cancel=lambda: not proceed()))
  File "/usr/lib/python3.7/site-packages/prompt_toolkit/eventloop/coroutine.py", line 86, in step_next
    new_f = coroutine.send(None)
  File "/usr/lib/python3.7/site-packages/prompt_toolkit/eventloop/async_generator.py", line 114, in consume_async_generator
    item = iterator.send(send)
  File "/usr/lib/python3.7/site-packages/prompt_toolkit/completion/base.py", line 166, in get_completions_async
    for item in self.get_completions(document, complete_event):
  File "/home/str/projects/xonsh/xonsh/ptk2/completer.py", line 45, in get_completions
    prefix, line_ex, begidx + expand_offset, endidx + expand_offset, self.ctx
  File "/home/str/projects/xonsh/xonsh/completer.py", line 36, in complete
    out = func(prefix, line, begidx, endidx, ctx)
  File "/home/str/projects/xonsh/xonsh/completers/commands.py", line 59, in complete_skipper
    cmd, " ".join(parts[skip_part_num:]), start - skip_len, end - skip_len, ctx
  File "/home/str/projects/xonsh/xonsh/completer.py", line 36, in complete
    out = func(prefix, line, begidx, endidx, ctx)
  File "/home/str/projects/xonsh/xonsh/completers/base.py", line 16, in complete_base
    prefix, line, start, end, ctx

Exception unsupported operand type(s) for |: 'tuple' and 'set'
```

Resolving patch:
diff --git a/xonsh/completers/base.py b/xonsh/completers/base.py
--- a/xonsh/completers/base.py
+++ b/xonsh/completers/base.py
@@ -11,19 +11,21 @@ def complete_base(prefix, line, start, end, ctx):
     and paths.  If we are completing the first argument, complete based on
     valid commands and python names.
     """
+    # get and unpack python completions
+    python_comps = complete_python(prefix, line, start, end, ctx)
+    if isinstance(python_comps, cabc.Sequence):
+        python_comps, python_comps_len = python_comps
+    else:
+        python_comps_len = None
+    # add command completions
+    out = python_comps | complete_command(prefix, line, start, end, ctx)
+    # add paths, if needed
     if line.strip() == "":
-        out = complete_python(prefix, line, start, end, ctx) | complete_command(
-            prefix, line, start, end, ctx
-        )
         paths = complete_path(prefix, line, start, end, ctx, False)
         return (out | paths[0]), paths[1]
     elif prefix == line:
-        python_comps = complete_python(prefix, line, start, end, ctx)
-        if isinstance(python_comps, cabc.Sequence):
-            return (
-                python_comps[0] | complete_command(prefix, line, start, end, ctx),
-                python_comps[1],
-            )
+        if python_comps_len is None:
+            return out
         else:
-            return python_comps | complete_command(prefix, line, start, end, ctx)
+            return out, python_comps_len
     return set()


Test patch: