annofabcli 1.111.2__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 (184) 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 +2 -3
  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/visualize_annotation_count.py +22 -23
  146. annofabcli/statistics/visualize_annotation_duration.py +21 -22
  147. annofabcli/statistics/visualize_statistics.py +36 -33
  148. annofabcli/statistics/visualize_video_duration.py +18 -20
  149. annofabcli/supplementary/delete_supplementary_data.py +4 -4
  150. annofabcli/supplementary/list_supplementary_data.py +3 -3
  151. annofabcli/supplementary/put_supplementary_data.py +8 -8
  152. annofabcli/supplementary/subcommand_supplementary.py +1 -3
  153. annofabcli/task/cancel_acceptance.py +16 -17
  154. annofabcli/task/change_operator.py +10 -12
  155. annofabcli/task/change_status_to_break.py +7 -9
  156. annofabcli/task/change_status_to_on_hold.py +10 -12
  157. annofabcli/task/complete_tasks.py +17 -18
  158. annofabcli/task/copy_tasks.py +3 -5
  159. annofabcli/task/delete_metadata_key_of_task.py +4 -6
  160. annofabcli/task/delete_tasks.py +6 -6
  161. annofabcli/task/download_task_json.py +4 -6
  162. annofabcli/task/list_all_tasks.py +7 -7
  163. annofabcli/task/list_all_tasks_added_task_history.py +12 -12
  164. annofabcli/task/list_tasks.py +6 -6
  165. annofabcli/task/list_tasks_added_task_history.py +9 -9
  166. annofabcli/task/put_tasks.py +4 -5
  167. annofabcli/task/put_tasks_by_count.py +1 -2
  168. annofabcli/task/reject_tasks.py +18 -20
  169. annofabcli/task/subcommand_task.py +1 -3
  170. annofabcli/task/update_metadata_of_task.py +5 -6
  171. annofabcli/task_history/download_task_history_json.py +4 -6
  172. annofabcli/task_history/list_all_task_history.py +5 -6
  173. annofabcli/task_history/list_task_history.py +3 -4
  174. annofabcli/task_history/subcommand_task_history.py +1 -3
  175. annofabcli/task_history_event/download_task_history_event_json.py +4 -6
  176. annofabcli/task_history_event/list_all_task_history_event.py +6 -6
  177. annofabcli/task_history_event/list_worktime.py +15 -15
  178. annofabcli/task_history_event/subcommand_task_history_event.py +1 -2
  179. {annofabcli-1.111.2.dist-info → annofabcli-1.112.0.dist-info}/METADATA +9 -15
  180. annofabcli-1.112.0.dist-info/RECORD +229 -0
  181. {annofabcli-1.111.2.dist-info → annofabcli-1.112.0.dist-info}/WHEEL +1 -1
  182. annofabcli-1.111.2.dist-info/RECORD +0 -228
  183. {annofabcli-1.111.2.dist-info → annofabcli-1.112.0.dist-info}/entry_points.txt +0 -0
  184. {annofabcli-1.111.2.dist-info → annofabcli-1.112.0.dist-info}/licenses/LICENSE +0 -0
@@ -14,7 +14,7 @@ from collections.abc import Collection, Iterator
14
14
  from dataclasses import dataclass, field
15
15
  from enum import Enum
16
16
  from pathlib import Path
17
- from typing import Any, Optional, Union
17
+ from typing import Any
18
18
 
19
19
  import annofabapi
20
20
  import pandas
@@ -26,7 +26,6 @@ from annofabapi.parser import (
26
26
  )
27
27
  from dataclasses_json import DataClassJsonMixin, config
28
28
 
29
- import annofabcli
30
29
  import annofabcli.common.cli
31
30
  from annofabcli.common.cli import (
32
31
  COMMAND_LINE_ERROR_STATUS_CODE,
@@ -117,10 +116,10 @@ class AnnotationDuration(DataClassJsonMixin):
117
116
  input_data_id: str
118
117
  input_data_name: str
119
118
 
120
- updated_datetime: Optional[str]
119
+ updated_datetime: str | None
121
120
  """アノテーションJSONに格納されているアノテーションの更新日時"""
122
121
 
123
- video_duration_second: Optional[float]
122
+ video_duration_second: float | None
124
123
  """動画の長さ[秒]"""
125
124
 
126
125
  annotation_duration_second: float
@@ -158,17 +157,17 @@ class ListAnnotationDurationByInputData:
158
157
  def __init__(
159
158
  self,
160
159
  *,
161
- target_labels: Optional[Collection[str]] = None,
162
- non_target_labels: Optional[Collection[str]] = None,
163
- target_attribute_names: Optional[Collection[AttributeNameKey]] = None,
164
- non_target_attribute_names: Optional[Collection[AttributeNameKey]] = None,
160
+ target_labels: Collection[str] | None = None,
161
+ non_target_labels: Collection[str] | None = None,
162
+ target_attribute_names: Collection[AttributeNameKey] | None = None,
163
+ non_target_attribute_names: Collection[AttributeNameKey] | None = None,
165
164
  ) -> None:
166
165
  self.target_labels = set(target_labels) if target_labels is not None else None
167
166
  self.target_attribute_names = set(target_attribute_names) if target_attribute_names is not None else None
168
167
  self.non_target_labels = set(non_target_labels) if non_target_labels is not None else None
169
168
  self.non_target_attribute_names = set(non_target_attribute_names) if non_target_attribute_names is not None else None
170
169
 
171
- def get_annotation_duration(self, simple_annotation: dict[str, Any], video_duration_second: Optional[float] = None) -> AnnotationDuration:
170
+ def get_annotation_duration(self, simple_annotation: dict[str, Any], video_duration_second: float | None = None) -> AnnotationDuration:
172
171
  """
173
172
  1個のアノテーションJSONに対して、ラベルごと/属性ごとの区間アノテーションの長さを取得する。
174
173
 
@@ -181,7 +180,7 @@ class ListAnnotationDurationByInputData:
181
180
  """区間アノテーションのdetail情報から、区間アノテーションの長さ(秒)を計算する"""
182
181
  return (detail["data"]["end"] - detail["data"]["begin"]) / 1000
183
182
 
184
- def convert_attribute_value_to_key(value: Union[bool, str, float]) -> str: # noqa: FBT001
183
+ def convert_attribute_value_to_key(value: bool | str | float) -> str: # noqa: FBT001
185
184
  """
186
185
  アノテーションJSONに格納されている属性値を、dict用のkeyに変換する。
187
186
 
@@ -257,9 +256,9 @@ class ListAnnotationDurationByInputData:
257
256
  self,
258
257
  annotation_path: Path,
259
258
  *,
260
- input_data_json_path: Optional[Path] = None,
261
- target_task_ids: Optional[Collection[str]] = None,
262
- task_query: Optional[TaskQuery] = None,
259
+ input_data_json_path: Path | None = None,
260
+ target_task_ids: Collection[str] | None = None,
261
+ task_query: TaskQuery | None = None,
263
262
  ) -> list[AnnotationDuration]:
264
263
  """
265
264
  アノテーションzipまたはそれを展開したディレクトリから、ラベルごと/属性ごとの区間アノテーションの長さを取得する。
@@ -267,7 +266,7 @@ class ListAnnotationDurationByInputData:
267
266
  Args:
268
267
  input_data_json_path: 入力データ全件ファイルのパス。動画の長さを取得するのに利用します。
269
268
  """
270
- dict_input_data: Optional[dict[str, dict[str, Any]]] = None
269
+ dict_input_data: dict[str, dict[str, Any]] | None = None
271
270
  if input_data_json_path is not None:
272
271
  with input_data_json_path.open() as f:
273
272
  input_data_list = json.load(f)
@@ -292,7 +291,7 @@ class ListAnnotationDurationByInputData:
292
291
  if not match_annotation_with_task_query(simple_annotation_dict, task_query):
293
292
  continue
294
293
 
295
- video_duration_second: Optional[float] = None
294
+ video_duration_second: float | None = None
296
295
  if dict_input_data is not None:
297
296
  input_data = dict_input_data[parser.input_data_id]
298
297
  video_duration_second = input_data["system_metadata"]["input_duration"]
@@ -331,7 +330,7 @@ class AnnotationDurationCsvByAttribute:
331
330
 
332
331
  return [(label, attribute_name, attribute_value) for (label, attribute_name, attribute_value) in columns if (label, attribute_name) not in non_selective_attribute_names]
333
332
 
334
- def _value_columns(self, annotation_duration_list: Collection[AnnotationDuration], prior_attribute_columns: Optional[list[AttributeValueKey]]) -> list[AttributeValueKey]:
333
+ def _value_columns(self, annotation_duration_list: Collection[AnnotationDuration], prior_attribute_columns: list[AttributeValueKey] | None) -> list[AttributeValueKey]:
335
334
  all_attr_key_set = {attr_key for c in annotation_duration_list for attr_key in c.annotation_duration_second_by_attribute}
336
335
  if prior_attribute_columns is not None:
337
336
  remaining_columns = sorted(all_attr_key_set - set(prior_attribute_columns))
@@ -364,7 +363,7 @@ class AnnotationDurationCsvByAttribute:
364
363
  def get_columns(
365
364
  self,
366
365
  annotation_duration_list: list[AnnotationDuration],
367
- prior_attribute_columns: Optional[list[AttributeValueKey]] = None,
366
+ prior_attribute_columns: list[AttributeValueKey] | None = None,
368
367
  ) -> list[AttributeValueKey]:
369
368
  basic_columns = [
370
369
  ("project_id", "", ""),
@@ -383,7 +382,7 @@ class AnnotationDurationCsvByAttribute:
383
382
  def create_df(
384
383
  self,
385
384
  annotation_duration_list: list[AnnotationDuration],
386
- prior_attribute_columns: Optional[list[AttributeValueKey]] = None,
385
+ prior_attribute_columns: list[AttributeValueKey] | None = None,
387
386
  ) -> pandas.DataFrame:
388
387
  def to_cell(c: AnnotationDuration) -> dict[tuple[str, str, str], Any]:
389
388
  cell: dict[AttributeValueKey, Any] = {
@@ -415,7 +414,7 @@ class AnnotationDurationCsvByLabel:
415
414
  ラベルごとのアノテーション長さをCSVとして出力するためのクラス。
416
415
  """
417
416
 
418
- def _value_columns(self, annotation_duration_list: list[AnnotationDuration], prior_label_columns: Optional[list[str]]) -> list[str]:
417
+ def _value_columns(self, annotation_duration_list: list[AnnotationDuration], prior_label_columns: list[str] | None) -> list[str]:
419
418
  all_attr_key_set = {attr_key for elm in annotation_duration_list for attr_key in elm.annotation_duration_second_by_label.keys()} # noqa: SIM118
420
419
  if prior_label_columns is not None:
421
420
  remaining_columns = sorted(all_attr_key_set - set(prior_label_columns))
@@ -429,7 +428,7 @@ class AnnotationDurationCsvByLabel:
429
428
  def get_columns(
430
429
  self,
431
430
  annotation_duration_list: list[AnnotationDuration],
432
- prior_label_columns: Optional[list[str]] = None,
431
+ prior_label_columns: list[str] | None = None,
433
432
  ) -> list[str]:
434
433
  basic_columns = [
435
434
  "project_id",
@@ -449,7 +448,7 @@ class AnnotationDurationCsvByLabel:
449
448
  def create_df(
450
449
  self,
451
450
  annotation_duration_list: list[AnnotationDuration],
452
- prior_label_columns: Optional[list[str]] = None,
451
+ prior_label_columns: list[str] | None = None,
453
452
  ) -> pandas.DataFrame:
454
453
  def to_dict(c: AnnotationDuration) -> dict[str, Any]:
455
454
  d: dict[str, Any] = {
@@ -481,16 +480,16 @@ class ListAnnotationDurationMain:
481
480
  def __init__(self, service: annofabapi.Resource) -> None:
482
481
  self.service = service
483
482
 
484
- def print_annotation_duration_csv(self, annotation_duration_list: list[AnnotationDuration], csv_type: CsvType, output_file: Path, *, annotation_specs: Optional[AnnotationSpecs]) -> None:
483
+ def print_annotation_duration_csv(self, annotation_duration_list: list[AnnotationDuration], csv_type: CsvType, output_file: Path, *, annotation_specs: AnnotationSpecs | None) -> None:
485
484
  if csv_type == CsvType.LABEL:
486
485
  # ラベル名の列順が、アノテーション仕様にあるラベル名の順番に対応するようにする。
487
- label_columns: Optional[list[str]] = None
486
+ label_columns: list[str] | None = None
488
487
  if annotation_specs is not None:
489
488
  label_columns = annotation_specs.label_keys()
490
489
 
491
490
  df = AnnotationDurationCsvByLabel().create_df(annotation_duration_list, prior_label_columns=label_columns)
492
491
  elif csv_type == CsvType.ATTRIBUTE:
493
- attribute_columns: Optional[list[AttributeValueKey]] = None
492
+ attribute_columns: list[AttributeValueKey] | None = None
494
493
  if annotation_specs is not None:
495
494
  attribute_columns = annotation_specs.selective_attribute_value_keys()
496
495
 
@@ -507,14 +506,14 @@ class ListAnnotationDurationMain:
507
506
  output_file: Path,
508
507
  arg_format: FormatArgument,
509
508
  *,
510
- project_id: Optional[str] = None,
511
- input_data_json_path: Optional[Path] = None,
512
- target_task_ids: Optional[Collection[str]] = None,
513
- task_query: Optional[TaskQuery] = None,
514
- csv_type: Optional[CsvType] = None,
509
+ project_id: str | None = None,
510
+ input_data_json_path: Path | None = None,
511
+ target_task_ids: Collection[str] | None = None,
512
+ task_query: TaskQuery | None = None,
513
+ csv_type: CsvType | None = None,
515
514
  ) -> None:
516
- annotation_specs: Optional[AnnotationSpecs] = None
517
- non_selective_attribute_name_keys: Optional[list[AttributeNameKey]] = None
515
+ annotation_specs: AnnotationSpecs | None = None
516
+ non_selective_attribute_name_keys: list[AttributeNameKey] | None = None
518
517
  if project_id is not None:
519
518
  annotation_specs = AnnotationSpecs(self.service, project_id, annotation_type=DefaultAnnotationType.RANGE.value)
520
519
  non_selective_attribute_name_keys = annotation_specs.non_selective_attribute_name_keys()
@@ -565,7 +564,7 @@ class ListAnnotationDuration(CommandLine):
565
564
  if not self.validate(args):
566
565
  sys.exit(COMMAND_LINE_ERROR_STATUS_CODE)
567
566
 
568
- project_id: Optional[str] = args.project_id
567
+ project_id: str | None = args.project_id
569
568
  if project_id is not None:
570
569
  super().validate_project(project_id, project_member_roles=[ProjectMemberRole.OWNER, ProjectMemberRole.TRAINING_DATA_USER])
571
570
  project, _ = self.service.api.get_project(project_id)
@@ -584,7 +583,7 @@ class ListAnnotationDuration(CommandLine):
584
583
 
585
584
  downloading_obj = DownloadingFile(self.service)
586
585
 
587
- def download_and_print_annotation_duration(project_id: str, temp_dir: Path, *, is_latest: bool, annotation_path: Optional[Path]) -> None:
586
+ def download_and_print_annotation_duration(project_id: str, temp_dir: Path, *, is_latest: bool, annotation_path: Path | None) -> None:
588
587
  if annotation_path is None:
589
588
  annotation_path = downloading_obj.download_annotation_zip_to_dir(
590
589
  project_id,
@@ -697,7 +696,7 @@ def main(args: argparse.Namespace) -> None:
697
696
  ListAnnotationDuration(service, facade, args).main()
698
697
 
699
698
 
700
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
699
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
701
700
  subcommand_name = "list_annotation_duration"
702
701
  subcommand_help = "ラベルごとまたは属性値ごとに区間アノテーションの長さ(秒)を出力します。"
703
702
  epilog = "オーナロールまたはアノテーションユーザロールを持つユーザで実行してください。"
@@ -7,12 +7,11 @@ import sys
7
7
  import tempfile
8
8
  from functools import partial
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
 
15
- import annofabcli
16
15
  import annofabcli.common.cli
17
16
  from annofabcli.common.cli import (
18
17
  COMMAND_LINE_ERROR_STATUS_CODE,
@@ -83,7 +82,7 @@ class ListVideoDuration(CommandLine):
83
82
  task_json: Path,
84
83
  input_data_json: Path,
85
84
  output_format: FormatArgument,
86
- output_file: Optional[Path],
85
+ output_file: Path | None,
87
86
  ) -> None:
88
87
  with task_json.open(encoding="utf-8") as f:
89
88
  task_list = json.load(f)
@@ -115,7 +114,7 @@ class ListVideoDuration(CommandLine):
115
114
  if not self.validate(args):
116
115
  sys.exit(COMMAND_LINE_ERROR_STATUS_CODE)
117
116
 
118
- project_id: Optional[str] = args.project_id
117
+ project_id: str | None = args.project_id
119
118
  if project_id is not None:
120
119
  super().validate_project(project_id, project_member_roles=[ProjectMemberRole.OWNER, ProjectMemberRole.TRAINING_DATA_USER])
121
120
  project, _ = self.service.api.get_project(project_id)
@@ -218,7 +217,7 @@ def main(args: argparse.Namespace) -> None:
218
217
  ListVideoDuration(service, facade, args).main()
219
218
 
220
219
 
221
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
220
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
222
221
  subcommand_name = "list_video_duration"
223
222
  subcommand_help = "各タスクの動画の長さを出力します。"
224
223
  epilog = "オーナロールまたはアノテーションユーザロールを持つユーザで実行してください。"
@@ -5,7 +5,7 @@ import datetime
5
5
  import logging
6
6
  from collections import defaultdict
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 dateutil.parser import parse
@@ -110,7 +110,7 @@ class ListWorktimeFromTaskHistoryEvent(CommandLine):
110
110
  def print_worktime_list(
111
111
  self,
112
112
  project_id: str,
113
- task_history_event_json: Optional[Path],
113
+ task_history_event_json: Path | None,
114
114
  ) -> None:
115
115
  super().validate_project(project_id, project_member_roles=None)
116
116
 
@@ -160,7 +160,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
160
160
  parser.set_defaults(subcommand_func=main)
161
161
 
162
162
 
163
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
163
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
164
164
  subcommand_name = "list_worktime"
165
165
  subcommand_help = "日ごとユーザごとの作業時間の一覧を出力します。"
166
166
  description = "タスク履歴イベント全件ファイルから、日ごとユーザごとの作業時間の一覧を出力します。"
@@ -1,8 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import logging
4
+ from collections.abc import Callable
4
5
  from pathlib import Path
5
- from typing import Any, Callable, Literal, Optional
6
+ from typing import Any, Literal
6
7
 
7
8
  import bokeh
8
9
  import bokeh.layouts
@@ -62,10 +63,10 @@ class ScatterGraph:
62
63
  y_axis_label: str,
63
64
  width: int = 1200,
64
65
  height: int = 1000,
65
- tooltip_columns: Optional[list[str]] = None,
66
+ tooltip_columns: list[str] | None = None,
66
67
  **figure_kwargs, # noqa: ANN003
67
68
  ) -> None:
68
- fig = figure(
69
+ fig = figure( # type: ignore[call-arg]
69
70
  title=title,
70
71
  x_axis_label=x_axis_label,
71
72
  y_axis_label=y_axis_label,
@@ -82,7 +83,7 @@ class ScatterGraph:
82
83
 
83
84
  self.figure = fig
84
85
 
85
- self.finding_user_widget: Optional[MultiChoice] = None
86
+ self.finding_user_widget: MultiChoice | None = None
86
87
  """ユーザーを探すためのWidget"""
87
88
 
88
89
  self.text_glyphs: dict[str, GlyphRenderer] = {}
@@ -146,7 +147,7 @@ class ScatterGraph:
146
147
 
147
148
  # 1点ごとに`text`で名前を表示している理由:
148
149
  # `add_multi_choice_widget_for_searching_user`関数で追加したMultiChoice Widgetで、名前の表示スタイルを変更するため
149
- for x, y, username, user_id in zip(source.data[x_column_name], source.data[y_column_name], source.data[username_column_name], source.data[user_id_column_name]):
150
+ for x, y, username, user_id in zip(source.data[x_column_name], source.data[y_column_name], source.data[username_column_name], source.data[user_id_column_name], strict=False):
150
151
  self.text_glyphs[user_id] = self.figure.text(
151
152
  x=x,
152
153
  y=y,
@@ -200,7 +201,7 @@ class ScatterGraph:
200
201
 
201
202
  # 1点ごとに`text`で名前を表示している理由:
202
203
  # `add_multi_choice_widget_for_searching_user`関数で追加したMultiChoice Widgetで、名前の表示スタイルを変更するため
203
- for x, y, username, user_id in zip(source.data[x_column_name], source.data[y_column_name], source.data[username_column_name], source.data[user_id_column_name]):
204
+ for x, y, username, user_id in zip(source.data[x_column_name], source.data[y_column_name], source.data[username_column_name], source.data[user_id_column_name], strict=False):
204
205
  self.text_glyphs[user_id] = self.figure.text(
205
206
  x=x,
206
207
  y=y,
@@ -228,7 +229,7 @@ class ScatterGraph:
228
229
  # 理由:名前の表示は`ColumnDataSource`を使っていない(`plot_scatter`メソッド参照)ため、ツールチップには値が"???"と表示される。
229
230
  # ユーザーが混乱しないようにするため、名前にカーソルを当てたときはツールチップが表示されないようにする。
230
231
  if self._hover_tool is not None and self._scatter_glyphs is not None:
231
- self._hover_tool.renderers = list(self._scatter_glyphs.values()) # type: ignore[assignment]
232
+ self._hover_tool.renderers = list(self._scatter_glyphs.values())
232
233
 
233
234
  def configure_legend(self): # noqa: ANN201
234
235
  """
@@ -275,7 +276,7 @@ class ScatterGraph:
275
276
  """
276
277
  code = code % (self.DEFAULT_USER_TEXT_FONT_STYLE, self.DEFAULT_USER_TEXT_FONT_SIZE)
277
278
  options = [(user_id, f"{user_id}:{username}") for user_id, username in users]
278
- multi_choice = MultiChoice(options=options, title="Find User:", width=300)
279
+ multi_choice = MultiChoice(options=options, title="Find User:", width=300) # type: ignore[arg-type]
279
280
  multi_choice.js_on_change(
280
281
  "value",
281
282
  CustomJS(code=code, args=args),
@@ -1,9 +1,6 @@
1
1
  import argparse
2
- from typing import Optional
3
2
 
4
- import annofabcli
5
3
  import annofabcli.common.cli
6
- import annofabcli.stat_visualization.merge_visualization_dir
7
4
  import annofabcli.statistics.list_annotation_area
8
5
  import annofabcli.statistics.list_annotation_attribute
9
6
  import annofabcli.statistics.list_annotation_attribute_filled_count
@@ -41,7 +38,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
41
38
  annofabcli.statistics.visualize_video_duration.add_parser(subparsers)
42
39
 
43
40
 
44
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
41
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
45
42
  subcommand_name = "statistics"
46
43
  subcommand_help = "統計関係のサブコマンド"
47
44
  description = "統計関係のサブコマンド"
@@ -5,13 +5,11 @@ import sys
5
5
  import tempfile
6
6
  from enum import Enum
7
7
  from pathlib import Path
8
- from typing import Optional
9
8
 
10
9
  import pandas
11
10
  from annofabapi.models import ProjectMemberRole, Task, TaskPhase, TaskStatus
12
11
  from annofabapi.utils import get_number_of_rejections
13
12
 
14
- import annofabcli
15
13
  import annofabcli.common.cli
16
14
  from annofabcli.common.cli import (
17
15
  ArgumentParser,
@@ -136,7 +134,7 @@ class SummarizeTaskCount(CommandLine):
136
134
  project, _ = self.service.api.get_project(project_id)
137
135
  return project["configuration"]["number_of_inspections"]
138
136
 
139
- def summarize_task_count(self, project_id: str, *, task_json_path: Optional[Path], is_latest: bool, temp_dir: Optional[Path] = None) -> None:
137
+ def summarize_task_count(self, project_id: str, *, task_json_path: Path | None, is_latest: bool, temp_dir: Path | None = None) -> None:
140
138
  # タスク全件ファイルをダウンロードするので、オーナロールかアノテーションユーザロールであることを確認する。
141
139
  super().validate_project(project_id, project_member_roles=[ProjectMemberRole.OWNER, ProjectMemberRole.TRAINING_DATA_USER])
142
140
 
@@ -150,7 +148,7 @@ class SummarizeTaskCount(CommandLine):
150
148
  task_count_df = create_task_count_summary(task_list, number_of_inspections=number_of_inspections)
151
149
  annofabcli.common.utils.print_csv(task_count_df, output=self.output)
152
150
 
153
- def get_task_list_with_downloading_file(self, project_id: str, task_json_path: Optional[Path], is_latest: bool, temp_dir: Optional[Path] = None) -> list[Task]: # noqa: FBT001
151
+ def get_task_list_with_downloading_file(self, project_id: str, task_json_path: Path | None, is_latest: bool, temp_dir: Path | None = None) -> list[Task]: # noqa: FBT001
154
152
  if task_json_path is None:
155
153
  if temp_dir is not None:
156
154
  downloading_obj = DownloadingFile(self.service)
@@ -188,7 +186,7 @@ class SummarizeTaskCount(CommandLine):
188
186
  project_id = args.project_id
189
187
  task_json_path = Path(args.task_json) if args.task_json is not None else None
190
188
 
191
- def process_task_count(temp_dir: Optional[Path]) -> None:
189
+ def process_task_count(temp_dir: Path | None) -> None:
192
190
  self.summarize_task_count(
193
191
  project_id,
194
192
  task_json_path=task_json_path,
@@ -237,7 +235,7 @@ def main(args: argparse.Namespace) -> None:
237
235
  SummarizeTaskCount(service, facade, args).main()
238
236
 
239
237
 
240
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
238
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
241
239
  subcommand_name = "summarize_task_count"
242
240
  subcommand_help = "タスクのフェーズ、ステータス、ステップごとにタスク数を出力します。"
243
241
  description = "タスクのフェーズ、ステータス、ステップごとにタスク数を、CSV形式で出力します。"
@@ -6,12 +6,10 @@ import logging
6
6
  import tempfile
7
7
  from enum import Enum
8
8
  from pathlib import Path
9
- from typing import Optional
10
9
 
11
10
  import pandas
12
11
  from annofabapi.models import ProjectMemberRole, Task, TaskPhase, TaskStatus
13
12
 
14
- import annofabcli
15
13
  import annofabcli.common.cli
16
14
  from annofabcli.common.cli import (
17
15
  ArgumentParser,
@@ -99,7 +97,7 @@ def get_task_id_prefix(task_id: str, delimiter: str) -> str:
99
97
  return delimiter.join(tmp_list[0 : len(tmp_list) - 1])
100
98
 
101
99
 
102
- def create_task_count_summary_df(task_list: list[Task], task_id_delimiter: Optional[str], task_id_groups: Optional[dict[str, list[str]]]) -> pandas.DataFrame:
100
+ def create_task_count_summary_df(task_list: list[Task], task_id_delimiter: str | None, task_id_groups: dict[str, list[str]] | None) -> pandas.DataFrame:
103
101
  """
104
102
  タスク数を集計したDataFrameを生成する。
105
103
 
@@ -228,7 +226,7 @@ def main(args: argparse.Namespace) -> None:
228
226
  SummarizeTaskCountByTaskId(service, facade, args).main()
229
227
 
230
228
 
231
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
229
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
232
230
  subcommand_name = "summarize_task_count_by_task_id_group"
233
231
  subcommand_help = "task_idのグループごとにタスク数を集計します。"
234
232
  epilog = "アノテーションユーザまたはオーナロールを持つユーザで実行してください。"
@@ -4,12 +4,10 @@ import logging
4
4
  import tempfile
5
5
  from enum import Enum
6
6
  from pathlib import Path
7
- from typing import Optional
8
7
 
9
8
  import pandas
10
9
  from annofabapi.models import ProjectMemberRole, Task, TaskPhase, TaskStatus
11
10
 
12
- import annofabcli
13
11
  import annofabcli.common.cli
14
12
  from annofabcli.common.cli import (
15
13
  ArgumentParser,
@@ -185,7 +183,7 @@ def main(args: argparse.Namespace) -> None:
185
183
  SummarizeTaskCountByUser(service, facade, args).main()
186
184
 
187
185
 
188
- def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
186
+ def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
189
187
  subcommand_name = "summarize_task_count_by_user"
190
188
  subcommand_help = "ユーザごとに、担当しているタスク数を出力します。"
191
189
  description = "ユーザごとに、担当しているタスク数をCSV形式で出力します。"
@@ -2,8 +2,9 @@ from __future__ import annotations
2
2
 
3
3
  import logging
4
4
  from collections import defaultdict
5
+ from collections.abc import Callable
5
6
  from pathlib import Path
6
- from typing import Any, Callable, Optional
7
+ from typing import Any
7
8
 
8
9
  import pandas
9
10
  from annofabapi.parser import lazy_parse_simple_annotation_zip
@@ -47,9 +48,9 @@ class AnnotationCount:
47
48
  annotation_zip: Path,
48
49
  project_id: str,
49
50
  *,
50
- get_annotation_count_func: Optional[Callable[[dict[str, Any]], int]] = None,
51
- include_labels: Optional[list[str]] = None,
52
- exclude_labels: Optional[list[str]] = None,
51
+ get_annotation_count_func: Callable[[dict[str, Any]], int] | None = None,
52
+ include_labels: list[str] | None = None,
53
+ exclude_labels: list[str] | None = None,
53
54
  ) -> AnnotationCount:
54
55
  """
55
56
  アノテーションZIPファイルからインスタンスを生成します。
@@ -3,7 +3,6 @@ from __future__ import annotations
3
3
  import logging
4
4
  from collections import defaultdict
5
5
  from pathlib import Path
6
- from typing import Optional
7
6
 
8
7
  import pandas
9
8
  from annofabapi.parser import lazy_parse_simple_annotation_zip
@@ -47,8 +46,8 @@ class AnnotationDuration:
47
46
  annotation_zip: Path,
48
47
  project_id: str,
49
48
  *,
50
- include_labels: Optional[list[str]] = None,
51
- exclude_labels: Optional[list[str]] = None,
49
+ include_labels: list[str] | None = None,
50
+ exclude_labels: list[str] | None = None,
52
51
  ) -> AnnotationDuration:
53
52
  """
54
53
  アノテーションZIPファイルからインスタンスを生成します。
@@ -9,11 +9,9 @@ import abc
9
9
  import itertools
10
10
  import logging
11
11
  from pathlib import Path
12
- from typing import Any, Optional
12
+ from typing import Any
13
13
 
14
- import bokeh
15
14
  import bokeh.layouts
16
- import bokeh.palettes
17
15
  import pandas
18
16
  from annofabapi.models import TaskPhase
19
17
  from bokeh.models.ui import UIElement
@@ -68,7 +66,7 @@ def _create_cumulative_dataframe(task_worktime_by_phase_user: TaskWorktimeByPhas
68
66
  class AbstractPhaseCumulativeProductivity(abc.ABC):
69
67
  """ロールごとの累積の生産性をプロットするための抽象クラス"""
70
68
 
71
- def __init__(self, df: pandas.DataFrame, phase: TaskPhase, *, custom_production_volume_list: Optional[list[ProductionVolumeColumn]] = None) -> None:
69
+ def __init__(self, df: pandas.DataFrame, phase: TaskPhase, *, custom_production_volume_list: list[ProductionVolumeColumn] | None = None) -> None:
72
70
  self.df = df
73
71
  self.phase = phase
74
72
  self.phase_name = self._get_phase_name(phase)
@@ -110,7 +108,7 @@ class AbstractPhaseCumulativeProductivity(abc.ABC):
110
108
  user_id_list: list[str],
111
109
  output_file: Path,
112
110
  *,
113
- metadata: Optional[dict[str, Any]],
111
+ metadata: dict[str, Any] | None,
114
112
  ) -> None:
115
113
  """
116
114
  折れ線グラフを、HTMLファイルに出力します。
@@ -150,7 +148,7 @@ class AbstractPhaseCumulativeProductivity(abc.ABC):
150
148
  username = df_subset.iloc[0]["username"]
151
149
 
152
150
  line_count += 1
153
- for line_graph, (x_column, y_column) in zip(line_graph_list, columns_list):
151
+ for line_graph, (x_column, y_column) in zip(line_graph_list, columns_list, strict=False):
154
152
  line_graph.add_line(source, x_column=x_column, y_column=y_column, legend_label=username, color=color)
155
153
 
156
154
  plotted_users.append((user_id, username))
@@ -184,14 +182,14 @@ class AbstractPhaseCumulativeProductivity(abc.ABC):
184
182
  production_volume_name: str,
185
183
  output_file: Path,
186
184
  *,
187
- target_user_id_list: Optional[list[str]] = None,
188
- metadata: Optional[dict[str, Any]] = None,
185
+ target_user_id_list: list[str] | None = None,
186
+ metadata: dict[str, Any] | None = None,
189
187
  ) -> None:
190
188
  raise NotImplementedError()
191
189
 
192
190
 
193
191
  class AnnotatorCumulativeProductivity(AbstractPhaseCumulativeProductivity):
194
- def __init__(self, df: pandas.DataFrame, *, custom_production_volume_list: Optional[list[ProductionVolumeColumn]] = None) -> None:
192
+ def __init__(self, df: pandas.DataFrame, *, custom_production_volume_list: list[ProductionVolumeColumn] | None = None) -> None:
195
193
  super().__init__(df, phase=TaskPhase.ANNOTATION, custom_production_volume_list=custom_production_volume_list)
196
194
 
197
195
  @classmethod
@@ -205,8 +203,8 @@ class AnnotatorCumulativeProductivity(AbstractPhaseCumulativeProductivity):
205
203
  production_volume_name: str,
206
204
  output_file: Path,
207
205
  *,
208
- target_user_id_list: Optional[list[str]] = None,
209
- metadata: Optional[dict[str, Any]] = None,
206
+ target_user_id_list: list[str] | None = None,
207
+ metadata: dict[str, Any] | None = None,
210
208
  ) -> None:
211
209
  """
212
210
  生産性を教師付作業者ごとにプロットする。
@@ -267,7 +265,7 @@ class AnnotatorCumulativeProductivity(AbstractPhaseCumulativeProductivity):
267
265
 
268
266
 
269
267
  class InspectorCumulativeProductivity(AbstractPhaseCumulativeProductivity):
270
- def __init__(self, df: pandas.DataFrame, *, custom_production_volume_list: Optional[list[ProductionVolumeColumn]] = None) -> None:
268
+ def __init__(self, df: pandas.DataFrame, *, custom_production_volume_list: list[ProductionVolumeColumn] | None = None) -> None:
271
269
  super().__init__(df, phase=TaskPhase.INSPECTION, custom_production_volume_list=custom_production_volume_list)
272
270
 
273
271
  @classmethod
@@ -281,8 +279,8 @@ class InspectorCumulativeProductivity(AbstractPhaseCumulativeProductivity):
281
279
  production_volume_name: str,
282
280
  output_file: Path,
283
281
  *,
284
- target_user_id_list: Optional[list[str]] = None,
285
- metadata: Optional[dict[str, Any]] = None,
282
+ target_user_id_list: list[str] | None = None,
283
+ metadata: dict[str, Any] | None = None,
286
284
  ) -> None:
287
285
  """
288
286
  生産性を検査作業者ごとにプロットする。
@@ -329,7 +327,7 @@ class InspectorCumulativeProductivity(AbstractPhaseCumulativeProductivity):
329
327
 
330
328
 
331
329
  class AcceptorCumulativeProductivity(AbstractPhaseCumulativeProductivity):
332
- def __init__(self, df: pandas.DataFrame, *, custom_production_volume_list: Optional[list[ProductionVolumeColumn]] = None) -> None:
330
+ def __init__(self, df: pandas.DataFrame, *, custom_production_volume_list: list[ProductionVolumeColumn] | None = None) -> None:
333
331
  super().__init__(df, phase=TaskPhase.ACCEPTANCE, custom_production_volume_list=custom_production_volume_list)
334
332
 
335
333
  @classmethod
@@ -343,8 +341,8 @@ class AcceptorCumulativeProductivity(AbstractPhaseCumulativeProductivity):
343
341
  production_volume_name: str,
344
342
  output_file: Path,
345
343
  *,
346
- target_user_id_list: Optional[list[str]] = None,
347
- metadata: Optional[dict[str, Any]] = None,
344
+ target_user_id_list: list[str] | None = None,
345
+ metadata: dict[str, Any] | None = None,
348
346
  ) -> None:
349
347
  """
350
348
  生産性を受入作業者ごとにプロットする。