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
@@ -7,13 +7,12 @@ import tempfile
7
7
  from collections.abc import Collection
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 pandas
13
13
  from annofabapi.models import InputDataType, ProjectMemberRole
14
14
  from dataclasses_json import DataClassJsonMixin
15
15
 
16
- import annofabcli
17
16
  import annofabcli.common.cli
18
17
  from annofabcli.common.annofab.annotation_zip import lazy_parse_simple_annotation_by_input_data
19
18
  from annofabcli.common.cli import COMMAND_LINE_ERROR_STATUS_CODE, ArgumentParser, CommandLine, build_annofabapi_resource_and_login, get_list_from_args
@@ -40,7 +39,7 @@ class RangeAnnotationInfo(DataClassJsonMixin):
40
39
  input_data_id: str
41
40
  input_data_name: str
42
41
 
43
- updated_datetime: Optional[str]
42
+ updated_datetime: str | None
44
43
  """アノテーションJSONに格納されているアノテーションの更新日時"""
45
44
 
46
45
  label: str
@@ -48,9 +47,10 @@ class RangeAnnotationInfo(DataClassJsonMixin):
48
47
  begin_second: float
49
48
  end_second: float
50
49
  duration_second: float
50
+ attributes: dict[str, str | int | bool]
51
51
 
52
52
 
53
- def get_range_annotation_info_list(simple_annotation: dict[str, Any], *, target_label_names: Optional[Collection[str]] = None) -> list[RangeAnnotationInfo]:
53
+ def get_range_annotation_info_list(simple_annotation: dict[str, Any], *, target_label_names: Collection[str] | None = None) -> list[RangeAnnotationInfo]:
54
54
  result = []
55
55
  target_label_names_set = set(target_label_names) if target_label_names is not None else None
56
56
  for detail in simple_annotation["details"]:
@@ -81,6 +81,7 @@ def get_range_annotation_info_list(simple_annotation: dict[str, Any], *, target_
81
81
  end_second=end_second,
82
82
  duration_second=duration_second,
83
83
  updated_datetime=simple_annotation["updated_datetime"],
84
+ attributes=detail["attributes"],
84
85
  )
85
86
  )
86
87
 
