Skip to content

Commit 63c3ade

Browse files
authored
Merge pull request #649 from superannotateai/friday
Friday
2 parents 469514d + 4ccf705 commit 63c3ade

31 files changed

+210
-124
lines changed

CHANGELOG.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ History
77
All release highlights of this project will be documented in this file.
88

99
4.4.15 - August 20, 2023
10-
_______________________
10+
________________________
1111

1212
**Added**
1313

1414
- Support for `relationship` class types in the document project.
1515

1616

1717
4.4.14 - August 20, 2023
18-
_______________________
18+
________________________
1919

2020
**Added**
2121

requirements.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
pydantic~=1.10
1+
pydantic>=1.10,!=2.0.*
22
aiohttp~=3.8
33
boto3~=1.26
4-
opencv-python~=4.7
4+
opencv-python-headless~=4.7
55
packaging~=23.1
66
plotly~=5.14
77
email-validator~=2.0
88
pandas~=1.3
99
ffmpeg-python~=0.2
10-
pillow~=9.5
10+
pillow>=9.5,~=10.0
1111
tqdm~=4.66.1
1212
requests~=2.31.0
1313
aiofiles==23.1.0

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def get_version():
3636
description="Python SDK to SuperAnnotate platform",
3737
license="MIT",
3838
author="SuperAnnotate AI",
39-
author_email="suppoort@superannotate.com",
39+
author_email="support@superannotate.com",
4040
url="https://github.com/superannotateai/superannotate-python-sdk",
4141
long_description=open("README.rst").read(),
4242
long_description_content_type="text/x-rst",

src/superannotate/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import sys
44

55

6-
__version__ = "4.4.15"
6+
__version__ = "4.4.16dev1"
77

88
sys.path.append(os.path.split(os.path.realpath(__file__))[0])
99

src/superannotate/lib/app/interface/base_interface.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@
1111
from typing import Sized
1212

