Skip to content

Commit d93fa98

Browse files
committed
Merge remote-tracking branch 'origin/master' into client
2 parents 3de7b2d + ac34952 commit d93fa98

File tree

10 files changed

+127
-32
lines changed

10 files changed

+127
-32
lines changed

README.rst

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,33 @@ Installation
1515
This is tested on Python 3.7+.
1616
Get in touch with ``adamdangoor@gmail.com`` if you would like to use this with another language.
1717

18+
Getting Started
19+
---------------
20+
21+
.. code:: python
22+
23+
import io
24+
25+
from vws import VWS, CloudRecoService
26+
27+
vws_client = VWS(server_access_key='...', server_secret_key='...')
28+
cloud_reco_client = CloudRecoService(client_access_key='...', client_secret_key='...')
29+
name = 'my_image_name'
30+
31+
with open('/path/to/image.png', 'rb') as my_image_file:
32+
my_image = io.BytesIO(my_image_file.read())
33+
34+
target_id = vws_client.add_target(
35+
name=name,
36+
width=1,
37+
image=my_image,
38+
)
39+
vws_client.wait_for_target_processed(target_id=target_id)
40+
matching_targets = cloud_reco_client.query(image=my_image)
41+
42+
assert matching_targets[0]['target_id'] == target_id
43+
44+
1845
Full Documentation
1946
------------------
2047

dev-requirements.txt

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
1-
autoflake==1.3
1+
autoflake==1.3.1
22
check-manifest==0.39
33
codecov==2.0.15 # Upload coverage data
44
doc8==0.8.0
55
dodgy==0.1.9 # Look for uploaded secrets
6-
dulwich==0.19.11
6+
dulwich==0.19.13
77
flake8-commas==2.0.0 # Require silicon valley commas
8-
flake8-quotes==2.0.1 # Require single quotes
8+
flake8-quotes==2.1.0 # Require single quotes
99
flake8==3.7.8 # Lint
1010
freezegun==0.3.12
1111
isort==4.3.21 # Lint imports
12-
mypy==0.720 # Type checking
12+
mypy==0.730 # Type checking
1313
pip_check_reqs==2.0.3
14-
pydocstyle==4.0.0 # Lint docstrings
14+
pydocstyle==4.0.1 # Lint docstrings
1515
pyenchant==2.0.0 # Bindings for a spellchecking sytem
1616
pygithub==1.43.8
1717
Pygments==2.4.2
18-
pylint==2.3.1 # Lint
18+
pylint==2.4.2 # Lint
1919
pyroma==2.5 # Packaging best practices checker
2020
pytest-cov==2.7.1 # Measure code coverage
21-
pytest==5.0.1 # Test runners
22-
PyYAML==5.1.1
23-
Sphinx==2.1.2
24-
sphinx-autodoc-typehints==1.7.0
21+
pytest==5.2.0 # Test runners
22+
PyYAML==5.1.2
23+
Sphinx==2.2.0
24+
sphinx-autodoc-typehints==1.8.0
2525
sphinxcontrib-spelling==4.3.0
26-
twine==1.13.0
26+
twine==2.0.0
2727
versioneer==0.18
28-
vulture==1.0
29-
VWS-Python-Mock==2018.12.1.0
28+
vulture==1.1
29+
VWS-Python-Mock==2019.9.28.0
3030
yapf==0.28.0 # Automatic formatting for Python

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
requests==2.22.0
22
timeout-decorator==0.4.1
3-
urllib3==1.25.3
3+
urllib3==1.25.6

spelling_private_dict.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
AuthenticationFailure
22
BadImage
3+
ConnectionErrorPossiblyImageTooLarge
34
ImageTooLarge
45
MatchProcessing
56
MaxNumResultsOutOfRange
@@ -11,6 +12,7 @@ TargetProcessingTimeout
1112
TargetStatusProcessing
1213
Ubuntu
1314
UnknownTarget
15+
UnknownVWSErrorPossiblyBadName
1416
api
1517
args
1618
ascii

