annofabcli 1.99.0__py3-none-any.whl → 1.100.3__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 (41) hide show
  1. annofabcli/__version__.py +1 -1
  2. annofabcli/annotation/change_annotation_attributes.py +2 -2
  3. annofabcli/annotation_specs/add_attribute_restriction.py +158 -0
  4. annofabcli/annotation_specs/attribute_restriction.py +240 -0
  5. annofabcli/annotation_specs/list_annotation_specs_attribute.py +51 -33
  6. annofabcli/annotation_specs/list_annotation_specs_choice.py +42 -17
  7. annofabcli/annotation_specs/list_annotation_specs_history.py +0 -1
  8. annofabcli/annotation_specs/list_annotation_specs_label.py +26 -93
  9. annofabcli/annotation_specs/list_annotation_specs_label_attribute.py +220 -0
  10. annofabcli/annotation_specs/list_attribute_restriction.py +8 -209
  11. annofabcli/annotation_specs/subcommand_annotation_specs.py +4 -0
  12. annofabcli/common/annofab/annotation_specs.py +25 -0
  13. annofabcli/common/cli.py +0 -29
  14. annofabcli/common/download.py +1 -1
  15. annofabcli/common/exceptions.py +2 -2
  16. annofabcli/common/facade.py +2 -2
  17. annofabcli/common/image.py +2 -2
  18. annofabcli/input_data/delete_input_data.py +6 -7
  19. annofabcli/input_data/list_input_data.py +0 -1
  20. annofabcli/instruction/list_instruction_history.py +0 -1
  21. annofabcli/job/delete_job.py +4 -4
  22. annofabcli/job/list_job.py +0 -1
  23. annofabcli/job/list_last_job.py +0 -1
  24. annofabcli/organization_member/list_organization_member.py +3 -5
  25. annofabcli/project/list_project.py +0 -3
  26. annofabcli/project_member/change_project_members.py +2 -3
  27. annofabcli/project_member/drop_project_members.py +8 -8
  28. annofabcli/project_member/invite_project_members.py +5 -6
  29. annofabcli/project_member/list_users.py +5 -7
  30. annofabcli/statistics/visualization/dataframe/task.py +0 -3
  31. annofabcli/task/complete_tasks.py +2 -2
  32. annofabcli/task/list_all_tasks.py +0 -1
  33. annofabcli/task/list_tasks.py +0 -2
  34. annofabcli/task/reject_tasks.py +76 -100
  35. annofabcli/task/update_metadata_of_task.py +1 -1
  36. annofabcli/task_history/list_task_history.py +1 -1
  37. {annofabcli-1.99.0.dist-info → annofabcli-1.100.3.dist-info}/METADATA +3 -8
  38. {annofabcli-1.99.0.dist-info → annofabcli-1.100.3.dist-info}/RECORD +41 -37
  39. {annofabcli-1.99.0.dist-info → annofabcli-1.100.3.dist-info}/LICENSE +0 -0
  40. {annofabcli-1.99.0.dist-info → annofabcli-1.100.3.dist-info}/WHEEL +0 -0
  41. {annofabcli-1.99.0.dist-info → annofabcli-1.100.3.dist-info}/entry_points.txt +0 -0
@@ -48,16 +48,16 @@ class ListUser(CommandLine):
48
48
  for project_id in project_id_list:
49
49
  try:
50
50
  project, _ = self.service.api.get_project(project_id)
51
- except requests.exceptions.HTTPError as e:
52
- logger.warning(e)
51
+ except requests.exceptions.HTTPError:
53
52
  logger.warning(
54
- f"project_id = {project_id} のプロジェクトにアクセスできなかった(存在しないproject_id、またはプロジェクトメンバでない)"
53
+ f"project_id='{project_id}' のプロジェクトにアクセスできなかった(存在しないproject_id、またはプロジェクトメンバでない)",
54
+ exc_info=True,
55
55
  )
56
56
  continue
57
57
 
58
58
  project_title = project["title"]
