Skip to content

Commit aa5e4b7

Browse files
committed
updated search folders
1 parent 05ab141 commit aa5e4b7

File tree

10 files changed

+202
-43
lines changed

10 files changed

+202
-43
lines changed

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,8 @@ def create_folder(self, project: NotEmptyStr, folder_name: NotEmptyStr):
328328
folder = res.data
329329
logger.info(f"Folder {folder.name} created in project {project.name}")
330330
return FolderSerializer(folder).serialize(
331-
exclude={"completedCount", "is_root"}
332-
)
331+
exclude={"completedCount", "is_root"}
332+
)
333333
if res.errors:
334334
raise AppException(res.errors)
335335

@@ -432,7 +432,7 @@ def search_folders(
432432
condition &= Condition("includeUsers", return_metadata, EQ)
433433
if status:
434434
condition &= Condition(
435-
"status", constants.ProjectStatus.get_value(status), EQ
435+
"status", constants.FolderStatus.get_value(status), EQ
436436
)
437437
response = self.controller.folders.list(project, condition)
438438
if response.errors:
@@ -539,6 +539,7 @@ def search_annotation_classes(
539539
540540
:param project: project name
541541
:type project: str
542+
542543
:param name_contains: search string. Returns those classes,
543544
where the given string is found anywhere within its name. If None, all annotation classes will be returned.
544545
:type name_contains: str

src/superannotate/lib/core/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from superannotate.lib.core.config import Config
44
from superannotate.lib.core.enums import AnnotationStatus
5+
from superannotate.lib.core.enums import FolderStatus
56
from superannotate.lib.core.enums import ImageQuality
67
from superannotate.lib.core.enums import ProjectStatus
78
from superannotate.lib.core.enums import ProjectType
@@ -105,6 +106,7 @@
105106
INVALID_JSON_MESSAGE = "Invalid json"
106107

107108
__alL__ = (
109+
FolderStatus,
108110
ProjectStatus,
109111
ProjectType,
110112
UserRole,

src/superannotate/lib/core/conditions.py

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from collections import namedtuple
22
from typing import Any
33
from typing import List
4-
from typing import NamedTuple
54

65
CONDITION_OR = "|"
76
CONDITION_AND = "&"
@@ -11,15 +10,17 @@
1110
CONDITION_LT = "<"
1211
CONDITION_LE = "<="
1312

14-
QueryCondition = namedtuple("QueryCondition", ("condition", "query", "pair"))
13+
QueryCondition = namedtuple("QueryCondition", ("condition", "pair", "item"))
1514

1615

1716
class Condition:
1817
def __init__(self, key: str, value: Any, condition_type: str):
1918
self._key = key
2019
self._value = value
2120
self._type = condition_type
22-
self._condition_set = [] # type: List[NamedTuple]
21+
self._condition_set: List[QueryCondition] = [
22+
QueryCondition(CONDITION_AND, {key: value}, self)
23+
]
2324

2425
@staticmethod
2526
def get_empty_condition():
@@ -32,13 +33,10 @@ def __or__(self, other):
3233
if not isinstance(other, Condition):
3334
raise Exception("Support the only Condition types")
3435

35-
self._condition_set.append(
36-
QueryCondition(
37-
CONDITION_OR,
38-
other.build_query(),
39-
{other._key: other._value} if type(other) == Condition else {},
36+
for _condition in other._condition_set:
37+
self._condition_set.append(
38+
QueryCondition(CONDITION_OR, _condition.pair, _condition.item)
4039
)
41-
)
4240
return self
4341

4442
def __and__(self, other):
@@ -52,19 +50,23 @@ def __and__(self, other):
5250
elif not isinstance(other, (Condition, EmptyCondition)):
5351
raise Exception("Support the only Condition types")
5452

55-
self._condition_set.append(
56-
QueryCondition(
57-
CONDITION_AND,
58-
other.build_query(),
59-
{other._key: other._value} if type(other) == Condition else {},
53+
for _condition in other._condition_set:
54+
self._condition_set.append(
55+
QueryCondition(CONDITION_AND, _condition.pair, _condition.item)
6056
)
61-
)
6257
return self
6358

59+
def _build(self):
60+
return f"{self._key}{self._type}{self._value}"
61+
6462
def build_query(self):
65-
return str(self) + "".join(
66-
[f"{condition[0]}{condition[1]}" for condition in self._condition_set]
67-
)
63+
items = []
64+
for condition in self._condition_set:
65+
if not items:
66+
items.append(condition.item._build())
67+
else:
68+
items.extend([condition.condition, condition.item._build()])
69+
return "".join(items)
6870

6971
def get_as_params_dict(self) -> dict:
7072
params = None if isinstance(self, EmptyCondition) else {self._key: self._value}
@@ -75,7 +77,7 @@ def get_as_params_dict(self) -> dict:
7577

7678
class EmptyCondition(Condition):
7779
def __init__(self, *args, **kwargs): # noqa
78-
...
80+
self._condition_set = []
7981

8082
def __or__(self, other):
8183
return other

src/superannotate/lib/core/enums.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ def get_name(cls, value):
4141
def get_value(cls, name):
4242
for enum in list(cls):
4343
if enum.__doc__.lower() == name.lower():
44+
if isinstance(enum.value, int):
45+
if enum.value < 0:
46+
return ""
4447
return enum.value
4548

4649
@classmethod
@@ -101,15 +104,15 @@ class ImageQuality(BaseTitledEnum):
101104

102105

103106
class ProjectStatus(BaseTitledEnum):
104-
Undefined = "Undefined", 0
107+
Undefined = "Undefined", -1
105108
NotStarted = "NotStarted", 1
106109
InProgress = "InProgress", 2
107110
Completed = "Completed", 3
108111
OnHold = "OnHold", 4
109112

110113

111114
class FolderStatus(BaseTitledEnum):
112-
Undefined = "Undefined", 0
115+
Undefined = "Undefined", -1
113116
NotStarted = "NotStarted", 1
114117
InProgress = "InProgress", 2
115118
Completed = "Completed", 3

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
class FolderService(BaseFolderService):
1010
URL_BASE = "folder"
11-
URL_LIST = "folders"
11+
URL_LIST = "/folders"
1212
URL_UPDATE = "folder/{}"
1313
URL_GET_BY_NAME = "folder/getFolderByName"
1414
URL_DELETE_MULTIPLE = "image/delete/images"
@@ -34,6 +34,12 @@ def list(self, condition: Condition = None):
3434
query_params=condition.get_as_params_dict() if condition else None,
3535
)
3636

37+
def update(self, project: entities.ProjectEntity, folder: entities.FolderEntity):
38+
params = {"project_id": project.id}
39+
return self.client.request(
40+
self.URL_UPDATE.format(folder.id), "put", data=folder.dict(), params=params
41+
)
42+
3743
def delete_multiple(
3844
self, project: entities.ProjectEntity, folders: List[entities.FolderEntity]
3945
):
@@ -69,9 +75,3 @@ def assign(
6975
params={"project_id": project.id},
7076
data={"folder_name": folder.name, "assign_user_ids": users},
7177
)
72-
73-
def update(self, project: entities.ProjectEntity, folder: entities.FolderEntity):
74-
params = {"project_id": project.id}
75-
return self.client.request(
76-
self.URL_UPDATE.format(folder.id), "put", data=folder.dict(), params=params
77-
)
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
{
2+
"metadata": {
3+
"width": "1920",
4+
"height": 10.80,
5+
"status": "InProgress",
6+
"url": "https://drive.google.com/uc?export=download&id=1wTd4NeE3Jt39k9DL_5GIqrO6R_hucsps",
7+
"duration": 30571000,
8+
"projectId": 165611,
9+
"error": false,
10+
"annotatorEmail": "A34@3.4@htfd.cm",
11+
"qaEmail": "43@fd.dcs",
12+
"lastAction": {
13+
"timestamp": 1635510590705,
14+
"email": "varduhi@superannotate.com"
15+
}
16+
},
17+
"instances": [
18+
{
19+
"meta": {
20+
"type": "bbox",
21+
"classId": 879460,
22+
"pointLabels": {
23+
"ds": "s"
24+
},
25+
"createdBy": {
26+
"email": "varduhi@superannotate.com",
27+
"role": "Admin"
28+
},
29+
"createdAt": "2021-10-29T12.29.45.668Z",
30+
"updatedBy": {
31+
"email": "varduhi@superannotate.com",
32+
"role": "qwert"
33+
},
34+
"updatedAt": "2021-10-29T12:29:50.696Z",
35+
"start": 0,
36+
"end": 30571000
37+
},
38+
"parameters": [
39+
{
40+
"start": 0,
41+
"end": 30571000,
42+
"timestamps": [
43+
{
44+
"points": {
45+
"x": 595.85,
46+
"y1": 223.82,
47+
"x2": 1278.92,
48+
"y2": 874.41
49+
},
50+
"timestamp": 0,
51+
"attributes": [
52+
{
53+
}
54+
]
55+
},
56+
{
57+
"points": {
58+
"x1": 595.85,
59+
"y1": 223.82,
60+
"x2": 1278.92,
61+
"y2": 874.41
62+
},
63+
"timestamp": 30571000,
64+
"attributes": [
65+
{
66+
},
67+
{
68+
"groupName": "numeric group"
69+
}
70+
]
71+
}
72+
]
73+
}
74+
]
75+
},
76+
{
77+
"meta": {
78+
"type": "bbox",
79+
"start": 0,
80+
"end": 30571000
81+
},
82+
"parameters": [
83+
{
84+
"start": 0,
85+
"end": 3057.1000,
86+
"timestamps": [
87+
{
88+
"points": {
89+
"x": 595.85,
90+
"y1": 223.82,
91+
"x2": 1278.92,
92+
"y2": 874.41
93+
},
94+
"timestamp": 0,
95+
"attributes": [
96+
{
97+
},
98+
{
99+
"groupName": "numeric group"
100+
}
101+
]
102+
}
103+
]
104+
}
105+
]
106+
}
107+
],
108+
"tags": [
109+
6,
110+
null
111+
]
112+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import os
2+
import json
3+
from unittest import TestCase
4+
from unittest.mock import patch
5+
6+
from src.superannotate import SAClient
7+
from tests import DATA_SET_PATH
8+
9+
sa = SAClient()
10+
11+
12+
class TestVectorValidators(TestCase):
13+
PROJECT_NAME = "video annotation upload with ree text and numeric"
14+
PROJECT_DESCRIPTION = "desc"
15+
PROJECT_TYPE = "Video"
16+
ANNOTATIONS_PATH = "invalid_annotations/video.mp4.json"
17+
18+
# @patch('builtins.print')
19+
def test_free_text_numeric_invalid(self):
20+
json_data = json.load(open(os.path.join(DATA_SET_PATH, self.ANNOTATIONS_PATH)))
21+
is_valid = sa.validate_annotations("video", json_data)
22+
assert not is_valid
23+

tests/integration/annotations/video/test_get_annotations_per_frame.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,20 @@
66

77
from src.superannotate import SAClient
88
from tests.integration.base import BaseTestCase
9+
from tests import DATA_SET_PATH
910

1011
sa = SAClient()
1112

1213

1314
class TestGetAnnotations(BaseTestCase):
1415
PROJECT_NAME = "test attach video urls"
15-
PATH_TO_URLS = "data_set/attach_video_for_annotation.csv"
16-
PATH_TO_URLS_WITHOUT_NAMES = "data_set/attach_urls_with_no_name.csv"
17-
PATH_TO_50K_URLS = "data_set/501_urls.csv"
16+
PATH_TO_URLS = "attach_video_for_annotation.csv"
17+
PATH_TO_URLS_WITHOUT_NAMES = "attach_urls_with_no_name.csv"
18+
PATH_TO_50K_URLS = "501_urls.csv"
1819
PROJECT_DESCRIPTION = "desc"
19-
ANNOTATIONS_PATH = "data_set/video_convertor_annotations"
20+
ANNOTATIONS_PATH = "video_convertor_annotations"
2021
VIDEO_NAME = "video.mp4"
21-
CLASSES_PATH = "data_set/video_annotation/classes/classes.json"
22+
CLASSES_PATH = "video_annotation/classes/classes.json"
2223
PROJECT_TYPE = "Video"
2324

2425
@property
@@ -27,15 +28,12 @@ def csv_path(self):
2728

2829
@property
2930
def classes_path(self):
30-
return os.path.join(self.folder_path, self.CLASSES_PATH)
31+
return os.path.join(DATA_SET_PATH, self.CLASSES_PATH)
3132

32-
@property
33-
def folder_path(self):
34-
return Path(__file__).parent.parent.parent
3533

3634
@property
3735
def annotations_path(self):
38-
return os.path.join(self.folder_path, self.ANNOTATIONS_PATH)
36+
return os.path.join(DATA_SET_PATH, self.ANNOTATIONS_PATH)
3937

4038
def test_video_annotation_upload(self):
4139
sa.create_annotation_classes_from_classes_json(self.PROJECT_NAME, self.classes_path)

tests/integration/folders/test_folders.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,12 @@ def test_create_long_name(self):
267267

268268
def test_search_folder(self):
269269
sa.create_folder(self.PROJECT_NAME, self.TEST_FOLDER_NAME_1)
270-
sa.create_folder(self.PROJECT_NAME, self.TEST_FOLDER_NAME_2)
270+
time.sleep(1)
271271
folders = sa.search_folders(self.PROJECT_NAME, self.TEST_FOLDER_NAME_1, return_metadata=True)
272272
assert len(folders) == 1
273273
assert folders[0]['name'] == self.TEST_FOLDER_NAME_1
274-
assert folders[0]['status'] == 'NotStarted'
274+
assert folders[0]['status'] == 'NotStarted'
275+
folders = sa.search_folders(self.PROJECT_NAME, status='Completed', return_metadata=True)
276+
assert len(folders) == 0
277+
folders = sa.search_folders(self.PROJECT_NAME, status='Undefined', return_metadata=True)
278+
assert len(folders) == 0

0 commit comments

Comments
 (0)