Best practice for customising TooSlowError

Hi!
I was wondering how I’d best treat timeouts that should raise custom errors. Think of a protocol where I want to receive a message with a certain timeout, and if it hits the deadline I want to raise an error that’s specific about which message was not received in time.

My question is two-fold. The first: Should my custom protocol error class inherit from trio.TooSlowError?

The second is about coding style. Which one is better/more pythonic/something else?

  • try:
      with trio.fail_after(TIMEOUT):
        await send_query("?")
        answer = await receive_answer(question="?")
    except trio.TooSlowError:
      raise ProtocolError("Got no answer for '?' in time")
    return answer + "!"
    
  • with trio.move_on_after(TIMEOUT) as timeout_scope:
      await send_query("?")
      answer = await receive_answer(question="?")
    if timeout_scope.cancel_called:
      raise ProtocolError("Question '?' not answered in time")
    return answer + "!"
    

The first one has the advantage(?) of also handling TooSlowErrors that were raised individually inside send_query/receive_answer, but imposes an extra level of nesting that seems unnecessary. The second is a bit shorter but I still don’t like it.
I wish there was something like

with trio.fail_after(TIMEOUT, lambda: ProtocolError("Question '?' not answered in time"))
  await send_query("?")
  answer = await receive_answer(question="?")
return answer + "!"