Skip to content

Commit dd6215e

Browse files
authored
Merge pull request #662 from superannotateai/develop
Develop
2 parents 55fc5b5 + 9e38a60 commit dd6215e

File tree

10 files changed

+101
-11
lines changed

10 files changed

+101
-11
lines changed

CHANGELOG.rst

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,20 @@ History
66

77
All release highlights of this project will be documented in this file.
88

9+
4.4.17 - December 21, 2023
10+
__________________________
11+
12+
**Added**
13+
14+
- ``SAClient.upload_annotations()`` added default values to the annotations during the upload.
15+
16+
**Updated**
17+
18+
- Fixed `SAClient.search_project() search with special characters.`
19+
- ``pandas`` dependency ``pandas~=2.0``
20+
921
4.4.16 - November 12, 2023
10-
_______________________
22+
__________________________
1123

1224
**Added**
1325

@@ -16,9 +28,9 @@ _______________________
1628
**Updated**
1729

1830
- Documentation updates
19-
- pillow dependency ``pillow>=9.5,~=10.0``.
20-
- opencv dependency replaced by ``opencv-python-headless~=4.7``.
21-
- pydantic dependency ``pydantic>=1.10,!=2.0.*``.
31+
- ``pillow`` dependency ``pillow>=9.5,~=10.0``.
32+
- ``opencv`` dependency replaced by ``opencv-python-headless~=4.7``.
33+
- ``pydantic`` dependency ``pydantic>=1.10,!=2.0.*``.
2234

2335
4.4.15 - August 20, 2023
2436
________________________

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ opencv-python-headless~=4.7
55
packaging~=23.1
66
plotly~=5.14
77
email-validator~=2.0
8-
pandas~=1.3
8+
pandas~=2.0
99
ffmpeg-python~=0.2
1010
pillow>=9.5,~=10.0
1111
tqdm~=4.66.1

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.16"
6+
__version__ = "4.4.17"
77

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

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1668,6 +1668,7 @@ def upload_annotations(
16681668
folder=folder,
16691669
annotations=annotations,
16701670
keep_status=keep_status,
1671+
user=self.controller.current_user,
16711672
)
16721673
if response.errors:
16731674
raise AppException(response.errors)

