Skip to content

Commit 7e0bbbf

Browse files
committed
Changed polygon points handeling
1 parent 7bab5fe commit 7e0bbbf

File tree

4 files changed

+55
-176
lines changed

4 files changed

+55
-176
lines changed

src/superannotate_schemas/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from superannotate_schemas.validators import AnnotationValidators
88

99

10-
__version__ = '1.0.42dev1'
10+
__version__ = '1.0.42dev2'
1111

1212

1313
__all__ = [

src/superannotate_schemas/schemas/base.py

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
from pydantic import conlist
1010
from pydantic import constr
1111
from pydantic import Extra
12+
from pydantic import StrictFloat
1213
from pydantic import StrictInt
13-
from pydantic import StrictFloat as PydanticStrictFloat
1414
from pydantic import StrictStr
1515
from pydantic import StrictBool
1616
from pydantic import Field
@@ -20,6 +20,9 @@
2020
from pydantic.errors import EnumMemberError
2121
from pydantic import validator
2222
from pydantic.validators import strict_str_validator
23+
from pydantic.validators import strict_float_validator
24+
from pydantic.validators import strict_int_validator
25+
from pydantic.validators import number_multiple_validator
2326
from pydantic.color import Color
2427
from pydantic.color import ColorType
2528

@@ -41,20 +44,6 @@ def enum_error_handling(self) -> str:
4144
return f"Invalid value, permitted: {permitted}"
4245

4346

44-
class StrictFloat(PydanticStrictFloat):
45-
46-
@classmethod
47-
def __get_validators__(cls):
48-
yield from super().__get_validators__()
49-
yield cls._validate_nan
50-
51-
@staticmethod
52-
def _validate_nan(v):
53-
if isnan(v):
54-
raise TypeError("NaN is not a valid float")
55-
return v
56-
57-
5847
EnumMemberError.__str__ = enum_error_handling
5948

6049
NotEmptyStr = constr(strict=True, min_length=1)
@@ -86,6 +75,45 @@ class Config:
8675
}
8776

8877

78+
class StrictPointNumber(BaseModel):
79+
__root__: Union[StrictInt, StrictFloat]
80+
81+
@classmethod
82+
def __get_validators__(cls):
83+
yield cls._validate_types
84+
85+
@classmethod
86+
def _validate_types(cls, value):
87+
is_valid_float, is_valid_int = True, True
88+
try:
89+
cls._validate_float(value)
90+
except TypeError:
91+
is_valid_float = False
92+
if not is_valid_float:
93+
try:
94+
cls._validate_int(value)
95+
except TypeError:
96+
is_valid_int = False
97+
if is_valid_float or is_valid_int:
98+
return value
99+
raise TypeError("is not a valid number. Integer or float types are expected")
100+
101+
@classmethod
102+
def _validate_int(cls, value):
103+
return strict_int_validator(value)
104+
105+
@classmethod
106+
def _validate_float(cls, value):
107+
strict_float_validator(value)
108+
return cls._validate_nan(value)
109+
110+
@staticmethod
111+
def _validate_nan(v):
112+
if isnan(v):
113+
raise TypeError("NaN is not a valid float")
114+
return v
115+
116+
89117
class AxisPoint(BaseModel):
90118
x: StrictNumber
91119
y: StrictNumber

src/superannotate_schemas/schemas/external/vector.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from pydantic import conlist
1010
from pydantic.error_wrappers import ErrorWrapper
1111

12-
from superannotate_schemas.schemas.base import StrictFloat
12+
from superannotate_schemas.schemas.base import StrictPointNumber
1313
from superannotate_schemas.schemas.base import AxisPoint
1414
from superannotate_schemas.schemas.base import BaseAttribute
1515
from superannotate_schemas.schemas.base import BaseImageMetadata
@@ -47,12 +47,12 @@ class Point(VectorInstance, AxisPoint):
4747

4848

4949
class PolyLine(VectorInstance):
50-
points: List[Union[StrictFloat, StrictInt]]
50+
points: List[StrictPointNumber]
5151

5252

5353
class Polygon(VectorInstance):
54-
points: conlist(Union[StrictFloat, StrictInt], min_items=3)
55-
exclude: Optional[List[List[Union[StrictFloat, StrictInt]]]] = []
54+
points: conlist(StrictPointNumber, min_items=3)
55+
exclude: Optional[List[List[StrictPointNumber]]] = []
5656

5757

5858
class Bbox(VectorInstance):

tests/test_validators.py

Lines changed: 7 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from superannotate_schemas.schemas.classes import AnnotationClass
77
from superannotate_schemas.validators import AnnotationValidators
8+
from superannotate_schemas.schemas.external.vector import Polygon
89

910

