Called by the client protocol to temporarily switch to a new
        send framer, receive framer, or both.  Can be called multiple
        times.  Each call to ``push_framer()`` must be paired with a
        call to ``pop_framer()``, which restores to the previously set
        framer.

        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 push_framer(self, *args, **kwargs):
        """
        Called by the client protocol to temporarily switch to a new
        send framer, receive framer, or both.  Can be called multiple
        times.  Each call to ``push_framer()`` must be paired with a
        call to ``pop_framer()``, which restores to the previously set
        framer.

        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)

        # Append the element to the framer stack
        self._framers.append(elem)