Describe the bug
When clicking file links generated by RichHandler in VS Code terminal on Windows, the path does not open. The issue is caused by two problems:
- Links use
file:// (two slashes) instead of the required file:/// (three slashes) for absolute Windows paths.
- Paths contain backslashes
\ instead of forward slashes / in the URI.
Sample code:
import logging
from rich.logging import RichHandler
logging.basicConfig(
level='NOTSET',
format='%(message)s',
datefmt='[%X]',
handlers=[
RichHandler(
show_path=True,
enable_link_path=True,
rich_tracebacks=True,
)
],
)
logger = logging.getLogger(__name__)
logger.info('some message')
Run the script in vscode terminal on Windows. Click on the filename in the generated output, you'll get:
[Window Title]
Visual Studio Code
[Main Instruction]
Path does not exist
[Content]
The path '\' does not exist on this computer.
[OK]
Platform
Click to expand
Windows
vscode's terminal, using cmd.exe
<!-- Failed to upload "image.png" -->
>python -m rich.diagnose
╭───────────────────────── <class 'rich.console.Console'> ─────────────────────────╮
│ A high level console interface. │
│ │
│ ╭──────────────────────────────────────────────────────────────────────────────╮ │
│ │ <console width=222 ColorSystem.TRUECOLOR> │ │
│ ╰──────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ color_system = 'truecolor' │
│ encoding = 'utf-8' │
│ file = <_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'> │
│ height = 14 │
│ is_alt_screen = False │
│ is_dumb_terminal = False │
│ is_interactive = True │
│ is_jupyter = False │
│ is_terminal = True │
│ legacy_windows = False │
│ no_color = False │
│ options = ConsoleOptions( │
│ size=ConsoleDimensions(width=222, height=14), │
│ legacy_windows=False, │
│ min_width=1, │
│ max_width=222, │
│ is_terminal=True, │
│ encoding='utf-8', │
│ max_height=14, │
│ justify=None, │
│ overflow=None, │
│ no_wrap=False, │
│ highlight=None, │
│ markup=None, │
│ height=None │
│ ) │
│ quiet = False │
│ record = False │
│ safe_box = True │
│ size = ConsoleDimensions(width=222, height=14) │
│ soft_wrap = False │
│ stderr = False │
│ style = None │
│ tab_size = 8 │
│ width = 222 │
╰──────────────────────────────────────────────────────────────────────────────────╯
╭── <class 'rich._windows.WindowsConsoleFeatures'> ───╮
│ Windows features available. │
│ │
│ ╭─────────────────────────────────────────────────╮ │
│ │ WindowsConsoleFeatures(vt=True, truecolor=True) │ │
│ ╰─────────────────────────────────────────────────╯ │
│ │
│ truecolor = True │
│ vt = True │
╰─────────────────────────────────────────────────────╯
╭────── Environment Variables ───────╮
│ { │
│ 'CLICOLOR': None, │
│ 'COLORTERM': 'truecolor', │
│ 'COLUMNS': None, │
│ 'JPY_PARENT_PID': None, │
│ 'JUPYTER_COLUMNS': None, │
│ 'JUPYTER_LINES': None, │
│ 'LINES': None, │
│ 'NO_COLOR': None, │
│ 'TERM_PROGRAM': 'vscode', │
│ 'TERM': None, │
│ 'TTY_COMPATIBLE': None, │
│ 'TTY_INTERACTIVE': None, │
│ 'VSCODE_VERBOSE_LOGGING': None │
│ } │
╰────────────────────────────────────╯
platform="Windows"
>uv pip show rich
Name: rich
Version: 15.0.0
Location: D:\...\.venv\Lib\site-packages
Requires: markdown-it-py, pygments
Required-by:
If you're using Rich in a Jupyter Notebook, run the following snippet in a cell
and paste the output in your bug report.
from rich.diagnose import report
report()
I've fixed this issue by modifying rich._log_render.LogRender.__call__.
|
def __call__( |
|
self, |
|
console: "Console", |
|
renderables: Iterable["ConsoleRenderable"], |
|
log_time: Optional[datetime] = None, |
|
time_format: Optional[Union[str, FormatTimeCallable]] = None, |
|
level: TextType = "", |
|
path: Optional[str] = None, |
|
line_no: Optional[int] = None, |
|
link_path: Optional[str] = None, |
|
) -> "Table": |
|
from .containers import Renderables |
|
from .table import Table |
|
|
|
output = Table.grid(padding=(0, 1)) |
|
output.expand = True |
|
if self.show_time: |
|
output.add_column(style="log.time") |
|
if self.show_level: |
|
output.add_column(style="log.level", width=self.level_width) |
|
output.add_column(ratio=1, style="log.message", overflow="fold") |
|
if self.show_path and path: |
|
output.add_column(style="log.path") |
|
row: List["RenderableType"] = [] |
|
if self.show_time: |
|
log_time = log_time or console.get_datetime() |
|
time_format = time_format or self.time_format |
|
if callable(time_format): |
|
log_time_display = time_format(log_time) |
|
else: |
|
log_time_display = Text(log_time.strftime(time_format)) |
|
if log_time_display == self._last_time and self.omit_repeated_times: |
|
row.append(Text(" " * len(log_time_display))) |
|
else: |
|
row.append(log_time_display) |
|
self._last_time = log_time_display |
|
if self.show_level: |
|
row.append(level) |
|
|
The changes I made were two:
- replace both
file://s with file:/// in style f-strings.
- add
link_path = link_path.replace('\\', '/') at the beginning of the function definition.
Why this works:
- According to the URI specification (RFC 8089 I believe) , the file URI scheme has the format:
file://<host>/<path>
<host> represents the machine where the file resides.
For local files on the same machine, the <host> must be empty (or localhost).
When the host is empty, the URI becomes file:/// (three slashes), followed by the absolute path.
Most Windows applications (including VS Code, File Explorer, and Windows Terminal) follow the RFC and require the triple-slash format for local file links. The double-slash format is either rejected or interpreted incorrectly (e.g., trying to open a network share named C:).
- The URI standard requires that path separators be forward slashes (/), even on Windows. Backslashes are not allowed in URIs because they have special meaning as escape characters.
So the log links generated by the following sample will work as expected:
import logging
from rich._log_render import LogRender
from rich.logging import RichHandler
# Store original method
_original_log_render_call = LogRender.__call__
def _patched_log_render_call(
self,
console,
renderables,
log_time=None,
time_format=None,
level='',
path=None,
line_no=None,
link_path=None,
):
"""Patched version that fixes Windows file links."""
# Fix Windows paths for the link
if link_path:
# Convert backslashes to forward slashes
link_path = link_path.replace('\\', '/')
# Add the third slash (will be used in the f-string below)
# The original code does: f"link file://{link_path}"
# We need: f"link file:///{link_path}"
# So we prepend a slash to link_path
link_path = '/' + link_path
# Call original with modified link_path
return _original_log_render_call(
self,
console,
renderables,
log_time,
time_format,
level,
path,
line_no,
link_path,
)
# Apply the patch BEFORE creating handlers
LogRender.__call__ = _patched_log_render_call
# Now configure logging normally
logging.basicConfig(
level='NOTSET',
format='%(message)s',
datefmt='[%X]',
handlers=[
RichHandler(
show_path=True,
enable_link_path=True,
rich_tracebacks=True,
)
],
)
logger = logging.getLogger(__name__)
logger.info('Test message with clickable link')
Describe the bug
When clicking file links generated by
RichHandlerin VS Code terminal on Windows, the path does not open. The issue is caused by two problems:file://(two slashes) instead of the requiredfile:///(three slashes) for absolute Windows paths.\instead of forward slashes/in the URI.Sample code:
Run the script in vscode terminal on Windows. Click on the filename in the generated output, you'll get:
Platform
Click to expand
Windows
vscode's terminal, using cmd.exe
If you're using Rich in a Jupyter Notebook, run the following snippet in a cell
and paste the output in your bug report.
I've fixed this issue by modifying
rich._log_render.LogRender.__call__.rich/rich/_log_render.py
Lines 32 to 70 in 46cebbb
The changes I made were two:
file://s withfile:///in style f-strings.link_path = link_path.replace('\\', '/')at the beginning of the function definition.Why this works:
file://<host>/<path><host>represents the machine where the file resides.For local files on the same machine, the
<host>must be empty (or localhost).When the host is empty, the URI becomes
file:///(three slashes), followed by the absolute path.Most Windows applications (including VS Code, File Explorer, and Windows Terminal) follow the RFC and require the triple-slash format for local file links. The double-slash format is either rejected or interpreted incorrectly (e.g., trying to open a network share named C:).
So the log links generated by the following sample will work as expected: