annofabcli 1.111.1__py3-none-any.whl → 1.112.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.
Files changed (185) hide show
  1. annofabcli/__main__.py +1 -2
  2. annofabcli/annotation/annotation_query.py +10 -10
  3. annofabcli/annotation/change_annotation_attributes.py +9 -9
  4. annofabcli/annotation/change_annotation_attributes_per_annotation.py +3 -4
  5. annofabcli/annotation/change_annotation_properties.py +13 -13
  6. annofabcli/annotation/copy_annotation.py +5 -5
  7. annofabcli/annotation/create_classification_annotation.py +6 -6
  8. annofabcli/annotation/delete_annotation.py +8 -8
  9. annofabcli/annotation/download_annotation_zip.py +1 -3
  10. annofabcli/annotation/dump_annotation.py +7 -7
  11. annofabcli/annotation/import_annotation.py +12 -12
  12. annofabcli/annotation/list_annotation.py +8 -8
  13. annofabcli/annotation/list_annotation_count.py +1 -2
  14. annofabcli/annotation/merge_segmentation.py +5 -5
  15. annofabcli/annotation/remove_segmentation_overlap.py +4 -4
  16. annofabcli/annotation/restore_annotation.py +6 -6
  17. annofabcli/annotation/subcommand_annotation.py +1 -2
  18. annofabcli/annotation_specs/add_attribute_restriction.py +4 -5
  19. annofabcli/annotation_specs/attribute_restriction.py +8 -8
  20. annofabcli/annotation_specs/export_annotation_specs.py +4 -5
  21. annofabcli/annotation_specs/get_annotation_specs_with_attribute_id_replaced.py +3 -4
  22. annofabcli/annotation_specs/get_annotation_specs_with_choice_id_replaced.py +3 -4
  23. annofabcli/annotation_specs/get_annotation_specs_with_label_id_replaced.py +3 -4
  24. annofabcli/annotation_specs/list_annotation_specs_attribute.py +9 -10
  25. annofabcli/annotation_specs/list_annotation_specs_choice.py +9 -10
  26. annofabcli/annotation_specs/list_annotation_specs_history.py +2 -2
  27. annofabcli/annotation_specs/list_annotation_specs_label.py +8 -9
  28. annofabcli/annotation_specs/list_annotation_specs_label_attribute.py +10 -11
  29. annofabcli/annotation_specs/list_attribute_restriction.py +2 -4
  30. annofabcli/annotation_specs/list_label_color.py +2 -3
  31. annofabcli/annotation_specs/put_label_color.py +3 -4
  32. annofabcli/annotation_specs/subcommand_annotation_specs.py +1 -3
  33. annofabcli/annotation_zip/list_annotation_3d_bounding_box.py +365 -0
  34. annofabcli/annotation_zip/list_annotation_bounding_box_2d.py +11 -12
  35. annofabcli/annotation_zip/list_range_annotation.py +24 -14
  36. annofabcli/annotation_zip/list_single_point_annotation.py +11 -12
  37. annofabcli/annotation_zip/subcommand_annotation_zip.py +3 -2
  38. annofabcli/annotation_zip/validate_annotation.py +8 -7
  39. annofabcli/comment/delete_comment.py +4 -6
  40. annofabcli/comment/download_comment_json.py +4 -6
  41. annofabcli/comment/list_all_comment.py +5 -6
  42. annofabcli/comment/list_comment.py +3 -4
  43. annofabcli/comment/put_comment.py +9 -10
  44. annofabcli/comment/put_comment_simply.py +5 -6
  45. annofabcli/comment/put_inspection_comment.py +1 -3
  46. annofabcli/comment/put_inspection_comment_simply.py +1 -3
  47. annofabcli/comment/put_onhold_comment.py +1 -3
  48. annofabcli/comment/put_onhold_comment_simply.py +1 -3
  49. annofabcli/comment/subcommand_comment.py +1 -3
  50. annofabcli/common/bokeh.py +4 -4
  51. annofabcli/common/cli.py +17 -17
  52. annofabcli/common/download.py +28 -29
  53. annofabcli/common/facade.py +37 -38
  54. annofabcli/common/image.py +14 -14
  55. annofabcli/common/utils.py +8 -8
  56. annofabcli/common/visualize.py +13 -13
  57. annofabcli/experimental/list_out_of_range_annotation_for_movie.py +3 -4
  58. annofabcli/experimental/subcommand_experimental.py +1 -3
  59. annofabcli/filesystem/draw_annotation.py +26 -26
  60. annofabcli/filesystem/filter_annotation.py +9 -10
  61. annofabcli/filesystem/mask_user_info.py +14 -14
  62. annofabcli/filesystem/merge_annotation.py +8 -8
  63. annofabcli/filesystem/subcommand_filesystem.py +1 -3
  64. annofabcli/input_data/copy_input_data.py +8 -9
  65. annofabcli/input_data/delete_input_data.py +2 -2
  66. annofabcli/input_data/delete_metadata_key_of_input_data.py +3 -5
  67. annofabcli/input_data/download_input_data_json.py +4 -6
  68. annofabcli/input_data/list_all_input_data.py +8 -8
  69. annofabcli/input_data/list_all_input_data_merged_task.py +4 -4
  70. annofabcli/input_data/list_input_data.py +4 -4
  71. annofabcli/input_data/put_input_data.py +5 -5
  72. annofabcli/input_data/put_input_data_with_zip.py +2 -3
  73. annofabcli/input_data/subcommand_input_data.py +1 -3
  74. annofabcli/input_data/update_input_data.py +6 -8
  75. annofabcli/input_data/update_metadata_of_input_data.py +3 -5
  76. annofabcli/instruction/copy_instruction.py +4 -5
  77. annofabcli/instruction/download_instruction.py +4 -5
  78. annofabcli/instruction/list_instruction_history.py +2 -2
  79. annofabcli/instruction/subcommand_instruction.py +1 -3
  80. annofabcli/instruction/upload_instruction.py +2 -3
  81. annofabcli/job/delete_job.py +1 -2
  82. annofabcli/job/list_job.py +4 -4
  83. annofabcli/job/list_last_job.py +3 -3
  84. annofabcli/job/subcommand_job.py +1 -3
  85. annofabcli/job/wait_job.py +4 -5
  86. annofabcli/my_account/get_my_account.py +1 -2
  87. annofabcli/my_account/subcommand_my_account.py +1 -3
  88. annofabcli/organization/list_organization.py +1 -2
  89. annofabcli/organization/subcommand_organization.py +1 -3
  90. annofabcli/organization_member/change_organization_member.py +3 -4
  91. annofabcli/organization_member/delete_organization_member.py +3 -4
  92. annofabcli/organization_member/invite_organization_member.py +1 -3
  93. annofabcli/organization_member/list_organization_member.py +2 -2
  94. annofabcli/organization_member/subcommand_organization_member.py +1 -3
  95. annofabcli/project/change_organization_of_project.py +3 -3
  96. annofabcli/project/change_project_status.py +3 -3
  97. annofabcli/project/copy_project.py +4 -4
  98. annofabcli/project/create_project.py +7 -7
  99. annofabcli/project/diff_projects.py +4 -5
  100. annofabcli/project/list_project.py +4 -4
  101. annofabcli/project/put_project.py +1 -2
  102. annofabcli/project/subcommand_project.py +1 -2
  103. annofabcli/project/update_configuration.py +3 -3
  104. annofabcli/project/update_project.py +6 -8
  105. annofabcli/project_member/change_project_members.py +7 -7
  106. annofabcli/project_member/copy_project_members.py +3 -3
  107. annofabcli/project_member/drop_project_members.py +1 -2
  108. annofabcli/project_member/invite_project_members.py +1 -3
  109. annofabcli/project_member/list_users.py +1 -2
  110. annofabcli/project_member/put_project_members.py +5 -5
  111. annofabcli/project_member/subcommand_project_member.py +1 -3
  112. annofabcli/stat_visualization/mask_visualization_dir.py +8 -9
  113. annofabcli/stat_visualization/merge_visualization_dir.py +6 -7
  114. annofabcli/stat_visualization/subcommand_stat_visualization.py +1 -2
  115. annofabcli/stat_visualization/summarize_whole_performance_csv.py +1 -2
  116. annofabcli/stat_visualization/write_graph.py +2 -3
  117. annofabcli/stat_visualization/write_performance_rating_csv.py +20 -27
  118. annofabcli/statistics/histogram.py +5 -6
  119. annofabcli/statistics/linegraph.py +13 -14
  120. annofabcli/statistics/list_annotation_area.py +38 -13
  121. annofabcli/statistics/list_annotation_attribute.py +9 -10
  122. annofabcli/statistics/list_annotation_attribute_filled_count.py +30 -31
  123. annofabcli/statistics/list_annotation_count.py +57 -58
  124. annofabcli/statistics/list_annotation_duration.py +33 -34
  125. annofabcli/statistics/list_video_duration.py +4 -5
  126. annofabcli/statistics/list_worktime.py +3 -3
  127. annofabcli/statistics/scatter.py +9 -8
  128. annofabcli/statistics/subcommand_statistics.py +1 -4
  129. annofabcli/statistics/summarize_task_count.py +4 -6
  130. annofabcli/statistics/summarize_task_count_by_task_id_group.py +2 -4
  131. annofabcli/statistics/summarize_task_count_by_user.py +1 -3
  132. annofabcli/statistics/visualization/dataframe/annotation_count.py +5 -4
  133. annofabcli/statistics/visualization/dataframe/annotation_duration.py +6 -7
  134. annofabcli/statistics/visualization/dataframe/cumulative_productivity.py +15 -17
  135. annofabcli/statistics/visualization/dataframe/productivity_per_date.py +17 -19
  136. annofabcli/statistics/visualization/dataframe/project_performance.py +3 -12
  137. annofabcli/statistics/visualization/dataframe/task.py +11 -12
  138. annofabcli/statistics/visualization/dataframe/task_worktime_by_phase_user.py +9 -10
  139. annofabcli/statistics/visualization/dataframe/user_performance.py +21 -19
  140. annofabcli/statistics/visualization/dataframe/whole_performance.py +3 -4
  141. annofabcli/statistics/visualization/dataframe/whole_productivity_per_date.py +12 -14
  142. annofabcli/statistics/visualization/dataframe/worktime_per_date.py +11 -13
  143. annofabcli/statistics/visualization/filtering_query.py +7 -7
  144. annofabcli/statistics/visualization/project_dir.py +27 -14
  145. annofabcli/statistics/visualization/visualization_source_files.py +49 -0
  146. annofabcli/statistics/visualize_annotation_count.py +22 -23
  147. annofabcli/statistics/visualize_annotation_duration.py +21 -22
  148. annofabcli/statistics/visualize_statistics.py +126 -69
  149. annofabcli/statistics/visualize_video_duration.py +18 -20
  150. annofabcli/supplementary/delete_supplementary_data.py +4 -4
  151. annofabcli/supplementary/list_supplementary_data.py +3 -3
  152. annofabcli/supplementary/put_supplementary_data.py +8 -8
  153. annofabcli/supplementary/subcommand_supplementary.py +1 -3
  154. annofabcli/task/cancel_acceptance.py +16 -17
  155. annofabcli/task/change_operator.py +10 -12
  156. annofabcli/task/change_status_to_break.py +7 -9
  157. annofabcli/task/change_status_to_on_hold.py +10 -12
  158. annofabcli/task/complete_tasks.py +17 -18
  159. annofabcli/task/copy_tasks.py +3 -5
  160. annofabcli/task/delete_metadata_key_of_task.py +4 -6
  161. annofabcli/task/delete_tasks.py +6 -6
  162. annofabcli/task/download_task_json.py +4 -6
  163. annofabcli/task/list_all_tasks.py +7 -7
  164. annofabcli/task/list_all_tasks_added_task_history.py +12 -12
  165. annofabcli/task/list_tasks.py +6 -6
  166. annofabcli/task/list_tasks_added_task_history.py +9 -9
  167. annofabcli/task/put_tasks.py +4 -5
  168. annofabcli/task/put_tasks_by_count.py +1 -2
  169. annofabcli/task/reject_tasks.py +18 -20
  170. annofabcli/task/subcommand_task.py +1 -3
  171. annofabcli/task/update_metadata_of_task.py +5 -6
  172. annofabcli/task_history/download_task_history_json.py +4 -6
  173. annofabcli/task_history/list_all_task_history.py +5 -6
  174. annofabcli/task_history/list_task_history.py +3 -4
  175. annofabcli/task_history/subcommand_task_history.py +1 -3
  176. annofabcli/task_history_event/download_task_history_event_json.py +4 -6
  177. annofabcli/task_history_event/list_all_task_history_event.py +6 -6
  178. annofabcli/task_history_event/list_worktime.py +15 -15
  179. annofabcli/task_history_event/subcommand_task_history_event.py +1 -2
  180. {annofabcli-1.111.1.dist-info → annofabcli-1.112.0.dist-info}/METADATA +9 -15
  181. annofabcli-1.112.0.dist-info/RECORD +229 -0
  182. {annofabcli-1.111.1.dist-info → annofabcli-1.112.0.dist-info}/WHEEL +1 -1
  183. annofabcli-1.111.1.dist-info/RECORD +0 -228
  184. {annofabcli-1.111.1.dist-info → annofabcli-1.112.0.dist-info}/entry_points.txt +0 -0
  185. {annofabcli-1.111.1.dist-info → annofabcli-1.112.0.dist-info}/licenses/LICENSE +0 -0