1313
import lib.core as constants
14-
import pydantic
1514
from lib.app.interface.types import validate_arguments
1615
from lib.core import CONFIG
1716
from lib.core import setup_logging
1817
from lib.core.entities.base import ConfigEntity
1918
from lib.core.entities.base import TokenStr
2019
from lib.core.exceptions import AppException
20+
from lib.core.pydantic_v1 import ErrorWrapper
21+
from lib.core.pydantic_v1 import ValidationError
2122
from lib.infrastructure.controller import Controller
2223
from lib.infrastructure.utils import extract_project_folder
2324
from lib.infrastructure.validators import wrap_error
@@ -61,7 +62,7 @@ def __init__(self, token: TokenStr = None, config_path: str = None):
6162
raise AppException(
6263
f"SuperAnnotate config file {constants.CONFIG_INI_FILE_LOCATION} not found."
6364
)
64-
except pydantic.ValidationError as e:
65+
except ValidationError as e:
6566
raise AppException(wrap_error(e))
6667
except KeyError:
6768
raise
@@ -78,13 +79,9 @@ def _retrieve_configs_from_json(path: Path) -> typing.Union[ConfigEntity]:
7879
token = json_data["token"]
7980
try:
8081
config = ConfigEntity(SA_TOKEN=token)
81-
except pydantic.ValidationError:
82-
raise pydantic.ValidationError(
83-
[
84-
pydantic.error_wrappers.ErrorWrapper(
85-
ValueError("Invalid token."), loc="token"
86-
)
87-
],
82+
except ValidationError:
83+
raise ValidationError(
84+
[ErrorWrapper(ValueError("Invalid token."), loc="token")],
8885
model=ConfigEntity,
8986
)
9087
host = json_data.get("main_endpoint")

src/superannotate/lib/app/interface/sdk_interface.py

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
from typing import TypeVar
1616
from typing import Union
1717

18-
import pydantic
1918
from typing_extensions import Literal
2019

2120
if sys.version_info < (3, 11):
@@ -24,10 +23,7 @@
2423
from typing import TypedDict, NotRequired, Required # noqa
2524

2625
import boto3
27-
from pydantic import conlist
28-
from pydantic import constr
29-
from pydantic import parse_obj_as
30-
from pydantic.error_wrappers import ValidationError
26+
3127
from tqdm import tqdm
3228

3329
import lib.core as constants
@@ -61,16 +57,18 @@
6157
from lib.core.types import MLModel
6258
from lib.core.types import PriorityScoreEntity
6359
from lib.core.types import Project
60+
from lib.core.pydantic_v1 import ValidationError
61+
from lib.core.pydantic_v1 import constr
62+
from lib.core.pydantic_v1 import conlist
63+
from lib.core.pydantic_v1 import parse_obj_as
6464
from lib.infrastructure.utils import extract_project_folder
6565
from lib.infrastructure.validators import wrap_error
6666

6767

6868
logger = logging.getLogger("sa")
6969

70-
7170
NotEmptyStr = TypeVar("NotEmptyStr", bound=constr(strict=True, min_length=1))
7271

73-
7472
PROJECT_STATUS = Literal["NotStarted", "InProgress", "Completed", "OnHold"]
7573

7674
PROJECT_TYPE = Literal[
@@ -1131,6 +1129,7 @@ def prepare_export(
11311129
annotation_statuses: Optional[List[ANNOTATION_STATUS]] = None,
11321130
include_fuse: Optional[bool] = False,
11331131
only_pinned=False,
1132+
**kwargs,
11341133
):
11351134
"""Prepare annotations and classes.json for export. Original and fused images for images with
11361135
annotations can be included with include_fuse flag.
@@ -1147,6 +1146,8 @@ def prepare_export(
11471146
:type include_fuse: bool
11481147
:param only_pinned: enable only pinned output in export. This option disables all other types of output.
11491148
:type only_pinned: bool
1149+
:param kwargs: Arbitrary kwarg ``integration_name``
1150+
can be provided which will be used as a storage to store export file
11501151
11511152
:return: metadata object of the prepared export
11521153
:rtype: dict
@@ -1165,12 +1166,22 @@ def prepare_export(
11651166
constants.AnnotationStatus.COMPLETED.name,
11661167
constants.AnnotationStatus.SKIPPED.name,
11671168
]
1169+
integration_name = kwargs.get("integration_name")
1170+
integration_id = None
1171+
if integration_name:
1172+
for integration in self.controller.integrations.list().data:
1173+
if integration.name == integration_name:
1174+
integration_id = integration.id
1175+
break
1176+
else:
1177+
raise AppException("Integration not found.")
11681178
response = self.controller.prepare_export(
11691179
project_name=project_name,
11701180
folder_names=folders,
11711181
include_fuse=include_fuse,
11721182
only_pinned=only_pinned,
11731183
annotation_statuses=annotation_statuses,
1184+
integration_id=integration_id,
11741185
)
11751186
if response.errors:
11761187
raise AppException(response.errors)
@@ -2095,7 +2106,7 @@ def delete_annotations(
20952106
20962107
:param project: project name or folder path (e.g., "project1/folder1")
20972108
:type project: str
2098-
:param item_names: item names. If None, all the items in the specified directory will be deleted.
2109+
:param item_names: item names. If None, all the annotations in the specified directory will be deleted.
20992110
:type item_names: list of strs
21002111
"""
21012112

@@ -2538,6 +2549,15 @@ def attach_items(
25382549
25392550
:return: uploaded, failed and duplicated item names
25402551
:rtype: tuple of list of strs
2552+
2553+
Example:
2554+
::
2555+
client = SAClient()
2556+
client.attach_items(
2557+
project = "Medical Annotations",
2558+
attachments = [{"name": "item", "url": "https://..."}]
2559+
)
2560+
25412561
"""
25422562

25432563
project_name, folder_name = extract_project_folder(project)
@@ -2549,7 +2569,7 @@ def attach_items(
25492569
for item, count in collections.Counter(attachments).items()
25502570
if count > 1
25512571
]
2552-
except pydantic.ValidationError:
2572+
except ValidationError:
25532573
(
25542574
unique_attachments,
25552575
duplicate_attachments,

src/superannotate/lib/app/interface/types.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33

44
from lib.core.enums import BaseTitledEnum
55
from lib.core.exceptions import AppException
6+
from lib.core.pydantic_v1 import constr
7+
from lib.core.pydantic_v1 import errors
8+
from lib.core.pydantic_v1 import pydantic_validate_arguments
9+
from lib.core.pydantic_v1 import PydanticTypeError
10+
from lib.core.pydantic_v1 import StrictStr
11+
from lib.core.pydantic_v1 import StrRegexError
12+
from lib.core.pydantic_v1 import ValidationError
613
from lib.infrastructure.validators import wrap_error
7-
from pydantic import constr
8-
from pydantic import errors
9-
from pydantic import StrictStr
10-
from pydantic import validate_arguments as pydantic_validate_arguments
11-
from pydantic import ValidationError
12-
from pydantic.errors import PydanticTypeError
13-
from pydantic.errors import StrRegexError
1414

1515

1616
class EnumMemberError(PydanticTypeError):

src/superannotate/lib/app/serializers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
from typing import Union
66

77
import superannotate.lib.core as constance
8-
from pydantic import BaseModel
98
from superannotate.lib.core.entities import BaseEntity
9+
from superannotate.lib.core.pydantic_v1 import BaseModel
1010

1111

1212
class BaseSerializer(ABC):

src/superannotate/lib/core/entities/base.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@
1313
from lib.core import LOG_FILE_LOCATION
1414
from lib.core.enums import AnnotationStatus
1515
from lib.core.enums import BaseTitledEnum
16-
from pydantic import BaseModel as PydanticBaseModel
17-
from pydantic import Extra
18-
from pydantic import Field
19-
from pydantic import StrictStr
20-
from pydantic.datetime_parse import parse_datetime
21-
from pydantic.typing import is_namedtuple
22-
from pydantic.utils import ROOT_KEY
23-
from pydantic.utils import sequence_like
24-
from pydantic.utils import ValueItems
25-
from typing_extensions import Literal
16+
from lib.core.pydantic_v1 import BaseModel
17+
from lib.core.pydantic_v1 import Extra
18+
from lib.core.pydantic_v1 import Field
19+
from lib.core.pydantic_v1 import is_namedtuple
20+
from lib.core.pydantic_v1 import Literal
21+
from lib.core.pydantic_v1 import parse_datetime
22+
from lib.core.pydantic_v1 import ROOT_KEY
23+
from lib.core.pydantic_v1 import sequence_like
24+
from lib.core.pydantic_v1 import StrictStr
25+
from lib.core.pydantic_v1 import ValueItems
2626

2727
DATE_TIME_FORMAT_ERROR_MESSAGE = (
2828
"does not match expected format YYYY-MM-DDTHH:MM:SS.fffZ"
@@ -37,7 +37,7 @@
3737
_missing = object()
3838

3939

40-
class BaseModel(PydanticBaseModel):
40+
class BaseModel(BaseModel):
4141
"""
4242
Added new extra keys
4343
- use_enum_names: that's for BaseTitledEnum to use names instead of enum objects
@@ -121,7 +121,7 @@ def _get_value(
121121
exclude_none: bool,
122122
) -> Any:
123123

124-
if isinstance(v, PydanticBaseModel):
124+
if isinstance(v, BaseModel):
125125
v_dict = v.dict(
126126
by_alias=by_alias,
127127
exclude_unset=exclude_unset,

src/superannotate/lib/core/entities/classes.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,24 @@
55
from typing import Optional
66

77
from lib.core.entities.base import BaseModel
8+
from lib.core.entities.base import parse_datetime
89
from lib.core.enums import BaseTitledEnum
910
from lib.core.enums import ClassTypeEnum
10-
from pydantic import BaseModel as BasePydanticModel
11-
from pydantic import Extra
12-
from pydantic import Field
13-
from pydantic import StrictInt
14-
from pydantic import StrictStr
15-
from pydantic import validator
16-
from pydantic.color import Color
17-
from pydantic.color import ColorType
18-
from pydantic.datetime_parse import parse_datetime
11+
from lib.core.pydantic_v1 import Color
12+
from lib.core.pydantic_v1 import ColorType
13+
from lib.core.pydantic_v1 import Extra
14+
from lib.core.pydantic_v1 import Field
15+
from lib.core.pydantic_v1 import StrictInt
16+
from lib.core.pydantic_v1 import StrictStr
17+
from lib.core.pydantic_v1 import validator
1918

2019
DATE_REGEX = r"\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d(?:\.\d{3})Z"
2120
DATE_TIME_FORMAT_ERROR_MESSAGE = (
2221
"does not match expected format YYYY-MM-DDTHH:MM:SS.fffZ"
2322
)
2423

2524

26-
class HexColor(BasePydanticModel):
25+
class HexColor(BaseModel):
2726
__root__: ColorType
2827

2928
@validator("__root__", pre=True)

0 commit comments

Comments
 (0)