59
59
  project_members = self.get_all_project_members(project_id, include_inactive=include_inactive)
60
- logger.info(f"{project_title} のプロジェクトメンバを {len(project_members)} 件取得した。project_id={project_id}")
60
+ logger.info(f"{project_title} のプロジェクトメンバを {len(project_members)} 件取得した。project_id='{project_id}'")
61
61
 
62
62
  for member in project_members:
63
63
  AddProps.add_properties_of_project(member, project_title)
@@ -75,9 +75,8 @@ class ListUser(CommandLine):
75
75
  include_inactive=args.include_inactive,
76
76
  )
77
77
 
78
- logger.info(f"プロジェトメンバ一覧の件数: {len(project_members)}")
78
+ logger.info(f"プロジェクトメンバ一覧の件数: {len(project_members)}")
79
79
  if args.format == FormatArgument.CSV.value:
80
- project_members = self.search_with_jmespath_expression(project_members)
81
80
  df = pandas.DataFrame(project_members)
82
81
  columns = get_columns_with_priority(df, prior_columns=self.PRIOR_COLUMNS)
83
82
  self.print_csv(df[columns])
@@ -111,7 +110,6 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
111
110
  )
112
111
  argument_parser.add_output()
113
112
  argument_parser.add_csv_format()
114
- argument_parser.add_query()
115
113
 
116
114
  parser.set_defaults(subcommand_func=main)
117
115
 
@@ -152,9 +152,6 @@ class Task:
152
152
  "inspection_comment_count",
153
153
  "inspection_comment_count_in_inspection_phase",
154
154
  "inspection_comment_count_in_acceptance_phase",
155
- # タスクの状態
156
- "inspection_is_skipped",
157
- "acceptance_is_skipped",
158
155
  ]
159
156
 
160
157
  @property
@@ -76,7 +76,7 @@ class CompleteTasksMain(CommandLineWithConfirm):
76
76
  comment_status: CommentStatus,
77
77
  ):
78
78
  if comment_list is None or len(comment_list) == 0:
79
- logger.warning(f"変更対象の検査コメントはなかった。task_id = {task.task_id}, input_data_id = {input_data_id}")
79
+ logger.warning(f"変更対象の検査コメントはなかった。task_id='{task.task_id}', input_data_id='{input_data_id}'")
80
80
  return
81
81
 
82
82
  def to_req_inspection(comment: dict[str, Any]) -> dict[str, Any]:
@@ -332,7 +332,7 @@ class CompleteTasksMain(CommandLineWithConfirm):
332
332
 
333
333
  task: Task = Task.from_dict(dict_task)
334
334
  logger.info(
335
- f"{logging_prefix} : タスク情報 task_id={task_id}, phase={task.phase.value}, phase_stage={task.phase_stage}, status={task.status.value}"
335
+ f"{logging_prefix} : タスク情報 task_id='{task_id}', phase={task.phase.value}, phase_stage={task.phase_stage}, status={task.status.value}"
336
336
  )
337
337
  if not self._validate_task(task, target_phase=target_phase, target_phase_stage=target_phase_stage, task_query=task_query):
338
338
  return False
@@ -97,7 +97,6 @@ class ListTasksWithJson(CommandLine):
97
97
 
98
98
  if len(task_list) > 0:
99
99
  if self.str_format == FormatArgument.CSV.value:
100
- task_list = self.search_with_jmespath_expression(task_list)
101
100
  df = pandas.DataFrame(task_list)
102
101
  columns = get_columns_with_priority(df, prior_columns=ListTasks.PRIOR_COLUMNS)
103
102
  self.print_csv(df[columns])
@@ -196,7 +196,6 @@ class ListTasks(CommandLine):
196
196
 
197
197
  if len(task_list) > 0:
198
198
  if self.str_format == FormatArgument.CSV.value:
199
- task_list = self.search_with_jmespath_expression(task_list)
200
199
  df = pandas.DataFrame(task_list)
201
200
  columns = get_columns_with_priority(df, prior_columns=self.PRIOR_COLUMNS)
