Proper handling of async responses to peers
This commit is contained in:
parent
218582ced8
commit
d53d92b890
@ -53,7 +53,7 @@ from .session import Session, create_sessions, get_os_window_sizing_data
|
||||
from .tabs import (
|
||||
SpecialWindow, SpecialWindowInstance, Tab, TabDict, TabManager
|
||||
)
|
||||
from .types import _T, SingleKey, WindowSystemMouseEvent, ac
|
||||
from .types import _T, AsyncResponse, SingleKey, WindowSystemMouseEvent, ac
|
||||
from .typing import PopenType, TypedDict
|
||||
from .utils import (
|
||||
func_name, get_editor, get_new_os_window_size, get_primary_selection,
|
||||
@ -435,7 +435,7 @@ class Boss:
|
||||
self.child_monitor.add_child(window.id, window.child.pid, window.child.child_fd, window.screen)
|
||||
self.window_id_map[window.id] = window
|
||||
|
||||
def _handle_remote_command(self, cmd: str, window: Optional[Window] = None, peer_id: int = 0) -> Optional[Dict[str, Any]]:
|
||||
def _handle_remote_command(self, cmd: str, window: Optional[Window] = None, peer_id: int = 0) -> Union[Dict[str, Any], None, AsyncResponse]:
|
||||
from .remote_control import handle_cmd
|
||||
response = None
|
||||
window = window or None
|
||||
@ -491,7 +491,7 @@ class Boss:
|
||||
tb = traceback.format_exc()
|
||||
self.show_error(_('remote_control mapping failed'), tb)
|
||||
|
||||
def peer_message_received(self, msg_bytes: bytes, peer_id: int) -> Optional[bytes]:
|
||||
def peer_message_received(self, msg_bytes: bytes, peer_id: int) -> Union[bytes, bool, None]:
|
||||
cmd_prefix = b'\x1bP@kitty-cmd'
|
||||
terminator = b'\x1b\\'
|
||||
if msg_bytes.startswith(cmd_prefix) and msg_bytes.endswith(terminator):
|
||||
@ -499,6 +499,8 @@ class Boss:
|
||||
response = self._handle_remote_command(cmd, peer_id=peer_id)
|
||||
if response is None:
|
||||
return None
|
||||
if isinstance(response, AsyncResponse):
|
||||
return True
|
||||
from kitty.remote_control import encode_response_for_peer
|
||||
return encode_response_for_peer(response)
|
||||
|
||||
@ -528,8 +530,7 @@ class Boss:
|
||||
|
||||
def handle_remote_cmd(self, cmd: str, window: Optional[Window] = None) -> None:
|
||||
response = self._handle_remote_command(cmd, window)
|
||||
if response is not None:
|
||||
if window is not None:
|
||||
if response is not None and not isinstance(response, AsyncResponse) and window is not None:
|
||||
window.send_cmd_response(response)
|
||||
|
||||
def _cleanup_tab_after_window_removal(self, src_tab: Tab) -> None:
|
||||
|
||||
@ -424,7 +424,7 @@ parse_input(ChildMonitor *self) {
|
||||
}
|
||||
if (resp) {
|
||||
if (PyBytes_Check(resp)) send_response_to_peer(msg->peer_id, PyBytes_AS_STRING(resp), PyBytes_GET_SIZE(resp));
|
||||
else send_response_to_peer(msg->peer_id, NULL, 0);
|
||||
else if (resp == Py_None) send_response_to_peer(msg->peer_id, NULL, 0);
|
||||
Py_CLEAR(resp);
|
||||
} else send_response_to_peer(msg->peer_id, NULL, 0);
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ from typing import (
|
||||
from kitty.cli import get_defaults_from_seq, parse_args, parse_option_spec
|
||||
from kitty.cli_stub import RCOptions as R
|
||||
from kitty.constants import appname, list_kitty_resources, running_in_kitty
|
||||
from kitty.types import AsyncResponse
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from kitty.boss import Boss as B
|
||||
@ -64,7 +65,7 @@ class PayloadGetter:
|
||||
|
||||
no_response = NoResponse()
|
||||
payload_get = object()
|
||||
ResponseType = Union[bool, str, None, NoResponse]
|
||||
ResponseType = Union[bool, str, None, NoResponse, AsyncResponse]
|
||||
CmdReturnType = Union[Dict[str, Any], List[Any], Tuple[Any, ...], str, int, float, bool]
|
||||
CmdGenerator = Iterator[CmdReturnType]
|
||||
PayloadType = Optional[Union[CmdReturnType, CmdGenerator]]
|
||||
|
||||
@ -3,9 +3,11 @@
|
||||
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from kitty.types import AsyncResponse
|
||||
|
||||
from .base import (
|
||||
MATCH_TAB_OPTION, ArgsType, Boss, PayloadGetType, PayloadType, RCOptions,
|
||||
RemoteCommand, ResponseType, Window, no_response
|
||||
RemoteCommand, ResponseType, Window
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -70,7 +72,7 @@ Exclude the currently active window from the list of windows to pick
|
||||
wids = set()
|
||||
boss.visual_window_select_action(tab, callback, payload_get('title') or 'Choose window', only_window_ids=wids)
|
||||
break
|
||||
return no_response
|
||||
return AsyncResponse()
|
||||
|
||||
def cancel_async_request(self, boss: 'Boss', window: Optional['Window'], payload_get: PayloadGetType) -> None:
|
||||
boss.cancel_current_visual_select()
|
||||
|
||||
@ -6,9 +6,9 @@ import os
|
||||
import re
|
||||
import sys
|
||||
import types
|
||||
from time import monotonic
|
||||
from contextlib import suppress
|
||||
from functools import partial
|
||||
from time import monotonic
|
||||
from typing import (
|
||||
Any, Dict, Generator, Iterable, List, Optional, Tuple, Union, cast
|
||||
)
|
||||
@ -21,10 +21,10 @@ from .rc.base import (
|
||||
NoResponse, ParsingOfArgsFailed, PayloadGetter, all_command_names,
|
||||
command_for_name, parse_subcommand_cli
|
||||
)
|
||||
from .types import AsyncResponse
|
||||
from .typing import BossType, WindowType
|
||||
from .utils import TTYIO, parse_address_spec
|
||||
|
||||
|
||||
active_async_requests: Dict[str, float] = {}
|
||||
|
||||
|
||||
@ -33,7 +33,7 @@ def encode_response_for_peer(response: Any) -> bytes:
|
||||
return b'\x1bP@kitty-cmd' + json.dumps(response).encode('utf-8') + b'\x1b\\'
|
||||
|
||||
|
||||
def handle_cmd(boss: BossType, window: Optional[WindowType], serialized_cmd: str, peer_id: int) -> Optional[Dict[str, Any]]:
|
||||
def handle_cmd(boss: BossType, window: Optional[WindowType], serialized_cmd: str, peer_id: int) -> Union[Dict[str, Any], None, AsyncResponse]:
|
||||
cmd = json.loads(serialized_cmd)
|
||||
v = cmd['version']
|
||||
no_response = cmd.get('no_response', False)
|
||||
@ -63,6 +63,8 @@ def handle_cmd(boss: BossType, window: Optional[WindowType], serialized_cmd: str
|
||||
raise
|
||||
if isinstance(ans, NoResponse):
|
||||
return None
|
||||
if isinstance(ans, AsyncResponse):
|
||||
return ans
|
||||
response: Dict[str, Any] = {'ok': True}
|
||||
if ans is not None:
|
||||
response['data'] = ans
|
||||
|
||||
@ -74,6 +74,10 @@ class WindowSystemMouseEvent(NamedTuple):
|
||||
ConvertibleToNumbers = Union[str, bytes, int, float]
|
||||
|
||||
|
||||
class AsyncResponse:
|
||||
pass
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
class RunOnce(Generic[_T]):
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user