Skip to content

Commit 1bce988

Browse files
authored
wrapper.put_annotation_for_simple_annotation_jsonに、アノテーション仕様V2版を指定できるようにする (#313)
* update pyproject.toml * annofab v0.111.0 * extensionを追加 * wrapper: put_annotation_for_simple_annotation_jsonをV2版のアノテーション仕様にも対応させる * format * update wrapper * spellチェックの設定を追加 * lint設定 * typo * test code追加 * devcontainerの更新 * 修正 * pytestで無視するファイルを設定 * ".netrc"ファイルが必要なテストを除く。テストしづらいため。 * update travis * updatetravis * update travis * update travis * version up
1 parent 54ffddb commit 1bce988

12 files changed

+164
-25
lines changed

.devcontainer/devcontainer.json

+5-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
"forwardPorts": [],
2020
"runArgs": [
2121
"--init",
22-
"--net=host"
22+
"--net=host",
23+
"--env=ANNOFAB_USER_ID",
24+
"--env=ANNOFAB_PASSWORD"
2325
],
2426
"containerEnv": {
2527
"CONTAINER_WORKSPACE": "${containerWorkspaceFolder}",
@@ -31,6 +33,7 @@
3133
"ms-python.python",
3234
"ms-python.vscode-pylance",
3335
"streetsidesoftware.code-spell-checker",
34-
"bungcip.better-toml"
36+
"bungcip.better-toml",
37+
"njpwerner.autodocstring"
3538
]
3639
}

.flake8

+1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ max-line-length = 120
55
# https://black.readthedocs.io/en/stable/the_black_code_style.html#line-length
66
extend-ignore = E203, W503
77

8+
exclude = test_*.py
89

.travis.yml

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
dist: xenial
1+
version: ~> 1.0
22
language: python
33
python:
44
- "3.6"
@@ -8,7 +8,9 @@ python:
88
install:
99
- pip install poetry
1010
- poetry install
11-
- echo -e "machine annofab.com\nlogin FOO\npassword BAR\n" > ~/.netrc && chmod 600 ~/.netrc
11+
env:
12+
# PyPIへのアクセス過多などで失敗するケースがあるので、タイムアウトを設定する
13+
- PIP_DEFAULT_TIMEOUT=100
1214
script:
1315
- make lint
1416
- pytest tests/test_local*.py

.vscode/cspell.json

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"version": "0.1",
3+
"ignorePaths": [
4+
"**/.git/objects/**",
5+
".devcontainer/",
6+
".vscode/",
7+
"LICENSE",
8+
"tests/",
9+
// 以下は自動生成されるファイルなのでチェックしない
10+
"generated_*.py",
11+
"models.py",
12+
"annofabapi/dataclass/*.py"
13+
],
14+
"enabledLanguageIds": [
15+
"python"
16+
],
17+
"words": [
18+
"additionals",
19+
"astimezone",
20+
"asyncio",
21+
"dateutil",
22+
"pylint",
23+
"tzlocal"
24+
]
25+
}

.vscode/settings.json

+9-11
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
{
2-
"python.linting.pylintEnabled": true,
2+
3+
"python.pythonPath": ".venv/bin/python",
4+
"python.languageServer": "Pylance",
5+
"python.autoComplete.addBrackets": true,
36
"python.autoComplete.extraPaths": [
47
".venv/lib/python3.8/site-packages/"
58
],
9+
// "poetry run"コマンドで実行することを想定しているので、venv環境を自動的にactivateしないようにする
10+
"python.terminal.activateEnvironment":false,
611

712
"python.formatting.blackPath": ".venv/bin/black",
813
"python.formatting.provider": "black",
914
"python.linting.enabled": true,
1015
"python.linting.lintOnSave": true,
16+
"python.linting.pylintEnabled": true,
1117
"python.linting.pylintPath": ".venv/bin/pylint",
1218
"python.linting.pylintArgs": [
1319
"--rcfile setup.cfg",
@@ -37,14 +43,6 @@
3743
"source.organizeImports": true
3844
},
3945
},
40-
"cSpell.ignorePaths": [
41-
"**/.git/objects/**",
42-
".devcontainer/",
43-
".vscode/",
44-
"LICENSE"
45-
],
46-
"cSpell.words": [
47-
"pylint",
48-
"asyncio"
49-
]
46+
"python.testing.autoTestDiscoverOnSaveEnabled": false,
47+
5048
}