202
201
  self.print_csv(df[columns])
@@ -255,7 +254,6 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
255
254
  argument_parser.add_output()
256
255
  argument_parser.add_csv_format()
257
256
 
258
- argument_parser.add_query()
259
257
  parser.set_defaults(subcommand_func=main)
260
258
 
261
259
 
@@ -27,7 +27,6 @@ from annofabcli.common.cli import (
27
27
  )
28
28
  from annofabcli.common.enums import CustomProjectType
29
29
  from annofabcli.common.facade import AnnofabApiFacade, TaskQuery, match_task_with_query
30
- from annofabcli.common.utils import add_dryrun_prefix
31
30
 
32
31
  logger = logging.getLogger(__name__)
33
32
 
@@ -39,12 +38,12 @@ class RejectTasksMain(CommandLineWithConfirm):
39
38
  self.comment_data = comment_data
40
39
  CommandLineWithConfirm.__init__(self, all_yes)
41
40
 
42
- def add_inspection_comment( # noqa: ANN201
41
+ def add_inspection_comment(
43
42
  self,
44
43
  project_id: str,
45
44
  task: dict[str, Any],
46
45
  inspection_comment: str,
47
- ):
46
+ ) -> None:
48
47
  """
49
48
  検査コメントを付与する。
50
49
 
@@ -53,9 +52,6 @@ class RejectTasksMain(CommandLineWithConfirm):
53
52
  task:
54
53
  inspection_comment:
55
54
 
56
- Returns:
57
- 更新した検査コメントの一覧
58
-
59
55
  """
60
56
  first_input_data_id = task["input_data_id_list"][0]
61
57
 
@@ -72,14 +68,14 @@ class RejectTasksMain(CommandLineWithConfirm):
72
68
  }
73
69
  ]
74
70
 
75
- return self.service.api.batch_update_comments(project_id, task["task_id"], first_input_data_id, request_body=req_inspection)[0]
71
+ self.service.api.batch_update_comments(project_id, task["task_id"], first_input_data_id, request_body=req_inspection)
76
72
 
77
73
  def confirm_reject_task(self, task_id: str, assign_last_annotator: bool, assigned_annotator_user_id: Optional[str]) -> bool: # noqa: FBT001
78
- confirm_message = f"task_id = {task_id} のタスクを差し戻しますか?"
74
+ confirm_message = f"task_id='{task_id}' のタスクを差し戻しますか?"
79
75
  if assign_last_annotator:
80
- confirm_message += "最後のannotation phaseの担当者を割り当てます。"
76
+ confirm_message += "最後の教師付フェーズの担当者を割り当てます。"
81
77
  elif assigned_annotator_user_id is not None:
82
- confirm_message += f"ユーザ '{assigned_annotator_user_id}' を担当者に割り当てます。"
78
+ confirm_message += f"user_id='{assigned_annotator_user_id}'のユーザーを担当者に割り当てます。"
83
79
  else:
84
80
  confirm_message += "担当者は割り当てません。"
85
81
 
@@ -99,50 +95,53 @@ class RejectTasksMain(CommandLineWithConfirm):
99
95
 
100
96
  task_id = task["task_id"]
101
97
  last_updated_datetime = task["updated_datetime"]
102
- try:
103
- if task["account_id"] != self.service.api.account_id:
104
- _task = self.service.wrapper.change_task_operator(
105
- project_id,
106
- task_id,
107
- operator_account_id=self.service.api.account_id,
108
- last_updated_datetime=last_updated_datetime,
109
- )
110
- last_updated_datetime = _task["updated_datetime"]
111
- logger.debug(f"{task_id}: 担当者を自分自身に変更しました。")
112
-
113
- changed_task = self.service.wrapper.change_task_status_to_working(project_id, task_id, last_updated_datetime=last_updated_datetime)
114
- return changed_task # noqa: TRY300
98
+ if task["account_id"] != self.service.api.account_id:
99
+ _task = self.service.wrapper.change_task_operator(
100
+ project_id,
101
+ task_id,
102
+ operator_account_id=self.service.api.account_id,
103
+ last_updated_datetime=last_updated_datetime,
104
+ )
105
+ last_updated_datetime = _task["updated_datetime"]
106
+ logger.debug(f"task_id='{task_id}'のタスクの担当者を自分自身に変更しました。")
115
107
 
116
- except requests.HTTPError:
117
- logger.warning(f"{task_id}: 担当者の変更、または作業中状態への変更に失敗しました。", exc_info=True)
118
- raise
108
+ changed_task = self.service.wrapper.change_task_status_to_working(project_id, task_id, last_updated_datetime=last_updated_datetime)
109
+ logger.debug(f"task_id='{task_id}'のタスクのステータスを作業中に変更しました。")
110
+ return changed_task
119
111
 
120
- def _can_reject_task( # noqa: ANN202
112
+ def _can_reject_task(
121
113
  self,
122
114
  task: dict[str, Any],
123
- assign_last_annotator: bool, # noqa: FBT001
115
+ *,
116
+ assign_last_annotator: bool,
124
117
  assigned_annotator_user_id: Optional[str],
125
- cancel_acceptance: bool = False, # noqa: FBT001, FBT002
118
+ cancel_acceptance: bool = False,
126
119
  task_query: Optional[TaskQuery] = None,
127
- ):
120
+ ) -> bool:
121
+ """
122
+ 以下の状態を見て、差し戻し可能かどうかを判断します。
123
+ * タスクのフェーズやステータス
124
+ * `--task_query`の条件にマッチするかどうか
125
+ * 差し戻しの確認メッセージに対して、ユーザがOKしたかどうか
126
+ """
128
127
  task_id = task["task_id"]
129
128
  if task["phase"] == TaskPhase.ANNOTATION.value:
130
- logger.warning(f"task_id = {task_id}: annotation phaseのため、差し戻しできません。")
129
+ logger.warning(f"task_id='{task_id}' :: 教師付フェーズのため、差し戻しできません。")
131
130
  return False
132
131
 
133
132
  if task["status"] == TaskStatus.WORKING.value:
134
- logger.warning(f"task_id = {task_id} : タスクのstatusが'作業中'なので、差し戻しできません。")
133
+ logger.warning(f"task_id='{task_id}' :: タスクのstatusが'作業中'なので、差し戻しできません。")
135
134
  return False
136
135
 
137
136
  if task["status"] == TaskStatus.COMPLETE.value and not cancel_acceptance:
138
137
  logger.warning(
139
- f"task_id = {task_id} : タスクのstatusが'完了'なので、差し戻しできません。"
138
+ f"task_id='{task_id}' :: タスクのstatusが'完了'なので、差し戻しできません。"
140
139
  f"受入完了を取消す場合は、コマンドライン引数に'--cancel_acceptance'を追加してください。"
141
140
  )
142
141
  return False
143
142
 
144
143
  if not match_task_with_query(Task.from_dict(task), task_query):
145
- logger.debug(f"task_id = {task_id} : `--task_query`の条件にマッチしないため、スキップします。task_query={task_query}")
144
+ logger.debug(f"task_id='{task_id}' : `--task_query`の条件にマッチしないため、スキップします。 :: task_query='{task_query}'")
146
145
  return False
147
146
 
148
147
  if not self.confirm_reject_task(task_id, assign_last_annotator=assign_last_annotator, assigned_annotator_user_id=assigned_annotator_user_id): # noqa: SIM103
@@ -150,29 +149,20 @@ class RejectTasksMain(CommandLineWithConfirm):
150
149
 
151
150
  return True
152
151
 
153
- def _cancel_acceptance(self, task: dict[str, Any]) -> dict[str, Any]:
154
- request_body = {
155
- "status": "not_started",
156
- "account_id": self.service.api.account_id,
157
- "last_updated_datetime": task["updated_datetime"],
158
- }
159
- content, _ = self.service.api.operate_task(task["project_id"], task["task_id"], request_body=request_body)
160
- return content
161
-
162
152
  def reject_task_with_adding_comment(
163
153
  self,
164
154
  project_id: str,
165
155
  task_id: str,
156
+ *,
166
157
  inspection_comment: Optional[str] = None,
167
- assign_last_annotator: bool = True, # noqa: FBT001, FBT002
158
+ assign_last_annotator: bool = True,
168
159
  assigned_annotator_user_id: Optional[str] = None,
169
- cancel_acceptance: bool = False, # noqa: FBT001, FBT002
160
+ cancel_acceptance: bool = False,
170
161
  task_query: Optional[TaskQuery] = None,
171
162
  task_index: Optional[int] = None,
172
- dryrun: bool = False, # noqa: FBT001, FBT002
173
163
  ) -> bool:
174
164
  """
175
- タスクを強制的に差し戻す
165
+ タスクを差し戻します。
176
166
 
177
167
  Args:
178
168
  project_id:
@@ -185,36 +175,14 @@ class RejectTasksMain(CommandLineWithConfirm):
185
175
  タスクを差し戻したかどうか
186
176
  """
187
177
 
188
- def _add_inspection_comment(task: dict[str, Any], inspection_comment: str) -> dict[str, Any]:
189
- # 検査コメントを付与する
190
- if not dryrun:
191
- # 検査コメントを付与するには「作業中」状態にする必要があるので、担当者を自分自身に変更して作業中状態にする
192
- task = self.change_to_working_status(project_id, task)
193
-
194
- try:
195
- self.add_inspection_comment(project_id, task, inspection_comment)
196
- # 作業時間が増えすぎないようにするため、すぐに休憩中状態にする
197
- task = self.service.wrapper.change_task_status_to_break(project_id, task_id, last_updated_datetime=task["updated_datetime"])
198
- logger.debug(f"{logging_prefix} : task_id = {task_id}, 検査コメントを付与しました。")
199
- return task # noqa: TRY300
200
- except requests.exceptions.HTTPError:
201
- logger.warning(f"{logging_prefix} : task_id = {task_id} 検査コメントの付与に失敗しました。", exc_info=True)
202
- # 作業時間が増えすぎないようにするため、すぐに休憩中状態にする
203
- self.service.wrapper.change_task_status_to_break(project_id, task_id, last_updated_datetime=task["updated_datetime"])
204
- raise
205
- else:
206
- task, _ = self.service.api.get_task(project_id, task_id)
207
- logger.debug(f"{logging_prefix} : task_id = {task_id}, 検査コメントを付与しました。")
208
- return task
209
-
210
178
  logging_prefix = f"{task_index + 1} 件目" if task_index is not None else ""
211
179
 
212
180
  task = self.service.wrapper.get_task_or_none(project_id, task_id)
213
181
  if task is None:
214
- logger.warning(f"{logging_prefix} : task_id='{task_id}'のタスクをは存在しないので、スキップします。")
182
+ logger.warning(f"{logging_prefix} :: task_id='{task_id}'のタスクをは存在しないので、スキップします。")
215
183
  return False
216
184
 
217
- logger.debug(f"{logging_prefix} : task_id = {task['task_id']}, status = {task['status']}, phase = {task['phase']}, ")
185
+ logger.debug(f"{logging_prefix} :: task_id='{task['task_id']}', status='{task['status']}', phase='{task['phase']}'")
218
186
 
219
187
  if not self._can_reject_task(
220
188
  task=task,
@@ -225,19 +193,27 @@ class RejectTasksMain(CommandLineWithConfirm):
225
193
  ):
226
194
  return False
227
195
 
228
- if task["status"] == TaskStatus.COMPLETE.value and cancel_acceptance and not dryrun:
229
- task = self._cancel_acceptance(task)
196
+ if task["status"] == TaskStatus.COMPLETE.value and cancel_acceptance:
197
+ task = self.service.wrapper.cancel_completed_task(
198
+ project_id, task_id, operator_account_id=self.service.api.account_id, last_updated_datetime=task["updated_datetime"]
199
+ )
200
+ logger.debug(f"{logging_prefix} :: task_id='{task_id}'のタスクに対して受入取消を実施(完了状態から未着手状態に変更)しました。")
230
201
 
