Skip to content

Commit

Permalink
Improve COCO parsing error messages (#684)
Browse files Browse the repository at this point in the history
* Improve error messages in COCO format

* Fix typo

* Add quotes to error messages

* Fix message

* Remove extra type from annotations

* Split polygon points check

* Use f style for most messages

* Add mask size value count check

* Prohibit float values in size

* Extract commond annotation template in error tests

* Rename invalid label to undeclared label

* Add validators and docs, update error hierarchy

* Add overloads to parse_field

* Add score field type test
  • Loading branch information
Maxim Zhiltsov authored Mar 23, 2022
1 parent 5e0c9b8 commit 543ab1a
Show file tree
Hide file tree
Showing 5 changed files with 432 additions and 70 deletions.
70 changes: 63 additions & 7 deletions datumaro/components/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
#
# SPDX-License-Identifier: MIT

from typing import Any, Tuple
from typing import Any, Optional, Tuple

from attrs import define, field
from attrs import define, field, validators

from datumaro.util.attrs_util import has_length, not_empty


class ImmutableObjectError(Exception):
Expand Down Expand Up @@ -197,21 +199,75 @@ class DatasetImportError(DatumaroError):
pass


class InvalidAnnotationError(DatasetImportError):
"""
A basic dataset parsing error. Should include the problem description in
the message.
"""


@define(auto_exc=False)
class InvalidFieldError(InvalidAnnotationError):
name: str = field(validator=[validators.instance_of(str), not_empty])
"""Field name"""

def __str__(self) -> str:
return f"Invalid annotation field '{self.name}' value"


@define(auto_exc=False)
class InvalidFieldTypeError(InvalidFieldError):
actual: str = field(validator=[validators.instance_of(str), not_empty])
"""Actual type of the field"""

expected: Tuple[str] = field(validator=[validators.instance_of(tuple), not_empty])
"""The list of expected types of the field"""

def __str__(self) -> str:
if len(self.expected) == 1:
expected = self.expected[0]
else:
expected = "one of " + ", ".join(self.expected)
return f"Invalid annotation field '{self.name}' type '{self.actual}'. Expected '{expected}'"


@define(auto_exc=False)
class MissingFieldError(InvalidFieldError):
def __str__(self) -> str:
return f"Missing annotation field '{self.name}'"


@define(auto_exc=False)
class UndeclaredLabelError(InvalidAnnotationError):
id: str = field(validator=validators.instance_of(str))
"""Index or name"""

def __str__(self) -> str:
return f"Undeclared label '{self.id}'"


@define(auto_exc=False)
class ItemImportError(DatasetImportError):
"""
Represents additional item error info. The error itself is supposed to be
in the `__cause__` member.
Wraps a dataset parsing error and provides additional error context info.
The error itself is supposed to be in the `__cause__` member.
"""

item_id: Tuple[str, str]
item_id: Tuple[Optional[str], Optional[str]] = field(
validator=[validators.instance_of(tuple), has_length(2)]
)
"""
(id, subset) of the item with problem.
If id or subset cannot be reported, such field is set to None.
"""

def __str__(self):
return "Failed to import item %s" % (self.item_id,)
return f"Failed to import item {self.item_id}"


class AnnotationImportError(ItemImportError):
pass
def __str__(self):
return f"Failed to import item {self.item_id} annotation"


@define(auto_exc=False)
Expand Down
Loading

0 comments on commit 543ab1a

Please sign in to comment.