code: def attrsignal(descriptor, signal_name, *, defer=False):
      
      def decorator(f):
          add_handler_spec(
              f,
              _attrsignal_spec(descriptor, signal_name, f, defer)
          )
          return f
      return decorator
docs: Connect the decorated method or coroutine method to the addressed signal on
      a descriptor.
  
      :param descriptor: The descriptor to connect to.
      :type descriptor: :class:`Descriptor` subclass.
      :param signal_name: Attribute name of the signal to connect to
      :type signal_name: :class:`str`
      :param defer: Flag indicating whether deferred execution of the decorated
                    method is desired; see below for details.
      :type defer: :class:`bool`
  
      The signal is discovered by accessing the attribute with the name
      `signal_name` on the :attr:`~Descriptor.value_type` of the `descriptor`.
  
      During instantiation of the service, the value of the descriptor is used
      to obtain the signal and then the decorated method is connected to the
      signal.
  
      If the signal is a :class:`.callbacks.Signal` and `defer` is false, the
      decorated object is connected using the default
      :attr:`~.callbacks.AdHocSignal.STRONG` mode.
  
      If the signal is a :class:`.callbacks.Signal` and `defer` is true and the
      decorated object is a coroutine function, the
      :attr:`~.callbacks.AdHocSignal.SPAWN_WITH_LOOP` mode with the default
      asyncio event loop is used. If the decorated object is not a coroutine
      function, :attr:`~.callbacks.AdHocSignal.ASYNC_WITH_LOOP` is used instead.
  
      If the signal is a :class:`.callbacks.SyncSignal`, `defer` must be false
      and the decorated object must be a coroutine function.
  
      .. versionadded:: 0.9