Skip to content

Commit 1a0ac60

Browse files
authored
Merge pull request #4 from superannotateai/develop
Develop
2 parents 4f9313f + ad06648 commit 1a0ac60

File tree

12 files changed

+2258
-125
lines changed

12 files changed

+2258
-125
lines changed

.github/workflows/changelog.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name: On release published
2+
on:
3+
release:
4+
types: [released]
5+
6+
jobs:
7+
changelog:
8+
name: Update changelog
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: actions/checkout@v2
12+
with:
13+
ref: master
14+
- uses: rhysd/changelog-from-release/action@v2
15+
with:
16+
file: CHANGELOG.md
17+
github_token: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/release.yml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,3 @@ jobs:
3333
uses: pypa/gh-action-pypi-publish@master
3434
with:
3535
password: ${{ secrets.PYPI_PASSWORD }}
36-
- uses: rhysd/changelog-from-release/action@v2
37-
with:
38-
file: CHANGELOG.md
39-
github_token: ${{ secrets.GITHUB_TOKEN }}
40-

setup.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
1+
import os
2+
import re
13
from pathlib import Path
24
from setuptools import find_packages, setup
35

46
this_directory = Path(__file__).parent
57
long_description = (this_directory / "README.md").read_text()
68

9+
def get_version():
10+
init = open(os.path.join(this_directory, 'src', 'superannotate_schemas', '__init__.py')).read()
11+
match = re.search(r'^__version__ = [\'"]([^\'"]+)[\'"]', init, re.M)
12+
if not match:
13+
raise RuntimeError('Unable to find version string.')
14+
return match.group(1)
715

