|
23 | 23 | DateRangeError, |
24 | 24 | FailError, |
25 | 25 | ImageTooLargeError, |
| 26 | + InvalidAcceptHeaderError, |
| 27 | + InvalidInstanceIdError, |
26 | 28 | MetadataTooLargeError, |
27 | 29 | ProjectHasNoAPIAccessError, |
28 | 30 | ProjectInactiveError, |
|
44 | 46 | TargetSummaryReport, |
45 | 47 | ) |
46 | 48 | from vws.response import Response |
| 49 | +from vws.vumark_accept import VuMarkAccept |
47 | 50 |
|
48 | 51 | _ImageType = io.BytesIO | BinaryIO |
49 | 52 |
|
@@ -700,3 +703,116 @@ def update_target( |
700 | 703 | expected_result_code="Success", |
701 | 704 | content_type="application/json", |
702 | 705 | ) |
| 706 | + |
| 707 | + def generate_vumark_instance( |
| 708 | + self, |
| 709 | + *, |
| 710 | + target_id: str, |
| 711 | + instance_id: str, |
| 712 | + accept: VuMarkAccept = VuMarkAccept.PNG, |
| 713 | + ) -> bytes: |
| 714 | + """Generate a VuMark instance image. |
| 715 | +
|
| 716 | + See |
| 717 | + https://developer.vuforia.com/library/vuforia-engine/web-api/vumark-generation-web-api/ |
| 718 | + for parameter details. |
| 719 | +
|
| 720 | + Args: |
| 721 | + target_id: The ID of the VuMark target. |
| 722 | + instance_id: The instance ID to encode in the VuMark. |
| 723 | + accept: The image format to return. |
| 724 | +
|
| 725 | + Returns: |
| 726 | + The VuMark instance image bytes. |
| 727 | +
|
| 728 | + Raises: |
| 729 | + ~vws.exceptions.vws_exceptions.AuthenticationFailureError: The |
| 730 | + secret key is not correct. |
| 731 | + ~vws.exceptions.vws_exceptions.FailError: There was an error with |
| 732 | + the request. For example, the given access key does not match a |
| 733 | + known database. |
| 734 | + ~vws.exceptions.vws_exceptions.InvalidAcceptHeaderError: The |
| 735 | + Accept header value is not supported. |
| 736 | + ~vws.exceptions.vws_exceptions.InvalidInstanceIdError: The |
| 737 | + instance ID is invalid. For example, it may be empty. |
| 738 | + ~vws.exceptions.vws_exceptions.RequestTimeTooSkewedError: There is |
| 739 | + an error with the time sent to Vuforia. |
| 740 | + ~vws.exceptions.vws_exceptions.TargetStatusNotSuccessError: The |
| 741 | + target is not in the success state. |
| 742 | + ~vws.exceptions.vws_exceptions.UnknownTargetError: The given target |
| 743 | + ID does not match a target in the database. |
| 744 | + ~vws.exceptions.custom_exceptions.ServerError: There is an error |
| 745 | + with Vuforia's servers. |
| 746 | + ~vws.exceptions.vws_exceptions.TooManyRequestsError: Vuforia is |
| 747 | + rate limiting access. |
| 748 | + """ |
| 749 | + request_path = f"/targets/{target_id}/instances" |
| 750 | + content_type = "application/json" |
| 751 | + request_data = json.dumps(obj={"instance_id": instance_id}).encode( |
| 752 | + encoding="utf-8", |
| 753 | + ) |
| 754 | + date_string = rfc_1123_date() |
| 755 | + |
| 756 | + signature_string = authorization_header( |
| 757 | + access_key=self._server_access_key, |
| 758 | + secret_key=self._server_secret_key, |
| 759 | + method=HTTPMethod.POST, |
| 760 | + content=request_data, |
| 761 | + content_type=content_type, |
| 762 | + date=date_string, |
| 763 | + request_path=request_path, |
| 764 | + ) |
| 765 | + |
| 766 | + headers = { |
| 767 | + "Authorization": signature_string, |
| 768 | + "Date": date_string, |
| 769 | + "Content-Type": content_type, |
| 770 | + "Accept": accept, |
| 771 | + } |
| 772 | + |
| 773 | + url = urljoin(base=self._base_vws_url, url=request_path) |
| 774 | + |
| 775 | + requests_response = requests.request( |
| 776 | + method=HTTPMethod.POST, |
| 777 | + url=url, |
| 778 | + headers=headers, |
| 779 | + data=request_data, |
| 780 | + timeout=self._request_timeout_seconds, |
| 781 | + ) |
| 782 | + |
| 783 | + if requests_response.status_code == HTTPStatus.OK: |
| 784 | + return bytes(requests_response.content) |
| 785 | + |
| 786 | + response = Response( |
| 787 | + text=requests_response.text, |
| 788 | + url=requests_response.url, |
| 789 | + status_code=requests_response.status_code, |
| 790 | + headers=dict(requests_response.headers), |
| 791 | + request_body=requests_response.request.body, |
| 792 | + tell_position=requests_response.raw.tell(), |
| 793 | + ) |
| 794 | + |
| 795 | + if ( |
| 796 | + requests_response.status_code == HTTPStatus.TOO_MANY_REQUESTS |
| 797 | + ): # pragma: no cover |
| 798 | + raise TooManyRequestsError(response=response) |
| 799 | + |
| 800 | + if ( |
| 801 | + requests_response.status_code >= HTTPStatus.INTERNAL_SERVER_ERROR |
| 802 | + ): # pragma: no cover |
| 803 | + raise ServerError(response=response) |
| 804 | + |
| 805 | + result_code = json.loads(s=response.text)["result_code"] |
| 806 | + |
| 807 | + exception = { |
| 808 | + "AuthenticationFailure": AuthenticationFailureError, |
| 809 | + "DateRangeError": DateRangeError, |
| 810 | + "Fail": FailError, |
| 811 | + "InvalidAcceptHeader": InvalidAcceptHeaderError, |
| 812 | + "InvalidInstanceId": InvalidInstanceIdError, |
| 813 | + "RequestTimeTooSkewed": RequestTimeTooSkewedError, |
| 814 | + "TargetStatusNotSuccess": TargetStatusNotSuccessError, |
| 815 | + "UnknownTarget": UnknownTargetError, |
| 816 | + }[result_code] |
| 817 | + |
| 818 | + raise exception(response=response) |
0 commit comments