231
- if inspection_comment is not None:
232
- task = _add_inspection_comment(task, inspection_comment)
233
202
  try:
234
- if not dryrun:
235
- # タスクを差し戻す
236
- # 担当者やステータスに関係なく差し戻すため、`force=True`を指定する
237
- self.service.wrapper.reject_task(project_id, task_id, force=True, last_updated_datetime=task["updated_datetime"])
203
+ if inspection_comment is not None:
204
+ # タスクを作業中状態にして、検査コメントを付与できる状態にする
205
+ task = self.change_to_working_status(project_id, task)
206
+ # 検査コメントを付与する
207
+ self.add_inspection_comment(project_id, task, inspection_comment)
208
+ logger.debug(f"{logging_prefix} :: task_id='{task_id}'のタスクに検査コメントを付与しました。")
209
+
210
+ # `reject_task`の`force`引数について
211
+ # 検査コメントを付与しない場合は、強制差し戻しが必要なのでTrueを指定する
212
+ # 検査コメントを付与する場合は、 強制差し戻しは不要。チェッカーロールでも実行できるようにするため、Falseにする
213
+ self.service.wrapper.reject_task(project_id, task_id, force=(inspection_comment is None), last_updated_datetime=task["updated_datetime"])
238
214
 
239
215
  if assign_last_annotator:
240
- logger.info(f"{logging_prefix} : task_id = {task_id} のタスクを差し戻しました。タスクの担当者は直前の教師付フェーズの担当者です。")
216
+ logger.debug(f"{logging_prefix} :: task_id='{task_id}' のタスクを差し戻しました。タスクの担当者は直前の教師付フェーズの担当者です。")
241
217
  return True
242
218
 
243
219
  else:
@@ -247,14 +223,21 @@ class RejectTasksMain(CommandLineWithConfirm):
247
223
  else None
248
224
  )
249
225
 
250
- if not dryrun:
251
- self.service.wrapper.change_task_operator(project_id, task_id, operator_account_id=assigned_annotator_account_id)
226
+ self.service.wrapper.change_task_operator(project_id, task_id, operator_account_id=assigned_annotator_account_id)
252
227
 
253
- logger.info(f"{logging_prefix} : task_id = {task_id} のタスクを差し戻しました。タスクの担当者: {assigned_annotator_user_id}")
228
+ logger.debug(f"{logging_prefix} :: task_id='{task_id}' のタスクを差し戻しました。タスクの担当者: '{assigned_annotator_user_id}'")
254
229
  return True
255
230
 
256
231
  except requests.exceptions.HTTPError:
257
- logger.warning(f"{logging_prefix} : task_id = {task_id} タスクの差し戻しに失敗しました。", exc_info=True)
232
+ logger.warning(f"{logging_prefix} : task_id='{task_id}'のタスクの差し戻しに失敗しました。", exc_info=True)
233
+
234
+ task, _ = self.service.api.get_task(project_id, task_id)
235
+ assert task is not None
236
+ # 作業中状態のまま放置すると、作業時間が超過してしまうため、休憩状態にする
237
+ if task["status"] == TaskStatus.WORKING.value:
238
+ self.service.wrapper.change_task_status_to_break(project_id, task_id, last_updated_datetime=task["updated_datetime"])
239
+ logger.debug(f"{logging_prefix} :: task_id='{task_id}' のタスクを休憩状態に戻しました。")
240
+
258
241
  return False
259
242
 
260
243
  def reject_task_for_task_wrapper(
@@ -266,7 +249,6 @@ class RejectTasksMain(CommandLineWithConfirm):
266
249
  assigned_annotator_user_id: Optional[str] = None,
267
250
  cancel_acceptance: bool = False, # noqa: FBT001, FBT002
268
251
  task_query: Optional[TaskQuery] = None,
269
- dryrun: bool = False, # noqa: FBT001, FBT002
270
252
  ) -> bool:
