docs: def set_framer(self, *args, **kwargs):
          """
          Called by the client protocol to replace the current send
          framer, receive framer, or both.  This does not alter the
          stack maintained by ``push_framer()`` and ``pop_framer()``; if
          this method is called after ``push_framer()``, then
          ``pop_framer()`` is called, the framers in force at the time
          ``push_framer()`` was called will be restored.
  
          When called with positional arguments, the first argument
          specifies a framer object to replace both send and receive
          framers.  A second argument may be used to specify a state
          object for the framers; if none is specified, a new one will
          be allocated and initialized by calling the appropriate framer
          initialization method.
  
          When called with keyword arguments, the ``send`` and ``recv``
          arguments specify the send and receive framer object,
          respectively.  If either is not provided, the existing framer
          for that direction will be maintained.  The ``send_state`` and
          ``recv_state`` arguments specify optional state objects for
          the respective framers, and will be allocated and initialized
          by calling the appropriate framer initialization method, if
          not provided.  If a state argument is given without a
          corresponding replacement framer, it will be ignored.
          """
  
          # First, interpret the arguments
          elem = self._interpret_framer(args, kwargs)
  
          # Now, replace the current top of the framer stack
          self._framers[-1] = elem