src/vws/_result_codes.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
Tools for managing result codes.
33
"""
44

5+
import json
6+
57
from requests import Response
68

79
from vws.exceptions import (
@@ -18,6 +20,7 @@
1820
TargetStatusNotSuccess,
1921
TargetStatusProcessing,
2022
UnknownTarget,
23+
UnknownVWSErrorPossiblyBadName,
2124
)
2225

2326

@@ -33,8 +36,18 @@ def raise_for_result_code(
3336
response: A response from Vuforia.
3437
expected_result_code: See
3538
https://library.vuforia.com/articles/Solution/How-To-Use-the-Vuforia-Web-Services-API.html#How-To-Interperete-VWS-API-Result-Codes
39+
40+
Raises:
41+
~vws.exceptions.UnknownVWSErrorPossiblyBadName: Vuforia returns an HTML
42+
page with the text "Oops, an error occurred". This has been seen to
43+
happen when the given name includes a bad character.
3644
"""
37-
result_code = response.json()['result_code']
45+
try:
46+
result_code = response.json()['result_code']
47+
except json.decoder.JSONDecodeError as exc:
48+
assert 'Oops' in response.text
49+
raise UnknownVWSErrorPossiblyBadName() from exc
50+
3851
if result_code == expected_result_code:
3952
return
4053

src/vws/exceptions.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,28 @@
22
Custom exceptions for Vuforia errors.
33
"""
44

5+
import requests
56
from requests import Response
67

78

9+
class UnknownVWSErrorPossiblyBadName(Exception):
10+
"""
11+
Exception raised when VWS returns an HTML page which says "Oops, an error
12+
occurred".
13+
14+
This has been seen to happen when the given name includes a bad character.
15+
"""
16+
17+
18+
class ConnectionErrorPossiblyImageTooLarge(
19+
requests.exceptions.ConnectionError,
20+
):
21+
"""
22+
Exception raised when a ConnectionError is raised from a query. This has
23+
been seen to happen when the given image is too large.
24+
"""
25+
26+
827
class MatchProcessing(Exception):
928
"""
1029
Exception raised when a query is made with an image which matches a target

src/vws/query.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@
1111

1212
from ._authorization import authorization_header, rfc_1123_date
1313
from ._result_codes import raise_for_result_code
14-
from .exceptions import MatchProcessing, MaxNumResultsOutOfRange
14+
from .exceptions import (
15+
ConnectionErrorPossiblyImageTooLarge,
16+
MatchProcessing,
17+
MaxNumResultsOutOfRange,
18+
)
1519
from .include_target_data import CloudRecoIncludeTargetData
1620

1721

