def target_summary( self, request: _RequestObjectProxy, context: _Context, ) -> str: """ Get a summary report for a target. Fake implementation of https://library.vuforia.com/articles/Solution/How-To-Use-the-Vuforia-Web-Services-API.html#How-To-Retrieve-a-Target-Summary-Report """ try: run_services_validators( request_headers=request.headers, request_body=request.body, request_method=request.method, request_path=request.path, databases=self._target_manager.databases, ) except ValidatorException as exc: context.headers = exc.headers context.status_code = exc.status_code return exc.response_text database = get_database_matching_server_keys( request_headers=request.headers, request_body=request.body, request_method=request.method, request_path=request.path, databases=self._target_manager.databases, ) assert isinstance(database, VuforiaDatabase) target_id = request.path.split('/')[-1] target = database.get_target(target_id=target_id) assert isinstance(database, VuforiaDatabase) date = email.utils.formatdate(None, localtime=False, usegmt=True) body = { 'status': target.status, 'transaction_id': uuid.uuid4().hex, 'result_code': ResultCodes.SUCCESS.value, 'database_name': database.database_name, 'target_name': target.name, 'upload_date': target.upload_date.strftime('%Y-%m-%d'), 'active_flag': target.active_flag, 'tracking_rating': target.tracking_rating, 'total_recos': target.total_recos, 'current_month_recos': target.current_month_recos, 'previous_month_recos': target.previous_month_recos, } body_json = json_dump(body) context.headers = { 'Connection': 'keep-alive', 'Content-Type': 'application/json', 'Content-Length': str(len(body_json)), 'Server': 'nginx', 'Date': date, } return body_json
def add_target( self, request: _RequestObjectProxy, context: _Context, ) -> str: """ Add a target. Fake implementation of https://library.vuforia.com/articles/Solution/How-To-Use-the-Vuforia-Web-Services-API.html#How-To-Add-a-Target """ name = request.json()['name'] database = get_database_matching_server_keys( request_headers=request.headers, request_body=request.body, request_method=request.method, request_path=request.path, databases=self.databases, ) assert isinstance(database, VuforiaDatabase) targets = ( target for target in database.targets if not target.delete_date ) if any(target.name == name for target in targets): context.status_code = HTTPStatus.FORBIDDEN body = { 'transaction_id': uuid.uuid4().hex, 'result_code': ResultCodes.TARGET_NAME_EXIST.value, } return json_dump(body) active_flag = request.json().get('active_flag') if active_flag is None: active_flag = True image = request.json()['image'] decoded = base64.b64decode(image) image_file = io.BytesIO(decoded) new_target = Target( name=request.json()['name'], width=request.json()['width'], image=image_file, active_flag=active_flag, processing_time_seconds=self._processing_time_seconds, application_metadata=request.json().get('application_metadata'), ) database.targets.add(new_target) context.status_code = HTTPStatus.CREATED body = { 'transaction_id': uuid.uuid4().hex, 'result_code': ResultCodes.TARGET_CREATED.value, 'target_id': new_target.target_id, } return json_dump(body)
def target_list( self, request: _RequestObjectProxy, context: _Context, ) -> str: """ Get a list of all targets. Fake implementation of https://library.vuforia.com/articles/Solution/How-To-Use-the-Vuforia-Web-Services-API.html#How-To-Get-a-Target-List-for-a-Cloud-Database """ try: run_services_validators( request_headers=request.headers, request_body=request.body, request_method=request.method, request_path=request.path, databases=self._target_manager.databases, ) except ValidatorException as exc: context.headers = exc.headers context.status_code = exc.status_code return exc.response_text database = get_database_matching_server_keys( request_headers=request.headers, request_body=request.body, request_method=request.method, request_path=request.path, databases=self._target_manager.databases, ) assert isinstance(database, VuforiaDatabase) date = email.utils.formatdate(None, localtime=False, usegmt=True) results = [target.target_id for target in database.not_deleted_targets] body: Dict[str, str | list[str]] = { 'transaction_id': uuid.uuid4().hex, 'result_code': ResultCodes.SUCCESS.value, 'results': results, } body_json = json_dump(body) context.headers = { 'Connection': 'keep-alive', 'Content-Type': 'application/json', 'Server': 'nginx', 'Date': date, 'Content-Length': str(len(body_json)), } return body_json
def _requests_mock_callback( request: _RequestObjectProxy, context: _Context, flask_app: Flask, ) -> str: """ Given a request to the flask app, send an equivalent request to an in memory fake of the flask app and return some key details of the response. :param request: The incoming request to pass onto the flask app. :param context: An object containing the collected known data about this response. :param flask_app: The Flask application to pass requests to. :return: A tuple of status code, response headers and response data from the flask app. """ test_client = flask_app.test_client() # See parameters at # https://werkzeug.palletsprojects.com/en/0.15.x/test/#werkzeug.test.EnvironBuilder cookie_string = request.headers.get('Cookie', '') cookie_list = cookie_string.split(';') cookie_list_no_empty = [item for item in cookie_list if item] request_cookies = [ list(parse_cookie(cookie).items())[0] for cookie in cookie_list_no_empty ] cookies_dict = dict(request_cookies) for key, value in cookies_dict.items(): test_client.set_cookie( server_name='', key=key, value=value, ) environ_builder = werkzeug.test.EnvironBuilder( path=request.path_url, method=request.method, headers=dict(request.headers), data=request.body, ) environ = environ_builder.get_environ() if 'Content-Length' in request.headers: environ['CONTENT_LENGTH'] = request.headers['Content-Length'] response = test_client.open(environ) context.headers = response.headers context.status_code = response.status_code return str(response.data.decode())
def query( self, request: _RequestObjectProxy, context: _Context, ) -> str: """ Perform an image recognition query. """ try: run_query_validators( request_path=request.path, request_headers=request.headers, request_body=request.body, request_method=request.method, databases=self._target_manager.databases, ) except ValidatorException as exc: context.headers = exc.headers context.status_code = exc.status_code return exc.response_text try: response_text = get_query_match_response_text( request_headers=request.headers, request_body=request.body, request_method=request.method, request_path=request.path, databases=self._target_manager.databases, query_processes_deletion_seconds=( self._query_processes_deletion_seconds), query_recognizes_deletion_seconds=( self._query_recognizes_deletion_seconds), ) except ActiveMatchingTargetsDeleteProcessing: deleted_target_matched_exception = DeletedTargetMatched() context.headers = deleted_target_matched_exception.headers context.status_code = deleted_target_matched_exception.status_code return deleted_target_matched_exception.response_text date = email.utils.formatdate(None, localtime=False, usegmt=True) context.headers = { 'Connection': 'keep-alive', 'Content-Type': 'application/json', 'Server': 'nginx', 'Date': date, 'Content-Length': str(len(response_text)), } return response_text
def delete_target( self, request: _RequestObjectProxy, context: _Context, ) -> str: """ Delete a target. Fake implementation of https://library.vuforia.com/articles/Solution/How-To-Use-the-Vuforia-Web-Services-API.html#How-To-Delete-a-Target """ body: Dict[str, str] = {} target = _get_target_from_request( request_path=request.path, databases=self.databases, ) if target.status == TargetStatuses.PROCESSING.value: context.status_code = HTTPStatus.FORBIDDEN body = { 'transaction_id': uuid.uuid4().hex, 'result_code': ResultCodes.TARGET_STATUS_PROCESSING.value, } return json_dump(body) target.delete() body = { 'transaction_id': uuid.uuid4().hex, 'result_code': ResultCodes.SUCCESS.value, } return json_dump(body)
def query( self, request: _RequestObjectProxy, context: _Context, ) -> str: """ Perform an image recognition query. """ try: response_text = get_query_match_response_text( request_headers=request.headers, request_body=request.body, request_method=request.method, request_path=request.path, databases=self.databases, query_processes_deletion_seconds=( self._query_processes_deletion_seconds), query_recognizes_deletion_seconds=( self._query_recognizes_deletion_seconds), ) except ( ActiveMatchingTargetsDeleteProcessing, MatchingTargetsWithProcessingStatus, ): # We return an example 500 response. # Each response given by Vuforia is different. # # Sometimes Vuforia will ignore matching targets with the # processing status, but we choose to: # * Do the most unexpected thing. # * Be consistent with every response. resources_dir = Path(__file__).parent.parent / 'resources' filename = 'match_processing_response.html' match_processing_resp_file = resources_dir / filename context.status_code = HTTPStatus.INTERNAL_SERVER_ERROR cache_control = 'must-revalidate,no-cache,no-store' context.headers['Cache-Control'] = cache_control content_type = 'text/html; charset=ISO-8859-1' context.headers['Content-Type'] = content_type return Path(match_processing_resp_file).read_text() return response_text
def update_target( self, request: _RequestObjectProxy, context: _Context, ) -> str: """ Update a target. Fake implementation of https://library.vuforia.com/articles/Solution/How-To-Use-the-Vuforia-Web-Services-API.html#How-To-Update-a-Target """ try: run_services_validators( request_headers=request.headers, request_body=request.body, request_method=request.method, request_path=request.path, databases=self._target_manager.databases, ) except ValidatorException as exc: context.headers = exc.headers context.status_code = exc.status_code return exc.response_text database = get_database_matching_server_keys( request_headers=request.headers, request_body=request.body, request_method=request.method, request_path=request.path, databases=self._target_manager.databases, ) assert isinstance(database, VuforiaDatabase) target_id = request.path.split('/')[-1] target = database.get_target(target_id=target_id) body: Dict[str, str] = {} date = email.utils.formatdate(None, localtime=False, usegmt=True) if target.status != TargetStatuses.SUCCESS.value: exception = TargetStatusNotSuccess() context.headers = exception.headers context.status_code = exception.status_code return exception.response_text width = request.json().get('width', target.width) name = request.json().get('name', target.name) active_flag = request.json().get('active_flag', target.active_flag) application_metadata = request.json().get( 'application_metadata', target.application_metadata, ) image_value = target.image_value if 'image' in request.json(): image_value = base64.b64decode(request.json()['image']) if 'active_flag' in request.json() and active_flag is None: fail_exception = Fail(status_code=HTTPStatus.BAD_REQUEST) context.headers = fail_exception.headers context.status_code = fail_exception.status_code return fail_exception.response_text if ( 'application_metadata' in request.json() and application_metadata is None ): fail_exception = Fail(status_code=HTTPStatus.BAD_REQUEST) context.headers = fail_exception.headers context.status_code = fail_exception.status_code return fail_exception.response_text # In the real implementation, the tracking rating can stay the same. # However, for demonstration purposes, the tracking rating changes but # when the target is updated. available_values = list(set(range(6)) - {target.tracking_rating}) processed_tracking_rating = random.choice(available_values) gmt = ZoneInfo('GMT') last_modified_date = datetime.datetime.now(tz=gmt) new_target = dataclasses.replace( target, name=name, width=width, active_flag=active_flag, application_metadata=application_metadata, image_value=image_value, processed_tracking_rating=processed_tracking_rating, last_modified_date=last_modified_date, ) database.targets.remove(target) database.targets.add(new_target) body = { 'result_code': ResultCodes.SUCCESS.value, 'transaction_id': uuid.uuid4().hex, } body_json = json_dump(body) context.headers = { 'Connection': 'keep-alive', 'Content-Type': 'application/json', 'Server': 'nginx', 'Date': date, 'Content-Length': str(len(body_json)), } return body_json
def get_duplicates( self, request: _RequestObjectProxy, context: _Context, ) -> str: """ Get targets which may be considered duplicates of a given target. Fake implementation of https://library.vuforia.com/articles/Solution/How-To-Use-the-Vuforia-Web-Services-API.html#How-To-Check-for-Duplicate-Targets """ try: run_services_validators( request_headers=request.headers, request_body=request.body, request_method=request.method, request_path=request.path, databases=self._target_manager.databases, ) except ValidatorException as exc: context.headers = exc.headers context.status_code = exc.status_code return exc.response_text database = get_database_matching_server_keys( request_headers=request.headers, request_body=request.body, request_method=request.method, request_path=request.path, databases=self._target_manager.databases, ) assert isinstance(database, VuforiaDatabase) target_id = request.path.split('/')[-1] target = database.get_target(target_id=target_id) other_targets = set(database.targets) - {target} similar_targets: list[str] = [ other.target_id for other in other_targets if other.image_value == target.image_value and TargetStatuses.FAILED.value not in (target.status, other.status) and TargetStatuses.PROCESSING.value != other.status and other.active_flag ] date = email.utils.formatdate(None, localtime=False, usegmt=True) body = { 'transaction_id': uuid.uuid4().hex, 'result_code': ResultCodes.SUCCESS.value, 'similar_targets': similar_targets, } body_json = json_dump(body) context.headers = { 'Connection': 'keep-alive', 'Content-Type': 'application/json', 'Server': 'nginx', 'Date': date, 'Content-Length': str(len(body_json)), } return body_json
def database_summary( self, request: _RequestObjectProxy, context: _Context, ) -> str: """ Get a database summary report. Fake implementation of https://library.vuforia.com/articles/Solution/How-To-Use-the-Vuforia-Web-Services-API.html#How-To-Get-a-Database-Summary-Report """ try: run_services_validators( request_headers=request.headers, request_body=request.body, request_method=request.method, request_path=request.path, databases=self._target_manager.databases, ) except ValidatorException as exc: context.headers = exc.headers context.status_code = exc.status_code return exc.response_text body: Dict[str, str | int] = {} database = get_database_matching_server_keys( request_headers=request.headers, request_body=request.body, request_method=request.method, request_path=request.path, databases=self._target_manager.databases, ) assert isinstance(database, VuforiaDatabase) date = email.utils.formatdate(None, localtime=False, usegmt=True) body = { 'result_code': ResultCodes.SUCCESS.value, 'transaction_id': uuid.uuid4().hex, 'name': database.database_name, 'active_images': len(database.active_targets), 'inactive_images': len(database.inactive_targets), 'failed_images': len(database.failed_targets), 'target_quota': database.target_quota, 'total_recos': database.total_recos, 'current_month_recos': database.current_month_recos, 'previous_month_recos': database.previous_month_recos, 'processing_images': len(database.processing_targets), 'reco_threshold': database.reco_threshold, 'request_quota': database.request_quota, 'request_usage': 0, } body_json = json_dump(body) context.headers = { 'Connection': 'keep-alive', 'Content-Type': 'application/json', 'Server': 'nginx', 'Date': date, 'Content-Length': str(len(body_json)), } return body_json
def delete_target( self, request: _RequestObjectProxy, context: _Context, ) -> str: """ Delete a target. Fake implementation of https://library.vuforia.com/articles/Solution/How-To-Use-the-Vuforia-Web-Services-API.html#How-To-Delete-a-Target """ try: run_services_validators( request_headers=request.headers, request_body=request.body, request_method=request.method, request_path=request.path, databases=self._target_manager.databases, ) except ValidatorException as exc: context.headers = exc.headers context.status_code = exc.status_code return exc.response_text body: Dict[str, str] = {} database = get_database_matching_server_keys( request_headers=request.headers, request_body=request.body, request_method=request.method, request_path=request.path, databases=self._target_manager.databases, ) assert isinstance(database, VuforiaDatabase) target_id = request.path.split('/')[-1] target = database.get_target(target_id=target_id) if target.status == TargetStatuses.PROCESSING.value: target_processing_exception = TargetStatusProcessing() context.headers = target_processing_exception.headers context.status_code = target_processing_exception.status_code return target_processing_exception.response_text now = datetime.datetime.now(tz=target.upload_date.tzinfo) new_target = dataclasses.replace(target, delete_date=now) database.targets.remove(target) database.targets.add(new_target) date = email.utils.formatdate(None, localtime=False, usegmt=True) body = { 'transaction_id': uuid.uuid4().hex, 'result_code': ResultCodes.SUCCESS.value, } body_json = json_dump(body) context.headers = { 'Connection': 'keep-alive', 'Content-Type': 'application/json', 'Server': 'nginx', 'Date': date, 'Content-Length': str(len(body_json)), } return body_json
def add_target( self, request: _RequestObjectProxy, context: _Context, ) -> str: """ Add a target. Fake implementation of https://library.vuforia.com/articles/Solution/How-To-Use-the-Vuforia-Web-Services-API.html#How-To-Add-a-Target """ try: run_services_validators( request_headers=request.headers, request_body=request.body, request_method=request.method, request_path=request.path, databases=self._target_manager.databases, ) except ValidatorException as exc: context.headers = exc.headers context.status_code = exc.status_code return exc.response_text database = get_database_matching_server_keys( request_headers=request.headers, request_body=request.body, request_method=request.method, request_path=request.path, databases=self._target_manager.databases, ) assert isinstance(database, VuforiaDatabase) given_active_flag = request.json().get('active_flag') active_flag = { None: True, True: True, False: False, }[given_active_flag] application_metadata = request.json().get('application_metadata') new_target = Target( name=request.json()['name'], width=request.json()['width'], image_value=base64.b64decode(request.json()['image']), active_flag=active_flag, processing_time_seconds=self._processing_time_seconds, application_metadata=application_metadata, ) database.targets.add(new_target) date = email.utils.formatdate(None, localtime=False, usegmt=True) context.status_code = HTTPStatus.CREATED body = { 'transaction_id': uuid.uuid4().hex, 'result_code': ResultCodes.TARGET_CREATED.value, 'target_id': new_target.target_id, } body_json = json_dump(body) context.headers = { 'Connection': 'keep-alive', 'Content-Type': 'application/json', 'Server': 'nginx', 'Date': date, 'Content-Length': str(len(body_json)), } return body_json
def update_target( self, request: _RequestObjectProxy, context: _Context, ) -> str: """ Update a target. Fake implementation of https://library.vuforia.com/articles/Solution/How-To-Use-the-Vuforia-Web-Services-API.html#How-To-Update-a-Target """ target = _get_target_from_request( request_path=request.path, databases=self.databases, ) body: Dict[str, str] = {} database = get_database_matching_server_keys( request_headers=request.headers, request_body=request.body, request_method=request.method, request_path=request.path, databases=self.databases, ) assert isinstance(database, VuforiaDatabase) if target.status != TargetStatuses.SUCCESS.value: context.status_code = HTTPStatus.FORBIDDEN body = { 'transaction_id': uuid.uuid4().hex, 'result_code': ResultCodes.TARGET_STATUS_NOT_SUCCESS.value, } return json_dump(body) if 'width' in request.json(): target.width = request.json()['width'] if 'active_flag' in request.json(): active_flag = request.json()['active_flag'] if active_flag is None: body = { 'transaction_id': uuid.uuid4().hex, 'result_code': ResultCodes.FAIL.value, } context.status_code = HTTPStatus.BAD_REQUEST return json_dump(body) target.active_flag = active_flag if 'application_metadata' in request.json(): if request.json()['application_metadata'] is None: body = { 'transaction_id': uuid.uuid4().hex, 'result_code': ResultCodes.FAIL.value, } context.status_code = HTTPStatus.BAD_REQUEST return json_dump(body) application_metadata = request.json()['application_metadata'] target.application_metadata = application_metadata if 'name' in request.json(): name = request.json()['name'] other_targets = set(database.targets) - set([target]) if any( other.name == name for other in other_targets if not other.delete_date ): context.status_code = HTTPStatus.FORBIDDEN body = { 'transaction_id': uuid.uuid4().hex, 'result_code': ResultCodes.TARGET_NAME_EXIST.value, } return json_dump(body) target.name = name if 'image' in request.json(): image = request.json()['image'] decoded = base64.b64decode(image) image_file = io.BytesIO(decoded) target.image = image_file # In the real implementation, the tracking rating can stay the same. # However, for demonstration purposes, the tracking rating changes but # when the target is updated. available_values = list(set(range(6)) - set([target.tracking_rating])) target.processed_tracking_rating = random.choice(available_values) gmt = ZoneInfo('GMT') now = datetime.datetime.now(tz=gmt) target.last_modified_date = now body = { 'result_code': ResultCodes.SUCCESS.value, 'transaction_id': uuid.uuid4().hex, } return json_dump(body)