Skip to content

Commit 718e78e

Browse files
authored
Merge pull request #412 from Labelbox/al-1280
adds to raise exception to main caller thread from prefetch generator
2 parents 8ff06e6 + 47bf08d commit 718e78e

File tree

8 files changed

+243
-47
lines changed

8 files changed

+243
-47
lines changed

labelbox/data/generator.py

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,25 +33,30 @@ class PrefetchGenerator:
3333
Useful for modifying the generator results based on data from a network
3434
"""
3535

36-
def __init__(self, data: Iterable[Any], prefetch_limit=20, num_executors=4):
36+
def __init__(self, data: Iterable[Any], prefetch_limit=20, num_executors=1):
3737
if isinstance(data, (list, tuple)):
3838
self._data = (r for r in data)
3939
else:
4040
self._data = data
4141

4242
self.queue = Queue(prefetch_limit)
43-
self._data = ThreadSafeGen(self._data)
4443
self.completed_threads = 0
4544
# Can only iterate over once it the queue.get hangs forever.
45+
self.multithread = num_executors > 1
4646
self.done = False
47-
self.num_executors = num_executors
48-
self.threads = [
49-
threading.Thread(target=self.fill_queue)
50-
for _ in range(num_executors)
51-
]
52-
for thread in self.threads:
53-
thread.daemon = True
54-
thread.start()
47+
48+
if self.multithread:
49+
self._data = ThreadSafeGen(self._data)
50+
self.num_executors = num_executors
51+
self.threads = [
52+
threading.Thread(target=self.fill_queue)
53+
for _ in range(num_executors)
54+
]
55+
for thread in self.threads:
56+
thread.daemon = True
57+
thread.start()
58+
else:
59+
self._data = iter(self._data)
5560

5661
def _process(self, value) -> Any:
5762
raise NotImplementedError("Abstract method needs to be implemented")
@@ -64,8 +69,8 @@ def fill_queue(self):
6469
raise ValueError("Unexpected None")
6570
self.queue.put(value)
6671
except Exception as e:
67-
logger.warning("Unexpected exception while filling the queue. %r",
68-
e)
72+
self.queue.put(
73+
ValueError(f"Unexpected exception while filling queue: {e}"))
6974
finally:
7075
self.queue.put(None)
7176

@@ -75,13 +80,20 @@ def __iter__(self):
7580
def __next__(self) -> Any:
7681
if self.done:
7782
raise StopIteration
78-
value = self.queue.get()
79-
while value is None:
80-
self.completed_threads += 1
81-
if self.completed_threads == self.num_executors:
82-
self.done = True
83-
for thread in self.threads:
84-
thread.join()
85-
raise StopIteration
83+
84+
if self.multithread:
8685
value = self.queue.get()
86+
87+
while value is None:
88+
self.completed_threads += 1
89+
if self.completed_threads == self.num_executors:
90+
self.done = True
91+
for thread in self.threads:
92+
thread.join()
93+
raise StopIteration
94+
value = self.queue.get()
95+
if isinstance(value, Exception):
96+
raise value
97+
else:
98+
value = self._process(next(self._data))
8799
return value

labelbox/data/serialization/coco/panoptic_dataset.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,12 +175,12 @@ def to_common(self, image_root: Path, mask_root: Path):
175175
raise ValueError(
176176
f"Cannot find file {im_path}. Make sure `image_root` is set properly"
177177
)
178-
179-
if not annotation.file_name.endswith('.png'):
178+
if not str(annotation.file_name).endswith('.png'):
180179
raise ValueError(
181180
f"COCO masks must be stored as png files and their extension must be `.png`. Found {annotation.file_name}"
182181
)
183-
mask = MaskData(file_path=Path(mask_root, annotation.file_name))
182+
mask = MaskData(
183+
file_path=str(Path(mask_root, annotation.file_name)))
184184

185185
for segmentation in annotation.segments_info:
186186
category = category_lookup[segmentation.category_id]
@@ -189,6 +189,6 @@ def to_common(self, image_root: Path, mask_root: Path):
189189
value=Mask(mask=mask,
190190
color=id_to_rgb(
191191
segmentation.id))))
192-
data = ImageData(file_path=im_path)
192+
data = ImageData(file_path=str(im_path))
193193
yield Label(data=data, annotations=annotations)
194194
del annotation_lookup[image.id]

labelbox/exceptions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,4 @@ class MALValidationError(LabelboxError):
122122

123123
class OperationNotAllowedException(Exception):
124124
"""Raised when user does not have permissions to a resource or has exceeded usage limit"""
125-
pass
125+
pass
Lines changed: 153 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,153 @@
1-
[{"ID": "ckw3ce1mc78b50zc30dqf0qhj", "DataRow ID": "ckw3cctc41uqg0zo5023e59hn", "Labeled Data": "https://storage.labelbox.com/ckk4q1vgapsau07324awnsjq2%2F8821d3e2-9059-b616-9d4a-9723da3ea073-im1?Expires=1638367029433&KeyName=labelbox-assets-key-3&Signature=FPOQz-alx3gHMK30ib1iPqJj0W0", "Label": {"objects": [{"featureId": "ckw3ce58u00003e66w9rh0onm", "schemaId": "ckw3cdy207b6t0zbn3sh52xoh", "color": "#1CE6FF", "title": "obj", "value": "obj", "polygon": [{"x": 99.405, "y": 56.15}, {"x": 111.421, "y": 99.129}, {"x": 146.082, "y": 80.413}, {"x": 118.815, "y": 47.369}], "instanceURI": "https://api.labelbox.com/masks/feature/ckw3ce58u00003e66w9rh0onm?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJja2s0cTF2Z3djMHZwMDcwNHhoeDdtNHZrIiwib3JnYW5pemF0aW9uSWQiOiJja2s0cTF2Z2Fwc2F1MDczMjRhd25zanEyIiwiaWF0IjoxNjM3MTU3NDI5LCJleHAiOjE2Mzk3NDk0Mjl9.L4PvjcpSIWV_9R5_M7c_24sj79wtserE_2hkx3ZeCMU"}], "classifications": [], "relationships": []}, "Created By": "msokoloff@labelbox.com", "Project Name": "test", "Created At": "2021-11-17T09:48:56.000Z", "Updated At": "2021-11-17T09:48:56.305Z", "Seconds to Label": 2.239, "External ID": "im1", "Agreement": -1, "Benchmark Agreement": -1, "Benchmark ID": null, "Dataset Name": "no-name", "Reviews": [], "View Label": "https://editor.labelbox.com?project=ckw3cd90b38br0zd4dh4n1xou&label=ckw3ce1mc78b50zc30dqf0qhj", "Has Open Issues": 0, "Skipped": false}, {"ID": "ckw3cea3f7b9t0zbn2tgp2y83", "DataRow ID": "ckw3cctc41uqo0zo5gpma1mr2", "Labeled Data": "https://storage.labelbox.com/ckk4q1vgapsau07324awnsjq2%2F1bc65970-9880-78b4-d298-7a7ef7f8f3fc-im3?Expires=1638367029433&KeyName=labelbox-assets-key-3&Signature=GZUsyQqYYlQPWBYv7GApFYlHXAc", "Label": {"objects": [], "classifications": [{"featureId": "ckw3ced5e00023e66236meh70", "schemaId": "ckw3cdy207b6v0zbn11gp0zz4", "title": "classification", "value": "classification", "answer": {"featureId": "ckw3ced5e00013e6652355ejd", "schemaId": "ckw3cdy207b6w0zbn2hgp3321", "title": "op1", "value": "op_1"}}], "relationships": []}, "Created By": "msokoloff@labelbox.com", "Project Name": "test", "Created At": "2021-11-17T09:49:02.000Z", "Updated At": "2021-11-17T09:49:02.220Z", "Seconds to Label": 5.373, "External ID": "im3", "Agreement": -1, "Benchmark Agreement": -1, "Benchmark ID": null, "Dataset Name": "no-name", "Reviews": [], "View Label": "https://editor.labelbox.com?project=ckw3cd90b38br0zd4dh4n1xou&label=ckw3cea3f7b9t0zbn2tgp2y83", "Has Open Issues": 0, "Skipped": false}, {"ID": "ckw3cec4v78ex0zc3aodwdekw", "DataRow ID": "ckw3cctc41uqs0zo52cy6eus1", "Labeled Data": "https://storage.labelbox.com/ckk4q1vgapsau07324awnsjq2%2Fdb42c0e8-e005-3305-ed35-b021f109b6a7-im4?Expires=1638367029433&KeyName=labelbox-assets-key-3&Signature=Hms9mqcIyWNDzoJUdvMa6_hRKY4", "Label": {"objects": [{"featureId": "ckw3cefl900033e66k41q6zpc", "schemaId": "ckw3cdy207b6t0zbn3sh52xoh", "color": "#1CE6FF", "title": "obj", "value": "obj", "polygon": [{"x": 69.58, "y": 42.292}, {"x": 64.932, "y": 74.128}, {"x": 91.888, "y": 64.601}, {"x": 86.775, "y": 41.828}], "instanceURI": "https://api.labelbox.com/masks/feature/ckw3cefl900033e66k41q6zpc?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJja2s0cTF2Z3djMHZwMDcwNHhoeDdtNHZrIiwib3JnYW5pemF0aW9uSWQiOiJja2s0cTF2Z2Fwc2F1MDczMjRhd25zanEyIiwiaWF0IjoxNjM3MTU3NDI5LCJleHAiOjE2Mzk3NDk0Mjl9.L4PvjcpSIWV_9R5_M7c_24sj79wtserE_2hkx3ZeCMU"}], "classifications": [{"featureId": "ckw3ceijf00053e669zaplftd", "schemaId": "ckw3cdy207b6v0zbn11gp0zz4", "title": "classification", "value": "classification", "answer": {"featureId": "ckw3ceijf00043e665ex22xkp", "schemaId": "ckw3cdy207b6y0zbn77201rux", "title": "op2", "value": "op_2"}}], "relationships": []}, "Created By": "msokoloff@labelbox.com", "Project Name": "test", "Created At": "2021-11-17T09:49:15.000Z", "Updated At": "2021-11-17T09:49:15.785Z", "Seconds to Label": 5, "External ID": "im4", "Agreement": -1, "Benchmark Agreement": -1, "Benchmark ID": null, "Dataset Name": "no-name", "Reviews": [], "View Label": "https://editor.labelbox.com?project=ckw3cd90b38br0zd4dh4n1xou&label=ckw3cec4v78ex0zc3aodwdekw", "Has Open Issues": 0, "Skipped": false}, {"ID": "ckw3ce1s34c1i0zbp32067q4v", "DataRow ID": "ckw3cctc41uqk0zo52n31egs1", "Labeled Data": "https://storage.labelbox.com/ckk4q1vgapsau07324awnsjq2%2F402cbd62-9127-5b50-57d6-d77aaf89f643-im2?Expires=1638367029433&KeyName=labelbox-assets-key-3&Signature=QIwHFUXN1mjBn8K4ZLWVQGQekmE", "Label": {}, "Created By": "msokoloff@labelbox.com", "Project Name": "test", "Created At": "2021-11-17T09:48:59.000Z", "Updated At": "2021-11-17T09:49:02.000Z", "Seconds to Label": 3.524, "External ID": "im2", "Agreement": -1, "Benchmark Agreement": -1, "Benchmark ID": null, "Dataset Name": "no-name", "Reviews": [], "View Label": "https://editor.labelbox.com?project=ckw3cd90b38br0zd4dh4n1xou&label=ckw3ce1s34c1i0zbp32067q4v", "Has Open Issues": 0, "Skipped": true}]
1+
[{
2+
"ID": "ckw3ce1mc78b50zc30dqf0qhj",
3+
"DataRow ID": "ckw3cctc41uqg0zo5023e59hn",
4+
"Labeled Data": "https://storage.labelbox.com/ckk4q1vgapsau07324awnsjq2%2F8821d3e2-9059-b616-9d4a-9723da3ea073-im1?Expires=1638367029433&KeyName=labelbox-assets-key-3&Signature=FPOQz-alx3gHMK30ib1iPqJj0W0",
5+
"Label": {
6+
"objects": [{
7+
"featureId": "ckw3ce58u00003e66w9rh0onm",
8+
"schemaId": "ckw3cdy207b6t0zbn3sh52xoh",
9+
"color": "#1CE6FF",
10+
"title": "obj",
11+
"value": "obj",
12+
"polygon": [{
13+
"x": 99.405,
14+
"y": 56.15
15+
}, {
16+
"x": 111.421,
17+
"y": 99.129
18+
}, {
19+
"x": 146.082,
20+
"y": 80.413
21+
}, {
22+
"x": 118.815,
23+
"y": 47.369
24+
}],
25+
"instanceURI": "https://api.labelbox.com/masks/feature/ckw3ce58u00003e66w9rh0onm?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJja2s0cTF2Z3djMHZwMDcwNHhoeDdtNHZrIiwib3JnYW5pemF0aW9uSWQiOiJja2s0cTF2Z2Fwc2F1MDczMjRhd25zanEyIiwiaWF0IjoxNjM3MTU3NDI5LCJleHAiOjE2Mzk3NDk0Mjl9.L4PvjcpSIWV_9R5_M7c_24sj79wtserE_2hkx3ZeCMU"
26+
}],
27+
"classifications": [],
28+
"relationships": []
29+
},
30+
"Created By": "msokoloff@labelbox.com",
31+
"Project Name": "test",
32+
"Created At": "2021-11-17T09:48:56.000Z",
33+
"Updated At": "2021-11-17T09:48:56.305Z",
34+
"Seconds to Label": 2.239,
35+
"External ID": "im1",
36+
"Agreement": -1,
37+
"Benchmark Agreement": -1,
38+
"Benchmark ID": null,
39+
"Dataset Name": "no-name",
40+
"Reviews": [],
41+
"View Label": "https://editor.labelbox.com?project=ckw3cd90b38br0zd4dh4n1xou&label=ckw3ce1mc78b50zc30dqf0qhj",
42+
"Has Open Issues": 0,
43+
"Skipped": false
44+
}, {
45+
"ID": "ckw3cea3f7b9t0zbn2tgp2y83",
46+
"DataRow ID": "ckw3cctc41uqo0zo5gpma1mr2",
47+
"Labeled Data": "https://storage.labelbox.com/ckk4q1vgapsau07324awnsjq2%2F1bc65970-9880-78b4-d298-7a7ef7f8f3fc-im3?Expires=1638367029433&KeyName=labelbox-assets-key-3&Signature=GZUsyQqYYlQPWBYv7GApFYlHXAc",
48+
"media_type": "image",
49+
"Label": {
50+
"objects": [],
51+
"classifications": [{
52+
"featureId": "ckw3ced5e00023e66236meh70",
53+
"schemaId": "ckw3cdy207b6v0zbn11gp0zz4",
54+
"title": "classification",
55+
"value": "classification",
56+
"answer": {
57+
"featureId": "ckw3ced5e00013e6652355ejd",
58+
"schemaId": "ckw3cdy207b6w0zbn2hgp3321",
59+
"title": "op1",
60+
"value": "op_1"
61+
}
62+
}],
63+
"relationships": []
64+
},
65+
"Created By": "msokoloff@labelbox.com",
66+
"Project Name": "test",
67+
"Created At": "2021-11-17T09:49:02.000Z",
68+
"Updated At": "2021-11-17T09:49:02.220Z",
69+
"Seconds to Label": 5.373,
70+
"External ID": "im3",
71+
"Agreement": -1,
72+
"Benchmark Agreement": -1,
73+
"Benchmark ID": null,
74+
"Dataset Name": "no-name",
75+
"Reviews": [],
76+
"View Label": "https://editor.labelbox.com?project=ckw3cd90b38br0zd4dh4n1xou&label=ckw3cea3f7b9t0zbn2tgp2y83",
77+
"Has Open Issues": 0,
78+
"Skipped": false
79+
}, {
80+
"ID": "ckw3cec4v78ex0zc3aodwdekw",
81+
"DataRow ID": "ckw3cctc41uqs0zo52cy6eus1",
82+
"Labeled Data": "https://storage.labelbox.com/ckk4q1vgapsau07324awnsjq2%2Fdb42c0e8-e005-3305-ed35-b021f109b6a7-im4?Expires=1638367029433&KeyName=labelbox-assets-key-3&Signature=Hms9mqcIyWNDzoJUdvMa6_hRKY4",
83+
"Label": {
84+
"objects": [{
85+
"featureId": "ckw3cefl900033e66k41q6zpc",
86+
"schemaId": "ckw3cdy207b6t0zbn3sh52xoh",
87+
"color": "#1CE6FF",
88+
"title": "obj",
89+
"value": "obj",
90+
"polygon": [{
91+
"x": 69.58,
92+
"y": 42.292
93+
}, {
94+
"x": 64.932,
95+
"y": 74.128
96+
}, {
97+
"x": 91.888,
98+
"y": 64.601
99+
}, {
100+
"x": 86.775,
101+
"y": 41.828
102+
}],
103+
"instanceURI": "https://api.labelbox.com/masks/feature/ckw3cefl900033e66k41q6zpc?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJja2s0cTF2Z3djMHZwMDcwNHhoeDdtNHZrIiwib3JnYW5pemF0aW9uSWQiOiJja2s0cTF2Z2Fwc2F1MDczMjRhd25zanEyIiwiaWF0IjoxNjM3MTU3NDI5LCJleHAiOjE2Mzk3NDk0Mjl9.L4PvjcpSIWV_9R5_M7c_24sj79wtserE_2hkx3ZeCMU"
104+
}],
105+
"classifications": [{
106+
"featureId": "ckw3ceijf00053e669zaplftd",
107+
"schemaId": "ckw3cdy207b6v0zbn11gp0zz4",
108+
"title": "classification",
109+
"value": "classification",
110+
"answer": {
111+
"featureId": "ckw3ceijf00043e665ex22xkp",
112+
"schemaId": "ckw3cdy207b6y0zbn77201rux",
113+
"title": "op2",
114+
"value": "op_2"
115+
}
116+
}],
117+
"relationships": []
118+
},
119+
"Created By": "msokoloff@labelbox.com",
120+
"Project Name": "test",
121+
"Created At": "2021-11-17T09:49:15.000Z",
122+
"Updated At": "2021-11-17T09:49:15.785Z",
123+
"Seconds to Label": 5,
124+
"External ID": "im4",
125+
"Agreement": -1,
126+
"Benchmark Agreement": -1,
127+
"Benchmark ID": null,
128+
"Dataset Name": "no-name",
129+
"Reviews": [],
130+
"View Label": "https://editor.labelbox.com?project=ckw3cd90b38br0zd4dh4n1xou&label=ckw3cec4v78ex0zc3aodwdekw",
131+
"Has Open Issues": 0,
132+
"Skipped": false
133+
}, {
134+
"ID": "ckw3ce1s34c1i0zbp32067q4v",
135+
"DataRow ID": "ckw3cctc41uqk0zo52n31egs1",
136+
"Labeled Data": "https://storage.labelbox.com/ckk4q1vgapsau07324awnsjq2%2F402cbd62-9127-5b50-57d6-d77aaf89f643-im2?Expires=1638367029433&KeyName=labelbox-assets-key-3&Signature=QIwHFUXN1mjBn8K4ZLWVQGQekmE",
137+
"media_type": "image",
138+
"Label": {},
139+
"Created By": "msokoloff@labelbox.com",
140+
"Project Name": "test",
141+
"Created At": "2021-11-17T09:48:59.000Z",
142+
"Updated At": "2021-11-17T09:49:02.000Z",
143+
"Seconds to Label": 3.524,
144+
"External ID": "im2",
145+
"Agreement": -1,
146+
"Benchmark Agreement": -1,
147+
"Benchmark ID": null,
148+
"Dataset Name": "no-name",
149+
"Reviews": [],
150+
"View Label": "https://editor.labelbox.com?project=ckw3cd90b38br0zd4dh4n1xou&label=ckw3ce1s34c1i0zbp32067q4v",
151+
"Has Open Issues": 0,
152+
"Skipped": true
153+
}]

tests/data/metrics/confusion_matrix/test_confusion_matrix_data_row.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
from pytest_cases import fixture_ref
2-
from pytest_cases import pytest_parametrize_plus, fixture_ref
2+
from pytest_cases import parametrize, fixture_ref
33

44
from labelbox.data.metrics.confusion_matrix.confusion_matrix import confusion_matrix_metric
55

66

7-
@pytest_parametrize_plus("tool_examples", [
7+
@parametrize("tool_examples", [
88
fixture_ref('polygon_pairs'),
99
fixture_ref('rectangle_pairs'),
1010
fixture_ref('mask_pairs'),
@@ -27,10 +27,9 @@ def test_overlapping_objects(tool_examples):
2727
expected), f"{example.predictions},{example.ground_truths}"
2828

2929

30-
@pytest_parametrize_plus(
31-
"tool_examples",
32-
[fixture_ref('checklist_pairs'),
33-
fixture_ref('radio_pairs')])
30+
@parametrize("tool_examples",
31+
[fixture_ref('checklist_pairs'),
32+
fixture_ref('radio_pairs')])
3433
def test_overlapping_classifications(tool_examples):
3534
for example in tool_examples:
3635
score = confusion_matrix_metric(example.ground_truths,

tests/data/metrics/confusion_matrix/test_confusion_matrix_feature.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
from pytest_cases import fixture_ref
2-
from pytest_cases import pytest_parametrize_plus, fixture_ref
2+
from pytest_cases import parametrize, fixture_ref
33

44
from labelbox.data.metrics.confusion_matrix.confusion_matrix import feature_confusion_matrix_metric
55

66

7-
@pytest_parametrize_plus("tool_examples", [
7+
@parametrize("tool_examples", [
88
fixture_ref('polygon_pairs'),
99
fixture_ref('rectangle_pairs'),
1010
fixture_ref('mask_pairs'),
@@ -23,10 +23,9 @@ def test_overlapping_objects(tool_examples):
2323
assert metrics == example.expected, f"{example.predictions},{example.ground_truths}"
2424

2525

26-
@pytest_parametrize_plus(
27-
"tool_examples",
28-
[fixture_ref('checklist_pairs'),
29-
fixture_ref('radio_pairs')])
26+
@parametrize("tool_examples",
27+
[fixture_ref('checklist_pairs'),
28+
fixture_ref('radio_pairs')])
3029
def test_overlapping_classifications(tool_examples):
3130
for example in tool_examples:
3231

tests/data/test_prefetch_generator.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import pytest
2+
from labelbox.data.generator import PrefetchGenerator
3+
from random import random
4+
5+
6+
class ChildClassGenerator(PrefetchGenerator):
7+
8+
def __init__(self, examples, num_executors=1):
9+
super().__init__(data=examples, num_executors=num_executors)
10+
11+
def _process(self, value):
12+
num = random()
13+
if num < .2:
14+
raise ValueError("Randomized value error")
15+
return value
16+
17+
18+
amount = (i for i in range(50))
19+
20+
21+
def test_single_thread_generator():
22+
generator = ChildClassGenerator(amount, num_executors=1)
23+
24+
with pytest.raises(ValueError):
25+
for _ in range(51):
26+
next(generator)
27+
28+
29+
def test_multi_thread_generator():
30+
generator = ChildClassGenerator(amount, num_executors=4)
31+
32+
with pytest.raises(ValueError):
33+
for _ in range(51):
34+
next(generator)

tests/integration/annotation_import/test_ndjson_validation.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import pytest
22
import ndjson
3-
from pytest_cases import pytest_parametrize_plus, fixture_ref
3+
from pytest_cases import parametrize, fixture_ref
44

55
from labelbox.exceptions import MALValidationError
66
from labelbox.schema.bulk_import_request import (NDChecklist, NDClassification,
@@ -23,14 +23,14 @@ def test_subclassification_construction(rectangle_inference):
2323
assert isinstance(tool.classifications[0], NDRadio)
2424

2525

26-
@pytest_parametrize_plus("inference, expected_type",
27-
[(fixture_ref('polygon_inference'), NDPolygon),
28-
(fixture_ref('rectangle_inference'), NDRectangle),
29-
(fixture_ref('line_inference'), NDPolyline),
30-
(fixture_ref('entity_inference'), NDTextEntity),
31-
(fixture_ref('segmentation_inference'), NDMask),
32-
(fixture_ref('segmentation_inference_rle'), NDMask),
33-
(fixture_ref('segmentation_inference_png'), NDMask)])
26+
@parametrize("inference, expected_type",
27+
[(fixture_ref('polygon_inference'), NDPolygon),
28+
(fixture_ref('rectangle_inference'), NDRectangle),
29+
(fixture_ref('line_inference'), NDPolyline),
30+
(fixture_ref('entity_inference'), NDTextEntity),
31+
(fixture_ref('segmentation_inference'), NDMask),
32+
(fixture_ref('segmentation_inference_rle'), NDMask),
33+
(fixture_ref('segmentation_inference_png'), NDMask)])
3434
def test_tool_construction(inference, expected_type):
3535
assert isinstance(NDTool.build(inference), expected_type)
3636

0 commit comments

Comments
 (0)