Skip to content

Commit daa817b

Browse files
committed
Add application metadata parameter to add_target
1 parent c35b647 commit daa817b

File tree

3 files changed

+92
-3
lines changed

3 files changed

+92
-3
lines changed

src/vws/exceptions.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,18 @@ def __init__(self, response: Response) -> None:
3333
"""
3434
super().__init__()
3535
self.response = response
36+
37+
38+
class MetadataTooLarge(Exception):
39+
"""
40+
Exception raised when Vuforia returns a response with a result code
41+
'MetadataTooLarge'.
42+
"""
43+
44+
def __init__(self, response: Response) -> None:
45+
"""
46+
Args:
47+
response: The response to a request to Vuforia.
48+
"""
49+
super().__init__()
50+
self.response = response

src/vws/vws.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,19 @@
77
import json
88
from enum import Enum
99
from time import sleep
10-
from typing import Dict, List, Union
10+
from typing import Dict, List, Optional, Union
1111
from urllib.parse import urljoin
1212

1313
import requests
1414
import timeout_decorator
1515
from requests import Response
1616

1717
from vws._authorization import authorization_header, rfc_1123_date
18-
from vws.exceptions import TargetStatusProcessing, UnknownTarget
18+
from vws.exceptions import (
19+
MetadataTooLarge,
20+
TargetStatusProcessing,
21+
UnknownTarget,
22+
)
1923

2024

2125
def _target_api_request(
@@ -107,6 +111,7 @@ class _ResultCodes(Enum):
107111
_EXCEPTIONS = {
108112
_ResultCodes.UNKNOWN_TARGET: UnknownTarget,
109113
_ResultCodes.TARGET_STATUS_PROCESSING: TargetStatusProcessing,
114+
_ResultCodes.METADATA_TOO_LARGE: MetadataTooLarge,
110115
}
111116

112117

@@ -137,6 +142,7 @@ def add_target(
137142
width: Union[int, float],
138143
image: io.BytesIO,
139144
active_flag: bool = True,
145+
application_metadata: Optional[bytes] = None,
140146
) -> str:
141147
"""
142148
Add a target to a Vuforia Web Services database.
@@ -149,18 +155,26 @@ def add_target(
149155
width: The width of the target.
150156
image: The image of the target.
151157
active_flag: Whether or not the target is active for query.
158+
application_metadata: The application metadata of the target.
159+
This will be base64 encoded.
152160
153161
Returns:
154162
The target ID of the new target.
155163
"""
156164
image_data = image.getvalue()
157165
image_data_encoded = base64.b64encode(image_data).decode('ascii')
166+
if application_metadata is None:
167+
metadata_encoded = None
168+
else:
169+
metadata_encoded_str = base64.b64encode(application_metadata)
170+
metadata_encoded = metadata_encoded_str.decode('ascii')
158171

159172
data = {
160173
'name': name,
161174
'width': width,
162175
'image': image_data_encoded,
163176
'active_flag': active_flag,
177+
'application_metadata': metadata_encoded,
164178
}
165179

166180
content = bytes(json.dumps(data), encoding='utf-8')
@@ -174,7 +188,12 @@ def add_target(
174188
base_vws_url=self._base_vws_url,
175189
)
176190

177-
return str(response.json()['target_id'])
191+
result_code = response.json()['result_code']
192+
if _ResultCodes(result_code) == _ResultCodes.TARGET_CREATED:
193+
return str(response.json()['target_id'])
194+
195+
exception = _EXCEPTIONS[_ResultCodes(result_code)]
196+
raise exception(response=response)
178197

179198
def get_target_record(self, target_id: str) -> Dict[str, Union[str, int]]:
180199
"""

tests/test_add_target.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66

77
import pytest
88
from mock_vws import MockVWS
9+
from requests import codes
910

1011
from vws import VWS
12+
from vws.exceptions import MetadataTooLarge
1113

1214

1315
class TestSuccess:
@@ -42,6 +44,8 @@ def test_add_two_targets(
4244
) -> None:
4345
"""
4446
No exception is raised when adding two targets with different names.
47+
48+
This demonstrates that the image seek position is not changed.
4549
"""
4650
client.add_target(name='x', width=1, image=high_quality_image)
4751
client.add_target(name='a', width=1, image=high_quality_image)
@@ -72,6 +76,57 @@ def test_custom_base_url(self, high_quality_image: io.BytesIO) -> None:
7276
)
7377

7478

79+
class TestApplicationMetadata:
80+
"""
81+
Tests for the ``application_metadata`` parameter to ``add_target``.
82+
"""
83+
84+
def test_none(self, client: VWS, high_quality_image: io.BytesIO) -> None:
85+
"""
86+
No exception is raised when ``None`` is given.
87+
"""
88+
client.add_target(
89+
name='x',
90+
width=1,
91+
image=high_quality_image,
92+
application_metadata=None,
93+
)
94+
95+
def test_given(
96+
self,
97+
client: VWS,
98+
high_quality_image: io.BytesIO,
99+
) -> None:
100+
"""
101+
No exception is raised when bytes are given.
102+
"""
103+
client.add_target(
104+
name='x',
105+
width=1,
106+
image=high_quality_image,
107+
application_metadata=b'a',
108+
)
109+
110+
def test_too_large(
111+
self,
112+
client: VWS,
113+
high_quality_image: io.BytesIO,
114+
) -> None:
115+
"""
116+
A ``MetadataTooLarge`` exception is raised if the metadata given is too
117+
large.
118+
"""
119+
with pytest.raises(MetadataTooLarge) as exc:
120+
client.add_target(
121+
name='x',
122+
width=1,
123+
image=high_quality_image,
124+
application_metadata=b'a' * 1024 * 1024,
125+
)
126+
127+
assert exc.value.response.status_code == codes.UNPROCESSABLE_ENTITY
128+
129+
75130
class TestActiveFlag:
76131
"""
77132
Tests for the ``active_flag`` parameter to ``add_target``.

0 commit comments

Comments
 (0)