1919from .utils import _async_in_context
2020
2121
22+ class UnknownSubshellError (KeyError ):
23+ """A subshell_id that does not name an existing subshell.
24+
25+ .. versionadded:: 7.4
26+ """
27+
28+ def __init__ (self , subshell_id : str ) -> None :
29+ super ().__init__ (subshell_id )
30+ self .subshell_id = subshell_id
31+
32+ def __str__ (self ) -> str :
33+ return f"Unknown subshell_id { self .subshell_id !r} "
34+
35+
2236class SubshellManager :
2337 """A manager of subshells.
2438
@@ -87,13 +101,24 @@ def close(self) -> None:
87101 self ._main_to_shell_channel .close ()
88102 self ._shell_channel_to_main .close ()
89103
104+ def _get_subshell (self , subshell_id : str ) -> SubshellThread :
105+ """Return the thread of the specified subshell.
106+
107+ The caller must hold ``_lock_cache``. Raises ``UnknownSubshellError`` if
108+ there is no such subshell.
109+ """
110+ try :
111+ return self ._cache [subshell_id ]
112+ except KeyError :
113+ raise UnknownSubshellError (subshell_id ) from None
114+
90115 def get_shell_channel_to_subshell_pair (self , subshell_id : str | None ) -> SocketPair :
91116 """Return the inproc socket pair used to send messages from the shell channel
92117 to a particular subshell or main shell."""
93118 if subshell_id is None :
94119 return self ._shell_channel_to_main
95120 with self ._lock_cache :
96- return self ._cache [ subshell_id ] .shell_channel_to_subshell
121+ return self ._get_subshell ( subshell_id ) .shell_channel_to_subshell
97122
98123 def get_subshell_to_shell_channel_socket (self , subshell_id : str | None ) -> zmq .Socket [t .Any ]:
99124 """Return the socket used by a particular subshell or main shell to send
@@ -102,7 +127,7 @@ def get_subshell_to_shell_channel_socket(self, subshell_id: str | None) -> zmq.S
102127 if subshell_id is None :
103128 return self ._main_to_shell_channel .from_socket
104129 with self ._lock_cache :
105- return self ._cache [ subshell_id ] .subshell_to_shell_channel .from_socket
130+ return self ._get_subshell ( subshell_id ) .subshell_to_shell_channel .from_socket
106131
107132 def get_shell_channel_to_subshell_socket (self , subshell_id : str | None ) -> zmq .Socket [t .Any ]:
108133 """Return the socket used by the shell channel to send messages to a particular
@@ -113,12 +138,12 @@ def get_shell_channel_to_subshell_socket(self, subshell_id: str | None) -> zmq.S
113138 def get_subshell_aborting (self , subshell_id : str ) -> bool :
114139 """Get the boolean aborting flag of the specified subshell."""
115140 with self ._lock_cache :
116- return self ._cache [ subshell_id ] .aborting
141+ return self ._get_subshell ( subshell_id ) .aborting
117142
118143 def get_subshell_asyncio_lock (self , subshell_id : str ) -> asyncio .Lock :
119144 """Return the asyncio lock belonging to the specified subshell."""
120145 with self ._lock_cache :
121- return self ._cache [ subshell_id ] .asyncio_lock
146+ return self ._get_subshell ( subshell_id ) .asyncio_lock
122147
123148 def list_subshell (self ) -> list [str ]:
124149 """Return list of current subshell ids.
@@ -141,7 +166,7 @@ def set_on_recv_callback(self, on_recv_callback):
141166 def set_subshell_aborting (self , subshell_id : str , aborting : bool ) -> None :
142167 """Set the aborting flag of the specified subshell."""
143168 with self ._lock_cache :
144- self ._cache [ subshell_id ] .aborting = aborting
169+ self ._get_subshell ( subshell_id ) .aborting = aborting
145170
146171 def subshell_id_from_thread_id (self , thread_id : int ) -> str | None :
147172 """Return subshell_id of the specified thread_id.
@@ -185,14 +210,15 @@ def _create_subshell(self) -> str:
185210 def _delete_subshell (self , subshell_id : str ) -> None :
186211 """Delete subshell identified by subshell_id.
187212
188- Raises key error if subshell_id not in cache.
213+ Raises ``UnknownSubshellError`` if subshell_id not in cache.
189214 """
190215 assert current_thread ().name == SHELL_CHANNEL_THREAD_NAME
191216
192217 with self ._lock_cache :
193- subshell_threwad = self ._cache .pop (subshell_id )
218+ subshell_thread = self ._get_subshell (subshell_id )
219+ del self ._cache [subshell_id ]
194220
195- self ._stop_subshell (subshell_threwad )
221+ self ._stop_subshell (subshell_thread )
196222
197223 def _process_control_request (
198224 self ,
0 commit comments