|
2 | 2 | import json |
3 | 3 | import os |
4 | 4 | import re |
5 | | -from collections import namedtuple |
| 5 | +import tempfile |
| 6 | +import zipfile |
| 7 | +from collections import Counter, namedtuple |
6 | 8 |
|
7 | 9 | import openpyxl |
8 | 10 | import pytest |
@@ -743,16 +745,14 @@ def test_template_merge_jinja_filters_docx( |
743 | 745 | template.save() |
744 | 746 |
|
745 | 747 | data = { |
746 | | - "data": json.dumps( |
747 | | - { |
748 | | - "test_date": "1984-09-15", |
749 | | - "test_time": "23:24", |
750 | | - "test_datetime": "1984-09-15 23:23", |
751 | | - "test_datetime2": "23:23-1984-09-15", |
752 | | - "test_none": None, |
753 | | - "test_nested": {"multiline": "This is\na test."}, |
754 | | - } |
755 | | - ), |
| 748 | + "data": json.dumps({ |
| 749 | + "test_date": "1984-09-15", |
| 750 | + "test_time": "23:24", |
| 751 | + "test_datetime": "1984-09-15 23:23", |
| 752 | + "test_datetime2": "23:23-1984-09-15", |
| 753 | + "test_none": None, |
| 754 | + "test_nested": {"multiline": "This is\na test."}, |
| 755 | + }), |
756 | 756 | } |
757 | 757 |
|
758 | 758 | if not missing_file: |
@@ -916,3 +916,36 @@ def test_placeholder_with_unsupported_operand( |
916 | 916 | with pytest.raises(exceptions.ValidationError) as exc_info: |
917 | 917 | serializer.validate({"data": {"E_BAU_NUMBER": 12345}}) |
918 | 918 | assert exc_info.value.args[0] == expected_error |
| 919 | + |
| 920 | + |
| 921 | +def test_template_merge_docx_libreoffice_bug( |
| 922 | + db, client, mock_filefield_name_validation, template, snapshot |
| 923 | +): |
| 924 | + """Verify a certain docx corruption bug does not occur. |
| 925 | +
|
| 926 | + Certain versions of python-docx and python-docxtemplate cause corruption |
| 927 | + of files that were originally created with LibreOffice. One effect of that |
| 928 | + corruption is a duplicate entry in the document-internal files; there |
| 929 | + are two docProps/core.xml files in the resulting document. |
| 930 | + """ |
| 931 | + file = django_file("created_with_libreoffice.docx") |
| 932 | + template.template.save(os.path.basename(file.name), file) |
| 933 | + template.engine = "docx-template" |
| 934 | + template.save() |
| 935 | + url = reverse("template-merge", args=[template.pk]) |
| 936 | + |
| 937 | + response = client.post(url, data={"data": {"test": "Test input"}}, format="json") |
| 938 | + |
| 939 | + with tempfile.NamedTemporaryFile(suffix=".docx") as tmp: |
| 940 | + tmp.write(response.content) |
| 941 | + tmp.seek(0) |
| 942 | + |
| 943 | + zzz = zipfile.ZipFile(tmp.name) |
| 944 | + name_counter = Counter() |
| 945 | + name_counter.update([f.filename for f in zzz.filelist]) |
| 946 | + |
| 947 | + problematic_names = { |
| 948 | + name: count for name, count in name_counter.most_common() if count > 1 |
| 949 | + } |
| 950 | + |
| 951 | + assert problematic_names == {}, "Duplicate entry in docx file's internal structure" |
0 commit comments