class_docstr: Subprocess communication protocol base class for `run_async_cmd`
  
  This class implements basic subprocess output handling. Derived classes
  like `StdOutCapture` should be used for subprocess communication that need
  to capture and return output. In particular, the `pipe_data_received()`
  method can be overwritten to implement "online" processing of process
  output.
  
  This class defines a default return value setup that causes
  `run_async_cmd()` to return a 2-tuple with the subprocess's exit code
  and a list with bytestrings of all captured output streams.
code: def _log_summary(self, fd: int, data: str | bytes) -> None:
      fd_name = self.fd_infos[fd][0]
      assert self.process is not None
      lgr.log(
          5,
          "Read %i bytes from %i[%s]%s",
          len(data),
          self.process.pid,
          fd_name,
          ":" if self._log_outputs else "",
      )
      if self._log_outputs:
          log_data = ensure_unicode(data)
          # The way we log is to stay consistent with Runner.
          # TODO: later we might just log in a single entry, without
          # fd_name prefix
          lgr.log(5, "%s| %s ", fd_name, log_data)
  
imports: from __future__ import annotations
  import logging
  import subprocess
  import warnings
  from collections import deque
  from locale import getpreferredencoding
  from typing import Any, Optional
  from datalad.utils import ensure_unicode
  from .exception import CommandError
label_desc: Use image node_id 3 for calling the WitlessProtocol obj's underlying member method code with example usage: obj._log_summary(fd, data) without return types