SVG-Compress hinzugefügt via svg-polish python module

This commit is contained in:
2026-06-10 10:17:36 +02:00
parent b880c4f03a
commit 0cec37eecd
4 changed files with 310 additions and 75 deletions
+104 -27
View File
@@ -273,57 +273,134 @@ class TestPptxImageCompress(unittest.TestCase):
self.fail("Output should not be None")
self.assertEqual(out.name, "image1.png")
self.assertEqual(out.stat().st_size, 80)
def test_compress_svg_with_svgo_returns_none_when_binary_missing(self):
def test_compress_with_caesium_ignores_svg(self):
with tempfile.TemporaryDirectory() as td:
root = Path(td)
svg = root / "vector.svg"
svg.write_text("<svg></svg>", encoding="utf-8")
out_dir = root / "out"
with mock.patch("pptx_image_compress.get_svgo_executable_path", return_value=root / "bin" / "svgo.cmd"):
out = pic.compress_svg_with_svgo(svg, out_dir)
with mock.patch("pptx_image_compress.which") as mocked_which:
out = pic.compress_with_caesium(
original=svg,
out_dir=out_dir,
caesium_threads=1,
quality=90,
min_savings="2%",
)
self.assertIsNone(out)
mocked_which.assert_not_called()
def test_optimize_svg_content_with_module_uses_optimize_path_with_options(self):
with tempfile.TemporaryDirectory() as td:
root = Path(td)
svg = root / "vector.svg"
svg.write_text("<svg></svg>", encoding="utf-8")
captured_options = {}
class FakeOptions:
def __init__(self, **kwargs):
captured_options.update(kwargs)
fake_module = mock.Mock()
fake_module.OptimizeOptions = FakeOptions
fake_module.optimize_path = mock.Mock(return_value="<svg/>")
fake_module.optimize_file = None
fake_module.optimize = None
fake_module.optimize_string = None
fake_module.polish = None
result = pic.optimize_svg_content_with_module(fake_module, svg)
self.assertEqual(result, "<svg/>")
self.assertEqual(captured_options["digits"], 2)
self.assertEqual(captured_options["indent_type"], "none")
self.assertEqual(captured_options["newlines"], False)
self.assertEqual(captured_options["strip_xml_prolog"], True)
self.assertEqual(captured_options["strip_comments"], True)
self.assertEqual(captured_options["strip_ids"], True)
self.assertEqual(captured_options["renderer_workaround"], False)
self.assertEqual(fake_module.optimize_path.call_count, 1)
def test_build_svg_polish_options_balanced_profile(self):
captured_options = {}
class FakeOptions:
def __init__(self, **kwargs):
captured_options.update(kwargs)
fake_module = mock.Mock()
fake_module.OptimizeOptions = FakeOptions
options = pic.build_svg_polish_options(fake_module, pic.SVG_PROFILE_BALANCED)
self.assertIsNotNone(options)
self.assertEqual(captured_options["digits"], 3)
self.assertEqual(captured_options["group_collapse"], True)
self.assertNotIn("strip_ids", captured_options)
def test_compress_svg_with_svg_polish_returns_none_when_module_missing(self):
with tempfile.TemporaryDirectory() as td:
root = Path(td)
svg = root / "vector.svg"
svg.write_text("<svg></svg>", encoding="utf-8")
out_dir = root / "out"
with mock.patch("pptx_image_compress.import_svg_polish_module", return_value=None):
out = pic.compress_svg_with_svg_polish(svg, out_dir)
self.assertEqual(out, None)
def test_compress_svg_with_svgo_uses_local_binary(self):
def test_compress_svg_with_svg_polish_uses_python_module(self):
with tempfile.TemporaryDirectory() as td:
root = Path(td)
svg = root / "vector.svg"
svg.write_text("<svg></svg>", encoding="utf-8")
svg.write_text("<svg> <g></g> </svg>", encoding="utf-8")
out_dir = root / "out"
fake_exe = root / "bin" / "svgo.cmd"
fake_exe.parent.mkdir(parents=True, exist_ok=True)
fake_exe.write_bytes(b"exe")
fake_module = mock.Mock()
fake_module.optimize = mock.Mock(return_value="<svg><g/></svg>")
fake_module.optimize_path = None
fake_module.optimize_file = None
fake_module.optimize_string = None
fake_module.polish = None
fake_module.OptimizeOptions = None
def fake_run(cmd, capture_output, text):
self.assertEqual(cmd[0], str(fake_exe))
self.assertEqual(cmd[1], str(svg))
self.assertEqual(cmd[2], "-o")
self.assertEqual(cmd[3], str(out_dir / "vector.svg"))
out_dir.mkdir(parents=True, exist_ok=True)
(out_dir / "vector.svg").write_text("<svg/>", encoding="utf-8")
return mock.Mock(returncode=0, stderr="")
with mock.patch("pptx_image_compress.get_svgo_executable_path", return_value=fake_exe):
with mock.patch("pptx_image_compress.subprocess.run", side_effect=fake_run):
out = pic.compress_svg_with_svgo(svg, out_dir)
with mock.patch("pptx_image_compress.import_svg_polish_module", return_value=fake_module):
out = pic.compress_svg_with_svg_polish(svg, out_dir)
self.assertEqual(out, out_dir / "vector.svg")
self.assertTrue((out_dir / "vector.svg").exists())
self.assertEqual((out_dir / "vector.svg").read_text(encoding="utf-8"), "<svg><g/></svg>")
fake_module.optimize.assert_called_once_with("<svg> <g></g> </svg>")
def test_compress_image_with_routing_uses_svg_backend(self):
def test_compress_svg_with_svg_polish_uses_polish_fallback(self):
with tempfile.TemporaryDirectory() as td:
root = Path(td)
svg = root / "vector.svg"
svg.write_text("<svg> <path/></svg>", encoding="utf-8")
out_dir = root / "out"
fake_module = mock.Mock()
fake_module.optimize = None
fake_module.polish = mock.Mock(return_value="<svg><path/></svg>")
with mock.patch("pptx_image_compress.import_svg_polish_module", return_value=fake_module):
out = pic.compress_svg_with_svg_polish(svg, out_dir)
self.assertEqual(out, out_dir / "vector.svg")
fake_module.polish.assert_called_once_with("<svg> <path/></svg>")
def test_compress_image_with_routing_does_not_fallback_to_raster_for_svg(self):
with tempfile.TemporaryDirectory() as td:
root = Path(td)
original = root / "vector.svg"
original.write_text("<svg></svg>", encoding="utf-8")
out_dir = root / "out"
out_dir.mkdir(parents=True, exist_ok=True)
vector_out = out_dir / "vector.svg"
vector_out.write_text("<svg/>", encoding="utf-8")
def fake_compressor(original_path: Path, out_subdir: Path, caesium_threads: int | None, quality: int, min_savings: str):
raise AssertionError("Raster compressor should not be called for svg")
raise AssertionError("Raster compressor must not run for svg")
with mock.patch("pptx_image_compress.compress_vector_image", return_value=vector_out):
with mock.patch("pptx_image_compress.compress_vector_image", return_value=None):
out = pic.compress_image_with_routing(
compressor=fake_compressor,
original=original,
@@ -333,7 +410,7 @@ class TestPptxImageCompress(unittest.TestCase):
min_savings="2%",
)
self.assertEqual(out, vector_out)
self.assertIsNone(out)
if __name__ == "__main__":