-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: improve command to upload local template files to storage backend
- Loading branch information
Showing
3 changed files
with
104 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
61 changes: 46 additions & 15 deletions
61
document_merge_service/api/management/commands/upload_local_templates.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,66 @@ | ||
import glob | ||
import os | ||
|
||
from django.conf import settings | ||
from django.core.files.storage import DefaultStorage | ||
from django.core.management.base import BaseCommand | ||
|
||
from document_merge_service.api.models import Template | ||
|
||
|
||
class Command(BaseCommand): | ||
help = "Add filesystem files to configured storage backend" | ||
help = "Upload local template files to configured storage backend" | ||
|
||
def add_arguments(self, parser): | ||
parser.add_argument("--dry-run", dest="dry", action="store_true", default=False) | ||
parser.add_argument( | ||
"-s", | ||
"--source", | ||
help="Glob-style path to the template files that should be uploaded. E.g. `/tmp/templates/*.docx`", | ||
dest="source", | ||
type=str, | ||
required=True, | ||
) | ||
parser.add_argument( | ||
"--dry-run", | ||
help="Only show what files would be uploaded to the storage backend; don't actually upload them.", | ||
dest="dry", | ||
action="store_true", | ||
default=False, | ||
) | ||
|
||
def handle(self, *args, **options): | ||
storage = DefaultStorage() | ||
for template in Template.objects.all(): | ||
|
||
for path in glob.iglob(options["source"]): | ||
filename = os.path.basename(path) | ||
|
||
try: | ||
with open( | ||
os.path.join(settings.MEDIA_ROOT, template.template.name), "rb" | ||
) as file: | ||
if not options.get("dry"): | ||
template = Template.objects.get(template=filename) | ||
except Template.DoesNotExist: | ||
self.stdout.write( | ||
self.style.WARNING(f'No template for filename "{filename}" found') | ||
) | ||
continue | ||
|
||
if not options.get("dry"): | ||
try: | ||
with open(path, "rb") as file: | ||
storage.delete(template.template.name) | ||
storage.save(template.template.name, file) | ||
self.stdout.write( | ||
self.style.SUCCESS(f"Uploaded file for '{template.pk}'") | ||
|
||
self.stdout.write( | ||
self.style.SUCCESS( | ||
f'Uploaded file for template "{template.pk}"' | ||
) | ||
else: | ||
self.stdout.write( | ||
self.style.WARNING(f"Would upload file for '{template.pk}'") | ||
) | ||
except Exception as e: # pragma: no cover | ||
self.stdout.write( | ||
self.style.ERROR( | ||
f'Could not upload file for template "{template.pk}": {str(e)}' | ||
) | ||
except Exception as e: # pragma: no cover | ||
) | ||
else: | ||
self.stdout.write( | ||
self.style.ERROR(f"Could not upload file '{template.pk}': {str(e)}") | ||
self.style.WARNING( | ||
f'Would upload file for template "{template.pk}"' | ||
) | ||
) |
56 changes: 49 additions & 7 deletions
56
document_merge_service/api/tests/test_upload_local_templates.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,63 @@ | ||
import hashlib | ||
import os | ||
import shutil | ||
|
||
import pytest | ||
from django.core.management import call_command | ||
from faker import Faker | ||
|
||
from document_merge_service.api.data import django_file | ||
|
||
|
||
def sha256sum(path): | ||
with open(path, "rb") as file: | ||
return hashlib.sha256(file.read()).hexdigest() | ||
|
||
|
||
def is_equal(a, b): | ||
return sha256sum(a) == sha256sum(b) | ||
|
||
|
||
@pytest.fixture | ||
def tmp_path(settings): | ||
path = os.path.join(settings.MEDIA_ROOT, f"local-templates-{Faker().uuid4()}") | ||
|
||
yield path | ||
|
||
shutil.rmtree(path, ignore_errors=True) | ||
|
||
|
||
@pytest.mark.parametrize("dry", [True, False]) | ||
def test_upload_local_templates(db, dry, settings, template_factory): | ||
def test_upload_local_templates(db, dry, template_factory, tmp_path): | ||
templates = [ | ||
template_factory(template=django_file("docx-template.docx")), | ||
template_factory(template=django_file("docx-template-syntax.docx")), | ||
template_factory(template=django_file("docx-template-syntax.docx")), | ||
] | ||
|
||
files = [ | ||
django_file( | ||
"docx-template.docx", | ||
new_path=tmp_path, | ||
new_name=templates[0].template.name, | ||
), | ||
django_file( | ||
"docx-template.docx", | ||
new_path=tmp_path, | ||
new_name=templates[1].template.name, | ||
), | ||
django_file( | ||
"docx-template.docx", | ||
new_path=tmp_path, | ||
new_name="some-file-without-template.docx", | ||
), | ||
] | ||
|
||
call_command("upload_local_templates", dry=dry) | ||
paths = [os.path.join(tmp_path, file.name) for file in files] | ||
|
||
assert not is_equal(templates[0].template.path, paths[0]) | ||
assert not is_equal(templates[1].template.path, paths[1]) | ||
|
||
call_command("upload_local_templates", dry=dry, source=f"{tmp_path}/*.docx") | ||
|
||
assert ( | ||
all([os.path.isfile(template.template.path) is True for template in templates]) | ||
is True | ||
) | ||
assert is_equal(templates[0].template.path, paths[0]) != dry | ||
assert is_equal(templates[1].template.path, paths[1]) != dry |