From aaf392c6efd32a6025c26847d02f952dcf700ba7 Mon Sep 17 00:00:00 2001 From: Abdu Ahmed Date: Sun, 24 May 2026 11:47:23 +0300 Subject: [PATCH] Fix --sort-reexports crash with non-seekable streams (e.g. stdin) When --sort-reexports was used with stdin, isort crashed with io.UnsupportedOperation because core.process() called seek() on stdout, which is not seekable. Fix: in api.sort_stream(), if sort_reexports is enabled and the output stream is not seekable, swap it for an internal StringIO buffer before passing to core.process(). Fixes #2393 --- isort/api.py | 2 ++ tests/unit/test_regressions.py | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/isort/api.py b/isort/api.py index abf8bdb1..43dec051 100644 --- a/isort/api.py +++ b/isort/api.py @@ -203,6 +203,8 @@ def sort_stream( if not output_stream.readable(): _internal_output = StringIO() + if config.sort_reexports and not _internal_output.seekable(): + _internal_output = StringIO() try: changed = core.process( input_stream, diff --git a/tests/unit/test_regressions.py b/tests/unit/test_regressions.py index bd0e538d..34920867 100644 --- a/tests/unit/test_regressions.py +++ b/tests/unit/test_regressions.py @@ -1985,3 +1985,27 @@ 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_sort_reexports_with_non_seekable_stream_issue_2393(): + """Ensure --sort-reexports does not crash when output stream is non-seekable (e.g. stdin). + See: https://github.com/PyCQA/isort/issues/2393 + """ + import sys + from io import StringIO + + code = "from test import B, A\n__all__ = ['B', 'A']\n" + input_stream = StringIO(code) + isort.api.sort_stream( + input_stream=input_stream, + output_stream=sys.stdout, + sort_reexports=True, + ) + input_stream = StringIO(code) + output_stream = StringIO() + isort.api.sort_stream( + input_stream=input_stream, + output_stream=output_stream, + sort_reexports=True, + ) + output_stream.seek(0) + assert "import A, B" in output_stream.read() \ No newline at end of file