mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-05-23 16:35:59 +00:00
refactor: thread release config through lead path (#2612)
Co-authored-by: greatmengqi <chenmengqi.0376@bytedance.com>
This commit is contained in:
@@ -2,6 +2,7 @@ import asyncio
|
||||
import stat
|
||||
from io import BytesIO
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
from _router_auth_helpers import call_unwrapped
|
||||
@@ -26,7 +27,7 @@ def test_upload_files_writes_thread_storage_and_skips_local_sandbox_sync(tmp_pat
|
||||
patch.object(uploads, "get_sandbox_provider", return_value=provider),
|
||||
):
|
||||
file = UploadFile(filename="notes.txt", file=BytesIO(b"hello uploads"))
|
||||
result = asyncio.run(call_unwrapped(uploads.upload_files, "thread-local", request=MagicMock(), files=[file]))
|
||||
result = asyncio.run(call_unwrapped(uploads.upload_files, "thread-local", request=MagicMock(), files=[file], config=SimpleNamespace()))
|
||||
|
||||
assert result.success is True
|
||||
assert len(result.files) == 1
|
||||
@@ -49,7 +50,7 @@ def test_upload_files_skips_acquire_when_thread_data_is_mounted(tmp_path):
|
||||
patch.object(uploads, "get_sandbox_provider", return_value=provider),
|
||||
):
|
||||
file = UploadFile(filename="notes.txt", file=BytesIO(b"hello uploads"))
|
||||
result = asyncio.run(call_unwrapped(uploads.upload_files, "thread-mounted", request=MagicMock(), files=[file]))
|
||||
result = asyncio.run(call_unwrapped(uploads.upload_files, "thread-mounted", request=MagicMock(), files=[file], config=SimpleNamespace()))
|
||||
|
||||
assert result.success is True
|
||||
assert (thread_uploads_dir / "notes.txt").read_bytes() == b"hello uploads"
|
||||
@@ -75,7 +76,7 @@ def test_upload_files_does_not_auto_convert_documents_by_default(tmp_path):
|
||||
patch.object(uploads, "convert_file_to_markdown", AsyncMock()) as convert_mock,
|
||||
):
|
||||
file = UploadFile(filename="report.pdf", file=BytesIO(b"pdf-bytes"))
|
||||
result = asyncio.run(call_unwrapped(uploads.upload_files, "thread-local", request=MagicMock(), files=[file]))
|
||||
result = asyncio.run(call_unwrapped(uploads.upload_files, "thread-local", request=MagicMock(), files=[file], config=SimpleNamespace()))
|
||||
|
||||
assert result.success is True
|
||||
assert len(result.files) == 1
|
||||
@@ -108,7 +109,7 @@ def test_upload_files_syncs_non_local_sandbox_and_marks_markdown_file(tmp_path):
|
||||
patch.object(uploads, "convert_file_to_markdown", AsyncMock(side_effect=fake_convert)),
|
||||
):
|
||||
file = UploadFile(filename="report.pdf", file=BytesIO(b"pdf-bytes"))
|
||||
result = asyncio.run(call_unwrapped(uploads.upload_files, "thread-aio", request=MagicMock(), files=[file]))
|
||||
result = asyncio.run(call_unwrapped(uploads.upload_files, "thread-aio", request=MagicMock(), files=[file], config=SimpleNamespace()))
|
||||
|
||||
assert result.success is True
|
||||
assert len(result.files) == 1
|
||||
@@ -147,7 +148,7 @@ def test_upload_files_makes_non_local_files_sandbox_writable(tmp_path):
|
||||
patch.object(uploads, "_make_file_sandbox_writable") as make_writable,
|
||||
):
|
||||
file = UploadFile(filename="report.pdf", file=BytesIO(b"pdf-bytes"))
|
||||
result = asyncio.run(call_unwrapped(uploads.upload_files, "thread-aio", request=MagicMock(), files=[file]))
|
||||
result = asyncio.run(call_unwrapped(uploads.upload_files, "thread-aio", request=MagicMock(), files=[file], config=SimpleNamespace()))
|
||||
|
||||
assert result.success is True
|
||||
make_writable.assert_any_call(thread_uploads_dir / "report.pdf")
|
||||
@@ -171,7 +172,7 @@ def test_upload_files_does_not_adjust_permissions_for_local_sandbox(tmp_path):
|
||||
patch.object(uploads, "_make_file_sandbox_writable") as make_writable,
|
||||
):
|
||||
file = UploadFile(filename="notes.txt", file=BytesIO(b"hello uploads"))
|
||||
result = asyncio.run(call_unwrapped(uploads.upload_files, "thread-local", request=MagicMock(), files=[file]))
|
||||
result = asyncio.run(call_unwrapped(uploads.upload_files, "thread-local", request=MagicMock(), files=[file], config=SimpleNamespace()))
|
||||
|
||||
assert result.success is True
|
||||
make_writable.assert_not_called()
|
||||
@@ -222,13 +223,13 @@ def test_upload_files_rejects_dotdot_and_dot_filenames(tmp_path):
|
||||
# These filenames must be rejected outright
|
||||
for bad_name in ["..", "."]:
|
||||
file = UploadFile(filename=bad_name, file=BytesIO(b"data"))
|
||||
result = asyncio.run(call_unwrapped(uploads.upload_files, "thread-local", request=MagicMock(), files=[file]))
|
||||
result = asyncio.run(call_unwrapped(uploads.upload_files, "thread-local", request=MagicMock(), files=[file], config=SimpleNamespace()))
|
||||
assert result.success is True
|
||||
assert result.files == [], f"Expected no files for unsafe filename {bad_name!r}"
|
||||
|
||||
# Path-traversal prefixes are stripped to the basename and accepted safely
|
||||
file = UploadFile(filename="../etc/passwd", file=BytesIO(b"data"))
|
||||
result = asyncio.run(call_unwrapped(uploads.upload_files, "thread-local", request=MagicMock(), files=[file]))
|
||||
result = asyncio.run(call_unwrapped(uploads.upload_files, "thread-local", request=MagicMock(), files=[file], config=SimpleNamespace()))
|
||||
assert result.success is True
|
||||
assert len(result.files) == 1
|
||||
assert result.files[0]["filename"] == "passwd"
|
||||
@@ -252,16 +253,20 @@ def test_delete_uploaded_file_removes_generated_markdown_companion(tmp_path):
|
||||
|
||||
|
||||
def test_auto_convert_documents_enabled_defaults_to_false_on_config_errors():
|
||||
with patch.object(uploads, "get_app_config", side_effect=RuntimeError("boom")):
|
||||
assert uploads._auto_convert_documents_enabled() is False
|
||||
class BrokenConfig:
|
||||
def __getattribute__(self, name):
|
||||
if name == "uploads":
|
||||
raise RuntimeError("boom")
|
||||
return super().__getattribute__(name)
|
||||
|
||||
assert uploads._auto_convert_documents_enabled(BrokenConfig()) is False
|
||||
|
||||
|
||||
def test_auto_convert_documents_enabled_reads_dict_backed_uploads_config():
|
||||
cfg = MagicMock()
|
||||
cfg.uploads = {"auto_convert_documents": True}
|
||||
|
||||
with patch.object(uploads, "get_app_config", return_value=cfg):
|
||||
assert uploads._auto_convert_documents_enabled() is True
|
||||
assert uploads._auto_convert_documents_enabled(cfg) is True
|
||||
|
||||
|
||||
def test_auto_convert_documents_enabled_accepts_boolean_and_string_truthy_values():
|
||||
@@ -277,11 +282,7 @@ def test_auto_convert_documents_enabled_accepts_boolean_and_string_truthy_values
|
||||
string_false_cfg = MagicMock()
|
||||
string_false_cfg.uploads = MagicMock(auto_convert_documents="false")
|
||||
|
||||
with patch.object(uploads, "get_app_config", return_value=false_cfg):
|
||||
assert uploads._auto_convert_documents_enabled() is False
|
||||
with patch.object(uploads, "get_app_config", return_value=true_cfg):
|
||||
assert uploads._auto_convert_documents_enabled() is True
|
||||
with patch.object(uploads, "get_app_config", return_value=string_true_cfg):
|
||||
assert uploads._auto_convert_documents_enabled() is True
|
||||
with patch.object(uploads, "get_app_config", return_value=string_false_cfg):
|
||||
assert uploads._auto_convert_documents_enabled() is False
|
||||
assert uploads._auto_convert_documents_enabled(false_cfg) is False
|
||||
assert uploads._auto_convert_documents_enabled(true_cfg) is True
|
||||
assert uploads._auto_convert_documents_enabled(string_true_cfg) is True
|
||||
assert uploads._auto_convert_documents_enabled(string_false_cfg) is False
|
||||
|
||||
Reference in New Issue
Block a user