Skip to content

Commit eb6282e

Browse files
committed
Add on-hold option to annotation data command
1 parent 72fe8b0 commit eb6282e

3 files changed

Lines changed: 58 additions & 0 deletions

File tree

annofabcli/annotation/change_annotation_data_per_annotation.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,12 +188,14 @@ def __init__(
188188
*,
189189
project_id: str,
190190
include_complete_task: bool,
191+
include_on_hold_task: bool,
191192
all_yes: bool,
192193
backup_dir: Path | None = None,
193194
) -> None:
194195
self.service = service
195196
self.project_id = project_id
196197
self.include_complete_task = include_complete_task
198+
self.include_on_hold_task = include_on_hold_task
197199
self.backup_dir = backup_dir
198200
self.dump_annotation_obj = DumpAnnotationMain(service, project_id)
199201
super().__init__(all_yes)
@@ -230,6 +232,13 @@ def change_annotation_data_for_task(self, task_id: str, annotation_list_per_inpu
230232
logger.info(f"task_id='{task_id}' :: タスクが作業中状態のため、{annotation_count} 件のアノテーションのdata変更をスキップします。")
231233
return False, ChangeAnnotationDataCount(success=0, failed=annotation_count)
232234

235+
if not self.include_on_hold_task and task["status"] == TaskStatus.ON_HOLD.value:
236+
logger.info(
237+
f"task_id='{task_id}' :: タスクが保留中状態のため、{annotation_count} 件のアノテーションのdata変更をスキップします。"
238+
"保留中状態のタスクのアノテーションも変更するには、`--include_on_hold_task` オプションを指定してください。"
239+
)
240+
return False, ChangeAnnotationDataCount(success=0, failed=annotation_count)
241+
233242
if not self.include_complete_task: # noqa: SIM102
234243
if task["status"] == TaskStatus.COMPLETE.value:
235244
logger.info(
@@ -340,6 +349,7 @@ def main(self) -> None:
340349
project_id=project_id,
341350
all_yes=args.yes,
342351
include_complete_task=args.include_complete_task,
352+
include_on_hold_task=args.include_on_hold_task,
343353
backup_dir=backup_dir,
344354
)
345355
main_obj.change_annotation_data(target_annotation_list)
@@ -383,6 +393,11 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
383393
action="store_true",
384394
help="指定した場合は、完了状態のタスクのアノテーションもdataを変更します。ただし、完了状態のタスクのアノテーションを変更するには、オーナーロールを持つユーザーが実行する必要があります。",
385395
)
396+
parser.add_argument(
397+
"--include_on_hold_task",
398+
action="store_true",
399+
help="指定した場合は、保留中状態のタスクのアノテーションもdataを変更します。指定しない場合、保留中状態のタスクはスキップされます。",
400+
)
386401

387402
parser.add_argument(
388403
"--backup",

docs/command_reference/annotation/change_data_per_annotation.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Description
88

99
属性値、ラベル、プロパティは変更しません。
1010
作業中状態のタスクに含まれるアノテーションは変更できません。
11+
保留中状態のタスクに含まれるアノテーションは、デフォルトでは変更できません。
1112

1213
外部ファイルが必要な塗りつぶしアノテーションなどは、このコマンドではサポートしていません。
1314

@@ -107,6 +108,8 @@ CSVのフォーマットは以下の通りです。
107108
デフォルトでは完了状態のタスクに含まれるアノテーションは変更できません。完了状態のタスクに含まれるアノテーションも変更する場合は、 ``--include_complete_task`` を指定してください。
108109
ただし、オーナーロールのユーザーで実行する必要があります。
109110

111+
デフォルトでは保留中状態のタスクに含まれるアノテーションは変更できません。保留中状態のタスクに含まれるアノテーションも変更する場合は、 ``--include_on_hold_task`` を指定してください。
112+
110113

111114

112115
Usage Details

tests/annotation/test_change_annotation_data_per_annotation.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
from __future__ import annotations
22

3+
from unittest.mock import Mock
4+
35
import pytest
46

57
from annofabcli.annotation.change_annotation_data_per_annotation import (
8+
ChangeAnnotationDataCount,
9+
ChangeAnnotationDataPerAnnotationMain,
610
TargetAnnotationData,
711
create_request_body_for_change_data,
812
get_annotation_data_list_per_task_id_input_data_id,
@@ -91,6 +95,42 @@ def test_skip_when_annotation_does_not_exist(self) -> None:
9195
assert actual_request_body == []
9296
assert actual_failed_count == 1
9397

98+
99+
class TestChangeAnnotationDataPerAnnotationMain:
100+
def test_change_annotation_data_for_task_skips_on_hold_task_by_default(self) -> None:
101+
service = Mock()
102+
service.wrapper.get_task_or_none.return_value = {"task_id": "task1", "status": "on_hold"}
103+
main_obj = ChangeAnnotationDataPerAnnotationMain(service, project_id="prj1", include_complete_task=False, include_on_hold_task=False, all_yes=True)
104+
105+
actual_is_changeable, actual_count = main_obj.change_annotation_data_for_task(
106+
"task1",
107+
{"input1": [TargetAnnotationData(task_id="task1", input_data_id="input1", annotation_id="anno1", data={"_type": "Range", "begin": 1000, "end": 5000})]},
108+
)
109+
110+
assert actual_is_changeable is False
111+
assert actual_count == ChangeAnnotationDataCount(success=0, failed=1)
112+
113+
def test_change_annotation_data_for_task_allows_on_hold_task_when_option_is_enabled(self, monkeypatch: pytest.MonkeyPatch) -> None:
114+
service = Mock()
115+
service.wrapper.get_task_or_none.return_value = {"task_id": "task1", "status": "on_hold"}
116+
main_obj = ChangeAnnotationDataPerAnnotationMain(service, project_id="prj1", include_complete_task=False, include_on_hold_task=True, all_yes=True)
117+
118+
def change_annotation_data_by_frame(task_id: str, input_data_id: str, anno_list: list[TargetAnnotationData]) -> ChangeAnnotationDataCount:
119+
assert task_id == "task1"
120+
assert input_data_id == "input1"
121+
assert len(anno_list) == 1
122+
return ChangeAnnotationDataCount(success=1, failed=0)
123+
124+
monkeypatch.setattr(main_obj, "change_annotation_data_by_frame", change_annotation_data_by_frame)
125+
126+
actual_is_changeable, actual_count = main_obj.change_annotation_data_for_task(
127+
"task1",
128+
{"input1": [TargetAnnotationData(task_id="task1", input_data_id="input1", annotation_id="anno1", data={"_type": "Range", "begin": 1000, "end": 5000})]},
129+
)
130+
131+
assert actual_is_changeable is True
132+
assert actual_count == ChangeAnnotationDataCount(success=1, failed=0)
133+
94134
def test_skip_when_data_type_is_changed(self) -> None:
95135
editor_annotation = {
96136
"project_id": "prj1",

0 commit comments

Comments
 (0)