271
253
  task_index, task_id = tpl
272
254
  try:
@@ -279,7 +261,6 @@ class RejectTasksMain(CommandLineWithConfirm):
279
261
  assigned_annotator_user_id=assigned_annotator_user_id,
280
262
  cancel_acceptance=cancel_acceptance,
281
263
  task_query=task_query,
282
- dryrun=dryrun,
283
264
  )
284
265
  except Exception: # pylint: disable=broad-except
285
266
  logger.warning(f"タスク'{task_id}'の差し戻しに失敗しました。", exc_info=True)
@@ -295,7 +276,6 @@ class RejectTasksMain(CommandLineWithConfirm):
295
276
  cancel_acceptance: bool = False, # noqa: FBT001, FBT002
296
277
  task_query: Optional[TaskQuery] = None,
297
278
  parallelism: Optional[int] = None,
298
- dryrun: bool = False, # noqa: FBT001, FBT002
299
279
  ) -> None:
300
280
  if task_query is not None:
301
281
  task_query = self.facade.set_account_id_of_task_query(project_id, task_query)
@@ -311,7 +291,6 @@ class RejectTasksMain(CommandLineWithConfirm):
311
291
  assigned_annotator_user_id=assigned_annotator_user_id,
312
292
  cancel_acceptance=cancel_acceptance,
313
293
  task_query=task_query,
314
- dryrun=dryrun,
315
294
  )
316
295
  with multiprocessing.Pool(parallelism) as pool:
317
296
  result_bool_list = pool.map(partial_func, enumerate(task_id_list))
@@ -331,7 +310,6 @@ class RejectTasksMain(CommandLineWithConfirm):
331
310
  assigned_annotator_user_id=assigned_annotator_user_id,
332
311
  cancel_acceptance=cancel_acceptance,
333
312
  task_query=task_query,
334
- dryrun=dryrun,
335
313
  )
336
314
  if result:
337
315
  success_count += 1
@@ -360,13 +338,14 @@ class RejectTasks(CommandLine):
360
338
  if not self.validate(args):
361
339
  sys.exit(COMMAND_LINE_ERROR_STATUS_CODE)
362
340
 
363
- if args.dryrun:
364
- add_dryrun_prefix(logger)
365
-
366
341
  task_id_list = annofabcli.common.cli.get_list_from_args(args.task_id)
367
342
  assign_last_annotator = not args.not_assign and args.assigned_annotator_user_id is None
368
343
 
369
- super().validate_project(args.project_id, [ProjectMemberRole.OWNER])
344
+ if not args.cancel_acceptance and args.comment is not None:
345
+ # 受入取消を実施しない AND 検査コメントを付与する場合はチェッカーロールでも実行できる
346
+ super().validate_project(args.project_id, [ProjectMemberRole.OWNER, ProjectMemberRole.ACCEPTER])
347
+ else:
348
+ super().validate_project(args.project_id, [ProjectMemberRole.OWNER])
370
349
 
371
350
  dict_task_query = annofabcli.common.cli.get_json_from_args(args.task_query)
372
351
  task_query: Optional[TaskQuery] = TaskQuery.from_dict(dict_task_query) if dict_task_query is not None else None
@@ -405,7 +384,6 @@ class RejectTasks(CommandLine):
405
384
  cancel_acceptance=args.cancel_acceptance,
406
385
  task_query=task_query,
407
386
  parallelism=args.parallelism,
408
- dryrun=args.dryrun,
409
387
  )
410
388
 
411
389
 
@@ -474,7 +452,6 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
474
452
  choices=PARALLELISM_CHOICES,
475
453
  help="使用するプロセス数(並列度)を指定してください。指定する場合は必ず ``--yes`` を指定してください。指定しない場合は、逐次的に処理します。", # noqa: E501
476
454
  )
