Skip to content

Commit 3e6f0b5

Browse files
committed
Merge branch 're-design-sdk' of https://github.com/superannotateai/superannotate-python-sdk into re-design-sdk
2 parents 5f5ca78 + cbf536b commit 3e6f0b5

File tree

10 files changed

+74
-31
lines changed

10 files changed

+74
-31
lines changed

pytest.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
minversion = 3.0
33
log_cli=true
44
python_files = test_*.py
5-
;addopts = -n32 --dist=loadscope
5+
addopts = -n32 --dist=loadscope

src/superannotate/lib/core/response.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
from typing import Union
22

3-
from lib.core.exceptions import AppException
4-
53

64
class Response:
75
def __init__(self, status: str = None, data: Union[dict, list] = None):
@@ -27,13 +25,7 @@ def status(self, value):
2725

2826
@property
2927
def errors(self):
30-
message = ""
31-
for error in self._errors:
32-
if isinstance(error, AppException):
33-
message += error.message + "\n"
34-
else:
35-
message += str(error)
36-
return message
28+
return "\n".join([str(error) for error in self._errors])
3729

3830
@errors.setter
3931
def errors(self, error: list):

src/superannotate/lib/core/serviceproviders.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
from abc import ABC
21
from abc import abstractmethod
32
from typing import Any
43
from typing import Dict
@@ -7,7 +6,16 @@
76
from typing import Tuple
87

98