annofabapi/__version__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.45.0"
1+
__version__ = "0.45.1"

annofabapi/api2.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def _request_wrapper(
4545
request_body: Optional[Any] = None,
4646
) -> Tuple[Any, requests.Response]:
4747
"""
48-
HTTP Requestを投げて、Reponseを返す
48+
HTTP Requestを投げて、Responseを返す
4949
Args:
5050
http_method:
5151
url_path:

annofabapi/wrapper.py

+49-3
Original file line numberDiff line numberDiff line change
@@ -542,13 +542,49 @@ def __to_annotation_detail_for_request(
542542

543543
return dest_obj
544544

545+
def __convert_annotation_specs_labels_v2_to_v1(
546+
self, labels_v2: List[Dict[str, Any]], additionals_v2: List[Dict[str, Any]]
547+
) -> List[LabelV1]:
548+
"""アノテーション仕様のV2版からV1版に変換する。V1版の方が扱いやすいので。
549+
550+
Args:
551+
labels_v2 (List[Dict[str, Any]]): V2版のラベル情報
552+
additionals_v2 (List[Dict[str, Any]]): V2版の属性情報
553+
554+
Returns:
555+
List[LabelV1]: V1版のラベル情報
556+
"""
557+
558+
def get_additional(additional_data_definition_id: str) -> Optional[Dict[str, Any]]:
559+
return _first_true(
560+
additionals_v2, pred=lambda e: e["additional_data_definition_id"] == additional_data_definition_id
561+
)
562+
563+
def to_label_v1(label_v2) -> LabelV1:
564+
additional_data_definition_id_list = label_v2["additional_data_definitions"]
565+
new_additional_data_definitions = []
566+
for additional_data_definition_id in additional_data_definition_id_list:
567+
additional = get_additional(additional_data_definition_id)
568+
if additional is not None:
569+
new_additional_data_definitions.append(additional)
570+
else:
571+
raise ValueError(
572+
f"additional_data_definition_id='{additional_data_definition_id}' に対応する属性情報が存在しません。"
573+
f"label_id='{label_v2['label_id']}', label_name_en='{self.__get_label_name_en(label_v2)}'"
574+
)
575+
label_v2["additional_data_definitions"] = new_additional_data_definitions
576+
return label_v2
577+
578+
return [to_label_v1(label_v2) for label_v2 in labels_v2]
579+
545580
def put_annotation_for_simple_annotation_json(
546581
self,
547582
project_id: str,
548583
task_id: str,
549584
input_data_id: str,
550585
simple_annotation_json: str,
551-
annotation_specs_labels: List[LabelV1],
586+
annotation_specs_labels: List[Dict[str, Any]],
587+
annotation_specs_additionals: Optional[List[Dict[str, Any]]] = None,
552588
) -> bool:
553589
"""
554590
AnnoFabからダウンロードしたアノテーションzip配下のJSONと同じフォーマット(Simple Annotation)の内容から、アノテーションを登録する。
@@ -557,10 +593,15 @@ def put_annotation_for_simple_annotation_json(
557593
project_id:
558594
task_id:
559595
input_data_id:
560-
simple_annotation_json:
596+
simple_annotation_json: AnnoFabからダウンロードしたアノテーションzip配下のJSONのパス
597+
annotation_specs_labels: アノテーション仕様のラベル情報。annotation_specs_additionalsが指定されている場合はV2版、指定されない場合はV1版。
598+
annotation_specs_additionals: アノテーション仕様の属性情報(V2版)
561599
562600
Returns:
563601
True:アノテーション情報をした。False: 登録するアノテーション情報がなかったため、登録しなかった。
602+
603+
Notes:
604+
2021/07以降、引数annotation_specs_labelsはV1版をサポートしなくなる予定です。
564605
"""
565606
parser = SimpleAnnotationDirParser(Path(simple_annotation_json))
566607
annotation = parser.load_json()
@@ -571,9 +612,14 @@ def put_annotation_for_simple_annotation_json(
571612
return False
572613

573614
request_details: List[Dict[str, Any]] = []
615+
annotation_specs_labels_v1 = (
616+
self.__convert_annotation_specs_labels_v2_to_v1(annotation_specs_labels, annotation_specs_additionals)
617+
if annotation_specs_additionals is not None
618+
else annotation_specs_labels
619+
)
574620
for detail in details:
575621
request_detail = self.__to_annotation_detail_for_request(
576-
project_id, parser, detail, annotation_specs_labels
622+
project_id, parser, detail, annotation_specs_labels_v1
577623
)
578624
if request_detail is not None:
579625
request_details.append(request_detail)

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "annofabapi"
3-
version = "0.45.0"
3+
version = "0.45.1"
44
description = "Python Clinet Library of AnnoFab WebAPI (https://annofab.com/docs/api/)"
55
authors = ["yuji38kwmt"]
66
license = "MIT"

pytest.ini

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
[pytest]
44
# Don't write `pytest-cov` Option
5-
addopts = --verbose --capture=no -rs
5+
addopts = --verbose --capture=no -rs --ignore=tests/test_sandbox.py
66

77
[annofab]
88
endpoint_url = https://annofab.com

tests/test_local_resource.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313

1414

1515
class TestBuild:
16-
def test_build_from_netrc(self):
17-
# ".netrc"ファイルが存在すること前提
18-
assert isinstance(build_from_netrc(), annofabapi.Resource)
16+
# def test_build_from_netrc(self):
17+
# # ".netrc"ファイルが存在すること前提
18+
# assert isinstance(build_from_netrc(), annofabapi.Resource)
1919

2020
def test_raise_ValueError(self):
2121
with pytest.raises(ValueError):

tests/test_sandbox.py

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
"""
2+
AnnoFabプロジェクトやタスクに大きく依存したテストコードです。
3+
"""
4+
import configparser
5+
import datetime
6+
import os
7+
import uuid
8+
9+
import pytest
10+
import requests
11+
from more_itertools import first_true
12+
13+
import annofabapi
14+
import annofabapi.utils
15+
from annofabapi.models import GraphType, JobType
16+
from tests.utils_for_test import WrapperForTest, create_csv_for_task
17+
18+
# プロジェクトトップに移動する
19+
os.chdir(os.path.dirname(os.path.abspath(__file__)) + "/../")
20+
inifile = configparser.ConfigParser()
21+
inifile.read("./pytest.ini", "UTF-8")
22+
23+
project_id = inifile["annofab"]["project_id"]
24+
task_id = inifile["annofab"]["task_id"]
25+
26+
27+
test_dir = "./tests/data"
28+
out_dir = "./tests/out"
29+
30+
endpoint_url = inifile["annofab"].get("endpoint_url", None)
31+
if endpoint_url is not None:
32+
service = annofabapi.build(endpoint_url=endpoint_url)
33+
else:
34+
service = annofabapi.build()
35+
36+
37+
class TestAnnotation:
38+
def test_wrapper_put_annotation_for_simple_annotation_json_v1(self):
39+
"""2021/07以降に廃止する予定"""
40+
project_id = "bf530c4e-1185-4a0c-994f-502fb01ea37e"
41+
annotation_specs_v1, _ = service.api.get_annotation_specs(project_id, query_params={"v": "1"})
42+
service.wrapper.put_annotation_for_simple_annotation_json(
43+
project_id=project_id,
44+
task_id="sample_0",
45+
input_data_id="0733d1e1-ef85-455e-aec0-ff05c499b711",
46+
simple_annotation_json=str(
47+
test_dir + "/simple-annotation/sample_1/c6e1c2ec-6c7c-41c6-9639-4244c2ed2839.json"
48+
),
49+
annotation_specs_labels=annotation_specs_v1["labels"],
50+
)
51+
52+
def test_wrapper_put_annotation_for_simple_annotation_json_v2(self):
53+
project_id = "bf530c4e-1185-4a0c-994f-502fb01ea37e"
54+
annotation_specs_v2, _ = service.api.get_annotation_specs(project_id, query_params={"v": "2"})
55+
service.wrapper.put_annotation_for_simple_annotation_json(
56+
project_id=project_id,
57+
task_id="sample_0",
58+
input_data_id="0733d1e1-ef85-455e-aec0-ff05c499b711",
59+
simple_annotation_json=str(
60+
test_dir + "/simple-annotation/sample_1/c6e1c2ec-6c7c-41c6-9639-4244c2ed2839.json"
61+
),
62+
annotation_specs_labels=annotation_specs_v2["labels"],
63+
annotation_specs_additionals=annotation_specs_v2["additionals"],
64+
)

0 commit comments

Comments
 (0)