Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions annofabapi/dataclass/annotation.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
)

AnnotationData = Union[str, Dict[str, Any]]
FullAnnotationData = Dict[str, Any]
FullAnnotationData = Any
AdditionalDataValue = Dict[str, Any]


Expand Down Expand Up @@ -191,7 +191,7 @@ class FullAnnotationDetail(DataClassJsonMixin):
data_holding_type: Optional[AnnotationDataHoldingType]
""""""

data: Optional[FullAnnotationData]
data: FullAnnotationData
""""""

additional_data_list: Optional[List[FullAnnotationAdditionalData]]
Expand Down Expand Up @@ -223,7 +223,7 @@ class FullAnnotation(DataClassJsonMixin):
input_data_name: Optional[str]
""""""

details: Optional[List[FullAnnotationDetail]]
details: List[FullAnnotationDetail]
""""""

updated_datetime: Optional[str]
Expand Down
63 changes: 43 additions & 20 deletions annofabapi/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
import os
import zipfile
from pathlib import Path
from typing import Any, Dict, Iterator, List, Optional
from typing import Any, Callable, Dict, Iterator, List, Optional

from annofabapi.dataclass.annotation import FullAnnotation, SimpleAnnotation
from annofabapi.exceptions import AnnotationOuterFileNotFoundError

CONVERT_ANNOTATION_DETAIL_DATA_FUNC = Callable[[Dict[str, Any]], Any]


def _trim_extension(file_path: str) -> str:
"""ファイルパスから拡張子を除去した文字列を返す"""
Expand Down Expand Up @@ -72,12 +74,25 @@ def open_outer_file(self, data_uri: str):

"""

@abc.abstractmethod
def parse(self) -> SimpleAnnotation:
"""
JSONファイルをパースする。
def parse(
self, convert_deitail_data_func: Optional[CONVERT_ANNOTATION_DETAIL_DATA_FUNC] = None
) -> SimpleAnnotation:
"""JSONファイルをパースする

Args:
convert_deitail_data_func: SimpleAnnotationDetailクラスのdataプロパティを変換する関数を指定します。
dictからdataclassに変換する際に使います。

Returns:
SimpleAnnotationインスタンス
"""

simple_annotation = SimpleAnnotation.from_dict(self.load_json()) # type: ignore
if convert_deitail_data_func is not None:
for detail in simple_annotation.details:
detail.data = convert_deitail_data_func(detail.data)
return simple_annotation

@abc.abstractmethod
def load_json(self) -> Any:
"""
Expand Down Expand Up @@ -144,11 +159,28 @@ def open_outer_file(self, data_uri: str):
"""

@abc.abstractmethod
def parse(self) -> FullAnnotation:
def load_json(self) -> Any:
"""
JSONファイルをパースする
JSONファイルをloadします
"""

def parse(self, convert_deitail_data_func: Optional[CONVERT_ANNOTATION_DETAIL_DATA_FUNC] = None) -> FullAnnotation:
"""JSONファイルをパースする

Args:
convert_deitail_data_func: FullAnnotationDetailクラスのdataプロパティを変換する関数を指定します。
dictからdataclassに変換する際に使います。

Returns:
FullAnnotationインスタンス
"""

full_annotation = FullAnnotation.from_dict(self.load_json()) # type: ignore
if convert_deitail_data_func is not None:
for detail in full_annotation.details:
detail.data = convert_deitail_data_func(detail.data)
return full_annotation


