fix(file-manager): treat explorer exit code 1 as success on Windows
This commit is contained in:
@@ -82,7 +82,7 @@ def _find_launcher(*names: str) -> tuple[str, str]:
|
||||
)
|
||||
|
||||
|
||||
def _launch(command: list[str]) -> None:
|
||||
def _launch(command: list[str], check_exit_code: bool = True) -> None:
|
||||
kwargs: Dict[str, Any] = {
|
||||
"shell": False,
|
||||
"stdin": subprocess.DEVNULL,
|
||||
@@ -97,6 +97,12 @@ def _launch(command: list[str]) -> None:
|
||||
except (OSError, ValueError) as exc:
|
||||
raise FileManagerError(f"Could not start the system file manager: {exc}") from exc
|
||||
|
||||
# Explorer commonly delegates the request to an existing shell process and
|
||||
# exits with code 1 even though the folder opened successfully. A successful
|
||||
# process creation is therefore the only reliable Windows signal.
|
||||
if not check_exit_code:
|
||||
return
|
||||
|
||||
# Most launcher commands exit immediately after handing the request to the
|
||||
# desktop. Catch a fast failure without waiting for a long-running manager.
|
||||
try:
|
||||
@@ -154,7 +160,7 @@ def open_in_file_manager(path_value: Any, system: str | None = None) -> Dict[str
|
||||
f"Opening folders is not supported on {display_name}."
|
||||
)
|
||||
|
||||
_launch(command)
|
||||
_launch(command, check_exit_code=platform_name != "windows")
|
||||
return {
|
||||
"platform": platform_name,
|
||||
"launcher": launcher,
|
||||
|
||||
@@ -87,6 +87,21 @@ class FileManagerTests(unittest.TestCase):
|
||||
self.assertEqual(command, [r"C:\Windows\explorer.exe", os.path.realpath(self.directory)])
|
||||
self.assertFalse(result["selected"])
|
||||
|
||||
@patch("core.file_manager.subprocess.Popen")
|
||||
@patch("core.file_manager.shutil.which")
|
||||
def test_windows_does_not_treat_explorer_exit_code_one_as_failure(
|
||||
self, mock_which, mock_popen
|
||||
):
|
||||
mock_which.return_value = r"C:\Windows\explorer.exe"
|
||||
process = MagicMock()
|
||||
process.wait.return_value = 1
|
||||
mock_popen.return_value = process
|
||||
|
||||
result = open_in_file_manager(self.file_path, system="Windows")
|
||||
|
||||
process.wait.assert_not_called()
|
||||
self.assertEqual(result["launcher"], "explorer")
|
||||
|
||||
@patch("core.file_manager.subprocess.Popen")
|
||||
@patch("core.file_manager.shutil.which", return_value="/usr/bin/open")
|
||||
def test_macos_reveals_a_file(self, _mock_which, mock_popen):
|
||||
|
||||
Reference in New Issue
Block a user