diff --git a/packages/markitdown/src/markitdown/__main__.py b/packages/markitdown/src/markitdown/__main__.py
index b2575540b6..31c0aea8e9 100644
--- a/packages/markitdown/src/markitdown/__main__.py
+++ b/packages/markitdown/src/markitdown/__main__.py
@@ -5,6 +5,7 @@
import os
import sys
import codecs
+import io
from typing import Any, Dict
from textwrap import dedent
from importlib.metadata import entry_points
@@ -248,8 +249,9 @@ def main():
markitdown = MarkItDown(enable_plugins=args.use_plugins)
if args.filename is None:
+ # Windows pipe-backed stdin can report seekable() even though it cannot rewind.
result = markitdown.convert_stream(
- sys.stdin.buffer,
+ io.BytesIO(sys.stdin.buffer.read()),
stream_info=stream_info,
keep_data_uris=args.keep_data_uris,
)
diff --git a/packages/markitdown/tests/test_cli_misc.py b/packages/markitdown/tests/test_cli_misc.py
index cf6c9ccc78..c059d74477 100644
--- a/packages/markitdown/tests/test_cli_misc.py
+++ b/packages/markitdown/tests/test_cli_misc.py
@@ -1,6 +1,11 @@
#!/usr/bin/env python3 -m pytest
+import io
import subprocess
+import sys
+from types import SimpleNamespace
+
from markitdown import __version__
+from markitdown.__main__ import main
# This file contains CLI tests that are not directly tested by the FileTestVectors.
# This includes things like help messages, version numbers, and invalid flags.
@@ -8,7 +13,9 @@
def test_version() -> None:
result = subprocess.run(
- ["python", "-m", "markitdown", "--version"], capture_output=True, text=True
+ [sys.executable, "-m", "markitdown", "--version"],
+ capture_output=True,
+ text=True,
)
assert result.returncode == 0, f"CLI exited with error: {result.stderr}"
@@ -17,7 +24,9 @@ def test_version() -> None:
def test_invalid_flag() -> None:
result = subprocess.run(
- ["python", "-m", "markitdown", "--foobar"], capture_output=True, text=True
+ [sys.executable, "-m", "markitdown", "--foobar"],
+ capture_output=True,
+ text=True,
)
assert result.returncode != 0, f"CLI exited with error: {result.stderr}"
@@ -27,6 +36,25 @@ def test_invalid_flag() -> None:
assert "SYNTAX" in result.stderr, "Expected 'SYNTAX' to appear in STDERR"
+def test_windows_pipe_input_is_buffered_before_conversion(monkeypatch, capsys) -> None:
+ class WindowsPipe(io.BytesIO):
+ def seek(self, offset: int, whence: int = io.SEEK_SET) -> int:
+ if whence == io.SEEK_END:
+ return super().seek(offset, whence)
+ return 0
+
+ stdin = SimpleNamespace(
+ buffer=WindowsPipe(b"
Test HTML
")
+ )
+ monkeypatch.setattr(sys, "stdin", stdin)
+ monkeypatch.setattr(sys, "argv", ["markitdown", "-x", "html"])
+
+ main()
+
+ captured = capsys.readouterr()
+ assert captured.out.strip() == "# Test HTML"
+
+
if __name__ == "__main__":
"""Runs this file's tests from the command line."""
test_version()
diff --git a/packages/markitdown/tests/test_cli_vectors.py b/packages/markitdown/tests/test_cli_vectors.py
index 547c7c0001..04e0754b16 100644
--- a/packages/markitdown/tests/test_cli_vectors.py
+++ b/packages/markitdown/tests/test_cli_vectors.py
@@ -4,6 +4,7 @@
import pytest
import subprocess
import locale
+import sys
from typing import List
if __name__ == "__main__":
@@ -46,7 +47,7 @@ def test_output_to_stdout(shared_tmp_dir, test_vector) -> None:
result = subprocess.run(
[
- "python",
+ sys.executable,
"-m",
"markitdown",
os.path.join(TEST_FILES_DIR, test_vector.filename),
@@ -69,7 +70,7 @@ def test_output_to_file(shared_tmp_dir, test_vector) -> None:
output_file = os.path.join(shared_tmp_dir, test_vector.filename + ".output")
result = subprocess.run(
[
- "python",
+ sys.executable,
"-m",
"markitdown",
"-o",
@@ -83,7 +84,7 @@ def test_output_to_file(shared_tmp_dir, test_vector) -> None:
assert result.returncode == 0, f"CLI exited with error: {result.stderr}"
assert os.path.exists(output_file), f"Output file not created: {output_file}"
- with open(output_file, "r") as f:
+ with open(output_file, "r", encoding="utf-8") as f:
output_data = f.read()
for test_string in test_vector.must_include:
assert test_string in output_data
@@ -104,10 +105,9 @@ def test_input_from_stdin_without_hints(shared_tmp_dir, test_vector) -> None:
result = subprocess.run(
[
- "python",
+ sys.executable,
"-m",
"markitdown",
- os.path.join(TEST_FILES_DIR, test_vector.filename),
],
input=test_input,
capture_output=True,
@@ -135,7 +135,12 @@ def test_convert_url(shared_tmp_dir, test_vector):
time.sleep(1) # Ensure we don't hit rate limits
result = subprocess.run(
- ["python", "-m", "markitdown", TEST_FILES_URL + "/" + test_vector.filename],
+ [
+ sys.executable,
+ "-m",
+ "markitdown",
+ TEST_FILES_URL + "/" + test_vector.filename,
+ ],
capture_output=True,
text=False,
)
@@ -155,7 +160,7 @@ def test_output_to_file_with_data_uris(shared_tmp_dir, test_vector) -> None:
output_file = os.path.join(shared_tmp_dir, test_vector.filename + ".output")
result = subprocess.run(
[
- "python",
+ sys.executable,
"-m",
"markitdown",
"--keep-data-uris",
@@ -170,7 +175,7 @@ def test_output_to_file_with_data_uris(shared_tmp_dir, test_vector) -> None:
assert result.returncode == 0, f"CLI exited with error: {result.stderr}"
assert os.path.exists(output_file), f"Output file not created: {output_file}"
- with open(output_file, "r") as f:
+ with open(output_file, "r", encoding="utf-8") as f:
output_data = f.read()
for test_string in test_vector.must_include:
assert test_string in output_data
diff --git a/packages/markitdown/tests/test_cu_converter.py b/packages/markitdown/tests/test_cu_converter.py
index 20b517f764..487407bb78 100644
--- a/packages/markitdown/tests/test_cu_converter.py
+++ b/packages/markitdown/tests/test_cu_converter.py
@@ -932,11 +932,11 @@ def test_use_cu_reads_from_stdin(self, capsys):
enable_plugins=False,
cu_endpoint="https://fake-cu",
)
- markitdown_instance.convert_stream.assert_called_once_with(
- input_buffer,
- stream_info=None,
- keep_data_uris=False,
- )
+
+ assert markitdown_instance.convert_stream.call_count == 1
+ call_args, call_kwargs = markitdown_instance.convert_stream.call_args
+ assert call_args[0].read() == b"fake pdf"
+ assert call_kwargs == {"stream_info": None, "keep_data_uris": False}
assert capsys.readouterr().out == "converted\n"