annofabcli 1.95.0__py3-none-any.whl → 1.96.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.
- annofabcli/__version__.py +1 -1
- annofabcli/annotation_specs/export_annotation_specs.py +10 -5
- annofabcli/statistics/list_annotation_attribute.py +310 -0
- annofabcli/statistics/subcommand_statistics.py +2 -0
- {annofabcli-1.95.0.dist-info → annofabcli-1.96.0.dist-info}/METADATA +1 -1
- {annofabcli-1.95.0.dist-info → annofabcli-1.96.0.dist-info}/RECORD +9 -8
- {annofabcli-1.95.0.dist-info → annofabcli-1.96.0.dist-info}/LICENSE +0 -0
- {annofabcli-1.95.0.dist-info → annofabcli-1.96.0.dist-info}/WHEEL +0 -0
- {annofabcli-1.95.0.dist-info → annofabcli-1.96.0.dist-info}/entry_points.txt +0 -0
annofabcli/__version__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "1.
|
|
1
|
+
__version__ = "1.96.0" # `poetry-dynamic-versioning`を使ってGitHubのバージョンタグを取得している。変更不要
|
|
@@ -20,15 +20,20 @@ from annofabcli.common.utils import print_according_to_format
|
|
|
20
20
|
logger = logging.getLogger(__name__)
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
class
|
|
23
|
+
class ExportAnnotationSpecs(CommandLine):
|
|
24
24
|
COMMON_MESSAGE = "annofabcli annotation_specs export: error:"
|
|
25
25
|
|
|
26
26
|
def get_history_id_from_before_index(self, project_id: str, before: int) -> Optional[str]:
|
|
27
27
|
histories, _ = self.service.api.get_annotation_specs_histories(project_id)
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
sorted_histories = sorted(histories, key=lambda x: x["updated_datetime"], reverse=True)
|
|
29
|
+
|
|
30
|
+
if before + 1 > len(sorted_histories):
|
|
31
|
+
logger.warning(
|
|
32
|
+
f"アノテーション仕様の履歴は{len(sorted_histories)}個のため、最新より{before}個前のアノテーション仕様は見つかりませんでした。"
|
|
33
|
+
)
|
|
30
34
|
return None
|
|
31
|
-
|
|
35
|
+
|
|
36
|
+
history = sorted_histories[before]
|
|
32
37
|
return history["history_id"]
|
|
33
38
|
|
|
34
39
|
def get_exported_annotation_specs(self, project_id: str, history_id: Optional[str]) -> dict[str, Any]:
|
|
@@ -107,7 +112,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
|
|
|
107
112
|
def main(args: argparse.Namespace) -> None:
|
|
108
113
|
service = build_annofabapi_resource_and_login(args)
|
|
109
114
|
facade = AnnofabApiFacade(service)
|
|
110
|
-
|
|
115
|
+
ExportAnnotationSpecs(service, facade, args).main()
|
|
111
116
|
|
|
112
117
|
|
|
113
118
|
def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
# pylint: disable=too-many-lines
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import argparse
|
|
5
|
+
import logging
|
|
6
|
+
import sys
|
|
7
|
+
import tempfile
|
|
8
|
+
import zipfile
|
|
9
|
+
from collections.abc import Collection, Iterator
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any, Literal, Optional, Union
|
|
12
|
+
|
|
13
|
+
import pandas
|
|
14
|
+
import pydantic
|
|
15
|
+
from annofabapi.models import ProjectMemberRole
|
|
16
|
+
from annofabapi.parser import (
|
|
17
|
+
SimpleAnnotationParser,
|
|
18
|
+
lazy_parse_simple_annotation_dir,
|
|
19
|
+
lazy_parse_simple_annotation_zip,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
import annofabcli
|
|
23
|
+
import annofabcli.common.cli
|
|
24
|
+
from annofabcli.common.cli import (
|
|
25
|
+
COMMAND_LINE_ERROR_STATUS_CODE,
|
|
26
|
+
ArgumentParser,
|
|
27
|
+
CommandLine,
|
|
28
|
+
build_annofabapi_resource_and_login,
|
|
29
|
+
)
|
|
30
|
+
from annofabcli.common.download import DownloadingFile
|
|
31
|
+
from annofabcli.common.enums import FormatArgument
|
|
32
|
+
from annofabcli.common.facade import (
|
|
33
|
+
AnnofabApiFacade,
|
|
34
|
+
TaskQuery,
|
|
35
|
+
match_annotation_with_task_query,
|
|
36
|
+
)
|
|
37
|
+
from annofabcli.common.type_util import assert_noreturn
|
|
38
|
+
from annofabcli.common.utils import print_csv, print_json
|
|
39
|
+
|
|
40
|
+
logger = logging.getLogger(__name__)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def lazy_parse_simple_annotation_by_input_data(annotation_path: Path) -> Iterator[SimpleAnnotationParser]:
|
|
44
|
+
if not annotation_path.exists():
|
|
45
|
+
raise RuntimeError(f"'{annotation_path}' は存在しません。")
|
|
46
|
+
|
|
47
|
+
if annotation_path.is_dir():
|
|
48
|
+
return lazy_parse_simple_annotation_dir(annotation_path)
|
|
49
|
+
elif zipfile.is_zipfile(str(annotation_path)):
|
|
50
|
+
return lazy_parse_simple_annotation_zip(annotation_path)
|
|
51
|
+
else:
|
|
52
|
+
raise RuntimeError(f"'{annotation_path}'は、zipファイルまたはディレクトリではありません。")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class AnnotationAttribute(pydantic.BaseModel):
|
|
56
|
+
"""
|
|
57
|
+
入力データまたはタスク単位の区間アノテーションの長さ情報。
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
task_id: str
|
|
61
|
+
task_status: str
|
|
62
|
+
task_phase: str
|
|
63
|
+
task_phase_stage: int
|
|
64
|
+
|
|
65
|
+
input_data_id: str
|
|
66
|
+
input_data_name: str
|
|
67
|
+
annotation_id: str
|
|
68
|
+
label: str
|
|
69
|
+
attributes: dict[str, Union[str, int, bool]]
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def get_annotation_attribute_list_from_annotation_json(
|
|
73
|
+
simple_annotation: dict[str, Any], *, target_labels: Collection[str] | None = None
|
|
74
|
+
) -> list[AnnotationAttribute]:
|
|
75
|
+
"""
|
|
76
|
+
1個のアノテーションJSONに対して、アノテーションの属性情報を取得します。
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
simple_annotation: アノテーションJSONファイルの内容
|
|
80
|
+
target_labels: 絞り込むラベルのcollection
|
|
81
|
+
"""
|
|
82
|
+
details = simple_annotation["details"]
|
|
83
|
+
|
|
84
|
+
result = []
|
|
85
|
+
for detail in details:
|
|
86
|
+
if target_labels is not None: # noqa: SIM102
|
|
87
|
+
if detail["label"] not in target_labels:
|
|
88
|
+
continue
|
|
89
|
+
|
|
90
|
+
result.append(
|
|
91
|
+
AnnotationAttribute(
|
|
92
|
+
task_id=simple_annotation["task_id"],
|
|
93
|
+
task_status=simple_annotation["task_status"],
|
|
94
|
+
task_phase=simple_annotation["task_phase"],
|
|
95
|
+
task_phase_stage=simple_annotation["task_phase_stage"],
|
|
96
|
+
input_data_id=simple_annotation["input_data_id"],
|
|
97
|
+
input_data_name=simple_annotation["input_data_name"],
|
|
98
|
+
label=detail["label"],
|
|
99
|
+
annotation_id=detail["annotation_id"],
|
|
100
|
+
attributes=detail["attributes"],
|
|
101
|
+
)
|
|
102
|
+
)
|
|
103
|
+
return result
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def get_annotation_attribute_list_from_annotation_zipdir_path(
|
|
107
|
+
annotation_zipdir_path: Path,
|
|
108
|
+
*,
|
|
109
|
+
target_task_ids: Optional[Collection[str]] = None,
|
|
110
|
+
task_query: Optional[TaskQuery] = None,
|
|
111
|
+
target_labels: Collection[str] | None = None,
|
|
112
|
+
) -> list[AnnotationAttribute]:
|
|
113
|
+
"""
|
|
114
|
+
アノテーションzipまたはそれを展開したディレクトリから、アノテーションの属性のlistを取得します。
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
"""
|
|
118
|
+
target_task_ids = set(target_task_ids) if target_task_ids is not None else None
|
|
119
|
+
|
|
120
|
+
iter_parser = lazy_parse_simple_annotation_by_input_data(annotation_zipdir_path)
|
|
121
|
+
|
|
122
|
+
result = []
|
|
123
|
+
logger.debug("アノテーションzipまたはディレクトリを読み込み中")
|
|
124
|
+
for index, parser in enumerate(iter_parser):
|
|
125
|
+
if (index + 1) % 1000 == 0:
|
|
126
|
+
logger.debug(f"{index + 1} 件目のJSONを読み込み中")
|
|
127
|
+
|
|
128
|
+
if target_task_ids is not None and parser.task_id not in target_task_ids:
|
|
129
|
+
continue
|
|
130
|
+
|
|
131
|
+
simple_annotation_dict = parser.load_json()
|
|
132
|
+
if task_query is not None: # noqa: SIM102
|
|
133
|
+
if not match_annotation_with_task_query(simple_annotation_dict, task_query):
|
|
134
|
+
continue
|
|
135
|
+
|
|
136
|
+
sub_result = get_annotation_attribute_list_from_annotation_json(simple_annotation_dict, target_labels=target_labels)
|
|
137
|
+
result.extend(sub_result)
|
|
138
|
+
|
|
139
|
+
return result
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def print_annotation_attribute_list_as_csv(annotation_attribute_list: list, output_file: Optional[Path]) -> None:
|
|
143
|
+
df = pandas.json_normalize(annotation_attribute_list)
|
|
144
|
+
|
|
145
|
+
# columns = [
|
|
146
|
+
# "task_id",
|
|
147
|
+
# "task_status"
|
|
148
|
+
# "task_phase",
|
|
149
|
+
# "task_phase_stage",
|
|
150
|
+
# "input_data_id",
|
|
151
|
+
# "input_data_name",
|
|
152
|
+
# "annotation_id",
|
|
153
|
+
# "label",
|
|
154
|
+
|
|
155
|
+
# ]
|
|
156
|
+
|
|
157
|
+
print_csv(df, output_file)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def print_annotation_attribute_list(
|
|
161
|
+
annotation_attribute_list: list[AnnotationAttribute],
|
|
162
|
+
output_file: Path,
|
|
163
|
+
output_format: Literal[FormatArgument.CSV, FormatArgument.JSON, FormatArgument.PRETTY_JSON],
|
|
164
|
+
) -> None:
|
|
165
|
+
tmp_annotation_attribute_list = [e.model_dump() for e in annotation_attribute_list]
|
|
166
|
+
if output_format == FormatArgument.CSV:
|
|
167
|
+
print_annotation_attribute_list_as_csv(tmp_annotation_attribute_list, output_file)
|
|
168
|
+
elif output_format == FormatArgument.JSON:
|
|
169
|
+
print_json(tmp_annotation_attribute_list, output=output_file, is_pretty=False)
|
|
170
|
+
elif output_format == FormatArgument.PRETTY_JSON:
|
|
171
|
+
print_json(tmp_annotation_attribute_list, output=output_file, is_pretty=True)
|
|
172
|
+
else:
|
|
173
|
+
raise assert_noreturn(output_format)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
class ListAnnotationAttribute(CommandLine):
|
|
177
|
+
COMMON_MESSAGE = "annofabcli statistics list_annotation_attribute: error:"
|
|
178
|
+
|
|
179
|
+
def validate(self, args: argparse.Namespace) -> bool:
|
|
180
|
+
if args.project_id is None and args.annotation is None:
|
|
181
|
+
print( # noqa: T201
|
|
182
|
+
f"{self.COMMON_MESSAGE} argument --project_id: '--annotation'が未指定のときは、'--project_id' を指定してください。",
|
|
183
|
+
file=sys.stderr,
|
|
184
|
+
)
|
|
185
|
+
return False
|
|
186
|
+
|
|
187
|
+
return True
|
|
188
|
+
|
|
189
|
+
def main(self) -> None:
|
|
190
|
+
args = self.args
|
|
191
|
+
|
|
192
|
+
if not self.validate(args):
|
|
193
|
+
sys.exit(COMMAND_LINE_ERROR_STATUS_CODE)
|
|
194
|
+
|
|
195
|
+
project_id: Optional[str] = args.project_id
|
|
196
|
+
if project_id is not None:
|
|
197
|
+
super().validate_project(project_id, project_member_roles=[ProjectMemberRole.OWNER, ProjectMemberRole.TRAINING_DATA_USER])
|
|
198
|
+
|
|
199
|
+
annotation_path = Path(args.annotation) if args.annotation is not None else None
|
|
200
|
+
|
|
201
|
+
task_id_list = annofabcli.common.cli.get_list_from_args(args.task_id) if args.task_id is not None else None
|
|
202
|
+
label_name_list = annofabcli.common.cli.get_list_from_args(args.label_name) if args.label_name is not None else None
|
|
203
|
+
task_query = TaskQuery.from_dict(annofabcli.common.cli.get_json_from_args(args.task_query)) if args.task_query is not None else None
|
|
204
|
+
|
|
205
|
+
output_file: Path = args.output
|
|
206
|
+
output_format = FormatArgument(args.format)
|
|
207
|
+
|
|
208
|
+
downloading_obj = DownloadingFile(self.service)
|
|
209
|
+
|
|
210
|
+
def download_and_print_annotation_attribute_list(
|
|
211
|
+
project_id: str, temp_dir: Path, *, is_latest: bool, annotation_path: Optional[Path]
|
|
212
|
+
) -> None:
|
|
213
|
+
if annotation_path is None:
|
|
214
|
+
annotation_path = temp_dir / f"{project_id}__annotation.zip"
|
|
215
|
+
downloading_obj.download_annotation_zip(
|
|
216
|
+
project_id,
|
|
217
|
+
dest_path=annotation_path,
|
|
218
|
+
is_latest=is_latest,
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
annotation_attribute_list = get_annotation_attribute_list_from_annotation_zipdir_path(
|
|
222
|
+
annotation_zipdir_path=annotation_path, target_task_ids=task_id_list, task_query=task_query, target_labels=label_name_list
|
|
223
|
+
)
|
|
224
|
+
print_annotation_attribute_list(annotation_attribute_list, output_file, output_format) # type: ignore[arg-type]
|
|
225
|
+
|
|
226
|
+
if project_id is not None:
|
|
227
|
+
if args.temp_dir is not None:
|
|
228
|
+
download_and_print_annotation_attribute_list(
|
|
229
|
+
project_id=project_id, temp_dir=args.temp_dir, is_latest=args.latest, annotation_path=annotation_path
|
|
230
|
+
)
|
|
231
|
+
else:
|
|
232
|
+
# `NamedTemporaryFile`を使わない理由: Windowsで`PermissionError`が発生するため
|
|
233
|
+
# https://qiita.com/yuji38kwmt/items/c6f50e1fc03dafdcdda0 参考
|
|
234
|
+
with tempfile.TemporaryDirectory() as str_temp_dir:
|
|
235
|
+
download_and_print_annotation_attribute_list(
|
|
236
|
+
project_id=project_id, temp_dir=Path(str_temp_dir), is_latest=args.latest, annotation_path=annotation_path
|
|
237
|
+
)
|
|
238
|
+
else:
|
|
239
|
+
assert annotation_path is not None
|
|
240
|
+
annotation_attribute_list = get_annotation_attribute_list_from_annotation_zipdir_path(
|
|
241
|
+
annotation_zipdir_path=annotation_path, target_task_ids=task_id_list, task_query=task_query, target_labels=label_name_list
|
|
242
|
+
)
|
|
243
|
+
print_annotation_attribute_list(annotation_attribute_list, output_file, output_format) # type: ignore[arg-type]
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def parse_args(parser: argparse.ArgumentParser) -> None:
|
|
247
|
+
argument_parser = ArgumentParser(parser)
|
|
248
|
+
|
|
249
|
+
annotation_group = parser.add_mutually_exclusive_group(required=True)
|
|
250
|
+
annotation_group.add_argument(
|
|
251
|
+
"--annotation",
|
|
252
|
+
type=str,
|
|
253
|
+
help="アノテーションzip、またはzipを展開したディレクトリを指定します。指定しない場合はAnnofabからダウンロードします。",
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
annotation_group.add_argument("-p", "--project_id", type=str, help="対象プロジェクトの project_id")
|
|
257
|
+
|
|
258
|
+
argument_parser.add_format(
|
|
259
|
+
choices=[FormatArgument.CSV, FormatArgument.JSON, FormatArgument.PRETTY_JSON],
|
|
260
|
+
default=FormatArgument.CSV,
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
argument_parser.add_output()
|
|
264
|
+
|
|
265
|
+
parser.add_argument(
|
|
266
|
+
"-tq",
|
|
267
|
+
"--task_query",
|
|
268
|
+
type=str,
|
|
269
|
+
help="集計対象タスクを絞り込むためのクエリ条件をJSON形式で指定します。使用できるキーは task_id, status, phase, phase_stage です。"
|
|
270
|
+
" ``file://`` を先頭に付けると、JSON形式のファイルを指定できます。",
|
|
271
|
+
)
|
|
272
|
+
argument_parser.add_task_id(required=False)
|
|
273
|
+
|
|
274
|
+
parser.add_argument(
|
|
275
|
+
"--label_name",
|
|
276
|
+
type=str,
|
|
277
|
+
nargs="+",
|
|
278
|
+
required=False,
|
|
279
|
+
help="出力対象のアノテーションのラベル名(英語)を指定します。指定しない場合はラベル名で絞り込みません。"
|
|
280
|
+
" ``file://`` を先頭に付けると、ラベル名の一覧が記載されたファイルを指定できます。",
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
parser.add_argument(
|
|
284
|
+
"--latest",
|
|
285
|
+
action="store_true",
|
|
286
|
+
help="``--annotation`` を指定しないとき、最新のアノテーションzipを参照します。このオプションを指定すると、アノテーションzipを更新するのに数分待ちます。", # noqa: E501
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
parser.add_argument(
|
|
290
|
+
"--temp_dir",
|
|
291
|
+
type=Path,
|
|
292
|
+
help="指定したディレクトリに、アノテーションZIPなどの一時ファイルをダウンロードします。",
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
parser.set_defaults(subcommand_func=main)
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def main(args: argparse.Namespace) -> None:
|
|
299
|
+
service = build_annofabapi_resource_and_login(args)
|
|
300
|
+
facade = AnnofabApiFacade(service)
|
|
301
|
+
ListAnnotationAttribute(service, facade, args).main()
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
|
|
305
|
+
subcommand_name = "list_annotation_attribute"
|
|
306
|
+
subcommand_help = "アノテーションZIPを読み込み、アノテーションの属性値の一覧を出力します。"
|
|
307
|
+
epilog = "オーナロールまたはアノテーションユーザロールを持つユーザで実行してください。"
|
|
308
|
+
parser = annofabcli.common.cli.add_parser(subparsers, subcommand_name, subcommand_help, description=subcommand_help, epilog=epilog)
|
|
309
|
+
parse_args(parser)
|
|
310
|
+
return parser
|
|
@@ -4,6 +4,7 @@ from typing import Optional
|
|
|
4
4
|
import annofabcli
|
|
5
5
|
import annofabcli.common.cli
|
|
6
6
|
import annofabcli.stat_visualization.merge_visualization_dir
|
|
7
|
+
import annofabcli.statistics.list_annotation_attribute
|
|
7
8
|
import annofabcli.statistics.list_annotation_count
|
|
8
9
|
import annofabcli.statistics.list_annotation_duration
|
|
9
10
|
import annofabcli.statistics.list_video_duration
|
|
@@ -21,6 +22,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
|
|
|
21
22
|
subparsers = parser.add_subparsers(dest="subcommand_name")
|
|
22
23
|
|
|
23
24
|
# サブコマンドの定義
|
|
25
|
+
annofabcli.statistics.list_annotation_attribute.add_parser(subparsers)
|
|
24
26
|
annofabcli.statistics.list_annotation_count.add_parser(subparsers)
|
|
25
27
|
annofabcli.statistics.list_annotation_duration.add_parser(subparsers)
|
|
26
28
|
annofabcli.statistics.list_video_duration.add_parser(subparsers)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
annofabcli/__init__.py,sha256=NMA7kFxmLlCiILQPHJa9mEuqXxtLALw_dwyXYsvz4VM,71
|
|
2
2
|
annofabcli/__main__.py,sha256=JzfycqVG9ENhWOCxTouZwpHwWTSrI-grLsaMudxjyBM,5283
|
|
3
|
-
annofabcli/__version__.py,sha256=
|
|
3
|
+
annofabcli/__version__.py,sha256=vUosqVW-MeQrE_vPK0xlTVGwdsd_pcLlczOaCRqUXgg,132
|
|
4
4
|
annofabcli/annotation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
annofabcli/annotation/annotation_query.py,sha256=ke3W3RT1-WfFzwt-TXcQwGmghG34vcKJkM_jxgbNKjU,15922
|
|
6
6
|
annofabcli/annotation/change_annotation_attributes.py,sha256=zHXyENZfbMGL_15xiK7Cy4cQ2sV0GjSVmKuPm3sOX7Y,17173
|
|
@@ -15,7 +15,7 @@ annofabcli/annotation/list_annotation_count.py,sha256=T9fbaoxWeDJIVgW_YgHRldbwrV
|
|
|
15
15
|
annofabcli/annotation/restore_annotation.py,sha256=naUEbt48ION9JSijCBR2aQdaoCrRu005tYq0vgUtyp0,14683
|
|
16
16
|
annofabcli/annotation/subcommand_annotation.py,sha256=Xu4SOHLpo_kPZbvE8hQHr9NRduPTESqu7pYC4LGDlXg,1872
|
|
17
17
|
annofabcli/annotation_specs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
|
-
annofabcli/annotation_specs/export_annotation_specs.py,sha256=
|
|
18
|
+
annofabcli/annotation_specs/export_annotation_specs.py,sha256=eZF5fj2P5U22_5UKgbpsUhZEUvVPMPerMpN4miIcnSA,4821
|
|
19
19
|
annofabcli/annotation_specs/get_annotation_specs_with_attribute_id_replaced.py,sha256=L0H0M31Amnm3ZEg9JdQe2A1vprsCLPTpj0LUFnP6GDY,8330
|
|
20
20
|
annofabcli/annotation_specs/get_annotation_specs_with_choice_id_replaced.py,sha256=mISJAgRTBMvISPk5__0w0MmhTkyQCcGPDin8K97x5Eg,6943
|
|
21
21
|
annofabcli/annotation_specs/get_annotation_specs_with_label_id_replaced.py,sha256=5tlvSdUXAUn8uQ1BXNWxkR2MIKnV6AJoxveiwD21IAo,7114
|
|
@@ -130,12 +130,13 @@ annofabcli/stat_visualization/write_performance_rating_csv.py,sha256=TDn7-poyFt2
|
|
|
130
130
|
annofabcli/statistics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
131
131
|
annofabcli/statistics/histogram.py,sha256=CvzDxT2cKLSnBGSqkZE6p92PayGxYYja1YyB24M4ALU,3245
|
|
132
132
|
annofabcli/statistics/linegraph.py,sha256=0kr7jVBNMiM2ECYhv3Ry5RitElKerSl9ZKxbKzfiplI,12494
|
|
133
|
+
annofabcli/statistics/list_annotation_attribute.py,sha256=WM0-Zw0Pm35olqrSXvbHnrb4mbC02qcjshLCrbPE3zg,12432
|
|
133
134
|
annofabcli/statistics/list_annotation_count.py,sha256=xsqXxRO21MW7Wbs96PEa8gHb3i7bxjQvoMHLB2eT-0g,50360
|
|
134
135
|
annofabcli/statistics/list_annotation_duration.py,sha256=9PCg1IA_g4HoHHSfsMVb2zBMLfLJ3u9Id8Qa9L8Qhko,31923
|
|
135
136
|
annofabcli/statistics/list_video_duration.py,sha256=uNeMteRBX2JG_AWmcgMJj0Jzbq_qF7bvAwr25GmeIiw,9124
|
|
136
137
|
annofabcli/statistics/list_worktime.py,sha256=C7Yu3IOW2EvhkJJv6gY3hNdS9_TOLmT_9LZsB7vLJ1o,6493
|
|
137
138
|
annofabcli/statistics/scatter.py,sha256=IUCwXix9GbZb6V82wjjb5q2eamrT5HQsU_bzDTjAFnM,11011
|
|
138
|
-
annofabcli/statistics/subcommand_statistics.py,sha256=
|
|
139
|
+
annofabcli/statistics/subcommand_statistics.py,sha256=JPixzhJGClQYVH6Tgby3KTD85df-aEJKvLAjfJCv-1E,2259
|
|
139
140
|
annofabcli/statistics/summarize_task_count.py,sha256=8OH6BBRYRjHJkWRTjU0A0OfXa7f3NIRHrxPNFlRt_hM,9707
|
|
140
141
|
annofabcli/statistics/summarize_task_count_by_task_id_group.py,sha256=TSSmcFv615NLcq6uqXmg3ilYqSHl3A5qp90msVQM1gE,8646
|
|
141
142
|
annofabcli/statistics/summarize_task_count_by_user.py,sha256=TRoJXpt2HOVb8QO2YtRejkOAxyK80_NsPt3Vk9es9C8,6948
|
|
@@ -199,8 +200,8 @@ annofabcli/task_history_event/download_task_history_event_json.py,sha256=hQLVbQ0
|
|
|
199
200
|
annofabcli/task_history_event/list_all_task_history_event.py,sha256=JQEgwOIXbbTIfeX23AVaoySHViOR9UGm9uoXuhVEBqo,6446
|
|
200
201
|
annofabcli/task_history_event/list_worktime.py,sha256=9jsRYa2C9bva8E1Aqxv9CCKDuCP0MvbiaIyQFTDpjqY,13150
|
|
201
202
|
annofabcli/task_history_event/subcommand_task_history_event.py,sha256=mJVJoT4RXk4HWnY7-Nrsl4If-gtaIIEXd2z7eFZwM2I,1260
|
|
202
|
-
annofabcli-1.
|
|
203
|
-
annofabcli-1.
|
|
204
|
-
annofabcli-1.
|
|
205
|
-
annofabcli-1.
|
|
206
|
-
annofabcli-1.
|
|
203
|
+
annofabcli-1.96.0.dist-info/LICENSE,sha256=pcqWYfxFtxBzhvKp3x9MXNM4xciGb2eFewaRhXUNHlo,1081
|
|
204
|
+
annofabcli-1.96.0.dist-info/METADATA,sha256=kHn5yPXYeuO3FK-MKUhhRcZ5vAhUakxbnLEOlqM6KsY,5626
|
|
205
|
+
annofabcli-1.96.0.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
206
|
+
annofabcli-1.96.0.dist-info/entry_points.txt,sha256=A8vlN9fiMhbYRcdBfSpl7piYzAwvkMhRXIPQUAvQFUo,55
|
|
207
|
+
annofabcli-1.96.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|