Skip to content

Commit 07a7d3f

Browse files
author
Florijan Stamenković
authored
Fix minor bugs and tidy tests up (#98)
1 parent d359402 commit 07a7d3f

File tree

13 files changed

+64
-45
lines changed

13 files changed

+64
-45
lines changed

.github/workflows/python-package.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
max-parallel: 1
1616
matrix:
1717
# TODO: unlock parallel testing by using more API keys
18-
python-version: [3.6]
18+
python-version: [3.6, 3.7, 3.8]
1919

2020
steps:
2121

@@ -73,4 +73,4 @@ jobs:
7373
# randall+staging-python@labelbox.com
7474
LABELBOX_TEST_API_KEY_STAGING: ${{ secrets.STAGING_LABELBOX_API_KEY }}
7575
run: |
76-
pytest -svv
76+
tox -e py -- -svv

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
# Changelog
2+
3+
## In progress
4+
### Fix
5+
* Custom queries with bad syntax now raise adequate exceptions (InvalidQuery)
6+
* Comparing a Labelbox object (e.g. Project) to None doesn't raise an exception
7+
* Adding `order_by` to `Project.labels` doesn't raise an exception
8+
29
## Version 2.4.9 (2020-11-09)
310
### Fix
411
* 2.4.8 was broken for > Python 3.6

docs/source/conf.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import sys
1515
sys.path.insert(0, os.path.abspath('../..'))
1616

17-
1817
# -- Project information -----------------------------------------------------
1918

2019
project = 'Labelbox Python API reference'
@@ -28,9 +27,7 @@
2827
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
2928
# ones.
3029
extensions = [
31-
'sphinx.ext.autodoc',
32-
'sphinx.ext.viewcode',
33-
'sphinxcontrib.napoleon'
30+
'sphinx.ext.autodoc', 'sphinx.ext.viewcode', 'sphinxcontrib.napoleon'
3431
]
3532

3633
# Add any paths that contain templates here, relative to this directory.
@@ -41,7 +38,6 @@
4138
# This pattern also affects html_static_path and html_extra_path.
4239
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
4340

44-
4541
# -- Options for HTML output -------------------------------------------------
4642

4743
# The theme to use for HTML and HTML Help pages. See the documentation for

labelbox/client.py

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@ def convert_value(value):
139139
error_502 = '502 Bad Gateway'
140140
if error_502 in response.text:
141141
raise labelbox.exceptions.InternalServerError(error_502)
142+
if "upstream connect error or disconnect/reset before headers" \
143+
in response.text:
144+
raise labelbox.exceptions.InternalServerError(
145+
"Connection reset")
142146
raise labelbox.exceptions.LabelboxError(
143147
"Failed to parse response as JSON: %s" % response.text)
144148

@@ -186,11 +190,27 @@ def check_errors(keywords, *path):
186190
if response_msg.startswith("You have exceeded"):
187191
raise labelbox.exceptions.ApiLimitError(response_msg)
188192

189-
prisma_error = check_errors(["INTERNAL_SERVER_ERROR"], "extensions",
190-
"code")
191-
if prisma_error:
192-
raise labelbox.exceptions.InternalServerError(
193-
prisma_error["message"])
193+
resource_not_found_error = check_errors(["RESOURCE_NOT_FOUND"],
194+
"extensions", "exception",
195+
"code")
196+
if resource_not_found_error is not None:
197+
# Return None and let the caller methods raise an exception
198+
# as they already know which resource type and ID was requested
199+
return None
200+
201+
# A lot of different error situations are now labeled serverside
202+
# as INTERNAL_SERVER_ERROR, when they are actually client errors.
203+
# TODO: fix this in the server API
204+
internal_server_error = check_errors(["INTERNAL_SERVER_ERROR"],
205+
"extensions", "code")
206+
if internal_server_error is not None:
207+
message = internal_server_error.get("message")
208+
209+
if message.startswith("Syntax Error"):
210+
raise labelbox.exceptions.InvalidQueryError(message)
211+
212+
else:
213+
raise labelbox.exceptions.InternalServerError(message)
194214

195215
if len(errors) > 0:
196216
logger.warning("Unparsed errors on query execution: %r", errors)
@@ -297,7 +317,7 @@ def _get_single(self, db_object_type, uid):
297317
"""
298318
query_str, params = query.get_single(db_object_type, uid)
299319
res = self.execute(query_str, params)
300-
res = res[utils.camel_case(db_object_type.type_name())]
320+
res = res and res.get(utils.camel_case(db_object_type.type_name()))
301321
if res is None:
302322
raise labelbox.exceptions.ResourceNotFoundError(
303323
db_object_type, params)

labelbox/orm/db_object.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ def __str__(self):
8282
return "<%s %s>" % (self.type_name().split(".")[-1], attribute_values)
8383

8484
def __eq__(self, other):
85-
return self.type_name() == other.type_name() and self.uid == other.uid
85+
return (isinstance(other, DbObject) and
86+
self.type_name() == other.type_name() and self.uid == other.uid)
8687

8788
def __hash__(self):
8889
return 7541 * hash(self.type_name()) + hash(self.uid)
@@ -152,8 +153,9 @@ def _to_one(self):
152153

153154
query_string, params = query.relationship(self.source, rel, None, None)
154155
result = self.source.client.execute(query_string, params)
155-
result = result[utils.camel_case(type(self.source).type_name())]
156-
result = result[rel.graphql_name]
156+
result = result and result.get(
157+
utils.camel_case(type(self.source).type_name()))
158+
result = result and result.get(rel.graphql_name)
157159
if result is None:
158160
return None
159161
return rel.destination_type(self.source.client, result)

labelbox/schema/project.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ def labels(self, datasets=None, order_by=None):
134134
id_param = "projectId"
135135
query_str = """query GetProjectLabelsPyApi($%s: ID!)
136136
{project (where: {id: $%s})
137-
{labels (skip: %%d first: %%d%s%s) {%s}}}""" % (
137+
{labels (skip: %%d first: %%d %s %s) {%s}}}""" % (
138138
id_param, id_param, where, order_by_str,
139139
query.results_query_part(Label))
140140

tests/integration/test_client_errors.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,9 @@ def test_invalid_attribute_error(client, rand_gen):
103103
project.delete()
104104

105105

106-
@pytest.mark.skip
106+
@pytest.mark.slow
107+
# TODO improve consistency
108+
@pytest.mark.skip(reason="Inconsistent test")
107109
def test_api_limit_error(client, rand_gen):
108110
project_id = client.create_project(name=rand_gen(str)).uid
109111

@@ -114,7 +116,7 @@ def get(arg):
114116
return e
115117

116118
with Pool(300) as pool:
117-
results = pool.map(get, list(range(1000)))
119+
results = pool.map(get, list(range(2000)))
118120

119121
assert labelbox.exceptions.ApiLimitError in {type(r) for r in results}
120122

tests/integration/test_data_rows.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ def test_data_row_bulk_creation(dataset, rand_gen):
4949

5050
data_rows[0].delete()
5151

52+
53+
@pytest.mark.slow
54+
def test_data_row_large_bulk_creation(dataset, rand_gen):
5255
# Do a longer task and expect it not to be complete immediately
5356
with NamedTemporaryFile() as fp:
5457
fp.write("Test data".encode())
@@ -62,7 +65,7 @@ def test_data_row_bulk_creation(dataset, rand_gen):
6265
data_rows = len(list(dataset.data_rows())) == 5003
6366

6467

65-
@pytest.mark.skip
68+
@pytest.mark.xfail(reason="DataRow.dataset() relationship not set")
6669
def test_data_row_single_creation(dataset, rand_gen):
6770
client = dataset.client
6871
assert len(list(dataset.data_rows())) == 0
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
import pytest
12
import requests
23

34

4-
def test_file_uplad(client, rand_gen):
5+
# TODO it seems that at some point Google Storage (gs prefix) started being
6+
# returned, and we can't just download those with requests. Fix this
7+
@pytest.mark.skip
8+
def test_file_upload(client, rand_gen):
59
data = rand_gen(str)
610
url = client.upload_data(data.encode())
711
assert requests.get(url).text == data

tests/integration/test_label.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ def test_labels(label_pack):
3030
assert list(data_row.labels()) == []
3131

3232

33+
# TODO check if this is supported or not
3334
@pytest.mark.skip
3435
def test_label_export(label_pack):
3536
project, dataset, data_row, label = label_pack

0 commit comments

Comments
 (0)