Skip to content

Commit 6960ef2

Browse files
Merge pull request #900 from adamtheturtle/update
Add Update option
2 parents 2080c9b + ba8457c commit 6960ef2

File tree

4 files changed

+161
-0
lines changed

4 files changed

+161
-0
lines changed

src/vws/exceptions.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,21 @@ def response(self) -> Response:
203203
return self._response
204204

205205

206+
class TargetStatusNotSuccess(Exception):
207+
"""
208+
Exception raised when Vuforia returns a response with a result code
209+
'TargetStatusNotSuccess'.
210+
"""
211+
212+
def __init__(self, response: Response) -> None:
213+
"""
214+
Args:
215+
response: The response to a request to Vuforia.
216+
"""
217+
super().__init__()
218+
self.response = response
219+
220+
206221
class TargetProcessingTimeout(Exception):
207222
"""
208223
Exception raised when waiting for a target to be processed times out.

src/vws/vws.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
ProjectInactive,
2424
TargetNameExist,
2525
TargetProcessingTimeout,
26+
TargetStatusNotSuccess,
2627
TargetStatusProcessing,
2728
UnknownTarget,
2829
)
@@ -111,6 +112,7 @@ def _raise_for_result_code(
111112
'ProjectInactive': ProjectInactive,
112113
'TargetNameExist': TargetNameExist,
113114
'TargetStatusProcessing': TargetStatusProcessing,
115+
'TargetStatusNotSuccess': TargetStatusNotSuccess,
114116
'UnknownTarget': UnknownTarget,
115117
}[result_code]
116118

@@ -490,3 +492,73 @@ def get_duplicate_targets(self, target_id: str) -> List[str]:
490492
)
491493

492494
return list(response.json()['similar_targets'])
495+
496+
def update_target(
497+
self,
498+
target_id: str,
499+
name: Optional[str] = None,
500+
width: Optional[Union[int, float]] = None,
501+
image: Optional[io.BytesIO] = None,
502+
active_flag: Optional[bool] = None,
503+
application_metadata: Optional[bytes] = None,
504+
) -> None:
505+
"""
506+
Add a target to a Vuforia Web Services database.
507+
508+
See
509+
https://library.vuforia.com/articles/Solution/How-To-Use-the-Vuforia-Web-Services-API#How-To-Add-a-Target
510+
for parameter details.
511+
512+
Args:
513+
target_id: The ID of the target to get details of.
514+
name: The name of the target.
515+
width: The width of the target.
516+
image: The image of the target.
517+
active_flag: Whether or not the target is active for query.
518+
application_metadata: The application metadata of the target.
519+
This will be base64 encoded.
520+
521+
Raises:
522+
~vws.exceptions.AuthenticationFailure: The secret key is not
523+
correct.
524+
~vws.exceptions.BadImage: There is a problem with the given image.
525+
For example, it must be a JPEG or PNG file in the grayscale or
526+
RGB color space.
527+
~vws.exceptions.Fail: There was an error with the request. For
528+
example, the given access key does not match a known database.
529+
~vws.exceptions.MetadataTooLarge: The given metadata is too large.
530+
The maximum size is 1 MB of data when Base64 encoded.
531+
~vws.exceptions.ImageTooLarge: The given image is too large.
532+
~vws.exceptions.TargetNameExist: A target with the given ``name``
533+
already exists.
534+
~vws.exceptions.ProjectInactive: The project is inactive.
535+
"""
536+
data: Dict[str, Union[str, bool, float, int]] = {}
537+
538+
if name is not None:
539+
data['name'] = name
540+
541+
if width is not None:
542+
data['width'] = width
543+
544+
if image is not None:
545+
image_data = image.getvalue()
546+
image_data_encoded = base64.b64encode(image_data).decode('ascii')
547+
data['image'] = image_data_encoded
548+
549+
if active_flag is not None:
550+
data['active_flag'] = active_flag
551+
552+
if application_metadata is not None:
553+
metadata_encoded_str = base64.b64encode(application_metadata)
554+
metadata_encoded = metadata_encoded_str.decode('ascii')
555+
data['application_metadata'] = metadata_encoded
556+
557+
content = bytes(json.dumps(data), encoding='utf-8')
558+
559+
self._make_request(
560+
method='PUT',
561+
content=content,
562+
request_path=f'/targets/{target_id}',
563+
expected_result_code='Success',
564+
)

tests/test_exceptions.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
MetadataTooLarge,
2222
ProjectInactive,
2323
TargetNameExist,
24+
TargetStatusNotSuccess,
2425
TargetStatusProcessing,
2526
UnknownTarget,
2627
)
@@ -225,3 +226,23 @@ def test_authentication_failure(high_quality_image: io.BytesIO) -> None:
225226
)
226227

227228
assert exc.value.response.status_code == codes.UNAUTHORIZED
229+
230+
231+
def test_target_status_not_success(
232+
client: VWS,
233+
high_quality_image: io.BytesIO,
234+
) -> None:
235+
"""
236+
A ``TargetStatusNotSuccess`` exception is raised when updating a target
237+
which has a status which is not "Success".
238+
"""
239+
target_id = client.add_target(
240+
name='x',
241+
width=1,
242+
image=high_quality_image,
243+
)
244+
245+
with pytest.raises(TargetStatusNotSuccess) as exc:
246+
client.update_target(target_id=target_id)
247+
248+
assert exc.value.response.status_code == codes.FORBIDDEN

tests/test_vws.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,3 +429,56 @@ def test_get_duplicate_targets(
429429
client.wait_for_target_processed(target_id=similar_target_id)
430430
duplicates = client.get_duplicate_targets(target_id=target_id)
431431
assert duplicates == [similar_target_id]
432+
433+
434+
class TestUpdateTarget:
435+
"""
436+
Tests for updating a target.
437+
"""
438+
439+
def test_update_target(
440+
self,
441+
client: VWS,
442+
high_quality_image: io.BytesIO,
443+
) -> None:
444+
"""
445+
It is possible to update a target.
446+
"""
447+
target_id = client.add_target(
448+
name='x',
449+
width=1,
450+
image=high_quality_image,
451+
active_flag=True,
452+
)
453+
client.wait_for_target_processed(target_id=target_id)
454+
client.update_target(
455+
target_id=target_id,
456+
name='x2',
457+
width=2,
458+
active_flag=False,
459+
# These will be tested in
460+
# https://github.com/adamtheturtle/vws-python/issues/809.
461+
image=high_quality_image,
462+
application_metadata=b'a',
463+
)
464+
465+
target_details = client.get_target_record(target_id=target_id)
466+
assert target_details['name'] == 'x2'
467+
assert target_details['width'] == 2
468+
assert not target_details['active_flag']
469+
470+
def test_no_fields_given(
471+
self,
472+
client: VWS,
473+
high_quality_image: io.BytesIO,
474+
) -> None:
475+
"""
476+
It is possible to give no update fields.
477+
"""
478+
target_id = client.add_target(
479+
name='x',
480+
width=1,
481+
image=high_quality_image,
482+
)
483+
client.wait_for_target_processed(target_id=target_id)
484+
client.update_target(target_id=target_id)

0 commit comments

Comments
 (0)