Skip to content

Commit e1ebe30

Browse files
committed
test fix
1 parent 7bed5a5 commit e1ebe30

File tree

8 files changed

+149
-112
lines changed

8 files changed

+149
-112
lines changed

pytest.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ minversion = 3.7
33
log_cli=true
44
python_files = test_*.py
55
;pytest_plugins = ['pytest_profiling']
6-
;addopts = -n auto --dist=loadscope
6+
addopts = -n auto --dist=loadscope
77

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,13 +161,22 @@ class Config:
161161
extra = Extra.ignore
162162

163163

164+
class UserEntity(BaseModel):
165+
id: Optional[str]
166+
first_name: Optional[str]
167+
last_name: Optional[str]
168+
email: Optional[str]
169+
picture: Optional[str]
170+
user_role: Optional[int]
171+
172+
164173
class TeamEntity(BaseModel):
165174
id: Optional[int]
166175
name: Optional[str]
167176
description: Optional[str]
168177
type: Optional[str]
169178
user_role: Optional[str]
170179
is_default: Optional[bool]
171-
users: Optional[List[Any]]
180+
users: Optional[List[UserEntity]]
172181
pending_invitations: Optional[List[Any]]
173182
creator_id: Optional[str]

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

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,7 +1037,6 @@ def validate_project_type(self):
10371037

