docs: def parse_sections(data):
      """
      yields one section at a time in the form
  
      [ (key, [val, ...]), ... ]
  
      where key is a string and val is a string representing a single
      line of any value associated with the key. Multiple vals may be
      present if the value is long enough to require line continuations
      in which case simply concatenate the vals together to get the full
      value.
      :type data: unicode in Py2, str in Py3
      """
  
      if not data:
          return
  
      # our current section
      curr = None
  
      for lineno, line in enumerate(data.splitlines()):
          # Clean up the line
          cleanline = line.replace('\x00', '')
  
          if not cleanline:
              # blank line means end of current section (if any)
              if curr:
                  yield curr
                  curr = None
  
          elif cleanline[0] == ' ':
              # line beginning with a space means a continuation
              if curr is None:
                  raise MalformedManifest("bad line continuation, "
                                          " line: %i" % lineno)
              else:
                  # pylint: disable=unsubscriptable-object
                  curr[-1][1].append(cleanline[1:])
  
          else:
              # otherwise the beginning of a new k:v pair
              if curr is None:
                  curr = list()
  
              try:
                  key, val = cleanline.split(':', 1)
                  curr.append((key, [val[1:]]))
              except ValueError:
                  raise MalformedManifest(
                      "Invalid manifest line: %i; line contents: %s"
                      % (lineno, cleanline))
  
  
      # yield and leftovers
      if curr:
          yield curr