diff --git a/invenio_records_resources/services/files/processors/base.py b/invenio_records_resources/services/files/processors/base.py index 87f0c4a2..b93f33ca 100644 --- a/invenio_records_resources/services/files/processors/base.py +++ b/invenio_records_resources/services/files/processors/base.py @@ -19,11 +19,11 @@ def __init__(self, processors): """Initialize the runner.""" self._processors = processors - def run(self, file_record, uow=None): + def run(self, file_record): """Run file processors or a given file record.""" for p in self._processors: if p.can_process(file_record): - p.process(file_record, uow=uow) + p.process(file_record) class FileProcessor: @@ -38,6 +38,6 @@ def can_process(self, file_record): """Determine if this processor can process a given file record.""" return False - def process(self, file_record, uow=None): + def process(self, file_record): """Process a file.""" pass diff --git a/invenio_records_resources/services/files/processors/image.py b/invenio_records_resources/services/files/processors/image.py index 2d7c40cb..5b8b8902 100644 --- a/invenio_records_resources/services/files/processors/image.py +++ b/invenio_records_resources/services/files/processors/image.py @@ -8,10 +8,13 @@ """Image metadata extractor.""" +import datetime import os +from io import BytesIO import pkg_resources from flask import current_app +from invenio_access.permissions import system_identity from invenio_records_resources.services.uow import TaskOp @@ -40,7 +43,7 @@ def can_process(self, file_record): return ext in current_app.config["RECORDS_RESOURCES_IMAGE_FORMATS"] return False - def process(self, file_record, uow=None): + def process(self, file_record): """Process the file record. Security: Do not execute ImageMagick inside an HTTP request. Always @@ -62,27 +65,3 @@ def process(self, file_record, uow=None): height = img_or_seq.height if width > 0 and height > 0: file_record.metadata.update({"width": width, "height": height}) - - -class TilesProcessor(FileProcessor): - - def __init__(self, valid_exts=["tif", "jpeg", "png", "jpg"]): - self.valid_exts = valid_exts - - def can_process(self, file_record): - if file_record.file.ext in self.valid_exts: - return True - - def process(self, file_record, uow): - record = file_record.record - from invenio_rdm_records.services.iiif.tasks import ( # TODO Temp fix for circular import - generate_zoomable_image, - ) - - uow.register( - TaskOp( - generate_zoomable_image, - record_id=record["id"], - file_key=file_record.key, - ) - ) diff --git a/invenio_records_resources/services/records/processors/base.py b/invenio_records_resources/services/records/processors/base.py new file mode 100644 index 00000000..d9ce6907 --- /dev/null +++ b/invenio_records_resources/services/records/processors/base.py @@ -0,0 +1,14 @@ +class RecordFilesProcessor: + """Base class for record files processors.""" + + def _can_process(self, file_record, draft, record): + """Determine if this processor can process a given record file.""" + return False + + def _process(self, file_record, draft, record, uow=None): + """Process a record file.""" + pass + + def __call__(self, file_record, draft, record, uow=None): + if self._can_process(file_record, draft, record): + self._process(file_record, draft, record, uow=uow) diff --git a/invenio_records_resources/services/records/processors/tiles.py b/invenio_records_resources/services/records/processors/tiles.py new file mode 100644 index 00000000..4c285b56 --- /dev/null +++ b/invenio_records_resources/services/records/processors/tiles.py @@ -0,0 +1,51 @@ +import datetime +from io import BytesIO + +from invenio_rdm_records.services.iiif.tasks import generate_zoomable_image + +from invenio_records_resources.services.records.processors.base import ( + RecordFilesProcessor, +) +from invenio_records_resources.services.uow import TaskOp + + +class TilesProcessor(RecordFilesProcessor): + + def __init__(self, valid_exts=["tif", "jpeg", "png", "jpg"]): + self.valid_exts = valid_exts + + def _can_process(self, file_record, record, draft): + if file_record.file.ext in self.valid_exts: + return True + + def _process(self, file_record, draft, record, uow): + ref = record if record.is_published else draft + ref.media_files.enabled = True + ref["media_files"]["enabled"] = True + + mf = ref.media_files.create( + f"{file_record.key}.ptif", + data={ + "metadata": { + "processor": { + "type": "image-tiles", + "status": "init", + # TODO: could also be just `mf.updated` + "updated_at": datetime.datetime.now().isoformat(), + "props": {}, + }, + }, + "access": {"hidden": False}, + }, + ) + + ref.media_files.create_obj(f"{file_record.key}.ptif", BytesIO()) + ref.media_files.commit(f"{file_record.key}.ptif") + + uow.register( + TaskOp( + generate_zoomable_image, + record_id=ref["id"], + file_key=file_record.key, + ) + )