FileProxy (used by Live when redirect_stdout=True) inherits isatty() from io.TextIOBase, which always returns False. This breaks code that checks sys.stdout.isatty() inside a Live context.
FileProxy already delegates fileno() (line 56-57) and has a generic __getattr__ fallback (line 25-26), but isatty() is defined on io.TextIOBase in the MRO, so __getattr__ is never reached for it.
Reproduction
import sys
from rich.console import Console
from rich.live import Live
console = Console()
print("Before Live:", sys.stdout.isatty()) # True
with Live("hello", console=console, redirect_stdout=True):
print("Inside Live:", sys.stdout.isatty()) # False (should be True)
print("After Live:", sys.stdout.isatty()) # True
Impact
Any code running inside a Live context with redirect_stdout=True that branches on isatty() gets the wrong answer. This is particularly problematic for applications that use Live for streaming display while also executing callbacks/tools that check whether stdout is a terminal.
Suggested fix
Add an isatty() method to FileProxy that delegates to the underlying file, consistent with how fileno() is already handled:
def isatty(self) -> bool:
return self.__file.isatty()
FileProxy(used byLivewhenredirect_stdout=True) inheritsisatty()fromio.TextIOBase, which always returnsFalse. This breaks code that checkssys.stdout.isatty()inside aLivecontext.FileProxyalready delegatesfileno()(line 56-57) and has a generic__getattr__fallback (line 25-26), butisatty()is defined onio.TextIOBasein the MRO, so__getattr__is never reached for it.Reproduction
Impact
Any code running inside a
Livecontext withredirect_stdout=Truethat branches onisatty()gets the wrong answer. This is particularly problematic for applications that useLivefor streaming display while also executing callbacks/tools that check whether stdout is a terminal.Suggested fix
Add an
isatty()method toFileProxythat delegates to the underlying file, consistent with howfileno()is already handled: