docs: def __alterDocstring(self, tail='', writer=None):
          """
          Runs eternally, processing docstring lines.
  
          Parses docstring lines as they get fed in via send, applies appropriate
          Doxygen tags, and passes them along in batches for writing.
          """
          assert isinstance(tail, str) and isinstance(writer, GeneratorType)
  
          lines = []
          timeToSend = False
          inCodeBlock = False
          inCodeBlockObj = [False]
          inSection = False
          prefix = ''
          firstLineNum = -1
          sectionHeadingIndent = 0
          codeChecker = self._checkIfCode(inCodeBlockObj)
          while True:
              lineNum, line = (yield)
              if firstLineNum < 0:
                  firstLineNum = lineNum
              # Don't bother doing extra work if it's a sentinel.
              if line is not None:
                  # Also limit work if we're not parsing the docstring.
                  if self.options.autobrief:
                      for doxyTag, tagRE in AstWalker.__singleLineREs.items():
                          match = tagRE.search(line)
                          if match:
                              # We've got a simple one-line Doxygen command
                              lines[-1], inCodeBlock = self._endCodeIfNeeded(
                                  lines[-1], inCodeBlock)
                              inCodeBlockObj[0] = inCodeBlock
                              writer.send((firstLineNum, lineNum - 1, lines))
                              lines = []
                              firstLineNum = lineNum
                              line = line.replace(match.group(1), doxyTag)
                              timeToSend = True
  
                      if inSection:
                          # The last line belonged to a section.
                          # Does this one too? (Ignoring empty lines.)
                          match = AstWalker.__blanklineRE.match(line)
                          if not match:
                              indent = len(line.expandtabs(self.options.tablength)) - \
                                  len(line.expandtabs(self.options.tablength).lstrip())
                              if indent <= sectionHeadingIndent:
                                  inSection = False
                              else:
                                  if lines[-1] == '#':
                                      # If the last line was empty, but we're still in a section
                                      # then we need to start a new paragraph.
                                      lines[-1] = '# @par'
  
                      match = AstWalker.__returnsStartRE.match(line)
                      if match:
                          # We've got a "returns" section
                          lines[-1], inCodeBlock = self._endCodeIfNeeded(
                              lines[-1], inCodeBlock)
                          inCodeBlockObj[0] = inCodeBlock
                          line = line.replace(match.group(0), ' @return\t').rstrip()
                          prefix = '@return\t'
                      else:
                          match = AstWalker.__argsStartRE.match(line)
                          if match:
                              # We've got an "arguments" section
                              line = line.replace(match.group(0), '').rstrip()
                              if 'attr' in match.group(0).lower():
                                  prefix = '@property\t'
                              else:
                                  prefix = '@param\t'
                              lines[-1], inCodeBlock = self._endCodeIfNeeded(
                                  lines[-1], inCodeBlock)
                              inCodeBlockObj[0] = inCodeBlock
                              lines.append('#' + line)
                              continue
                          else:
                              match = AstWalker.__argsRE.match(line)
                              if match and not inCodeBlock:
                                  # We've got something that looks like an item /
                                  # description pair.
                                  if 'property' in prefix:
                                      line = '# {0}\t{1[name]}{2}# {1[desc]}'.format(
                                          prefix, match.groupdict(), linesep)
                                  else:
                                      line = ' {0}\t{1[name]}\t{1[desc]}'.format(
                                          prefix, match.groupdict())
                              else:
                                  match = AstWalker.__raisesStartRE.match(line)
                                  if match:
                                      line = line.replace(match.group(0), '').rstrip()
                                      if 'see' in match.group(1).lower():
                                          # We've got a "see also" section
                                          prefix = '@sa\t'
                                      else:
                                          # We've got an "exceptions" section
                                          prefix = '@exception\t'
                                      lines[-1], inCodeBlock = self._endCodeIfNeeded(
                                          lines[-1], inCodeBlock)
                                      inCodeBlockObj[0] = inCodeBlock
                                      lines.append('#' + line)
                                      continue
                                  else:
                                      match = AstWalker.__listRE.match(line)
                                      if match and not inCodeBlock:
                                          # We've got a list of something or another
                                          itemList = []
                                          for itemMatch in AstWalker.__listItemRE.findall(self._stripOutAnds(
                                                                                          match.group(0))):
                                              itemList.append('# {0}\t{1}{2}'.format(
                                                  prefix, itemMatch, linesep))
                                          line = ''.join(itemList)[1:]
                                      else:
                                          match = AstWalker.__examplesStartRE.match(line)
                                          if match and lines[-1].strip() == '#' \
                                             and self.options.autocode:
                                              # We've got an "example" section
                                              inCodeBlock = True
                                              inCodeBlockObj[0] = True
                                              line = line.replace(match.group(0),
                                                                  ' @b Examples{0}# @code'.format(linesep))
                                          else:
                                              match = AstWalker.__sectionStartRE.match(line)
                                              if match:
                                                  # We've got an arbitrary section
                                                  prefix = ''
                                                  inSection = True
                                                  # What's the indentation of the section heading?
                                                  sectionHeadingIndent = len(line.expandtabs(self.options.tablength)) \
                                                      - len(line.expandtabs(self.options.tablength).lstrip())
                                                  line = line.replace(
                                                      match.group(0),
                                                      ' @par {0}'.format(match.group(1))
                                                  )
                                                  if lines[-1] == '# @par':
                                                      lines[-1] = '#'
                                                  lines[-1], inCodeBlock = self._endCodeIfNeeded(
                                                      lines[-1], inCodeBlock)
                                                  inCodeBlockObj[0] = inCodeBlock
                                                  lines.append('#' + line)
                                                  continue
                                              elif prefix:
                                                  match = AstWalker.__singleListItemRE.match(line)
                                                  if match and not inCodeBlock:
                                                      # Probably a single list item
                                                      line = ' {0}\t{1}'.format(
                                                          prefix, match.group(0))
                                                  elif self.options.autocode:
                                                      codeChecker.send(
                                                          (
                                                              line, lines,
                                                              lineNum - firstLineNum
                                                          )
                                                      )
                                                      inCodeBlock = inCodeBlockObj[0]
                                              else:
                                                  if self.options.autocode:
                                                      codeChecker.send(
                                                          (
                                                              line, lines,
                                                              lineNum - firstLineNum
                                                          )
                                                      )
                                                      inCodeBlock = inCodeBlockObj[0]
  
                  # If we were passed a tail, append it to the docstring.
                  # Note that this means that we need a docstring for this
                  # item to get documented.
                  if tail and lineNum == len(self.docLines) - 1:
                      line = '{0}{1}# {2}'.format(line.rstrip(), linesep, tail)
  
                  # Add comment marker for every line.
                  line = '#{0}'.format(line.rstrip())
                  # Ensure the first line has the Doxygen double comment.
                  if lineNum == 0:
                      line = '#' + line
  
                  lines.append(line.replace(' ' + linesep, linesep))
              else:
                  # If we get our sentinel value, send out what we've got.
                  timeToSend = True
  
              if timeToSend:
                  lines[-1], inCodeBlock = self._endCodeIfNeeded(lines[-1],
                                                                 inCodeBlock)
                  inCodeBlockObj[0] = inCodeBlock
                  writer.send((firstLineNum, lineNum, lines))
                  lines = []
                  firstLineNum = -1
                  timeToSend = False