Skip to content

Commit 667fc86

Browse files
authored
[AL-5537] Vb/vb/export v2 video al 5537 (#1055)
1 parent f54a675 commit 667fc86

File tree

10 files changed

+534
-62
lines changed

10 files changed

+534
-62
lines changed

tests/conftest.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
1+
import glob
12
from datetime import datetime
23
from random import randint
34
from string import ascii_letters
45

56
import pytest
67

8+
pytest_plugins = [
9+
fixture_file.replace("tests/", "").replace("/", ".").replace(".py", "")
10+
for fixture_file in glob.glob(
11+
"tests/integration/annotation_import/fixtures/[!__]*.py",)
12+
]
13+
714

815
@pytest.fixture
916
def rand_gen():

tests/integration/annotation_import/conftest.py

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -119,18 +119,6 @@ def text_data_row(rand_gen):
119119
}
120120

121121

122-
@pytest.fixture()
123-
def video_data_row(rand_gen):
124-
return {
125-
"row_data":
126-
"https://storage.googleapis.com/labelbox-datasets/video-sample-data/sample-video-1.mp4",
127-
"global_key":
128-
f"https://storage.googleapis.com/labelbox-datasets/video-sample-data/sample-video-1.mp4-{rand_gen(str)}",
129-
"media_type":
130-
"VIDEO",
131-
}
132-
133-
134122
@pytest.fixture
135123
def data_row_json_by_data_type(audio_data_row, conversation_data_row,
136124
dicom_data_row, geospatial_data_row,
@@ -149,6 +137,19 @@ def data_row_json_by_data_type(audio_data_row, conversation_data_row,
149137
}
150138

151139

140+
@pytest.fixture
141+
def v2_exports_by_data_type(expected_export_v2_image, expected_export_v2_audio,
142+
expected_export_v2_html, expected_export_v2_text,
143+
expected_export_v2_video):
144+
return {
145+
'image': expected_export_v2_image,
146+
'audio': expected_export_v2_audio,
147+
'html': expected_export_v2_html,
148+
'text': expected_export_v2_text,
149+
'video': expected_export_v2_video,
150+
}
151+
152+
152153
@pytest.fixture
153154
def annotations_by_data_type(polygon_inference, rectangle_inference,
154155
line_inference, entity_inference,
@@ -397,16 +398,6 @@ def dataset_pdf_entity(client, rand_gen, document_data_row):
397398
dataset.delete()
398399

399400

400-
@pytest.fixture
401-
def video_data(client, rand_gen, video_data_row):
402-
dataset = client.create_dataset(name=rand_gen(str))
403-
data_row_ids = []
404-
data_row = dataset.create_data_row(video_data_row)
405-
data_row_ids.append(data_row.uid)
406-
yield dataset, data_row_ids
407-
dataset.delete()
408-
409-
410401
@pytest.fixture
411402
def dataset_conversation_entity(client, rand_gen, conversation_entity_data_row):
412403
dataset = client.create_dataset(name=rand_gen(str))
@@ -751,3 +742,31 @@ def _convert_to_plain_object(obj):
751742
@pytest.fixture
752743
def annotation_import_test_helpers() -> Type[AnnotationImportTestHelpers]:
753744
return AnnotationImportTestHelpers()
745+
746+
747+
class ExportV2Helpers:
748+
749+
@classmethod
750+
def run_export_v2_task(cls, project, num_retries=5, params={}):
751+
task = None
752+
params = params if params else {
753+
"performance_details": False,
754+
"label_details": True
755+
}
756+
while (num_retries > 0):
757+
task = project.export_v2(params=params)
758+
task.wait_till_done()
759+
assert task.status == "COMPLETE"
760+
assert task.errors is None
761+
if len(task.result) == 0:
762+
num_retries -= 1
763+
time.sleep(5)
764+
else:
765+
break
766+
767+
return task.result
768+
769+
770+
@pytest.fixture
771+
def export_v2_test_helpers() -> Type[ExportV2Helpers]:
772+
return ExportV2Helpers()

tests/integration/annotation_import/fixtures/__init__.py

Whitespace-only changes.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import pytest
2+
from labelbox.data.annotation_types.classification.classification import Checklist, ClassificationAnnotation, ClassificationAnswer, Radio
3+
from labelbox.data.annotation_types.geometry.point import Point
4+
from labelbox.data.annotation_types.geometry.rectangle import Rectangle
5+
6+
from labelbox.data.annotation_types.video import VideoObjectAnnotation
7+
8+
9+
@pytest.fixture
10+
def bbox_video_annotation_objects():
11+
bbox_annotation = [
12+
VideoObjectAnnotation(
13+
name="bbox",
14+
keyframe=True,
15+
frame=13,
16+
segment_index=0,
17+
value=Rectangle(
18+
start=Point(x=146.0, y=98.0), # Top left
19+
end=Point(x=382.0, y=341.0), # Bottom right
20+
),
21+
classifications=[
22+
ClassificationAnnotation(
23+
name='nested',
24+
value=Radio(answer=ClassificationAnswer(
25+
name='radio_option_1',
26+
classifications=[
27+
ClassificationAnnotation(
28+
name='nested_checkbox',
29+
value=Checklist(answer=[
30+
ClassificationAnswer(
31+
name='nested_checkbox_option_1'),
32+
ClassificationAnswer(
33+
name='nested_checkbox_option_2')
34+
]))
35+
])),
36+
)
37+
]),
38+
VideoObjectAnnotation(
39+
name="bbox",
40+
keyframe=True,
41+
frame=19,
42+
segment_index=0,
43+
value=Rectangle(
44+
start=Point(x=146.0, y=98.0), # Top left
45+
end=Point(x=382.0, y=341.0), # Bottom right
46+
))
47+
]
48+
49+
return bbox_annotation
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
import pytest
2+
3+
4+
@pytest.fixture()
5+
def expected_export_v2_image():
6+
exported_annotations = {
7+
'objects': [{
8+
'name':
9+
'polygon',
10+
'annotation_kind':
11+
'ImagePolygon',
12+
'classifications': [],
13+
'polygon': [{
14+
'x': 147.692,
15+
'y': 118.154
16+
}, {
17+
'x': 142.769,
18+
'y': 104.923
19+
}, {
20+
'x': 57.846,
21+
'y': 118.769
22+
}, {
23+
'x': 28.308,
24+
'y': 169.846
25+
}, {
26+
'x': 147.692,
27+
'y': 118.154
28+
}]
29+
}, {
30+
'name': 'bbox',
31+
'annotation_kind': 'ImageBoundingBox',
32+
'classifications': [{
33+
'name': 'nested',
34+
'radio_answer': {
35+
'name': 'radio_option_1',
36+
'classifications': []
37+
}
38+
}],
39+
'bounding_box': {
40+
'top': 48.0,
41+
'left': 58.0,
42+
'height': 65.0,
43+
'width': 12.0
44+
}
45+
}, {
46+
'name': 'polyline',
47+
'annotation_kind': 'ImageLine',
48+
'classifications': [],
49+
'line': [{
50+
'x': 147.692,
51+
'y': 118.154
52+
}, {
53+
'x': 150.692,
54+
'y': 160.154
55+
}]
56+
}],
57+
'classifications': [{
58+
'name': 'checklist',
59+
'checklist_answers': [{
60+
'name': 'option1',
61+
'classifications': []
62+
}]
63+
}, {
64+
'name': 'text',
65+
'text_answer': {
66+
'content': 'free form text...'
67+
}
68+
}],
69+
'relationships': []
70+
}
71+
72+
return exported_annotations
73+
74+
75+
@pytest.fixture()
76+
def expected_export_v2_audio():
77+
expected_annotations = {
78+
'objects': [],
79+
'classifications': [{
80+
'name': 'checklist',
81+
'checklist_answers': [{
82+
'name': 'option1',
83+
'classifications': []
84+
}]
85+
}, {
86+
'name': 'text',
87+
'text_answer': {
88+
'content': 'free form text...'
89+
}
90+
}],
91+
'relationships': []
92+
}
93+
return expected_annotations
94+
95+
96+
@pytest.fixture()
97+
def expected_export_v2_html():
98+
expected_annotations = {
99+
'objects': [],
100+
'classifications': [{
101+
'name': 'text',
102+
'text_answer': {
103+
'content': 'free form text...'
104+
}
105+
}, {
106+
'name': 'checklist',
107+
'checklist_answers': [{
108+
'name': 'option1',
109+
'classifications': []
110+
}]
111+
}],
112+
'relationships': []
113+
}
114+
return expected_annotations
115+
116+
117+
@pytest.fixture()
118+
def expected_export_v2_text():
119+
expected_annotations = {
120+
'objects': [{
121+
'name': 'named-entity',
122+
'annotation_kind': 'TextEntity',
123+
'classifications': [],
124+
'location': {
125+
'start': 67,
126+
'end': 128
127+
}
128+
}],
129+
'classifications': [{
130+
'name': 'checklist',
131+
'checklist_answers': [{
132+
'name': 'option1',
133+
'classifications': []
134+
}]
135+
}, {
136+
'name': 'text',
137+
'text_answer': {
138+
'content': 'free form text...'
139+
}
140+
}],
141+
'relationships': []
142+
}
143+
return expected_annotations
144+
145+
146+
@pytest.fixture()
147+
def expected_export_v2_video():
148+
expected_annotations = {
149+
'frames': {},
150+
'segments': {},
151+
'key_frame_feature_map': {},
152+
'classifications': [{
153+
'name': 'checklist',
154+
'checklist_answers': [{
155+
'name': 'option1',
156+
'classifications': []
157+
}]
158+
}]
159+
}
160+
return expected_annotations

tests/integration/annotation_import/test_bulk_import_request.py

Lines changed: 4 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -347,45 +347,9 @@ def test_pdf_document_entity(client, configured_project_without_data_rows,
347347

348348
def test_nested_video_object_annotations(client,
349349
configured_project_without_data_rows,
350-
video_data, rand_gen):
351-
bbox_annotation = [
352-
VideoObjectAnnotation(
353-
name="bbox",
354-
keyframe=True,
355-
frame=13,
356-
segment_index=0,
357-
value=Rectangle(
358-
start=Point(x=146.0, y=98.0), # Top left
359-
end=Point(x=382.0, y=341.0), # Bottom right
360-
),
361-
classifications=[
362-
ClassificationAnnotation(
363-
name='nested',
364-
value=Radio(answer=ClassificationAnswer(
365-
name='radio_option_1',
366-
classifications=[
367-
ClassificationAnnotation(
368-
name='nested_checkbox',
369-
value=Checklist(answer=[
370-
ClassificationAnswer(
371-
name='nested_checkbox_option_1'),
372-
ClassificationAnswer(
373-
name='nested_checkbox_option_2')
374-
]))
375-
])),
376-
)
377-
]),
378-
VideoObjectAnnotation(
379-
name="bbox",
380-
keyframe=True,
381-
frame=19,
382-
segment_index=0,
383-
value=Rectangle(
384-
start=Point(x=146.0, y=98.0), # Top left
385-
end=Point(x=382.0, y=341.0), # Bottom right
386-
))
387-
]
388-
350+
video_data,
351+
bbox_video_annotation_objects,
352+
rand_gen):
389353
labels = []
390354
_, data_row_uids = video_data
391355
configured_project_without_data_rows.create_batch(
@@ -397,7 +361,7 @@ def test_nested_video_object_annotations(client,
397361
for data_row_uid in data_row_uids:
398362
labels.append(
399363
Label(data=VideoData(uid=data_row_uid),
400-
annotations=bbox_annotation))
364+
annotations=bbox_video_annotation_objects))
401365
import_annotations = MALPredictionImport.create_from_objects(
402366
client=client,
403367
project_id=configured_project_without_data_rows.uid,

0 commit comments

Comments
 (0)