aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Lib/_pyio.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/_pyio.py')
-rw-r--r--Lib/_pyio.py17
1 files changed, 16 insertions, 1 deletions
diff --git a/Lib/_pyio.py b/Lib/_pyio.py
index 18849b309b8..2a1d2a33d02 100644
--- a/Lib/_pyio.py
+++ b/Lib/_pyio.py
@@ -238,7 +238,7 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None,
result = raw
try:
line_buffering = False
- if buffering == 1 or buffering < 0 and raw.isatty():
+ if buffering == 1 or buffering < 0 and raw._isatty_open_only():
buffering = -1
line_buffering = True
if buffering < 0:
@@ -1794,6 +1794,21 @@ class FileIO(RawIOBase):
self._checkClosed()
return os.isatty(self._fd)
+ def _isatty_open_only(self):
+ """Checks whether the file is a TTY using an open-only optimization.
+
+ TTYs are always character devices. If the interpreter knows a file is
+ not a character device when it would call ``isatty``, can skip that
+ call. Inside ``open()`` there is a fresh stat result that contains that
+ information. Use the stat result to skip a system call. Outside of that
+ context TOCTOU issues (the fd could be arbitrarily modified by
+ surrounding code).
+ """
+ if (self._stat_atopen is not None
+ and not stat.S_ISCHR(self._stat_atopen.st_mode)):
+ return True
+ return os.isatty(self._fd)
+
@property
def closefd(self):
"""True if the file descriptor will be closed by close()."""