asyncssh icon indicating copy to clipboard operation
asyncssh copied to clipboard

Incompatible with Fig.io

Open forabi-cosuno opened this issue 2 years ago • 3 comments

    return fut.result()
           ^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/[email protected]/3.11.6_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/tasks.py", line 694, in _wrap_awaitable
    return (yield from awaitable.__await__())
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/lib/python3.11/site-packages/asyncssh/connection.py", line 8226, in connect
    new_options = cast(SSHClientConnectionOptions, await _run_in_executor(
                                                   ^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/lib/python3.11/site-packages/asyncssh/connection.py", line 516, in _run_in_executor
    return await loop.run_in_executor(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/[email protected]/3.11.6_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/lib/python3.11/site-packages/asyncssh/connection.py", line 6600, in __init__
    super().__init__(options=options, last_config=last_config, **kwargs)
  File "/opt/homebrew/lib/python3.11/site-packages/asyncssh/misc.py", line 350, in __init__
    self.prepare(**self.kwargs)
  File "/opt/homebrew/lib/python3.11/site-packages/asyncssh/connection.py", line 7301, in prepare
    config = SSHClientConfig.load(last_config, config, reload,
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/lib/python3.11/site-packages/asyncssh/config.py", line 390, in load
    config.parse(Path(path))
  File "/opt/homebrew/lib/python3.11/site-packages/asyncssh/config.py", line 350, in parse
    handler(self, option, args)
  File "/opt/homebrew/lib/python3.11/site-packages/asyncssh/config.py", line 147, in _include
    self.parse(path)
  File "/opt/homebrew/lib/python3.11/site-packages/asyncssh/config.py", line 350, in parse
    handler(self, option, args)
  File "/opt/homebrew/lib/python3.11/site-packages/asyncssh/config.py", line 167, in _match
    self._error('Invalid match condition')
  File "/opt/homebrew/lib/python3.11/site-packages/asyncssh/config.py", line 81, in _error
    raise ConfigParseError('%s line %s: %s' % (self._path, self._line_no,
asyncssh.config.ConfigParseError: /Users/fwz/.fig/ssh line 1: Invalid match condition
^C2023-11-29 12:33:05 WARNING  MAIN: Got first exit signal! Terminating gracefully.
2023-11-29 12:33:05 INFO     MAIN: Server finished its work.

Contents of ~/.fig/ssh

Match exec="command -v fig && fig _ generate-ssh %r"
  Include ~/.fig/ssh_inner

Commenting out the contents of this file makes rsp work fine (https://github.com/Snawoot/rsp/issues/10).

forabi-cosuno avatar Nov 30 '23 11:11 forabi-cosuno

It looks like AsyncSSH is having trouble parsing the '=' syntax here on "Match exec". It does support this, but I think right now it may only work for the first keyword on the line.

As a workaround for now, try changing the line to:

Match exec "command -v fig && fig _ generate-ssh %r"

ronf avatar Nov 30 '23 14:11 ronf

Here's a proper fix to try:

--- a/asyncssh/config.py
+++ b/asyncssh/config.py
@@ -315,22 +315,26 @@ class SSHConfig:
                     continue

                 try:
-                    args = shlex.split(line)
+                    split_args = shlex.split(line)
                 except ValueError as exc:
                     self._error(str(exc))

-                option = args.pop(0)
-
-                if option.endswith('='):
-                    option = option[:-1]
-                elif '=' in option:
-                    option, arg = option.split('=', 1)
-                    args[:0] =[arg]
-                elif args and args[0] == '=':
-                    del args[0]
-                elif args and args[0].startswith('='):
-                    args[0] = args[0][1:]
+                args = []
+
+                for arg in split_args:
+                    if arg.startswith('='):
+                        if len(arg) > 1:
+                            args.append(arg[1:])
+                    elif arg.endswith('='):
+                        args.append(arg[:-1])
+                    elif '=' in arg:
+                        arg, val = arg.split('=', 1)
+                        args.append(arg)
+                        args.append(val)
+                    else:
+                        args.append(arg)

+                option = args.pop(0)
                 loption = option.lower()

                 if loption in self._no_split:

With this change, the original "Match exec" line with the equals should work.

ronf avatar Dec 01 '23 05:12 ronf

The above change is now available as commit a788cfb in the "develop" branch.

ronf avatar Dec 03 '23 00:12 ronf

This fix is now available in AsyncSSH 2.15.0.

ronf avatar Jul 03 '24 22:07 ronf