@@ -109,8 +109,8 @@ async def thread_manager_anext() -> None:
109109 context = self ._main_thread_ctx ,
110110 )
111111
112- self ._readers : Dict [_FileDescriptorLike , Callable ] = {}
113- self ._writers : Dict [_FileDescriptorLike , Callable ] = {}
112+ self ._readers : Dict [int , Tuple [ _FileDescriptorLike , Callable ] ] = {}
113+ self ._writers : Dict [int , Tuple [ _FileDescriptorLike , Callable ] ] = {}
114114
115115 # Writing to _waker_w will wake up the selector thread, which
116116 # watches for _waker_r to be readable.
@@ -261,27 +261,45 @@ def _handle_select(
261261 def _handle_event (
262262 self ,
263263 fd : _FileDescriptorLike ,
264- cb_map : Dict [_FileDescriptorLike , Callable ],
264+ cb_map : Dict [int , Tuple [ _FileDescriptorLike , Callable ] ],
265265 ) -> None :
266266 try :
267- callback = cb_map [fd ]
267+ fileobj , callback = cb_map [fd ]
268268 except KeyError :
269269 return
270270 callback ()
271271
272+ def _split_fd (self , fd : _FileDescriptorLike ) -> Tuple [int , _FileDescriptorLike ]:
273+ """Return fd, file object
274+
275+ Keeps a handle on the fileobject given,
276+ but always registers integer FD
277+ """
278+ fileno = fd
279+ if not isinstance (fileno , int ):
280+ try :
281+ fileno = int (fileno .fileno ())
282+ except (AttributeError , TypeError , ValueError ):
283+ # This code matches selectors._fileobj_to_fd function.
284+ raise ValueError (f"Invalid file object: { fd !r} " ) from None
285+ return fileno , fd
286+
272287 def add_reader (
273288 self , fd : _FileDescriptorLike , callback : Callable [..., None ], * args : Any
274289 ) -> None :
275- self ._readers [fd ] = functools .partial (callback , * args )
290+ fd , fileobj = self ._split_fd (fd )
291+ self ._readers [fd ] = (fileobj , functools .partial (callback , * args ))
276292 self ._wake_selector ()
277293
278294 def add_writer (
279295 self , fd : _FileDescriptorLike , callback : Callable [..., None ], * args : Any
280296 ) -> None :
281- self ._writers [fd ] = functools .partial (callback , * args )
297+ fd , fileobj = self ._split_fd (fd )
298+ self ._writers [fd ] = (fileobj , functools .partial (callback , * args ))
282299 self ._wake_selector ()
283300
284301 def remove_reader (self , fd : _FileDescriptorLike ) -> bool :
302+ fd , _ = self ._split_fd (fd )
285303 try :
286304 del self ._readers [fd ]
287305 except KeyError :
@@ -290,6 +308,7 @@ def remove_reader(self, fd: _FileDescriptorLike) -> bool:
290308 return True
291309
292310 def remove_writer (self , fd : _FileDescriptorLike ) -> bool :
311+ fd , _ = self ._split_fd (fd )
293312 try :
294313 del self ._writers [fd ]
295314 except KeyError :
0 commit comments