Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ Version 8.3.2

Released 2026-04-02

- Quote the ``/select,`` argument passed to Explorer in ``launch(locate=True)``
on Windows so that paths containing spaces are handled correctly.
:issue:`2994`
- Fix handling of ``flag_value`` when ``is_flag=False`` to allow such options to be
used without an explicit value. :issue:`3084` :pr:`3152`
- Hide ``Sentinel.UNSET`` values as ``None`` when using ``lookup_default()``.
Expand Down
4 changes: 2 additions & 2 deletions src/click/_termui_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -698,8 +698,8 @@ def _unquote_file(url: str) -> str:
null.close()
elif WIN:
if locate:
url = _unquote_file(url)
args = ["explorer", f"/select,{url}"]
url = _unquote_file(url).replace('"', '""')
args = ["explorer", f'/select,"{url}"']
else:
args = ["start"]
if wait:
Expand Down
31 changes: 31 additions & 0 deletions tests/test_termui.py
Original file line number Diff line number Diff line change
Expand Up @@ -710,3 +710,34 @@ def cli(flag):
assert result.output == expected_output
assert not result.stderr
assert result.exit_code == 0 if expected not in (REPEAT, INVALID) else 1


@pytest.mark.skipif(not WIN, reason="Windows-only")
def test_open_url_locate_quotes_path_with_spaces():
"""launch(locate=True) must quote the path so Explorer handles spaces."""
from unittest.mock import patch

path = r"C:\path with spaces\file.txt"

with patch("subprocess.call", return_value=0) as mock_call:
click._termui_impl.open_url(path, locate=True)

args = mock_call.call_args[0][0]
# The /select, argument must wrap the path in double quotes
assert args[0] == "explorer"
assert args[1] == f'/select,"{path}"'


@pytest.mark.skipif(not WIN, reason="Windows-only")
def test_open_url_locate_escapes_quotes_in_path():
"""Embedded double-quotes in path are escaped as \"\"."""
from unittest.mock import patch

path = 'C:\\path\\with "quotes"\\file.txt'

with patch("subprocess.call", return_value=0) as mock_call:
click._termui_impl.open_url(path, locate=True)

args = mock_call.call_args[0][0]
escaped = path.replace('"', '""')
assert args[1] == f'/select,"{escaped}"'