From f2a75a0dcbd5ab40622f088f82d0955740e5176d Mon Sep 17 00:00:00 2001 From: Eesh Saxena Date: Fri, 14 Aug 2026 12:44:26 +0530 Subject: [PATCH] Raise PackageNotFoundError for a non-zip stream, not BadZipFile Opening a document from a path that is not a package raises PackageNotFoundError, but opening one from a *stream* that is not a zip fell through to ZipFile and raised a bare zipfile.BadZipFile instead. PhysPkgReader.__new__ passes streams straight to the zip reader ("pass it to Zip reader to sort out"), but the reader never sorted out the not-a-zip case. Catch BadZipFile in _ZipPkgReader and raise PackageNotFoundError, so a bad stream and a bad path fail the same way. Added a test. --- src/docx/opc/phys_pkg.py | 9 +++++++-- tests/opc/test_phys_pkg.py | 4 ++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/docx/opc/phys_pkg.py b/src/docx/opc/phys_pkg.py index 5ec32237c..ee31ac79d 100644 --- a/src/docx/opc/phys_pkg.py +++ b/src/docx/opc/phys_pkg.py @@ -1,7 +1,7 @@ """Provides a general interface to a `physical` OPC package, such as a zip file.""" import os -from zipfile import ZIP_DEFLATED, ZipFile, is_zipfile +from zipfile import ZIP_DEFLATED, BadZipFile, ZipFile, is_zipfile from docx.opc.exceptions import PackageNotFoundError from docx.opc.packuri import CONTENT_TYPES_URI @@ -73,7 +73,12 @@ class _ZipPkgReader(PhysPkgReader): def __init__(self, pkg_file): super(_ZipPkgReader, self).__init__() - self._zipf = ZipFile(pkg_file, "r") + try: + self._zipf = ZipFile(pkg_file, "r") + except BadZipFile: + raise PackageNotFoundError( + "Package not found or not a valid OPC package file" + ) def blob_for(self, pack_uri): """Return blob corresponding to `pack_uri`. diff --git a/tests/opc/test_phys_pkg.py b/tests/opc/test_phys_pkg.py index 6de0d868b..f02b10f78 100644 --- a/tests/opc/test_phys_pkg.py +++ b/tests/opc/test_phys_pkg.py @@ -68,6 +68,10 @@ def it_raises_when_pkg_path_is_not_a_package(self): with pytest.raises(PackageNotFoundError): PhysPkgReader("foobar") + def it_raises_when_pkg_stream_is_not_a_zip(self): + with pytest.raises(PackageNotFoundError): + PhysPkgReader(io.BytesIO(b"not a zip")) + class DescribeZipPkgReader: def it_is_used_by_PhysPkgReader_when_pkg_is_a_zip(self):