annofabcli/__main__.py CHANGED
@@ -4,7 +4,6 @@ import argparse
4
4
  import copy
5
5
  import logging
6
6
  import sys
7
- from typing import Optional
8
7
 
9
8
  import pandas
10
9
 
@@ -65,7 +64,7 @@ def mask_sensitive_value_in_argv(argv: list[str]) -> list[str]:
65
64
  return tmp_argv
66
65
 
67
66
 
68
- def main(arguments: Optional[list[str]] = None) -> None:
67
+ def main(arguments: list[str] | None = None) -> None:
69
68
  """
70
69
  annofabcliコマンドのメイン処理
71
70
  注意: `deprecated`なツールは、サブコマンド化しない。
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass
4
- from typing import Any, Optional, Union
4
+ from typing import Any
5
5
 
6
6
  import more_itertools
7
7
  from annofabapi.dataclass.annotation import AdditionalDataV1
@@ -9,7 +9,7 @@ from annofabapi.models import AdditionalDataDefinitionType
9
9
  from annofabapi.util.annotation_specs import get_english_message
10
10
  from dataclasses_json import DataClassJsonMixin
11
11
 
12
- AttributeValue = Optional[Union[str, int, bool]]
12
+ AttributeValue = str | int | bool | None
13
13
  """属性値の型情報"""
14
14
 
15
15
 
@@ -138,7 +138,7 @@ def _get_additional_data_v2(additional_data: dict[str, Any], attribute_value: At
138
138
  return {"definition_id": additional_data_definition_id, "value": result_value}
139
139
 
140
140
 
141
- def convert_attributes_from_cli_to_api(attributes: dict[str, AttributeValue], annotation_specs: dict[str, Any], *, label_id: Optional[str] = None) -> list[AdditionalDataV1]:
141
+ def convert_attributes_from_cli_to_api(attributes: dict[str, AttributeValue], annotation_specs: dict[str, Any], *, label_id: str | None = None) -> list[AdditionalDataV1]:
142
142
  """