@@ -90,9 +91,9 @@ def get_range_annotation_info_list(simple_annotation: dict[str, Any], *, target_
90
91
  def get_range_annotation_info_list_from_annotation_path(
91
92
  annotation_path: Path,
92
93
  *,
93
- target_task_ids: Optional[Collection[str]] = None,
94
- task_query: Optional[TaskQuery] = None,
95
- target_label_names: Optional[Collection[str]] = None,
94
+ target_task_ids: Collection[str] | None = None,
95
+ task_query: TaskQuery | None = None,
96
+ target_label_names: Collection[str] | None = None,
96
97
  ) -> list[RangeAnnotationInfo]:
97
98
  range_annotation_list = []
98
99
  target_task_ids = set(target_task_ids) if target_task_ids is not None else None
@@ -114,7 +115,7 @@ def get_range_annotation_info_list_from_annotation_path(
114
115
  def create_df(
115
116
  range_annotation_list: list[RangeAnnotationInfo],
116
117
  ) -> pandas.DataFrame:
117
- columns = [
118
+ base_columns = [
118
119
  "project_id",
119
120
  "task_id",
120
121
  "task_status",
@@ -129,7 +130,16 @@ def create_df(
129
130
  "end_second",
130
131
  "duration_second",
131
132
  ]
132
- df = pandas.DataFrame([e.to_dict(encode_json=True) for e in range_annotation_list], columns=columns)
133
+
134
+ if not range_annotation_list:
135
+ # 空のリストの場合は、base_columnsのみで空のDataFrameを返す
136
+ return pandas.DataFrame(columns=base_columns)
137
+
138
+ tmp_range_annotation_list = [e.to_dict(encode_json=True) for e in range_annotation_list]
139
+ df = pandas.json_normalize(tmp_range_annotation_list)
140
+
141
+ attribute_columns = sorted(col for col in df.columns if col.startswith("attributes."))
142
+ columns = base_columns + attribute_columns
133
143
 
134
144
  return df[columns]
135
145
 
@@ -139,9 +149,9 @@ def print_range_annotation(
139
149
  output_file: Path,
140
150
  output_format: FormatArgument,
141
151
  *,
142
- target_task_ids: Optional[Collection[str]] = None,
143
- task_query: Optional[TaskQuery] = None,
144
- target_label_names: Optional[Collection[str]] = None,
152
+ target_task_ids: Collection[str] | None = None,
153
+ task_query: TaskQuery | None = None,
154
+ target_label_names: Collection[str] | None = None,
145
155
  ) -> None:
146
156
  range_annotation_list = get_range_annotation_info_list_from_annotation_path(
147
157
  annotation_path,
@@ -187,7 +197,7 @@ class ListRangeAnnotation(CommandLine):
187
197
  if not self.validate(args):
188
198
  sys.exit(COMMAND_LINE_ERROR_STATUS_CODE)
189
199
 
190
- project_id: Optional[str] = args.project_id
200
+ project_id: str | None = args.project_id
191
201
  if project_id is not None:
192
202
  super().validate_project(project_id, project_member_roles=[ProjectMemberRole.OWNER, ProjectMemberRole.TRAINING_DATA_USER])
193
203
  project, _ = self.service.api.get_project(project_id)
@@ -299,7 +309,7 @@ def main(args: argparse.Namespace) -> None:
299
309
  ListRangeAnnotation(service, facade, args).main()
300
310
 
301
311
 
302
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
312
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
303
313
  subcommand_name = "list_range_annotation"
304
314
  subcommand_help = "アノテーションZIPから動画プロジェクトの区間アノテーションの情報を出力します。"
305
315
  epilog = "アノテーションZIPをダウンロードする場合は、オーナロールまたはアノテーションユーザロールを持つユーザで実行してください。"
@@ -5,13 +5,12 @@ import tempfile
5
5
  from collections.abc import Collection
6
6
  from dataclasses import dataclass
7
7
  from pathlib import Path
8
- from typing import Any, Optional
8
+ from typing import Any
9
9
 
10
10
  import pandas
11
11
  from annofabapi.models import InputDataType, ProjectMemberRole
12
12
  from dataclasses_json import DataClassJsonMixin
13
13
 
14
- import annofabcli
15
14
  import annofabcli.common.cli
16
15
  from annofabcli.common.annofab.annotation_zip import lazy_parse_simple_annotation_by_input_data
17
16
  from annofabcli.common.cli import COMMAND_LINE_ERROR_STATUS_CODE, ArgumentParser, CommandLine, build_annofabapi_resource_and_login, get_list_from_args
@@ -38,7 +37,7 @@ class AnnotationSinglePointInfo(DataClassJsonMixin):
38
37
  input_data_id: str
39
38
  input_data_name: str
40
39
 
41
- updated_datetime: Optional[str]
40
+ updated_datetime: str | None
42
41
  """アノテーションJSONに格納されているアノテーションの更新日時"""
43
42
 
44
43
  label: str
@@ -46,7 +45,7 @@ class AnnotationSinglePointInfo(DataClassJsonMixin):
46
45
  point: dict[str, int]
47
46
 
48
47
 
49
- def get_annotation_single_point_info_list(simple_annotation: dict[str, Any], *, target_label_names: Optional[Collection[str]] = None) -> list[AnnotationSinglePointInfo]:
48
+ def get_annotation_single_point_info_list(simple_annotation: dict[str, Any], *, target_label_names: Collection[str] | None = None) -> list[AnnotationSinglePointInfo]:
50
49
  result = []
51
50
  target_label_names_set = set(target_label_names) if target_label_names is not None else None
52
51
  for detail in simple_annotation["details"]:
@@ -80,9 +79,9 @@ def get_annotation_single_point_info_list(simple_annotation: dict[str, Any], *,
80
79
  def get_annotation_single_point_info_list_from_annotation_path(
81
80
  annotation_path: Path,
82
81
  *,
83
- target_task_ids: Optional[Collection[str]] = None,
84
- task_query: Optional[TaskQuery] = None,
85
- target_label_names: Optional[Collection[str]] = None,
82
+ target_task_ids: Collection[str] | None = None,
83
+ task_query: TaskQuery | None = None,
84
+ target_label_names: Collection[str] | None = None,
86
85
  ) -> list[AnnotationSinglePointInfo]:
87
86
  annotation_point_list = []
88
87
  target_task_ids = set(target_task_ids) if target_task_ids is not None else None
@@ -147,9 +146,9 @@ def print_annotation_single_point(
147
146
  output_file: Path,
148
147
  output_format: FormatArgument,
149
148
  *,
150
- target_task_ids: Optional[Collection[str]] = None,
151
- task_query: Optional[TaskQuery] = None,
152
- target_label_names: Optional[Collection[str]] = None,
149
+ target_task_ids: Collection[str] | None = None,
150
+ task_query: TaskQuery | None = None,
151
+ target_label_names: Collection[str] | None = None,
153
152
  ) -> None:
154
153
  annotation_point_list = get_annotation_single_point_info_list_from_annotation_path(
155
154
  annotation_path,
@@ -195,7 +194,7 @@ class ListAnnotationSinglePoint(CommandLine):
195
194
  if not self.validate(args):
196
195
  sys.exit(COMMAND_LINE_ERROR_STATUS_CODE)
197
196
 
198
- project_id: Optional[str] = args.project_id
197
+ project_id: str | None = args.project_id
199
198
  if project_id is not None:
200
199
  super().validate_project(project_id, project_member_roles=[ProjectMemberRole.OWNER, ProjectMemberRole.TRAINING_DATA_USER])
201
200
  project, _ = self.service.api.get_project(project_id)
@@ -308,7 +307,7 @@ def main(args: argparse.Namespace) -> None:
308
307
  ListAnnotationSinglePoint(service, facade, args).main()
309
308
 
310
309
 
311
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
310
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
312
311
  subcommand_name = "list_single_point_annotation"
313
312
  subcommand_help = "アノテーションZIPから点アノテーションの座標情報を出力します。"
314
313
  epilog = "アノテーションZIPをダウンロードする場合は、オーナロールまたはアノテーションユーザロールを持つユーザで実行してください。"
@@ -1,9 +1,9 @@
1
1
  """サブコマンド annotation_zip"""
2
2
 
3
3
  import argparse
4
- from typing import Optional
5
4
 
6
5
  import annofabcli
6
+ from annofabcli.annotation_zip.list_annotation_3d_bounding_box import add_parser as add_parser_list_annotation_3d_bounding_box
7
7
  from annofabcli.annotation_zip.list_annotation_bounding_box_2d import add_parser as add_parser_list_annotation_bounding_box_2d
8
8
  from annofabcli.annotation_zip.list_range_annotation import add_parser as add_parser_list_range_annotation
9
9
  from annofabcli.annotation_zip.list_single_point_annotation import add_parser as add_parser_list_single_point_annotation
@@ -18,6 +18,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
18
18
  subparsers = parser.add_subparsers(dest="subcommand_name")
19
19
 
20
20
  # サブコマンドの定義
21
+ add_parser_list_annotation_3d_bounding_box(subparsers)
21
22
  add_parser_list_annotation_bounding_box_2d(subparsers)
22
23
  add_parser_list_range_annotation(subparsers)
23
24
  add_parser_list_single_point_annotation(subparsers)
@@ -25,7 +26,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
25
26
  # add_parser_validate_annotation(subparsers)
26
27
 
27
28
 
28
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
29
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
29
30
  """
30
31
  annotation_zipサブコマンドを追加する。
31
32
  Args:
@@ -6,9 +6,10 @@ import json
6
6
  import logging
7
7
  import sys
8
8
  import tempfile
9
+ from collections.abc import Callable
9
10
  from dataclasses import dataclass
10
11
  from pathlib import Path
11
- from typing import Any, Callable, Optional
12
+ from typing import Any
12
13
 
13
14
  import annofabapi
14
15
  import pandas
@@ -37,8 +38,8 @@ class ValidationResult:
37
38
  label_name: str
38
39
  function_name: str
39
40
  is_valid: bool
40
- error_message: Optional[str] = None
41
- detail_data: Optional[dict[str, Any]] = None
41
+ error_message: str | None = None
42
+ detail_data: dict[str, Any] | None = None
42
43
 
43
44
 
44
45
  class ValidationFunctionLoader:
@@ -101,7 +102,7 @@ class AnnotationValidator:
101
102
  service: annofabapi.Resource,
102
103
  project_id: str,
103
104
  validation_functions: dict[str, Callable[[dict[str, Any]], bool]],
104
- task_query: Optional[TaskQuery] = None,
105
+ task_query: TaskQuery | None = None,
105
106
  ) -> None:
106
107
  self.service = service
107
108
  self.project_id = project_id
@@ -233,7 +234,7 @@ class ValidateAnnotation(CommandLine):
233
234
  logger.info(f"読み込んだバリデーション関数: {list(validation_functions.keys())}")
234
235
 
235
236
  # タスク検索クエリ
236
- task_query: Optional[TaskQuery] = None
237
+ task_query: TaskQuery | None = None
237
238
  if args.task_query is not None:
238
239
  dict_task_query = annofabcli.common.cli.get_json_from_args(args.task_query)
239
240
  task_query = TaskQuery.from_dict(dict_task_query)
@@ -277,7 +278,7 @@ class ValidateAnnotation(CommandLine):
277
278
  # サマリー表示
278
279
  self._print_summary(results)
279
280
 
280
- def _output_results(self, results: list[ValidationResult], format_type: str, output_file: Optional[Path]) -> None:
281
+ def _output_results(self, results: list[ValidationResult], format_type: str, output_file: Path | None) -> None:
281
282
  """バリデーション結果を出力する"""
282
283
  if not results:
283
284
  logger.info("バリデーション結果はありません。")
@@ -382,7 +383,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
382
383
  parser.set_defaults(subcommand_func=main)
383
384
 
384
385
 
385
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
386
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
386
387
  subcommand_name = "validate"
387
388
  subcommand_help = "ユーザー定義のバリデーション関数でアノテーションZIPを検証します。"
388
389
  description = "ユーザー定義のバリデーション関数でアノテーションZIPを検証します。\nバリデーション関数は 'validate_' から始まる関数名で定義してください。"
@@ -3,14 +3,12 @@ import json
3
3
  import logging
4
4
  import multiprocessing
5
5
  import sys
6
- from typing import Any, Optional
6
+ from typing import Any
7
7
 
8
8
  import annofabapi
9
- import annofabapi.utils
10
9
  import requests
11
10
  from annofabapi.models import ProjectMemberRole, TaskStatus
12
11
 
13
- import annofabcli
14
12
  import annofabcli.common.cli
15
13
  from annofabcli.common.cli import (
16
14
  COMMAND_LINE_ERROR_STATUS_CODE,
@@ -106,7 +104,7 @@ class DeleteCommentMain(CommandLineWithConfirm):
106
104
  self,
107
105
  task_id: str,
108
106
  comment_ids_for_task: DeletedCommentsForTask,
109
- task_index: Optional[int] = None,
107
+ task_index: int | None = None,
110
108
  ) -> int:
111
109
  """
112
110
  タスクに対してコメントを削除します。
@@ -172,7 +170,7 @@ class DeleteCommentMain(CommandLineWithConfirm):
172
170
  def delete_comments_for_task_list(
173
171
  self,
174
172
  comment_ids_for_task_list: DeletedComments,
175
- parallelism: Optional[int] = None,
173
+ parallelism: int | None = None,
176
174
  ) -> None:
177
175
  comments_count = sum(len(e) for e in comment_ids_for_task_list.values())
178
176
  logger.info(f"削除対象のコメントを含むタスクの個数: {len(comment_ids_for_task_list)}, 削除対象のコメントを含む入力データ数: {comments_count}")
@@ -260,7 +258,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
260
258
  parser.set_defaults(subcommand_func=main)
261
259
 
262
260
 
263
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
261
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
264
262
  subcommand_name = "delete"
265
263
  subcommand_help = "コメントを削除します。"
266
264
  description = "コメントを削除します。\n【注意】他人の付けたコメントも削除できてしまいます。"
@@ -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
@@ -15,17 +13,17 @@ logger = logging.getLogger(__name__)
15
13
 
16
14
 
17
15
  class DownloadingComment(CommandLine):
18
- def download_comment_json(self, project_id: str, output_file: Path): # noqa: ANN201
16
+ def download_comment_json(self, project_id: str, output_file: Path) -> None:
19
17
  super().validate_project(project_id, [ProjectMemberRole.OWNER, ProjectMemberRole.TRAINING_DATA_USER])
20
18
  project_title = self.facade.get_project_title(project_id)
21
- logger.info(f"{project_title} のコメント全件ファイルをダウンロードします。")
19
+ logger.info(f"project_id='{project_id}'のコメント全件ファイルをダウンロードします。 :: project_title='{project_title}'")
22
20
 
23
21
  obj = DownloadingFile(self.service)
24
22
  obj.download_comment_json(
25
23
  project_id,
26
24
  str(output_file),
27
25
  )
28
- logger.info(f"コメント全件ファイルをダウンロードしました。output={output_file}")
26
+ logger.info(f"project_id='{project_id}'のコメント全件ファイルをダウンロードしました。 :: output='{output_file}', project_title='{project_title}'")
29
27
 
30
28
  def main(self) -> None:
31
29
  args = self.args
@@ -50,7 +48,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
50
48
  parser.set_defaults(subcommand_func=main)
51
49
 
52
50
 
53
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
51
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
54
52
  subcommand_name = "download"
55
53
  subcommand_help = "コメント全件ファイルをダウンロードします。"
56
54
  epilog = "オーナロールまたはアノテーションユーザロールを持つユーザで実行してください。"
@@ -10,13 +10,12 @@ import logging
10
10
  import tempfile
11
11
  from collections.abc import Collection
12
12
  from pathlib import Path
13
- from typing import Any, Optional
13
+ from typing import Any
14
14
 
15
15
  import annofabapi
16
16
  import pandas
17
17
  from annofabapi.models import CommentType
18
18
 
19
- import annofabcli
20
19
  import annofabcli.common.cli
21
20
  from annofabcli.comment.list_comment import create_empty_df_comment, create_reply_counter
22
21
  from annofabcli.common.cli import ArgumentParser, CommandLine, build_annofabapi_resource_and_login
@@ -36,9 +35,9 @@ class ListAllCommentMain:
36
35
  def get_all_comment(
37
36
  self,
38
37
  project_id: str,
39
- comment_json: Optional[Path],
40
- task_ids: Optional[Collection[str]],
41
- comment_type: Optional[CommentType],
38
+ comment_json: Path | None,
39
+ task_ids: Collection[str] | None,
40
+ comment_type: CommentType | None,
42
41
  exclude_reply: bool, # noqa: FBT001
43
42
  ) -> list[dict[str, Any]]:
44
43
  if comment_json is None:
@@ -154,7 +153,7 @@ def main(args: argparse.Namespace) -> None:
154
153
  ListAllComment(service, facade, args).main()
155
154
 
156
155
 
157
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
156
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
158
157
  subcommand_name = "list_all"
159
158
  subcommand_help = "すべてのコメントの一覧を出力します。"
160
159
  description = (
@@ -3,13 +3,12 @@ from __future__ import annotations
3
3
  import argparse
4
4
  import logging
5
5
  from collections import Counter
6
- from typing import Any, Optional
6
+ from typing import Any
7
7
 
8
8
  import pandas
9
9
  import requests
10
10
  from annofabapi.models import Comment, CommentType
11
11
 
12
- import annofabcli
13
12
  import annofabcli.common.cli
14
13
  from annofabcli.common.cli import ArgumentParser, CommandLine, build_annofabapi_resource_and_login
15
14
  from annofabcli.common.enums import FormatArgument
@@ -61,7 +60,7 @@ class ListingComments(CommandLine):
61
60
  c["reply_count"] = reply_counter.get(key, 0)
62
61
  return comments
63
62
 
64
- def get_comment_list(self, project_id: str, task_id_list: list[str], *, comment_type: Optional[CommentType], exclude_reply: bool) -> list[dict[str, Any]]:
63
+ def get_comment_list(self, project_id: str, task_id_list: list[str], *, comment_type: CommentType | None, exclude_reply: bool) -> list[dict[str, Any]]:
65
64
  all_comments: list[Comment] = []
66
65
 
67
66
  for task_id in task_id_list:
@@ -151,7 +150,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
151
150
  parser.set_defaults(subcommand_func=main)
152
151
 
153
152
 
154
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
153
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
155
154
  subcommand_name = "list"
156
155
  subcommand_help = "コメント一覧を出力します。"
157
156
 
@@ -4,10 +4,9 @@ import logging
4
4
  import multiprocessing
5
5
  import uuid
6
6
  from dataclasses import dataclass
7
- from typing import Any, Optional
7
+ from typing import Any
8
8
 
9
9
  import annofabapi
10
- import annofabapi.utils
11
10
  import requests
12
11
  from annofabapi.models import CommentType, TaskPhase, TaskStatus
13
12
  from dataclasses_json import DataClassJsonMixin
@@ -29,13 +28,13 @@ class AddedComment(DataClassJsonMixin):
29
28
  comment: str
30
29
  """コメントの中身"""
31
30
 
32
- data: Optional[dict[str, Any]]
31
+ data: dict[str, Any] | None
33
32
  """コメントを付与する位置や区間"""
34
33
 
35
- annotation_id: Optional[str]
34
+ annotation_id: str | None
36
35
  """コメントに紐付けるアノテーションID"""
37
36
 
38
- phrases: Optional[list[str]]
37
+ phrases: list[str] | None
39
38
  """参照している定型指摘ID"""
40
39
 
41
40
 
@@ -139,7 +138,7 @@ class PutCommentMain(CommandLineWithConfirm):
139
138
  self,
140
139
  task_id: str,
141
140
  comments_for_task: AddedCommentsForTask,
142
- task_index: Optional[int] = None,
141
+ task_index: int | None = None,
143
142
  ) -> int:
144
143
  """
145
144
  タスクにコメントを付与します。
@@ -207,7 +206,7 @@ class PutCommentMain(CommandLineWithConfirm):
207
206
  def add_comments_for_task_list(
208
207
  self,
209
208
  comments_for_task_list: AddedComments,
210
- parallelism: Optional[int] = None,
209
+ parallelism: int | None = None,
211
210
  ) -> None:
212
211
  comments_count = sum(len(e) for e in comments_for_task_list.values())
213
212
  logger.info(f"{self.comment_type_name}を付与するタスク数: {len(comments_for_task_list)}, {self.comment_type_name}を付与する入力データ数: {comments_count}")
@@ -252,10 +251,10 @@ def convert_cli_comments(dict_comments: dict[str, Any], *, comment_type: Comment
252
251
  data: dict[str, Any]
253
252
  """コメントを付与する位置や区間"""
254
253
 
255
- annotation_id: Optional[str] = None
254
+ annotation_id: str | None = None
256
255
  """コメントに紐付けるアノテーションID"""
257
256
 
258
- phrases: Optional[list[str]] = None
257
+ phrases: list[str] | None = None
259
258
  """参照している定型指摘ID"""
260
259
 
261
260
  @dataclass
@@ -267,7 +266,7 @@ def convert_cli_comments(dict_comments: dict[str, Any], *, comment_type: Comment
267
266
  comment: str
268
267
  """コメントの中身"""
269
268
 
270
- annotation_id: Optional[str] = None
269
+ annotation_id: str | None = None
271
270
  """コメントに紐付けるアノテーションID"""
272
271
 
273
272
  def convert_inspection_comment(comment: dict[str, Any]) -> AddedComment:
@@ -4,10 +4,9 @@ import uuid
4
4
  from collections.abc import Collection
5
5
  from dataclasses import dataclass
6
6
  from functools import partial
7
- from typing import Any, Optional
7
+ from typing import Any
8
8
 
9
9
  import annofabapi
10
- import annofabapi.utils
11
10
  from annofabapi.models import CommentType, TaskPhase, TaskStatus
12
11
 
13
12
  from annofabcli.comment.utils import get_comment_type_name
@@ -26,10 +25,10 @@ class AddedSimpleComment:
26
25
  comment: str
27
26
  """コメントの中身"""
28
27
 
29
- data: Optional[dict[str, Any]]
28
+ data: dict[str, Any] | None
30
29
  """コメントを付与する位置や区間"""
31
30
 
32
- phrases: Optional[list[str]] = None
31
+ phrases: list[str] | None = None
33
32
  """参照している定型指摘ID"""
34
33
 
35
34
 
@@ -103,7 +102,7 @@ class PutCommentSimplyMain(CommandLineWithConfirm):
103
102
  self,
104
103
  task_id: str,
105
104
  comment_info: AddedSimpleComment,
106
- task_index: Optional[int] = None,
105
+ task_index: int | None = None,
107
106
  ) -> bool:
108
107
  """
109
108
  タスクにコメントを付与します。
@@ -166,7 +165,7 @@ class PutCommentSimplyMain(CommandLineWithConfirm):
166
165
  self,
167
166
  task_ids: Collection[str],
168
167
  comment_info: AddedSimpleComment,
169
- parallelism: Optional[int] = None,
168
+ parallelism: int | None = None,
170
169
  ) -> None:
171
170
  logger.info(f"{len(task_ids)} 件のタスクに{self.comment_type_name}を付与します。")
172
171
 
@@ -4,11 +4,9 @@ import argparse
4
4
  import json
5
5
  import logging
6
6
  import sys
7
- from typing import Optional
8
7
 
9
8
  from annofabapi.models import CommentType, ProjectMemberRole
10
9
 
11
- import annofabcli
12
10
  import annofabcli.common.cli
13
11
  from annofabcli.comment.put_comment import PutCommentMain, convert_cli_comments
14
12
  from annofabcli.common.cli import (
@@ -83,7 +81,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
83
81
  parser.set_defaults(subcommand_func=main)
84
82
 
85
83
 
86
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
84
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
87
85
  subcommand_name = "put_inspection"
88
86
  subcommand_help = "検査コメントを付与します"
89
87
  description = "検査コメントを付与します。"
@@ -1,12 +1,10 @@
1
1
  import argparse
2
2
  import logging
3
3
  import sys
4
- from typing import Optional
5
4
 
6
5
  from annofabapi.models import CommentType, InputDataType, ProjectMemberRole
7
6
  from annofabapi.plugin import EditorPluginId
8
7
 
9
- import annofabcli
10
8
  import annofabcli.common.cli
11
9
  from annofabcli.comment.put_comment_simply import AddedSimpleComment, PutCommentSimplyMain
12
10
  from annofabcli.common.cli import (
@@ -135,7 +133,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
135
133
  parser.set_defaults(subcommand_func=main)
136
134
 
137
135
 
138
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
136
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
139
137
  subcommand_name = "put_inspection_simply"
140
138
  subcommand_help = "``comment put_inspection`` コマンドよりも、簡単に検査コメントを付与します。"
141
139
  epilog = "チェッカーロールまたはオーナロールを持つユーザで実行してください。"
@@ -2,11 +2,9 @@ import argparse
2
2
  import json
3
3
  import logging
4
4
  import sys
5
- from typing import Optional
6
5
 
7
6
  from annofabapi.models import CommentType
8
7
 
9
- import annofabcli
10
8
  import annofabcli.common.cli
11
9
  from annofabcli.comment.put_comment import PutCommentMain, convert_cli_comments
12
10
  from annofabcli.common.cli import (
@@ -84,7 +82,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
84
82
  parser.set_defaults(subcommand_func=main)
85
83
 
86
84
 
87
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
85
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
88
86
  subcommand_name = "put_onhold"
89
87
  subcommand_help = "保留コメントを付与します"
90
88
 
@@ -1,11 +1,9 @@
1
1
  import argparse
2
2
  import logging
3
3
  import sys
4
- from typing import Optional
5
4
 
6
5
  from annofabapi.models import CommentType
7
6
 
8
- import annofabcli
9
7
  import annofabcli.common.cli
10
8
  from annofabcli.comment.put_comment_simply import AddedSimpleComment, PutCommentSimplyMain
11
9
  from annofabcli.common.cli import (
@@ -87,7 +85,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
87
85
  parser.set_defaults(subcommand_func=main)
88
86
 
89
87
 
90
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
88
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
91
89
  subcommand_name = "put_onhold_simply"
92
90
  subcommand_help = "``comment put_onhold`` コマンドよりも、簡単に保留コメントを付与します。"
93
91
 
@@ -1,7 +1,5 @@
1
1
  import argparse
2
- from typing import Optional
3
2
 
4
- import annofabcli
5
3
  import annofabcli.comment.delete_comment
6
4
  import annofabcli.comment.download_comment_json
7
5
  import annofabcli.comment.list_all_comment
@@ -27,7 +25,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
27
25
  annofabcli.comment.put_onhold_comment_simply.add_parser(subparsers)
28
26
 
29
27
 
30
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
28
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
31
29
  subcommand_name = "comment"
32
30
  subcommand_help = "コメント関係のサブコマンド"
33
31