@@ -68,6 +72,8 @@ def query(
6872
which was recently added, updated or deleted and Vuforia
6973
returns an error in this case.
7074
~vws.exceptions.ProjectInactive: The project is inactive.
75+
~vws.exceptions.ConnectionErrorPossiblyImageTooLarge: The given
76+
image is too large.
7177
7278
Returns:
7379
An ordered list of target details of matching targets.
@@ -101,12 +107,15 @@ def query(
101107
'Content-Type': content_type_header,
102108
}
103109

104-
response = requests.request(
105-
method=method,
106-
url=urljoin(base=self._base_vwq_url, url=request_path),
107-
headers=headers,
108-
data=content,
109-
)
110+
try:
111+
response = requests.request(
112+
method=method,
113+
url=urljoin(base=self._base_vwq_url, url=request_path),
114+
headers=headers,
115+
data=content,
116+
)
117+
except requests.exceptions.ConnectionError as exc:
118+
raise ConnectionErrorPossiblyImageTooLarge from exc
110119

111120
if 'Integer out of range' in response.text:
112121
raise MaxNumResultsOutOfRange(response=response)

src/vws/vws.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,10 @@ def add_target(
178178
~vws.exceptions.ProjectInactive: The project is inactive.
179179
~vws.exceptions.RequestTimeTooSkewed: There is an error with the
180180
time sent to Vuforia.
181+
~vws.exceptions.UnknownVWSErrorPossiblyBadName: Vuforia returns an
182+
HTML page with the text "Oops, an error occurred". This has
183+
been seen to happen when the given name includes a bad
184+
character.
181185
"""
182186
image_data = image.getvalue()
183187
image_data_encoded = base64.b64encode(image_data).decode('ascii')

tests/test_exceptions.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
TargetStatusNotSuccess,
2626
TargetStatusProcessing,
2727
UnknownTarget,
28+
UnknownVWSErrorPossiblyBadName,
2829
)
2930

3031

@@ -52,6 +53,17 @@ def test_invalid_given_id(vws_client: VWS) -> None:
5253
assert exc.value.response.status_code == codes.NOT_FOUND
5354

5455

56+
def test_add_bad_name(vws_client: VWS, high_quality_image: io.BytesIO) -> None:
57+
"""
58+
When a name with a bad character is given, an
59+
``UnknownVWSErrorPossiblyBadName`` exception is raised.
60+
"""
61+
max_char_value = 65535
62+
bad_name = chr(max_char_value + 1)
63+
with pytest.raises(UnknownVWSErrorPossiblyBadName):
64+
vws_client.add_target(name=bad_name, width=1, image=high_quality_image)
65+
66+
5567
def test_request_quota_reached() -> None:
5668
"""
5769
See https://github.com/adamtheturtle/vws-python/issues/822 for writing
@@ -262,20 +274,14 @@ def test_match_processing(
262274
high_quality_image: io.BytesIO,
263275
) -> None:
264276
"""
265-
A ``MatchProcessing`` exception is raised when a deleted target is matched.
277+
A ``MatchProcessing`` exception is raised when a target in processing is
278+
matched.
266279
"""
267-
target_id = vws_client.add_target(
280+
vws_client.add_target(
268281
name='x',
269282
width=1,
270283
image=high_quality_image,
271284
)
272285
with pytest.raises(MatchProcessing) as exc:
273286
cloud_reco_client.query(image=high_quality_image)
274287
assert exc.value.response.status_code == codes.INTERNAL_SERVER_ERROR
275-
vws_client.wait_for_target_processed(target_id=target_id)
276-
cloud_reco_client.query(image=high_quality_image)
277-
vws_client.delete_target(target_id=target_id)
278-
with pytest.raises(MatchProcessing) as exc:
279-
cloud_reco_client.query(image=high_quality_image)
280-
281-
assert exc.value.response.status_code == codes.INTERNAL_SERVER_ERROR

tests/test_query.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@
1010
from mock_vws.database import VuforiaDatabase
1111

1212
from vws import VWS, CloudRecoService
13-
from vws.exceptions import MaxNumResultsOutOfRange
13+
from vws.exceptions import (
14+
ConnectionErrorPossiblyImageTooLarge,
15+
MaxNumResultsOutOfRange,
16+
)
1417
from vws.include_target_data import CloudRecoIncludeTargetData
1518

1619

@@ -48,6 +51,18 @@ def test_match(
4851
[matching_target] = cloud_reco_client.query(image=high_quality_image)
4952
assert matching_target['target_id'] == target_id
5053

54+
def test_too_large(
55+
self,
56+
cloud_reco_client: CloudRecoService,
57+
png_too_large: io.BytesIO,
58+
) -> None:
59+
"""
60+
A ``ConnectionErrorPossiblyImageTooLarge`` exception is raised if an
61+
image which is too large is given.
62+
"""
63+
with pytest.raises(ConnectionErrorPossiblyImageTooLarge):
64+
cloud_reco_client.query(image=png_too_large)
65+
5166

5267
class TestCustomBaseVWQURL:
5368
"""

0 commit comments

Comments
 (0)