143
143
  CLI用の属性をAPI用の属性に変換します。
144
144
 
@@ -193,7 +193,7 @@ def convert_attributes_from_cli_to_api(attributes: dict[str, AttributeValue], an
193
193
  return attributes_for_webapi
194
194
 
195
195
 
196
- def convert_attributes_from_cli_to_additional_data_list_v2(attributes: dict[str, AttributeValue], annotation_specs: dict[str, Any], *, label_id: Optional[str] = None) -> list[dict[str, Any]]:
196
+ def convert_attributes_from_cli_to_additional_data_list_v2(attributes: dict[str, AttributeValue], annotation_specs: dict[str, Any], *, label_id: str | None = None) -> list[dict[str, Any]]:
197
197
  """
198
198
  CLI用の属性情報をAPI用の `AdditionalDataV2` に相当するdictに変換します。
199
199
 
@@ -254,10 +254,10 @@ class AnnotationQueryForCLI(DataClassJsonMixin):
254
254
  CLIでアノテーションを絞り込むためのクエリ。
255
255
  """
256
256
 
257
- label: Optional[str] = None
257
+ label: str | None = None
258
258
  """ラベル名(英語)"""
259
259
 
260
- attributes: Optional[dict[str, AttributeValue]] = None
260
+ attributes: dict[str, AttributeValue] | None = None
261
261
  """
262
262
  keyが属性名(英語),valueが属性値のdict。
263
263
  属性が排他選択の場合、属性値は選択肢名(英語)。
@@ -279,8 +279,8 @@ class AnnotationQueryForCLI(DataClassJsonMixin):
279
279
  dict[str,Any]: WebAPIのquery_paramsに渡すdict
280
280
  """
281
281
  assert self.label is not None or self.attributes is not None
282
- label_id: Optional[str] = None
283
- attributes_for_webapi: Optional[list[AdditionalDataV1]] = None
282
+ label_id: str | None = None
283
+ attributes_for_webapi: list[AdditionalDataV1] | None = None
284
284
 
285
285
  if self.label is not None:
286
286
  tmp = [e for e in annotation_specs["labels"] if get_english_message(e["label_name"]) == self.label]
@@ -309,10 +309,10 @@ class AnnotationQueryForAPI(DataClassJsonMixin):
309
309
  https://annofab.com/docs/api/#tag/x-data-types/AnnotationQuery に対応しています。
310
310
  """
311
311
 
312
- label_id: Optional[str] = None
312
+ label_id: str | None = None
313
313
  """ラベルID"""
314
314
 
315
- attributes: Optional[list[AdditionalDataV1]] = None
315
+ attributes: list[AdditionalDataV1] | None = None
316
316
  """属性IDと属性値のList"""
317
317
 
318
318
  def __post_init__(self) -> None:
@@ -8,7 +8,7 @@ import multiprocessing
8
8
  import sys
9
9
  from enum import Enum
10
10
  from pathlib import Path
11
- from typing import Any, Optional
11
+ from typing import Any
12
12
 
13
13
  import annofabapi
14
14
  from annofabapi.dataclass.task import Task
@@ -58,7 +58,7 @@ class ChangeAnnotationAttributesMain(CommandLineWithConfirm):
58
58
 
59
59
  self.dump_annotation_obj = DumpAnnotationMain(service, project_id)
60
60
 
61
- def change_annotation_attributes(self, annotation_list: list[dict[str, Any]], additional_data_list: list[dict[str, Any]]) -> Optional[list[dict[str, Any]]]:
61
+ def change_annotation_attributes(self, annotation_list: list[dict[str, Any]], additional_data_list: list[dict[str, Any]]) -> list[dict[str, Any]] | None:
62
62
  """
63
63
  アノテーション属性値を変更する。
64
64
 
@@ -112,8 +112,8 @@ class ChangeAnnotationAttributesMain(CommandLineWithConfirm):
112
112
  annotation_query: AnnotationQueryForAPI,
113
113
  additional_data_list: list[dict[str, Any]],
114
114
  *,
115
- backup_dir: Optional[Path] = None,
116
- task_index: Optional[int] = None,
115
+ backup_dir: Path | None = None,
116
+ task_index: int | None = None,
117
117
  ) -> tuple[bool, int]:
118
118
  """
119
119
  タスクに対してアノテーション属性値を変更する。
@@ -170,7 +170,7 @@ class ChangeAnnotationAttributesMain(CommandLineWithConfirm):
170
170
  annotation_query: AnnotationQueryForAPI,
171
171
  additional_data_list: list[dict[str, Any]],
172
172
  *,
173
- backup_dir: Optional[Path] = None,
173
+ backup_dir: Path | None = None,
174
174
  ) -> tuple[bool, int]:
175
175
  task_index, task_id = tpl
176
176
  try:
@@ -191,8 +191,8 @@ class ChangeAnnotationAttributesMain(CommandLineWithConfirm):
191
191
  annotation_query: AnnotationQueryForAPI,
192
192
  additional_data_list: list[dict[str, Any]],
193
193
  *,
194
- backup_dir: Optional[Path] = None,
195
- parallelism: Optional[int] = None,
194
+ backup_dir: Path | None = None,
195
+ parallelism: int | None = None,
196
196
  ) -> None:
197
197
  """
198
198
  複数のタスクに対してアノテーションの属性値を変更します。
@@ -272,7 +272,7 @@ class ChangeAttributesOfAnnotation(CommandLine):
272
272
  return annotation_query_for_cli.to_query_for_api(annotation_specs)
273
273
 
274
274
  @classmethod
275
- def get_additional_data_list_from_cli_attributes(cls, str_attributes: str, annotation_specs: dict[str, Any], label_id: Optional[str]) -> list[dict[str, Any]]:
275
+ def get_additional_data_list_from_cli_attributes(cls, str_attributes: str, annotation_specs: dict[str, Any], label_id: str | None) -> list[dict[str, Any]]:
276
276
  """
277
277
  CLIから受け取った`--attributes`の値から、APIに渡す属性情報(`AdditionalDataListV2`)を返します。
278
278
  """
@@ -383,7 +383,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
383
383
  parser.set_defaults(subcommand_func=main)
384
384
 
385
385
 
386
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
386
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
387
387
  subcommand_name = "change_attributes"
388
388
  subcommand_help = "アノテーションの属性値を変更します。"
389
389
  description = (
@@ -6,7 +6,6 @@ import logging
6
6
  import sys
7
7
  from collections import defaultdict
8
8
  from pathlib import Path
9
- from typing import Optional, Union
10
9
 
11
10
  import annofabapi
12
11
  import pandas
@@ -30,7 +29,7 @@ from annofabcli.common.facade import AnnofabApiFacade
30
29
  logger = logging.getLogger(__name__)
31
30
 
32
31
 
33
- Attributes = dict[str, Optional[Union[str, int, bool]]]
32
+ Attributes = dict[str, str | int | bool | None]
34
33
  """属性情報"""
35
34
 
36
35
 
@@ -66,7 +65,7 @@ class ChangeAnnotationAttributesPerAnnotationMain(CommandLineWithConfirm):
66
65
  project_id: str,
67
66
  is_force: bool,
68
67
  all_yes: bool,
69
- backup_dir: Optional[Path] = None,
68
+ backup_dir: Path | None = None,
70
69
  ) -> None:
71
70
  self.service = service
72
71
  self.project_id = project_id
@@ -314,7 +313,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
314
313
  parser.set_defaults(subcommand_func=main)
315
314
 
316
315
 
317
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
316
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
318
317
  subcommand_name = "change_attributes_per_annotation"
319
318
  subcommand_help = "各アノテーションの属性値を変更します。"
320
319
  epilog = "オーナロールまたはチェッカーロールを持つユーザで実行してください。"
@@ -8,7 +8,7 @@ import multiprocessing
8
8
  import sys
9
9
  from dataclasses import dataclass
10
10
  from pathlib import Path
11
- from typing import Any, Optional
11
+ from typing import Any
12
12
 
13
13
  import annofabapi
14
14
  from annofabapi.models import ProjectMemberRole, SingleAnnotation, TaskStatus
@@ -34,7 +34,7 @@ logger = logging.getLogger(__name__)
34
34
 
35
35
  @dataclass
36
36
  class AnnotationDetailForCli(DataClassJsonMixin):
37
- is_protected: Optional[bool] = None
37
+ is_protected: bool | None = None
38
38
 
39
39
 
40
40
  class ChangePropertiesOfAnnotationMain(CommandLineWithConfirm):
@@ -113,7 +113,7 @@ class ChangePropertiesOfAnnotationMain(CommandLineWithConfirm):
113
113
  for annotation in annotations:
114
114
  _to_request_body_elm(annotation)
115
115
 
116
- def get_annotation_list_for_task(self, task_id: str, annotation_query: Optional[AnnotationQueryForAPI]) -> list[dict[str, Any]]:
116
+ def get_annotation_list_for_task(self, task_id: str, annotation_query: AnnotationQueryForAPI | None) -> list[dict[str, Any]]:
117
117
  """
118
118
  タスク内のアノテーション一覧を取得する。
119
119
 
@@ -136,9 +136,9 @@ class ChangePropertiesOfAnnotationMain(CommandLineWithConfirm):
136
136
  self,
137
137
  task_id: str,
138
138
  properties: AnnotationDetailForCli,
139
- annotation_query: Optional[AnnotationQueryForAPI] = None,
140
- backup_dir: Optional[Path] = None,
141
- task_index: Optional[int] = None,
139
+ annotation_query: AnnotationQueryForAPI | None = None,
140
+ backup_dir: Path | None = None,
141
+ task_index: int | None = None,
142
142
  ) -> bool:
143
143
  """
144
144
  タスクに対してアノテーションのプロパティを変更する。
@@ -162,7 +162,7 @@ class ChangePropertiesOfAnnotationMain(CommandLineWithConfirm):
162
162
  logger.info(f"タスク'{task_id}'は作業中または受入完了状態のため、アノテーションプロパティの変更をスキップします。 status={dict_task['status']}")
163
163
  return False
164
164
 
165
- old_account_id: Optional[str] = dict_task["account_id"]
165
+ old_account_id: str | None = dict_task["account_id"]
166
166
  changed_operator = False
167
167
 
168
168
  if self.is_force:
@@ -217,8 +217,8 @@ class ChangePropertiesOfAnnotationMain(CommandLineWithConfirm):
217
217
  self,
218
218
  tpl: tuple[int, str],
219
219
  properties: AnnotationDetailForCli,
220
- annotation_query: Optional[AnnotationQueryForAPI] = None,
221
- backup_dir: Optional[Path] = None,
220
+ annotation_query: AnnotationQueryForAPI | None = None,
221
+ backup_dir: Path | None = None,
222
222
  ) -> bool:
223
223
  task_index, task_id = tpl
224
224
  try:
@@ -237,9 +237,9 @@ class ChangePropertiesOfAnnotationMain(CommandLineWithConfirm):
237
237
  self,
238
238
  task_id_list: list[str],
239
239
  properties: AnnotationDetailForCli,
240
- annotation_query: Optional[AnnotationQueryForAPI] = None,
241
- backup_dir: Optional[Path] = None,
242
- parallelism: Optional[int] = None,
240
+ annotation_query: AnnotationQueryForAPI | None = None,
241
+ backup_dir: Path | None = None,
242
+ parallelism: int | None = None,
243
243
  ):
244
244
  project_title = self.facade.get_project_title(self.project_id)
245
245
  logger.info(f"プロジェクト'{project_title}'に対して、タスク{len(task_id_list)} 件のアノテーションのプロパティを変更します")
@@ -396,7 +396,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
396
396
  parser.set_defaults(subcommand_func=main)
397
397
 
398
398
 
399
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
399
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
400
400
  subcommand_name = "change_properties"
401
401
  subcommand_help = "アノテーションのプロパティを変更します。"
402
402
  description = (
@@ -7,7 +7,7 @@ import multiprocessing
7
7
  import sys
8
8
  from abc import ABC, abstractmethod
9
9
  from dataclasses import dataclass
10
- from typing import Any, Optional
10
+ from typing import Any
11
11
 
12
12
  import annofabapi
13
13
  from annofabapi.models import ProjectMemberRole
@@ -79,7 +79,7 @@ def parse_copy_target(str_copy_target: str) -> CopyTarget:
79
79
  * `task1/input5:task2/input6`
80
80
  """
81
81
 
82
- def _parse_with_slash(target: str) -> tuple[str, Optional[str]]:
82
+ def _parse_with_slash(target: str) -> tuple[str, str | None]:
83
83
  tmp = target.split("/")
84
84
  if len(tmp) == 1:
85
85
  return (tmp[0], None)
@@ -163,7 +163,7 @@ class CopyAnnotationMain(CommandLineWithConfirm):
163
163
 
164
164
  copy_count = 0
165
165
 
166
- for src_input_data_id, dest_input_data_id in zip(src_input_data_id_list, dest_input_data_id_list):
166
+ for src_input_data_id, dest_input_data_id in zip(src_input_data_id_list, dest_input_data_id_list, strict=False):
167
167
  try:
168
168
  result = self.copy_annotation_by_input_data(
169
169
  CopyTargetByInputData(
@@ -304,7 +304,7 @@ class CopyAnnotationMain(CommandLineWithConfirm):
304
304
  logger.warning(f"'{copy_target.src}'のアノテーションを'{copy_target.dest}'へコピーするのに失敗しました。", exc_info=True)
305
305
  return False
306
306
 
307
- def copy_annotations(self, copy_target_list: list[CopyTarget], *, parallelism: Optional[int] = None): # noqa: ANN201
307
+ def copy_annotations(self, copy_target_list: list[CopyTarget], *, parallelism: int | None = None): # noqa: ANN201
308
308
  if parallelism is not None:
309
309
  with multiprocessing.Pool(parallelism) as pool:
310
310
  result_bool_list = pool.map(self.copy_annotation_wrapper, copy_target_list)
@@ -414,7 +414,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
414
414
  parser.set_defaults(subcommand_func=main)
415
415
 
416
416
 
417
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
417
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
418
418
  subcommand_name = "copy"
419
419
  subcommand_help = "アノテーションをコピーします."
420
420
  description = "タスク単位または入力データ単位で、アノテーションをコピーします。"
@@ -4,7 +4,7 @@ import argparse
4
4
  import logging
5
5
  import multiprocessing
6
6
  import sys
7
- from typing import Any, Optional
7
+ from typing import Any
8
8
 
9
9
  import annofabapi
10
10
  from annofabapi.models import DefaultAnnotationType, ProjectMemberRole, TaskStatus
@@ -50,7 +50,7 @@ class CreateClassificationAnnotationMain(CommandLineWithConfirm):
50
50
  my_member, _ = self.service.api.get_my_member_in_project(project_id)
51
51
  self.my_project_member_role = ProjectMemberRole(my_member["member_role"])
52
52
 
53
- def _validate_and_prepare_task(self, task_id: str) -> tuple[Optional[dict[str, Any]], bool, Optional[str]]:
53
+ def _validate_and_prepare_task(self, task_id: str) -> tuple[dict[str, Any] | None, bool, str | None]:
54
54
  """
55
55
  タスクの検証と準備を行う
56
56
 
@@ -76,7 +76,7 @@ class CreateClassificationAnnotationMain(CommandLineWithConfirm):
76
76
  )
77
77
  return None, False, None
78
78
 
79
- old_account_id: Optional[str] = None
79
+ old_account_id: str | None = None
80
80
  changed_operator = False
81
81
 
82
82
  if self.is_change_operator_to_me:
@@ -216,7 +216,7 @@ class CreateClassificationAnnotationMain(CommandLineWithConfirm):
216
216
 
217
217
  return created_count
218
218
 
219
- def execute_task(self, task_id: str, labels: list[str], task_index: Optional[int] = None) -> bool:
219
+ def execute_task(self, task_id: str, labels: list[str], task_index: int | None = None) -> bool:
220
220
  """
221
221
  1個のタスクに対して全体アノテーションを作成する。
222
222
 
@@ -260,7 +260,7 @@ class CreateClassificationAnnotationMain(CommandLineWithConfirm):
260
260
  else:
261
261
  return created_count > 0
262
262
 
263
- def main(self, task_ids: list[str], labels: list[str], parallelism: Optional[int] = None) -> None:
263
+ def main(self, task_ids: list[str], labels: list[str], parallelism: int | None = None) -> None:
264
264
  """
265
265
  メイン処理
266
266
 
@@ -392,7 +392,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
392
392
  parser.set_defaults(subcommand_func=main)
393
393
 
394
394
 
395
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
395
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
396
396
  subcommand_name = "create_classification"
397
397
  subcommand_help = "全体アノテーション(Classification)を作成します。"