10-
class SuerannotateServiceProvider(ABC):
9+
class SingleInstanceMetaClass(type):
10+
_instances = {}
11+
12+
def __call__(cls, *args, **kwargs):
13+
if cls not in SingleInstanceMetaClass._instances:
14+
SingleInstanceMetaClass._instances[cls] = super().__call__(*args, **kwargs)
15+
return SingleInstanceMetaClass._instances[cls]
16+
17+
18+
class SuerannotateServiceProvider(metaclass=SingleInstanceMetaClass):
1119
@abstractmethod
1220
def attach_files(
1321
self,

src/superannotate/lib/core/usecases.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,7 +1359,9 @@ def __init__(
13591359

13601360
def validate_image_quality(self):
13611361
for setting in self._to_update:
1362-
if setting["attribute"].lower() == "imagequality" and isinstance(setting["value"], str):
1362+
if setting["attribute"].lower() == "imagequality" and isinstance(
1363+
setting["value"], str
1364+
):
13631365
setting["value"] = constances.ImageQuality.get_value(setting["value"])
13641366
return
13651367

@@ -1593,7 +1595,7 @@ def execute(self):
15931595
self._backend_service.delete_images(
15941596
project_id=self._project.uuid,
15951597
team_id=self._project.team_id,
1596-
image_ids=image_ids[i : i + self.CHUNK_SIZE],
1598+
image_ids=image_ids[i : i + self.CHUNK_SIZE], # noqa: E203
15971599
)
15981600
return self._response
15991601

src/superannotate/lib/infrastructure/repositories.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ def update(self, entity: ProjectSettingEntity):
190190
res = self._service.set_project_settings(
191191
self._project.uuid, self._project.team_id, [entity.to_dict()]
192192
)
193-
return self.dict2entity(res[0])
193+
return entity
194194

195195
@staticmethod
196196
def dict2entity(data: dict):

src/superannotate/lib/infrastructure/services.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ def __init__(self, api_url: str, auth_token: str, logger, paginate_by=None):
2929
self.logger = logger
3030
self._paginate_by = paginate_by
3131
self.team_id = auth_token.split("=")[-1]
32+
self._session = None
33+
34+
@property
35+
def session(self):
36+
if not self._session:
37+
self._session = requests.Session()
38+
self._session.headers.update(self.default_headers)
39+
return self._session
3240

3341
@property
3442
def default_headers(self):
@@ -69,16 +77,11 @@ def _request(
6977
) -> requests.Response:
7078
kwargs = {"json": data} if data else {}
7179
headers_dict = self.default_headers.copy()
72-
headers_dict.update(headers if headers else {})
73-
method = getattr(requests, method)
80+
self.session.headers.update(headers if headers else {})
81+
method = getattr(self.session, method)
7482
with self.safe_api():
7583
response = method(
76-
url,
77-
**kwargs,
78-
headers=headers_dict,
79-
params=params,
80-
timeout=60,
81-
verify=False,
84+
url, **kwargs, headers=headers_dict, params=params, timeout=60,
8285
)
8386
if response.status_code == 404 and retried < 3:
8487
return self._request(
@@ -239,7 +242,8 @@ def get_projects(self, query_string: str = None) -> list:
239242
url = urljoin(self.api_url, self.URL_LIST_PROJECTS)
240243
if query_string:
241244
url = f"{url}?{query_string}"
242-
return self._get_all_pages(url)
245+
data = self._get_all_pages(url)
246+
return data
243247

244248
def create_project(self, project_data: dict) -> dict:
245249
create_project_url = urljoin(self.api_url, self.URL_CREATE_PROJECT)

tests/integration/test_folders.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ def test_project_folder_image_count(self):
182182
self.PROJECT_NAME, self.folder_path, annotation_status="InProgress"
183183
)
184184
num_images = sa.get_project_image_count(self.PROJECT_NAME)
185-
self.assertEqual(num_images, 0)
185+
self.assertEqual(num_images, 4)
186186

187187
sa.create_folder(self.PROJECT_NAME, self.TEST_FOLDER_NAME_1)
188188
sa.upload_images_from_folder_to_project(
@@ -191,7 +191,7 @@ def test_project_folder_image_count(self):
191191
annotation_status="InProgress",
192192
)
193193
num_images = sa.get_project_image_count(self.PROJECT_NAME)
194-
self.assertEqual(num_images, 0)
194+
self.assertEqual(num_images, 4)
195195

196196
num_images = sa.get_project_image_count(
197197
self.PROJECT_NAME + f"/{self.TEST_FOLDER_NAME_1}"
@@ -201,7 +201,7 @@ def test_project_folder_image_count(self):
201201
num_images = sa.get_project_image_count(
202202
self.PROJECT_NAME, with_all_subfolders=True
203203
)
204-
self.assertEqual(num_images, 4)
204+
self.assertEqual(num_images, 8)
205205

206206
def test_delete_images(self):
207207
sa.create_folder(self.PROJECT_NAME, self.TEST_FOLDER_NAME_1)
@@ -252,7 +252,7 @@ def test_copy_images3(self):
252252
)
253253

254254
num_images = sa.get_project_image_count(self.PROJECT_NAME)
255-
assert num_images == 0
255+
assert num_images == 4
256256

257257
def test_copy_images4(self):
258258
sa.upload_images_from_folder_to_project(
@@ -269,7 +269,7 @@ def test_copy_images4(self):
269269
self.assertEqual(num_images, 2)
270270

271271
num_images = sa.get_project_image_count(self.PROJECT_NAME)
272-
self.assertEqual(num_images, 0)
272+
self.assertEqual(num_images, 4)
273273

274274
def test_copy_images(self):
275275
sa.create_folder(self.PROJECT_NAME, self.TEST_FOLDER_NAME_1)
Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22
from os.path import dirname
33
import src.superannotate as sa
4+
from src.superannotate.lib.app.exceptions import AppException
45
from tests.integration.base import BaseTestCase
56

67

@@ -9,6 +10,10 @@ class TestInterface(BaseTestCase):
910
TEST_FOLDER_PATH = "data_set/sample_project_vector"
1011
PROJECT_DESCRIPTION = "desc"
1112
PROJECT_TYPE = "Vector"
13+
TEST_FOLDER_NAME = "folder"
14+
EXAMPLE_IMAGE_1 = "example_image_1.jpg"
15+
EXAMPLE_IMAGE_2 = "example_image_2.jpg"
16+
1217
@property
1318
def folder_path(self):
1419
return os.path.join(dirname(dirname(__file__)), self.TEST_FOLDER_PATH)
@@ -17,5 +22,26 @@ def test_get_project_default_image_quality_in_editor(self):
1722
sa.invite_contributor_to_team(2, 2)
1823
self.assertIsNotNone(sa.get_project_default_image_quality_in_editor(self.PROJECT_NAME))
1924

20-
def test_get_project_metadata(self):
21-
pass
25+
def test_delete_images(self):
26+
sa.create_folder(self.PROJECT_NAME, self.TEST_FOLDER_NAME)
27+
28+
sa.upload_images_from_folder_to_project(
29+
f"{self.PROJECT_NAME}/{self.TEST_FOLDER_NAME}",
30+
self.folder_path,
31+
annotation_status="InProgress",
32+
)
33+
num_images = sa.get_project_image_count(
34+
self.PROJECT_NAME, with_all_subfolders=True
35+
)
36+
self.assertEqual(num_images, 4)
37+
sa.delete_images(f"{self.PROJECT_NAME}/{self.TEST_FOLDER_NAME}")
38+
39+
num_images = sa.get_project_image_count(
40+
self.PROJECT_NAME, with_all_subfolders=True
41+
)
42+
self.assertEqual(num_images, 0)
43+
44+
def test_delete_folder(self):
45+
print(sa.search_folders(self.PROJECT_NAME))
46+
with self.assertRaises(AppException):
47+
sa.delete_folders(self.PROJECT_NAME, ["non-existing folder"])

tests/profiling/profiling.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import src.superannotate as sa
2+
3+
import time
4+
5+
6+
7+
stat = time.time()
8+
sa.search_annotation_classes("Vector Project")
9+
end = time.time()
10+
print(11, end-stat)

tests/unit/test_usecases.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from unittest.mock import Mock
33

44
import pytest
5+
56
from src.superannotate.lib.core.exceptions import AppValidationException
67
from src.superannotate.lib.core.usecases import BaseUseCase
78

0 commit comments

Comments
 (0)