annofabcli 1.106.0__py3-none-any.whl → 1.106.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- annofabcli/annotation/dump_annotation.py +26 -11
- annofabcli/annotation/import_annotation.py +14 -1
- annofabcli/project/copy_project.py +3 -1
- annofabcli/task/copy_tasks.py +1 -1
- {annofabcli-1.106.0.dist-info → annofabcli-1.106.2.dist-info}/METADATA +1 -1
- {annofabcli-1.106.0.dist-info → annofabcli-1.106.2.dist-info}/RECORD +9 -9
- {annofabcli-1.106.0.dist-info → annofabcli-1.106.2.dist-info}/WHEEL +0 -0
- {annofabcli-1.106.0.dist-info → annofabcli-1.106.2.dist-info}/entry_points.txt +0 -0
- {annofabcli-1.106.0.dist-info → annofabcli-1.106.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -63,12 +63,12 @@ class DumpAnnotationMain:
|
|
|
63
63
|
outer_file_path = outer_dir / f"{annotation_id}"
|
|
64
64
|
self.service.wrapper.download(detail["url"], outer_file_path)
|
|
65
65
|
|
|
66
|
-
def dump_annotation_for_input_data(self, task_id: str, input_data_id: str, task_dir: Path) -> None:
|
|
67
|
-
editor_annotation, _ = self.service.api.get_editor_annotation(self.project_id, task_id, input_data_id, query_params={"v": "2"})
|
|
66
|
+
def dump_annotation_for_input_data(self, task_id: str, input_data_id: str, task_dir: Path, *, task_history_id: Optional[str] = None) -> None:
|
|
67
|
+
editor_annotation, _ = self.service.api.get_editor_annotation(self.project_id, task_id, input_data_id, query_params={"v": "2", "task_history_id": task_history_id})
|
|
68
68
|
json_path = task_dir / f"{input_data_id}.json"
|
|
69
69
|
self.dump_editor_annotation(editor_annotation=editor_annotation, json_path=json_path)
|
|
70
70
|
|
|
71
|
-
def dump_annotation_for_task(self, task_id: str, output_dir: Path, *, task_index: Optional[int] = None) -> bool:
|
|
71
|
+
def dump_annotation_for_task(self, task_id: str, output_dir: Path, *, task_index: Optional[int] = None, task_history_index: Optional[int] = None) -> bool:
|
|
72
72
|
"""
|
|
73
73
|
タスク配下のアノテーションをファイルに保存する。
|
|
74
74
|
|
|
@@ -85,15 +85,23 @@ class DumpAnnotationMain:
|
|
|
85
85
|
logger.warning(f"task_id = '{task_id}' のタスクは存在しません。スキップします。")
|
|
86
86
|
return False
|
|
87
87
|
|
|
88
|
+
task_history_id: Optional[str] = None
|
|
89
|
+
if task_history_index is not None:
|
|
90
|
+
task_histories, _ = self.service.api.get_task_histories(self.project_id, task_id)
|
|
91
|
+
if task_history_index >= len(task_histories):
|
|
92
|
+
logger.warning(f"task_id='{task_id}' :: task_history_index='{task_history_index}'のタスク履歴は存在しません。タスク履歴は{len(task_histories)}件です。スキップします。")
|
|
93
|
+
return False
|
|
94
|
+
task_history_id = task_histories[task_history_index]["task_history_id"]
|
|
95
|
+
|
|
88
96
|
input_data_id_list = task["input_data_id_list"]
|
|
89
97
|
task_dir = output_dir / task_id
|
|
90
98
|
task_dir.mkdir(exist_ok=True, parents=True)
|
|
91
|
-
logger.debug(f"{logger_prefix}task_id = '{task_id}' のアノテーション情報を '{task_dir}' ディレクトリに保存します。")
|
|
99
|
+
logger.debug(f"{logger_prefix}task_id = '{task_id}' のアノテーション情報を '{task_dir}' ディレクトリに保存します。 :: task_history_id='{task_history_id}'")
|
|
92
100
|
|
|
93
101
|
is_failure = False
|
|
94
102
|
for input_data_id in input_data_id_list:
|
|
95
103
|
try:
|
|
96
|
-
self.dump_annotation_for_input_data(task_id, input_data_id, task_dir=task_dir)
|
|
104
|
+
self.dump_annotation_for_input_data(task_id, input_data_id, task_dir=task_dir, task_history_id=task_history_id)
|
|
97
105
|
except Exception:
|
|
98
106
|
logger.warning(f"タスク'{task_id}', 入力データ'{input_data_id}' のアノテーション情報のダンプに失敗しました。", exc_info=True)
|
|
99
107
|
is_failure = True
|
|
@@ -101,15 +109,15 @@ class DumpAnnotationMain:
|
|
|
101
109
|
|
|
102
110
|
return not is_failure
|
|
103
111
|
|
|
104
|
-
def dump_annotation_for_task_wrapper(self, tpl: tuple[int, str], output_dir: Path) -> bool:
|
|
112
|
+
def dump_annotation_for_task_wrapper(self, tpl: tuple[int, str], output_dir: Path, *, task_history_index: Optional[int] = None) -> bool:
|
|
105
113
|
task_index, task_id = tpl
|
|
106
114
|
try:
|
|
107
|
-
return self.dump_annotation_for_task(task_id, output_dir=output_dir, task_index=task_index)
|
|
115
|
+
return self.dump_annotation_for_task(task_id, output_dir=output_dir, task_index=task_index, task_history_index=task_history_index)
|
|
108
116
|
except Exception: # pylint: disable=broad-except
|
|
109
117
|
logger.warning(f"タスク'{task_id}'のアノテーション情報のダンプに失敗しました。", exc_info=True)
|
|
110
118
|
return False
|
|
111
119
|
|
|
112
|
-
def dump_annotation(self, task_id_list: list[str], output_dir: Path, parallelism: Optional[int] = None)
|
|
120
|
+
def dump_annotation(self, task_id_list: list[str], output_dir: Path, *, task_history_index: Optional[int] = None, parallelism: Optional[int] = None) -> None:
|
|
113
121
|
project_title = self.facade.get_project_title(self.project_id)
|
|
114
122
|
logger.info(f"プロジェクト'{project_title}'に対して、タスク{len(task_id_list)} 件のアノテーションをファイルに保存します。")
|
|
115
123
|
|
|
@@ -118,7 +126,7 @@ class DumpAnnotationMain:
|
|
|
118
126
|
success_count = 0
|
|
119
127
|
|
|
120
128
|
if parallelism is not None:
|
|
121
|
-
func = functools.partial(self.dump_annotation_for_task_wrapper, output_dir=output_dir)
|
|
129
|
+
func = functools.partial(self.dump_annotation_for_task_wrapper, task_history_index=task_history_index, output_dir=output_dir)
|
|
122
130
|
with multiprocessing.Pool(parallelism) as pool:
|
|
123
131
|
result_bool_list = pool.map(func, enumerate(task_id_list))
|
|
124
132
|
success_count = len([e for e in result_bool_list if e])
|
|
@@ -126,7 +134,7 @@ class DumpAnnotationMain:
|
|
|
126
134
|
else:
|
|
127
135
|
for task_index, task_id in enumerate(task_id_list):
|
|
128
136
|
try:
|
|
129
|
-
result = self.dump_annotation_for_task(task_id, output_dir=output_dir, task_index=task_index)
|
|
137
|
+
result = self.dump_annotation_for_task(task_id, output_dir=output_dir, task_history_index=task_history_index, task_index=task_index)
|
|
130
138
|
if result:
|
|
131
139
|
success_count += 1
|
|
132
140
|
except Exception:
|
|
@@ -149,7 +157,7 @@ class DumpAnnotation(CommandLine):
|
|
|
149
157
|
super().validate_project(project_id, project_member_roles=None)
|
|
150
158
|
|
|
151
159
|
main_obj = DumpAnnotationMain(self.service, project_id)
|
|
152
|
-
main_obj.dump_annotation(task_id_list, output_dir=output_dir, parallelism=args.parallelism)
|
|
160
|
+
main_obj.dump_annotation(task_id_list, output_dir=output_dir, parallelism=args.parallelism, task_history_index=args.task_history_index)
|
|
153
161
|
|
|
154
162
|
|
|
155
163
|
def main(args: argparse.Namespace) -> None:
|
|
@@ -166,6 +174,13 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
|
|
|
166
174
|
|
|
167
175
|
parser.add_argument("-o", "--output_dir", type=str, required=True, help="出力先ディレクトリのパス")
|
|
168
176
|
|
|
177
|
+
parser.add_argument(
|
|
178
|
+
"--task_history_index",
|
|
179
|
+
type=int,
|
|
180
|
+
help="指定したタスク履歴のインデックス(ゼロ始まり)で付与されたアノテーション情報をダンプします。過去のアノテーション結果をダンプする場合に指定します。"
|
|
181
|
+
"ただし、過去のアノテーションデータは30日間しか保持されません。30日より前に更新されたアノテーションをダンプした場合は、アノテーションが0件の状態でダンプされます。",
|
|
182
|
+
)
|
|
183
|
+
|
|
169
184
|
parser.add_argument(
|
|
170
185
|
"--parallelism",
|
|
171
186
|
type=int,
|
|
@@ -152,13 +152,26 @@ class AnnotationConverter:
|
|
|
152
152
|
|
|
153
153
|
def _convert_attribute_value( # noqa: PLR0911, PLR0912
|
|
154
154
|
self,
|
|
155
|
-
attribute_value: Union[str, int, bool], # noqa: FBT001
|
|
155
|
+
attribute_value: Optional[Union[str, int, bool]], # noqa: FBT001
|
|
156
156
|
additional_data_type: AdditionalDataDefinitionType,
|
|
157
157
|
attribute_name: str,
|
|
158
158
|
choices: list[dict[str, Any]],
|
|
159
159
|
*,
|
|
160
160
|
log_message_suffix: str,
|
|
161
161
|
) -> Optional[dict[str, Any]]:
|
|
162
|
+
"""
|
|
163
|
+
JSONに記載されている属性値を、APIに渡すための `AdditionalDataValue`スキーマに変換します。
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
attribute_value: 属性値。 `None`の場合は、Noneを返します。
|
|
167
|
+
additional_data_type: 属性の型
|
|
168
|
+
attribute_name: 属性名
|
|
169
|
+
choices: 選択肢情報。`AdditionalDataDefinitionType.CHOICE`や`AdditionalDataDefinitionType.SELECT`の場合に利用する。
|
|
170
|
+
log_message_suffix: ログメッセージのサフィックス
|
|
171
|
+
"""
|
|
172
|
+
if attribute_value is None:
|
|
173
|
+
return None
|
|
174
|
+
|
|
162
175
|
if additional_data_type == AdditionalDataDefinitionType.FLAG:
|
|
163
176
|
if not isinstance(attribute_value, bool):
|
|
164
177
|
message = f"属性'{attribute_name}'に対応する属性値の型は bool である必要があります。 :: attribute_value='{attribute_value}', additional_data_type='{additional_data_type}' :: {log_message_suffix}" # noqa: E501
|
|
@@ -83,6 +83,8 @@ class CopyProject(CommandLine):
|
|
|
83
83
|
|
|
84
84
|
if copied_targets is not None:
|
|
85
85
|
logger.info(f"コピー対象: {[e.value for e in copied_targets]}")
|
|
86
|
+
else:
|
|
87
|
+
logger.info("コピー対象: None")
|
|
86
88
|
|
|
87
89
|
confirm_message = f"プロジェクト'{src_project_title}'(project_id='{src_project_id}')を、プロジェクト'{dest_title}'(project_id='{dest_project_id}') にコピーしますか?"
|
|
88
90
|
if not self.confirm_processing(confirm_message):
|
|
@@ -111,7 +113,7 @@ class CopyProject(CommandLine):
|
|
|
111
113
|
max_job_access=DEFAULT_WAIT_OPTIONS.max_tries,
|
|
112
114
|
)
|
|
113
115
|
if result:
|
|
114
|
-
logger.info("
|
|
116
|
+
logger.info(f"プロジェクト'{src_project_title}'のコピーが完了しました。 :: dest_project_id='{dest_project_id}', dest_project_title='{dest_title}'")
|
|
115
117
|
else:
|
|
116
118
|
logger.info("プロジェクトのコピーは実行中 または 失敗しました。")
|
|
117
119
|
|
annofabcli/task/copy_tasks.py
CHANGED
|
@@ -221,7 +221,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
|
|
|
221
221
|
def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
|
|
222
222
|
subcommand_name = "copy"
|
|
223
223
|
subcommand_help = "タスクをコピーします。"
|
|
224
|
-
description = "
|
|
224
|
+
description = "タスクをコピーします。タスクに含まれるアノテーションはコピーされません。"
|
|
225
225
|
epilog = "オーナロールを持つユーザで実行してください。"
|
|
226
226
|
|
|
227
227
|
parser = annofabcli.common.cli.add_parser(subparsers, subcommand_name, subcommand_help, description, epilog=epilog)
|
|
@@ -9,8 +9,8 @@ annofabcli/annotation/change_annotation_properties.py,sha256=Kp_LZ5sSoVmmjGE80AB
|
|
|
9
9
|
annofabcli/annotation/copy_annotation.py,sha256=Pih2k3vvpgfT3Ovb3gZw2L_8fK_ws_wKR7ARYG5hG_8,18407
|
|
10
10
|
annofabcli/annotation/delete_annotation.py,sha256=hQApNrx2Ci1bBWk0dRGA0oJkIgDHwl6Jy0-33gYF6jo,22989
|
|
11
11
|
annofabcli/annotation/download_annotation_zip.py,sha256=P_ZpdqIaSFEmB8jjpdykcRhh2tVlHxSlXFrYreJjShE,3282
|
|
12
|
-
annofabcli/annotation/dump_annotation.py,sha256=
|
|
13
|
-
annofabcli/annotation/import_annotation.py,sha256=
|
|
12
|
+
annofabcli/annotation/dump_annotation.py,sha256=Q-p6f5XBs7khDgrfY5Q3CGLBMKEerJWO_CQ8_73UXVM,9972
|
|
13
|
+
annofabcli/annotation/import_annotation.py,sha256=xCNnVEd8Ss6aN1XdDsTDf3AuRyB1ocAr0ofbxX1bWSc,33997
|
|
14
14
|
annofabcli/annotation/list_annotation.py,sha256=uKcOuGC7lzd6vVbzizkiZtYdXJ7EzY0iifuiqKl2wQM,10707
|
|
15
15
|
annofabcli/annotation/list_annotation_count.py,sha256=T9fbaoxWeDJIVgW_YgHRldbwrVZWiE-57lfJrDQrj80,6474
|
|
16
16
|
annofabcli/annotation/merge_segmentation.py,sha256=kIsCeXtJxzd6nobQPpi0fscaRDlTx3tg1qpy5PDfSJI,18107
|
|
@@ -114,7 +114,7 @@ annofabcli/organization_member/subcommand_organization_member.py,sha256=iK-Y4PxG
|
|
|
114
114
|
annofabcli/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
115
115
|
annofabcli/project/change_organization_of_project.py,sha256=yeR8Xu4nmvrA4jGfsPDmFxf-qJxvEVQAvluierJRMxc,11300
|
|
116
116
|
annofabcli/project/change_project_status.py,sha256=AQQFFYjUnwrFshuYS_xSGyLAp2lJ-7SSIuaigPTLBYk,8657
|
|
117
|
-
annofabcli/project/copy_project.py,sha256=
|
|
117
|
+
annofabcli/project/copy_project.py,sha256=O1TooJ0VVbRP84d4Y-8e6Z7pKMwhBEwPu3EBv15hPlY,7131
|
|
118
118
|
annofabcli/project/diff_projects.py,sha256=OsR0otV6MOCbUgGEDsYganu5cuHYZbpHbBAqujwBAw8,16531
|
|
119
119
|
annofabcli/project/list_project.py,sha256=OWnbCyShI4ceugxML8kSAD2nkyld5MlpXfbvQu2__4Y,10367
|
|
120
120
|
annofabcli/project/put_project.py,sha256=dsRJfx2ga4mmYci40q91UzXeQN6m_3fMU9mrcFRpY9Q,6033
|
|
@@ -186,7 +186,7 @@ annofabcli/task/change_operator.py,sha256=1LLpez79ezW_MqcNN608kjxp3xTS1uRRioqcug
|
|
|
186
186
|
annofabcli/task/change_status_to_break.py,sha256=hwdFTFW-zV0VxuinoBB5n6mvHJ7g9ChjrSOXZcNk88w,8621
|
|
187
187
|
annofabcli/task/change_status_to_on_hold.py,sha256=vWRyk6IK3HcgTWDIbbhXzsrtuoa7OlXCf8CvUpFp_Uw,12981
|
|
188
188
|
annofabcli/task/complete_tasks.py,sha256=ssg_Z7ADRQRXvXgK2k5TEmvbRjrJQ33cXeb8kG8Y3jc,24917
|
|
189
|
-
annofabcli/task/copy_tasks.py,sha256=
|
|
189
|
+
annofabcli/task/copy_tasks.py,sha256=66C1NQq46d6HenLpQCnkTjiXedL4iVtCu6qUimosVyU,8742
|
|
190
190
|
annofabcli/task/delete_metadata_key_of_task.py,sha256=Cjqe3fWKeRzVxxlrGyt3TS-x1riD55LnNXLIS9JPoTw,8029
|
|
191
191
|
annofabcli/task/delete_tasks.py,sha256=7T5eNCMW06ABekNGLwhTitDK5qn0tiPKrEXyJXyQNvs,13098
|
|
192
192
|
annofabcli/task/download_task_json.py,sha256=Ocjecmdf2WV_Sq3u1InfMLIsT3XSw0ojyJmJbhv2sgg,2803
|
|
@@ -209,8 +209,8 @@ annofabcli/task_history_event/download_task_history_event_json.py,sha256=hQLVbQ0
|
|
|
209
209
|
annofabcli/task_history_event/list_all_task_history_event.py,sha256=EeKMyPUxGwYCFtWQHHW954ZserGm8lUqrwNnV1iX9X4,6830
|
|
210
210
|
annofabcli/task_history_event/list_worktime.py,sha256=Y7Pu5DP7scPf7HPt6CTiTvB1_5_Nfi1bStUIaCpkhII,15507
|
|
211
211
|
annofabcli/task_history_event/subcommand_task_history_event.py,sha256=mJVJoT4RXk4HWnY7-Nrsl4If-gtaIIEXd2z7eFZwM2I,1260
|
|
212
|
-
annofabcli-1.106.
|
|
213
|
-
annofabcli-1.106.
|
|
214
|
-
annofabcli-1.106.
|
|
215
|
-
annofabcli-1.106.
|
|
216
|
-
annofabcli-1.106.
|
|
212
|
+
annofabcli-1.106.2.dist-info/METADATA,sha256=8kDxW3p5iajthMP9TJNcPUUEhZMOK1HCqPC83tRHcqU,5286
|
|
213
|
+
annofabcli-1.106.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
214
|
+
annofabcli-1.106.2.dist-info/entry_points.txt,sha256=C2uSUc-kkLJpoK_mDL5FEMAdorLEMPfwSf8VBMYnIFM,56
|
|
215
|
+
annofabcli-1.106.2.dist-info/licenses/LICENSE,sha256=pcqWYfxFtxBzhvKp3x9MXNM4xciGb2eFewaRhXUNHlo,1081
|
|
216
|
+
annofabcli-1.106.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|