477
- parser.add_argument("--dryrun", action="store_true", help="差し戻しが行われた時の結果を表示しますが、実際はタスクを差し戻しません。")
478
455
 
479
456
  parser.set_defaults(subcommand_func=main)
480
457
 
@@ -482,12 +459,11 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
482
459
  def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
483
460
  subcommand_name = "reject"
484
461
  subcommand_help = "タスクを差し戻します。"
485
- description = (
486
- "タスクを差し戻します。差し戻す際、検査コメントを付与することもできます。"
487
- "作業中状態のタスクに対しては指し戻せません。"
488
- "このコマンドで差し戻したタスクは、画面から差し戻したタスクとは異なり、抜取検査・抜取受入のスキップ判定に影響を及ぼしません。"
462
+ description = "タスクを差し戻します。差し戻す際、検査コメントを付与することもできます。作業中状態のタスクに対しては差し戻せません。"
463
+ epilog = (
464
+ "オーナロールを持つユーザで実行してください。"
465
+ "``--cancel_acceptance`` を指定していない AND ``--comment`` を指定している場合は、チェッカーロールを持つユーザーも実行できます。"
489
466
  )
490
- epilog = "オーナロールを持つユーザで実行してください。"
491
467
 
492
468
  parser = annofabcli.common.cli.add_parser(subparsers, subcommand_name, subcommand_help, description, epilog=epilog)
493
469
  parse_args(parser)
@@ -259,7 +259,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
259
259
  parser.add_argument(
260
260
  "--overwrite",
261
261
  action="store_true",
262
- help="指定した場合、メタデータを上書きして更新します(すでに設定されているメタデータは削除されます)。指定しない場合、 ``--metadata`` に指定されたキーのみ更新されます。", # noqa: E501
262
+ help="指定した場合、メタデータを上書きして更新します(すでに設定されているメタデータは削除されます)。指定しない場合、 ``--metadata`` に指定されたキーのみ更新されます。 ``--yes`` と一緒に指定すると、処理時間は大幅に短くなります。", # noqa: E501
263
263
  )
264
264
 
265
265
  parser.add_argument(
@@ -42,7 +42,7 @@ class ListTaskHistoryMain:
42
42
  logger.info(f"{task_index + 1} 件のタスクの履歴情報を取得しました。")
43
43
  if task_history_list is not None:
44
44
  if len(task_history_list) == 0:
45
- logger.debug(f"task_id='{task_id}`の履歴情報は0件でした。")
45
+ logger.debug(f"task_id='{task_id}'の履歴情報は0件でした。")
46
46
  task_history_dict[task_id] = task_history_list
47
47
  else:
48
48
  logger.warning(f"task_id='{task_id}'のタスク履歴は見つかりませんでした。")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: annofabcli
3
- Version: 1.99.0
3
+ Version: 1.100.3
4
4
  Summary: Utility Command Line Interface for AnnoFab
5
5
  Home-page: https://github.com/kurusugawa-computer/annofab-cli
6
6
  License: MIT
@@ -23,7 +23,6 @@ Requires-Dist: annofabapi (>=1.4.1,<2.0.0)
23
23
  Requires-Dist: bokeh (>=3.3,<3.7)
24
24
  Requires-Dist: dictdiffer
25
25
  Requires-Dist: isodate
26
- Requires-Dist: jmespath
27
26
  Requires-Dist: more-itertools
28
27
  Requires-Dist: numpy
29
28
  Requires-Dist: pandas (>=2,<3)
@@ -58,14 +57,10 @@ Description-Content-Type: text/markdown
58
57
 
59
58
 
60
59
  ## 廃止予定
61
-
62
-
63
- ### 2022-11-01 以降
64
- * JMESPathを指定できる `--query`を削除します。使いどころがあまりないのと、`jq`コマンドでも対応できるためです。
65
-
60
+ * TODO
66
61
 
67
62
  # Requirements
68
- * Python 3.9
63
+ * Python 3.9+
69
64
 
70
65
  # Install
71
66