Source code for bot_api.internal.recording_text_writer

"""
RecordingTextWriter - Captures stdout/stderr output for sending to server.
This matches the functionality of RecordingPrintStream (Java) and RecordingTextWriter (C#/.NET).
"""

import sys
from io import StringIO
from threading import Lock
from typing import TextIO


[docs] class RecordingTextWriter: """ A text writer wrapper that records all written text and forwards it to an underlying writer. Thread-safe for concurrent writes (e.g., from print statements in event handlers). """
[docs] def __init__(self, text_writer: TextIO): """ Initialize the recording text writer. Args: text_writer: The underlying text writer to forward output to (e.g., sys.stdout) """ self._text_writer = text_writer self._string_writer = StringIO() self._lock = Lock()
[docs] def write(self, text: str) -> int: """ Write text to both the underlying writer and the recording buffer. Thread-safe. Args: text: The text to write Returns: The number of characters written """ with self._lock: self._text_writer.write(text) self._string_writer.write(text) return len(text)
[docs] def flush(self) -> None: """Flush both the underlying writer and the recording buffer. Thread-safe.""" with self._lock: self._text_writer.flush() self._string_writer.flush()
[docs] def read_next(self) -> str: """ Read and clear the recorded output since the last read. Thread-safe. Returns: The recorded output as a string """ with self._lock: output = self._string_writer.getvalue() # Clear the buffer self._string_writer.close() self._string_writer = StringIO() return output
[docs] def isatty(self) -> bool: """Return whether the underlying writer is a TTY.""" return self._text_writer.isatty()
@property def encoding(self) -> str: """Return the encoding of the underlying writer.""" return getattr(self._text_writer, 'encoding', 'utf-8') @property def errors(self): """Return the error handling mode of the underlying writer.""" return getattr(self._text_writer, 'errors', None)