docx/malformed-non-zip

A plain-UTF-8 text file with a .docx extension. The library must raise a typed opc-level exception (PackageNotFoundError or subclass — python-docx uses NotADocxError); a bare zipfile.BadZipFile leaks implementation detail and pins users to the library's zip backend choice.

Library verdicts: python-docx: — docxjs: —

Metadata

Feature iddocx/malformed-non-zip
Formatdocx
Categorymalformed-recovery
Spececma-376-5-part-2 § 10.1.1 Package

XPath assertions

No XPath assertions declared.

Render assertions

No render assertions declared.

Generator source

scripts/gen_malformed_non_zip_docx.py

#!/usr/bin/env python3
"""Generate ``fixtures/docx/malformed-non-zip.docx``.

A plain-UTF-8 text file with a ``.docx`` extension. The library must
raise a typed opc-level exception — python-docx uses
:class:`docx.opc.exceptions.NotADocxError`, a subclass of
``PackageNotFoundError``. A bare :class:`zipfile.BadZipFile` is NOT
sufficient: that leaks an implementation detail and pins users to
python-docx's choice of zip backend.
"""

from __future__ import annotations

import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent))
from _malformed_common import write_plain_bytes

_REPO_ROOT = Path(__file__).resolve().parent.parent
_OUT = _REPO_ROOT / "fixtures" / "docx" / "malformed-non-zip.docx"

_PAYLOAD = (
    b"This file has a .docx extension but is plain UTF-8 text, not a "
    b"ZIP archive. A conforming reader must reject it with a typed "
    b"opc-level exception, not a bare zipfile.BadZipFile.\n"
) * 4


def main() -> int:
    _OUT.parent.mkdir(parents=True, exist_ok=True)
    write_plain_bytes(_OUT, _PAYLOAD)
    print(_OUT)
    return 0


if __name__ == "__main__":
    raise SystemExit(main())

Manifest (expanded)

{
  "id": "docx/malformed-non-zip",
  "title": "Malformed input: file is not a ZIP archive",
  "format": "docx",
  "category": "malformed-recovery",
  "summary": "A plain-UTF-8 text file with a .docx extension. The library must raise a typed opc-level exception (PackageNotFoundError or subclass — python-docx uses NotADocxError); a bare zipfile.BadZipFile leaks implementation detail and pins users to the library's zip backend choice.",
  "roles": [
    "authoring"
  ],
  "spec": {
    "source": "ecma-376-5-part-2",
    "clause": "10.1.1",
    "element": "Package",
    "notes": "An OPC package is a ZIP (ECMA-376 part 2 clause 10.1.1). Not-a-zip input is the most basic 'reject gracefully' case."
  },
  "fixtures": {
    "machine": "docx/malformed-non-zip"
  },
  "generator": {
    "python": "scripts/gen_malformed_non_zip_docx.py"
  },
  "behavior_assertions": [
    {
      "id": "raises-typed-exception",
      "kind": "library_raises",
      "library": "python-docx",
      "method": "docx.Document",
      "args": [
        "{fixture_path}"
      ],
      "expected_exception": [
        "PackageNotFoundError",
        "NotADocxError",
        "OpcError"
      ],
      "forbidden_exception": "BadZipFile",
      "description": "Must raise a typed opc exception — NOT a bare zipfile.BadZipFile. python-docx raises NotADocxError today (a subclass of PackageNotFoundError)."
    }
  ]
}

Fixture

Download malformed-non-zip.docx (0.7 KB)

Reference preview

No rendered reference is available for this case.

Spec notes

An OPC package is a ZIP (ECMA-376 part 2 clause 10.1.1). Not-a-zip input is the most basic 'reject gracefully' case.