Skip to content

Commit 6a34aeb

Browse files
authored
Release 3.54.0 (#1258)
2 parents ddb8063 + d67624e commit 6a34aeb

16 files changed

+153
-50
lines changed

.yapfignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
pytest.ini
1+
Makefile
2+
*.txt
3+
*.ini

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
# Changelog
2+
# Version 3.54.0 (2023-10-10)
3+
## Added
4+
* Add exports v1 deprecation warning
5+
* Create method in SDK to modify LPO priorities in bulk
6+
## Removed
7+
* Remove backoff library
28
# Version 3.53.0 (2023-10-03)
39
## Added
410
* Remove LPO deprecation warning and allow greater range of priority values

docs/source/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
copyright = '2021, Labelbox'
2222
author = 'Labelbox'
2323

24-
release = '3.53.0'
24+
release = '3.54.0'
2525

2626
# -- General configuration ---------------------------------------------------
2727

labelbox/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name = "labelbox"
2-
__version__ = "3.53.0"
2+
__version__ = "3.54.0"
33

44
from labelbox.client import Client
55
from labelbox.schema.project import Project

labelbox/schema/annotation_import.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import time
66
from typing import Any, BinaryIO, Dict, List, Union, TYPE_CHECKING, cast
77

8-
import backoff
8+
from google.api_core import retry
99
from labelbox import parser
1010
import requests
1111
from tqdm import tqdm # type: ignore
@@ -109,12 +109,9 @@ def wait_until_done(self,
109109
pbar.update(100 - pbar.n)
110110
pbar.close()
111111

112-
@backoff.on_exception(
113-
backoff.expo,
114-
(labelbox.exceptions.ApiLimitError, labelbox.exceptions.TimeoutError,
115-
labelbox.exceptions.NetworkError),
116-
max_tries=10,
117-
jitter=None)
112+
@retry.Retry(predicate=retry.if_exception_type(
113+
labelbox.exceptions.ApiLimitError, labelbox.exceptions.TimeoutError,
114+
labelbox.exceptions.NetworkError))
118115
def __backoff_refresh(self) -> None:
119116
self.refresh()
120117

labelbox/schema/batch.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import requests
1010
import logging
1111
import time
12+
import warnings
1213

1314
if TYPE_CHECKING:
1415
from labelbox import Project
@@ -103,6 +104,10 @@ def export_data_rows(self,
103104
Raises:
104105
LabelboxError: if the export fails or is unable to download within the specified time.
105106
"""
107+
warnings.warn(
108+
"You are currently utilizing exports v1 for this action, which will be deprecated after December 31st, 2023. We recommend transitioning to exports v2. To view export v2 details, visit our docs: https://docs.labelbox.com/reference/label-export",
109+
DeprecationWarning)
110+
106111
id_param = "batchId"
107112
metadata_param = "includeMetadataInput"
108113
query_str = """mutation GetBatchDataRowsExportUrlPyApi($%s: ID!, $%s: Boolean!)

labelbox/schema/bulk_import_request.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import logging
77
from pathlib import Path
88
import pydantic
9-
import backoff
9+
from google.api_core import retry
1010
from labelbox import parser
1111
import requests
1212
from pydantic import BaseModel, root_validator, validator
@@ -197,11 +197,9 @@ def wait_until_done(self, sleep_time_seconds: int = 5) -> None:
197197
time.sleep(sleep_time_seconds)
198198
self.__exponential_backoff_refresh()
199199

200-
@backoff.on_exception(
201-
backoff.expo, (lb_exceptions.ApiLimitError, lb_exceptions.TimeoutError,
202-
lb_exceptions.NetworkError),
203-
max_tries=10,
204-
jitter=None)
200+
@retry.Retry(predicate=retry.if_exception_type(lb_exceptions.ApiLimitError,
201+
lb_exceptions.TimeoutError,
202+
lb_exceptions.NetworkError))
205203
def __exponential_backoff_refresh(self) -> None:
206204
self.refresh()
207205

labelbox/schema/dataset.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from collections.abc import Iterable
66
from string import Template
77
import time
8+
import warnings
89

910
from labelbox import parser
1011
from itertools import islice
@@ -565,6 +566,9 @@ def export_data_rows(self,
565566
Raises:
566567
LabelboxError: if the export fails or is unable to download within the specified time.
567568
"""
569+
warnings.warn(
570+
"You are currently utilizing exports v1 for this action, which will be deprecated after December 31st, 2023. We recommend transitioning to exports v2. To view export v2 details, visit our docs: https://docs.labelbox.com/reference/label-export",
571+
DeprecationWarning)
568572
id_param = "datasetId"
569573
metadata_param = "includeMetadataInput"
570574
query_str = """mutation GetDatasetDataRowsExportUrlPyApi($%s: ID!, $%s: Boolean!)

labelbox/schema/model_run.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import time
66
import logging
77
import requests
8+
import warnings
89
from labelbox import parser
910
from enum import Enum
1011

@@ -470,6 +471,9 @@ def export_labels(
470471
If the server didn't generate during the `timeout_seconds` period,
471472
None is returned.
472473
"""
474+
warnings.warn(
475+
"You are currently utilizing exports v1 for this action, which will be deprecated after December 31st, 2023. We recommend transitioning to exports v2. To view export v2 details, visit our docs: https://docs.labelbox.com/reference/label-export",
476+
DeprecationWarning)
473477
sleep_time = 2
474478
query_str = """mutation exportModelRunAnnotationsPyApi($modelRunId: ID!) {
475479
exportModelRunAnnotations(data: {modelRunId: $modelRunId}) {

labelbox/schema/project.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import json
22
import logging
33
import time
4+
import warnings
45
from collections import namedtuple
56
from datetime import datetime, timezone
67
from pathlib import Path
@@ -231,6 +232,9 @@ def export_queued_data_rows(
231232
Raises:
232233
LabelboxError: if the export fails or is unable to download within the specified time.
233234
"""
235+
warnings.warn(
236+
"You are currently utilizing exports v1 for this action, which will be deprecated after December 31st, 2023. We recommend transitioning to exports v2. To view export v2 details, visit our docs: https://docs.labelbox.com/reference/label-export",
237+
DeprecationWarning)
234238
id_param = "projectId"
235239
metadata_param = "includeMetadataInput"
236240
query_str = """mutation GetQueuedDataRowsExportUrlPyApi($%s: ID!, $%s: Boolean!)
@@ -334,6 +338,9 @@ def export_labels(self,
334338
URL of the data file with this Project's labels. If the server didn't
335339
generate during the `timeout_seconds` period, None is returned.
336340
"""
341+
warnings.warn(
342+
"You are currently utilizing exports v1 for this action, which will be deprecated after December 31st, 2023. We recommend transitioning to exports v2. To view export v2 details, visit our docs: https://docs.labelbox.com/reference/label-export",
343+
DeprecationWarning)
337344

338345
def _string_from_dict(dictionary: dict, value_with_quotes=False) -> str:
339346
"""Returns a concatenated string of the dictionary's keys and values
@@ -1166,6 +1173,60 @@ def set_labeling_parameter_overrides(self, data) -> bool:
11661173
res = self.client.execute(query_str, {id_param: self.uid})
11671174
return res["project"]["setLabelingParameterOverrides"]["success"]
11681175

1176+
def update_data_row_labeling_priority(
1177+
self,
1178+
data_rows: List[str],
1179+
priority: int,
1180+
) -> bool:
1181+
"""
1182+
Updates labeling parameter overrides to this project in bulk. This method allows up to 1 million data rows to be
1183+
updated at once.
1184+
1185+
See information on priority here:
1186+
https://docs.labelbox.com/en/configure-editor/queue-system#reservation-system
1187+
1188+
Args:
1189+
data_rows (iterable): An iterable of data row ids.
1190+
priority (int): Priority for the new override. See above for more information.
1191+
1192+
Returns:
1193+
bool, indicates if the operation was a success.
1194+
"""
1195+
1196+
method = "createQueuePriorityUpdateTask"
1197+
priority_param = "priority"
1198+
project_param = "projectId"
1199+
data_rows_param = "dataRowIds"
1200+
query_str = """mutation %sPyApi(
1201+
$%s: Int!
1202+
$%s: ID!
1203+
$%s: [ID!]
1204+
) {
1205+
project(where: { id: $%s }) {
1206+
%s(
1207+
data: { priority: $%s, dataRowIds: $%s }
1208+
) {
1209+
taskId
1210+
}
1211+
}
1212+
}
1213+
""" % (method, priority_param, project_param, data_rows_param,
1214+
project_param, method, priority_param, data_rows_param)
1215+
res = self.client.execute(
1216+
query_str, {
1217+
priority_param: priority,
1218+
project_param: self.uid,
1219+
data_rows_param: data_rows
1220+
})["project"][method]
1221+
1222+
task_id = res['taskId']
1223+
1224+
task = self._wait_for_task(task_id)
1225+
if task.status != "COMPLETE":
1226+
raise LabelboxError(f"Priority was not updated successfully: " +
1227+
json.dumps(task.errors))
1228+
return True
1229+
11691230
def upsert_review_queue(self, quota_factor) -> None:
11701231
""" Sets the the proportion of total assets in a project to review.
11711232

mypy.ini

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
[mypy]
22

3-
[mypy-backoff.*]
4-
ignore_missing_imports = True
5-
63
[mypy-google.*]
74
ignore_missing_imports = True
85

requirements.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
backoff==1.10.0
21
geojson
32
google-api-core>=1.22.1
43
imagesize

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
url="https://labelbox.com",
2121
packages=setuptools.find_packages(),
2222
install_requires=[
23-
"backoff==1.10.0", "requests>=2.22.0", "google-api-core>=1.22.1",
24-
"pydantic>=1.8,<2.0", "tqdm", "python-dateutil>=2.8.2,<2.9.0"
23+
"requests>=2.22.0", "google-api-core>=1.22.1", "pydantic>=1.8,<2.0",
24+
"tqdm", "python-dateutil>=2.8.2,<2.9.0"
2525
],
2626
extras_require={
2727
'data': [

tests/integration/conftest.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import pytest
1212
import requests
1313

14-
from labelbox import Dataset
14+
from labelbox import Dataset, DataRow
1515
from labelbox import LabelingFrontend
1616
from labelbox import OntologyBuilder, Tool, Option, Classification, MediaType
1717
from labelbox.orm import query
@@ -167,6 +167,29 @@ def consensus_project(client, rand_gen):
167167
project.delete()
168168

169169

170+
@pytest.fixture
171+
def consensus_project_with_batch(consensus_project, initial_dataset, rand_gen,
172+
image_url):
173+
project = consensus_project
174+
dataset = initial_dataset
175+
176+
task = dataset.create_data_rows([{DataRow.row_data: image_url}] * 3)
177+
task.wait_till_done()
178+
assert task.status == "COMPLETE"
179+
180+
data_rows = list(dataset.data_rows())
181+
assert len(data_rows) == 3
182+
183+
batch = project.create_batch(
184+
rand_gen(str),
185+
data_rows, # sample of data row objects
186+
5 # priority between 1(Highest) - 5(lowest)
187+
)
188+
189+
yield [project, batch, data_rows]
190+
batch.delete()
191+
192+
170193
@pytest.fixture
171194
def dataset(client, rand_gen):
172195
dataset = client.create_dataset(name=rand_gen(str))

tests/integration/export_v2/test_export_video.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,14 @@ def org_id(client):
1717
return client.get_organization().uid
1818

1919

20-
def test_export_v2_video(client, configured_project_without_data_rows,
21-
video_data, video_data_row, is_adv_enabled,
22-
bbox_video_annotation_objects, rand_gen, user_id,
23-
org_id):
24-
25-
orgid = client.get_organization().uid
26-
userid = client.get_user().uid
20+
def test_export_v2_video(
21+
client,
22+
configured_project_without_data_rows,
23+
video_data,
24+
video_data_row,
25+
bbox_video_annotation_objects,
26+
rand_gen,
27+
):
2728

2829
project = configured_project_without_data_rows
2930
project_id = project.uid
@@ -51,6 +52,7 @@ def test_export_v2_video(client, configured_project_without_data_rows,
5152

5253
num_retries = 5
5354
task = None
55+
5456
while (num_retries > 0):
5557
task = project.export_v2(
5658
params={
@@ -72,7 +74,10 @@ def test_export_v2_video(client, configured_project_without_data_rows,
7274
assert data_row_export['global_key'] == video_data_row['global_key']
7375
assert data_row_export['row_data'] == video_data_row['row_data']
7476
assert export_data[0]['media_attributes']['mime_type'] == 'video/mp4'
75-
77+
assert export_data[0]['media_attributes'][
78+
'frame_rate'] == 10 # as per the video_data fixture
79+
assert export_data[0]['media_attributes'][
80+
'frame_count'] == 100 # as per the video_data fixture
7681
expected_export_label = {
7782
'label_kind': 'Video',
7883
'version': '1.0.0',

tests/integration/test_labeling_parameter_overrides.py

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,8 @@
22
from labelbox import DataRow
33

44

5-
def test_labeling_parameter_overrides(consensus_project, initial_dataset,
6-
rand_gen, image_url):
7-
project = consensus_project
8-
dataset = initial_dataset
9-
10-
task = dataset.create_data_rows([{DataRow.row_data: image_url}] * 3)
11-
task.wait_till_done()
12-
assert task.status == "COMPLETE"
13-
14-
data_rows = list(dataset.data_rows())
15-
assert len(data_rows) == 3
16-
17-
project.create_batch(
18-
rand_gen(str),
19-
data_rows, # sample of data row objects
20-
5 # priority between 1(Highest) - 5(lowest)
21-
)
5+
def test_labeling_parameter_overrides(consensus_project_with_batch):
6+
[project, _, data_rows] = consensus_project_with_batch
227

238
init_labeling_parameter_overrides = list(
249
project.labeling_parameter_overrides())
@@ -45,10 +30,27 @@ def test_labeling_parameter_overrides(consensus_project, initial_dataset,
4530
data = [(data_rows[2], "a_string", 3)]
4631
project.set_labeling_parameter_overrides(data)
4732
assert str(exc_info.value) == \
48-
f"Priority must be an int. Found <class 'str'> for data_row {data_rows[2]}. Index: 0"
33+
f"Priority must be an int. Found <class 'str'> for data_row {data_rows[2]}. Index: 0"
4934

5035
with pytest.raises(TypeError) as exc_info:
5136
data = [(data_rows[2].uid, 1)]
5237
project.set_labeling_parameter_overrides(data)
5338
assert str(exc_info.value) == \
54-
"data_row should be be of type DataRow. Found <class 'str'>. Index: 0"
39+
"data_row should be be of type DataRow. Found <class 'str'>. Index: 0"
40+
41+
42+
def test_set_labeling_priority(consensus_project_with_batch):
43+
[project, _, data_rows] = consensus_project_with_batch
44+
45+
init_labeling_parameter_overrides = list(
46+
project.labeling_parameter_overrides())
47+
assert len(init_labeling_parameter_overrides) == 3
48+
assert {o.priority for o in init_labeling_parameter_overrides} == {5, 5, 5}
49+
50+
data = [data_row.uid for data_row in data_rows]
51+
success = project.update_data_row_labeling_priority(data, 1)
52+
assert success
53+
54+
updated_overrides = list(project.labeling_parameter_overrides())
55+
assert len(updated_overrides) == 3
56+
assert {o.priority for o in updated_overrides} == {1, 1, 1}

0 commit comments

Comments
 (0)