diff --git a/isort/main.py b/isort/main.py index 9369ddd1..c0ce1ef0 100644 --- a/isort/main.py +++ b/isort/main.py @@ -1060,7 +1060,18 @@ def main(argv: Sequence[str] | None = None, stdin: TextIOWrapper | None = None) if show_files: sys.exit("Error: can't show files for streaming input.") - input_stream = sys.stdin if stdin is None else stdin + if stdin is None: + raw = sys.stdin.buffer.read() + if b"\r\n" in raw: + line_ending = "\r\n" + elif b"\r" in raw: + line_ending = "\r" + else: + line_ending = "\n" + import io + input_stream = io.TextIOWrapper(io.BytesIO(raw), encoding=sys.stdin.encoding or "utf-8") + else: + input_stream = stdin if check: incorrectly_sorted = not api.check_stream( input_stream=input_stream, diff --git a/tests/unit/test_regressions.py b/tests/unit/test_regressions.py index bd0e538d..d65dd10f 100644 --- a/tests/unit/test_regressions.py +++ b/tests/unit/test_regressions.py @@ -1985,3 +1985,19 @@ def test_comment_on_opening_line_of_aliased_import_does_not_move(): isort.code(short_line, profile="black") == "from mod import attr as alias # type: ignore[attr-defined] # My comment\n" ) + + +def test_lf_line_endings_preserved_from_stdin_issue_2453(): + """LF line endings should be preserved when reading from stdin on Windows. + See: https://github.com/PyCQA/isort/issues/2453 + """ + import io + lf_content = "import os\nimport re\n" + input_stream = io.TextIOWrapper( + io.BytesIO(lf_content.encode("utf-8")), encoding="utf-8" + ) + output_stream = io.StringIO() + from isort import core + core.process(input_stream, output_stream) + result = output_stream.getvalue() + assert "\r\n" not in result, "LF input should not be converted to CRLF"