1011
class TestSchemas(TestCase):
@@ -974,162 +975,6 @@ def test_validate_video_invalid_instance_without_type_and_attr_annotation(self,
974975
self.assertEqual(validator.generate_report(),
975976
"instances[2].meta.type field required")
976977

977-
@patch('builtins.print')
978-
def test_validate_vector_template_polygon_polyline_min_annotation(self, mock_print):
979-
json_name = "test.json"
980-
with tempfile.TemporaryDirectory() as tmpdir_name:
981-
with open(f"{tmpdir_name}/{json_name}", "w") as json_file:
982-
json_file.write(
983-
'''
984-
{
985-
"metadata": {
986-
"lastAction": {
987-
"email": "some@some.com",
988-
"timestamp": 1636964198056
989-
},
990-
"width": "1234",
991-
"height": 1540,
992-
"name": "t.png",
993-
"projectId": 164988,
994-
"isPredicted": false,
995-
"status": "Completed",
996-
"pinned": false,
997-
"annotatorEmail": null,
998-
"qaEmail": null
999-
},
1000-
"comments": [],
1001-
"tags": [],
1002-
"instances": [
1003-
{
1004-
"type": "template",
1005-
"classId": 880080,
1006-
"probability": 100,
1007-
"points": [
1008-
],
1009-
"connections": [
1010-
{
1011-
"id": 1,
1012-
"from": 1,
1013-
"to": 2
1014-
}
1015-
],
1016-
"groupId": 0,
1017-
"pointLabels": {},
1018-
"locked": false,
1019-
"visible": true,
1020-
"attributes": [],
1021-
"templateId": 4728,
1022-
"trackingId": null,
1023-
"error": null,
1024-
"createdAt": "2021-11-15T08:24:40.712Z",
1025-
"createdBy": {
1026-
"email": "shab.prog@gmail.com",
1027-
"role": "Admin"
1028-
},
1029-
"creationType": "Manual",
1030-
"updatedAt": "2021-11-15T08:24:46.440Z",
1031-
"updatedBy": {
1032-
"email": "shab.prog@gmail.com",
1033-
"role": "Admin"
1034-
},
1035-
"className": "kj",
1036-
"templateName": "templ1"
1037-
},
1038-
{
1039-
"type": "polygon",
1040-
"classId": 880080,
1041-
"probability": 100,
1042-
"points": [
1043-
233.69
1044-
],
1045-
"groupId": 0,
1046-
"pointLabels": {},
1047-
"locked": true,
1048-
"visible": true,
1049-
"attributes": [],
1050-
"trackingId": null,
1051-
"error": null,
1052-
"createdAt": "2021-11-15T08:18:16.103Z",
1053-
"createdBy": {
1054-
"email": "some@some.com",
1055-
"role": "Admin"
1056-
},
1057-
"creationType": "Manual",
1058-
"updatedAt": "2021-11-15T08:18:20.233Z",
1059-
"updatedBy": {
1060-
"email": "some@some.com",
1061-
"role": "Admin"
1062-
},
1063-
"className": "kj"
1064-
},
1065-
{
1066-
"type": "polyline",
1067-
"classId": 880080,
1068-
"probability": 100,
1069-
"points": [
1070-
218.22
1071-
],
1072-
"groupId": 0,
1073-
"pointLabels": {},
1074-
"locked": false,
1075-
"visible": true,
1076-
"attributes": [],
1077-
"trackingId": null,
1078-
"error": null,
1079-
"createdAt": "2021-11-15T08:18:06.203Z",
1080-
"createdBy": {
1081-
"email": "some@some.com",
1082-
"role": "Admin"
1083-
},
1084-
"creationType": "Manual",
1085-
"updatedAt": "2021-11-15T08:18:13.439Z",
1086-
"updatedBy": {
1087-
"email": "some@some.com",
1088-
"role": "Admin"
1089-
},
1090-
"className": "kj"
1091-
},
1092-
{
1093-
"type": "bbox",
1094-
"classId": 880080,
1095-
"probability": 100,
1096-
"points": {
1097-
"x1": 487.78,
1098-
"x2": 1190.87,
1099-
"y1": 863.91,
1100-
"y2": 1463.78
1101-
},
1102-
"groupId": 0,
1103-
"pointLabels": {},
1104-
"locked": false,
1105-
"visible": true,
1106-
"attributes": [],
1107-
"trackingId": null,
1108-
"error": null,
1109-
"createdAt": "2021-11-15T06:43:09.812Z",
1110-
"createdBy": {
1111-
"email": "some@some.com",
1112-
"role": "Admin"
1113-
},
1114-
"creationType": "Manual",
1115-
"updatedAt": "2021-11-15T08:16:48.807Z",
1116-
"updatedBy": {
1117-
"email": "some@some.com",
1118-
"role": "Admin"
1119-
},
1120-
"className": "kj"
1121-
}
1122-
]
1123-
}
1124-
'''
1125-
)
1126-
1127-
with open(f"{tmpdir_name}/{json_name}", "r") as f:
1128-
data = json.loads(f.read())
1129-
validator = AnnotationValidators.get_validator("vector")(data)
1130-
self.assertFalse(validator.is_valid())
1131-
self.assertEqual(len(validator.generate_report()), 246)
1132-
1133978
def test_validate_video_point_labels(self):
1134979
with tempfile.TemporaryDirectory() as tmpdir_name:
1135980
with open(f"{tmpdir_name}/test_validate_video_point_labels.json",
@@ -2114,3 +1959,9 @@ def test_validate_tag_without_class_name(self):
21141959
self.assertFalse(validator.is_valid())
21151960
print(validator.generate_report())
21161961
self.assertEqual(len(validator.generate_report()), 191)
1962+
1963+
def test_strict_points(self):
1964+
try:
1965+
Polygon(points=["asd", 1, 1.0, 3], type="polygon")
1966+
except Exception as e:
1967+
print(333, e)

0 commit comments

Comments
 (0)