class SimpleAnnotationZipParser(SimpleAnnotationParser):
"""
Expand All @@ -172,9 +204,6 @@ def __init__(self, zip_file: zipfile.ZipFile, json_file_path: str):
self.__zip_file = zip_file
super().__init__(json_file_path)

def parse(self) -> SimpleAnnotation:
return SimpleAnnotation.from_dict(self.load_json()) # type: ignore

def load_json(self) -> Any:
with self.__zip_file.open(self.json_file_path) as entry:
return json.load(entry)
Expand Down Expand Up @@ -208,9 +237,6 @@ class SimpleAnnotationDirParser(SimpleAnnotationParser):
def __init__(self, json_file_path: Path):
super().__init__(str(json_file_path))

def parse(self) -> SimpleAnnotation:
return SimpleAnnotation.from_dict(self.load_json()) # type: ignore

def load_json(self) -> Any:
with open(self.json_file_path, encoding="utf-8") as f:
return json.load(f)
Expand Down Expand Up @@ -245,11 +271,9 @@ def __init__(self, zip_file: zipfile.ZipFile, json_file_path: str):
self.__zip_file = zip_file
super().__init__(json_file_path)

def parse(self) -> FullAnnotation:
def load_json(self) -> Any:
with self.__zip_file.open(self.json_file_path) as entry:
anno_dict: dict = json.load(entry)
# mypyの "has no attribute "from_dict" " をignore
return FullAnnotation.from_dict(anno_dict) # type: ignore
return json.load(entry)

def open_outer_file(self, data_uri: str):
outer_file_path = _trim_extension(self.json_file_path) + "/" + data_uri
Expand Down Expand Up @@ -281,10 +305,9 @@ class FullAnnotationDirParser(FullAnnotationParser):
def __init__(self, json_file_path: Path):
super().__init__(str(json_file_path))

def parse(self) -> FullAnnotation:
def load_json(self) -> Any:
with open(self.json_file_path, encoding="utf-8") as f:
anno_dict: dict = json.load(f)
return FullAnnotation.from_dict(anno_dict) # type: ignore
return json.load(f)

def open_outer_file(self, data_uri: str):
outer_file_path = _trim_extension(self.json_file_path) + "/" + data_uri
Expand Down
6 changes: 3 additions & 3 deletions generate/partial-header/dataclass/annotation.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from annofabapi.models import (
AnnotationDataHoldingType,
InternationalizationMessage,
AdditionalDataDefinitionType,
AnnotationDataHoldingType,
AnnotationType,
InternationalizationMessage,
TaskPhase,
TaskStatus,
)

AnnotationData = Union[str, Dict[str, Any]]
FullAnnotationData = Dict[str, Any]
FullAnnotationData = Any
AdditionalDataValue = Dict[str, Any]
52 changes: 51 additions & 1 deletion tests/test_local_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import annofabapi
import annofabapi.parser
import annofabapi.utils
from annofabapi.dataclass.annotation import FullAnnotation, SimpleAnnotation
from annofabapi.dataclass.annotation import FullAnnotation, FullAnnotationDataPoints, SimpleAnnotation
from annofabapi.exceptions import AnnotationOuterFileNotFoundError
from annofabapi.parser import (
FullAnnotationDirParser,
Expand Down Expand Up @@ -43,6 +43,24 @@ def test_SimpleAnnotationZipParser(self):
with pytest.raises(AnnotationOuterFileNotFoundError):
parser.open_outer_file("foo")

def convert_deitail_data(self, dict_data):
if dict_data["_type"] == "Points":
dict_data["type"] = dict_data["_type"]
return FullAnnotationDataPoints.from_dict(dict_data)
else:
return dict_data

def test_parse_for_zip(self):
zip_path = Path(test_dir / "simple-annotation.zip")
with zipfile.ZipFile(zip_path) as zip_file:
parser = SimpleAnnotationZipParser(zip_file, "sample_1/c86205d1-bdd4-4110-ae46-194e661d622b.json")

simple_annotation = parser.parse()
assert type(simple_annotation.details[0].data) == dict

simple_annotation2 = parser.parse(self.convert_deitail_data)
assert type(simple_annotation2.details[0].data) == FullAnnotationDataPoints

def test_SimpleAnnotationDirParser(self):
dir_path = Path(test_dir / "simple-annotation")

Expand Down Expand Up @@ -118,6 +136,10 @@ def test_simple_annotation_dir(self):
assert type(simple_annotation) == SimpleAnnotation
index += 1

dict_simple_annotation = parser.load_json()
assert type(dict_simple_annotation) == dict
assert "details" in dict_simple_annotation

assert index == 4

def test_lazy_parse_simple_annotation_zip_by_task(self):
Expand Down Expand Up @@ -166,6 +188,11 @@ def test_full_annotation_zip(self):
parser = FullAnnotationZipParser(zip_file, "sample_1/c86205d1-bdd4-4110-ae46-194e661d622b.json")
assert parser.task_id == "sample_1"
assert parser.input_data_id == "c86205d1-bdd4-4110-ae46-194e661d622b"

dict_simple_annotation = parser.load_json()
assert type(dict_simple_annotation) == dict
assert "details" in dict_simple_annotation

with pytest.raises(AnnotationOuterFileNotFoundError):
parser.open_outer_file("foo")

Expand All @@ -186,5 +213,28 @@ def test_full_annotation_dir(self):
)
assert parser.task_id == "sample_1"
assert parser.input_data_id == "c86205d1-bdd4-4110-ae46-194e661d622b"

dict_simple_annotation = parser.load_json()
assert type(dict_simple_annotation) == dict
assert "details" in dict_simple_annotation

with pytest.raises(AnnotationOuterFileNotFoundError):
parser.open_outer_file("foo")

def convert_deitail_data(self, dict_data):
if dict_data["_type"] == "Points":
dict_data["type"] = dict_data["_type"]
return FullAnnotationDataPoints.from_dict(dict_data)
else:
return dict_data

def test_parse_for_zip(self):
zip_path = Path(test_dir / "full-annotation.zip")
with zipfile.ZipFile(zip_path) as zip_file:
parser = FullAnnotationZipParser(zip_file, "sample_1/c86205d1-bdd4-4110-ae46-194e661d622b.json")

full_annotation = parser.parse()
assert type(full_annotation.details[0].data) == dict

full_annotation2 = parser.parse(self.convert_deitail_data)
assert type(full_annotation2.details[0].data) == FullAnnotationDataPoints