From e00eea455025f1ce2e7be33264ee2849da1b51f4 Mon Sep 17 00:00:00 2001 From: Matteo Campinoti Date: Thu, 8 Aug 2024 13:55:37 +0200 Subject: [PATCH 1/8] cli:app_edit_lock - add edit lock command --- digiarch/cli.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/digiarch/cli.py b/digiarch/cli.py index 516bdf3a..44b908ca 100644 --- a/digiarch/cli.py +++ b/digiarch/cli.py @@ -1044,6 +1044,50 @@ def app_edit_rename( handle_end(ctx, database, exception, logger) +@app_edit.command("lock", no_args_is_help=True, short_help="Lock files.") +@argument("root", nargs=1, type=ClickPath(exists=True, file_okay=False, writable=True, resolve_path=True)) +@argument_ids(True) +@argument("reason", nargs=1, type=str, required=True) +@option("--lock/--unlock", is_flag=True, default=True, help="Lock or unlock files.") +@pass_context +def app_edit_lock( + ctx: Context, + root: str, + ids: tuple[str], + id_type: str, + id_files: bool, + reason: str, + lock: bool, +) -> None: + database_path: Path = Path(root) / "_metadata" / "files.db" + + if not database_path.is_file(): + raise FileNotFoundError(database_path) + + program_name: str = ctx.find_root().command.name + logger: Logger = setup_logger(program_name, files=[database_path.parent / f"{program_name}.log"], streams=[stdout]) + + if id_type in ("warnings",): + where: str = f"{id_type} like '%\"' || ? || '\"%'" + elif id_type.endswith("-like"): + id_type = id_type.removesuffix("-like") + where: str = f"{id_type} like ?" + else: + where: str = f"{id_type} = ?" + + with FileDB(database_path) as database: + handle_start(ctx, database, logger) + + with ExceptionManager(BaseException) as exception: + for file_id in ids: + for file in database.files.select(where=where, parameters=[str(file_id)]): + file.lock = lock + database.files.update(file) + database.add_history(file.uuid, "file.lock", reason=reason).log(INFO) + + handle_end(ctx, database, exception, logger) + + @app_edit.command("rollback", no_args_is_help=True, short_help="Roll back edits.") @argument("root", nargs=1, type=ClickPath(exists=True, file_okay=False, writable=True, resolve_path=True)) @argument( From 7c55fd07b0133c20d74d9e6b59390a928891ee6e Mon Sep 17 00:00:00 2001 From: Matteo Campinoti Date: Thu, 8 Aug 2024 14:06:04 +0200 Subject: [PATCH 2/8] tests:edit_lock - add test for edit lock command --- tests/test_cli.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/test_cli.py b/tests/test_cli.py index a6a254a5..82c0072a 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -24,6 +24,7 @@ from digiarch.cli import app from digiarch.cli import app_edit from digiarch.cli import app_edit_action +from digiarch.cli import app_edit_lock from digiarch.cli import app_edit_remove from digiarch.cli import app_edit_rename from digiarch.cli import app_edit_rollback @@ -559,6 +560,42 @@ def test_edit_remove_ids_file(tests_folder: Path, files_folder: Path, files_fold assert history_edit.reason == test_reason +def test_edit_lock(tests_folder: Path, files_folder: Path, files_folder_copy: Path): + database_path: Path = files_folder / "_metadata" / "files.db" + database_path_copy: Path = files_folder_copy / database_path.relative_to(files_folder) + database_path_copy.parent.mkdir(parents=True, exist_ok=True) + copy(database_path, database_path_copy) + + with FileDB(database_path_copy) as database: + files: list[File] = list(database.files.select(order_by=[("random()", "asc")], limit=3)) + + test_reason: str = "lock" + + app.main( + [ + app_edit.name, + app_edit_lock.name, + str(files_folder_copy), + "--uuid", + *(str(f.uuid) for f in files), + test_reason, + ] + ) + + with FileDB(database_path_copy) as database: + for file in files: + file_new: Optional[File] = database.files.select(where="uuid = ?", parameters=[str(file.uuid)]).fetchone() + assert file_new is None + assert file.lock is True + + history_edit: Optional[HistoryEntry] = database.history.select( + where="uuid = ? and operation like ? || '%'", + parameters=[str(file.uuid), "digiarch.edit.lock:"], + ).fetchone() + assert history_edit is not None + assert history_edit.reason == test_reason + + # noinspection DuplicatedCode def test_edit_rollback_action(tests_folder: Path, files_folder: Path, files_folder_copy: Path): database_path: Path = files_folder / "_metadata" / "files.db" From 6a6883ee9a62c44322fe3cecba3d4380d96ab72f Mon Sep 17 00:00:00 2001 From: Matteo Campinoti Date: Thu, 8 Aug 2024 14:07:43 +0200 Subject: [PATCH 3/8] cli:app_edit_lock - fix incorrect argument --- digiarch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/digiarch/cli.py b/digiarch/cli.py index 44b908ca..82397d1a 100644 --- a/digiarch/cli.py +++ b/digiarch/cli.py @@ -1083,7 +1083,7 @@ def app_edit_lock( for file in database.files.select(where=where, parameters=[str(file_id)]): file.lock = lock database.files.update(file) - database.add_history(file.uuid, "file.lock", reason=reason).log(INFO) + database.add_history(file.uuid, "file.lock", None, reason).log(INFO) handle_end(ctx, database, exception, logger) From 926b99cf6d8ec4f082a9657adae00367ec8dd483 Mon Sep 17 00:00:00 2001 From: Matteo Campinoti Date: Thu, 8 Aug 2024 14:32:07 +0200 Subject: [PATCH 4/8] tests:edit_lock - fix errors --- tests/test_cli.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index 82c0072a..42e53ddc 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -571,22 +571,22 @@ def test_edit_lock(tests_folder: Path, files_folder: Path, files_folder_copy: Pa test_reason: str = "lock" - app.main( - [ - app_edit.name, - app_edit_lock.name, - str(files_folder_copy), - "--uuid", - *(str(f.uuid) for f in files), - test_reason, - ] - ) + args: list[str] = [ + app_edit.name, + app_edit_lock.name, + str(files_folder_copy), + "--uuid", + *(str(f.uuid) for f in files), + test_reason, + ] + + app.main(args, standalone_mode=False) with FileDB(database_path_copy) as database: for file in files: file_new: Optional[File] = database.files.select(where="uuid = ?", parameters=[str(file.uuid)]).fetchone() - assert file_new is None - assert file.lock is True + assert file_new is not None + assert file_new.lock is True history_edit: Optional[HistoryEntry] = database.history.select( where="uuid = ? and operation like ? || '%'", From e02b3ce9ff890b4ee3fd5281586b2c8e53df5d36 Mon Sep 17 00:00:00 2001 From: Matteo Campinoti Date: Thu, 8 Aug 2024 14:32:15 +0200 Subject: [PATCH 5/8] cli:app_edit_lock - fix history entry --- digiarch/cli.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/digiarch/cli.py b/digiarch/cli.py index 82397d1a..0b145f17 100644 --- a/digiarch/cli.py +++ b/digiarch/cli.py @@ -1048,7 +1048,7 @@ def app_edit_rename( @argument("root", nargs=1, type=ClickPath(exists=True, file_okay=False, writable=True, resolve_path=True)) @argument_ids(True) @argument("reason", nargs=1, type=str, required=True) -@option("--lock/--unlock", is_flag=True, default=True, help="Lock or unlock files.") +@option("--lock/--unlock", is_flag=True, default=True, show_default=True, help="Lock or unlock files.") @pass_context def app_edit_lock( ctx: Context, @@ -1083,7 +1083,9 @@ def app_edit_lock( for file in database.files.select(where=where, parameters=[str(file_id)]): file.lock = lock database.files.update(file) - database.add_history(file.uuid, "file.lock", None, reason).log(INFO) + event = HistoryEntry.command_history(ctx, "file.lock", file.uuid, None, reason) + database.history.insert(event) + event.log(INFO) handle_end(ctx, database, exception, logger) From b885c3465858b76b1173807584c7c527afd7a60e Mon Sep 17 00:00:00 2001 From: Matteo Campinoti Date: Thu, 8 Aug 2024 14:36:53 +0200 Subject: [PATCH 6/8] poetry - version minor 2.0.2 > 2.1.0 --- digiarch/__version__.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/digiarch/__version__.py b/digiarch/__version__.py index 0309ae29..9aa3f903 100644 --- a/digiarch/__version__.py +++ b/digiarch/__version__.py @@ -1 +1 @@ -__version__ = "2.0.2" +__version__ = "2.1.0" diff --git a/pyproject.toml b/pyproject.toml index ca0469eb..e85e902f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "digiarch" -version = "2.0.2" +version = "2.1.0" description = "Tools for the Digital Archive Project at Aarhus Stadsarkiv" authors = ["Aryan Muhammadi Landi ", "Nina Jensen ", "Aarhus Stadsarkiv "] license = "GPL-3.0" From 93032f0170dbdbc800fb9773db0ecae602b77e4c Mon Sep 17 00:00:00 2001 From: Matteo Campinoti Date: Thu, 8 Aug 2024 14:40:25 +0200 Subject: [PATCH 7/8] cli:app_edit_rollback - add support for edit lock, lock events store before and after lock value --- digiarch/cli.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/digiarch/cli.py b/digiarch/cli.py index 0b145f17..d075cc51 100644 --- a/digiarch/cli.py +++ b/digiarch/cli.py @@ -1081,9 +1081,9 @@ def app_edit_lock( with ExceptionManager(BaseException) as exception: for file_id in ids: for file in database.files.select(where=where, parameters=[str(file_id)]): + event = HistoryEntry.command_history(ctx, "file.lock", file.uuid, [file.lock, lock], reason) file.lock = lock database.files.update(file) - event = HistoryEntry.command_history(ctx, "file.lock", file.uuid, None, reason) database.history.insert(event) event.log(INFO) @@ -1158,6 +1158,11 @@ def app_edit_rollback(ctx: Context, root: str, time_from: datetime, time_to: dat except DatabaseError: file.get_absolute_path().rename(file.get_absolute_path().with_name(new_name)) file.relative_path = file.relative_path.with_name(new_name) + elif event_command == f"{program_name}.{app_edit.name}.{app_edit_lock.name}": + file = database.files.select(where="uuid = ?", parameters=[str(event.uuid)]).fetchone() + if file: + file.lock = event.data[0] + database.files.update(file) if file: command.uuid = file.uuid From d4ea04046bbb38842b46a0e339eaefdd523af716 Mon Sep 17 00:00:00 2001 From: Matteo Campinoti Date: Thu, 8 Aug 2024 14:51:54 +0200 Subject: [PATCH 8/8] cli:app_edit_lock - add docstring --- digiarch/cli.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/digiarch/cli.py b/digiarch/cli.py index d075cc51..b3c3f03e 100644 --- a/digiarch/cli.py +++ b/digiarch/cli.py @@ -1059,6 +1059,11 @@ def app_edit_lock( reason: str, lock: bool, ) -> None: + """ + Lock files from being edited by reidentify. + + To unlock files, use the --unlock option. + """ database_path: Path = Path(root) / "_metadata" / "files.db" if not database_path.is_file():