diff --git a/src/docx/__init__.py b/src/docx/__init__.py index fd06c84d2..3d5f34a15 100644 --- a/src/docx/__init__.py +++ b/src/docx/__init__.py @@ -44,6 +44,7 @@ def part_class_selector(content_type: str, reltype: str) -> Type[Part] | None: PartFactory.part_type_for[CT.OPC_CORE_PROPERTIES] = CorePropertiesPart PartFactory.part_type_for[CT.WML_COMMENTS] = CommentsPart PartFactory.part_type_for[CT.WML_DOCUMENT_MAIN] = DocumentPart +PartFactory.part_type_for[CT.WML_TEMPLATE_MAIN] = DocumentPart PartFactory.part_type_for[CT.WML_FOOTER] = FooterPart PartFactory.part_type_for[CT.WML_HEADER] = HeaderPart PartFactory.part_type_for[CT.WML_NUMBERING] = NumberingPart diff --git a/src/docx/api.py b/src/docx/api.py index aea876458..276bc58c0 100644 --- a/src/docx/api.py +++ b/src/docx/api.py @@ -25,7 +25,7 @@ def Document(docx: str | IO[bytes] | None = None) -> DocumentObject: """ docx = _default_docx_path() if docx is None else docx document_part = cast("DocumentPart", Package.open(docx).main_document_part) - if document_part.content_type != CT.WML_DOCUMENT_MAIN: + if document_part.content_type not in (CT.WML_DOCUMENT_MAIN, CT.WML_TEMPLATE_MAIN): tmpl = "file '%s' is not a Word file, content type is '%s'" raise ValueError(tmpl % (docx, document_part.content_type)) return document_part.document diff --git a/src/docx/opc/constants.py b/src/docx/opc/constants.py index a3d0e0812..30b856614 100644 --- a/src/docx/opc/constants.py +++ b/src/docx/opc/constants.py @@ -135,6 +135,9 @@ class CONTENT_TYPE: WML_DOCUMENT_MAIN = ( "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml" ) + WML_TEMPLATE_MAIN = ( + "application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml" + ) WML_ENDNOTES = "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml" WML_FONT_TABLE = "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml" WML_FOOTER = "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml" diff --git a/tests/test_dotx_template.py b/tests/test_dotx_template.py new file mode 100644 index 000000000..14ea32714 --- /dev/null +++ b/tests/test_dotx_template.py @@ -0,0 +1,36 @@ +"""Tests for Issue #1532: .dotx template support.""" + +import os + +import pytest + +from docx import Document +from docx.package import Package +from docx.parts.document import DocumentPart + + +class DescribeDotxTemplate: + """Unit-test suite for .dotx file support.""" + + def it_can_load_a_dotx_template_file(self): + """Test loading a real .dotx file.""" + template_path = "test_dotx_real.dotx" + + if not os.path.exists(template_path): + pytest.skip(f"Template file {template_path} not found") + + # It should load the file successfully + doc = Document(template_path) + assert doc is not None + assert hasattr(doc, "paragraphs") + + def it_creates_document_part_for_dotx_files(self): + """Test that .dotx files create DocumentPart, not generic Part.""" + template_path = "test_dotx_real.dotx" + + if not os.path.exists(template_path): + pytest.skip(f"Template file {template_path} not found") + + pkg = Package.open(template_path) + # It should create a DocumentPart, not a generic Part + assert isinstance(pkg.main_document_part, DocumentPart) \ No newline at end of file