Open sangshuduo opened 5 months ago
Hello, First of all, are you sure your server was started before the client run? Did you try to upgrade the websocket version to the latest one?
Maybe I confuse the difference between echo-server and listen command. Since I can't see any response from echo-server when I send a text to the echo-server. However, even when I ran echo-server first, then run ws listen it still exit with ConnectionClosed error. Could you please introduce a typical scenario of how to set up a server can respond explicitly to the screen after receiving the text from a client? Thanks.
ws --version ws version 0.1.0
python3 --version Python 3.10.13
`ws listen ws://localhost:8000/hello ✔ 9657 21:58:08 ExceptionGroup: all attempts to connect to localhost:8000 failed (2 sub-exceptions)
The above exception was the direct cause of the following exception:
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮ │ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/trio_websocket/_impl.py:120 in │ │ open_websocket │ │ │ │ 117 │ async with trio.open_nursery() as new_nursery: │ │ 118 │ │ try: │ │ 119 │ │ │ with trio.fail_after(connect_timeout): │ │ ❱ 120 │ │ │ │ connection = await connect_websocket(new_nursery, host, port, │ │ 121 │ │ │ │ │ resource, use_ssl=use_ssl, subprotocols=subprotocols, │ │ 122 │ │ │ │ │ extra_headers=extra_headers, │ │ 123 │ │ │ │ │ message_queue_size=message_queue_size, │ │ │ │ ╭───────────────────────── locals ──────────────────────────╮ │ │ │ connect_timeout = 5.0 │ │ │ │ disconnect_timeout = 5.0 │ │ │ │ extra_headers = None │ │ │ │ host = 'localhost' │ │ │ │ max_message_size = 1048576 │ │ │ │ message_queue_size = 1 │ │ │ │ new_nursery = <trio.Nursery object at 0x105ddcbb0> │ │ │ │ port = 8000 │ │ │ │ resource = '/hello' │ │ │ │ subprotocols = None │ │ │ │ use_ssl = False │ │ │ ╰───────────────────────────────────────────────────────────╯ │ │ │ │ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/trio_websocket/_impl.py:183 in │ │ connect_websocket │ │ │ │ 180 │ logger.debug('Connecting to ws%s://%s:%d%s', │ │ 181 │ │ '' if ssl_context is None else 's', host, port, resource) │ │ 182 │ if ssl_context is None: │ │ ❱ 183 │ │ stream = await trio.open_tcp_stream(host, port) │ │ 184 │ else: │ │ 185 │ │ stream = await trio.open_ssl_over_tcp_stream(host, port, │ │ 186 │ │ │ ssl_context=ssl_context, https_compatible=True) │ │ │ │ ╭───────────────────────── locals ──────────────────────────╮ │ │ │ extra_headers = None │ │ │ │ host = 'localhost' │ │ │ │ max_message_size = 1048576 │ │ │ │ message_queue_size = 1 │ │ │ │ nursery = <trio.Nursery object at 0x105ddcbb0> │ │ │ │ port = 8000 │ │ │ │ resource = '/hello' │ │ │ │ ssl_context = None │ │ │ │ subprotocols = None │ │ │ │ use_ssl = False │ │ │ ╰───────────────────────────────────────────────────────────╯ │ │ │ │ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/trio/_highlevel_open_tcp_stream.py:403 │ │ in open_tcp_stream │ │ │ │ 400 │ │ if winning_socket is None: │ │ 401 │ │ │ assert len(oserrors) == len(targets) │ │ 402 │ │ │ msg = f"all attempts to connect to {format_host_port(host, port)} failed" │ │ ❱ 403 │ │ │ raise OSError(msg) from ExceptionGroup(msg, oserrors) │ │ 404 │ │ else: │ │ 405 │ │ │ stream = trio.SocketStream(winning_socket) │ │ 406 │ │ │ open_sockets.remove(winningsocket) │ │ │ │ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │ │ │ = '' │ │ │ │ addr = ('127.0.0.1', 8000) │ │ │ │ address_family = <AddressFamily.AF_INET: 2> │ │ │ │ attempt_connect = <function open_tcp_stream..attempt_connect at 0x105dd8700> │ │
│ │ attempt_failed = Event(_tasks=set(), _flag=True) │ │
│ │ happy_eyeballs_delay = 0.25 │ │
│ │ host = 'localhost' │ │
│ │ local_address = None │ │
│ │ msg = 'all attempts to connect to localhost:8000 failed' │ │
│ │ nursery = <trio.Nursery object at 0x105ddc4f0> │ │
│ │ open_sockets = { │ │
│ │ │ <trio.socket.socket [closed] fd=-1, │ │
│ │ family=AddressFamily.AF_INET6, type=SocketKind.SOCK_STREAM, proto=6>, │ │
│ │ │ <trio.socket.socket [closed] fd=-1, family=AddressFamily.AF_INET, │ │
│ │ type=SocketKind.SOCK_STREAM, proto=6> │ │
│ │ } │ │
│ │ oserrors = [ │ │
│ │ │ ConnectionRefusedError(61, "Error connecting to ('::1', 8000, 0, │ │
│ │ 0): Connection refused"), │ │
│ │ │ ConnectionRefusedError(61, "Error connecting to ('127.0.0.1', │ │
│ │ 8000): Connection refused") │ │
│ │ ] │ │
│ │ port = 8000 │ │
│ │ proto = 6 │ │
│ │ socket_type = <SocketKind.SOCK_STREAM: 1> │ │
│ │ targets = [ │ │
│ │ │ ( │ │
│ │ │ │ <AddressFamily.AF_INET6: 30>, │ │
│ │ │ │ <SocketKind.SOCK_STREAM: 1>, │ │
│ │ │ │ 6, │ │
│ │ │ │ '', │ │
│ │ │ │ ('::1', 8000, 0, 0) │ │
│ │ │ ), │ │
│ │ │ ( │ │
│ │ │ │ <AddressFamily.AF_INET: 2>, │ │
│ │ │ │ <SocketKind.SOCK_STREAM: 1>, │ │
│ │ │ │ 6, │ │
│ │ │ │ '', │ │
│ │ │ │ ('127.0.0.1', 8000) │ │
│ │ │ ) │ │
│ │ ] │ │
│ │ winning_socket = None │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
OSError: all attempts to connect to localhost:8000 failed
The above exception was the direct cause of the following exception:
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮ │ /Users/sangshuduo/anaconda3/bin/ws:8 in │
│ │
│ 5 from ws.main import cli │
│ 6 if name == 'main': │
│ 7 │ sys.argv[0] = re.sub(r'(-script.pyw|.exe)?$', '', sys.argv[0]) │
│ ❱ 8 │ sys.exit(cli()) │
│ 9 │
│ │
│ ╭────────────────────────────────── locals ───────────────────────────────────╮ │
│ │ cli = │ │
│ │ re = <module 're' from '/Users/sangshuduo/anaconda3/lib/python3.10/re.py'> │ │
│ │ sys = <module 'sys' (built-in)> │ │
│ ╰─────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/click/core.py:1157 in call │
│ │
│ 1154 │ │
│ 1155 │ def call(self, *args: t.Any, kwargs: t.Any) -> t.Any: │
│ 1156 │ │ """Alias for :meth: │ │
│ ╰─────────────────────────╯ │
│ │
│ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/click/core.py:1078 in main │
│ │
│ 1075 │ │ try: │
│ 1076 │ │ │ try: │
│ 1077 │ │ │ │ with self.make_context(prog_name, args, extra) as ctx: │
│ ❱ 1078 │ │ │ │ │ rv = self.invoke(ctx) │
│ 1079 │ │ │ │ │ if not standalone_mode: │
│ 1080 │ │ │ │ │ │ return rv │
│ 1081 │ │ │ │ │ # it's not safe to │ │
│ │ standalone_mode = True │ │
│ │ windows_expand_args = True │ │
│ ╰──────────────────────────────────────────────────────────────────╯ │
│ │
│ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/click/core.py:1688 in invoke │
│ │
│ 1685 │ │ │ │ super().invoke(ctx) │
│ 1686 │ │ │ │ sub_ctx = cmd.make_context(cmd_name, args, parent=ctx) │
│ 1687 │ │ │ │ with sub_ctx: │
│ ❱ 1688 │ │ │ │ │ return _process_result(sub_ctx.command.invoke(sub_ctx)) │
│ 1689 │ │ │
│ 1690 │ │ # In chain mode we create the contexts step by step, but after the │
│ 1691 │ │ # base command has been invoked. Because at that point we do not │
│ │
│ ╭───────────────────────────────────────── locals ─────────────────────────────────────────╮ │
│ │ _process_result = <function MultiCommand.invoke.._process_result at 0x10265fd90> │ │
│ │ args = [] │ │
│ │ cmd = │ │
│ │ cmd_name = 'listen' │ │
│ │ ctx = <click.core.Context object at 0x1027953f0> │ │
│ │ self = │ │
│ │ sub_ctx = <click.core.Context object at 0x105dddd80> │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/click/core.py:1434 in invoke │
│ │
│ 1431 │ │ │ echo(style(message, fg="red"), err=True) │
│ 1432 │ │ │
│ 1433 │ │ if self.callback is not None: │
│ ❱ 1434 │ │ │ return ctx.invoke(self.callback, *ctx.params) │
│ 1435 │ │
│ 1436 │ def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: │
│ 1437 │ │ """Return a list of completions for the incomplete value. Looks │
│ │
│ ╭───────────────────── locals ──────────────────────╮ │
│ │ ctx = <click.core.Context object at 0x105dddd80> │ │
│ │ self = │ │
│ ╰───────────────────────────────────────────────────╯ │
│ │
│ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/click/core.py:783 in invoke │
│ │
│ 780 │ │ │
│ 781 │ │ with augment_usage_errors(self): │
│ 782 │ │ │ with ctx: │
│ ❱ 783 │ │ │ │ return callback( args, kwargs) │
│ 784 │ │
│ 785 │ def forward( │
│ 786 │ │ self, cmd: "Command", *args: t.Any, **kwargs: t.Any # noqa: B902 │
│ │
│ ╭──────────────────────────── locals ─────────────────────────────╮ │
│ │ _Context__callback = <function listen at 0x105764d30> │ │
│ │ _Context__self = <click.core.Context object at 0x105dddd80> │ │
│ │ args = () │ │
│ │ ctx = <click.core.Context object at 0x105dddd80> │ │
│ │ kwargs = { │ │
│ │ │ 'url': 'ws://localhost:8000/hello', │ │
│ │ │ 'is_json': False, │ │
│ │ │ 'duration': None, │ │
│ │ │ 'filename': None │ │
│ │ } │ │
│ ╰─────────────────────────────────────────────────────────────────╯ │
│ │
│ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/ws/commands/listen.py:76 in listen │
│ │
│ 73 @filename_option │
│ 74 def listen(url: str, is_json: bool, duration: float, filename: str): │
│ 75 │ """Listens messages on a given URL.""" │
│ ❱ 76 │ trio.run(main, url, is_json, duration, filename) │
│ 77 │
│ │
│ ╭──────────────── locals ────────────────╮ │
│ │ duration = None │ │
│ │ filename = None │ │
│ │ is_json = False │ │
│ │ url = 'ws://localhost:8000/hello' │ │
│ ╰────────────────────────────────────────╯ │
│ │
│ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/trio/_core/_run.py:2275 in run │
│ │
│ 2272 │ if isinstance(runner.main_task_outcome, Value): │
│ 2273 │ │ return cast(RetT, runner.main_task_outcome.value) │
│ 2274 │ elif isinstance(runner.main_task_outcome, Error): │
│ ❱ 2275 │ │ raise runner.main_task_outcome.error │
│ 2276 │ else: # pragma: no cover │
│ 2277 │ │ raise AssertionError(runner.main_task_outcome) │
│ 2278 │
│ │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │ args = ( │ │
│ │ │ 'ws://localhost:8000/hello', │ │
│ │ │ False, │ │
│ │ │ None, │ │
│ │ │ None │ │
│ │ ) │ │
│ │ async_fn = <function main at 0x105764b80> │ │
│ │ clock = None │ │
│ │ gen = <generator object unrolled_run at 0x105df06d0> │ │
│ │ instruments = () │ │
│ │ next_send = [] │ │
│ │ prev_library = None │ │
│ │ restrict_keyboard_interrupt_to_checkpoints = False │ │
│ │ runner = Runner( │ │
│ │ │ clock=SystemClock( │ │
│ │ │ │ offset=162718.46147645527 │ │
│ │ │ ), │ │
│ │ │ instruments={'_all': {}}, │ │
│ │ │ io_manager=KqueueIOManager( │ │
│ │ │ │ _kqueue=<select.kqueue object at │ │
│ │ 0x1025ffbf0>, │ │
│ │ │ │ _registered={}, │ │
│ │ │ │ │ │
│ │ _force_wakeup=<trio._core._wakeup_socketpair.W… │ │
│ │ object at 0x105ddce20>, │ │
│ │ │ │ _force_wakeup_fd=4 │ │
│ │ │ ), │ │
│ │ │ ki_manager=KIManager(handler=None), │ │
│ │ │ strict_exception_groups=False, │ │
│ │ │ _locals={ │ │
│ │ │ │ : │ │
│ │ <trio.CapacityLimiter at 0x105dde710, 0/40 with │ │
│ │ 0 waiting> │ │
│ │ │ }, │ │
│ │ │ runq=deque(), │ │
│ │ │ tasks=set(), │ │
│ │ │ deadlines=Deadlines(_heap=[], _active=0), │ │
│ │ │ init_task=Task( │ │
│ │ │ │ _parent_nursery=None, │ │
│ │ │ │ coro=<coroutine object Runner.init at │ │
│ │ 0x105df0740>, │ │
│ │ │ │ _runner=..., │ │
│ │ │ │ name='', │ │
│ │ │ │ context=<_contextvars.Context object at │ │
│ │ 0x105deaa80>, │ │
│ │ │ │ _counter=0, │ │
│ │ │ │ _next_send_fn=None, │ │
│ │ │ │ _next_send=None, │ │
│ │ │ │ _abort_func=None, │ │
│ │ │ │ custom_sleep_data=None, │ │
│ │ │ │ _child_nurseries=[], │ │
│ │ │ │ _eventual_parent_nursery=None, │ │
│ │ │ │ _cancel_points=3, │ │
│ │ │ │ _schedule_points=4 │ │
│ │ │ ), │ │
│ │ │ system_nursery=<trio.Nursery object at │ │
│ │ 0x105dde1d0>, │ │
│ │ │ system_context=<_contextvars.Context object │ │
│ │ at 0x105dea180>, │ │
│ │ │ main_task=Task( │ │
│ │ │ │ _parent_nursery=<trio.Nursery object at │ │
│ │ 0x105dde260>, │ │
│ │ │ │ coro=<coroutine object main at │ │
│ │ 0x105df07b0>, │ │
│ │ │ │ _runner=..., │ │
│ │ │ │ name='ws.commands.listen.main', │ │
│ │ │ │ context=<_contextvars.Context object at │ │
│ │ 0x105deac80>, │ │
│ │ │ │ _counter=1, │ │
│ │ │ │ _next_send_fn=None, │ │
│ │ │ │ _next_send=None, │ │
│ │ │ │ _abort_func=None, │ │
│ │ │ │ custom_sleep_data=None, │ │
│ │ │ │ _child_nurseries=[], │ │
│ │ │ │ _eventual_parent_nursery=None, │ │
│ │ │ │ _cancel_points=1, │ │
│ │ │ │ _schedule_points=1 │ │
│ │ │ ), │ │
│ │ │ main_task_outcome=Error( │ │
│ │ │ │ _unwrapped=False, │ │
│ │ │ │ error=HandshakeError() │ │
│ │ │ ), │ │
│ │ │ entry_queue=EntryQueue( │ │
│ │ │ │ queue=deque(), │ │
│ │ │ │ idempotent_queue={}, │ │
│ │ │ │ │ │
│ │ wakeup=<trio._core._wakeup_socketpair.WakeupSo… │ │
│ │ object at 0x105ddd300>, │ │
│ │ │ │ done=True, │ │
│ │ │ │ lock=<unlocked _thread.RLock object │ │
│ │ owner=0 count=0 at 0x105dea6c0> │ │
│ │ │ ), │ │
│ │ │ trio_token=TrioToken( │ │
│ │ │ │ _reentry_queue=EntryQueue( │ │
│ │ │ │ │ queue=deque(), │ │
│ │ │ │ │ idempotent_queue={}, │ │
│ │ │ │ │ │ │
│ │ wakeup=<trio._core._wakeup_socketpair.WakeupSo… │ │
│ │ object at 0x105ddd300>, │ │
│ │ │ │ │ done=True, │ │
│ │ │ │ │ lock=<unlocked _thread.RLock object │ │
│ │ owner=0 count=0 at 0x105dea6c0> │ │
│ │ │ │ ) │ │
│ │ │ ), │ │
│ │ │ asyncgens=AsyncGenerators( │ │
│ │ │ │ alive=set(), │ │
│ │ │ │ trailing_needs_finalize=set(), │ │
│ │ │ │ │ │
│ │ prev_hooks=asyncgen_hooks(firstiter=None, │ │
│ │ finalizer=None) │ │
│ │ │ ), │ │
│ │ │ clock_autojump_threshold=inf, │ │
│ │ │ is_guest=False, │ │
│ │ │ guest_tick_scheduled=False, │ │
│ │ │ ki_pending=False, │ │
│ │ │ waiting_for_idle=SortedDict({}) │ │
│ │ ) │ │
│ │ strict_exception_groups = False │ │
│ │ timeout = 0 │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/ws/commands/listen.py:60 in main │
│ │
│ 57 │
│ 58 │
│ 59 async def main(url: str, is_json: bool, duration: Optional[float] = None, filename: Opti │
│ ❱ 60 │ async with trio.open_nursery() as nursery: │
│ 61 │ │ nursery.start_soon(function_runner, nursery.cancel_scope, listen_messages, url, │
│ 62 │ │ nursery.start_soon(signal_handler, nursery.cancel_scope) │
│ 63 │ │ nursery.start_soon(sleep_until, nursery.cancel_scope, duration) │
│ │
│ ╭────────────────────────────── locals ──────────────────────────────╮ │
│ │ @TRIO_KI_PROTECTION_ENABLED = False │ │
│ │ duration = None │ │
│ │ filename = None │ │
│ │ is_json = False │ │
│ │ nursery = <trio.Nursery object at 0x105ddd4e0> │ │
│ │ url = 'ws://localhost:8000/hello' │ │
│ ╰────────────────────────────────────────────────────────────────────╯ │
│ │
│ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/trio/_core/_run.py:971 in aexit │
│ │
│ 968 │ │ │ # allow us to encapsulate this context fixup. │
│ 969 │ │ │ old_context = combined_error_from_nursery.context │
│ 970 │ │ │ try: │
│ ❱ 971 │ │ │ │ raise combined_error_fromnursery │
│ 972 │ │ │ finally: │
│ 973 │ │ │ │ , value, _ = sys.exc_info() │
│ 974 │ │ │ │ assert value is combined_error_from_nursery │
│ │
│ ╭───────────────────────────────────────── locals ──────────────────────────────────────────╮ │
│ │ @TRIO_KI_PROTECTION_ENABLED = True │ │
│ │ etype = None │ │
│ │ exc = None │ │
│ │ old_context = OSError('all attempts to connect to localhost:8000 failed') │ │
│ │ self = NurseryManager(strict_exception_groups=False) │ │
│ │ tb = None │ │
│ ╰───────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/ws/utils/io.py:22 in function_runner │
│ │
│ 19 │
│ 20 │
│ 21 async def function_runner(scope: trio.CancelScope, function: Callable, args: Any) -> No │
│ ❱ 22 │ await function(args) │
│ 23 │ # noinspection PyAsyncCall │
│ 24 │ scope.cancel() │
│ 25 │
│ │
│ ╭───────────────────────────────── locals ─────────────────────────────────╮ │
│ │ @TRIO_KI_PROTECTION_ENABLED = False │ │
│ │ args = ('ws://localhost:8000/hello', False, None) │ │
│ │ function = <function listen_messages at 0x105764af0> │ │
│ │ scope = CancelScope( │ │
│ │ │ _cancel_status=None, │ │
│ │ │ _has_been_entered=True, │ │
│ │ │ _registered_deadline=inf, │ │
│ │ │ _cancel_called=True, │ │
│ │ │ cancelled_caught=True, │ │
│ │ │ _deadline=inf, │ │
│ │ │ _shield=False │ │
│ │ ) │ │
│ ╰──────────────────────────────────────────────────────────────────────────╯ │
│ │
│ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/ws/commands/listen.py:47 in │
│ listen_messages │
│ │
│ 44 async def listen_messages(url: str, is_json: bool, filename: Optional[str] = None) -> No │
│ 45 │ configure_console_recording(console, get_settings(), filename) │
│ 46 │ │
│ ❱ 47 │ async with websocket_client(url) as client: │
│ 48 │ │ while True: │
│ 49 │ │ │ message = await client.get_message() │
│ 50 │ │ │ is_bytes = isinstance(message, bytes) │
│ │
│ ╭──────────────── locals ────────────────╮ │
│ │ filename = None │ │
│ │ is_json = False │ │
│ │ url = 'ws://localhost:8000/hello' │ │
│ ╰────────────────────────────────────────╯ │
│ │
│ /Users/sangshuduo/anaconda3/lib/python3.10/contextlib.py:199 in aenter │
│ │
│ 196 │ │ # they are only needed for recreation, which is not possible anymore │
│ 197 │ │ del self.args, self.kwds, self.func │
│ 198 │ │ try: │
│ ❱ 199 │ │ │ return await anext(self.gen) │
│ 200 │ │ except StopAsyncIteration: │
│ 201 │ │ │ raise RuntimeError("generator didn't yield") from None │
│ 202 │
│ │
│ ╭──────────────────────────────── locals ─────────────────────────────────╮ │
│ │ self = <contextlib._AsyncGeneratorContextManager object at 0x105ddc850> │ │
│ ╰─────────────────────────────────────────────────────────────────────────╯ │
│ │
│ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/ws/client.py:92 in websocket_client │
│ │
│ 89 │ ) │
│ 90 │ │
│ 91 │ try: │
│ ❱ 92 │ │ async with open_websocket_url(url, ssl_context=ssl_context, **arguments) as ws: │
│ 93 │ │ │ yield ws │
│ 94 │ except ConnectionTimeout: │
│ 95 │ │ console.print(f'[error]Unable to connect to {url}') │
│ │
│ ╭──────────────────── locals ────────────────────╮ │
│ │ arguments = { │ │
│ │ │ 'connect_timeout': 5.0, │ │
│ │ │ 'disconnect_timeout': 5.0, │ │
│ │ │ 'message_queue_size': 1, │ │
│ │ │ 'max_message_size': 1048576, │ │
│ │ │ 'extra_headers': None │ │
│ │ } │ │
│ │ settings = Settings( │ │
│ │ │ connect_timeout=5.0, │ │
│ │ │ disconnect_timeout=5.0, │ │
│ │ │ response_timeout=5.0, │ │
│ │ │ message_queue_size=1, │ │
│ │ │ max_message_size=1048576, │ │
│ │ │ extra_headers=None, │ │
│ │ │ terminal_width=180, │ │
│ │ │ tls_ca_file=None, │ │
│ │ │ tls_certificate_file=None, │ │
│ │ │ tls_key_file=None, │ │
│ │ │ tls_password=None │ │
│ │ ) │ │
│ │ ssl_context = None │ │
│ │ url = 'ws://localhost:8000/hello' │ │
│ ╰────────────────────────────────────────────────╯ │
│ │
│ /Users/sangshuduo/anaconda3/lib/python3.10/contextlib.py:199 in aenter │
│ │
│ 196 │ │ # they are only needed for recreation, which is not possible anymore │
│ 197 │ │ del self.args, self.kwds, self.func │
│ 198 │ │ try: │
│ ❱ 199 │ │ │ return await anext(self.gen) │
│ 200 │ │ except StopAsyncIteration: │
│ 201 │ │ │ raise RuntimeError("generator didn't yield") from None │
│ 202 │
│ │
│ ╭──────────────────────────────── locals ─────────────────────────────────╮ │
│ │ self = <contextlib._AsyncGeneratorContextManager object at 0x105ddc8b0> │ │
│ ╰─────────────────────────────────────────────────────────────────────────╯ │
│ │
│ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/trio_websocket/_impl.py:128 in │
│ open_websocket │
│ │
│ 125 │ │ except trio.TooSlowError: │
│ 126 │ │ │ raise ConnectionTimeout from None │
│ 127 │ │ except OSError as e: │
│ ❱ 128 │ │ │ raise HandshakeError from e │
│ 129 │ │ try: │
│ 130 │ │ │ yield connection │
│ 131 │ │ finally: │
│ │
│ ╭───────────────────────── locals ──────────────────────────╮ │
│ │ connect_timeout = 5.0 │ │
│ │ disconnect_timeout = 5.0 │ │
│ │ extra_headers = None │ │
│ │ host = 'localhost' │ │
│ │ max_message_size = 1048576 │ │
│ │ message_queue_size = 1 │ │
│ │ new_nursery = <trio.Nursery object at 0x105ddcbb0> │ │
│ │ port = 8000 │ │
│ │ resource = '/hello' │ │
│ │ subprotocols = None │ │
│ │ use_ssl = False │ │
│ ╰───────────────────────────────────────────────────────────╯ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
HandshakeError`
main
.""" │ │ ❱ 1157 │ │ return self.main(*args, kwargs) │ │ 1158 │ │ 1159 │ │ 1160 class Command(BaseCommand): │ │ │ │ ╭──────── locals ─────────╮ │ │ │ args = () │ │ │ │ kwargs = {} │ │ │ │ self =ctx.exit(rv)
here! │ │ │ │ ╭───────────────────────────── locals ─────────────────────────────╮ │ │ │ args = ['listen', 'ws://localhost:8000/hello'] │ │ │ │ complete_var = None │ │ │ │ ctx = <click.core.Context object at 0x1027953f0> │ │ │ │ extra = {} │ │ │ │ prog_name = 'ws' │ │ │ │ self =