Skip to content

Commit 5103f9b

Browse files
authored
Merge pull request #169 from superannotateai/re-design-sdk
Re design sdk
2 parents 5bad7ea + e33fb04 commit 5103f9b

File tree

11 files changed

+95
-30
lines changed

11 files changed

+95
-30
lines changed

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
name='superannotate',
2828
version=version,
2929
package_dir={"": "src"},
30-
30+
package_data={"superannotate": ["logging.conf"]},
3131
packages=find_packages(where="src"),
3232
description='Python SDK to SuperAnnotate platform',
3333
license='MIT',

src/superannotate/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import logging.config
2+
13
from superannotate.lib.app.analytics.class_analytics import attribute_distribution
24
from superannotate.lib.app.analytics.class_analytics import class_distribution
35
from superannotate.lib.app.annotation_helpers import add_annotation_bbox_to_json
@@ -243,6 +245,7 @@
243245
"upload_videos_from_folder_to_project",
244246
# Annotation Section
245247
"create_annotation_class",
248+
"delete_annotation_class",
246249
"prepare_export",
247250
"download_export",
248251
"set_images_annotation_statuses",
@@ -284,3 +287,8 @@
284287
]
285288

286289
__author__ = "Superannotate"
290+
import os
291+
292+
file_dir = os.path.split(os.path.realpath(__file__))[0]
293+
294+
logging.config.fileConfig(os.path.join(file_dir, "logging.conf"))

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

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
from lib.app.serializers import BaseSerializers
3737
from lib.app.serializers import ImageSerializer
3838
from lib.app.serializers import ProjectSerializer
39+
from lib.app.serializers import SettingsSerializer
3940
from lib.app.serializers import TeamSerializer
4041
from lib.core.enums import ImageQuality
4142
from lib.core.exceptions import AppException
@@ -45,15 +46,7 @@
4546
from tqdm import tqdm
4647

4748

48-
logging.basicConfig(level=logging.INFO)
49-
formatter = logging.Formatter(fmt="SA-PYTHON-SDK - %(levelname)s - %(message)s")
50-
51-
handler = logging.StreamHandler()
52-
handler.setFormatter(formatter)
53-
5449
logger = logging.getLogger("superannotate-python-sdk")
55-
logger.setLevel(logging.INFO)
56-
logger.addHandler(handler)
5750

5851
controller = Controller(logger)
5952

@@ -864,8 +857,12 @@ def get_project_metadata(
864857
).data
865858

866859
metadata = ProjectSerializer(response["project"]).serialize()
860+
if response.get("settings"):
861+
metadata["settings"] = [
862+
SettingsSerializer(setting).serialize() for setting in response["settings"]
863+
]
867864

868-
for elem in "settings", "classes", "workflows", "contributors":
865+
for elem in "classes", "workflows", "contributors":
869866
if response.get(elem):
870867
metadata[elem] = [
871868
BaseSerializers(attribute).serialize() for attribute in response[elem]
@@ -2690,7 +2687,6 @@ def delete_model(model):
26902687
logger.info("Failed to delete model, please try again")
26912688
else:
26922689
logger.info("Model successfully deleted")
2693-
raise AppException("Failed to delete model")
26942690
return model
26952691

26962692

@@ -2706,11 +2702,11 @@ def stop_model_training(model):
27062702

27072703
model_id = None
27082704
if isinstance(model, dict):
2709-
model_id = model['id']
2705+
model_id = model["id"]
27102706
else:
27112707
res = controller.search_models(name=model).data
27122708
if len(res):
2713-
model_id = res[0]['id']
2709+
model_id = res[0]["id"]
27142710
else:
27152711
raise AppException("Model not found.")
27162712

@@ -3542,4 +3538,4 @@ def aggregate_annotations_as_df(
35423538
include_tags,
35433539
verbose,
35443540
folder_names,
3545-
)
3541+
)