398
398
  description = (
@@ -7,7 +7,7 @@ import sys
7
7
  from collections import defaultdict
8
8
  from dataclasses import dataclass
9
9
  from pathlib import Path
10
- from typing import Any, Optional
10
+ from typing import Any
11
11
 
12
12
  import annofabapi
13
13
  import pandas
@@ -87,7 +87,7 @@ class DeleteAnnotationMain(CommandLineWithConfirm):
87
87
  request_body = [_to_request_body_elm(annotation) for annotation in annotation_list]
88
88
  self.service.api.batch_update_annotations(self.project_id, request_body=request_body)
89
89
 
90
- def get_annotation_list_for_task(self, task_id: str, annotation_query: Optional[AnnotationQueryForAPI]) -> list[dict[str, Any]]:
90
+ def get_annotation_list_for_task(self, task_id: str, annotation_query: AnnotationQueryForAPI | None) -> list[dict[str, Any]]:
91
91
  """
92
92
  タスク内のアノテーション一覧を取得する。
93
93
 
@@ -109,8 +109,8 @@ class DeleteAnnotationMain(CommandLineWithConfirm):
109
109
  def delete_annotation_for_task(
110
110
  self,
111
111
  task_id: str,
112
- annotation_query: Optional[AnnotationQueryForAPI] = None,
113
- backup_dir: Optional[Path] = None,
112
+ annotation_query: AnnotationQueryForAPI | None = None,
113
+ backup_dir: Path | None = None,
114
114
  ) -> None:
115
115
  """
116
116
  タスクに対してアノテーションを削除する
@@ -159,8 +159,8 @@ class DeleteAnnotationMain(CommandLineWithConfirm):
159
159
  def delete_annotation_for_task_list(
160
160
  self,
161
161
  task_id_list: list[str],
162
- annotation_query: Optional[AnnotationQueryForAPI] = None,
163
- backup_dir: Optional[Path] = None,
162
+ annotation_query: AnnotationQueryForAPI | None = None,
163
+ backup_dir: Path | None = None,
164
164
  ) -> None:
165
165
  project_title = self.facade.get_project_title(self.project_id)
166
166
  logger.info(f"プロジェクト'{project_title}'に対して、タスク{len(task_id_list)} 件のアノテーションを削除します。")
@@ -278,7 +278,7 @@ class DeleteAnnotationMain(CommandLineWithConfirm):
278
278
  def delete_annotation_by_id_list(
279
279
  self,
280
280
  annotation_list: list[DeletedAnnotationInfo],
281
- backup_dir: Optional[Path] = None,
281
+ backup_dir: Path | None = None,
282
282
  ) -> None:
283
283
  """
284
284
  task_id, input_data_id, annotation_id のリストで指定されたアノテーションのみ削除する
@@ -492,7 +492,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
492
492
  parser.set_defaults(subcommand_func=main)
493
493
 
494
494
 
495
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
495
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
496
496
  subcommand_name = "delete"
497
497
  subcommand_help = "アノテーションを削除します。"
498
498
  description = (
@@ -1,11 +1,9 @@
1
1
  import argparse
2
2
  import logging
3
3
  from pathlib import Path
4
- from typing import Optional
5
4
 
6
5
  from annofabapi.models import ProjectMemberRole
7
6
 
8
- import annofabcli
9
7
  import annofabcli.common.cli
10
8
  from annofabcli.common.cli import CommandLine, build_annofabapi_resource_and_login
11
9
  from annofabcli.common.download import DownloadingFile
@@ -67,7 +65,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
67
65
  parser.set_defaults(subcommand_func=main)
68
66
 
69
67
 
70
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
68
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
71
69
  subcommand_name = "download"
72
70
  subcommand_help = "アノテーションZIPをダウンロードします。"
73
71
  description = "アノテーションZIPをダウンロードします。"
@@ -6,7 +6,7 @@ import json
6
6
  import logging
7
7
  import multiprocessing
8
8
  from pathlib import Path
9
- from typing import Any, Optional
9
+ from typing import Any
10
10
 
11
11
  import annofabapi
12
12
  from annofabapi.models import AnnotationDataHoldingType
@@ -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, *, task_history_id: Optional[str] = None) -> None:
66
+ def dump_annotation_for_input_data(self, task_id: str, input_data_id: str, task_dir: Path, *, task_history_id: str | None = None) -> None:
67
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, task_history_index: Optional[int] = None) -> bool:
71
+ def dump_annotation_for_task(self, task_id: str, output_dir: Path, *, task_index: int | None = None, task_history_index: int | None = None) -> bool:
72
72
  """
73
73
  タスク配下のアノテーションをファイルに保存する。
74
74
 
@@ -85,7 +85,7 @@ class DumpAnnotationMain:
85
85
  logger.warning(f"task_id = '{task_id}' のタスクは存在しません。スキップします。")
86
86
  return False
87
87
 
88
- task_history_id: Optional[str] = None
88
+ task_history_id: str | None = None
89
89
  if task_history_index is not None:
90
90
  task_histories, _ = self.service.api.get_task_histories(self.project_id, task_id)
91
91
  if task_history_index >= len(task_histories):
@@ -109,7 +109,7 @@ class DumpAnnotationMain:
109
109
 
110
110
  return not is_failure
111
111
 
112
- def dump_annotation_for_task_wrapper(self, tpl: tuple[int, str], output_dir: Path, *, task_history_index: Optional[int] = None) -> bool:
112
+ def dump_annotation_for_task_wrapper(self, tpl: tuple[int, str], output_dir: Path, *, task_history_index: int | None = None) -> bool:
113
113
  task_index, task_id = tpl
114
114
  try:
115
115
  return self.dump_annotation_for_task(task_id, output_dir=output_dir, task_index=task_index, task_history_index=task_history_index)
@@ -117,7 +117,7 @@ class DumpAnnotationMain:
117
117
  logger.warning(f"タスク'{task_id}'のアノテーション情報のダンプに失敗しました。", exc_info=True)
118
118
  return False
119
119
 
120
- def dump_annotation(self, task_id_list: list[str], output_dir: Path, *, task_history_index: Optional[int] = None, parallelism: Optional[int] = None) -> None:
120
+ def dump_annotation(self, task_id_list: list[str], output_dir: Path, *, task_history_index: int | None = None, parallelism: int | None = None) -> None:
121
121
  project_title = self.facade.get_project_title(self.project_id)
122
122
  logger.info(f"プロジェクト'{project_title}'に対して、タスク{len(task_id_list)} 件のアノテーションをファイルに保存します。")
123
123
 
@@ -191,7 +191,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
191
191
  parser.set_defaults(subcommand_func=main)
192
192
 
193
193
 
194
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
194
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
195
195
  subcommand_name = "dump"
196
196
  subcommand_help = "``annotation restore`` コマンドに読み込ませることができるアノテーション情報を出力します。"
197
197
  description = "``annotation restore`` コマンドに読み込ませることができるアノテーション情報を出力します。アノテーションのバックアップ目的で利用することを想定しています。"
@@ -10,7 +10,7 @@ import zipfile
10
10
  from collections.abc import Iterator
11
11
  from dataclasses import dataclass
12
12
  from pathlib import Path
13
- from typing import Any, Optional, Union
13
+ from typing import Any
14
14
 
15
15
  import annofabapi
16
16
  import ulid
@@ -60,10 +60,10 @@ class ImportedSimpleAnnotationDetail(DataClassJsonMixin):
60
60
  data: dict[str, Any]
61
61
  """"""
62
62
 
63
- attributes: Optional[dict[str, Union[str, bool, int]]] = None
63
+ attributes: dict[str, str | bool | int] | None = None
64
64
  """属性情報。キーは属性の名前、値は属性の値。 """
65
65
 
66
- annotation_id: Optional[str] = None
66
+ annotation_id: str | None = None
67
67
  """アノテーションID"""
68
68
 
69
69
 
@@ -152,13 +152,13 @@ class AnnotationConverter:
152
152
 
153
153
  def _convert_attribute_value( # noqa: PLR0911, PLR0912
154
154
  self,
155
- attribute_value: Optional[Union[str, int, bool]], # noqa: FBT001
155
+ attribute_value: str | int | bool | None, # 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
- ) -> Optional[dict[str, Any]]:
161
+ ) -> dict[str, Any] | None:
162
162
  """
163
163
  JSONに記載されている属性値を、APIに渡すための `AdditionalDataValue`スキーマに変換します。
164
164
 
@@ -235,7 +235,7 @@ class AnnotationConverter:
235
235
  else:
236
236
  assert_noreturn(additional_data_type)
237
237
 
238
- def convert_attributes(self, attributes: dict[str, Any], *, label_name: Optional[str] = None, log_message_suffix: str = "") -> list[dict[str, Any]]:
238
+ def convert_attributes(self, attributes: dict[str, Any], *, label_name: str | None = None, log_message_suffix: str = "") -> list[dict[str, Any]]:
239
239
  """
