♻️(backend) automatic delete temporary files
To leverage the automatic deletion of temporary files, we do the conversion inside the with context. Even if the conversion fails, the temporary file will be deleted.
This commit is contained in:
@@ -3,7 +3,6 @@ Declare and configure the models for the impress core application
|
||||
"""
|
||||
|
||||
import hashlib
|
||||
import os
|
||||
import tempfile
|
||||
import textwrap
|
||||
import uuid
|
||||
@@ -609,26 +608,25 @@ class Template(BaseModel):
|
||||
"""
|
||||
|
||||
reference_docx = "core/static/reference.docx"
|
||||
output = BytesIO()
|
||||
|
||||
# Convert the HTML to a temporary docx file
|
||||
with tempfile.NamedTemporaryFile(delete=False, suffix=".docx") as tmp_file:
|
||||
with tempfile.NamedTemporaryFile(suffix=".docx", prefix="docx_") as tmp_file:
|
||||
output_path = tmp_file.name
|
||||
|
||||
pypandoc.convert_text(
|
||||
html_string,
|
||||
"docx",
|
||||
format="html",
|
||||
outputfile=output_path,
|
||||
extra_args=["--reference-doc", reference_docx],
|
||||
)
|
||||
pypandoc.convert_text(
|
||||
html_string,
|
||||
"docx",
|
||||
format="html",
|
||||
outputfile=output_path,
|
||||
extra_args=["--reference-doc", reference_docx],
|
||||
)
|
||||
|
||||
# Create a BytesIO object to store the output of the temporary docx file
|
||||
with open(output_path, "rb") as f:
|
||||
output = BytesIO(f.read())
|
||||
|
||||
# Remove the temporary docx file
|
||||
os.remove(output_path)
|
||||
# Create a BytesIO object to store the output of the temporary docx file
|
||||
with open(output_path, "rb") as f:
|
||||
output = BytesIO(f.read())
|
||||
|
||||
# Ensure the pointer is at the beginning
|
||||
output.seek(0)
|
||||
|
||||
response = FileResponse(
|
||||
@@ -636,6 +634,7 @@ class Template(BaseModel):
|
||||
content_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||
)
|
||||
response["Content-Disposition"] = f"attachment; filename={self.title}.docx"
|
||||
|
||||
return response
|
||||
|
||||
def generate_document(self, body, body_type, export_format):
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
Unit tests for the Template model
|
||||
"""
|
||||
|
||||
import os
|
||||
from unittest import mock
|
||||
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
@@ -185,3 +188,30 @@ def test_models_templates_get_abilities_preset_role(django_assert_num_queries):
|
||||
"partial_update": False,
|
||||
"generate_document": True,
|
||||
}
|
||||
|
||||
|
||||
def test_models_templates__generate_word():
|
||||
"""Generate word document and assert no tmp files are left in /tmp folder."""
|
||||
template = factories.TemplateFactory()
|
||||
response = template.generate_word("<p>Test body</p>", {})
|
||||
|
||||
assert response.status_code == 200
|
||||
assert len([f for f in os.listdir("/tmp") if f.startswith("docx_")]) == 0
|
||||
|
||||
|
||||
@mock.patch(
|
||||
"pypandoc.convert_text",
|
||||
side_effect=RuntimeError("Conversion failed"),
|
||||
)
|
||||
def test_models_templates__generate_word__raise_error(_mock_send_mail):
|
||||
"""
|
||||
Generate word document and assert no tmp files are left in /tmp folder
|
||||
even when the conversion fails.
|
||||
"""
|
||||
template = factories.TemplateFactory()
|
||||
|
||||
try:
|
||||
template.generate_word("<p>Test body</p>", {})
|
||||
except RuntimeError as e:
|
||||
assert str(e) == "Conversion failed"
|
||||
assert len([f for f in os.listdir("/tmp") if f.startswith("docx_")]) == 0
|
||||
|
||||
Reference in New Issue
Block a user