10381038
def execute(self):
10391039
if self.is_valid():
1040-
self.reporter.disable_info()
10411040
response = GetAnnotations(
10421041
config=self._config,
10431042
reporter=Reporter(log_info=False),
@@ -1046,10 +1045,9 @@ def execute(self):
10461045
item_names=[self._video_name],
10471046
service_provider=self._service_provider,
10481047
).execute()
1049-
self.reporter.enable_info()
10501048
if response.data:
10511049
generator = VideoFrameGenerator(response.data[0], fps=self._fps)
1052-
self.reporter.log_info(
1050+
logger.info(
10531051
f"Getting annotations for {generator.frames_count} frames from {self._video_name}."
10541052
)
10551053
if response.errors:
@@ -1412,21 +1410,10 @@ def validate_item_names(self):
14121410
self._item_names = [
14131411
i for i in self._item_names if not (i in seen or seen.add(i))
14141412
]
1415-
elif self._item_names is None:
1416-
self._item_names_provided = False
1417-
condition = Condition("project_id", self._project.id, EQ) & Condition(
1418-
"folder_id", self._folder.id, EQ
1419-
)
1420-
1421-
self._item_names = [
1422-
item.name for item in self._service_provider.items.list(condition).data
1423-
]
1424-
else:
1425-
self._item_names = []
14261413

14271414
def _prettify_annotations(self, annotations: List[dict]):
14281415
re_struct = {}
1429-
if self._item_names_provided:
1416+
if self._item_names:
14301417
for annotation in annotations:
14311418
re_struct[annotation["metadata"]["name"]] = annotation
14321419
try:
@@ -1528,19 +1515,23 @@ def execute(self):
15281515
self._project, self._folder, self._item_names
15291516
)
15301517
)
1518+
len_items, len_provided_items = len(items), len(self._item_names)
1519+
if len_items != len_provided_items:
1520+
self.reporter.log_warning(
1521+
f"Could not find annotations for {len_provided_items - len_items}/{len_provided_items} items."
1522+
)
15311523
else:
15321524
condition = Condition("project_id", self._project.id, EQ) & Condition(
15331525
"folder_id", self._folder.id, EQ
15341526
)
15351527
items = get_or_raise(self._service_provider.items.list(condition))
15361528
id_item_map = {i.id: i for i in items}
1537-
15381529
if not items:
15391530
logger.info("No annotations to download.")
15401531
self._response.data = []
15411532
return self._response
15421533
items_count = len(items)
1543-
logger.info(
1534+
self.reporter.log_info(
15441535
f"Getting {items_count} annotations from "
15451536
f"{self._project.name}{f'/{self._folder.name}' if self._folder.name != 'root' else ''}."
15461537
)
@@ -1563,12 +1554,8 @@ def execute(self):
15631554
logger.error(e)
15641555
self._response.errors = AppException("Can't get annotations.")
15651556
return self._response
1566-
received_items_count = len(annotations)
15671557
self.reporter.finish_progress()
1568-
if items_count > received_items_count:
1569-
self.reporter.log_warning(
1570-
f"Could not find annotations for {items_count - received_items_count}/{items_count} items."
1571-
)
1558+
15721559
self._response.data = self._prettify_annotations(annotations)
15731560
return self._response
15741561

tests/integration/annotations/test_get_annotations.py

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,8 @@ def folder_path(self):
2424

2525
# @pytest.mark.flaky(reruns=3)
2626
def test_get_annotations(self):
27-
sa.upload_images_from_folder_to_project(
28-
self.PROJECT_NAME, self.folder_path, annotation_status="InProgress"
29-
)
27+
self._attach_items(count=4)
28+
3029
sa.create_annotation_classes_from_classes_json(
3130
self.PROJECT_NAME, f"{self.folder_path}/classes/classes.json"
3231
)
@@ -126,24 +125,23 @@ def test_get_annotations10000(self):
126125
a = sa.get_annotations(self.PROJECT_NAME)
127126
assert len(a) == count
128127

129-
def test_get_annotation(self): # to_delete
130-
count = 2
131-
sa.attach_items(
132-
self.PROJECT_NAME,
133-
[
134-
{"name": f"example_image_{i}.jpg", "url": f"url_{i}"}
135-
for i in range(count)
136-
], # noqa
137-
)
138-
assert len(sa.search_items(self.PROJECT_NAME)) == count
139-
a = sa.get_annotations(self.PROJECT_NAME)
140-
assert len(a) == count
141-
142-
def test_get_annotations_duplicated_names(self):
128+
def test_get_annotations_logs(self):
143129
self._attach_items(count=4)
130+
items_names = [self.IMAGE_NAME] * 4
131+
items_names.append("Non-existent item")
144132
with self.assertLogs("sa", level="INFO") as cm:
145-
sa.get_annotations(self.PROJECT_NAME, [self.IMAGE_NAME] * 4)
146-
assert "INFO:sa:Dropping duplicates. Found 1/4 unique items." in cm.output
133+
assert len(sa.get_annotations(self.PROJECT_NAME, items_names)) == 4
134+
assert (
135+
"INFO:sa:Dropping duplicates. Found 2/5 unique items." == cm.output[0]
136+
)
137+
assert (
138+
"WARNING:sa:Could not find annotations for 1/2 items." == cm.output[1]
139+
)
140+
assert (
141+
f"INFO:sa:Getting 1 annotations from {self.PROJECT_NAME}."
142+
== cm.output[2]
143+
)
144+
assert len(cm.output) == 3
147145

148146

149147
class TestGetAnnotationsVideo(BaseTestCase):
@@ -172,7 +170,7 @@ def folder_path(self):
172170
def annotations_path(self):
173171
return os.path.join(self.folder_path, self.ANNOTATIONS_PATH)
174172

175-
def test_video_annotation_upload_root(self):
173+
def test_video_get_annotations_root(self):
176174
sa.create_annotation_classes_from_classes_json(
177175
self.PROJECT_NAME, self.classes_path
178176
)
@@ -187,7 +185,7 @@ def test_video_annotation_upload_root(self):
187185
annotations = sa.get_annotations(self.PROJECT_NAME)
188186
self.assertEqual(len(annotations), 2)
189187

190-
def test_video_annotation_upload_folder(self):
188+
def test_video_get_annotations_from_folder(self):
191189
sa.create_annotation_classes_from_classes_json(
192190
self.PROJECT_NAME, self.classes_path
193191
)
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import json
2+
import os
3+
import tempfile
4+
from pathlib import Path
5+
6+
from src.superannotate import SAClient
7+
from src.superannotate.lib.app.helpers import get_annotation_paths
8+
from tests import DATA_SET_PATH
9+
from tests.integration.base import BaseTestCase
10+
11+
sa = SAClient()
12+
13+
14+
class TestAnnotationUploadVector(BaseTestCase):
15+
PROJECT_NAME = "Test-upload_annotations"
16+
PROJECT_DESCRIPTION = "Desc"
17+
PROJECT_TYPE = "Vector"
18+
TEST_FOLDER_PATH = "data_set/sample_vector_annotations_with_tag_classes"
19+
TEST_4_FOLDER_PATH = "data_set/sample_project_vector"
20+
TEST_BIG_FOLDER_PATH = "sample_big_json_vector"
21+
22+
IMAGE_NAME = "example_image_1.jpg"
23+
24+
@property
25+
def data_set(self):
26+
return Path(__file__).parent.parent.parent
27+
28+
@property
29+
def big_annotations_folder_path(self):
30+
return os.path.join(DATA_SET_PATH, self.TEST_BIG_FOLDER_PATH)
31+
32+
@staticmethod
33+
def _get_annotations_from_folder(path):
34+
paths = get_annotation_paths(path)
35+
annotations = []
36+
for i in paths:
37+
annotations.append(json.load(open(i)))
38+
return annotations
39+
40+
def test_large_annotations_upload_get_download(self):
41+
items_to_attach = [
42+
{"name": f"aearth_mov_00{i}.jpg", "url": f"url_{i}"} for i in range(1, 6)
43+
]
44+
sa.attach_items(
45+
self.PROJECT_NAME,
46+
items_to_attach,
47+
)
48+
sa.create_annotation_classes_from_classes_json(
49+
self.PROJECT_NAME,
50+
f"{self.big_annotations_folder_path}/classes/classes.json",
51+
)
52+
annotations = self._get_annotations_from_folder(
53+
self.big_annotations_folder_path
54+
)
55+
with self.assertLogs("sa", level="INFO") as cm:
56+
uploaded, _, _ = sa.upload_annotations(
57+
self.PROJECT_NAME, annotations
58+
).values()
59+
assert (
60+
"INFO:sa:Uploading 5/5 annotations to the project Test-upload_annotations."
61+
== cm.output[0]
62+
)
63+
assert len(uploaded) == 5
64+
65+
with self.assertLogs("sa", level="INFO") as cm:
66+
annotations = sa.get_annotations(self.PROJECT_NAME)
67+
assert (
68+
"INFO:sa:Getting 5 annotations from Test-upload_annotations."
69+
== cm.output[0]
70+
)
71+
assert len(annotations) == 5
72+
assert [
73+
len(annotation["instances"]) > 1 for annotation in annotations
74+
].count(True) == 4
75+
76+
with tempfile.TemporaryDirectory() as tmpdir:
77+
with self.assertLogs("sa", level="INFO") as cm:
78+
sa.download_annotations(self.PROJECT_NAME, tmpdir)
79+
assert cm.output[0].startswith(
80+
"INFO:sa:Downloading the annotations of the requested items to /var/"
81+
)
82+
assert cm.output[0].endswith("This might take a while…")
83+
84+
for item_name in items_to_attach:
85+
annotation = self._get_annotations_from_folder(
86+
f"{tmpdir}/{os.listdir(tmpdir)[0]}/{items_to_attach[0]['name']}___objects.json"
87+
)
88+
for i in annotations:
89+
if i["metadata"]["name"] == item_name:
90+
assert i == annotation

tests/integration/annotations/test_upload_annotations.py

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ class TestAnnotationUploadVector(BaseTestCase):
1616
PROJECT_TYPE = "Vector"
1717
TEST_FOLDER_PATH = "data_set/sample_vector_annotations_with_tag_classes"
1818
TEST_4_FOLDER_PATH = "data_set/sample_project_vector"
19-
TEST_BIG_FOLDER_PATH = "sample_big_json_vector"
2019
TEST_LARGE_FOLDER_PATH = "sample_large_json_vector"
2120
IMAGE_NAME = "example_image_1.jpg"
2221

@@ -28,10 +27,6 @@ def data_set(self):
2827
def folder_path(self):
2928
return os.path.join(Path(__file__).parent.parent.parent, self.TEST_FOLDER_PATH)
3029

31-
@property
32-
def big_annotations_folder_path(self):
33-
return os.path.join(DATA_SET_PATH, self.TEST_BIG_FOLDER_PATH)
34-
3530
@property
3631
def large_annotations_folder_path(self):
3732
return os.path.join(DATA_SET_PATH, self.TEST_LARGE_FOLDER_PATH)
@@ -115,25 +110,3 @@ def test_upload_large_annotations(self):
115110
assert [len(annotation["instances"]) > 1 for annotation in annotations].count(
116111
True
117112
) == 5
118-
119-
def test_upload_big_annotations(self):
120-
sa.attach_items(
121-
self.PROJECT_NAME,
122-
[
123-
{"name": f"aearth_mov_00{i}.jpg", "url": f"url_{i}"}
124-
for i in range(1, 6)
125-
], # noqa
126-
)
127-
sa.create_annotation_classes_from_classes_json(
128-
self.PROJECT_NAME,
129-
f"{self.big_annotations_folder_path}/classes/classes.json",
130-
)
131-
annotations = self._get_annotations_from_folder(
132-
self.big_annotations_folder_path
133-
)
134-
uploaded, _, _ = sa.upload_annotations(self.PROJECT_NAME, annotations).values()
135-
assert len(uploaded) == 5
136-
annotations = sa.get_annotations(self.PROJECT_NAME)
137-
assert [len(annotation["instances"]) > 1 for annotation in annotations].count(
138-
True
139-
) == 4

tests/integration/annotations/test_upload_annotations_from_folder_to_project.py

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ class TestAnnotationUploadVector(BaseTestCase):
1414
PROJECT_TYPE = "Vector"
1515
TEST_FOLDER_PATH = "data_set/sample_vector_annotations_with_tag_classes"
1616
TEST_4_FOLDER_PATH = "data_set/sample_project_vector"
17-
TEST_BIG_FOLDER_PATH = "sample_big_json_vector"
1817
TEST_LARGE_FOLDER_PATH = "sample_large_json_vector"
1918
IMAGE_NAME = "example_image_1.jpg"
2019

@@ -26,10 +25,6 @@ def data_set(self):
2625
def folder_path(self):
2726
return os.path.join(Path(__file__).parent.parent.parent, self.TEST_FOLDER_PATH)
2827

29-
@property
30-
def big_annotations_folder_path(self):
31-
return os.path.join(DATA_SET_PATH, self.TEST_BIG_FOLDER_PATH)
32-
3328
@property
3429
def large_annotations_folder_path(self):
3530
return os.path.join(DATA_SET_PATH, self.TEST_LARGE_FOLDER_PATH)
@@ -100,27 +95,6 @@ def test_upload_large_annotations(self):
10095
True
10196
) == 5
10297

103-
def test_upload_big_annotations(self):
104-
sa.attach_items(
105-
self.PROJECT_NAME,
106-
[
107-
{"name": f"aearth_mov_00{i}.jpg", "url": f"url_{i}"}
108-
for i in range(1, 6)
109-
], # noqa
110-
)
111-
sa.create_annotation_classes_from_classes_json(
112-
self.PROJECT_NAME,
113-
f"{self.big_annotations_folder_path}/classes/classes.json",
114-
)
115-
uploaded, _, _ = sa.upload_annotations_from_folder_to_project(
116-
self.PROJECT_NAME, self.big_annotations_folder_path
117-
)
118-
assert len(uploaded) == 5
119-
annotations = sa.get_annotations(self.PROJECT_NAME)
120-
assert [len(annotation["instances"]) > 1 for annotation in annotations].count(
121-
True
122-
) == 4
123-
12498

12599
class TestExportUploadVector(BaseTestCase):
126100
PROJECT_NAME = "Test-TestExporeExportUploadVector"

0 commit comments

Comments
 (0)