From a86558522017669f7a26fbf095840f469d8a873b Mon Sep 17 00:00:00 2001 From: Vito Sansevero Date: Sat, 24 Oct 2026 07:57:07 -0700 Subject: [PATCH] feat(system): close the browser server's log files before its root goes The logs now live in the library's data folder, which for the browser test server is /user/__promptmanager; Windows could not remove the temp root while the server still held prompt_manager.log open. The API test's node folder is spelled in lower case because public paths are case-folded on Windows. --- tests/browser/server.py | 14 ++++++++++++++ tests/test_api_library_location.py | 5 +++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/tests/browser/server.py b/tests/browser/server.py index bdcaf465..85c54461 100644 --- a/tests/browser/server.py +++ b/tests/browser/server.py @@ -3,6 +3,7 @@ import argparse import asyncio import json +import logging import os import shutil import socket @@ -654,6 +655,18 @@ def exit_when_stdin_closes(loop: asyncio.AbstractEventLoop) -> threading.Thread: return thread +def close_owned_log_files() -> None: + """Close Prompt Manager's own log handlers before the temp root goes. + + The logs live in the library's data folder (#249 S6b), which for this + server is /user/__promptmanager; Windows cannot remove a file + this process still has open. + """ + for handler in logging.getLogger("prompt_manager").handlers[:]: + if getattr(handler, "_prompt_manager_owned", False) is True: + handler.close() + + def main(argv: list[str] | None = None) -> None: parser = argparse.ArgumentParser() parser.add_argument( @@ -678,6 +691,7 @@ def main(argv: list[str] | None = None) -> None: finally: # create_app works inside the root; Windows cannot remove a process's cwd. os.chdir(original_cwd) + close_owned_log_files() if __name__ == "__main__": diff --git a/tests/test_api_library_location.py b/tests/test_api_library_location.py index 68eae643..4a1a12ef 100644 --- a/tests/test_api_library_location.py +++ b/tests/test_api_library_location.py @@ -36,7 +36,8 @@ URL = "/prompt_manager/system/library" class LibraryAPITestCase(AdminAPITestCase): async def get_application(self): app = await super().get_application() - self.ext = os.path.join(str(self.comfy_dir), "custom_nodes", "PM") + # Lower case: a public path is case-folded on Windows (normcase). + self.ext = os.path.join(str(self.comfy_dir), "custom_nodes", "pm") os.makedirs(self.ext) self.user = os.path.join(str(self.comfy_dir), "user") os.makedirs(self.user) @@ -80,7 +81,7 @@ class TestLocationRoute(LibraryAPITestCase): self.assertEqual( body["location"], { - "path": "custom_nodes/PM/prompts.db", + "path": "custom_nodes/pm/prompts.db", "source": "node_folder", "movable": True, "keep": False,