docs: def execute_with_lock(self, executable: str, lock: ConnectedConsulLockInformation, *, capture_stdout: bool=False,
                            capture_stderr: bool=False) -> Tuple[int, Optional[bytes], Optional[bytes]]:
          """
          TODO
          :param executable:
          :param lock:
          :param capture_stdout:
          :param capture_stderr:
          :return:
          """
          assert lock is not None
          redirects = Munch(stdout=subprocess.PIPE if capture_stdout else sys.stdout,
                           stderr=subprocess.PIPE if capture_stderr else sys.stderr)
  
          # Patch for when sys.stdout and sys.stderr have been reassigned (e.g. in IDE test runners)
          non_realtime_redirects: Dict[str, StringIO] = {}
          for name, redirect in redirects.items():
              if isinstance(redirect, StringIO):
                  logger.warning(f"Cannot capture {name} in real-time as `sys.{name}` does not have a fileno")
                  non_realtime_redirects[name] = redirect
                  redirects[name] = subprocess.PIPE
  
          outputs = Munch(stdout=None, stderr=None)
          with lock:
              process = subprocess.Popen(executable, shell=True, stdout=redirects.stdout, stderr=redirects.stderr)
              outputs.stdout, outputs.stderr = process.communicate()
  
          # Second part of redirect reassignment patch
          for name, original_redirect in non_realtime_redirects.items():
              captured = outputs[name]
              getattr(sys, name).write(captured.decode("utf-8"))
  
          return process.returncode, \
                 outputs.stdout if capture_stdout else None, \
                 outputs.stderr if capture_stderr else None