240
240
  インポート対象のアノテーションJSONに格納されている`attributes`を`AdditionalDataListV2`のlistに変換します。
241
241
 
@@ -339,7 +339,7 @@ class AnnotationConverter:
339
339
  details: list[ImportedSimpleAnnotationDetail],
340
340
  old_details: list[dict[str, Any]],
341
341
  *,
342
- updated_datetime: Optional[str] = None,
342
+ updated_datetime: str | None = None,
343
343
  ) -> dict[str, Any]:
344
344
  """
345
345
  アノテーションJSONに記載されたアノテーション情報を、`put_annotation` APIに渡す形式に変換します。
@@ -487,7 +487,7 @@ class ImportAnnotationMain(CommandLineWithConfirm):
487
487
 
488
488
  return success_input_data_count, success_annotation_count
489
489
 
490
- def execute_task(self, task_parser: SimpleAnnotationParserByTask, task_index: Optional[int] = None) -> bool:
490
+ def execute_task(self, task_parser: SimpleAnnotationParserByTask, task_index: int | None = None) -> bool:
491
491
  """
492
492
  1個のタスクに対してアノテーションを登録する。
493
493
 
@@ -514,7 +514,7 @@ class ImportAnnotationMain(CommandLineWithConfirm):
514
514
  logger.info(f"タスク'{task_id}'は作業中または受入完了状態のため、インポートをスキップします。 status={task['status']}")
515
515
  return False
516
516
 
517
- old_account_id: Optional[str] = None
517
+ old_account_id: str | None = None
518
518
  changed_operator = False
519
519
  if self.is_force:
520
520
  if not can_put_annotation(task, self.service.api.account_id):
@@ -566,8 +566,8 @@ class ImportAnnotationMain(CommandLineWithConfirm):
566
566
  def main(
567
567
  self,
568
568
  iter_task_parser: Iterator[SimpleAnnotationParserByTask],
569
- target_task_ids: Optional[set[str]] = None,
570
- parallelism: Optional[int] = None,
569
+ target_task_ids: set[str] | None = None,
570
+ parallelism: int | None = None,
571
571
  ) -> None:
572
572
  def get_iter_task_parser_from_task_ids(_iter_task_parser: Iterator[SimpleAnnotationParserByTask], _target_task_ids: set[str]) -> Iterator[SimpleAnnotationParserByTask]:
573
573
  for task_parser in _iter_task_parser:
@@ -746,7 +746,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
746
746
  parser.set_defaults(subcommand_func=main)
747
747
 
748
748
 
749
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
749
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
750
750
  subcommand_name = "import"
751
751
  subcommand_help = "アノテーションをインポートします。"
752
752
  description = "アノテーションをインポートします。アノテーションのフォーマットは、Simpleアノテーションと同じフォルダ構成のzipファイルまたはディレクトリです。ただし、作業中/完了状態のタスクはインポートできません。" # noqa: E501
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  import argparse
4
4
  import logging
5
5
  import sys
6
- from typing import Any, Optional
6
+ from typing import Any
7
7
 
8
8
  import annofabapi
9
9
  import pandas
@@ -52,10 +52,10 @@ class ListAnnotationMain:
52
52
  def get_annotation_list(
53
53
  self,
54
54
  project_id: str,
55
- annotation_query: Optional[AnnotationQueryForAPI],
55
+ annotation_query: AnnotationQueryForAPI | None,
56
56
  *,
57
- task_id: Optional[str] = None,
58
- input_data_id: Optional[str] = None,
57
+ task_id: str | None = None,
58
+ input_data_id: str | None = None,
59
59
  ) -> list[SingleAnnotation]:
60
60
  dict_query = {}
61
61
  if annotation_query is not None:
@@ -73,10 +73,10 @@ class ListAnnotationMain:
73
73
  def get_all_annotation_list(
74
74
  self,
75
75
  project_id: str,
76
- annotation_query: Optional[AnnotationQueryForAPI],
76
+ annotation_query: AnnotationQueryForAPI | None,
77
77
  *,
78
- task_id_list: Optional[list[str]],
79
- input_data_id_list: Optional[list[str]],
78
+ task_id_list: list[str] | None,
79
+ input_data_id_list: list[str] | None,
80
80
  ) -> list[SingleAnnotation]:
81
81
  assert task_id_list is None or input_data_id_list is None, "task_id_listとinput_data_listのどちらかはNoneにしてください。"
82
82
 
@@ -252,7 +252,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
252
252
  parser.set_defaults(subcommand_func=main)
253
253
 
254
254
 
255
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
255
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
256
256
  subcommand_name = "list"
257
257
  subcommand_help = "アノテーションの一覧を出力します。"
258
258
  description = "アノテーションの一覧を出力します。"