Skip to content

Commit 4071653

Browse files
committed
Handle closed standard input gracefully
For: #26
1 parent f9bd0e4 commit 4071653

File tree

6 files changed

+60
-24
lines changed

6 files changed

+60
-24
lines changed

.github/workflows/lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,5 @@ jobs:
4646
run: |
4747
set -o xtrace
4848
./run-tests
49-
git clone https://github.com/nickboucher/trojan-source
49+
git clone https://github.com/nickboucher/trojan-source ~/trojan-source
5050
./unicode-testscript

run-tests

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,20 @@ NO_COLOR="" COLORTERM="" TERM="xterm-direct" "${pytest[@]}" "${@}"
1717
find . -type f -name "*.py" -print0 | xargs -0 "${pylint[@]}"
1818
"${mypy[@]}" .
1919

20-
utils=(stprint stecho stcat stcatn sttee stsponge)
20+
stdin_utils_to_stdout=(stcat stcatn)
21+
stdin_utils_to_file=(sttee stsponge)
22+
utils=(stprint stecho "${stdin_utils[@]}")
2123
cd "${git_toplevel}/usr/bin"
2224
"${black[@]}" -- "${utils[@]}"
2325
"${pylint[@]}" -- "${utils[@]}"
2426
for file in "${utils[@]}"; do
2527
"${mypy[@]}" -- "${file}"
2628
done
29+
30+
for util in "${stdin_utils_to_stdout[@]}"; do
31+
./"${util}" <&-
32+
./"${util}" - <&-
33+
done
34+
for util in "${stdin_utils_to_file[@]}"; do
35+
./"${util}" <&-
36+
done

usr/lib/python3/dist-packages/stdisplay/stcat.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,31 @@
77

88
"""Safely print stdin or file to stdout."""
99

10-
from fileinput import input as file_input
11-
from sys import stdin, stdout, modules
10+
from pathlib import Path
11+
from sys import argv, stdin, stdout, modules
1212
from stdisplay.stdisplay import stdisplay
1313

1414

1515
def main() -> None:
1616
"""Safely print stdin or file to stdout."""
1717
# https://github.com/pytest-dev/pytest/issues/4843
18-
if "pytest" not in modules:
18+
if "pytest" not in modules and stdin is not None:
1919
stdin.reconfigure(errors="ignore") # type: ignore
20-
## File input reads stdin when no file is provided or file is '-'.
21-
for untrusted_text in file_input(encoding="ascii", errors="replace"):
22-
stdout.write(stdisplay(untrusted_text))
20+
if len(argv) == 1:
21+
if stdin is not None:
22+
for untrusted_line in stdin:
23+
stdout.write(stdisplay(untrusted_line))
24+
stdout.flush()
25+
return
26+
for untrusted_arg in argv[1:]:
27+
if untrusted_arg == "-":
28+
if stdin is not None:
29+
for untrusted_line in stdin:
30+
stdout.write(stdisplay(untrusted_line))
31+
else:
32+
path = Path(untrusted_arg)
33+
untrusted_text = path.read_text(encoding="ascii", errors="replace")
34+
stdout.write(stdisplay(untrusted_text))
2335
stdout.flush()
2436

2537

usr/lib/python3/dist-packages/stdisplay/stcatn.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,34 @@
1010
(trim trailing whitespace, ensure final newline).
1111
"""
1212

13-
from fileinput import input as file_input
14-
from sys import stdin, stdout, modules
13+
from pathlib import Path
14+
from sys import argv, stdin, stdout, modules
1515
from stdisplay.stdisplay import stdisplay
1616

1717

1818
def main() -> None:
1919
"""
20-
main
20+
Safely print stdin or file to stdout with tweaks
21+
(trim trailing whitespace, ensure final newline).
2122
"""
2223
# https://github.com/pytest-dev/pytest/issues/4843
23-
if "pytest" not in modules:
24+
if "pytest" not in modules and stdin is not None:
2425
stdin.reconfigure(errors="ignore") # type: ignore
25-
26-
for line in file_input(encoding="ascii", errors="replace"):
27-
stdout.write(stdisplay(line).rstrip() + "\n")
28-
26+
if len(argv) == 1:
27+
if stdin is not None:
28+
for untrusted_line in stdin:
29+
stdout.write(stdisplay(untrusted_line).rstrip() + "\n")
30+
stdout.flush()
31+
return
32+
for untrusted_arg in argv[1:]:
33+
if untrusted_arg == "-":
34+
if stdin is not None:
35+
for untrusted_line in stdin:
36+
stdout.write(stdisplay(untrusted_line).rstrip() + "\n")
37+
else:
38+
path = Path(untrusted_arg)
39+
untrusted_text = path.read_text(encoding="ascii", errors="replace")
40+
stdout.write(stdisplay(untrusted_text).rstrip() + "\n")
2941
stdout.flush()
3042

3143

usr/lib/python3/dist-packages/stdisplay/stsponge.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@
1616
def main() -> None:
1717
"""Safely print stdin to stdout or file."""
1818
# https://github.com/pytest-dev/pytest/issues/4843
19-
if "pytest" not in modules:
19+
if "pytest" not in modules and stdin is not None:
2020
stdin.reconfigure(errors="ignore") # type: ignore
2121
untrusted_text_list = []
22-
for untrusted_text in stdin:
23-
untrusted_text_list.append(untrusted_text)
22+
if stdin is not None:
23+
for untrusted_text in stdin:
24+
untrusted_text_list.append(untrusted_text)
2425
if len(argv) == 1:
2526
stdout.write(stdisplay("".join(untrusted_text_list)))
2627
stdout.flush()

usr/lib/python3/dist-packages/stdisplay/sttee.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@
1313
def main() -> None:
1414
"""Safely print stdin to stdout and file."""
1515
# https://github.com/pytest-dev/pytest/issues/4843
16-
if "pytest" not in modules:
16+
if "pytest" not in modules and stdin is not None:
1717
stdin.reconfigure(errors="ignore") # type: ignore
1818
untrusted_text_list = []
19-
for untrusted_text in stdin:
20-
untrusted_text_list.append(untrusted_text)
21-
stdout.write(stdisplay(untrusted_text))
22-
stdout.flush()
19+
if stdin is not None:
20+
for untrusted_text in stdin:
21+
untrusted_text_list.append(untrusted_text)
22+
stdout.write(stdisplay(untrusted_text))
23+
stdout.flush()
2324
if len(argv) > 1:
2425
for file_arg in argv[1:]:
2526
with open(file_arg, mode="w", encoding="ascii") as file:

0 commit comments

Comments
 (0)