src/superannotate/lib/core/usecases/annotations.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ def __init__(
295295
folder: FolderEntity,
296296
annotations: List[dict],
297297
service_provider: BaseServiceProvider,
298+
user: UserEntity,
298299
keep_status: bool = False,
299300
):
300301
super().__init__(reporter)
@@ -304,6 +305,7 @@ def __init__(
304305
self._service_provider = service_provider
305306
self._keep_status = keep_status
306307
self._report = Report([], [], [], [])
308+
self._user = user
307309

308310
def validate_project_type(self):
309311
if self._project.type == constants.ProjectType.PIXEL.value:
@@ -439,6 +441,9 @@ def execute(self):
439441
annotation_name = annotation["metadata"]["name"]
440442
item = name_item_map.get(annotation_name)
441443
if item:
444+
annotation = UploadAnnotationUseCase.set_defaults(
445+
self._user.email, annotation, self._project.type
446+
)
442447
items_to_upload.append(
443448
ItemToUpload(item=item, annotation_json=annotation)
444449
)

src/superannotate/lib/infrastructure/controller.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,7 @@ def upload_multiple(
568568
folder: FolderEntity,
569569
annotations: List[dict],
570570
keep_status: bool,
571+
user: UserEntity,
571572
):
572573
use_case = usecases.UploadAnnotationsUseCase(
573574
reporter=Reporter(),
@@ -576,6 +577,7 @@ def upload_multiple(
576577
annotations=annotations,
577578
service_provider=self.service_provider,
578579
keep_status=keep_status,
580+
user=user,
579581
)
580582
return use_case.execute()
581583

src/superannotate/lib/infrastructure/services/http_client.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
import aiohttp
1515
import requests
16+
from aiohttp.client_exceptions import ClientError
1617
from lib.core.exceptions import AppException
1718
from lib.core.service_types import ServiceResponse
1819
from lib.core.serviceproviders import BaseClient
@@ -197,7 +198,7 @@ def serialize_response(
197198
if not response.ok:
198199
if response.status_code in (502, 504):
199200
data[
200-
"_error"
201+
"res_error"
201202
] = "Our service is currently unavailable, please try again later."
202203
return content_type(**data)
203204
else:
@@ -234,7 +235,13 @@ async def request(self, *args, **kwargs) -> aiohttp.ClientResponse:
234235
for _ in range(attempts):
235236
delay += self.BACKOFF_FACTOR
236237
attempts -= 1
237-
response = await super()._request(*args, **kwargs)
238+
try:
239+
response = await super()._request(*args, **kwargs)
240+
except ClientError:
241+
if not attempts:
242+
raise
243+
await asyncio.sleep(delay)
244+
continue
238245
if response.status not in self.RETRY_STATUS_CODES or not attempts:
239246
return response
240247
await asyncio.sleep(delay)

src/superannotate/lib/infrastructure/services/project.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,8 @@ def create(self, entity: entities.ProjectEntity) -> ServiceResponse:
4444

4545
def list(self, condition: Condition = None):
4646
return self.client.paginate(
47-
url=f"{self.URL_LIST}?{condition.build_query()}"
48-
if condition
49-
else self.URL_LIST,
47+
url=self.URL_LIST,
48+
query_params=condition.get_as_params_dict(),
5049
item_type=entities.ProjectEntity,
5150
)
5251

tests/integration/annotations/test_upload_annotations.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ def test_annotation_folder_upload_download(self):
7171
assert i["annotation_status"] == "InProgress"
7272
assert annotation["instances"][-1]["type"] == "tag"
7373
assert annotation["instances"][-2]["type"] == "tag"
74+
assert annotation["instances"][-2]["probability"] == 100
75+
assert annotation["instances"][-2]["creationType"] == "Preannotation"
7476

7577
def test_upload_keep_true(self):
7678
self._attach_items()
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
from src.superannotate import SAClient
2+
from tests.integration.base import BaseTestCase
3+
4+
sa = SAClient()
5+
6+
7+
class TestProjectSearch(BaseTestCase):
8+
PROJECT_NAME = "TestProjectSearch"
9+
PROJECT_DESCRIPTION = "Desc"
10+
PROJECT_TYPE = "Vector"
11+
PROJECT_NAME_2 = "TestProjectSearch2"
12+
REPLACED_PROJECT_NAME = "TestProjectSearchReplaced"
13+
PROJECT_NAME_CONTAIN_SPECIAL_CHARACTER = "TestProjectName!@#$%+"
14+
15+
def setUp(self, *args, **kwargs):
16+
self.tearDown()
17+
self._project = sa.create_project(
18+
self.PROJECT_NAME, self.PROJECT_DESCRIPTION, self.PROJECT_TYPE
19+
)
20+
self._project_2 = sa.create_project(
21+
self.PROJECT_NAME_2, self.PROJECT_DESCRIPTION, self.PROJECT_TYPE
22+
)
23+
24+
def tearDown(self) -> None:
25+
projects = []
26+
projects.extend(sa.search_projects(self.PROJECT_NAME, return_metadata=True))
27+
projects.extend(
28+
sa.search_projects(self.REPLACED_PROJECT_NAME, return_metadata=True)
29+
)
30+
projects.extend(
31+
sa.search_projects(
32+
self.PROJECT_NAME_CONTAIN_SPECIAL_CHARACTER, return_metadata=True
33+
)
34+
)
35+
for project in projects:
36+
try:
37+
sa.delete_project(project)
38+
except Exception as _:
39+
pass
40+
41+
def test_project_search(self):
42+
# search before rename
43+
result = sa.search_projects(self.PROJECT_NAME, return_metadata=True)
44+
assert len(result) == 2
45+
46+
# search after rename
47+
sa.rename_project(self.PROJECT_NAME, self.REPLACED_PROJECT_NAME)
48+
meta = sa.get_project_metadata(self.REPLACED_PROJECT_NAME)
49+
self.assertEqual(meta["name"], self.REPLACED_PROJECT_NAME)
50+
result = sa.search_projects(self.REPLACED_PROJECT_NAME, return_metadata=True)
51+
assert len(result) == 1
52+
assert result[0]["name"] == self.REPLACED_PROJECT_NAME
53+
54+
def test_project_search_special_character(self):
55+
sa.rename_project(
56+
self.PROJECT_NAME, self.PROJECT_NAME_CONTAIN_SPECIAL_CHARACTER
57+
)
58+
meta = sa.get_project_metadata(self.PROJECT_NAME_CONTAIN_SPECIAL_CHARACTER)
59+
self.assertEqual(meta["name"], self.PROJECT_NAME_CONTAIN_SPECIAL_CHARACTER)
60+
result = sa.search_projects("!@#$%+", return_metadata=True)
61+
assert len(result) == 1
62+
assert result[0]["name"] == self.PROJECT_NAME_CONTAIN_SPECIAL_CHARACTER

0 commit comments

Comments
 (0)