Skip to content

Commit

Permalink
Merge pull request #119 from AndydeCleyre/feature/stdin-stdout
Browse files Browse the repository at this point in the history
Implement stdin-stdout operation with '-' file argument
  • Loading branch information
bwhmather authored Nov 4, 2024
2 parents f89be62 + 39593a8 commit 6e66c2c
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 17 deletions.
2 changes: 1 addition & 1 deletion src/ssort/_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def find_python_files(
paths_set = set()
for pattern in patterns:
path = pathlib.Path(pattern)
if not path.is_dir():
if str(path) == "-" or not path.is_dir():
subpaths = [path]
else:
subpaths = [
Expand Down
56 changes: 40 additions & 16 deletions src/ssort/_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ def main():
"needs to be changed. Otherwise returns 1.",
)
parser.add_argument(
"files", nargs="*", help="One or more python files to sort"
"files",
nargs="*",
help="One or more python files to sort, or '-' for stdin.",
)

args = parser.parse_args()
Expand All @@ -56,20 +58,29 @@ def main():
for path in find_python_files(args.files):
errors = False

try:
original_bytes = path.read_bytes()
except FileNotFoundError:
sys.stderr.write(f"ERROR: {escape_path(path)} does not exist\n")
unsortable += 1
continue
except IsADirectoryError:
sys.stderr.write(f"ERROR: {escape_path(path)} is a directory\n")
unsortable += 1
continue
except PermissionError:
sys.stderr.write(f"ERROR: {escape_path(path)} is not readable\n")
unsortable += 1
continue
if str(path) == "-":
original_bytes = sys.stdin.buffer.read()
else:
try:
original_bytes = path.read_bytes()
except FileNotFoundError:
sys.stderr.write(
f"ERROR: {escape_path(path)} does not exist\n"
)
unsortable += 1
continue
except IsADirectoryError:
sys.stderr.write(
f"ERROR: {escape_path(path)} is a directory\n"
)
unsortable += 1
continue
except PermissionError:
sys.stderr.write(
f"ERROR: {escape_path(path)} is not readable\n"
)
unsortable += 1
continue

# The logic for converting from bytes to text is duplicated in `ssort`
# and here because we need access to the text to be able to compute a
Expand All @@ -80,6 +91,8 @@ def main():
sys.stderr.write(
f"ERROR: unknown encoding, {exc.encoding!r}, in {escape_path(path)}\n"
)
if str(path) == "-":
sys.stdout.buffer.write(original_bytes)
unsortable += 1
continue

Expand All @@ -89,6 +102,8 @@ def main():
sys.stderr.write(
f"ERROR: encoding error in {escape_path(path)}: {exc}\n"
)
if str(path) == "-":
sys.stdout.buffer.write(original_bytes)
unsortable += 1
continue

Expand Down Expand Up @@ -129,10 +144,14 @@ def _on_wildcard_import(**kwargs):
)

if errors:
if str(path) == "-":
sys.stdout.buffer.write(original_bytes)
unsortable += 1
continue

except Exception as e:
if str(path) == "-":
sys.stdout.buffer.write(original_bytes)
raise Exception(f"ERROR while sorting {path}\n") from e

if original != updated:
Expand All @@ -154,8 +173,13 @@ def _on_wildcard_import(**kwargs):
updated_bytes = re.sub("\n", newline, updated_bytes)
updated_bytes = updated_bytes.encode(encoding)

path.write_bytes(updated_bytes)
if str(path) == "-":
sys.stdout.buffer.write(updated_bytes)
else:
path.write_bytes(updated_bytes)
else:
if str(path) == "-" and not args.check:
sys.stdout.buffer.write(original_bytes)
unchanged += 1

if args.show_diff:
Expand Down
29 changes: 29 additions & 0 deletions tests/test_executable.py
Original file line number Diff line number Diff line change
Expand Up @@ -420,3 +420,32 @@ def test_ssort_run_module():
module_output = module_result.stderr.splitlines(keepends=True)

assert module_output == entrypoint_output


@pytest.mark.parametrize(
("stdin", "stdout"),
(
(_unsorted, _good),
(_good, _good),
(_encoding, _encoding),
(_character, _character),
(_syntax, _syntax),
(_resolution, _resolution),
(_double_resolution, _double_resolution),
),
ids=(
"unsorted",
"good",
"encoding",
"character",
"syntax",
"resolution",
"double_resolution",
),
)
def test_ssort_stdin(stdin, stdout):
for command in [(sys.executable, "-m", "ssort"), ("ssort",)]:
result = subprocess.run(
[*command, "-"], capture_output=True, input=stdin
)
assert result.stdout == stdout

0 comments on commit 6e66c2c

Please sign in to comment.