diff --git a/src/docx/package.py b/src/docx/package.py index 7ea47e6e1..9132c4339 100644 --- a/src/docx/package.py +++ b/src/docx/package.py @@ -88,6 +88,10 @@ def _get_by_sha1(self, sha1: str) -> ImagePart | None: """Return the image part in this collection having a SHA1 hash matching `sha1`, or |None| if not found.""" for image_part in self._image_parts: + # ---skip parts loaded for an unsupported image type (e.g. SVG), which + # ---come through the image relationships as a plain Part and have no sha1 + if not hasattr(image_part, "sha1"): + continue if image_part.sha1 == sha1: return image_part return None diff --git a/tests/test_package.py b/tests/test_package.py index ac9839828..6eef18bf7 100644 --- a/tests/test_package.py +++ b/tests/test_package.py @@ -8,6 +8,7 @@ from docx.image.image import Image from docx.opc.packuri import PackURI +from docx.opc.part import Part from docx.package import ImageParts, Package from docx.parts.image import ImagePart @@ -102,6 +103,18 @@ def but_it_adds_a_new_image_part_when_match_fails( _add_image_part_.assert_called_once_with(image_parts, image_) assert image_part is image_part_ + def it_skips_parts_without_a_sha1_when_matching(self, request: FixtureRequest): + # ---an unsupported image type (e.g. SVG) is reached through the image + # ---relationships as a plain Part with no sha1, and must be skipped + # ---rather than raising AttributeError--- + non_image_part = instance_mock(request, Part) + image_part = instance_mock(request, ImagePart, sha1="f005ba11") + image_parts = ImageParts() + image_parts.append(non_image_part) + image_parts.append(image_part) + + assert image_parts._get_by_sha1("f005ba11") is image_part + @pytest.mark.parametrize( ("existing_partname_numbers", "expected_partname_number"), [