src/superannotate/lib/app/serializers.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,11 @@ def deserialize(data):
6262
if isinstance(data, list):
6363
return [ImageEntity(**image) for image in data]
6464
return ImageEntity(**data)
65+
66+
67+
class SettingsSerializer(BaseSerializers):
68+
def serialize(self):
69+
data = super().serialize()
70+
if data["attribute"] == "ImageQuality":
71+
data["value"] = constance.ImageQuality.get_name(data["value"])
72+
return data

src/superannotate/lib/core/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from pathlib import Path
22

33
from superannotate.lib.core.enums import AnnotationStatus
4+
from superannotate.lib.core.enums import ImageQuality
45
from superannotate.lib.core.enums import ProjectType
56
from superannotate.lib.core.enums import SegmentationStatus
67
from superannotate.lib.core.enums import TrainingStatus
@@ -63,6 +64,7 @@
6364
TrainingStatus,
6465
SegmentationStatus,
6566
TrainingTask,
67+
ImageQuality,
6668
AnnotationStatus,
6769
CONFIG_FILE_LOCATION,
6870
BACKEND_URL,

src/superannotate/lib/core/serviceproviders.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,4 +287,4 @@ def run_segmentation(
287287
def run_prediction(
288288
self, team_id: int, project_id: int, ml_model_id: int, image_ids: list
289289
):
290-
raise NotImplementedError
290+
raise NotImplementedError

src/superannotate/lib/core/usecases.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1938,6 +1938,7 @@ def execute(self):
19381938
project = self._projects.get_one(
19391939
uuid=self._project.uuid, team_id=self._project.team_id
19401940
)
1941+
data["project"] = project
19411942
if self._include_complete_image_count:
19421943
projects = self._projects.get_all(
19431944
condition=(
@@ -1948,8 +1949,6 @@ def execute(self):
19481949
)
19491950
if projects:
19501951
data["project"] = projects[0]
1951-
else:
1952-
data["project"] = project
19531952

19541953
if self._include_annotation_classes:
19551954
self.annotation_classes_use_case.execute()
@@ -3537,7 +3536,8 @@ def __init__(self, model_id: int, models: BaseManageableRepository):
35373536
self._models = models
35383537

35393538
def execute(self):
3540-
self._models.delete(self._model_id)
3539+
self._response.data = self._models.delete(self._model_id)
3540+
return self._response
35413541

35423542

35433543
class StopModelTraining(BaseUseCase):
@@ -4157,7 +4157,9 @@ def s3_repository(self):
41574157
return self._s3_repo_instance
41584158

41594159
def _upload_image(self, image_path: str):
4160-
ProcessedImage = namedtuple("ProcessedImage", ["uploaded", "path", "entity"])
4160+
ProcessedImage = namedtuple(
4161+
"ProcessedImage", ["uploaded", "path", "entity", "name"]
4162+
)
41614163
if self._from_s3_bucket:
41624164
image_bytes = (
41634165
GetS3ImageUseCase(s3_bucket=self._from_s3_bucket, image_path=image_path)
@@ -4178,9 +4180,16 @@ def _upload_image(self, image_path: str):
41784180

41794181
if not upload_response.errors and upload_response.data:
41804182
entity = upload_response.data
4181-
return ProcessedImage(uploaded=True, path=entity.path, entity=entity)
4183+
return ProcessedImage(
4184+
uploaded=True,
4185+
path=entity.path,
4186+
entity=entity,
4187+
name=Path(image_path).name,
4188+
)
41824189
else:
4183-
return ProcessedImage(uploaded=False, path=image_path, entity=None)
4190+
return ProcessedImage(
4191+
uploaded=False, path=image_path, entity=None, name=Path(image_path).name
4192+
)
41844193

41854194
@property
41864195
def paths(self):
@@ -4278,7 +4287,7 @@ def execute(self):
42784287
if processed_image.uploaded and processed_image.entity:
42794288
uploaded_images.append(processed_image)
42804289
else:
4281-
failed_images.append(processed_image)
4290+
failed_images.append(processed_image.path)
42824291
yield
42834292

42844293
uploaded = []
@@ -4294,6 +4303,7 @@ def execute(self):
42944303

42954304
attachments, duplications = response.data
42964305
uploaded.extend(attachments)
4297-
# duplicates.extend(duplications)
4306+
uploaded = [image["name"] for image in uploaded]
4307+
failed_images = [image.name for image in failed_images]
42984308

4299-
self.response.data = uploaded, failed_images, duplications
4309+
self._response.data = uploaded, failed_images, duplications

src/superannotate/lib/infrastructure/controller.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,7 @@ def assign_images(
777777

778778
def un_assign_images(self, project_name, folder_name, image_names):
779779
project = self._get_project(project_name)
780-
folder = self._get_folder(folder_name)
780+
folder = self._get_folder(project, folder_name)
781781
use_case = usecases.UnAssignImagesUseCase(
782782
project_entity=project,
783783
service=self._backend_client,

src/superannotate/lib/infrastructure/services.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@
77
from urllib.parse import urljoin
88

99
import lib.core as constance
10-
import requests
10+
import requests.packages.urllib3
1111
from lib.core.exceptions import AppException
1212
from lib.core.serviceproviders import SuerannotateServiceProvider
1313
from requests.exceptions import HTTPError
1414

15+
requests.packages.urllib3.disable_warnings()
16+
1517

1618
class BaseBackendService(SuerannotateServiceProvider):
1719
AUTH_TYPE = "sdk"
@@ -71,7 +73,12 @@ def _request(
7173
method = getattr(requests, method)
7274
with self.safe_api():
7375
response = method(
74-
url, **kwargs, headers=headers_dict, params=params, timeout=60, verify=False
76+
url,
77+
**kwargs,
78+
headers=headers_dict,
79+
params=params,
80+
timeout=60,
81+
verify=False,
7582
)
7683
if response.status_code == 404 and retried < 3:
7784
return self._request(
@@ -159,6 +166,7 @@ class SuperannotateBackendService(BaseBackendService):
159166
URL_GET_TEMPLATES = "templates"
160167
URL_PROJECT_WORKFLOW_ATTRIBUTE = "project/{}/workflow_attribute"
161168
URL_MODELS = "ml_models"
169+
URL_MODEL = "ml_model"
162170
URL_STOP_MODEL_TRAINING = "ml_model/{}/stopTrainingJob"
163171
URL_GET_MODEL_METRICS = "ml_models/{}/getCurrentMetrics"
164172
URL_BULK_GET_FOLDERS = "foldersByTeam"
@@ -885,7 +893,7 @@ def update_model(self, team_id: int, model_id: int, data: dict):
885893
return res.json()
886894

887895
def delete_model(self, team_id: int, model_id: int):
888-
delete_model_url = urljoin(self.api_url, f"{self.URL_MODELS}/{model_id}")
896+
delete_model_url = urljoin(self.api_url, f"{self.URL_MODEL}/{model_id}")
889897
res = self._request(delete_model_url, "delete", params={"team_id": team_id})
890898
return res.ok
891899

src/superannotate/logging.conf

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
[loggers]
2+
keys=root,superannotate-python-sdk
3+
4+
[handlers]
5+
keys=consoleHandler
6+
7+
[formatters]
8+
keys=consoleFormatter
9+
10+
[logger_root]
11+
level=DEBUG
12+
handlers=consoleHandler
13+
14+
[logger_superannotate-python-sdk]
15+
level=DEBUG
16+
handlers=consoleHandler
17+
qualname=consoleFormatter
18+
propagate=0
19+
20+
[handler_consoleHandler]
21+
class=StreamHandler
22+
level=INFO
23+
formatter=consoleFormatter
24+
args=(sys.stdout,)
25+
26+
[formatter_consoleFormatter]
27+
format=SA-PYTHON-SDK - %(levelname)s - %(message)s
28+
datefmt=

0 commit comments

Comments
 (0)