816
setup(
917
name='superannotate_schemas',
1018
long_description=long_description,
1119
long_description_content_type='text/markdown',
12-
version='1.0.1',
20+
version=get_version(),
1321
package_dir={"": "src"},
1422
packages=find_packages(where="src"),
1523
description='SuperAnnotate JSON Schemas',

src/superannotate_schemas/__init__.py

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

99

10-
__version__ = "1.0.0"
11-
10+
__version__ = '1.0.24b'
1211

1312
__all__ = [
1413
"__version__",

src/superannotate_schemas/schemas/base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from pydantic.color import ColorType
2323

2424
from superannotate_schemas.schemas.enums import CreationTypeEnum
25-
from superannotate_schemas.schemas.enums import ImageRoleEnum
25+
from superannotate_schemas.schemas.enums import BaseImageRoleEnum
2626
from superannotate_schemas.schemas.enums import VectorAnnotationTypeEnum
2727
from superannotate_schemas.schemas.enums import AnnotationStatusEnum
2828
from superannotate_schemas.schemas.constances import DATE_REGEX
@@ -93,7 +93,7 @@ def validate_created_at(cls, value):
9393

9494
class UserAction(BaseModel):
9595
email: EmailStr
96-
role: ImageRoleEnum
96+
role: BaseImageRoleEnum
9797

9898

9999
class TrackableModel(BaseModel):

src/superannotate_schemas/schemas/enums.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class VectorAnnotationTypeEnum(str, Enum):
1515
class CreationTypeEnum(str, Enum):
1616
MANUAL = "Manual"
1717
PREDICTION = "Prediction"
18-
PRE_ANNOTATION = "Pre-annotation"
18+
PRE_ANNOTATION = "Preannotation"
1919

2020

2121
class AnnotationStatusEnum(str, Enum):
@@ -33,5 +33,8 @@ class BaseRoleEnum(str, Enum):
3333
QA = "QA"
3434

3535

36-
class ImageRoleEnum(str, Enum):
36+
class BaseImageRoleEnum(str, Enum):
3737
CUSTOMER = "Customer"
38+
ADMIN = "Admin"
39+
ANNOTATOR = "Annotator"
40+
QA = "QA"

src/superannotate_schemas/schemas/external/vector.py

Lines changed: 52 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,26 @@
22
from typing import Optional
33
from typing import Union
44

5+
from pydantic import BaseModel
6+
from pydantic import Field
7+
from pydantic import StrictFloat
8+
from pydantic import StrictInt
9+
from pydantic import StrictStr
10+
from pydantic import ValidationError
11+
from pydantic import conlist
12+
from pydantic.error_wrappers import ErrorWrapper
13+
14+
from superannotate_schemas.schemas.base import AxisPoint
15+
from superannotate_schemas.schemas.base import BaseAttribute
16+
from superannotate_schemas.schemas.base import BaseImageMetadata
517
from superannotate_schemas.schemas.base import BaseVectorInstance
618
from superannotate_schemas.schemas.base import BboxPoints
719
from superannotate_schemas.schemas.base import Comment
8-
from superannotate_schemas.schemas.base import BaseImageMetadata
20+
from superannotate_schemas.schemas.base import INVALID_DICT_MESSAGE
21+
from superannotate_schemas.schemas.base import NotEmptyStr
22+
from superannotate_schemas.schemas.base import StrictNumber
923
from superannotate_schemas.schemas.base import Tag
10-
from superannotate_schemas.schemas.base import BaseAttribute
11-
from superannotate_schemas.schemas.base import AxisPoint
1224
from superannotate_schemas.schemas.enums import VectorAnnotationTypeEnum
13-
from superannotate_schemas.schemas.base import StrictNumber
14-
from superannotate_schemas.schemas.base import NotEmptyStr
15-
16-
from pydantic import BaseModel
17-
from pydantic import StrictInt
18-
from pydantic import StrictFloat
19-
from pydantic import conlist
20-
from pydantic import Field
21-
from pydantic import StrictStr
22-
from pydantic import validate_model
23-
from pydantic import ValidationError
24-
from pydantic import validator
2525

2626

2727
class Attribute(BaseAttribute):
@@ -53,7 +53,7 @@ class Bbox(VectorInstance):
5353
points: BboxPoints
5454

5555

56-
class RotatedBoxPoints(VectorInstance):
56+
class RotatedBoxPoints(BaseModel):
5757
x1: StrictNumber
5858
y1: StrictNumber
5959
x2: StrictNumber
@@ -118,23 +118,43 @@ class Cuboid(VectorInstance):
118118
}
119119

120120

121+
class AnnotationInstance(BaseModel):
122+
__root__: Union[
123+
Template, Cuboid, Point, PolyLine, Polygon, Bbox, Ellipse, RotatedBox
124+
]
125+
126+
@classmethod
127+
def __get_validators__(cls):
128+
yield cls.return_action
129+
130+
@classmethod
131+
def return_action(cls, values):
132+
try:
133+
try:
134+
instance_type = values["type"]
135+
except KeyError:
136+
raise ValidationError(
137+
[ErrorWrapper(ValueError("field required"), "type")], cls
138+
)
139+
return ANNOTATION_TYPES[instance_type](**values)
140+
except KeyError:
141+
raise ValidationError(
142+
[
143+
ErrorWrapper(
144+
ValueError(
145+
f"invalid type, valid types are {', '.join(ANNOTATION_TYPES.keys())}"
146+
),
147+
"type",
148+
)
149+
],
150+
cls,
151+
)
152+
except TypeError as e:
153+
raise TypeError(INVALID_DICT_MESSAGE) from e
154+
155+
121156
class VectorAnnotation(BaseModel):
122157
metadata: Metadata
123158
comments: Optional[List[Comment]] = Field(list())
124159
tags: Optional[List[Tag]] = Field(list())
125-
instances: Optional[
126-
List[
127-
Union[Template, Cuboid, Point, PolyLine, Polygon, Bbox, Ellipse, RotatedBox]
128-
]
129-
] = Field(list())
130-
131-
@validator("instances", pre=True, each_item=True)
132-
def check_instances(cls, instance):
133-
# todo add type checking
134-
annotation_type = instance.get("type")
135-
result = validate_model(ANNOTATION_TYPES[annotation_type], instance)
136-
if result[2]:
137-
raise ValidationError(
138-
result[2].raw_errors, model=ANNOTATION_TYPES[annotation_type]
139-
)
140-
return instance
160+
instances: Optional[List[AnnotationInstance]] = Field(list())

src/superannotate_schemas/schemas/external/video.py

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,16 @@
1212
from superannotate_schemas.schemas.base import NotEmptyStr
1313
from superannotate_schemas.schemas.base import PointLabels
1414
from superannotate_schemas.schemas.base import Tag
15+
from superannotate_schemas.schemas.base import INVALID_DICT_MESSAGE
1516

1617
from pydantic import BaseModel
1718
from pydantic import StrictBool
1819
from pydantic import conlist
20+
from pydantic import ValidationError
1921
from pydantic import Field
2022
from pydantic import StrictInt
2123
from pydantic import StrictStr
22-
24+
from pydantic.error_wrappers import ErrorWrapper
2325

2426
class Attribute(BaseAttribute):
2527
name: NotEmptyStr
@@ -107,7 +109,50 @@ class EventInstance(BaseModel):
107109
}
108110

109111

