From 964c582c9e302f7d3cdf5dfb03ad4b5b231974de Mon Sep 17 00:00:00 2001 From: Shubham Padkonde Date: Fri, 2 Oct 2026 15:57:00 +0530 Subject: [PATCH] fix: decode escaped file output URI paths --- spectator/writer/file_writer.py | 4 ++-- tests/writer/test_file_writer.py | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/spectator/writer/file_writer.py b/spectator/writer/file_writer.py index 515925d..9d9ba4b 100644 --- a/spectator/writer/file_writer.py +++ b/spectator/writer/file_writer.py @@ -1,5 +1,5 @@ import sys -from urllib.parse import urlparse +from urllib.parse import unquote, urlparse from spectator.config import Config from spectator.writer import Writer @@ -20,7 +20,7 @@ def __init__(self, config: Config) -> None: self._file = sys.stdout self._owns_file = False else: - self._file = open(urlparse(config.location).path, "a", encoding="utf-8") + self._file = open(unquote(urlparse(config.location).path), "a", encoding="utf-8") self._owns_file = True def write(self, line: str) -> None: diff --git a/tests/writer/test_file_writer.py b/tests/writer/test_file_writer.py index 32dc494..268a4af 100644 --- a/tests/writer/test_file_writer.py +++ b/tests/writer/test_file_writer.py @@ -4,12 +4,22 @@ from contextlib import closing, redirect_stderr, redirect_stdout from tempfile import TemporaryDirectory from unittest.mock import patch +from urllib.parse import quote from spectator import Config, FileWriter class FileWriterTest(unittest.TestCase): + def test_file_writer_escaped_path(self): + with TemporaryDirectory() as tmpdir: + tmp_file = os.path.join(tmpdir, "metrics space #%25.txt") + with closing(FileWriter(Config(f"file://{quote(tmp_file)}"))) as writer: + writer.write("foo") + with open(tmp_file, encoding="utf-8") as source: + self.assertEqual("foo\n", source.read()) + self.assertEqual(["metrics space #%25.txt"], os.listdir(tmpdir)) + def test_file_writer_custom(self): with TemporaryDirectory() as tmpdir: tmp_file = os.path.join(tmpdir, "file-writer.txt")