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.

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