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
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import json
4
4
  import math
5
- from typing import Any, Optional
5
+ from typing import Any
6
6
 
7
7
  from bokeh.models import LayoutDOM
8
8
  from bokeh.models.widgets.markups import PreText
@@ -15,16 +15,16 @@ def create_pretext_from_metadata(metadata: dict[str, Any]) -> PreText:
15
15
  return PreText(text=text)
16
16
 
17
17
 
18
- def convert_1d_figure_list_to_2d(figure_list: list[figure], *, ncols: int = 4) -> list[list[Optional[LayoutDOM]]]:
18
+ def convert_1d_figure_list_to_2d(figure_list: list[figure], *, ncols: int = 4) -> list[list[LayoutDOM | None]]:
19
19
  """
20
20
  1次元のfigure_listを、grid layout用に2次元のfigureリストに変換する。
21
21
  """
22
- row_list: list[list[Optional[LayoutDOM]]] = []
22
+ row_list: list[list[LayoutDOM | None]] = []
23
23
 
24
24
  for i in range(math.ceil(len(figure_list) / ncols)):
25
25
  start = i * ncols
26
26
  end = (i + 1) * ncols
27
- row: list[Optional[LayoutDOM]] = []
27
+ row: list[LayoutDOM | None] = []
28
28
  row.extend(figure_list[start:end])
29
29
  if len(row) < ncols:
30
30
  row.extend([None] * (ncols - len(row)))
annofabcli/common/cli.py CHANGED
@@ -9,7 +9,7 @@ import logging
9
9
  import os
10
10
  import pkgutil
11
11
  from pathlib import Path
12
- from typing import Any, Optional
12
+ from typing import Any
13
13
 
14
14
  import annofabapi
15
15
  import pandas
@@ -81,12 +81,12 @@ def build_annofabapi_resource_and_login(args: argparse.Namespace) -> annofabapi.
81
81
 
82
82
 
83
83
  def add_parser(
84
- subparsers: Optional[argparse._SubParsersAction],
84
+ subparsers: argparse._SubParsersAction | None,
85
85
  command_name: str,
86
86
  command_help: str,
87
- description: Optional[str] = None,
87
+ description: str | None = None,
88
88
  is_subcommand: bool = True, # noqa: FBT001, FBT002
89
- epilog: Optional[str] = None,
89
+ epilog: str | None = None,
90
90
  ) -> argparse.ArgumentParser:
91
91
  """
92
92
  サブコマンド用にparserを追加する
@@ -159,7 +159,7 @@ def add_parser(
159
159
  return parser
160
160
 
161
161
 
162
- def get_list_from_args(str_list: Optional[list[str]] = None) -> list[str]:
162
+ def get_list_from_args(str_list: list[str] | None = None) -> list[str]:
163
163
  """
164
164
  文字列のListのサイズが1で、プレフィックスが`file://`ならば、ファイルパスとしてファイルを読み込み、行をListとして返す。
165
165
  そうでなければ、引数の値をそのまま返す。
@@ -185,7 +185,7 @@ def get_list_from_args(str_list: Optional[list[str]] = None) -> list[str]:
185
185
  return str_list
186
186
 
187
187
 
188
- def get_json_from_args(target: Optional[str] = None) -> Any: # noqa: ANN401
188
+ def get_json_from_args(target: str | None = None) -> Any: # noqa: ANN401
189
189
  """
190
190
  JSON形式をPythonオブジェクトに変換する。
191
191
  プレフィックスが`file://`ならば、ファイルパスとしてファイルを読み込み、Pythonオブジェクトを返す。
@@ -202,7 +202,7 @@ def get_json_from_args(target: Optional[str] = None) -> Any: # noqa: ANN401
202
202
  return json.loads(target)
203
203
 
204
204
 
205
- def get_input_data_size(str_input_data_size: str) -> Optional[InputDataSize]:
205
+ def get_input_data_size(str_input_data_size: str) -> InputDataSize | None:
206
206
  """400x300を(400,300)に変換する"""
207
207
  splitted_list = str_input_data_size.split("x")
208
208
  if len(splitted_list) < 2:
@@ -380,7 +380,7 @@ class ArgumentParser:
380
380
  def __init__(self, parser: argparse.ArgumentParser) -> None:
381
381
  self.parser = parser
382
382
 
383
- def add_project_id(self, help_message: Optional[str] = None) -> None:
383
+ def add_project_id(self, help_message: str | None = None) -> None:
384
384
  """
