docs: def send_frame(self, frame):
          '''
          Send a single frame. If there is no transport or we're not connected
          yet, append to the output buffer, else send immediately to the socket.
          This is called from within the MethodFrames.
          '''
          if self._closed:
              if self._close_info and len(self._close_info['reply_text']) > 0:
                  raise ConnectionClosed("connection is closed: %s : %s" %
                                         (self._close_info['reply_code'],
                                          self._close_info['reply_text']))
              raise ConnectionClosed("connection is closed")
  
          if self._transport is None or \
                  (not self._connected and frame.channel_id != 0):
              self._output_frame_buffer.append(frame)
              return
  
          if self._debug > 1:
              self.logger.debug("WRITE: %s", frame)
  
          buf = bytearray()
          frame.write_frame(buf)
          if len(buf) > self._frame_max:
              self.close(
                  reply_code=501,
                  reply_text='attempted to send frame of %d bytes, frame max %d' % (
                      len(buf), self._frame_max),
                  class_id=0, method_id=0, disconnect=True)
              raise ConnectionClosed(
                  "connection is closed: %s : %s" %
                  (self._close_info['reply_code'],
                   self._close_info['reply_text']))
          self._transport.write(buf)
  
          self._frames_written += 1