mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-26 13:47:20 -05:00
fix: say a pipe when output goes to a pipe
| tee log.txt was told its output went to a file. The line now names a pipe or a file, and says how to keep the run or answer.
This commit is contained in:
1 parent
359c260e98
commit
71162d124d
2 files changed
+52
-2
No files matched your search
+18
-2
@@ -9023,6 +9023,18 @@ def _is_terminal(stream: TextIO) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def _output_kind(stream: TextIO) -> str:
|
||||
""""pipe" or "file" for what stream writes to, "" when neither is known.
|
||||
`| tee log.txt` shows every line, `> log.txt` none of them."""
|
||||
try:
|
||||
mode = os.fstat(stream.fileno()).st_mode
|
||||
except (OSError, ValueError, AttributeError, io.UnsupportedOperation):
|
||||
return ""
|
||||
if stat.S_ISFIFO(mode) or stat.S_ISSOCK(mode):
|
||||
return "pipe"
|
||||
return "file" if stat.S_ISREG(mode) else ""
|
||||
|
||||
|
||||
def _install(args: argparse.Namespace, real_stdout: TextIO) -> None:
|
||||
"""One run of the installer, once the options are read."""
|
||||
KEPT.reset()
|
||||
@@ -9035,8 +9047,12 @@ def _install(args: argparse.Namespace, real_stdout: TextIO) -> None:
|
||||
# to a prompt nobody could see.
|
||||
interactive = False
|
||||
if not listing and not args.check:
|
||||
print("Output goes to a file, so nothing is asked: the run goes on as "
|
||||
"with --no-input.", file=sys.stderr)
|
||||
kind = _output_kind(real_stdout)
|
||||
where = f"Output goes to a {kind}" if kind else "Output is not a terminal"
|
||||
undo = "the pipe" if kind == "pipe" else "the redirection"
|
||||
print(f"{where}, so nothing is asked: the run goes on as with --no-input. "
|
||||
f"Add --no-input to say so, or run it without {undo} to answer.",
|
||||
file=sys.stderr)
|
||||
print(f"{term.bold('RetroBIOS')} {term.dim(installer_id())}\n")
|
||||
|
||||
os_type = detect_os()
|
||||
|
||||
@@ -618,6 +618,40 @@ class OutputToAFileAsksNothing(unittest.TestCase):
|
||||
self.assertNotIn("Enter) install everything", proc.stdout)
|
||||
self.assertEqual(len(installed), len(FakeRepository.PAYLOADS))
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "a pseudo-terminal for stdin")
|
||||
def test_a_pipe_is_named_a_pipe(self):
|
||||
"""`install.py | tee log.txt` was told its output went to a file."""
|
||||
import pty
|
||||
|
||||
master, slave = pty.openpty()
|
||||
self.addCleanup(os.close, master)
|
||||
self.addCleanup(os.close, slave)
|
||||
with FakeRepository() as repo:
|
||||
piped = subprocess.run(
|
||||
[*repo.command(), "--dry-run"], env=repo.env(), stdin=slave,
|
||||
capture_output=True, text=True, timeout=60, check=False)
|
||||
log = repo.root / "log.txt"
|
||||
with open(log, "w", encoding="utf-8") as handle:
|
||||
filed = subprocess.run(
|
||||
[*repo.command(), "--dry-run"], env=repo.env(), stdin=slave,
|
||||
stdout=handle, stderr=subprocess.PIPE, text=True, timeout=60,
|
||||
check=False)
|
||||
self.assertIn("Output goes to a pipe, so nothing is asked", piped.stderr)
|
||||
self.assertIn("run it without the pipe to answer", piped.stderr)
|
||||
self.assertIn("Output goes to a file, so nothing is asked", filed.stderr)
|
||||
self.assertIn("run it without the redirection to answer", filed.stderr)
|
||||
for proc in (piped, filed):
|
||||
self.assertIn("Add --no-input to say so", proc.stderr)
|
||||
|
||||
def test_the_kind_of_output(self):
|
||||
self.assertEqual(install._output_kind(io.StringIO()), "")
|
||||
read, write = os.pipe()
|
||||
with open(read, "rb") as reader, open(write, "w") as writer:
|
||||
self.assertEqual(install._output_kind(writer), "pipe")
|
||||
del reader
|
||||
with tempfile.TemporaryFile("w", dir=REPO_ROOT / "tmp") as handle:
|
||||
self.assertEqual(install._output_kind(handle), "file")
|
||||
|
||||
|
||||
class _Tty(io.StringIO):
|
||||
def isatty(self) -> bool:
|
||||
|
||||
Reference in new issue
Block a user