385
385
  '--project_id` 引数を追加
386
386
  """
@@ -389,7 +389,7 @@ class ArgumentParser:
389
389
 
390
390
  self.parser.add_argument("-p", "--project_id", type=str, required=True, help=help_message)
391
391
 
392
- def add_task_id(self, *, required: bool = True, help_message: Optional[str] = None) -> None:
392
+ def add_task_id(self, *, required: bool = True, help_message: str | None = None) -> None:
393
393
  """
394
394
  '--task_id` 引数を追加
395
395
  """
@@ -398,7 +398,7 @@ class ArgumentParser:
398
398
 
399
399
  self.parser.add_argument("-t", "--task_id", type=str, required=required, nargs="+", help=help_message)
400
400
 
401
- def add_input_data_id(self, *, required: bool = True, help_message: Optional[str] = None) -> None:
401
+ def add_input_data_id(self, *, required: bool = True, help_message: str | None = None) -> None:
402
402
  """
403
403
  '--input_data_id` 引数を追加
404
404
  """
@@ -407,7 +407,7 @@ class ArgumentParser:
407
407
 
408
408
  self.parser.add_argument("-i", "--input_data_id", type=str, required=required, nargs="+", help=help_message)
409
409
 
410
- def add_format(self, choices: list[FormatArgument], default: FormatArgument, help_message: Optional[str] = None) -> None:
410
+ def add_format(self, choices: list[FormatArgument], default: FormatArgument, help_message: str | None = None) -> None:
411
411
  """
412
412
  '--format` 引数を追加
413
413
  """
@@ -416,7 +416,7 @@ class ArgumentParser:
416
416
 
417
417
  self.parser.add_argument("-f", "--format", type=str, choices=[e.value for e in choices], default=default.value, help=help_message)
418
418
 
419
- def add_output(self, *, required: bool = False, help_message: Optional[str] = None) -> None:
419
+ def add_output(self, *, required: bool = False, help_message: str | None = None) -> None:
420
420
  """
421
421
  '--output` 引数を追加
422
422
  """
@@ -425,7 +425,7 @@ class ArgumentParser:
425
425
 
426
426
  self.parser.add_argument("-o", "--output", type=str, required=required, help=help_message)
427
427
 
428
- def add_task_query(self, *, required: bool = False, help_message: Optional[str] = None) -> None:
428
+ def add_task_query(self, *, required: bool = False, help_message: str | None = None) -> None:
429
429
  if help_message is None:
430
430
  help_message = (
431
431
  "タスクを絞り込むためのクエリ条件をJSON形式で指定します。"
@@ -476,10 +476,10 @@ class CommandLineWithoutWebapi:
476
476
  all_yes: bool = False
477
477
 
478
478
  #: 出力先
479
- output: Optional[str] = None
479
+ output: str | None = None
480
480
 
481
481
  #: 出力フォーマット
482
- str_format: Optional[str] = None
482
+ str_format: str | None = None
483
483
 
484
484
  def __init__(self, args: argparse.Namespace) -> None:
485
485
  self.args = args
@@ -575,8 +575,8 @@ class CommandLine(CommandLineWithoutWebapi):
575
575
  def validate_project(
576
576
  self,
577
577
  project_id: str,
578
- project_member_roles: Optional[list[ProjectMemberRole]] = None,
579
- organization_member_roles: Optional[list[OrganizationMemberRole]] = None,
578
+ project_member_roles: list[ProjectMemberRole] | None = None,
579
+ organization_member_roles: list[OrganizationMemberRole] | None = None,
580
580
  ) -> None:
581
581
  """
582
582
  プロジェクト or 組織に対して、必要な権限が付与されているかを確認する。
@@ -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) -> Optional[str]:
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: Optional[WaitOptions] = None,
52
- job_id: Optional[str] = None,
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: Union[str, Path],
71
+ dest_path: str | Path,
73
72
  is_latest: bool = False, # noqa: FBT001, FBT002
74
- wait_options: Optional[WaitOptions] = None,
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: Union[str, Path],
82
+ dest_path: str | Path,
84
83
  is_latest: bool = False, # noqa: FBT001, FBT002
85
- wait_options: Optional[WaitOptions] = None,
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: Optional[WaitOptions] = None) -> None:
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: Union[str, Path],
127
+ dest_path: str | Path,
129
128
  is_latest: bool = False, # noqa: FBT001, FBT002