112+
class AnnotationInstance(BaseModel):
113+
__root__: Union[
114+
BboxInstance, EventInstance
115+
]
116+
117+
@classmethod
118+
def __get_validators__(cls):
119+
yield cls.return_action
120+
121+
@classmethod
122+
def return_action(cls, values):
123+
124+
try:
125+
meta = values.get("meta")
126+
if not meta:
127+
raise ValidationError(
128+
[ErrorWrapper(ValueError("field required"), "meta")], cls
129+
)
130+
try:
131+
instance_type = meta["type"]
132+
except KeyError:
133+
raise ValidationError(
134+
[ErrorWrapper(ValueError("field required"), "meta.type")], cls
135+
)
136+
return ANNOTATION_TYPES[instance_type](**values)
137+
except KeyError:
138+
raise ValidationError(
139+
[
140+
ErrorWrapper(
141+
ValueError(
142+
f"invalid type, valid types are {', '.join(ANNOTATION_TYPES.keys())}"
143+
),
144+
"meta.type",
145+
)
146+
],
147+
cls,
148+
)
149+
except TypeError as e:
150+
raise ValidationError(
151+
[ErrorWrapper(ValueError(INVALID_DICT_MESSAGE), "meta")], cls
152+
)
153+
154+
110155
class VideoAnnotation(BaseModel):
111156
metadata: MetaData
112-
instances: Optional[List[Union[EventInstance, BboxInstance]]] = Field(list())
157+
instances: Optional[List[AnnotationInstance]] = Field(list())
113158
tags: Optional[List[Tag]] = Field(list())

src/superannotate_schemas/schemas/internal/vector.py

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from superannotate_schemas.schemas.base import AxisPoint
1212
from superannotate_schemas.schemas.base import VectorAnnotationTypeEnum
1313
from superannotate_schemas.schemas.base import StrictNumber
14+
from superannotate_schemas.schemas.base import INVALID_DICT_MESSAGE
1415

1516
from pydantic import BaseModel
1617
from pydantic import StrictInt
@@ -20,6 +21,7 @@
2021
from pydantic import validate_model
2122
from pydantic import ValidationError
2223
from pydantic import validator
24+
from pydantic.error_wrappers import ErrorWrapper
2325

2426

2527
class Attribute(BaseAttribute):
@@ -47,7 +49,7 @@ class Bbox(VectorInstance):
4749
points: BboxPoints
4850

4951

50-
class RotatedBoxPoints(VectorInstance):
52+
class RotatedBoxPoints(BaseModel):
5153
x1: StrictNumber
5254
y1: StrictNumber
5355
x2: StrictNumber
@@ -110,6 +112,40 @@ class Cuboid(VectorInstance):
110112
VectorAnnotationTypeEnum.RBBOX: RotatedBox,
111113
}
112114

115+
class AnnotationInstance(BaseModel):
116+
__root__: Union[
117+
Template, Cuboid, Point, PolyLine, Polygon, Bbox, Ellipse, RotatedBox
118+
]
119+
120+
@classmethod
121+
def __get_validators__(cls):
122+
yield cls.return_action
123+
124+
@classmethod
125+
def return_action(cls, values):
126+
try:
127+
try:
128+
instance_type = values["type"]
129+
except KeyError:
130+
raise ValidationError(
131+
[ErrorWrapper(ValueError("field required"), "type")], cls
132+
)
133+
return ANNOTATION_TYPES[instance_type](**values)
134+
except KeyError:
135+
raise ValidationError(
136+
[
137+
ErrorWrapper(
138+
ValueError(
139+
f"invalid type, valid types are {', '.join(ANNOTATION_TYPES.keys())}"
140+
),
141+
"type",
142+
)
143+
],
144+
cls,
145+
)
146+
except TypeError as e:
147+
raise TypeError(INVALID_DICT_MESSAGE) from e
148+
113149

114150
class VectorAnnotation(BaseModel):
115151
metadata: Metadata
@@ -123,11 +159,36 @@ class VectorAnnotation(BaseModel):
123159

124160
@validator("instances", pre=True, each_item=True)
125161
def check_instances(cls, instance):
126-
# todo add type checking
127162
annotation_type = instance.get("type")
163+
if not annotation_type:
164+
raise ValidationError(
165+
[
166+
ErrorWrapper(
167+
ValueError(
168+
f"type field required"
169+
),
170+
"type",
171+
)
172+
],
173+
model=BaseModel
174+
)
175+
model_type = ANNOTATION_TYPES.get(annotation_type)
176+
if not model_type:
177+
raise ValidationError(
178+
[
179+
ErrorWrapper(
180+
ValueError(
181+
f"invalid value"
182+
),
183+
"type",
184+
)
185+
],
186+
model=BaseModel
187+
)
128188
result = validate_model(ANNOTATION_TYPES[annotation_type], instance)
129189
if result[2]:
130190
raise ValidationError(
131191
result[2].raw_errors, model=ANNOTATION_TYPES[annotation_type]
132192
)
133193
return instance
194+

0 commit comments

Comments
 (0)