annofabcli 1.111.2__py3-none-any.whl → 1.113.0__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/__main__.py +1 -2
- annofabcli/annotation/annotation_query.py +10 -10
- annofabcli/annotation/change_annotation_attributes.py +10 -10
- annofabcli/annotation/change_annotation_attributes_per_annotation.py +4 -5
- annofabcli/annotation/change_annotation_properties.py +14 -14
- annofabcli/annotation/copy_annotation.py +6 -6
- annofabcli/annotation/create_classification_annotation.py +7 -7
- annofabcli/annotation/delete_annotation.py +9 -9
- annofabcli/annotation/download_annotation_zip.py +1 -3
- annofabcli/annotation/dump_annotation.py +8 -8
- annofabcli/annotation/import_annotation.py +13 -13
- annofabcli/annotation/list_annotation.py +9 -9
- annofabcli/annotation/list_annotation_count.py +2 -3
- annofabcli/annotation/merge_segmentation.py +6 -6
- annofabcli/annotation/remove_segmentation_overlap.py +5 -5
- annofabcli/annotation/restore_annotation.py +7 -7
- annofabcli/annotation/subcommand_annotation.py +1 -2
- annofabcli/annotation_specs/add_attribute_restriction.py +4 -5
- annofabcli/annotation_specs/attribute_restriction.py +8 -8
- annofabcli/annotation_specs/export_annotation_specs.py +4 -5
- annofabcli/annotation_specs/get_annotation_specs_with_attribute_id_replaced.py +3 -4
- annofabcli/annotation_specs/get_annotation_specs_with_choice_id_replaced.py +3 -4
- annofabcli/annotation_specs/get_annotation_specs_with_label_id_replaced.py +3 -4
- annofabcli/annotation_specs/list_annotation_specs_attribute.py +9 -10
- annofabcli/annotation_specs/list_annotation_specs_choice.py +9 -10
- annofabcli/annotation_specs/list_annotation_specs_history.py +3 -3
- annofabcli/annotation_specs/list_annotation_specs_label.py +8 -9
- annofabcli/annotation_specs/list_annotation_specs_label_attribute.py +10 -11
- annofabcli/annotation_specs/list_attribute_restriction.py +2 -4
- annofabcli/annotation_specs/list_label_color.py +2 -3
- annofabcli/annotation_specs/put_label_color.py +3 -4
- annofabcli/annotation_specs/subcommand_annotation_specs.py +1 -3
- annofabcli/annotation_zip/list_annotation_3d_bounding_box.py +365 -0
- annofabcli/annotation_zip/list_annotation_bounding_box_2d.py +37 -38
- annofabcli/annotation_zip/list_polygon_annotation.py +390 -0
- annofabcli/annotation_zip/list_polyline_annotation.py +402 -0
- annofabcli/annotation_zip/list_range_annotation.py +25 -15
- annofabcli/annotation_zip/list_single_point_annotation.py +25 -34
- annofabcli/annotation_zip/subcommand_annotation_zip.py +7 -2
- annofabcli/annotation_zip/validate_annotation.py +8 -7
- annofabcli/comment/delete_comment.py +4 -6
- annofabcli/comment/download_comment_json.py +4 -6
- annofabcli/comment/list_all_comment.py +5 -6
- annofabcli/comment/list_comment.py +3 -4
- annofabcli/comment/put_comment.py +9 -10
- annofabcli/comment/put_comment_simply.py +5 -6
- annofabcli/comment/put_inspection_comment.py +1 -3
- annofabcli/comment/put_inspection_comment_simply.py +1 -3
- annofabcli/comment/put_onhold_comment.py +1 -3
- annofabcli/comment/put_onhold_comment_simply.py +1 -3
- annofabcli/comment/subcommand_comment.py +1 -3
- annofabcli/common/bokeh.py +4 -4
- annofabcli/common/cli.py +18 -17
- annofabcli/common/download.py +28 -29
- annofabcli/common/facade.py +37 -38
- annofabcli/common/image.py +14 -14
- annofabcli/common/utils.py +8 -8
- annofabcli/common/visualize.py +13 -13
- annofabcli/experimental/list_out_of_range_annotation_for_movie.py +3 -4
- annofabcli/experimental/subcommand_experimental.py +1 -3
- annofabcli/filesystem/draw_annotation.py +27 -27
- annofabcli/filesystem/filter_annotation.py +9 -10
- annofabcli/filesystem/mask_user_info.py +15 -15
- annofabcli/filesystem/merge_annotation.py +9 -9
- annofabcli/filesystem/subcommand_filesystem.py +1 -3
- annofabcli/input_data/copy_input_data.py +8 -9
- annofabcli/input_data/delete_input_data.py +3 -3
- annofabcli/input_data/delete_metadata_key_of_input_data.py +3 -5
- annofabcli/input_data/download_input_data_json.py +4 -6
- annofabcli/input_data/list_all_input_data.py +9 -9
- annofabcli/input_data/list_all_input_data_merged_task.py +5 -5
- annofabcli/input_data/list_input_data.py +5 -5
- annofabcli/input_data/put_input_data.py +6 -6
- annofabcli/input_data/put_input_data_with_zip.py +3 -4
- annofabcli/input_data/subcommand_input_data.py +1 -3
- annofabcli/input_data/update_input_data.py +6 -8
- annofabcli/input_data/update_metadata_of_input_data.py +3 -5
- annofabcli/instruction/copy_instruction.py +5 -6
- annofabcli/instruction/download_instruction.py +5 -6
- annofabcli/instruction/list_instruction_history.py +3 -3
- annofabcli/instruction/subcommand_instruction.py +1 -3
- annofabcli/instruction/upload_instruction.py +3 -4
- annofabcli/job/delete_job.py +2 -3
- annofabcli/job/list_job.py +5 -5
- annofabcli/job/list_last_job.py +4 -4
- annofabcli/job/subcommand_job.py +1 -3
- annofabcli/job/wait_job.py +4 -5
- annofabcli/my_account/get_my_account.py +2 -3
- annofabcli/my_account/subcommand_my_account.py +1 -3
- annofabcli/organization/list_organization.py +2 -3
- annofabcli/organization/subcommand_organization.py +1 -3
- annofabcli/organization_member/change_organization_member.py +3 -4
- annofabcli/organization_member/delete_organization_member.py +3 -4
- annofabcli/organization_member/invite_organization_member.py +1 -3
- annofabcli/organization_member/list_organization_member.py +3 -3
- annofabcli/organization_member/subcommand_organization_member.py +1 -3
- annofabcli/project/change_organization_of_project.py +4 -4
- annofabcli/project/change_project_status.py +4 -4
- annofabcli/project/copy_project.py +5 -5
- annofabcli/project/create_project.py +8 -8
- annofabcli/project/diff_projects.py +4 -5
- annofabcli/project/list_project.py +5 -5
- annofabcli/project/put_project.py +2 -3
- annofabcli/project/subcommand_project.py +1 -2
- annofabcli/project/update_configuration.py +4 -4
- annofabcli/project/update_project.py +6 -8
- annofabcli/project_member/change_project_members.py +8 -8
- annofabcli/project_member/copy_project_members.py +4 -4
- annofabcli/project_member/drop_project_members.py +2 -3
- annofabcli/project_member/invite_project_members.py +1 -3
- annofabcli/project_member/list_users.py +2 -3
- annofabcli/project_member/put_project_members.py +6 -6
- annofabcli/project_member/subcommand_project_member.py +1 -3
- annofabcli/stat_visualization/mask_visualization_dir.py +8 -9
- annofabcli/stat_visualization/merge_visualization_dir.py +6 -7
- annofabcli/stat_visualization/subcommand_stat_visualization.py +1 -2
- annofabcli/stat_visualization/summarize_whole_performance_csv.py +1 -2
- annofabcli/stat_visualization/write_graph.py +2 -3
- annofabcli/stat_visualization/write_performance_rating_csv.py +20 -27
- annofabcli/statistics/histogram.py +5 -6
- annofabcli/statistics/linegraph.py +13 -14
- annofabcli/statistics/list_annotation_area.py +38 -13
- annofabcli/statistics/list_annotation_attribute.py +9 -10
- annofabcli/statistics/list_annotation_attribute_filled_count.py +30 -31
- annofabcli/statistics/list_annotation_count.py +57 -58
- annofabcli/statistics/list_annotation_duration.py +33 -34
- annofabcli/statistics/list_video_duration.py +4 -5
- annofabcli/statistics/list_worktime.py +4 -4
- annofabcli/statistics/scatter.py +9 -8
- annofabcli/statistics/subcommand_statistics.py +1 -4
- annofabcli/statistics/summarize_task_count.py +4 -6
- annofabcli/statistics/summarize_task_count_by_task_id_group.py +2 -4
- annofabcli/statistics/summarize_task_count_by_user.py +1 -3
- annofabcli/statistics/visualization/dataframe/annotation_count.py +5 -4
- annofabcli/statistics/visualization/dataframe/annotation_duration.py +2 -3
- annofabcli/statistics/visualization/dataframe/cumulative_productivity.py +15 -17
- annofabcli/statistics/visualization/dataframe/productivity_per_date.py +17 -19
- annofabcli/statistics/visualization/dataframe/project_performance.py +3 -12
- annofabcli/statistics/visualization/dataframe/task.py +11 -12
- annofabcli/statistics/visualization/dataframe/task_worktime_by_phase_user.py +9 -10
- annofabcli/statistics/visualization/dataframe/user_performance.py +21 -19
- annofabcli/statistics/visualization/dataframe/whole_performance.py +3 -4
- annofabcli/statistics/visualization/dataframe/whole_productivity_per_date.py +12 -14
- annofabcli/statistics/visualization/dataframe/worktime_per_date.py +11 -13
- annofabcli/statistics/visualization/filtering_query.py +7 -7
- annofabcli/statistics/visualization/project_dir.py +27 -14
- annofabcli/statistics/visualize_annotation_count.py +22 -23
- annofabcli/statistics/visualize_annotation_duration.py +21 -22
- annofabcli/statistics/visualize_statistics.py +36 -33
- annofabcli/statistics/visualize_video_duration.py +18 -20
- annofabcli/supplementary/delete_supplementary_data.py +5 -5
- annofabcli/supplementary/list_supplementary_data.py +4 -4
- annofabcli/supplementary/put_supplementary_data.py +9 -9
- annofabcli/supplementary/subcommand_supplementary.py +1 -3
- annofabcli/task/cancel_acceptance.py +16 -17
- annofabcli/task/change_operator.py +10 -12
- annofabcli/task/change_status_to_break.py +7 -9
- annofabcli/task/change_status_to_on_hold.py +10 -12
- annofabcli/task/complete_tasks.py +17 -18
- annofabcli/task/copy_tasks.py +3 -5
- annofabcli/task/delete_metadata_key_of_task.py +4 -6
- annofabcli/task/delete_tasks.py +7 -7
- annofabcli/task/download_task_json.py +4 -6
- annofabcli/task/list_all_tasks.py +8 -8
- annofabcli/task/list_all_tasks_added_task_history.py +14 -13
- annofabcli/task/list_tasks.py +7 -7
- annofabcli/task/list_tasks_added_task_history.py +10 -10
- annofabcli/task/put_tasks.py +5 -6
- annofabcli/task/put_tasks_by_count.py +2 -3
- annofabcli/task/reject_tasks.py +18 -20
- annofabcli/task/subcommand_task.py +1 -3
- annofabcli/task/update_metadata_of_task.py +5 -6
- annofabcli/task_history/download_task_history_json.py +4 -6
- annofabcli/task_history/list_all_task_history.py +6 -7
- annofabcli/task_history/list_task_history.py +4 -5
- annofabcli/task_history/subcommand_task_history.py +1 -3
- annofabcli/task_history_event/download_task_history_event_json.py +4 -6
- annofabcli/task_history_event/list_all_task_history_event.py +7 -7
- annofabcli/task_history_event/list_worktime.py +17 -16
- annofabcli/task_history_event/subcommand_task_history_event.py +1 -2
- {annofabcli-1.111.2.dist-info → annofabcli-1.113.0.dist-info}/METADATA +9 -15
- annofabcli-1.113.0.dist-info/RECORD +231 -0
- {annofabcli-1.111.2.dist-info → annofabcli-1.113.0.dist-info}/WHEEL +1 -1
- annofabcli-1.111.2.dist-info/RECORD +0 -228
- {annofabcli-1.111.2.dist-info → annofabcli-1.113.0.dist-info}/entry_points.txt +0 -0
- {annofabcli-1.111.2.dist-info → annofabcli-1.113.0.dist-info}/licenses/LICENSE +0 -0
annofabcli/common/download.py
CHANGED
|
@@ -3,7 +3,6 @@ import datetime
|
|
|
3
3
|
import logging.config
|
|
4
4
|
from functools import partial
|
|
5
5
|
from pathlib import Path
|
|
6
|
-
from typing import Optional, Union
|
|
7
6
|
|
|
8
7
|
import annofabapi
|
|
9
8
|
import requests
|
|
@@ -23,7 +22,7 @@ DOWNLOADING_FILETYPE_DICT = {
|
|
|
23
22
|
DEFAULT_WAIT_OPTIONS = WaitOptions(interval=60, max_tries=360)
|
|
24
23
|
|
|
25
24
|
|
|
26
|
-
def _get_annofab_error_message(http_error: requests.HTTPError) ->
|
|
25
|
+
def _get_annofab_error_message(http_error: requests.HTTPError) -> str | None:
|
|
27
26
|
obj = http_error.response.json()
|
|
28
27
|
errors = obj.get("errors")
|
|
29
28
|
if errors is None:
|
|
@@ -48,8 +47,8 @@ class DownloadingFile:
|
|
|
48
47
|
self,
|
|
49
48
|
project_id: str,
|
|
50
49
|
job_type: ProjectJobType,
|
|
51
|
-
wait_options:
|
|
52
|
-
job_id:
|
|
50
|
+
wait_options: WaitOptions | None = None,
|
|
51
|
+
job_id: str | None = None,
|
|
53
52
|
):
|
|
54
53
|
if wait_options is None:
|
|
55
54
|
wait_options = DEFAULT_WAIT_OPTIONS
|
|
@@ -69,9 +68,9 @@ class DownloadingFile:
|
|
|
69
68
|
async def download_annotation_zip_with_async(
|
|
70
69
|
self,
|
|
71
70
|
project_id: str,
|
|
72
|
-
dest_path:
|
|
71
|
+
dest_path: str | Path,
|
|
73
72
|
is_latest: bool = False, # noqa: FBT001, FBT002
|
|
74
|
-
wait_options:
|
|
73
|
+
wait_options: WaitOptions | None = None,
|
|
75
74
|
) -> None:
|
|
76
75
|
loop = asyncio.get_event_loop()
|
|
77
76
|
partial_func = partial(self.download_annotation_zip, project_id, dest_path, is_latest, wait_options)
|
|
@@ -80,9 +79,9 @@ class DownloadingFile:
|
|
|
80
79
|
def download_annotation_zip(
|
|
81
80
|
self,
|
|
82
81
|
project_id: str,
|
|
83
|
-
dest_path:
|
|
82
|
+
dest_path: str | Path,
|
|
84
83
|
is_latest: bool = False, # noqa: FBT001, FBT002
|
|
85
|
-
wait_options:
|
|
84
|
+
wait_options: WaitOptions | None = None,
|
|
86
85
|
should_download_full_annotation: bool = False, # noqa: FBT001, FBT002
|
|
87
86
|
) -> None:
|
|
88
87
|
"""アノテーションZIPをダウンロードします。"""
|
|
@@ -108,7 +107,7 @@ class DownloadingFile:
|
|
|
108
107
|
else:
|
|
109
108
|
raise e # noqa: TRY201
|
|
110
109
|
|
|
111
|
-
def wait_until_updated_annotation_zip(self, project_id: str, wait_options:
|
|
110
|
+
def wait_until_updated_annotation_zip(self, project_id: str, wait_options: WaitOptions | None = None) -> None:
|
|
112
111
|
job_id = None
|
|
113
112
|
try:
|
|
114
113
|
job = self.service.api.post_annotation_archive_update(project_id)[0]["job"]
|
|
@@ -125,9 +124,9 @@ class DownloadingFile:
|
|
|
125
124
|
async def download_input_data_json_with_async(
|
|
126
125
|
self,
|
|
127
126
|
project_id: str,
|
|
128
|
-
dest_path:
|
|
127
|
+
dest_path: str | Path,
|
|
129
128
|
is_latest: bool = False, # noqa: FBT001, FBT002
|
|
130
|
-
wait_options:
|
|
129
|
+
wait_options: WaitOptions | None = None,
|
|
131
130
|
) -> None:
|
|
132
131
|
loop = asyncio.get_event_loop()
|
|
133
132
|
partial_func = partial(self.download_input_data_json, project_id, dest_path, is_latest, wait_options)
|
|
@@ -136,9 +135,9 @@ class DownloadingFile:
|
|
|
136
135
|
def download_input_data_json(
|
|
137
136
|
self,
|
|
138
137
|
project_id: str,
|
|
139
|
-
dest_path:
|
|
138
|
+
dest_path: str | Path,
|
|
140
139
|
is_latest: bool = False, # noqa: FBT001, FBT002
|
|
141
|
-
wait_options:
|
|
140
|
+
wait_options: WaitOptions | None = None,
|
|
142
141
|
) -> None:
|
|
143
142
|
if is_latest:
|
|
144
143
|
self.wait_until_updated_input_data_json(project_id, wait_options)
|
|
@@ -155,7 +154,7 @@ class DownloadingFile:
|
|
|
155
154
|
else:
|
|
156
155
|
raise e # noqa: TRY201
|
|
157
156
|
|
|
158
|
-
def wait_until_updated_input_data_json(self, project_id: str, wait_options:
|
|
157
|
+
def wait_until_updated_input_data_json(self, project_id: str, wait_options: WaitOptions | None = None) -> None:
|
|
159
158
|
job_id = None
|
|
160
159
|
try:
|
|
161
160
|
job = self.service.api.post_project_inputs_update(project_id)[0]["job"]
|
|
@@ -172,15 +171,15 @@ class DownloadingFile:
|
|
|
172
171
|
async def download_task_json_with_async(
|
|
173
172
|
self,
|
|
174
173
|
project_id: str,
|
|
175
|
-
dest_path:
|
|
174
|
+
dest_path: str | Path,
|
|
176
175
|
is_latest: bool = False, # noqa: FBT001, FBT002
|
|
177
|
-
wait_options:
|
|
176
|
+
wait_options: WaitOptions | None = None,
|
|
178
177
|
) -> None:
|
|
179
178
|
loop = asyncio.get_event_loop()
|
|
180
179
|
partial_func = partial(self.download_task_json, project_id, dest_path, is_latest=is_latest, wait_options=wait_options)
|
|
181
180
|
await loop.run_in_executor(None, partial_func)
|
|
182
181
|
|
|
183
|
-
def download_task_json(self, project_id: str, dest_path:
|
|
182
|
+
def download_task_json(self, project_id: str, dest_path: str | Path, *, is_latest: bool = False, wait_options: WaitOptions | None = None) -> None:
|
|
184
183
|
if is_latest:
|
|
185
184
|
self.wait_until_updated_task_json(project_id, wait_options)
|
|
186
185
|
self.service.wrapper.download_project_tasks_url(project_id, dest_path)
|
|
@@ -196,7 +195,7 @@ class DownloadingFile:
|
|
|
196
195
|
else:
|
|
197
196
|
raise e # noqa: TRY201
|
|
198
197
|
|
|
199
|
-
def wait_until_updated_task_json(self, project_id: str, wait_options:
|
|
198
|
+
def wait_until_updated_task_json(self, project_id: str, wait_options: WaitOptions | None = None) -> None:
|
|
200
199
|
job_id = None
|
|
201
200
|
try:
|
|
202
201
|
job = self.service.api.post_project_tasks_update(project_id)[0]["job"]
|
|
@@ -210,7 +209,7 @@ class DownloadingFile:
|
|
|
210
209
|
|
|
211
210
|
self._wait_for_completion(project_id, job_type=ProjectJobType.GEN_TASKS_LIST, wait_options=wait_options, job_id=job_id)
|
|
212
211
|
|
|
213
|
-
async def download_task_history_json_with_async(self, project_id: str, dest_path:
|
|
212
|
+
async def download_task_history_json_with_async(self, project_id: str, dest_path: str | Path) -> None:
|
|
214
213
|
"""
|
|
215
214
|
非同期でタスク履歴全件ファイルをダウンロードする。
|
|
216
215
|
|
|
@@ -219,7 +218,7 @@ class DownloadingFile:
|
|
|
219
218
|
"""
|
|
220
219
|
return self.download_task_history_json(project_id, dest_path=dest_path)
|
|
221
220
|
|
|
222
|
-
def download_task_history_json(self, project_id: str, dest_path:
|
|
221
|
+
def download_task_history_json(self, project_id: str, dest_path: str | Path) -> None:
|
|
223
222
|
"""
|
|
224
223
|
タスク履歴全件ファイルをダウンロードする。
|
|
225
224
|
|
|
@@ -237,7 +236,7 @@ class DownloadingFile:
|
|
|
237
236
|
raise DownloadingFileNotFoundError(f"project_id='{project_id}'のプロジェクトに、タスク履歴全件ファイルが存在しないため、ダウンロードできませんでした。") from e
|
|
238
237
|
raise e # noqa: TRY201
|
|
239
238
|
|
|
240
|
-
def download_task_history_event_json(self, project_id: str, dest_path:
|
|
239
|
+
def download_task_history_event_json(self, project_id: str, dest_path: str | Path) -> None:
|
|
241
240
|
"""
|
|
242
241
|
タスク履歴イベント全件ファイルをダウンロードする。
|
|
243
242
|
|
|
@@ -255,7 +254,7 @@ class DownloadingFile:
|
|
|
255
254
|
raise DownloadingFileNotFoundError(f"project_id='{project_id}'のプロジェクトに、タスク履歴イベント全件ファイルが存在しないため、ダウンロードできませんでした。") from e
|
|
256
255
|
raise e # noqa: TRY201
|
|
257
256
|
|
|
258
|
-
async def download_task_history_event_json_with_async(self, project_id: str, dest_path:
|
|
257
|
+
async def download_task_history_event_json_with_async(self, project_id: str, dest_path: str | Path) -> None:
|
|
259
258
|
"""
|
|
260
259
|
非同期でタスク履歴全件ファイルをダウンロードする。
|
|
261
260
|
|
|
@@ -265,7 +264,7 @@ class DownloadingFile:
|
|
|
265
264
|
"""
|
|
266
265
|
return self.download_task_history_event_json(project_id, dest_path=dest_path)
|
|
267
266
|
|
|
268
|
-
async def download_inspection_json_with_async(self, project_id: str, dest_path:
|
|
267
|
+
async def download_inspection_json_with_async(self, project_id: str, dest_path: str | Path) -> None:
|
|
269
268
|
"""
|
|
270
269
|
非同期で検査コメント全件ファイルをダウンロードする。
|
|
271
270
|
|
|
@@ -275,7 +274,7 @@ class DownloadingFile:
|
|
|
275
274
|
|
|
276
275
|
return self.download_inspection_comment_json(project_id, dest_path=dest_path)
|
|
277
276
|
|
|
278
|
-
def download_inspection_comment_json(self, project_id: str, dest_path:
|
|
277
|
+
def download_inspection_comment_json(self, project_id: str, dest_path: str | Path) -> None:
|
|
279
278
|
"""
|
|
280
279
|
検査コメント全件ファイルをダウンロードする。
|
|
281
280
|
|
|
@@ -290,7 +289,7 @@ class DownloadingFile:
|
|
|
290
289
|
raise DownloadingFileNotFoundError(f"project_id='{project_id}'のプロジェクトに、検査コメント全件ファイルが存在しないため、ダウンロードできませんでした。") from e
|
|
291
290
|
raise e # noqa: TRY201
|
|
292
291
|
|
|
293
|
-
async def download_comment_json_with_async(self, project_id: str, dest_path:
|
|
292
|
+
async def download_comment_json_with_async(self, project_id: str, dest_path: str | Path) -> None:
|
|
294
293
|
"""
|
|
295
294
|
非同期でコメント全件ファイルをダウンロードする。
|
|
296
295
|
|
|
@@ -300,7 +299,7 @@ class DownloadingFile:
|
|
|
300
299
|
|
|
301
300
|
return self.download_comment_json(project_id, dest_path=dest_path)
|
|
302
301
|
|
|
303
|
-
def download_comment_json(self, project_id: str, dest_path:
|
|
302
|
+
def download_comment_json(self, project_id: str, dest_path: str | Path) -> None:
|
|
304
303
|
"""
|
|
305
304
|
コメント全件ファイルをダウンロードする。
|
|
306
305
|
|
|
@@ -322,7 +321,7 @@ class DownloadingFile:
|
|
|
322
321
|
output_dir: Path,
|
|
323
322
|
*,
|
|
324
323
|
is_latest: bool = False,
|
|
325
|
-
wait_options:
|
|
324
|
+
wait_options: WaitOptions | None = None,
|
|
326
325
|
) -> Path:
|
|
327
326
|
"""
|
|
328
327
|
アノテーションZIPをoutput_dirに統一された命名規則でダウンロードする。
|
|
@@ -352,7 +351,7 @@ class DownloadingFile:
|
|
|
352
351
|
output_dir: Path,
|
|
353
352
|
*,
|
|
354
353
|
is_latest: bool = False,
|
|
355
|
-
wait_options:
|
|
354
|
+
wait_options: WaitOptions | None = None,
|
|
356
355
|
) -> Path:
|
|
357
356
|
"""
|
|
358
357
|
タスクJSONをoutput_dirに統一された命名規則でダウンロードする。
|
|
@@ -382,7 +381,7 @@ class DownloadingFile:
|
|
|
382
381
|
output_dir: Path,
|
|
383
382
|
*,
|
|
384
383
|
is_latest: bool = False,
|
|
385
|
-
wait_options:
|
|
384
|
+
wait_options: WaitOptions | None = None,
|
|
386
385
|
) -> Path:
|
|
387
386
|
"""
|
|
388
387
|
入力データJSONをoutput_dirに統一された命名規則でダウンロードする。
|
annofabcli/common/facade.py
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
from collections.abc import Collection
|
|
4
|
+
from collections.abc import Callable, Collection
|
|
5
5
|
from dataclasses import dataclass
|
|
6
|
-
from typing import Any
|
|
6
|
+
from typing import Any
|
|
7
7
|
|
|
8
8
|
import annofabapi
|
|
9
|
-
import annofabapi.utils
|
|
10
9
|
import more_itertools
|
|
11
10
|
from annofabapi.dataclass.annotation import AdditionalDataV1
|
|
12
11
|
from annofabapi.dataclass.input import InputData
|
|
@@ -33,27 +32,27 @@ class AnnotationQuery(DataClassJsonMixin):
|
|
|
33
32
|
"""
|
|
34
33
|
|
|
35
34
|
label_id: str
|
|
36
|
-
attributes:
|
|
35
|
+
attributes: list[AdditionalDataV1] | None = None
|
|
37
36
|
|
|
38
37
|
|
|
39
38
|
@dataclass
|
|
40
39
|
class AdditionalDataForCli(DataClassJsonMixin):
|
|
41
|
-
additional_data_definition_id:
|
|
40
|
+
additional_data_definition_id: str | None = None
|
|
42
41
|
"""属性ID"""
|
|
43
42
|
|
|
44
|
-
additional_data_definition_name_en:
|
|
43
|
+
additional_data_definition_name_en: str | None = None
|
|
45
44
|
"""属性の英語名"""
|
|
46
45
|
|
|
47
|
-
flag:
|
|
46
|
+
flag: bool | None = None
|
|
48
47
|
|
|
49
|
-
integer:
|
|
48
|
+
integer: int | None = None
|
|
50
49
|
|
|
51
|
-
comment:
|
|
50
|
+
comment: str | None = None
|
|
52
51
|
|
|
53
|
-
choice:
|
|
52
|
+
choice: str | None = None
|
|
54
53
|
"""選択肢ID"""
|
|
55
54
|
|
|
56
|
-
choice_name_en:
|
|
55
|
+
choice_name_en: str | None = None
|
|
57
56
|
"""選択肢の英語名"""
|
|
58
57
|
|
|
59
58
|
|
|
@@ -63,10 +62,10 @@ class AnnotationQueryForCli(DataClassJsonMixin):
|
|
|
63
62
|
コマンドライン上で指定するアノテーション検索条件
|
|
64
63
|
"""
|
|
65
64
|
|
|
66
|
-
label_name_en:
|
|
65
|
+
label_name_en: str | None = None
|
|
67
66
|
"""ラベルの英語名"""
|
|
68
|
-
label_id:
|
|
69
|
-
attributes:
|
|
67
|
+
label_id: str | None = None
|
|
68
|
+
attributes: list[AdditionalDataForCli] | None = None
|
|
70
69
|
|
|
71
70
|
|
|
72
71
|
@dataclass
|
|
@@ -75,12 +74,12 @@ class TaskQuery(DataClassJsonMixin):
|
|
|
75
74
|
コマンドライン上で指定するタスクの検索条件
|
|
76
75
|
"""
|
|
77
76
|
|
|
78
|
-
task_id:
|
|
79
|
-
phase:
|
|
80
|
-
status:
|
|
81
|
-
phase_stage:
|
|
82
|
-
user_id:
|
|
83
|
-
account_id:
|
|
77
|
+
task_id: str | None = None
|
|
78
|
+
phase: TaskPhase | None = None
|
|
79
|
+
status: TaskStatus | None = None
|
|
80
|
+
phase_stage: int | None = None
|
|
81
|
+
user_id: str | None = None
|
|
82
|
+
account_id: str | None = None
|
|
84
83
|
no_user: bool = False
|
|
85
84
|
"""Trueなら未割り当てのタスクで絞り込む"""
|
|
86
85
|
|
|
@@ -91,12 +90,12 @@ class InputDataQuery(DataClassJsonMixin):
|
|
|
91
90
|
コマンドライン上で指定する入力データの検索条件
|
|
92
91
|
"""
|
|
93
92
|
|
|
94
|
-
input_data_id:
|
|
95
|
-
input_data_name:
|
|
96
|
-
input_data_path:
|
|
93
|
+
input_data_id: str | None = None
|
|
94
|
+
input_data_name: str | None = None
|
|
95
|
+
input_data_path: str | None = None
|
|
97
96
|
|
|
98
97
|
|
|
99
|
-
def match_annotation_with_task_query(annotation: dict[str, Any], task_query:
|
|
98
|
+
def match_annotation_with_task_query(annotation: dict[str, Any], task_query: TaskQuery | None) -> bool:
|
|
100
99
|
"""
|
|
101
100
|
Simple Annotationが、タスククエリ条件に合致するか
|
|
102
101
|
|
|
@@ -130,7 +129,7 @@ def match_annotation_with_task_query(annotation: dict[str, Any], task_query: Opt
|
|
|
130
129
|
|
|
131
130
|
|
|
132
131
|
def match_task_with_query( # pylint: disable=too-many-return-statements # noqa: PLR0911
|
|
133
|
-
task: Task, task_query:
|
|
132
|
+
task: Task, task_query: TaskQuery | None
|
|
134
133
|
) -> bool:
|
|
135
134
|
"""
|
|
136
135
|
タスク情報が、タスククエリ条件に合致するかどうか。
|
|
@@ -175,7 +174,7 @@ def match_task_with_query( # pylint: disable=too-many-return-statements # noqa
|
|
|
175
174
|
|
|
176
175
|
|
|
177
176
|
def match_input_data_with_query( # pylint: disable=too-many-return-statements
|
|
178
|
-
input_data: InputData, input_data_query:
|
|
177
|
+
input_data: InputData, input_data_query: InputDataQuery | None
|
|
179
178
|
) -> bool:
|
|
180
179
|
"""
|
|
181
180
|
入力データが、クエリ条件に合致するかどうか。
|
|
@@ -222,7 +221,7 @@ def convert_annotation_specs_labels_v2_to_v1(labels_v2: list[dict[str, Any]], ad
|
|
|
222
221
|
List[LabelV1]: V1版のラベル情報
|
|
223
222
|
"""
|
|
224
223
|
|
|
225
|
-
def get_additional(additional_data_definition_id: str) ->
|
|
224
|
+
def get_additional(additional_data_definition_id: str) -> dict[str, Any] | None:
|
|
226
225
|
return more_itertools.first_true(additionals_v2, pred=lambda e: e["additional_data_definition_id"] == additional_data_definition_id)
|
|
227
226
|
|
|
228
227
|
def to_label_v1(label_v2: dict[str, Any]) -> dict[str, Any]:
|
|
@@ -249,7 +248,7 @@ class AnnofabApiFacade:
|
|
|
249
248
|
"""
|
|
250
249
|
|
|
251
250
|
#: 組織メンバ一覧のキャッシュ
|
|
252
|
-
_organization_members:
|
|
251
|
+
_organization_members: tuple[str, list[OrganizationMember]] | None = None
|
|
253
252
|
|
|
254
253
|
_project_members_dict: dict[str, list[ProjectMember]] = {} # noqa: RUF012
|
|
255
254
|
"""プロジェクトメンバ一覧の情報。key:project_id, value:プロジェクトメンバ一覧"""
|
|
@@ -258,7 +257,7 @@ class AnnofabApiFacade:
|
|
|
258
257
|
self.service = service
|
|
259
258
|
|
|
260
259
|
@staticmethod
|
|
261
|
-
def get_account_id_last_annotation_phase(task_histories: list[dict[str, Any]]) ->
|
|
260
|
+
def get_account_id_last_annotation_phase(task_histories: list[dict[str, Any]]) -> str | None:
|
|
262
261
|
"""
|
|
263
262
|
タスク履歴の最後のannotation phaseを担当したaccount_idを取得する. なければNoneを返す
|
|
264
263
|
Args:
|
|
@@ -303,7 +302,7 @@ class AnnofabApiFacade:
|
|
|
303
302
|
project, _ = self.service.api.get_project(project_id)
|
|
304
303
|
return project["title"]
|
|
305
304
|
|
|
306
|
-
def _get_organization_member_with_predicate(self, project_id: str, predicate: Callable[[Any], bool]) ->
|
|
305
|
+
def _get_organization_member_with_predicate(self, project_id: str, predicate: Callable[[Any], bool]) -> OrganizationMember | None:
|
|
307
306
|
"""
|
|
308
307
|
account_idから組織メンバを取得する。
|
|
309
308
|
インスタンス変数に組織メンバがあれば、WebAPIは実行しない。
|
|
@@ -335,7 +334,7 @@ class AnnofabApiFacade:
|
|
|
335
334
|
update_organization_members()
|
|
336
335
|
return self._get_organization_member_with_predicate(project_id, predicate)
|
|
337
336
|
|
|
338
|
-
def _get_project_member_with_predicate(self, project_id: str, predicate: Callable[[Any], bool]) ->
|
|
337
|
+
def _get_project_member_with_predicate(self, project_id: str, predicate: Callable[[Any], bool]) -> ProjectMember | None:
|
|
339
338
|
"""
|
|
340
339
|
project_memberを取得する
|
|
341
340
|
|
|
@@ -352,7 +351,7 @@ class AnnofabApiFacade:
|
|
|
352
351
|
self._project_members_dict[project_id] = project_member_list
|
|
353
352
|
return more_itertools.first_true(project_member_list, pred=predicate)
|
|
354
353
|
|
|
355
|
-
def get_project_member_from_account_id(self, project_id: str, account_id: str) ->
|
|
354
|
+
def get_project_member_from_account_id(self, project_id: str, account_id: str) -> ProjectMember | None:
|
|
356
355
|
"""
|
|
357
356
|
account_idからプロジェクトメンバを取得する。
|
|
358
357
|
|
|
@@ -365,7 +364,7 @@ class AnnofabApiFacade:
|
|
|
365
364
|
"""
|
|
366
365
|
return self._get_project_member_with_predicate(project_id, predicate=lambda e: e["account_id"] == account_id)
|
|
367
366
|
|
|
368
|
-
def get_project_member_from_user_id(self, project_id: str, user_id: str) ->
|
|
367
|
+
def get_project_member_from_user_id(self, project_id: str, user_id: str) -> ProjectMember | None:
|
|
369
368
|
"""
|
|
370
369
|
user_idからプロジェクトメンバを取得する。
|
|
371
370
|
|
|
@@ -378,7 +377,7 @@ class AnnofabApiFacade:
|
|
|
378
377
|
"""
|
|
379
378
|
return self._get_project_member_with_predicate(project_id, predicate=lambda e: e["user_id"] == user_id)
|
|
380
379
|
|
|
381
|
-
def get_organization_member_from_user_id(self, project_id: str, user_id: str) ->
|
|
380
|
+
def get_organization_member_from_user_id(self, project_id: str, user_id: str) -> OrganizationMember | None:
|
|
382
381
|
"""
|
|
383
382
|
user_idから組織メンバを取得する。
|
|
384
383
|
インスタンス変数に組織メンバがあれば、WebAPIは実行しない。
|
|
@@ -392,7 +391,7 @@ class AnnofabApiFacade:
|
|
|
392
391
|
"""
|
|
393
392
|
return self._get_organization_member_with_predicate(project_id, lambda e: e["user_id"] == user_id)
|
|
394
393
|
|
|
395
|
-
def get_user_id_from_account_id(self, project_id: str, account_id: str) ->
|
|
394
|
+
def get_user_id_from_account_id(self, project_id: str, account_id: str) -> str | None:
|
|
396
395
|
"""
|
|
397
396
|
account_idからuser_idを取得する.
|
|
398
397
|
インスタンス変数に組織メンバがあれば、WebAPIは実行しない。
|
|
@@ -411,7 +410,7 @@ class AnnofabApiFacade:
|
|
|
411
410
|
else:
|
|
412
411
|
return member.get("user_id")
|
|
413
412
|
|
|
414
|
-
def get_account_id_from_user_id(self, project_id: str, user_id: str) ->
|
|
413
|
+
def get_account_id_from_user_id(self, project_id: str, user_id: str) -> str | None:
|
|
415
414
|
"""
|
|
416
415
|
user_idからaccount_idを取得する。
|
|
417
416
|
インスタンス変数に組織メンバがあれば、WebAPIは実行しない。
|
|
@@ -502,8 +501,8 @@ class AnnofabApiFacade:
|
|
|
502
501
|
def validate_project(
|
|
503
502
|
self,
|
|
504
503
|
project_id: str,
|
|
505
|
-
project_member_roles:
|
|
506
|
-
organization_member_roles:
|
|
504
|
+
project_member_roles: list[ProjectMemberRole] | None = None,
|
|
505
|
+
organization_member_roles: list[OrganizationMemberRole] | None = None,
|
|
507
506
|
) -> None:
|
|
508
507
|
"""
|
|
509
508
|
プロジェクト or 組織に対して、必要な権限が付与されているかを確認する。
|
annofabcli/common/image.py
CHANGED
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
|
|
6
6
|
import logging
|
|
7
7
|
import zipfile
|
|
8
|
+
from collections.abc import Callable
|
|
8
9
|
from pathlib import Path
|
|
9
|
-
from typing import Any
|
|
10
|
+
from typing import Any
|
|
10
11
|
|
|
11
|
-
import PIL
|
|
12
12
|
import PIL.Image
|
|
13
13
|
import PIL.ImageDraw
|
|
14
14
|
from annofabapi.dataclass.annotation import SimpleAnnotationDetail
|
|
@@ -24,7 +24,7 @@ IsParserFunc = Callable[[SimpleAnnotationParser], bool]
|
|
|
24
24
|
"""アノテーションparserに対してboolを返す関数"""
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
def get_data_uri_of_outer_file(annotation: SimpleAnnotationDetail) ->
|
|
27
|
+
def get_data_uri_of_outer_file(annotation: SimpleAnnotationDetail) -> str | None:
|
|
28
28
|
"""
|
|
29
29
|
外部ファイルの data_uri を取得する
|
|
30
30
|
Args:
|
|
@@ -45,7 +45,7 @@ def fill_annotation(
|
|
|
45
45
|
draw: PIL.ImageDraw.ImageDraw,
|
|
46
46
|
annotation: SimpleAnnotationDetail,
|
|
47
47
|
label_color_dict: dict[str, RGB],
|
|
48
|
-
outer_image:
|
|
48
|
+
outer_image: Any | None = None, # noqa: ANN401
|
|
49
49
|
) -> PIL.ImageDraw.ImageDraw:
|
|
50
50
|
"""
|
|
51
51
|
1個のアノテーションを、塗りつぶしで描画する。(矩形、ポリゴン、塗りつぶし、塗りつぶしv2)
|
|
@@ -94,7 +94,7 @@ def fill_annotation_list(
|
|
|
94
94
|
draw: PIL.ImageDraw.ImageDraw,
|
|
95
95
|
parser: SimpleAnnotationParser,
|
|
96
96
|
label_color_dict: dict[str, RGB],
|
|
97
|
-
label_name_list:
|
|
97
|
+
label_name_list: list[str] | None = None,
|
|
98
98
|
) -> PIL.ImageDraw.ImageDraw:
|
|
99
99
|
"""
|
|
100
100
|
1個の入力データに属するアノテーションlistを描画する
|
|
@@ -142,8 +142,8 @@ def write_annotation_image( # noqa: ANN201
|
|
|
142
142
|
image_size: InputDataSize,
|
|
143
143
|
label_color_dict: dict[str, RGB],
|
|
144
144
|
output_image_file: Path,
|
|
145
|
-
background_color:
|
|
146
|
-
label_name_list:
|
|
145
|
+
background_color: Any | None = None, # noqa: ANN401
|
|
146
|
+
label_name_list: list[str] | None = None,
|
|
147
147
|
):
|
|
148
148
|
"""
|
|
149
149
|
JSONファイルに記載されているアノテーション情報を、画像化する。
|
|
@@ -191,7 +191,7 @@ def write_annotation_grayscale_image(
|
|
|
191
191
|
parser: SimpleAnnotationParser,
|
|
192
192
|
image_size: InputDataSize,
|
|
193
193
|
output_image_file: Path,
|
|
194
|
-
label_name_list:
|
|
194
|
+
label_name_list: list[str] | None = None,
|
|
195
195
|
) -> None:
|
|
196
196
|
"""
|
|
197
197
|
JSONファイルに記載されているアノテーション情報を、グレースケール(8bit 1channel)で画像化します。
|
|
@@ -267,12 +267,12 @@ def write_annotation_images_from_path(
|
|
|
267
267
|
annotation_path: Path,
|
|
268
268
|
label_color_dict: dict[str, RGB],
|
|
269
269
|
output_dir_path: Path,
|
|
270
|
-
image_size:
|
|
271
|
-
input_data_dict:
|
|
270
|
+
image_size: InputDataSize | None = None,
|
|
271
|
+
input_data_dict: dict[str, InputData] | None = None,
|
|
272
272
|
output_image_extension: str = "png",
|
|
273
|
-
background_color:
|
|
274
|
-
label_name_list:
|
|
275
|
-
is_target_parser_func:
|
|
273
|
+
background_color: Any | None = None, # noqa: ANN401
|
|
274
|
+
label_name_list: list[str] | None = None,
|
|
275
|
+
is_target_parser_func: IsParserFunc | None = None,
|
|
276
276
|
) -> bool:
|
|
277
277
|
"""
|
|
278
278
|
Annofabからダウンロードしたアノテーションzipファイル、またはそのzipを展開したディレクトリから、アノテーション情報を画像化します。
|
|
@@ -297,7 +297,7 @@ def write_annotation_images_from_path(
|
|
|
297
297
|
|
|
298
298
|
"""
|
|
299
299
|
|
|
300
|
-
def _get_image_size(input_data_id: str) ->
|
|
300
|
+
def _get_image_size(input_data_id: str) -> InputDataSize | None:
|
|
301
301
|
def _get_image_size_from_system_metadata(arg_input_data: dict[str, Any]): # noqa: ANN202
|
|
302
302
|
# 入力データの`input_data.system_metadata.original_resolution`を参照して、画像サイズを決める。
|
|
303
303
|
original_resolution = arg_input_data["system_metadata"]["original_resolution"]
|
annofabcli/common/utils.py
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import logging
|
|
3
|
-
import logging.config
|
|
4
3
|
import os
|
|
5
4
|
import re
|
|
6
5
|
import sys
|
|
6
|
+
from collections.abc import Callable
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from typing import Any,
|
|
8
|
+
from typing import Any, TypeVar
|
|
9
9
|
|
|
10
10
|
import dateutil.parser
|
|
11
11
|
import isodate
|
|
@@ -46,7 +46,7 @@ def duplicated_set(target_list: list[T]) -> set[T]:
|
|
|
46
46
|
return {x for x in set(target_list) if target_list.count(x) > 1}
|
|
47
47
|
|
|
48
48
|
|
|
49
|
-
def output_string(target: str, output:
|
|
49
|
+
def output_string(target: str, output: str | Path | None = None) -> None:
|
|
50
50
|
"""
|
|
51
51
|
文字列を出力する。
|
|
52
52
|
|
|
@@ -64,7 +64,7 @@ def output_string(target: str, output: Optional[Union[str, Path]] = None) -> Non
|
|
|
64
64
|
logger.info(f"'{output}'を出力しました。")
|
|
65
65
|
|
|
66
66
|
|
|
67
|
-
def print_json(target: Any, is_pretty: bool = False, output:
|
|
67
|
+
def print_json(target: Any, is_pretty: bool = False, output: str | Path | None = None) -> None: # noqa: ANN401, FBT001, FBT002
|
|
68
68
|
"""
|
|
69
69
|
JSONを出力する。
|
|
70
70
|
|
|
@@ -80,7 +80,7 @@ def print_json(target: Any, is_pretty: bool = False, output: Optional[Union[str,
|
|
|
80
80
|
output_string(json.dumps(target, ensure_ascii=False), output)
|
|
81
81
|
|
|
82
82
|
|
|
83
|
-
def print_csv(df: pandas.DataFrame, output:
|
|
83
|
+
def print_csv(df: pandas.DataFrame, output: str | Path | None = None, to_csv_kwargs: dict[str, Any] | None = None) -> None:
|
|
84
84
|
if output is not None:
|
|
85
85
|
Path(output).parent.mkdir(parents=True, exist_ok=True)
|
|
86
86
|
|
|
@@ -98,7 +98,7 @@ def print_csv(df: pandas.DataFrame, output: Optional[Union[str, Path]] = None, t
|
|
|
98
98
|
logger.info(f"'{output}'を出力しました。")
|
|
99
99
|
|
|
100
100
|
|
|
101
|
-
def print_id_list(id_list: list[Any], output:
|
|
101
|
+
def print_id_list(id_list: list[Any], output: str | Path | None) -> None:
|
|
102
102
|
s = "\n".join(id_list)
|
|
103
103
|
output_string(s, output)
|
|
104
104
|
|
|
@@ -106,7 +106,7 @@ def print_id_list(id_list: list[Any], output: Optional[Union[str, Path]]) -> Non
|
|
|
106
106
|
def print_according_to_format(
|
|
107
107
|
target: Any, # noqa: ANN401
|
|
108
108
|
format: FormatArgument, # noqa: A002
|
|
109
|
-
output:
|
|
109
|
+
output: str | Path | None = None,
|
|
110
110
|
) -> None:
|
|
111
111
|
"""
|
|
112
112
|
コマンドライン引数 ``--format`` の値にしたがって、内容を出力する。
|
|
@@ -171,7 +171,7 @@ def is_file_scheme(str_value: str) -> bool:
|
|
|
171
171
|
return str_value.startswith("file://")
|
|
172
172
|
|
|
173
173
|
|
|
174
|
-
def get_file_scheme_path(str_value: str) ->
|
|
174
|
+
def get_file_scheme_path(str_value: str) -> str | None:
|
|
175
175
|
"""
|
|
176
176
|
file schemaのパスを取得する。file schemeでない場合は、Noneを返す
|
|
177
177
|
|
annofabcli/common/visualize.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import enum
|
|
4
|
-
from typing import Any
|
|
4
|
+
from typing import Any
|
|
5
5
|
|
|
6
6
|
import annofabapi
|
|
7
7
|
import more_itertools
|
|
@@ -32,15 +32,15 @@ class AddProps:
|
|
|
32
32
|
"""
|
|
33
33
|
|
|
34
34
|
#: 組織メンバ一覧のキャッシュ
|
|
35
|
-
_organization_members:
|
|
36
|
-
_project_member_list:
|
|
35
|
+
_organization_members: list[OrganizationMember] | None = None
|
|
36
|
+
_project_member_list: list[ProjectMember] | None = None
|
|
37
37
|
|
|
38
38
|
def __init__(self, service: annofabapi.Resource, project_id: str) -> None:
|
|
39
39
|
self.service = service
|
|
40
40
|
self.project_id = project_id
|
|
41
41
|
|
|
42
|
-
self._specs_labels:
|
|
43
|
-
self._specs_inspection_phrases:
|
|
42
|
+
self._specs_labels: list[dict[str, Any]] | None = None
|
|
43
|
+
self._specs_inspection_phrases: list[dict[str, Any]] | None = None
|
|
44
44
|
|
|
45
45
|
def _set_annotation_specs(self): # noqa: ANN202
|
|
46
46
|
"""
|
|
@@ -84,7 +84,7 @@ class AddProps:
|
|
|
84
84
|
return millisecond / 1000 / 3600
|
|
85
85
|
|
|
86
86
|
@staticmethod
|
|
87
|
-
def get_message(i18n_messages: dict[str, Any], locale: MessageLocale) ->
|
|
87
|
+
def get_message(i18n_messages: dict[str, Any], locale: MessageLocale) -> str | None:
|
|
88
88
|
messages: list[dict[str, Any]] = i18n_messages["messages"]
|
|
89
89
|
dict_message = more_itertools.first_true(messages, pred=lambda e: e["lang"] == locale.value)
|
|
90
90
|
if dict_message is not None:
|
|
@@ -112,7 +112,7 @@ class AddProps:
|
|
|
112
112
|
target["username"] = username
|
|
113
113
|
return target
|
|
114
114
|
|
|
115
|
-
def get_project_member_from_account_id(self, account_id: str) ->
|
|
115
|
+
def get_project_member_from_account_id(self, account_id: str) -> ProjectMember | None:
|
|
116
116
|
if self._project_member_list is None:
|
|
117
117
|
project_member_list = self.service.wrapper.get_all_project_members(self.project_id, query_params={"include_inactive_member": True})
|
|
118
118
|
self._project_member_list = project_member_list
|
|
@@ -128,22 +128,22 @@ class AddProps:
|
|
|
128
128
|
organization, _ = self.service.api.get_organization_of_project(project_id)
|
|
129
129
|
return organization["organization_name"]
|
|
130
130
|
|
|
131
|
-
def get_phrase_name(self, phrase_id: str, locale: MessageLocale) ->
|
|
132
|
-
phrase:
|
|
131
|
+
def get_phrase_name(self, phrase_id: str, locale: MessageLocale) -> str | None:
|
|
132
|
+
phrase: dict[str, Any] | None = more_itertools.first_true(self.specs_inspection_phrases, pred=lambda e: e["id"] == phrase_id)
|
|
133
133
|
if phrase is None:
|
|
134
134
|
return None
|
|
135
135
|
|
|
136
136
|
return self.get_message(phrase["text"], locale)
|
|
137
137
|
|
|
138
|
-
def get_label_name(self, label_id: str, locale: MessageLocale) ->
|
|
138
|
+
def get_label_name(self, label_id: str, locale: MessageLocale) -> str | None:
|
|
139
139
|
label = more_itertools.first_true(self.specs_labels, pred=lambda e: e["label_id"] == label_id)
|
|
140
140
|
if label is None:
|
|
141
141
|
return None
|
|
142
142
|
|
|
143
143
|
return self.get_message(label["label_name"], locale)
|
|
144
144
|
|
|
145
|
-
def get_additional_data_name(self, additional_data_definition_id: str, locale: MessageLocale, label_id:
|
|
146
|
-
def _get_additional_data_name(arg_additional_data_definitions: list[dict[str, Any]]) ->
|
|
145
|
+
def get_additional_data_name(self, additional_data_definition_id: str, locale: MessageLocale, label_id: str | None = None) -> str | None:
|
|
146
|
+
def _get_additional_data_name(arg_additional_data_definitions: list[dict[str, Any]]) -> str | None:
|
|
147
147
|
additional_data = more_itertools.first_true(
|
|
148
148
|
arg_additional_data_definitions,
|
|
149
149
|
pred=lambda e: e["additional_data_definition_id"] == additional_data_definition_id,
|
|
@@ -194,7 +194,7 @@ class AddProps:
|
|
|
194
194
|
"""
|
|
195
195
|
return self._add_user_info(instruction_history)
|
|
196
196
|
|
|
197
|
-
def add_properties_to_inspection(self, inspection: Inspection, detail:
|
|
197
|
+
def add_properties_to_inspection(self, inspection: Inspection, detail: dict[str, Any] | None = None) -> Inspection:
|
|
198
198
|
"""
|
|
199
199
|
検査コメントに、以下のキーを追加する.
|
|
200
200
|
commenter_user_id
|