130
- wait_options: Optional[WaitOptions] = None,
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: Union[str, Path],
138
+ dest_path: str | Path,
140
139
  is_latest: bool = False, # noqa: FBT001, FBT002
141
- wait_options: Optional[WaitOptions] = None,
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: Optional[WaitOptions] = None) -> None:
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: Union[str, Path],
174
+ dest_path: str | Path,
176
175
  is_latest: bool = False, # noqa: FBT001, FBT002
177
- wait_options: Optional[WaitOptions] = None,
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: Union[str, Path], *, is_latest: bool = False, wait_options: Optional[WaitOptions] = None) -> None:
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: Optional[WaitOptions] = None) -> None:
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: Union[str, Path]) -> None:
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: Union[str, Path]) -> None:
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: Union[str, Path]) -> None:
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: Union[str, Path]) -> None:
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: Union[str, Path]) -> None:
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: Union[str, Path]) -> None:
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: Union[str, Path]) -> None:
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: Union[str, Path]) -> None:
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: Optional[WaitOptions] = None,
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: Optional[WaitOptions] = None,
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: Optional[WaitOptions] = None,
384
+ wait_options: WaitOptions | None = None,
386
385
  ) -> Path:
387
386
  """
388
387
  入力データJSONをoutput_dirに統一された命名規則でダウンロードする。
@@ -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, Callable, Optional
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: Optional[list[AdditionalDataV1]] = None
35
+ attributes: list[AdditionalDataV1] | None = None
37
36
 
38
37
 
39
38
  @dataclass
40
39
  class AdditionalDataForCli(DataClassJsonMixin):
41
- additional_data_definition_id: Optional[str] = None
40
+ additional_data_definition_id: str | None = None
42
41
  """属性ID"""
43
42
 
44
- additional_data_definition_name_en: Optional[str] = None
43
+ additional_data_definition_name_en: str | None = None
45
44
  """属性の英語名"""
46
45
 
47
- flag: Optional[bool] = None
46
+ flag: bool | None = None
48
47
 
49
- integer: Optional[int] = None
48
+ integer: int | None = None
50
49
 
51
- comment: Optional[str] = None
50
+ comment: str | None = None
52
51
 
53
- choice: Optional[str] = None
52
+ choice: str | None = None
54
53
  """選択肢ID"""
55
54
 
56
- choice_name_en: Optional[str] = None
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: Optional[str] = None
65
+ label_name_en: str | None = None
67
66
  """ラベルの英語名"""
68
- label_id: Optional[str] = None
69
- attributes: Optional[list[AdditionalDataForCli]] = None
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: Optional[str] = None
79
- phase: Optional[TaskPhase] = None
80
- status: Optional[TaskStatus] = None
81
- phase_stage: Optional[int] = None
82
- user_id: Optional[str] = None
83
- account_id: Optional[str] = None
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: Optional[str] = None
95
- input_data_name: Optional[str] = None
96
- input_data_path: Optional[str] = None
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: Optional[TaskQuery]) -> bool:
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: Optional[TaskQuery]
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: Optional[InputDataQuery]
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) -> Optional[dict[str, Any]]:
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: Optional[tuple[str, list[OrganizationMember]]] = None
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]]) -> Optional[str]:
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]) -> Optional[OrganizationMember]:
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]) -> Optional[ProjectMember]:
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) -> Optional[ProjectMember]:
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) -> Optional[ProjectMember]:
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) -> Optional[OrganizationMember]:
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) -> Optional[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) -> Optional[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: Optional[list[ProjectMemberRole]] = None,
506
- organization_member_roles: Optional[list[OrganizationMemberRole]] = None,
504
+ project_member_roles: list[ProjectMemberRole] | None = None,
505
+ organization_member_roles: list[OrganizationMemberRole] | None = None,
507
506
  ) -> None:
508
507
  """
509
508
  プロジェクト or 組織に対して、必要な権限が付与されているかを確認する。
@@ -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, Callable, Optional
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) -> Optional[str]:
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: Optional[Any] = None, # noqa: ANN401
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: Optional[list[str]] = None,
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: Optional[Any] = None, # noqa: ANN401
146
- label_name_list: Optional[list[str]] = None,
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: Optional[list[str]] = None,
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: Optional[InputDataSize] = None,
271
- input_data_dict: Optional[dict[str, InputData]] = None,
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: Optional[Any] = None, # noqa: ANN401
274
- label_name_list: Optional[list[str]] = None,
275
- is_target_parser_func: Optional[IsParserFunc] = None,
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) -> Optional[InputDataSize]:
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"]