class_docstr: A line splitter that handles 'streamed content' and is based
  on python's built-in splitlines().
class_docstr_tok: ["A","line","splitter","that","handles","'streamed","content","'","and","is","based","on","python","'s","built-in","splitlines","(",")","."]
code: def process(self, data: str) -> list[str]:
      assert isinstance(data, str), f"data ({data}) is not of type str"
  
      # There is nothing to do if we do not get any data, since
      # remaining data would not change, and if it is not None,
      # it has already been parsed.
      if data == "":
          return []
  
      # Update remaining data before attempting to split lines.
      if self.remaining_data is None:
          self.remaining_data = ""
      self.remaining_data += data
  
      if self.separator is None:
          # If no separator was specified, use python's built in
          # line split wisdom to split on any known line ending.
          lines_with_ends = self.remaining_data.splitlines(
              keepends=True
          )
          detected_lines = self.remaining_data.splitlines()
  
          # If the last line is identical in lines with ends and
          # lines without ends, it was unterminated, remove it
          # from the list of detected lines and keep it for the
          # next round
          if lines_with_ends[-1] == detected_lines[-1]:
              self.remaining_data = lines_with_ends[-1]
              del lines_with_ends[-1]
              del detected_lines[-1]
          else:
              self.remaining_data = None
  
          if self.keep_ends:
              return lines_with_ends
          return detected_lines
  
      else:
          # Split lines on separator. This will create additional
          # empty lines if `remaining_data` end with the separator.
          detected_lines = self.remaining_data.split(self.separator)
  
          # If replaced data did not end with the separator, it contains an
          # unterminated line. We save that for the next round. Otherwise,
          # we mark that we do not have remaining data.
          if not data.endswith(self.separator):
              self.remaining_data = detected_lines[-1]
          else:
              self.remaining_data = None
  
          # If replaced data ended with the canonical line ending, we
          # have an extra empty line in detected_lines. If it did not
          # end with canonical line ending, we have to remove the
          # unterminated line.
          del detected_lines[-1]
  
          if self.keep_ends:
              return [line + self.separator for line in detected_lines]
          return detected_lines
  
file_path: datalad/datalad/runner/utils.py
imports: from __future__ import annotations
  import logging
  from collections import defaultdict
  from typing import Optional
label_desc: Use image node_id 2 for calling the LineSplitter obj's underlying member method code with example usage: obj.process(data) and returns: list, detected_lines, detected_lines, lines_with_ends, unknown