docs: def parse_txt_hdrs(self,
                         s,  # type: str
                         stream_id=1,  # type: int
                         body=None,  # type: Optional[str]
                         max_frm_sz=4096,  # type: int
                         max_hdr_lst_sz=0,  # type: int
                         is_sensitive=lambda n, v: False,  # type: Callable[[str, str], bool]  # noqa: E501
                         should_index=lambda x: False,  # type: Callable[[str], bool]  # noqa: E501
                         register=True,  # type: bool
                         ):
          # type: (...) -> H2Seq
          """ parse_txt_hdrs parses headers expressed in text and converts them
          into a series of H2Frames with the "correct" flags. A body can be provided  # noqa: E501
          in which case, the data frames are added, bearing the End Stream flag,
          instead of the H2HeadersFrame/H2ContinuationFrame. The generated frames
          may respect max_frm_sz (SETTINGS_MAX_FRAME_SIZE) and
          max_hdr_lst_sz (SETTINGS_MAX_HEADER_LIST_SIZE) if provided. The headers
          are split into multiple headers fragment (and H2Frames) to respect these  # noqa: E501
          limits. Also, a callback can be provided to tell if a header should be
          never indexed (sensitive headers, such as cookies), and another callback  # noqa: E501
          say if the header should be registered into the index table at all.
          For an header to be registered, the is_sensitive callback must return
          False AND the should_index callback should return True. This is the
          default behavior.
  
          @param str s: the string to parse for headers
          @param int stream_id: the stream id to use in the generated H2Frames
          @param str|None body: the eventual body of the request, that is added to the generated frames  # noqa: E501
          @param int max_frm_sz: the maximum frame size. This is used to split the headers and data frames according to  # noqa: E501
          the maximum frame size negotiated for this connection
          @param int max_hdr_lst_sz: the maximum size of a "header fragment" as defined in RFC7540  # noqa: E501
          @param callable is_sensitive: callback that returns True if the provided header is sensible and must be stored  # noqa: E501
          in a header packet requesting this header never to be indexed
          @param callable should_index: callback that returns True if the provided header should be stored in a header  # noqa: E501
          packet requesting indexation in the dynamic header table.
          @param bool register: whether to register new headers with incremental indexing as we parse them  # noqa: E501
          @raise Exception
          """
  
          sio = BytesIO(s)
  
          base_frm_len = len(raw(H2Frame()))
  
          ret = H2Seq()
          cur_frm = H2HeadersFrame()  # type: Union[H2HeadersFrame, H2ContinuationFrame]  # noqa: E501
          cur_hdr_sz = 0
  
          # For each line in the headers str to parse
          for hdr_line in sio:
              hdr_name, hdr_value = self._parse_header_line(hdr_line)
              if hdr_name is None:
                  continue
  
              new_hdr, new_hdr_len = self._convert_a_header_to_a_h2_header(
                  hdr_name, hdr_value, is_sensitive, should_index
              )
              new_hdr_bin_len = len(raw(new_hdr))
  
              if register and isinstance(new_hdr, HPackLitHdrFldWithIncrIndexing):  # noqa: E501
                  self.register(new_hdr)
  
              # The new header binary length (+ base frame size) must not exceed
              # the maximum frame size or it will just never fit. Also, the
              # header entry length (as specified in RFC7540 par6.5.2) must not
              # exceed the maximum length of a header fragment or it will just
              # never fit
              if (new_hdr_bin_len + base_frm_len > max_frm_sz or
                      (max_hdr_lst_sz != 0 and new_hdr_len > max_hdr_lst_sz)):
                  raise Exception('Header too long: {}'.format(hdr_name))
  
              if (max_frm_sz < len(raw(cur_frm)) + base_frm_len + new_hdr_len or
                  (
                      max_hdr_lst_sz != 0 and
                      max_hdr_lst_sz < cur_hdr_sz + new_hdr_len
              )
              ):
                  flags = set()
                  if isinstance(cur_frm, H2HeadersFrame) and not body:
                      flags.add('ES')
                  ret.frames.append(H2Frame(stream_id=stream_id, flags=flags) / cur_frm)  # noqa: E501
                  cur_frm = H2ContinuationFrame()
                  cur_hdr_sz = 0
  
              hdr_list = cur_frm.hdrs
              hdr_list += new_hdr
              cur_hdr_sz += new_hdr_len
  
          flags = {'EH'}
          if isinstance(cur_frm, H2HeadersFrame) and not body:
              flags.add('ES')
          ret.frames.append(H2Frame(stream_id=stream_id, flags=flags) / cur_frm)
  
          if body:
              base_data_frm_len = len(raw(H2DataFrame()))
              sio = BytesIO(body)
              frgmt = sio.read(max_frm_sz - base_data_frm_len - base_frm_len)
              while frgmt:
                  nxt_frgmt = sio.read(max_frm_sz - base_data_frm_len - base_frm_len)  # noqa: E501
                  flags = set()
                  if len(nxt_frgmt) == 0:
                      flags.add('ES')
                  ret.frames.append(
                      H2Frame(stream_id=stream_id, flags=flags) / H2DataFrame(data=frgmt)  # noqa: E501
                  )
                  frgmt = nxt_frgmt
          return ret