From 3f1e46408ce25f4c3f425eba46171a6b2c80309d Mon Sep 17 00:00:00 2001 From: Adam Dangoor Date: Tue, 8 Sep 2026 10:28:01 +0100 Subject: [PATCH 1/4] Use the pyrefly all preset --- admin/create_secrets_files.py | 20 +-- pyproject.toml | 2 +- src/mock_vws/_flask_server/target_manager.py | 44 +++--- src/mock_vws/_flask_server/vwq.py | 2 +- src/mock_vws/_flask_server/vws.py | 58 +++---- .../_httpx2_mock_server/decorators.py | 10 +- src/mock_vws/_matching.py | 2 +- src/mock_vws/_mock_common.py | 2 +- src/mock_vws/_model_target_web_api.py | 128 +++++++++------- src/mock_vws/_query_tools.py | 6 +- .../_query_validators/auth_validators.py | 4 +- .../content_length_validators.py | 2 +- .../content_type_validators.py | 2 +- .../_query_validators/date_validators.py | 4 +- .../_query_validators/fields_validators.py | 2 +- src/mock_vws/_reco_counts_web_api.py | 10 +- .../mock_web_services_api.py | 44 +++--- src/mock_vws/_respx_mock_server/decorators.py | 10 +- .../active_flag_validators.py | 4 +- .../_services_validators/auth_validators.py | 2 +- .../content_length_validators.py | 2 +- .../content_type_validators.py | 2 +- .../_services_validators/date_validators.py | 2 +- .../_services_validators/image_validators.py | 4 +- .../_services_validators/json_validators.py | 4 +- .../metadata_validators.py | 6 +- .../_services_validators/name_validators.py | 6 +- .../project_state_validators.py | 3 +- .../request_rate_limiter.py | 6 +- src/mock_vws/_services_validators/routes.py | 1 + .../_services_validators/target_validators.py | 2 +- .../_services_validators/width_validators.py | 2 +- src/mock_vws/database.py | 4 +- src/mock_vws/decorators.py | 12 +- src/mock_vws/model_target.py | 14 +- src/mock_vws/target.py | 12 +- tests/conftest.py | 4 +- .../model_target_prepared_requests.py | 4 +- tests/mock_vws/fixtures/prepared_requests.py | 2 +- tests/mock_vws/fixtures/vuforia_backends.py | 34 ++--- tests/mock_vws/test_add_target.py | 80 +++++----- tests/mock_vws/test_authorization_header.py | 18 +-- tests/mock_vws/test_content_length.py | 10 +- tests/mock_vws/test_database_summary.py | 10 +- tests/mock_vws/test_date_header.py | 2 +- tests/mock_vws/test_delete_target.py | 2 +- tests/mock_vws/test_docker.py | 40 ++--- tests/mock_vws/test_flask_app_usage.py | 122 +++++++++------ tests/mock_vws/test_get_duplicates.py | 2 +- tests/mock_vws/test_get_target.py | 4 +- tests/mock_vws/test_httpx2_mock_usage.py | 22 +-- tests/mock_vws/test_invalid_json.py | 4 +- .../test_model_target_failure_response.py | 21 +-- .../test_model_target_generation_failure.py | 14 +- .../test_model_target_generation_warning.py | 14 +- tests/mock_vws/test_model_target_retries.py | 14 +- .../test_model_target_training_allowance.py | 2 +- tests/mock_vws/test_model_target_web_api.py | 66 ++++---- tests/mock_vws/test_query.py | 28 ++-- tests/mock_vws/test_reco_counts_report.py | 14 +- tests/mock_vws/test_requests_mock_usage.py | 144 +++++++++--------- tests/mock_vws/test_respx_mock_usage.py | 10 +- tests/mock_vws/test_target_list.py | 4 +- tests/mock_vws/test_target_summary.py | 2 +- tests/mock_vws/test_unexpected_json.py | 4 +- tests/mock_vws/test_update_target.py | 22 +-- tests/mock_vws/test_vumark_generation_api.py | 6 +- tests/mock_vws/utils/__init__.py | 4 +- tests/mock_vws/utils/assertions.py | 16 +- 69 files changed, 625 insertions(+), 560 deletions(-) diff --git a/admin/create_secrets_files.py b/admin/create_secrets_files.py index 4ad3e3cd8..265c27c3e 100644 --- a/admin/create_secrets_files.py +++ b/admin/create_secrets_files.py @@ -133,7 +133,7 @@ def _create_and_get_vumark_target_id( vumark_template_name: str, ) -> str: """Upload a VuMark template and get its target ID.""" - vws_web_tools.upload_vumark_template( + _ = vws_web_tools.upload_vumark_template( driver=driver, database_name=vumark_database_name, svg_file_path=VUMARK_TEMPLATE_SVG_FILE_PATH, @@ -292,11 +292,11 @@ def main() -> None: files_to_create = [file for file in required_files if not file.exists()] driver: WebDriver | None = None - while files_to_create: + while bool(files_to_create): if driver is None: driver = vws_web_tools.create_chrome_driver() file = files_to_create[-1] - sys.stdout.write(f"Creating database {file.name}\n") + _ = sys.stdout.write(f"Creating database {file.name}\n") ( cloud_license_name, cloud_database_name, @@ -305,7 +305,7 @@ def main() -> None: ) = _create_vuforia_resource_names() try: - sys.stdout.write("Creating cloud database details\n") + _ = sys.stdout.write("Creating cloud database details\n") cloud_database_details = _create_and_get_cloud_database_details( driver=driver, email_address=email_address, @@ -313,19 +313,19 @@ def main() -> None: cloud_license_name=cloud_license_name, cloud_database_name=cloud_database_name, ) - sys.stdout.write("Creating VuMark database details\n") + _ = sys.stdout.write("Creating VuMark database details\n") vumark_details = _create_and_get_vumark_details( driver=driver, vumark_database_name=vumark_database_name, ) - sys.stdout.write("Creating VuMark target\n") + _ = sys.stdout.write("Creating VuMark target\n") vumark_target_id = _create_and_get_vumark_target_id( driver=driver, vumark_database_name=vumark_database_name, vumark_template_name=vumark_template_name, ) except TimeoutException: - sys.stderr.write("Timed out during database setup\n") + _ = sys.stderr.write("Timed out during database setup\n") driver.quit() driver = None continue @@ -343,9 +343,9 @@ def main() -> None: model_target_username=email_address, model_target_password=password, ) - file.write_text(data=file_contents) - sys.stdout.write(f"Created database {file.name}\n") - files_to_create.pop() + _ = file.write_text(data=file_contents) + _ = sys.stdout.write(f"Created database {file.name}\n") + _ = files_to_create.pop() if __name__ == "__main__": diff --git a/pyproject.toml b/pyproject.toml index 6048ec5fd..894c5d2e6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -449,7 +449,7 @@ search_path = [ "src", ] errors.non-exhaustive-match = "error" -preset = "strict" +preset = "all" [tool.pyright] typeCheckingMode = "strict" diff --git a/src/mock_vws/_flask_server/target_manager.py b/src/mock_vws/_flask_server/target_manager.py index 3471b4bcd..5b3b100f3 100644 --- a/src/mock_vws/_flask_server/target_manager.py +++ b/src/mock_vws/_flask_server/target_manager.py @@ -687,9 +687,9 @@ def put_oauth2_client_credential() -> Response: """Add or replace an OAuth2 client credential.""" value = json.loads(s=request.data) credential = OAuth2ClientCredential( - client_id=value["client_id"], - client_secret=value["client_secret"], - scopes=tuple(value["scopes"]), + client_id=value["client_id"], # pyrefly: ignore [unknown-argument-type] + client_secret=value["client_secret"], # pyrefly: ignore [unknown-argument-type] + scopes=tuple(value["scopes"]), # pyrefly: ignore [unknown-argument-type] ) TARGET_MANAGER.add_oauth2_client_credential(credential=credential) return Response(response="", status=HTTPStatus.NO_CONTENT) @@ -722,16 +722,16 @@ def create_target(database_name: str) -> Response: request_json = json.loads(s=request.data) settings = TargetManagerSettings.model_validate(obj={}) - image_bytes = base64.b64decode(s=request_json["image_base64"]) + image_bytes = base64.b64decode(s=request_json["image_base64"]) # pyrefly: ignore [unknown-argument-type] target_tracking_rater = settings.target_rater.to_target_rater() target = ImageTarget( - name=request_json["name"], - width=request_json["width"], + name=request_json["name"], # pyrefly: ignore [unknown-argument-type] + width=request_json["width"], # pyrefly: ignore [unknown-argument-type] image_value=image_bytes, - active_flag=request_json["active_flag"], - processing_time_seconds=request_json["processing_time_seconds"], - application_metadata=request_json["application_metadata"], - target_id=request_json["target_id"], + active_flag=request_json["active_flag"], # pyrefly: ignore [unknown-argument-type] + processing_time_seconds=request_json["processing_time_seconds"], # pyrefly: ignore [unknown-argument-type] + application_metadata=request_json["application_metadata"], # pyrefly: ignore [unknown-argument-type] + target_id=request_json["target_id"], # pyrefly: ignore [unknown-argument-type] target_tracking_rater=target_tracking_rater, ) with TARGET_MANAGER.lock: @@ -816,26 +816,26 @@ def update_target(database_name: str, target_id: str) -> Response: target = database.get_target(target_id=target_id) - name = request_json.get("name", target.name) - active_flag = request_json.get("active_flag", target.active_flag) + name = request_json.get("name", target.name) # pyrefly: ignore [unknown-variable-type] + active_flag = request_json.get("active_flag", target.active_flag) # pyrefly: ignore [unknown-variable-type] gmt = ZoneInfo(key="GMT") last_modified_date = datetime.datetime.now(tz=gmt) - width = request_json.get("width", target.width) - application_metadata = request_json.get( + width = request_json.get("width", target.width) # pyrefly: ignore [unknown-variable-type] + application_metadata = request_json.get( # pyrefly: ignore [unknown-variable-type] "application_metadata", target.application_metadata, ) image_value = target.image_value if "image" in request_json: - image_value = base64.b64decode(s=request_json["image"]) + image_value = base64.b64decode(s=request_json["image"]) # pyrefly: ignore [unknown-argument-type] new_target = copy.replace( target, - name=name, - width=width, - active_flag=active_flag, - application_metadata=application_metadata, + name=name, # pyrefly: ignore [unknown-argument-type] + width=width, # pyrefly: ignore [unknown-argument-type] + active_flag=active_flag, # pyrefly: ignore [unknown-argument-type] + application_metadata=application_metadata, # pyrefly: ignore [unknown-argument-type] image_value=image_value, last_modified_date=last_modified_date, ) @@ -891,15 +891,15 @@ def set_target_recognition_counts( new_target = copy.replace( target, - current_month_recos=request_json.get( + current_month_recos=request_json.get( # pyrefly: ignore [unknown-argument-type] "current_month_recos", target.current_month_recos, ), - previous_month_recos=request_json.get( + previous_month_recos=request_json.get( # pyrefly: ignore [unknown-argument-type] "previous_month_recos", target.previous_month_recos, ), - total_recos=request_json.get("total_recos", target.total_recos), + total_recos=request_json.get("total_recos", target.total_recos), # pyrefly: ignore [unknown-argument-type] ) database.targets.remove(target) diff --git a/src/mock_vws/_flask_server/vwq.py b/src/mock_vws/_flask_server/vwq.py index a87f48307..c13075d6f 100644 --- a/src/mock_vws/_flask_server/vwq.py +++ b/src/mock_vws/_flask_server/vwq.py @@ -95,7 +95,7 @@ def set_terminate_wsgi_input() -> None: """ try: set_terminate_wsgi_input_true = ( - CLOUDRECO_FLASK_APP.config["VWS_MOCK_TERMINATE_WSGI_INPUT"] is True + CLOUDRECO_FLASK_APP.config["VWS_MOCK_TERMINATE_WSGI_INPUT"] is True # pyrefly: ignore [unknown-variable-type] ) except KeyError: set_terminate_wsgi_input_true = False diff --git a/src/mock_vws/_flask_server/vws.py b/src/mock_vws/_flask_server/vws.py index 5ad802dcb..a1ab8dc62 100644 --- a/src/mock_vws/_flask_server/vws.py +++ b/src/mock_vws/_flask_server/vws.py @@ -210,7 +210,7 @@ def add_model_target_dataset( ) -> None: """Add a Model Target dataset.""" timeout_seconds = 30 - requests.post( + _ = requests.post( url=self._datasets_url, json=model_target_dataset.to_dict(), timeout=timeout_seconds, @@ -219,7 +219,7 @@ def add_model_target_dataset( def remove_model_target_dataset(self, dataset_uuid: str) -> None: """Remove a Model Target dataset.""" timeout_seconds = 30 - requests.delete( + _ = requests.delete( url=f"{self._datasets_url}/{dataset_uuid}", timeout=timeout_seconds, ) @@ -230,9 +230,9 @@ def oauth2_client_credentials(self) -> dict[str, OAuth2ClientCredential]: response = requests.get(url=self._credentials_url, timeout=30) credentials = ( OAuth2ClientCredential( - client_id=value["client_id"], - client_secret=value["client_secret"], - scopes=tuple(value["scopes"]), + client_id=value["client_id"], # pyrefly: ignore [unknown-argument-type] + client_secret=value["client_secret"], # pyrefly: ignore [unknown-argument-type] + scopes=tuple(value["scopes"]), # pyrefly: ignore [unknown-argument-type] ) for value in response.json() ) @@ -243,7 +243,7 @@ def add_oauth2_client_credential( credential: OAuth2ClientCredential, ) -> None: """Add or replace an OAuth2 client credential.""" - requests.post( + _ = requests.post( url=self._credentials_url, json={ "client_id": credential.client_id, @@ -255,7 +255,7 @@ def add_oauth2_client_credential( def remove_oauth2_client_credential(self, client_id: str) -> None: """Remove an OAuth2 client credential.""" - requests.delete( + _ = requests.delete( url=f"{self._credentials_url}/{client_id}", timeout=30, ) @@ -332,7 +332,7 @@ def set_terminate_wsgi_input() -> None: """ try: set_terminate_wsgi_input_true = ( - VWS_FLASK_APP.config["VWS_MOCK_TERMINATE_WSGI_INPUT"] is True + VWS_FLASK_APP.config["VWS_MOCK_TERMINATE_WSGI_INPUT"] is True # pyrefly: ignore [unknown-variable-type] ) except KeyError: set_terminate_wsgi_input_true = False @@ -367,7 +367,7 @@ def validate_request() -> None: or request.path.startswith("/reports/recoCounts/") ): return - run_services_validators( + _ = run_services_validators( request_headers=dict(request.headers), request_body=request.data, request_method=request.method, @@ -746,8 +746,8 @@ def add_target() -> Response: # We do not use ``request.get_json(force=True)`` because this only works # when the content type is given as ``application/json``. request_json = json.loads(s=request.data) - name = request_json["name"] - active_flag = request_json.get("active_flag") + name = request_json["name"] # pyrefly: ignore [unknown-variable-type] + active_flag = request_json.get("active_flag") # pyrefly: ignore [unknown-variable-type] if active_flag is None: active_flag = True @@ -755,18 +755,18 @@ def add_target() -> Response: target_tracking_rater = HardcodedTargetTrackingRater(rating=1) new_target = ImageTarget( - name=name, - width=request_json["width"], - image_value=base64.b64decode(s=request_json["image"]), - active_flag=active_flag, + name=name, # pyrefly: ignore [unknown-argument-type] + width=request_json["width"], # pyrefly: ignore [unknown-argument-type] + image_value=base64.b64decode(s=request_json["image"]), # pyrefly: ignore [unknown-argument-type] + active_flag=active_flag, # pyrefly: ignore [unknown-argument-type] processing_time_seconds=settings.processing_time_seconds, - application_metadata=request_json.get("application_metadata"), + application_metadata=request_json.get("application_metadata"), # pyrefly: ignore [unknown-argument-type] target_tracking_rater=target_tracking_rater, ) databases_url = f"{settings.target_manager_base_url}/cloud_databases" timeout_seconds = 30 - requests.post( + _ = requests.post( url=f"{databases_url}/{database.database_name}/targets", json=new_target.to_dict(), timeout=timeout_seconds, @@ -885,7 +885,7 @@ def delete_target(target_id: str) -> Response: raise TargetStatusProcessingError databases_url = f"{settings.target_manager_base_url}/cloud_databases" - requests.delete( + _ = requests.delete( url=f"{databases_url}/{database.database_name}/targets/{target_id}", timeout=30, ) @@ -929,7 +929,7 @@ def generate_vumark_instance(target_id: str) -> Response: *cloud_databases, *vumark_databases, ] - run_services_validators( + _ = run_services_validators( request_headers=dict(request.headers), request_body=request.data, request_method=request.method, @@ -1234,10 +1234,10 @@ def update_target(target_id: str) -> Response: update_values: dict[str, str | int | float | bool | None] = {} if "width" in request_json: - update_values["width"] = request_json["width"] + update_values["width"] = request_json["width"] # pyrefly: ignore [unknown-argument-type] if "active_flag" in request_json: - active_flag = request_json["active_flag"] + active_flag = request_json["active_flag"] # pyrefly: ignore [unknown-variable-type] if active_flag is None: _LOGGER.warning( msg=( @@ -1246,10 +1246,10 @@ def update_target(target_id: str) -> Response: ), ) raise FailError(status_code=HTTPStatus.BAD_REQUEST) - update_values["active_flag"] = active_flag + update_values["active_flag"] = active_flag # pyrefly: ignore [unknown-argument-type] if "application_metadata" in request_json: - application_metadata = request_json["application_metadata"] + application_metadata = request_json["application_metadata"] # pyrefly: ignore [unknown-variable-type] if application_metadata is None: _LOGGER.warning( msg=( @@ -1258,21 +1258,21 @@ def update_target(target_id: str) -> Response: ), ) raise FailError(status_code=HTTPStatus.BAD_REQUEST) - update_values["application_metadata"] = application_metadata + update_values["application_metadata"] = application_metadata # pyrefly: ignore [unknown-argument-type] if "name" in request_json: - name = request_json["name"] - update_values["name"] = name + name = request_json["name"] # pyrefly: ignore [unknown-variable-type] + update_values["name"] = name # pyrefly: ignore [unknown-argument-type] if "image" in request_json: - image = request_json["image"] - update_values["image"] = image + image = request_json["image"] # pyrefly: ignore [unknown-variable-type] + update_values["image"] = image # pyrefly: ignore [unknown-argument-type] put_url = ( f"{settings.target_manager_base_url}/cloud_databases/" f"{database.database_name}/targets/{target_id}" ) - requests.put(url=put_url, json=update_values, timeout=30) + _ = requests.put(url=put_url, json=update_values, timeout=30) date = email.utils.formatdate(timeval=None, localtime=False, usegmt=True) headers = { diff --git a/src/mock_vws/_httpx2_mock_server/decorators.py b/src/mock_vws/_httpx2_mock_server/decorators.py index 764573261..c873f7558 100644 --- a/src/mock_vws/_httpx2_mock_server/decorators.py +++ b/src/mock_vws/_httpx2_mock_server/decorators.py @@ -60,7 +60,7 @@ def _to_request_data( A ``RequestData`` with method, path, headers, and body set. """ path = request.url.raw_path.decode(encoding="ascii") - if base_path and path.startswith(base_path): + if len(base_path) > 0 and path.startswith(base_path): path = path[len(base_path) :] return RequestData( method=request.method, @@ -148,7 +148,7 @@ def match(self, *, request: httpx2.Request) -> _MockRoute | None: for route in self.routes: if route.http_method != request.method: continue - if route.url_pattern.search(string=url): + if bool(route.url_pattern.search(string=url)): return route return None @@ -189,7 +189,7 @@ def handle_request(self, request: httpx2.Request) -> httpx2.Response: fake route matches, unless unmatched requests are passed through. """ - request.read() + _ = request.read() route = self._fakes.match(request=request) if route is not None: return route.handler(request) @@ -391,6 +391,6 @@ def async_transport_for_url( attribute="_transport_for_url", new=async_transport_for_url, ) - sync_patch.start() - async_patch.start() + _ = sync_patch.start() + _ = async_patch.start() return Httpx2Router(stop_fns=(async_patch.stop, sync_patch.stop)) diff --git a/src/mock_vws/_matching.py b/src/mock_vws/_matching.py index 3e9b52bbd..212089f7d 100644 --- a/src/mock_vws/_matching.py +++ b/src/mock_vws/_matching.py @@ -46,7 +46,7 @@ def _match_score( raise TypeError(message) if score is None: return None - return float(score) + return score @beartype diff --git a/src/mock_vws/_mock_common.py b/src/mock_vws/_mock_common.py index 718f682e2..5ed3bb1e0 100644 --- a/src/mock_vws/_mock_common.py +++ b/src/mock_vws/_mock_common.py @@ -138,7 +138,7 @@ def http_date() -> str: @beartype -def json_dump(*, body: dict[str, Any]) -> str: +def json_dump(*, body: dict[str, Any]) -> str: # pyrefly: ignore [explicit-any] """ Returns: JSON dump of data in the same way that Vuforia dumps data. diff --git a/src/mock_vws/_model_target_web_api.py b/src/mock_vws/_model_target_web_api.py index 761b589e9..25e39a8bd 100644 --- a/src/mock_vws/_model_target_web_api.py +++ b/src/mock_vws/_model_target_web_api.py @@ -144,7 +144,7 @@ def remove_oauth2_client_credential(self, client_id: str) -> None: def _json_response( *, status_code: HTTPStatus, - body: dict[str, Any], + body: dict[str, Any], # pyrefly: ignore [explicit-any] ) -> _ResponseType: """Return a JSON response.""" body_json = json_dump(body=body) @@ -168,7 +168,7 @@ def _error_response( details: list[dict[str, str]] | None, ) -> _ResponseType: """Return an error response shaped like the Model Target Web API.""" - error: dict[str, Any] = {"code": code, "message": message} + error: dict[str, Any] = {"code": code, "message": message} # pyrefly: ignore [explicit-any] if target is not None: error["target"] = target if details is not None: @@ -235,7 +235,7 @@ def _content_length_error(request: RequestData) -> _ResponseType | None: return None try: - int(given_content_length) + _ = int(given_content_length) except ValueError: error = ContentLengthHeaderNotIntError() return (error.status_code, dict(error.headers), error.response_text) @@ -259,7 +259,7 @@ def _basic_auth_credentials(auth_header: str | None) -> tuple[str, str] | None: return None client_id, separator, client_secret = decoded_credentials.partition(":") - if not separator: + if len(separator) == 0: return None return client_id, client_secret @@ -315,12 +315,12 @@ def _jwt_signature_error(*, bearer_token: str) -> str | None: signature. """ encoded_signature = bearer_token.rpartition(".")[2] - if not encoded_signature: + if len(encoded_signature) == 0: return "The signature must not be empty" try: padding = "=" * (-len(encoded_signature) % 4) - base64.b64decode( + _ = base64.b64decode( s=encoded_signature + padding, altchars=b"-_", validate=True, @@ -343,7 +343,7 @@ def _jwt_scopes(*, bearer_token: str) -> frozenset[str]: validate=True, ), ) - scope = payload.get("scope", "") + scope = payload.get("scope", "") # pyrefly: ignore [unknown-variable-type] if not isinstance(scope, str): return frozenset() return frozenset(scope.split()) @@ -365,7 +365,7 @@ def _require_bearer_token( details=None, ) bearer_token = auth_header.removeprefix("Bearer ").strip() - if not bearer_token: + if len(bearer_token) == 0: return _error_response( status_code=HTTPStatus.UNAUTHORIZED, code="401", @@ -443,7 +443,7 @@ def _require_state_based_scope( def _fake_jwt(*, token_source: bytes, scopes: frozenset[str]) -> str: """Return a deterministic bearer token for the mock.""" - def encode_part(value: dict[str, Any]) -> str: + def encode_part(value: dict[str, Any]) -> str: # pyrefly: ignore [explicit-any] """Return a base64url-encoded token part.""" raw_part = json.dumps( obj=value, @@ -531,7 +531,7 @@ def oauth2_token( # noqa: PLR0911 # pylint: disable=too-many-return-statements else: username = form.get("username", [""])[0] password = form.get("password", [""])[0] - if not username or not password: + if len(username) == 0 or len(password) == 0: return _oauth2_error_response( status_code=HTTPStatus.BAD_REQUEST, body={ @@ -551,7 +551,10 @@ def oauth2_token( # noqa: PLR0911 # pylint: disable=too-many-return-statements }, ) - token_source = request.body or (auth_header or "").encode() + auth_text = auth_header if auth_header is not None else "" + token_source = ( + request.body if len(request.body) > 0 else auth_text.encode() + ) requested_scope = form.get("scope", [""])[0] if grant_type == "client_credentials" and dynamic_credential is not None: credential_scopes = frozenset(dynamic_credential.scopes) @@ -559,7 +562,10 @@ def oauth2_token( # noqa: PLR0911 # pylint: disable=too-many-return-statements credential_scopes = _MODEL_TARGET_SCOPES | { _CLIENT_CREDENTIALS_SCOPE, } - scopes = frozenset(requested_scope.split()) or credential_scopes + requested_scopes = frozenset(requested_scope.split()) + scopes = ( + requested_scopes if len(requested_scopes) > 0 else credential_scopes + ) if not scopes.issubset(credential_scopes): return _oauth2_error_response( status_code=HTTPStatus.BAD_REQUEST, @@ -603,11 +609,11 @@ def _require_client_credentials_scope( target="jwt", details=None, ) - jwt_error = ( - _jwt_header_error(bearer_token=bearer_token) - or _jwt_payload_error(bearer_token=bearer_token) - or _jwt_signature_error(bearer_token=bearer_token) - ) + jwt_error = _jwt_header_error(bearer_token=bearer_token) + if jwt_error is None: + jwt_error = _jwt_payload_error(bearer_token=bearer_token) + if jwt_error is None: + jwt_error = _jwt_signature_error(bearer_token=bearer_token) if jwt_error is not None: return _error_response( status_code=HTTPStatus.UNAUTHORIZED, @@ -793,9 +799,12 @@ def _is_json_object(*, value: object) -> bool: @beartype -def _load_request_json(request: RequestData) -> dict[str, Any] | _ResponseType: +def _load_request_json(request: RequestData) -> dict[str, Any] | _ResponseType: # pyrefly: ignore [explicit-any] """Load a Model Target dataset creation request body.""" - content_type = _get_header(request=request, name="Content-Type") or "" + content_type_header = _get_header(request=request, name="Content-Type") + content_type = ( + content_type_header if content_type_header is not None else "" + ) if "application/json" not in content_type: return _error_response( status_code=HTTPStatus.UNSUPPORTED_MEDIA_TYPE, @@ -805,7 +814,7 @@ def _load_request_json(request: RequestData) -> dict[str, Any] | _ResponseType: details=None, ) try: - request_json: dict[str, Any] = json.loads( + request_json: dict[str, Any] = json.loads( # pyrefly: ignore [explicit-any] s=request.body.decode(encoding="utf-8"), ) except (UnicodeDecodeError, json.JSONDecodeError) as exc: @@ -827,7 +836,7 @@ def _load_request_json(request: RequestData) -> dict[str, Any] | _ResponseType: @beartype -def _cad_data_source_details(*, models: list[Any]) -> list[dict[str, str]]: +def _cad_data_source_details(*, models: list[Any]) -> list[dict[str, str]]: # pyrefly: ignore [explicit-any] """Return validation details for each model's CAD data source. One and only one of ``cadDataUrl``, ``cadDataBlob`` and ``cadDataUuid`` @@ -841,7 +850,7 @@ def _cad_data_source_details(*, models: list[Any]) -> list[dict[str, str]]: + ( "One of `cadDataBlob`, `cadDataUrl`, `cadDataUuid` need " "to be provided" - if not sources + if not bool(sources) else "Only one of `cadDataBlob`, `cadDataUrl`, " "`cadDataUuid` need to be provided" ) @@ -862,7 +871,7 @@ def _cad_data_source_details(*, models: list[Any]) -> list[dict[str, str]]: @beartype def _model_field_details( *, - models: list[Any], + models: list[Any], # pyrefly: ignore [explicit-any] dataset_type: ModelTargetDatasetType, ) -> list[dict[str, str]]: """Return validation details for the fields of each model.""" @@ -880,11 +889,11 @@ def _model_field_details( for field in ("name", "views") if field not in model ] - if missing_details: + if bool(missing_details): return missing_details cad_data_source_details = _cad_data_source_details(models=models) - if cad_data_source_details: + if bool(cad_data_source_details): return cad_data_source_details string_fields = sorted( @@ -905,7 +914,7 @@ def _model_field_details( for field in string_fields if field in model and not isinstance(model[field], str) ] - if string_details: + if bool(string_details): return string_details enum_details: list[dict[str, str]] = [] @@ -913,15 +922,16 @@ def _model_field_details( for field, allowed_values in sorted(enum_field_values.items()): if field in {"motionHint", "trackingMode"}: continue - if field not in model or model[field] in allowed_values: + if field not in model or model[field] in allowed_values: # pyrefly: ignore [unknown-argument-type] continue - value = model[field] + value = model[field] # pyrefly: ignore [unknown-variable-type] messages = { "automaticColoring": ( "invalid automaticColoring. Should be one of 'never', " f"'always', 'auto'. You provided '{value}'" ), "cadDataFormat": ( + # pyrefly: ignore [unknown-argument-type] "Unrecognized cadDataFormat '" f"{str(object=value).upper()}'. " "Allowed values are: ZIP, GLB, DRC_GLB, DRC_GLTF, DAE, " @@ -971,7 +981,7 @@ def _model_field_details( @beartype -def _view_details(*, models: list[Any]) -> list[dict[str, str]]: +def _view_details(*, models: list[Any]) -> list[dict[str, str]]: # pyrefly: ignore [explicit-any] """Return validation details for the guide views of each model.""" views = [ (model_index, view_index, view) @@ -990,7 +1000,7 @@ def _view_details(*, models: list[Any]) -> list[dict[str, str]]: for model_index, view_index, view in views if not isinstance(view, dict) ] - if object_details: + if bool(object_details): return object_details missing_details = [ @@ -1005,7 +1015,7 @@ def _view_details(*, models: list[Any]) -> list[dict[str, str]]: for field in ("name",) if field not in view ] - if missing_details: + if bool(missing_details): return missing_details name_details = [ @@ -1047,7 +1057,7 @@ def _is_json_number(*, value: object) -> bool: @beartype def _guide_view_position_details( *, - models: list[Any], + models: list[Any], # pyrefly: ignore [explicit-any] ) -> list[dict[str, str]]: """Return validation details for the guide view positions.""" positions = [ @@ -1069,7 +1079,7 @@ def _guide_view_position_details( for field in ("rotation", "translation") if field not in position ] - if missing_details: + if bool(missing_details): return missing_details array_details = [ @@ -1084,7 +1094,7 @@ def _guide_view_position_details( for field in ("rotation", "translation") if not isinstance(position[field], list) ] - if array_details: + if bool(array_details): return array_details return [ @@ -1099,7 +1109,7 @@ def _guide_view_position_details( for model_index, view_index, position in positions for field in ("rotation", "translation") for element_index, element in enumerate(iterable=position[field]) - if not _is_json_number(value=element) + if not _is_json_number(value=element) # pyrefly: ignore [unknown-argument-type] ] @@ -1111,7 +1121,7 @@ def _configuration_states( ) -> tuple[frozenset[str] | None, dict[str, str] | None]: """Load the state names from a State-Based Model Target config.""" try: - configuration: Any = json.loads(s=configuration_string) + configuration: Any = json.loads(s=configuration_string) # pyrefly: ignore [explicit-any] except json.JSONDecodeError: return None, { "code": "VALIDATION_ERROR", @@ -1137,13 +1147,13 @@ def _configuration_states( "states: error.expected.jsobject" ), } - configuration_states: dict[str, Any] = configuration["states"] + configuration_states: dict[str, Any] = configuration["states"] # pyrefly: ignore [explicit-any] state_names = frozenset(configuration_states) return state_names, None @beartype -def _state_based_details(*, models: list[Any]) -> list[dict[str, str]]: +def _state_based_details(*, models: list[Any]) -> list[dict[str, str]]: # pyrefly: ignore [explicit-any] """Return validation details for State-Based Model Targets.""" state_fields = [ (model_index, view_index, view["states"]) @@ -1162,7 +1172,7 @@ def _state_based_details(*, models: list[Any]) -> list[dict[str, str]]: for model_index, view_index, states in state_fields if not isinstance(states, list) ] - if array_details: + if bool(array_details): return array_details element_details = [ @@ -1177,13 +1187,13 @@ def _state_based_details(*, models: list[Any]) -> list[dict[str, str]]: for state_index, state in enumerate(iterable=states) if not isinstance(state, str) ] - if element_details: + if bool(element_details): return element_details details: list[dict[str, str]] = [] configured_states: dict[int, frozenset[str]] = {} for model_index, model in enumerate(iterable=models): - configuration_string = model.get("stateBasedConfigurationJsonString") + configuration_string = model.get("stateBasedConfigurationJsonString") # pyrefly: ignore [unknown-variable-type] if not isinstance(configuration_string, str): continue state_names, detail = _configuration_states( @@ -1195,7 +1205,7 @@ def _state_based_details(*, models: list[Any]) -> list[dict[str, str]]: if state_names is not None: configured_states[model_index] = state_names - if details: + if bool(details): return details for model_index, view_index, states in state_fields: @@ -1221,7 +1231,7 @@ def _state_based_details(*, models: list[Any]) -> list[dict[str, str]]: ), } for state in states - if state not in configured_states[model_index] + if state not in configured_states[model_index] # pyrefly: ignore [unknown-argument-type] ) return details @@ -1230,7 +1240,7 @@ def _state_based_details(*, models: list[Any]) -> list[dict[str, str]]: @beartype def _model_count_details( *, - models: list[Any], + models: list[Any], # pyrefly: ignore [explicit-any] dataset_type: ModelTargetDatasetType, ) -> list[dict[str, str]]: """Return validation details for the number of models.""" @@ -1281,7 +1291,7 @@ def _model_count_details( @beartype def _top_level_details( *, - request_json: dict[str, Any], + request_json: dict[str, Any], # pyrefly: ignore [explicit-any] ) -> list[dict[str, str]]: """Return validation details for the top-level dataset fields.""" missing_details = [ @@ -1292,7 +1302,7 @@ def _top_level_details( for field in ("models", "name", "targetSdk") if field not in request_json ] - if missing_details: + if bool(missing_details): return missing_details type_details = [ @@ -1320,15 +1330,15 @@ def _top_level_details( @beartype def _validate_dataset_request( *, - request_json: dict[str, Any], + request_json: dict[str, Any], # pyrefly: ignore [explicit-any] dataset_type: ModelTargetDatasetType, ) -> _ResponseType | None: """Validate the dataset request enough for useful mock feedback.""" details = _top_level_details(request_json=request_json) - if not details: + if not bool(details): # Vuforia's schema validator reads fields from non-object model and # view values as though they were empty objects. - models: list[Any] = [ + models: list[Any] = [ # pyrefly: ignore [explicit-any] model if isinstance(model, dict) else {} for model in request_json["models"] ] @@ -1338,18 +1348,22 @@ def _validate_dataset_request( view if isinstance(view, dict) else dict[str, Any]() for view in model["views"] ] - details = ( - _model_field_details(models=models, dataset_type=dataset_type) - or _view_details(models=models) - or _guide_view_position_details(models=models) - or _state_based_details(models=models) - or _model_count_details( + details = _model_field_details( + models=models, dataset_type=dataset_type + ) + if len(details) == 0: + details = _view_details(models=models) + if len(details) == 0: + details = _guide_view_position_details(models=models) + if len(details) == 0: + details = _state_based_details(models=models) + if len(details) == 0: + details = _model_count_details( models=models, dataset_type=dataset_type, ) - ) - if details: + if bool(details): return _validation_error_response(details=details) return None diff --git a/src/mock_vws/_query_tools.py b/src/mock_vws/_query_tools.py index 8601830f8..aa1176651 100644 --- a/src/mock_vws/_query_tools.py +++ b/src/mock_vws/_query_tools.py @@ -49,7 +49,7 @@ def get_query_match_response_text( # In the real Vuforia, targets which have just # been deleted may still get recognized. # We document this difference in ``differences-to-vws.rst``. - and not target.delete_date + and not bool(target.delete_date) and target.status == TargetStatuses.SUCCESS.value ] @@ -61,7 +61,7 @@ def get_query_match_response_text( if match.tracking_rating > minimum_rating ] - results: list[dict[str, Any]] = [] + results: list[dict[str, Any]] = [] # pyrefly: ignore [explicit-any] for target in matches: target_timestamp = target.last_modified_date.timestamp() if target.application_metadata is None: @@ -77,7 +77,7 @@ def get_query_match_response_text( } if include_target_data == "all" or ( - include_target_data == "top" and not results + include_target_data == "top" and not bool(results) ): result = { "target_id": target.target_id, diff --git a/src/mock_vws/_query_validators/auth_validators.py b/src/mock_vws/_query_validators/auth_validators.py index edce27080..729520f6a 100644 --- a/src/mock_vws/_query_validators/auth_validators.py +++ b/src/mock_vws/_query_validators/auth_validators.py @@ -52,7 +52,7 @@ def validate_auth_header_number_of_parts( header = request_headers["Authorization"] parts = header.split(sep=" ") expected_number_of_parts = 2 - if len(parts) == expected_number_of_parts and parts[1]: + if bool(len(parts) == expected_number_of_parts and parts[1]): return _LOGGER.warning(msg="The authorization header is malformed.") @@ -100,7 +100,7 @@ def validate_auth_header_has_signature( MalformedAuthHeaderError: The "Authorization" header has no signature. """ header = request_headers["Authorization"] - if header.count(":") == 1 and header.split(sep=":")[1]: + if bool(header.count(":") == 1 and header.split(sep=":")[1]): return _LOGGER.warning(msg="The authorization header has no signature.") diff --git a/src/mock_vws/_query_validators/content_length_validators.py b/src/mock_vws/_query_validators/content_length_validators.py index 4cb799fb5..30bcdb21a 100644 --- a/src/mock_vws/_query_validators/content_length_validators.py +++ b/src/mock_vws/_query_validators/content_length_validators.py @@ -31,7 +31,7 @@ def validate_content_length_header_is_int( given_content_length = request_headers["Content-Length"] try: - int(given_content_length) + _ = int(given_content_length) except ValueError as exc: _LOGGER.warning(msg="The Content-Length header is not an integer.") raise ContentLengthHeaderNotIntError from exc diff --git a/src/mock_vws/_query_validators/content_type_validators.py b/src/mock_vws/_query_validators/content_type_validators.py index 586978ccc..015a0d526 100644 --- a/src/mock_vws/_query_validators/content_type_validators.py +++ b/src/mock_vws/_query_validators/content_type_validators.py @@ -39,7 +39,7 @@ def validate_content_type_header( """ request_headers_dict = dict(request_headers) content_type_header = request_headers_dict.get("Content-Type", "") - if not content_type_header: + if not bool(content_type_header): _LOGGER.warning(msg="The content type header is empty.") raise NoContentTypeError diff --git a/src/mock_vws/_query_validators/date_validators.py b/src/mock_vws/_query_validators/date_validators.py index 116aff3eb..8c3480a8d 100644 --- a/src/mock_vws/_query_validators/date_validators.py +++ b/src/mock_vws/_query_validators/date_validators.py @@ -67,7 +67,9 @@ def validate_date_format(*, request_headers: Mapping[str, str]) -> None: for date_format in _accepted_date_formats(): with contextlib.suppress(ValueError): - datetime.datetime.strptime(date_header, date_format).astimezone() + _ = datetime.datetime.strptime( + date_header, date_format + ).astimezone() return _LOGGER.warning(msg="The date header is in the wrong format.") diff --git a/src/mock_vws/_query_validators/fields_validators.py b/src/mock_vws/_query_validators/fields_validators.py index 610f3e6dd..74a8e47a5 100644 --- a/src/mock_vws/_query_validators/fields_validators.py +++ b/src/mock_vws/_query_validators/fields_validators.py @@ -23,7 +23,7 @@ def validate_extra_fields(*, form: MultipartForm) -> None: parsed_keys = form.fields.keys() | form.files.keys() known_parameters = {"image", "max_num_results", "include_target_data"} - if not parsed_keys - known_parameters: + if not bool(parsed_keys - known_parameters): return _LOGGER.warning(msg="Unknown parameters are given.") diff --git a/src/mock_vws/_reco_counts_web_api.py b/src/mock_vws/_reco_counts_web_api.py index 40223104a..2ae778ced 100644 --- a/src/mock_vws/_reco_counts_web_api.py +++ b/src/mock_vws/_reco_counts_web_api.py @@ -129,7 +129,7 @@ def _reco_counts_for_month( return { target_id: reco_count for target_id, reco_count in reco_counts.items() - if reco_count + if bool(reco_count) } @@ -159,10 +159,12 @@ def create_reco_counts_report( FailError: The given month is not a month in the ``YYYY-mm`` form which the report can be requested for. """ - request_json: dict[str, Any] = json.loads(s=request_body) + request_json: dict[str, Any] = json.loads(s=request_body) # pyrefly: ignore [explicit-any] month = request_json["month"] - if not isinstance(month, str) or not _MONTH_PATTERN.fullmatch( - string=month, + if not isinstance(month, str) or not bool( + _MONTH_PATTERN.fullmatch( + string=month, + ) ): _LOGGER.warning(msg='The given "month" is not in the YYYY-mm form.') raise FailError(status_code=HTTPStatus.BAD_REQUEST) diff --git a/src/mock_vws/_requests_mock_server/mock_web_services_api.py b/src/mock_vws/_requests_mock_server/mock_web_services_api.py index c1787573a..c929a395d 100644 --- a/src/mock_vws/_requests_mock_server/mock_web_services_api.py +++ b/src/mock_vws/_requests_mock_server/mock_web_services_api.py @@ -290,9 +290,10 @@ def create_standard_model_target_dataset( request: RequestData, ) -> _ResponseType: """Create a standard Model Target dataset.""" - if failure := self._configured_model_target_failure( + failure = self._configured_model_target_failure( request_phase=ModelTargetRequest.CREATE, - ): + ) + if failure is not None: return failure return create_model_target_dataset( request=request, @@ -315,9 +316,10 @@ def create_advanced_model_target_dataset( request: RequestData, ) -> _ResponseType: """Create an advanced Model Target dataset.""" - if failure := self._configured_model_target_failure( + failure = self._configured_model_target_failure( request_phase=ModelTargetRequest.CREATE, - ): + ) + if failure is not None: return failure return create_model_target_dataset( request=request, @@ -343,9 +345,10 @@ def get_standard_model_target_dataset_status( request: RequestData, ) -> _ResponseType: """Return a standard Model Target dataset creation status.""" - if failure := self._configured_model_target_failure( + failure = self._configured_model_target_failure( request_phase=ModelTargetRequest.STATUS, - ): + ) + if failure is not None: return failure dataset_uuid = request.path.split(sep="/")[-2] return get_model_target_dataset_status( @@ -367,9 +370,10 @@ def get_advanced_model_target_dataset_status( request: RequestData, ) -> _ResponseType: """Return an advanced Model Target dataset creation status.""" - if failure := self._configured_model_target_failure( + failure = self._configured_model_target_failure( request_phase=ModelTargetRequest.STATUS, - ): + ) + if failure is not None: return failure dataset_uuid = request.path.split(sep="/")[-2] return get_model_target_dataset_status( @@ -391,9 +395,10 @@ def download_standard_model_target_dataset( request: RequestData, ) -> _ResponseType: """Download a standard Model Target dataset.""" - if failure := self._configured_model_target_failure( + failure = self._configured_model_target_failure( request_phase=ModelTargetRequest.DOWNLOAD, - ): + ) + if failure is not None: return failure dataset_uuid = request.path.split(sep="/")[-2] return download_model_target_dataset( @@ -415,9 +420,10 @@ def download_advanced_model_target_dataset( request: RequestData, ) -> _ResponseType: """Download an advanced Model Target dataset.""" - if failure := self._configured_model_target_failure( + failure = self._configured_model_target_failure( request_phase=ModelTargetRequest.DOWNLOAD, - ): + ) + if failure is not None: return failure dataset_uuid = request.path.split(sep="/")[-2] return download_model_target_dataset( @@ -438,9 +444,10 @@ def delete_standard_model_target_dataset( request: RequestData, ) -> _ResponseType: """Delete a standard Model Target dataset.""" - if failure := self._configured_model_target_failure( + failure = self._configured_model_target_failure( request_phase=ModelTargetRequest.DELETE, - ): + ) + if failure is not None: return failure dataset_uuid = request.path.split(sep="/")[-1] return delete_model_target_dataset( @@ -462,9 +469,10 @@ def delete_advanced_model_target_dataset( request: RequestData, ) -> _ResponseType: """Delete an advanced Model Target dataset.""" - if failure := self._configured_model_target_failure( + failure = self._configured_model_target_failure( request_phase=ModelTargetRequest.DELETE, - ): + ) + if failure is not None: return failure dataset_uuid = request.path.split(sep="/")[-1] return delete_model_target_dataset( @@ -544,7 +552,7 @@ def add_target(self, request: RequestData) -> _ResponseType: except ValidatorError as exc: return exc.status_code, exc.headers, exc.response_text - request_json: dict[str, Any] = json.loads(s=request.body) + request_json: dict[str, Any] = json.loads(s=request.body) # pyrefly: ignore [explicit-any] given_active_flag = request_json.get("active_flag") active_flag = { None: True, @@ -1002,7 +1010,7 @@ def update_target(self, request: RequestData) -> _ResponseType: exception.response_text, ) - request_json: dict[str, Any] = json.loads(s=request.body) + request_json: dict[str, Any] = json.loads(s=request.body) # pyrefly: ignore [explicit-any] name = request_json.get("name", target.name) active_flag = request_json.get("active_flag", target.active_flag) diff --git a/src/mock_vws/_respx_mock_server/decorators.py b/src/mock_vws/_respx_mock_server/decorators.py index 8f26e76e4..1efa46d48 100644 --- a/src/mock_vws/_respx_mock_server/decorators.py +++ b/src/mock_vws/_respx_mock_server/decorators.py @@ -36,7 +36,7 @@ def _to_request_data( A RequestData with method, path, headers, and body set. """ path = request.url.raw_path.decode(encoding="ascii") - if base_path and path.startswith(base_path): + if len(base_path) > 0 and path.startswith(base_path): path = path[len(base_path) :] return RequestData( method=request.method, @@ -156,7 +156,7 @@ def start_respx_router( api, route.route_name, ) - router.route( + _ = router.route( method=http_method, url=compiled_url_pattern, ).mock( @@ -169,9 +169,9 @@ def start_respx_router( ) if real_http: - router.route().pass_through() + _ = router.route().pass_through() else: - router.route().mock(side_effect=_block_unmatched) + _ = router.route().mock(side_effect=_block_unmatched) router.start() @@ -186,7 +186,7 @@ def start_respx_router( # backends, whose patches form a LIFO stack. ``respx.Router.start`` # looks its mocker up by name, and this router is created with the # default name, so the lookup cannot fail. - mocker = Mocker.registry[router.using or ""] + mocker = Mocker.registry[router.using if router.using is not None else ""] mocker.routers.remove(router) mocker.routers.insert(0, router) diff --git a/src/mock_vws/_services_validators/active_flag_validators.py b/src/mock_vws/_services_validators/active_flag_validators.py index 58eab5c40..e84171b55 100644 --- a/src/mock_vws/_services_validators/active_flag_validators.py +++ b/src/mock_vws/_services_validators/active_flag_validators.py @@ -26,9 +26,9 @@ def validate_active_flag(*, context: ValidatorContext) -> None: if "active_flag" not in request_json: return - active_flag = request_json["active_flag"] + active_flag = request_json["active_flag"] # pyrefly: ignore [unknown-variable-type] - if active_flag in {True, False, None}: + if active_flag in {True, False, None}: # pyrefly: ignore [unknown-argument-type] return _LOGGER.warning( diff --git a/src/mock_vws/_services_validators/auth_validators.py b/src/mock_vws/_services_validators/auth_validators.py index ccc86d927..931a53ed8 100644 --- a/src/mock_vws/_services_validators/auth_validators.py +++ b/src/mock_vws/_services_validators/auth_validators.py @@ -78,7 +78,7 @@ def validate_auth_header_has_signature( FailError: The "Authorization" header does not include a signature. """ header = request_headers["Authorization"] - if header.count(":") == 1 and header.split(sep=":")[1]: + if bool(header.count(":") == 1 and header.split(sep=":")[1]): return _LOGGER.warning( diff --git a/src/mock_vws/_services_validators/content_length_validators.py b/src/mock_vws/_services_validators/content_length_validators.py index 925c74fb5..7019feae0 100644 --- a/src/mock_vws/_services_validators/content_length_validators.py +++ b/src/mock_vws/_services_validators/content_length_validators.py @@ -46,7 +46,7 @@ def validate_content_length_header_is_int( integer """ try: - int(_given_content_length(context=context)) + _ = int(_given_content_length(context=context)) except ValueError as exc: _LOGGER.warning(msg="The Content-Length header is not an integer.") raise ContentLengthHeaderNotIntError from exc diff --git a/src/mock_vws/_services_validators/content_type_validators.py b/src/mock_vws/_services_validators/content_type_validators.py index cbaba695f..d6c2ea303 100644 --- a/src/mock_vws/_services_validators/content_type_validators.py +++ b/src/mock_vws/_services_validators/content_type_validators.py @@ -20,7 +20,7 @@ def validate_content_type_header_given(*, context: ValidatorContext) -> None: Raises: AuthenticationFailureError: No ``Content-Type`` header is given. """ - if dict(context.request_headers).get("Content-Type"): + if bool(dict(context.request_headers).get("Content-Type")): return _LOGGER.warning(msg="No Content-Type header is given.") diff --git a/src/mock_vws/_services_validators/date_validators.py b/src/mock_vws/_services_validators/date_validators.py index 0677d804c..c8f7beddf 100644 --- a/src/mock_vws/_services_validators/date_validators.py +++ b/src/mock_vws/_services_validators/date_validators.py @@ -47,7 +47,7 @@ def validate_date_format(*, context: ValidatorContext) -> None: """ date_header = context.request_headers["Date"] try: - datetime.datetime.strptime(date_header, _DATE_FORMAT).astimezone() + _ = datetime.datetime.strptime(date_header, _DATE_FORMAT).astimezone() except ValueError as exc: _LOGGER.warning(msg="The date header is in the wrong format.") raise FailError(status_code=HTTPStatus.BAD_REQUEST) from exc diff --git a/src/mock_vws/_services_validators/image_validators.py b/src/mock_vws/_services_validators/image_validators.py index ee12cfafe..a0f5782c6 100644 --- a/src/mock_vws/_services_validators/image_validators.py +++ b/src/mock_vws/_services_validators/image_validators.py @@ -32,12 +32,12 @@ def validate_image_data_type(*, context: ValidatorContext) -> None: if "image" not in request_json: return - image = request_json["image"] + image = request_json["image"] # pyrefly: ignore [unknown-variable-type] if isinstance(image, str): return - _LOGGER.warning('Image data is not a string: "%s"', image) + _LOGGER.warning('Image data is not a string: "%s"', image) # pyrefly: ignore [unknown-argument-type] raise FailError(status_code=HTTPStatus.BAD_REQUEST) diff --git a/src/mock_vws/_services_validators/json_validators.py b/src/mock_vws/_services_validators/json_validators.py index 57ccafb70..2040fc386 100644 --- a/src/mock_vws/_services_validators/json_validators.py +++ b/src/mock_vws/_services_validators/json_validators.py @@ -28,7 +28,7 @@ def validate_no_body_given(*, context: ValidatorContext) -> None: Raises: UnnecessaryRequestBodyError: A request body was given. """ - if not context.request_body: + if not bool(context.request_body): return _LOGGER.warning( @@ -60,7 +60,7 @@ def _validate_json( ValidatorError: The request body is empty, is not valid UTF-8, or is not a JSON object. """ - if not context.request_body: + if not bool(context.request_body): _LOGGER.warning(msg="The request body is empty.") raise make_empty_body_error() diff --git a/src/mock_vws/_services_validators/metadata_validators.py b/src/mock_vws/_services_validators/metadata_validators.py index fcef39644..d898800a2 100644 --- a/src/mock_vws/_services_validators/metadata_validators.py +++ b/src/mock_vws/_services_validators/metadata_validators.py @@ -33,7 +33,7 @@ def validate_metadata_size(*, context: ValidatorContext) -> None: application_metadata = request_json.get("application_metadata") if application_metadata is None: return - decoded = decode_base64(encoded_data=application_metadata) + decoded = decode_base64(encoded_data=application_metadata) # pyrefly: ignore [unknown-argument-type] max_metadata_bytes = 1024 * 1024 - 1 if len(decoded) <= max_metadata_bytes: @@ -61,7 +61,7 @@ def validate_metadata_encoding(*, context: ValidatorContext) -> None: return try: - decode_base64(encoded_data=application_metadata) + _ = decode_base64(encoded_data=application_metadata) # pyrefly: ignore [unknown-argument-type] except binascii.Error as exc: _LOGGER.warning(msg="The application metadata is not base64 encoded.") raise FailError(status_code=HTTPStatus.UNPROCESSABLE_ENTITY) from exc @@ -82,7 +82,7 @@ def validate_metadata_type(*, context: ValidatorContext) -> None: if "application_metadata" not in request_json: return - application_metadata = request_json["application_metadata"] + application_metadata = request_json["application_metadata"] # pyrefly: ignore [unknown-variable-type] if application_metadata is None or isinstance(application_metadata, str): return diff --git a/src/mock_vws/_services_validators/name_validators.py b/src/mock_vws/_services_validators/name_validators.py index bc49df600..be8ead175 100644 --- a/src/mock_vws/_services_validators/name_validators.py +++ b/src/mock_vws/_services_validators/name_validators.py @@ -167,7 +167,7 @@ def validate_name_length(*, context: ValidatorContext) -> None: return max_length = 64 - if name and len(name) <= max_length: + if len(name) > 0 and len(name) <= max_length: return _LOGGER.warning(msg="Name is not between 1 and 64 characters in length.") @@ -188,7 +188,7 @@ def validate_name_does_not_exist_new_target( TargetNameExistError: The target name already exists. """ name = _new_target_name(context=context) - if not _targets_with_name(context=context, name=name): + if not bool(_targets_with_name(context=context, name=name)): return _LOGGER.warning(msg="Target name already exists.") @@ -216,7 +216,7 @@ def validate_name_does_not_exist_existing_target( return matching_name_targets = _targets_with_name(context=context, name=name) - if not matching_name_targets: + if not bool(matching_name_targets): return (matching_name_target,) = matching_name_targets diff --git a/src/mock_vws/_services_validators/project_state_validators.py b/src/mock_vws/_services_validators/project_state_validators.py index b8cc8484e..4d9260565 100644 --- a/src/mock_vws/_services_validators/project_state_validators.py +++ b/src/mock_vws/_services_validators/project_state_validators.py @@ -32,7 +32,8 @@ def validate_project_state(*, context: ValidatorContext) -> None: States.PROJECT_HAS_NO_API_ACCESS: ProjectHasNoApiAccessError, States.PROJECT_SUSPENDED: ProjectSuspendedError, } - if error := state_errors.get(context.database.state): + error = state_errors.get(context.database.state) + if error is not None: raise error if context.database.state != States.PROJECT_INACTIVE: diff --git a/src/mock_vws/_services_validators/request_rate_limiter.py b/src/mock_vws/_services_validators/request_rate_limiter.py index 5356d1d7e..7119925c2 100644 --- a/src/mock_vws/_services_validators/request_rate_limiter.py +++ b/src/mock_vws/_services_validators/request_rate_limiter.py @@ -79,8 +79,10 @@ def validate( deque(), ) window_start = now - limit.window_seconds - while request_times and request_times[0] <= window_start: - request_times.popleft() + while ( + len(request_times) > 0 and request_times[0] <= window_start + ): + _ = request_times.popleft() if len(request_times) >= limit.max_requests: raise TooManyRequestsError diff --git a/src/mock_vws/_services_validators/routes.py b/src/mock_vws/_services_validators/routes.py index 8d8302eb7..e25c3dc76 100644 --- a/src/mock_vws/_services_validators/routes.py +++ b/src/mock_vws/_services_validators/routes.py @@ -386,6 +386,7 @@ def match_route(*, request_path: str, request_method: str) -> Route: route for route in _ROUTES if re.fullmatch(pattern=route.path_pattern, string=request_path) + is not None and request_method == route.http_method ) return matching_route diff --git a/src/mock_vws/_services_validators/target_validators.py b/src/mock_vws/_services_validators/target_validators.py index 70a5de805..279e6b8a9 100644 --- a/src/mock_vws/_services_validators/target_validators.py +++ b/src/mock_vws/_services_validators/target_validators.py @@ -52,6 +52,6 @@ def validate_target_id_exists(*, context: ValidatorContext) -> None: for target in context.database.not_deleted_targets if target.target_id == target_id ] - if not matching_targets: + if not bool(matching_targets): _LOGGER.warning('The target ID "%s" does not exist.', target_id) raise UnknownTargetError diff --git a/src/mock_vws/_services_validators/width_validators.py b/src/mock_vws/_services_validators/width_validators.py index fa5b7bbdc..454141359 100644 --- a/src/mock_vws/_services_validators/width_validators.py +++ b/src/mock_vws/_services_validators/width_validators.py @@ -25,7 +25,7 @@ def validate_width(*, context: ValidatorContext) -> None: if "width" not in request_json: return - width = request_json["width"] + width = request_json["width"] # pyrefly: ignore [unknown-variable-type] width_is_number = isinstance(width, int | float) width_positive = width_is_number and width > 0 diff --git a/src/mock_vws/database.py b/src/mock_vws/database.py index 3deb97f4a..4e3a86750 100644 --- a/src/mock_vws/database.py +++ b/src/mock_vws/database.py @@ -216,7 +216,9 @@ def from_dict(cls, database_dict: CloudDatabaseDict) -> Self: @property def not_deleted_targets(self) -> set[ImageTarget]: """All targets which have not been deleted.""" - return {target for target in self.targets if not target.delete_date} + return { + target for target in self.targets if not bool(target.delete_date) + } @property def active_targets(self) -> set[ImageTarget]: diff --git a/src/mock_vws/decorators.py b/src/mock_vws/decorators.py index 3b5982dd7..9447e0bc2 100644 --- a/src/mock_vws/decorators.py +++ b/src/mock_vws/decorators.py @@ -194,7 +194,7 @@ def __init__( for url in (base_vwq_url, base_vws_url): parse_result = urlparse(url=url) - if not parse_result.scheme: + if not bool(parse_result.scheme): raise MissingSchemeError(url=url) # The options are kept so that decorating a function can build an @@ -206,7 +206,7 @@ def __init__( cloud_query_failure_response=cloud_query_failure_response, duplicate_match_checker=duplicate_match_checker, query_match_checker=query_match_checker, - processing_time_seconds=float(processing_time_seconds), + processing_time_seconds=processing_time_seconds, model_target_generation_failure=model_target_generation_failure, model_target_failure_response=model_target_failure_response, model_target_generation_warning=model_target_generation_warning, @@ -369,7 +369,7 @@ def set_target_recognition_counts( if target.target_id == target_id ] - if not matches: + if not bool(matches): msg = f'No target has the ID "{target_id}".' raise ValueError(msg) @@ -477,11 +477,11 @@ def respond(request: PreparedRequest) -> _ResponseType: body_bytes = request.body path = request.path_url - if base_path and path.startswith(base_path): + if len(base_path) > 0 and path.startswith(base_path): path = path[len(base_path) :] request_data = RequestData( - method=request.method or "", + method=request.method if request.method is not None else "", path=path, headers=dict(request.headers), body=body_bytes, @@ -516,7 +516,7 @@ def __enter__(self) -> Self: api, route.route_name, ) - mock.add_callback( + _ = mock.add_callback( method=http_method, url=compiled_url_pattern, callback=self._wrap_callback( diff --git a/src/mock_vws/model_target.py b/src/mock_vws/model_target.py index dfd094a78..8144b8227 100644 --- a/src/mock_vws/model_target.py +++ b/src/mock_vws/model_target.py @@ -14,11 +14,11 @@ class ModelTargetDatasetDict(TypedDict): """A dictionary type which represents a Model Target dataset.""" - request_body: dict[str, Any] + request_body: dict[str, Any] # pyrefly: ignore [explicit-any] dataset_type_name: str processing_time_seconds: float generation_failure_message: str | None - generation_warning: dict[str, Any] | None + generation_warning: dict[str, Any] | None # pyrefly: ignore [explicit-any] uuid: str created_at: str @@ -100,7 +100,7 @@ class ModelTargetGenerationWarning: """ message: str = "Warning after creating dataset" - details: list[dict[str, Any]] = field( + details: list[dict[str, Any]] = field( # pyrefly: ignore [explicit-any] default_factory=lambda: [ { "code": "LOW_RECOGNITION_QUALITY", @@ -141,7 +141,7 @@ class ModelTargetDataset: generation_warning: A warning to return when processing completes. """ - request_body: dict[str, Any] = field(hash=False) + request_body: dict[str, Any] = field(hash=False) # pyrefly: ignore [explicit-any] dataset_type: ModelTargetDatasetType processing_time_seconds: float = field(hash=False) generation_failure: ModelTargetGenerationFailure | None = field(hash=False) @@ -188,7 +188,7 @@ def to_dict(self) -> ModelTargetDatasetDict: if self.generation_failure is not None: generation_failure_message = self.generation_failure.message - generation_warning: dict[str, Any] | None = None + generation_warning: dict[str, Any] | None = None # pyrefly: ignore [explicit-any] if self.generation_warning is not None: generation_warning = { "message": self.generation_warning.message, @@ -221,10 +221,10 @@ def status(self) -> str: return "failed" return "done" - def status_body(self) -> dict[str, Any]: + def status_body(self) -> dict[str, Any]: # pyrefly: ignore [explicit-any] """Return a status response body for this dataset.""" status = self.status - body: dict[str, Any] = { + body: dict[str, Any] = { # pyrefly: ignore [explicit-any] "status": status, "uuid": self.uuid_, "createdAt": _format_datetime(value=self.created_at), diff --git a/src/mock_vws/target.py b/src/mock_vws/target.py index 71e46c171..a70622cbc 100644 --- a/src/mock_vws/target.py +++ b/src/mock_vws/target.py @@ -127,7 +127,7 @@ def status(self) -> str: suitable the target is for detection. """ processing_time = datetime.timedelta( - seconds=float(self.processing_time_seconds), + seconds=self.processing_time_seconds, ) timezone = self.upload_date.tzinfo @@ -151,7 +151,7 @@ def tracking_rating(self) -> int: # That this is half of the total processing time is unrealistic. # In VWS it is not a constant percentage: it was observed as # roughly one second of a roughly thirty second processing time. - seconds=float(self.processing_time_seconds) / 2, + seconds=self.processing_time_seconds / 2, ) timezone = self.upload_date.tzinfo @@ -221,7 +221,7 @@ def from_dict(cls, target_dict: ImageTargetDict) -> Self: def to_dict(self) -> ImageTargetDict: """Dump a target to a dictionary which can be loaded as JSON.""" delete_date: str | None = None - if self.delete_date: + if self.delete_date is not None: delete_date = self.delete_date.isoformat() image_base64 = base64.encodebytes(s=self.image_value).decode() @@ -231,7 +231,7 @@ def to_dict(self) -> ImageTargetDict: "width": self.width, "image_base64": image_base64, "active_flag": self.active_flag, - "processing_time_seconds": float(self.processing_time_seconds), + "processing_time_seconds": self.processing_time_seconds, "application_metadata": self.application_metadata, "target_id": self.target_id, "last_modified_date": self.last_modified_date.isoformat(), @@ -268,7 +268,7 @@ def status(self) -> str: VuMark targets always succeed after processing. """ processing_time = datetime.timedelta( - seconds=float(self.processing_time_seconds), + seconds=self.processing_time_seconds, ) timezone = self.upload_date.tzinfo @@ -305,7 +305,7 @@ def to_dict(self) -> VuMarkTargetDict: return { "target_id": self.target_id, "name": self.name, - "processing_time_seconds": float(self.processing_time_seconds), + "processing_time_seconds": self.processing_time_seconds, "last_modified_date": self.last_modified_date.isoformat(), "upload_date": self.upload_date.isoformat(), } diff --git a/tests/conftest.py b/tests/conftest.py index a7795bd69..3256f746d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -268,7 +268,7 @@ def not_base64_encoded_processable(*, request: pytest.FixtureRequest) -> str: not_base64_encoded_string: str = request.param with pytest.raises(expected_exception=binascii.Error): - base64.b64decode(s=not_base64_encoded_string, validate=True) + _ = base64.b64decode(s=not_base64_encoded_string, validate=True) return not_base64_encoded_string @@ -294,6 +294,6 @@ def not_base64_encoded_not_processable( not_base64_encoded_string: str = request.param with pytest.raises(expected_exception=binascii.Error): - base64.b64decode(s=not_base64_encoded_string, validate=True) + _ = base64.b64decode(s=not_base64_encoded_string, validate=True) return not_base64_encoded_string diff --git a/tests/mock_vws/fixtures/model_target_prepared_requests.py b/tests/mock_vws/fixtures/model_target_prepared_requests.py index c981fc80e..d334f625b 100644 --- a/tests/mock_vws/fixtures/model_target_prepared_requests.py +++ b/tests/mock_vws/fixtures/model_target_prepared_requests.py @@ -19,7 +19,7 @@ MODEL_TARGET_VWS_HOST = "https://vws.vuforia.com" MODEL_TARGET_DATASET_UUID = "0b12466eee5d49409a440927006ff5d8" -_DATASET_REQUEST: dict[str, Any] = { +_DATASET_REQUEST: dict[str, Any] = { # pyrefly: ignore [explicit-any] "name": "dataset-name", "targetSdk": "10.18", "models": [ @@ -77,7 +77,7 @@ def get_access_token( response=response, status_codes=HTTPStatus.OK, ) - response_json: dict[str, Any] = json.loads(s=response.text) + response_json: dict[str, Any] = json.loads(s=response.text) # pyrefly: ignore [explicit-any] access_token = response_json["access_token"] assert isinstance(access_token, str) assert response_json["token_type"] == "bearer" diff --git a/tests/mock_vws/fixtures/prepared_requests.py b/tests/mock_vws/fixtures/prepared_requests.py index c820fe8b6..4aff9071b 100644 --- a/tests/mock_vws/fixtures/prepared_requests.py +++ b/tests/mock_vws/fixtures/prepared_requests.py @@ -348,7 +348,7 @@ def update_target( target_id: str, ) -> Endpoint: """Return details of the endpoint for updating a target.""" - data: dict[str, Any] = {} + data: dict[str, Any] = {} # pyrefly: ignore [explicit-any] request_path = f"/targets/{target_id}" content = json.dumps(obj=data).encode(encoding="utf-8") content_type = "application/json" diff --git a/tests/mock_vws/fixtures/vuforia_backends.py b/tests/mock_vws/fixtures/vuforia_backends.py index 5d2ad3a8d..e7b8cefe4 100644 --- a/tests/mock_vws/fixtures/vuforia_backends.py +++ b/tests/mock_vws/fixtures/vuforia_backends.py @@ -135,10 +135,10 @@ def _enable_use_real_vuforia( monkeypatch: pytest.MonkeyPatch, ) -> Generator[None]: """Test against the real Vuforia.""" - assert monkeypatch - assert inactive_cloud_database - assert vumark_vuforia_database - assert inactive_vumark_database + assert bool(monkeypatch) + assert bool(inactive_cloud_database) + assert bool(vumark_vuforia_database) + assert bool(inactive_vumark_database) _delete_all_targets(database_keys=working_database) yield @@ -153,7 +153,7 @@ def _enable_use_mock_vuforia( monkeypatch: pytest.MonkeyPatch, ) -> Generator[None]: """Test against the in-memory mock Vuforia.""" - assert monkeypatch + assert bool(monkeypatch) working_database = CloudDatabase( database_id=working_database.database_id, database_name=working_database.database_name, @@ -265,40 +265,40 @@ def _enable_use_flask_in_process( for database in requests.get( url=cloud_databases_url, timeout=30 ).json(): - requests.delete( - url=cloud_databases_url + "/" + database["database_name"], + _ = requests.delete( + url=cloud_databases_url + "/" + database["database_name"], # pyrefly: ignore [unknown-argument-type] timeout=30, ) for database in requests.get( url=vumark_databases_url, timeout=30 ).json(): - requests.delete( - url=vumark_databases_url + "/" + database["database_name"], + _ = requests.delete( + url=vumark_databases_url + "/" + database["database_name"], # pyrefly: ignore [unknown-argument-type] timeout=30, ) - requests.post( + _ = requests.post( url=cloud_databases_url, json=working_database.to_dict(), timeout=30, ) - requests.post( + _ = requests.post( url=cloud_databases_url, json=inactive_cloud_database.to_dict(), timeout=30, ) - requests.post( + _ = requests.post( url=vumark_databases_url, json=vumark_database.to_dict(), timeout=30, ) - requests.post( + _ = requests.post( url=vumark_databases_url, json=inactive_vumark_db.to_dict(), timeout=30, ) for vumark_target in vumark_database.vumark_targets: - requests.post( + _ = requests.post( url=( f"{vumark_databases_url}" f"/{vumark_database.database_name}/vumark_targets" @@ -321,7 +321,7 @@ def _enable_use_real_model_target_vuforia( the load balancer in front of the real Model Target Web API occasionally returns for a request which is not at fault. """ - assert monkeypatch + assert bool(monkeypatch) with retrying_transient_real_backend_failures(): yield @@ -332,7 +332,7 @@ def _enable_use_mock_model_target_vuforia( monkeypatch: pytest.MonkeyPatch, ) -> Generator[None]: """Test against the in-memory mock Model Target Web API.""" - assert monkeypatch + assert bool(monkeypatch) with MockVWS(): yield @@ -343,7 +343,7 @@ def _enable_use_flask_in_process_model_target_vuforia( monkeypatch: pytest.MonkeyPatch, ) -> Generator[None]: """Test against the Flask-backed mock Model Target Web API.""" - assert monkeypatch + assert bool(monkeypatch) VWS_FLASK_APP.config["VWS_MOCK_TERMINATE_WSGI_INPUT"] = True target_manager_base_url = "http://example.com" monkeypatch.setenv( diff --git a/tests/mock_vws/test_add_target.py b/tests/mock_vws/test_add_target.py index a595eec0a..0dd4c9e60 100644 --- a/tests/mock_vws/test_add_target.py +++ b/tests/mock_vws/test_add_target.py @@ -43,7 +43,7 @@ def _add_target_to_vws( *, vws_client: VWS, - data: dict[str, Any], + data: dict[str, Any], # pyrefly: ignore [explicit-any] content_type: str, ) -> Response: """Return a response from a request to the endpoint to add a target. @@ -81,10 +81,10 @@ def assert_success(response: Response) -> None: ) expected_keys = {"result_code", "transaction_id", "target_id"} response_json = json.loads(s=response.text) - target_id = response_json["target_id"] + target_id = response_json["target_id"] # pyrefly: ignore [unknown-variable-type] expected_target_id_length = 32 - assert len(target_id) == expected_target_id_length - assert all(char in hexdigits for char in target_id) + assert len(target_id) == expected_target_id_length # pyrefly: ignore [unknown-argument-type] + assert all(char in hexdigits for char in target_id) # pyrefly: ignore [unknown-argument-type] assert isinstance(response_json, dict) assert response_json.keys() == expected_keys @@ -158,7 +158,7 @@ def test_empty_content_type( with pytest.raises( expected_exception=AuthenticationFailureError, ) as exc: - _add_target_to_vws( + _ = _add_target_to_vws( vws_client=vws_client, data=data, content_type="", @@ -197,10 +197,10 @@ def test_missing_data( "width": 1, "image": image_data_encoded, } - data.pop(data_to_remove) + _ = data.pop(data_to_remove) with pytest.raises(expected_exception=FailError) as exc: - _add_target_to_vws( + _ = _add_target_to_vws( vws_client=vws_client, data=data, content_type="application/json", @@ -242,7 +242,7 @@ def test_width_invalid( } with pytest.raises(expected_exception=FailError) as exc: - _add_target_to_vws( + _ = _add_target_to_vws( vws_client=vws_client, data=data, content_type="application/json", @@ -261,7 +261,7 @@ def test_width_valid( image_file_failed_state: io.BytesIO, ) -> None: """Positive numbers are valid widths.""" - vws_client.add_target( + _ = vws_client.add_target( name="example", width=0.01, image=image_file_failed_state, @@ -297,7 +297,7 @@ def test_name_valid( vws_client: VWS, ) -> None: """Names between 1 and 64 characters in length are valid.""" - vws_client.add_target( + _ = vws_client.add_target( name=name, width=1, image=image_file_failed_state, @@ -356,14 +356,14 @@ def test_name_invalid( if status_code == HTTPStatus.INTERNAL_SERVER_ERROR: with pytest.raises(expected_exception=ServerError) as exc: - _add_target_to_vws( + _ = _add_target_to_vws( vws_client=vws_client, data=data, content_type="application/json", ) else: with pytest.raises(expected_exception=FailError) as exc: - _add_target_to_vws( + _ = _add_target_to_vws( vws_client=vws_client, data=data, content_type="application/json", @@ -382,7 +382,7 @@ def test_existing_target_name( vws_client: VWS, ) -> None: """Only one target can have a given name.""" - vws_client.add_target( + _ = vws_client.add_target( name="example_name", width=1, image=image_file_failed_state, @@ -391,7 +391,7 @@ def test_existing_target_name( ) with pytest.raises(expected_exception=TargetNameExistError) as exc: - vws_client.add_target( + _ = vws_client.add_target( name="example_name", width=1, image=image_file_failed_state, @@ -422,7 +422,7 @@ def test_deleted_existing_target_name( vws_client.wait_for_target_processed(target_id=target_id) vws_client.delete_target(target_id=target_id) - vws_client.add_target( + _ = vws_client.add_target( name="example_name", width=1, image=image_file_failed_state, @@ -449,7 +449,7 @@ def test_image_valid( JPEG and PNG files in the RGB and greyscale color spaces are allowed. """ - vws_client.add_target( + _ = vws_client.add_target( name="example_name", width=1, image=image_files_failed_state, @@ -470,7 +470,7 @@ def test_bad_image_format_or_color_space( greyscale or RGB color space. """ with pytest.raises(expected_exception=BadImageError) as exc: - vws_client.add_target( + _ = vws_client.add_target( name="example_name", width=1, image=bad_image_file, @@ -492,7 +492,7 @@ def test_corrupted( ) -> None: """An error is returned when the given image is corrupted.""" with pytest.raises(expected_exception=BadImageError) as exc: - vws_client.add_target( + _ = vws_client.add_target( name="example_name", width=1, image=corrupted_image_file, @@ -516,7 +516,7 @@ def test_truncated(vws_client: VWS) -> None: image_file = make_truncated_png_file() with pytest.raises(expected_exception=BadImageError) as exc: - vws_client.add_target( + _ = vws_client.add_target( name="example_name", width=1, image=image_file, @@ -541,7 +541,7 @@ def test_decompression_bomb(vws_client: VWS) -> None: assert len(image_file.getvalue()) < max_bytes with pytest.raises(expected_exception=ImageTooLargeError) as exc: - vws_client.add_target( + _ = vws_client.add_target( name="example_name", width=1, image=image_file, @@ -576,7 +576,7 @@ def test_image_pixel_count_too_large( height=height, ) - vws_client.add_target( + _ = vws_client.add_target( name="example_name", width=1, image=image_not_too_many_pixels, @@ -585,7 +585,7 @@ def test_image_pixel_count_too_large( ) with pytest.raises(expected_exception=ImageTooLargeError) as exc: - vws_client.add_target( + _ = vws_client.add_target( name="example_name_2", width=1, image=pixel_count_too_large, @@ -617,7 +617,7 @@ def test_image_file_size_too_large( assert image_content_size < max_bytes assert (image_content_size * 1.05) > max_bytes - vws_client.add_target( + _ = vws_client.add_target( name="example_name", width=1, image=png_just_under_max_size, @@ -629,7 +629,7 @@ def test_image_file_size_too_large( assert image_content_size > max_bytes with pytest.raises(expected_exception=ImageTooLargeError) as exc: - vws_client.add_target( + _ = vws_client.add_target( name="example_name_2", width=1, image=png_too_large, @@ -663,7 +663,7 @@ def test_not_base64_encoded_processable( } with pytest.raises(expected_exception=BadImageError) as exc: - _add_target_to_vws( + _ = _add_target_to_vws( vws_client=vws_client, data=data, content_type="application/json", @@ -694,7 +694,7 @@ def test_not_base64_encoded_not_processable( } with pytest.raises(expected_exception=FailError) as exc: - _add_target_to_vws( + _ = _add_target_to_vws( vws_client=vws_client, data=data, content_type="application/json", @@ -714,7 +714,7 @@ def test_not_image(vws_client: VWS) -> None: is returned. """ with pytest.raises(expected_exception=BadImageError) as exc: - vws_client.add_target( + _ = vws_client.add_target( name="example_name", width=1, image=io.BytesIO(initial_bytes=b"not_image_data"), @@ -746,7 +746,7 @@ def test_invalid_type( } with pytest.raises(expected_exception=FailError) as exc: - _add_target_to_vws( + _ = _add_target_to_vws( vws_client=vws_client, data=data, content_type="application/json", @@ -821,7 +821,7 @@ def test_invalid( } with pytest.raises(expected_exception=FailError) as exc: - _add_target_to_vws( + _ = _add_target_to_vws( vws_client=vws_client, data=data, content_type=content_type, @@ -855,8 +855,8 @@ def test_not_set( vws_client=vws_client, data=data, content_type="application/json" ) response_json = json.loads(s=response.text) - target_id = response_json["target_id"] - target_details = vws_client.get_target_record(target_id=target_id) + target_id = response_json["target_id"] # pyrefly: ignore [unknown-variable-type] + target_details = vws_client.get_target_record(target_id=target_id) # pyrefly: ignore [unknown-argument-type] assert target_details.target_record.active_flag is True @staticmethod @@ -883,8 +883,8 @@ def test_set_to_none( ) response_json = json.loads(s=response.text) - target_id = response_json["target_id"] - target_details = vws_client.get_target_record(target_id=target_id) + target_id = response_json["target_id"] # pyrefly: ignore [unknown-variable-type] + target_details = vws_client.get_target_record(target_id=target_id) # pyrefly: ignore [unknown-argument-type] assert target_details.target_record.active_flag is True @@ -918,7 +918,7 @@ def test_invalid_extra_data( } with pytest.raises(expected_exception=FailError) as exc: - _add_target_to_vws( + _ = _add_target_to_vws( vws_client=vws_client, data=data, content_type="application/json", @@ -955,7 +955,7 @@ def test_base64_encoded( encoding="ascii" ) - vws_client.add_target( + _ = vws_client.add_target( name="example", width=1, image=image_file_failed_state, @@ -1013,7 +1013,7 @@ def test_invalid_type( } with pytest.raises(expected_exception=FailError) as exc: - _add_target_to_vws( + _ = _add_target_to_vws( vws_client=vws_client, data=data, content_type="application/json", @@ -1037,7 +1037,7 @@ def test_not_base64_encoded_processable( allowed as application metadata. """ - vws_client.add_target( + _ = vws_client.add_target( name="example", width=1, image=high_quality_image, @@ -1058,7 +1058,7 @@ def test_not_base64_encoded_not_processable( as application metadata. """ with pytest.raises(expected_exception=FailError) as exc: - vws_client.add_target( + _ = vws_client.add_target( name="example", width=1, image=high_quality_image, @@ -1092,7 +1092,7 @@ def test_metadata_too_large( ).decode(encoding="ascii") with pytest.raises(expected_exception=MetadataTooLargeError) as exc: - vws_client.add_target( + _ = vws_client.add_target( name="example", width=1, image=image_file_failed_state, @@ -1122,7 +1122,7 @@ def test_inactive_project( returned. """ with pytest.raises(expected_exception=ProjectInactiveError) as exc: - inactive_vws_client.add_target( + _ = inactive_vws_client.add_target( name="example", width=1, image=image_file_failed_state, diff --git a/tests/mock_vws/test_authorization_header.py b/tests/mock_vws/test_authorization_header.py index 2f9367f62..9a949401e 100644 --- a/tests/mock_vws/test_authorization_header.py +++ b/tests/mock_vws/test_authorization_header.py @@ -42,7 +42,7 @@ def test_missing(endpoint: Endpoint) -> None: **endpoint.headers, "Date": date, } - new_headers.pop("Authorization", None) + _ = new_headers.pop("Authorization", None) new_endpoint = Endpoint( base_url=endpoint.base_url, @@ -259,7 +259,7 @@ def test_bad_access_key_services( ) with pytest.raises(expected_exception=FailError) as exc: - vws_client.get_target_record(target_id=uuid.uuid4().hex) + _ = vws_client.get_target_record(target_id=uuid.uuid4().hex) assert exc.value.response.status_code == HTTPStatus.BAD_REQUEST @@ -281,7 +281,7 @@ def test_bad_access_key_query( with pytest.raises( expected_exception=cloud_reco_exceptions.AuthenticationFailureError ) as exc: - cloud_reco_client.query(image=high_quality_image) + _ = cloud_reco_client.query(image=high_quality_image) response = exc.value.response @@ -299,8 +299,8 @@ def test_bad_access_key_query( "result_code", } assert_valid_transaction_id(response=response) - result_code = json.loads(s=response.text)["result_code"] - transaction_id = json.loads(s=response.text)["transaction_id"] + result_code = json.loads(s=response.text)["result_code"] # pyrefly: ignore [unknown-variable-type] + transaction_id = json.loads(s=response.text)["transaction_id"] # pyrefly: ignore [unknown-variable-type] assert result_code == ResultCodes.AUTHENTICATION_FAILURE.value # The separators are inconsistent and we test this. expected_text = ( @@ -325,7 +325,7 @@ def test_bad_secret_key_services( ) with pytest.raises(expected_exception=AuthenticationFailureError): - vws_client.get_target_record(target_id=uuid.uuid4().hex) + _ = vws_client.get_target_record(target_id=uuid.uuid4().hex) @staticmethod def test_bad_secret_key_query( @@ -345,7 +345,7 @@ def test_bad_secret_key_query( with pytest.raises( expected_exception=cloud_reco_exceptions.AuthenticationFailureError ) as exc: - cloud_reco_client.query(image=high_quality_image) + _ = cloud_reco_client.query(image=high_quality_image) response = exc.value.response @@ -363,8 +363,8 @@ def test_bad_secret_key_query( "result_code", } assert_valid_transaction_id(response=response) - result_code = json.loads(s=response.text)["result_code"] - transaction_id = json.loads(s=response.text)["transaction_id"] + result_code = json.loads(s=response.text)["result_code"] # pyrefly: ignore [unknown-variable-type] + transaction_id = json.loads(s=response.text)["transaction_id"] # pyrefly: ignore [unknown-variable-type] assert result_code == ResultCodes.AUTHENTICATION_FAILURE.value # The separators are inconsistent and we test this. expected_text = ( diff --git a/tests/mock_vws/test_content_length.py b/tests/mock_vws/test_content_length.py index 41e34fe24..5ccd32a36 100644 --- a/tests/mock_vws/test_content_length.py +++ b/tests/mock_vws/test_content_length.py @@ -32,7 +32,7 @@ def test_not_integer(endpoint: Endpoint) -> None: Length`` is not an integer. """ - if not endpoint.headers.get("Content-Type"): + if not bool(endpoint.headers.get("Content-Type")): return content_length = "0.4" @@ -60,7 +60,7 @@ def test_not_integer(endpoint: Endpoint) -> None: netloc = urlparse(url=endpoint.base_url).netloc if netloc == "cloudreco.vuforia.com": - assert not response.text + assert not bool(response.text) assert response.headers == { "Content-Length": str(object=len(response.text)), "Connection": "Close", @@ -92,7 +92,7 @@ def test_not_integer(endpoint: Endpoint) -> None: @pytest.mark.skip(reason="It takes too long to run this test.") def test_too_large(endpoint: Endpoint) -> None: # pragma: no cover """An error is given if the given content length is too large.""" - if not endpoint.headers.get("Content-Type"): + if not bool(endpoint.headers.get("Content-Type")): pytest.skip(reason="No Content-Type header for this request") netloc = urlparse(url=endpoint.base_url).netloc @@ -123,7 +123,7 @@ def test_too_large(endpoint: Endpoint) -> None: # pragma: no cover # retry on the Gateway Timeout. if netloc == "cloudreco.vuforia.com": assert response.status_code == HTTPStatus.GATEWAY_TIMEOUT - assert not response.text + assert not bool(response.text) assert response.headers == { "Content-Length": str(object=len(response.text)), "Connection": "keep-alive", @@ -151,7 +151,7 @@ def test_too_small(endpoint: Endpoint) -> None: length is too small. """ - if not endpoint.headers.get("Content-Type"): + if not bool(endpoint.headers.get("Content-Type")): return real_content_length = len(endpoint.data) diff --git a/tests/mock_vws/test_database_summary.py b/tests/mock_vws/test_database_summary.py index c5fff2fcf..7ced0edd0 100644 --- a/tests/mock_vws/test_database_summary.py +++ b/tests/mock_vws/test_database_summary.py @@ -262,7 +262,7 @@ def test_processing_images( with MockVWS() as mock: mock.add_cloud_database(cloud_database=database) - vws_client.add_target( + _ = vws_client.add_target( name=uuid.uuid4().hex, width=1, image=image_file_success_state_low_rating, @@ -320,7 +320,7 @@ def test_query_request( vws_client.wait_for_target_processed(target_id=target_id) report_before = vws_client.get_database_summary_report() - cloud_reco_client.query(image=high_quality_image) + _ = cloud_reco_client.query(image=high_quality_image) report_after = vws_client.get_database_summary_report() total_recos_change = ( @@ -371,7 +371,7 @@ def test_bad_target_request( original_request_usage = report.request_usage with pytest.raises(expected_exception=FailError) as exc: - vws_client.add_target( + _ = vws_client.add_target( name="example", width=-1, image=high_quality_image, @@ -398,7 +398,7 @@ def test_query_request( """ report = vws_client.get_database_summary_report() original_request_usage = report.request_usage - cloud_reco_client.query(image=high_quality_image) + _ = cloud_reco_client.query(image=high_quality_image) report = vws_client.get_database_summary_report() new_request_usage = report.request_usage # The request usage goes up for the database summary request, not the @@ -415,4 +415,4 @@ def test_inactive_project( inactive_vws_client: VWS, ) -> None: """The project's active state does not affect the database summary.""" - inactive_vws_client.get_database_summary_report() + _ = inactive_vws_client.get_database_summary_report() diff --git a/tests/mock_vws/test_date_header.py b/tests/mock_vws/test_date_header.py index 0bf55ac4e..92cb7a20f 100644 --- a/tests/mock_vws/test_date_header.py +++ b/tests/mock_vws/test_date_header.py @@ -50,7 +50,7 @@ def test_no_date_header(endpoint: Endpoint) -> None: **endpoint.headers, "Authorization": authorization_string, } - new_headers.pop("Date", None) + _ = new_headers.pop("Date", None) new_endpoint = Endpoint( base_url=endpoint.base_url, diff --git a/tests/mock_vws/test_delete_target.py b/tests/mock_vws/test_delete_target.py index 0d184a08e..e896aeccd 100644 --- a/tests/mock_vws/test_delete_target.py +++ b/tests/mock_vws/test_delete_target.py @@ -50,7 +50,7 @@ def test_processed(*, target_id: str, vws_client: VWS) -> None: vws_client.delete_target(target_id=target_id) with pytest.raises(expected_exception=UnknownTargetError): - vws_client.get_target_record(target_id=target_id) + _ = vws_client.get_target_record(target_id=target_id) @pytest.mark.usefixtures("verify_mock_vuforia") diff --git a/tests/mock_vws/test_docker.py b/tests/mock_vws/test_docker.py index 2b3b00a79..1117aabae 100644 --- a/tests/mock_vws/test_docker.py +++ b/tests/mock_vws/test_docker.py @@ -71,7 +71,7 @@ class _MockDeployment: def _poll_health_check(container: Container) -> None: """Poll a container until it reports a healthy status.""" container.reload() - health_status = container.attrs["State"]["Health"]["Status"] + health_status = container.attrs["State"]["Health"]["Status"] # pyrefly: ignore [unknown-variable-type] # In theory this might not be hit by coverage. # Let's keep it required by coverage for now. if health_status != "healthy": @@ -93,7 +93,7 @@ def wait_for_health_check(container: Container) -> None: except ValueError as exc: # pragma: no cover container.reload() logs = container.logs().decode(errors="replace") - health_log = container.attrs["State"]["Health"].get("Log", []) + health_log = container.attrs["State"]["Health"].get("Log", []) # pyrefly: ignore [unknown-variable-type] probes = "\n".join( f" exit={entry.get('ExitCode')!r} " f"start={entry.get('Start')!r} end={entry.get('End')!r}\n" @@ -130,7 +130,7 @@ def _wait_for_model_target_dataset_done( timeout=30, ) assert response.status_code == HTTPStatus.OK - status = response.json()["status"] + status = response.json()["status"] # pyrefly: ignore [unknown-variable-type] if status != "done": error_message = f"Dataset {dataset_uuid} status is {status!r}." raise ValueError(error_message) @@ -185,16 +185,16 @@ def _free_port() -> int: type=socket.SOCK_STREAM, ) as sock: sock.bind(("127.0.0.1", 0)) - return int(sock.getsockname()[1]) + return int(sock.getsockname()[1]) # pyrefly: ignore [unknown-argument-type] @beartype def _published_base_url(*, container: Container) -> str: """Return the host-reachable base URL of a container.""" container.reload() - port_attrs = container.attrs["NetworkSettings"]["Ports"] - host_ip = port_attrs["5000/tcp"][0]["HostIp"] - host_port = port_attrs["5000/tcp"][0]["HostPort"] + port_attrs = container.attrs["NetworkSettings"]["Ports"] # pyrefly: ignore [unknown-variable-type] + host_ip = port_attrs["5000/tcp"][0]["HostIp"] # pyrefly: ignore [unknown-variable-type] + host_port = port_attrs["5000/tcp"][0]["HostPort"] # pyrefly: ignore [unknown-variable-type] return f"http://{host_ip}:{host_port}" @@ -262,7 +262,7 @@ def fixture_custom_bridge_network() -> Iterator[Network]: # This does leave behind untagged images. for image in images_to_remove: - image.remove(force=True) + _ = image.remove(force=True) network.remove() @@ -445,7 +445,7 @@ def test_model_target_dataset_survives_vws_restart( timeout=30, ) assert oauth_response.status_code == HTTPStatus.OK - access_token = oauth_response.json()["access_token"] + access_token = oauth_response.json()["access_token"] # pyrefly: ignore [unknown-variable-type] dataset_request = { "name": "example-dataset", @@ -473,12 +473,12 @@ def test_model_target_dataset_survives_vws_restart( timeout=30, ) assert create_dataset_response.status_code == HTTPStatus.CREATED - dataset_uuid = create_dataset_response.json()["uuid"] + dataset_uuid = create_dataset_response.json()["uuid"] # pyrefly: ignore [unknown-variable-type] _wait_for_model_target_dataset_done( base_vws_url=base_vws_url, - dataset_uuid=dataset_uuid, - access_token=access_token, + dataset_uuid=dataset_uuid, # pyrefly: ignore [unknown-argument-type] + access_token=access_token, # pyrefly: ignore [unknown-argument-type] ) mock_deployment.vws_container.restart() @@ -572,12 +572,12 @@ def test_reco_counts_report_round_trip( assert report_response.status_code == HTTPStatus.OK report_json = report_response.json() assert report_json["result_code"] == "Success" - presigned_url = report_json["presigned_url"] + presigned_url = report_json["presigned_url"] # pyrefly: ignore [unknown-variable-type] # The download URL is built from the ``VWS_BASE_URL`` of the VWS # container, so it reaches that container. assert presigned_url.startswith(mock_deployment.base_vws_url) - report_content = _wait_for_reco_counts_report(presigned_url=presigned_url) + report_content = _wait_for_reco_counts_report(presigned_url=presigned_url) # pyrefly: ignore [unknown-argument-type] assert report_content == ( f"target_id,reco_count\r\n{target_id},{_CURRENT_MONTH_RECOS}\r\n" @@ -643,18 +643,18 @@ def test_request_rate_limit(*, mock_deployment: _MockDeployment) -> None: _create_cloud_database(deployment=mock_deployment, database=database) vws_client = _vws_client(deployment=mock_deployment, database=database) - vws_client.list_targets() + _ = vws_client.list_targets() with pytest.raises(expected_exception=TooManyRequestsError): - vws_client.list_targets() + _ = vws_client.list_targets() # Other endpoints are not limited. - vws_client.get_database_summary_report() + _ = vws_client.get_database_summary_report() mock_deployment.vws_container.restart() wait_for_health_check(container=mock_deployment.vws_container) - vws_client.list_targets() + _ = vws_client.list_targets() def test_deleted_database(*, mock_deployment: _MockDeployment) -> None: @@ -668,7 +668,7 @@ def test_deleted_database(*, mock_deployment: _MockDeployment) -> None: _create_cloud_database(deployment=mock_deployment, database=database) vws_client = _vws_client(deployment=mock_deployment, database=database) - vws_client.list_targets() + _ = vws_client.list_targets() delete_response = requests.delete( url=( @@ -680,6 +680,6 @@ def test_deleted_database(*, mock_deployment: _MockDeployment) -> None: assert delete_response.status_code == HTTPStatus.OK with pytest.raises(expected_exception=FailError) as exc: - vws_client.list_targets() + _ = vws_client.list_targets() assert exc.value.response.status_code == HTTPStatus.BAD_REQUEST diff --git a/tests/mock_vws/test_flask_app_usage.py b/tests/mock_vws/test_flask_app_usage.py index 7bb83184b..d980768a9 100644 --- a/tests/mock_vws/test_flask_app_usage.py +++ b/tests/mock_vws/test_flask_app_usage.py @@ -127,7 +127,9 @@ def test_default( """By default, targets in the mock takes 2 seconds to be processed.""" database = CloudDatabase() databases_url = _EXAMPLE_URL_FOR_TARGET_MANAGER + "/cloud_databases" - requests.post(url=databases_url, json=database.to_dict(), timeout=30) + _ = requests.post( + url=databases_url, json=database.to_dict(), timeout=30 + ) time_taken = processing_time_seconds( vuforia_database=database, @@ -151,7 +153,9 @@ def test_custom( ) database = CloudDatabase() databases_url = _EXAMPLE_URL_FOR_TARGET_MANAGER + "/cloud_databases" - requests.post(url=databases_url, json=database.to_dict(), timeout=30) + _ = requests.post( + url=databases_url, json=database.to_dict(), timeout=30 + ) time_taken = processing_time_seconds( vuforia_database=database, @@ -182,7 +186,7 @@ def test_request_quota_reached() -> None: ) with pytest.raises(expected_exception=RequestQuotaReachedError): - client.list_targets() + _ = client.list_targets() @staticmethod def test_target_quota_reached( @@ -204,7 +208,7 @@ def test_target_quota_reached( ) with pytest.raises(expected_exception=TargetQuotaReachedError): - client.add_target( + _ = client.add_target( name="example", width=1, image=image_file_failed_state, @@ -229,7 +233,7 @@ def test_too_many_requests() -> None: ) with pytest.raises(expected_exception=TooManyRequestsError): - client.list_targets() + _ = client.list_targets() @staticmethod def test_per_endpoint_limits() -> None: @@ -254,12 +258,12 @@ def test_per_endpoint_limits() -> None: server_secret_key=database.server_secret_key, ) - client.list_targets() + _ = client.list_targets() with pytest.raises(expected_exception=TooManyRequestsError): - client.list_targets() + _ = client.list_targets() # Other endpoints are not limited. - client.get_database_summary_report() + _ = client.get_database_summary_report() class TestRecognitionCounts: @@ -371,7 +375,9 @@ def test_duplicate_keys() -> None: ) databases_url = _EXAMPLE_URL_FOR_TARGET_MANAGER + "/cloud_databases" - requests.post(url=databases_url, json=database.to_dict(), timeout=30) + _ = requests.post( + url=databases_url, json=database.to_dict(), timeout=30 + ) for bad_database, expected_message in ( (bad_server_access_key_db, server_access_key_conflict_error), @@ -405,17 +411,17 @@ def test_give_no_details(high_quality_image: io.BytesIO) -> None: assert "database_name" in data vws_client = VWS( - server_access_key=data["server_access_key"], - server_secret_key=data["server_secret_key"], + server_access_key=data["server_access_key"], # pyrefly: ignore [unknown-argument-type] + server_secret_key=data["server_secret_key"], # pyrefly: ignore [unknown-argument-type] ) cloud_reco_client = CloudRecoService( - client_access_key=data["client_access_key"], - client_secret_key=data["client_secret_key"], + client_access_key=data["client_access_key"], # pyrefly: ignore [unknown-argument-type] + client_secret_key=data["client_secret_key"], # pyrefly: ignore [unknown-argument-type] ) - assert not vws_client.list_targets() - assert not cloud_reco_client.query(image=high_quality_image) + assert not bool(vws_client.list_targets()) + assert not bool(cloud_reco_client.query(image=high_quality_image)) @staticmethod @pytest.mark.parametrize( @@ -473,7 +479,7 @@ def test_give_no_details(high_quality_image: io.BytesIO) -> None: ], ) def test_invalid_field( - body: dict[str, Any], + body: dict[str, Any], # pyrefly: ignore [explicit-any] expected_loc: list[str], expected_message: str, ) -> None: @@ -488,7 +494,7 @@ def test_invalid_field( (error,) = response.json()["errors"] assert error["loc"] == expected_loc assert error["msg"] == expected_message - assert not TARGET_MANAGER.cloud_databases + assert not bool(TARGET_MANAGER.cloud_databases) @staticmethod @pytest.mark.parametrize( @@ -600,7 +606,9 @@ def test_duplicate_keys() -> None: ) databases_url = _EXAMPLE_URL_FOR_TARGET_MANAGER + "/vumark_databases" - requests.post(url=databases_url, json=database.to_dict(), timeout=30) + _ = requests.post( + url=databases_url, json=database.to_dict(), timeout=30 + ) for bad_database, expected_message in ( (bad_server_access_key_db, server_access_key_conflict_error), @@ -636,7 +644,7 @@ def test_invalid_state_name() -> None: "'PROJECT_SUSPENDED', 'PROJECT_INACTIVE', " "'PROJECT_HAS_NO_API_ACCESS'" ) - assert not TARGET_MANAGER.vumark_databases + assert not bool(TARGET_MANAGER.vumark_databases) class TestTargetInUnknownDatabase: @@ -740,11 +748,11 @@ def test_delete_cloud_database() -> None: assert response.status_code == HTTPStatus.CREATED data = json.loads(s=response.text) - delete_url = databases_url + "/" + data["database_name"] - response = requests.delete(url=delete_url, json={}, timeout=30) + delete_url = databases_url + "/" + data["database_name"] # pyrefly: ignore [unknown-variable-type] + response = requests.delete(url=delete_url, json={}, timeout=30) # pyrefly: ignore [unknown-argument-type] assert response.status_code == HTTPStatus.OK - response = requests.delete(url=delete_url, json={}, timeout=30) + response = requests.delete(url=delete_url, json={}, timeout=30) # pyrefly: ignore [unknown-argument-type] assert response.status_code == HTTPStatus.NOT_FOUND @@ -770,11 +778,11 @@ def test_delete_vumark_database() -> None: assert response.status_code == HTTPStatus.CREATED data = json.loads(s=response.text) - delete_url = databases_url + "/" + data["database_name"] - response = requests.delete(url=delete_url, json={}, timeout=30) + delete_url = databases_url + "/" + data["database_name"] # pyrefly: ignore [unknown-variable-type] + response = requests.delete(url=delete_url, json={}, timeout=30) # pyrefly: ignore [unknown-argument-type] assert response.status_code == HTTPStatus.OK - response = requests.delete(url=delete_url, json={}, timeout=30) + response = requests.delete(url=delete_url, json={}, timeout=30) # pyrefly: ignore [unknown-argument-type] assert response.status_code == HTTPStatus.NOT_FOUND @@ -806,7 +814,9 @@ def test_exact_match( pil_image.save(fp=re_exported_image, format="PNG") databases_url = _EXAMPLE_URL_FOR_TARGET_MANAGER + "/cloud_databases" - requests.post(url=databases_url, json=database.to_dict(), timeout=30) + _ = requests.post( + url=databases_url, json=database.to_dict(), timeout=30 + ) target_id = vws_client.add_target( name="example", @@ -823,7 +833,7 @@ def test_exact_match( different_image_result = cloud_reco_client.query( image=re_exported_image, ) - assert not different_image_result + assert not bool(different_image_result) @staticmethod def test_structural_similarity_matcher( @@ -851,7 +861,9 @@ def test_structural_similarity_matcher( re_exported_image = io.BytesIO() pil_image.save(fp=re_exported_image, format="PNG") databases_url = _EXAMPLE_URL_FOR_TARGET_MANAGER + "/cloud_databases" - requests.post(url=databases_url, json=database.to_dict(), timeout=30) + _ = requests.post( + url=databases_url, json=database.to_dict(), timeout=30 + ) assert re_exported_image.getvalue() != high_quality_image.getvalue() @@ -875,7 +887,7 @@ def test_structural_similarity_matcher( different_image_result = cloud_reco_client.query( image=different_high_quality_image, ) - assert not different_image_result + assert not bool(different_image_result) class TestDuplicatesImageMatchers: @@ -900,7 +912,9 @@ def test_exact_match( pil_image.save(fp=re_exported_image, format="PNG") databases_url = _EXAMPLE_URL_FOR_TARGET_MANAGER + "/cloud_databases" - requests.post(url=databases_url, json=database.to_dict(), timeout=30) + _ = requests.post( + url=databases_url, json=database.to_dict(), timeout=30 + ) target_id = vws_client.add_target( name="example_0", @@ -953,7 +967,9 @@ def test_structural_similarity_matcher( pil_image.save(fp=re_exported_image, format="PNG") databases_url = _EXAMPLE_URL_FOR_TARGET_MANAGER + "/cloud_databases" - requests.post(url=databases_url, json=database.to_dict(), timeout=30) + _ = requests.post( + url=databases_url, json=database.to_dict(), timeout=30 + ) target_id = vws_client.add_target( name="example", @@ -987,7 +1003,9 @@ def test_default( """By default, the BRISQUE target rater is used.""" database = CloudDatabase() databases_url = _EXAMPLE_URL_FOR_TARGET_MANAGER + "/cloud_databases" - requests.post(url=databases_url, json=database.to_dict(), timeout=30) + _ = requests.post( + url=databases_url, json=database.to_dict(), timeout=30 + ) vws_client = VWS( server_access_key=database.server_access_key, @@ -1039,7 +1057,9 @@ def test_brisque( database = CloudDatabase() databases_url = _EXAMPLE_URL_FOR_TARGET_MANAGER + "/cloud_databases" - requests.post(url=databases_url, json=database.to_dict(), timeout=30) + _ = requests.post( + url=databases_url, json=database.to_dict(), timeout=30 + ) vws_client = VWS( server_access_key=database.server_access_key, @@ -1089,7 +1109,9 @@ def test_perfect( monkeypatch.setenv(name="TARGET_RATER", value="perfect") database = CloudDatabase() databases_url = _EXAMPLE_URL_FOR_TARGET_MANAGER + "/cloud_databases" - requests.post(url=databases_url, json=database.to_dict(), timeout=30) + _ = requests.post( + url=databases_url, json=database.to_dict(), timeout=30 + ) vws_client = VWS( server_access_key=database.server_access_key, @@ -1130,7 +1152,9 @@ def test_random( database = CloudDatabase() databases_url = _EXAMPLE_URL_FOR_TARGET_MANAGER + "/cloud_databases" - requests.post(url=databases_url, json=database.to_dict(), timeout=30) + _ = requests.post( + url=databases_url, json=database.to_dict(), timeout=30 + ) vws_client = VWS( server_access_key=database.server_access_key, @@ -1260,7 +1284,7 @@ def test_standard_dataset_workflow( data={"grant_type": "client_credentials"}, timeout=30, ) - token = token_response.json()["access_token"] + token = token_response.json()["access_token"] # pyrefly: ignore [unknown-variable-type] headers = {"Authorization": f"Bearer {token}"} create_response = requests.post( @@ -1269,7 +1293,7 @@ def test_standard_dataset_workflow( json=_MODEL_TARGET_DATASET_REQUEST, timeout=30, ) - dataset_uuid = create_response.json()["uuid"] + dataset_uuid = create_response.json()["uuid"] # pyrefly: ignore [unknown-variable-type] status_response = requests.get( url=( "https://vws.vuforia.com/modeltargets/datasets/" @@ -1296,7 +1320,7 @@ def test_standard_dataset_workflow( assert dataset_zip.namelist() == ["MTDataset.dat", "MTDataset.xml"] @staticmethod - def _dataset_status(dataset_uuid: str) -> dict[str, Any]: + def _dataset_status(dataset_uuid: str) -> dict[str, Any]: # pyrefly: ignore [explicit-any] """Return a dataset's status response body from the VWS app.""" token_response = requests.post( url="https://vws.vuforia.com/oauth2/token", @@ -1304,7 +1328,7 @@ def _dataset_status(dataset_uuid: str) -> dict[str, Any]: data={"grant_type": "client_credentials"}, timeout=30, ) - token = token_response.json()["access_token"] + token = token_response.json()["access_token"] # pyrefly: ignore [unknown-variable-type] status_response = requests.get( url=( "https://vws.vuforia.com/modeltargets/datasets/" @@ -1314,7 +1338,7 @@ def _dataset_status(dataset_uuid: str) -> dict[str, Any]: timeout=30, ) assert status_response.status_code == HTTPStatus.OK - status_body: dict[str, Any] = status_response.json() + status_body: dict[str, Any] = status_response.json() # pyrefly: ignore [explicit-any] return status_body def test_seeded_generation_failure(self) -> None: @@ -1403,7 +1427,7 @@ class TestResponseDelay: @staticmethod def _make_request() -> None: """Make a request to the VWS API.""" - requests.get( + _ = requests.get( url="https://vws.vuforia.com/summary", headers={ "Date": email.utils.formatdate( @@ -1421,7 +1445,9 @@ def test_default_no_delay(self) -> None: """By default, there is no response delay.""" database = CloudDatabase() databases_url = _EXAMPLE_URL_FOR_TARGET_MANAGER + "/cloud_databases" - requests.post(url=databases_url, json=database.to_dict(), timeout=30) + _ = requests.post( + url=databases_url, json=database.to_dict(), timeout=30 + ) start = time.monotonic() self._make_request() @@ -1439,7 +1465,9 @@ def test_delay_is_applied( ) database = CloudDatabase() databases_url = _EXAMPLE_URL_FOR_TARGET_MANAGER + "/cloud_databases" - requests.post(url=databases_url, json=database.to_dict(), timeout=30) + _ = requests.post( + url=databases_url, json=database.to_dict(), timeout=30 + ) start = time.monotonic() self._make_request() @@ -1613,7 +1641,7 @@ def test_create_targets_while_listing_databases( database = _create_cloud_database(base_url=base_url) with requests.Session() as setup_session: for _ in range(_NUM_EXISTING_TARGETS): - _create_image_target( + _ = _create_image_target( session=setup_session, base_url=base_url, database=database, @@ -1643,7 +1671,7 @@ def reader(session: requests.Session) -> list[requests.Response]: for response in all_responses if response.status_code not in {HTTPStatus.OK, HTTPStatus.CREATED} ] - assert not error_statuses + assert not bool(error_statuses) expected_num_targets = _NUM_EXISTING_TARGETS + ( _NUM_WRITER_THREADS * _NUM_REQUESTS_PER_WRITER @@ -1676,7 +1704,7 @@ def test_update_targets_while_listing_databases( database=database, image_base64=small_image_base64, ) - target_ids.add(response.json()["target_id"]) + target_ids.add(response.json()["target_id"]) # pyrefly: ignore [unknown-argument-type] target_ids_to_update = list(target_ids)[:_NUM_WRITER_THREADS] target_ids_to_update_lock = threading.Lock() @@ -1705,7 +1733,7 @@ def reader(session: requests.Session) -> list[requests.Response]: for response in all_responses if response.status_code != HTTPStatus.OK ] - assert not error_statuses + assert not bool(error_statuses) listings = [ response.json() diff --git a/tests/mock_vws/test_get_duplicates.py b/tests/mock_vws/test_get_duplicates.py index a245bf1b4..c18f216e0 100644 --- a/tests/mock_vws/test_get_duplicates.py +++ b/tests/mock_vws/test_get_duplicates.py @@ -292,6 +292,6 @@ def test_inactive_project(inactive_vws_client: VWS) -> None: returned. """ with pytest.raises(expected_exception=ProjectInactiveError): - inactive_vws_client.get_duplicate_targets( + _ = inactive_vws_client.get_duplicate_targets( target_id=uuid.uuid4().hex, ) diff --git a/tests/mock_vws/test_get_target.py b/tests/mock_vws/test_get_target.py index 325517864..1e5fe59da 100644 --- a/tests/mock_vws/test_get_target.py +++ b/tests/mock_vws/test_get_target.py @@ -170,4 +170,6 @@ class TestInactiveProject: def test_inactive_project(inactive_vws_client: VWS) -> None: """The project's active state does not affect getting a target.""" with pytest.raises(expected_exception=UnknownTargetError): - inactive_vws_client.get_target_record(target_id=uuid.uuid4().hex) + _ = inactive_vws_client.get_target_record( + target_id=uuid.uuid4().hex + ) diff --git a/tests/mock_vws/test_httpx2_mock_usage.py b/tests/mock_vws/test_httpx2_mock_usage.py index dae0ce549..22ee3b153 100644 --- a/tests/mock_vws/test_httpx2_mock_usage.py +++ b/tests/mock_vws/test_httpx2_mock_usage.py @@ -57,7 +57,7 @@ } -def _run[T](*, coroutine: Coroutine[Any, Any, T]) -> T: +def _run[T](*, coroutine: Coroutine[Any, Any, T]) -> T: # pyrefly: ignore [explicit-any] """Run a coroutine to completion. The test suite has no plugin for asynchronous tests, so asynchronous @@ -80,7 +80,7 @@ def _unused_local_url() -> str: """ sock = socket.socket() sock.bind(("", 0)) - port = sock.getsockname()[1] + port = sock.getsockname()[1] # pyrefly: ignore [unknown-variable-type] sock.close() return f"http://localhost:{port}" @@ -124,7 +124,7 @@ def test_response_delay_causes_httpx2_timeout() -> None: transport=HTTPX2Transport(), ) with pytest.raises(expected_exception=httpx2.ReadTimeout): - client.get_database_summary_report() + _ = client.get_database_summary_report() assert calls == [0.1] @@ -162,7 +162,7 @@ def test_bad_credentials_are_rejected() -> None: with pytest.raises( expected_exception=AuthenticationFailureError, ): - client.get_database_summary_report() + _ = client.get_database_summary_report() @staticmethod def test_add_get_and_delete_target( @@ -194,7 +194,7 @@ def test_add_get_and_delete_target( client.delete_target(target_id=target_id) with pytest.raises(expected_exception=UnknownTargetError): - client.get_target_record(target_id=target_id) + _ = client.get_target_record(target_id=target_id) @staticmethod def test_nested_mocks() -> None: @@ -211,11 +211,11 @@ def test_nested_mocks() -> None: with MockVWS(base_vws_url="https://vuforia.vws.example.com"): inner_response = httpx2.get(url=inner_url, timeout=30) with pytest.raises(expected_exception=httpx2.ConnectError): - httpx2.get(url=outer_url, timeout=30) + _ = httpx2.get(url=outer_url, timeout=30) outer_response = httpx2.get(url=outer_url, timeout=30) with pytest.raises(expected_exception=httpx2.ConnectError): - httpx2.get(url=inner_url, timeout=30) + _ = httpx2.get(url=inner_url, timeout=30) assert inner_response.status_code == HTTPStatus.UNAUTHORIZED assert outer_response.status_code == HTTPStatus.UNAUTHORIZED @@ -450,7 +450,7 @@ def test_close() -> None: transport.close() with MockVWS(), pytest.raises(expected_exception=RuntimeError): - transport( + _ = transport( method="GET", url="https://vws.vuforia.com/summary", headers={}, @@ -490,7 +490,7 @@ def test_unmocked_address_blocked() -> None: MockVWS(), pytest.raises(expected_exception=httpx2.ConnectError), ): - _run(coroutine=_async_get(url=url)) + _ = _run(coroutine=_async_get(url=url)) @staticmethod def test_real_http() -> None: @@ -505,7 +505,7 @@ def test_real_http() -> None: MockVWS(real_http=True), pytest.raises(expected_exception=httpx2.ConnectError), ): - _run(coroutine=_async_get(url=url)) + _ = _run(coroutine=_async_get(url=url)) class TestModelTargetWebAPI: @@ -521,7 +521,7 @@ def test_standard_dataset_status() -> None: json=_MODEL_TARGET_DATASET_REQUEST, timeout=30, ) - dataset_uuid = create_response.json()["uuid"] + dataset_uuid = create_response.json()["uuid"] # pyrefly: ignore [unknown-variable-type] status_response = httpx2.get( url=( "https://vws.vuforia.com/modeltargets/datasets/" diff --git a/tests/mock_vws/test_invalid_json.py b/tests/mock_vws/test_invalid_json.py index 77e23638f..a08072b59 100644 --- a/tests/mock_vws/test_invalid_json.py +++ b/tests/mock_vws/test_invalid_json.py @@ -103,7 +103,7 @@ def _assert_body_rejected(*, endpoint: Endpoint, content: bytes) -> None: return assert response.status_code == HTTPStatus.BAD_REQUEST - assert not response.text + assert not bool(response.text) assert "Content-Type" not in response.headers @@ -302,5 +302,5 @@ def test_invalid_json_with_skewed_time(endpoint: Endpoint) -> None: return assert response.status_code == HTTPStatus.BAD_REQUEST - assert not response.text + assert not bool(response.text) assert "Content-Type" not in response.headers diff --git a/tests/mock_vws/test_model_target_failure_response.py b/tests/mock_vws/test_model_target_failure_response.py index 7e704e2c2..58561ef29 100644 --- a/tests/mock_vws/test_model_target_failure_response.py +++ b/tests/mock_vws/test_model_target_failure_response.py @@ -14,10 +14,10 @@ _CLIENT_ID = "client-id" _CLIENT_SECRET = "client-secret" type _HTTPResponse = requests.Response | httpx.Response -type _DatasetRequestSender = Callable[[dict[str, Any]], _HTTPResponse] +type _DatasetRequestSender = Callable[[dict[str, Any]], _HTTPResponse] # pyrefly: ignore [explicit-any] -def _dataset_body() -> dict[str, Any]: +def _dataset_body() -> dict[str, Any]: # pyrefly: ignore [explicit-any] """Return an otherwise-valid Model Target dataset request body.""" return { "name": "configured-failure-test", @@ -32,7 +32,7 @@ def _dataset_body() -> dict[str, Any]: } -def _requests_create_dataset(body: dict[str, Any]) -> _HTTPResponse: +def _requests_create_dataset(body: dict[str, Any]) -> _HTTPResponse: # pyrefly: ignore [explicit-any] """Acquire a token and create a dataset using ``requests``.""" token_response = requests.post( url=f"{_BASE_URL}/oauth2/token", @@ -41,7 +41,7 @@ def _requests_create_dataset(body: dict[str, Any]) -> _HTTPResponse: timeout=30, ) token_response.raise_for_status() - token = token_response.json()["access_token"] + token = token_response.json()["access_token"] # pyrefly: ignore [unknown-variable-type] return requests.post( url=f"{_BASE_URL}/modeltargets/datasets", headers={"Authorization": f"Bearer {token}"}, @@ -50,7 +50,7 @@ def _requests_create_dataset(body: dict[str, Any]) -> _HTTPResponse: ) -def _httpx_create_dataset(body: dict[str, Any]) -> _HTTPResponse: +def _httpx_create_dataset(body: dict[str, Any]) -> _HTTPResponse: # pyrefly: ignore [explicit-any] """Acquire a token and create a dataset using ``httpx``.""" token_response = httpx.post( url=f"{_BASE_URL}/oauth2/token", @@ -58,8 +58,8 @@ def _httpx_create_dataset(body: dict[str, Any]) -> _HTTPResponse: data={"grant_type": "client_credentials"}, timeout=30, ) - token_response.raise_for_status() - token = token_response.json()["access_token"] + _ = token_response.raise_for_status() + token = token_response.json()["access_token"] # pyrefly: ignore [unknown-variable-type] return httpx.post( url=f"{_BASE_URL}/modeltargets/datasets", headers={"Authorization": f"Bearer {token}"}, @@ -108,7 +108,7 @@ def _httpx_create_dataset(body: dict[str, Any]) -> _HTTPResponse: ) def test_configured_failure_response( *, - send_request: _DatasetRequestSender, + send_request: _DatasetRequestSender, # pyrefly: ignore [explicit-any] status_code: HTTPStatus, headers: dict[str, str], body: str | bytes, @@ -136,7 +136,8 @@ def test_configured_failure_response( ids=["requests", "httpx"], ) def test_unselected_request_is_handled_normally( - *, send_request: _DatasetRequestSender + *, + send_request: _DatasetRequestSender, # pyrefly: ignore [explicit-any] ) -> None: """A failure configured for another phase does not affect creation.""" failure = ModelTargetFailureResponse( @@ -196,7 +197,7 @@ def test_selected_request_returns_failure( timeout=30, ) token_response.raise_for_status() - token = token_response.json()["access_token"] + token = token_response.json()["access_token"] # pyrefly: ignore [unknown-variable-type] response = requests.request( method=method, url=f"{_BASE_URL}/modeltargets/{collection}{path_suffix}", diff --git a/tests/mock_vws/test_model_target_generation_failure.py b/tests/mock_vws/test_model_target_generation_failure.py index 71b752859..a9a34ef64 100644 --- a/tests/mock_vws/test_model_target_generation_failure.py +++ b/tests/mock_vws/test_model_target_generation_failure.py @@ -17,7 +17,7 @@ "c2lnbmF0dXJl" ) _CREATE_URL = "https://vws.vuforia.com/modeltargets/datasets" -_REQUEST_BODY: dict[str, Any] = { +_REQUEST_BODY: dict[str, Any] = { # pyrefly: ignore [explicit-any] "name": "dataset-name", "targetSdk": "10.18", "models": [ @@ -37,12 +37,12 @@ ], } type _HTTPResponse = requests.Response | httpx.Response | httpx2.Response -type _RequestSender = Callable[[str, dict[str, Any] | None], _HTTPResponse] +type _RequestSender = Callable[[str, dict[str, Any] | None], _HTTPResponse] # pyrefly: ignore [explicit-any] def _requests_request( url: str, - json_body: dict[str, Any] | None, + json_body: dict[str, Any] | None, # pyrefly: ignore [explicit-any] ) -> _HTTPResponse: """Send a Model Target request with ``requests``.""" if json_body is None: @@ -61,7 +61,7 @@ def _requests_request( def _httpx_request( url: str, - json_body: dict[str, Any] | None, + json_body: dict[str, Any] | None, # pyrefly: ignore [explicit-any] ) -> _HTTPResponse: """Send a Model Target request with ``httpx``.""" if json_body is None: @@ -80,7 +80,7 @@ def _httpx_request( def _httpx2_request( url: str, - json_body: dict[str, Any] | None, + json_body: dict[str, Any] | None, # pyrefly: ignore [explicit-any] ) -> _HTTPResponse: """Send a Model Target request with ``httpx2``.""" if json_body is None: @@ -111,7 +111,7 @@ def _httpx2_request( ) def test_configured_generation_failure( *, - send_request: _RequestSender, + send_request: _RequestSender, # pyrefly: ignore [explicit-any] processing_time_seconds: float, expected_status: str, time_field: str, @@ -125,7 +125,7 @@ def test_configured_generation_failure( model_target_generation_failure=failure, ): create_response = send_request(_CREATE_URL, _REQUEST_BODY) - dataset_uuid = create_response.json()["uuid"] + dataset_uuid = create_response.json()["uuid"] # pyrefly: ignore [unknown-variable-type] status_response = send_request( f"{_CREATE_URL}/{dataset_uuid}/status", None, diff --git a/tests/mock_vws/test_model_target_generation_warning.py b/tests/mock_vws/test_model_target_generation_warning.py index 8170471b4..b28efa1be 100644 --- a/tests/mock_vws/test_model_target_generation_warning.py +++ b/tests/mock_vws/test_model_target_generation_warning.py @@ -20,7 +20,7 @@ "c2lnbmF0dXJl" ) _CREATE_URL = "https://vws.vuforia.com/modeltargets/datasets" -_REQUEST_BODY: dict[str, Any] = { +_REQUEST_BODY: dict[str, Any] = { # pyrefly: ignore [explicit-any] "name": "dataset-name", "targetSdk": "10.18", "models": [ @@ -40,12 +40,12 @@ ], } type _HTTPResponse = requests.Response | httpx.Response -type _RequestSender = Callable[[str, dict[str, Any] | None], _HTTPResponse] +type _RequestSender = Callable[[str, dict[str, Any] | None], _HTTPResponse] # pyrefly: ignore [explicit-any] def _requests_request( url: str, - json_body: dict[str, Any] | None, + json_body: dict[str, Any] | None, # pyrefly: ignore [explicit-any] ) -> _HTTPResponse: """Send a Model Target request with ``requests``.""" if json_body is None: @@ -64,7 +64,7 @@ def _requests_request( def _httpx_request( url: str, - json_body: dict[str, Any] | None, + json_body: dict[str, Any] | None, # pyrefly: ignore [explicit-any] ) -> _HTTPResponse: """Send a Model Target request with ``httpx``.""" if json_body is None: @@ -95,7 +95,7 @@ def _httpx_request( ) def test_configured_generation_warning( *, - send_request: _RequestSender, + send_request: _RequestSender, # pyrefly: ignore [explicit-any] processing_time_seconds: float, expected_status: str, time_field: str, @@ -122,7 +122,7 @@ def test_configured_generation_warning( model_target_generation_warning=warning, ): create_response = send_request(_CREATE_URL, _REQUEST_BODY) - dataset_uuid = create_response.json()["uuid"] + dataset_uuid = create_response.json()["uuid"] # pyrefly: ignore [unknown-variable-type] status_response = send_request( f"{_CREATE_URL}/{dataset_uuid}/status", None, @@ -155,7 +155,7 @@ def test_generation_warning_and_failure_are_mutually_exclusive() -> None: expected_exception=ValueError, match="failure and warning configurations are mutually exclusive", ): - MockVWS( + _ = MockVWS( model_target_generation_failure=ModelTargetGenerationFailure(), model_target_generation_warning=ModelTargetGenerationWarning(), ) diff --git a/tests/mock_vws/test_model_target_retries.py b/tests/mock_vws/test_model_target_retries.py index e36ccef72..a89c8c10f 100644 --- a/tests/mock_vws/test_model_target_retries.py +++ b/tests/mock_vws/test_model_target_retries.py @@ -103,7 +103,7 @@ def send() -> requests.Response: match=r"Connection aborted\.", ), ): - send_with_transient_retries(method=HTTPMethod.GET, send=send) + _ = send_with_transient_retries(method=HTTPMethod.GET, send=send) @staticmethod def test_error_response_is_not_retried() -> None: @@ -119,7 +119,7 @@ def send() -> requests.Response: return _response(status_code=HTTPStatus.UNAUTHORIZED) with retrying_transient_real_backend_failures(): - send_with_transient_retries(method=HTTPMethod.GET, send=send) + _ = send_with_transient_retries(method=HTTPMethod.GET, send=send) assert attempts == 1 @@ -140,7 +140,7 @@ def send() -> requests.Response: return _response(status_code=HTTPStatus.BAD_GATEWAY) with retrying_transient_real_backend_failures(): - send_with_transient_retries(method=HTTPMethod.POST, send=send) + _ = send_with_transient_retries(method=HTTPMethod.POST, send=send) assert attempts == 1 @@ -184,10 +184,10 @@ def test_endpoint_send() -> None: This is the path which the cross-cutting Model Target endpoint tests take, and it is where a gateway failure has been seen. """ - responses.add( + _ = responses.add( method=responses.GET, url=_URL, status=HTTPStatus.BAD_GATEWAY ) - responses.add( + _ = responses.add( method=responses.GET, url=_URL, status=HTTPStatus.UNAUTHORIZED ) endpoint = ModelTargetEndpoint( @@ -208,10 +208,10 @@ def test_endpoint_send() -> None: @responses.activate def test_model_target_get() -> None: """``model_target_get`` retries a transient failure.""" - responses.add( + _ = responses.add( method=responses.GET, url=_URL, status=HTTPStatus.GATEWAY_TIMEOUT ) - responses.add(method=responses.GET, url=_URL, body=b"dataset") + _ = responses.add(method=responses.GET, url=_URL, body=b"dataset") with retrying_transient_real_backend_failures(): response = model_target_get(url=_URL, headers={}, timeout=30) diff --git a/tests/mock_vws/test_model_target_training_allowance.py b/tests/mock_vws/test_model_target_training_allowance.py index db0174741..be881d3cc 100644 --- a/tests/mock_vws/test_model_target_training_allowance.py +++ b/tests/mock_vws/test_model_target_training_allowance.py @@ -14,7 +14,7 @@ "eyJzY29wZSI6Im1vZGVsdGFyZ2V0cy5hbGwifQ." "c2lnbmF0dXJl" ) -_REQUEST_BODY: dict[str, Any] = { +_REQUEST_BODY: dict[str, Any] = { # pyrefly: ignore [explicit-any] "name": "dataset-name", "targetSdk": "10.18", "models": [ diff --git a/tests/mock_vws/test_model_target_web_api.py b/tests/mock_vws/test_model_target_web_api.py index a47c785e2..af6cc5d3b 100644 --- a/tests/mock_vws/test_model_target_web_api.py +++ b/tests/mock_vws/test_model_target_web_api.py @@ -50,7 +50,7 @@ ) -_VIEW: dict[str, Any] = { +_VIEW: dict[str, Any] = { # pyrefly: ignore [explicit-any] "name": "view-name", "guideViewPosition": { "translation": [0, 0, 5], @@ -60,7 +60,7 @@ @beartype -def _dataset_request(*, cad_data_url: str) -> dict[str, Any]: +def _dataset_request(*, cad_data_url: str) -> dict[str, Any]: # pyrefly: ignore [explicit-any] """Return a standard Model Target dataset request.""" return { "name": f"dataset-{uuid4().hex}", @@ -88,7 +88,7 @@ def _cad_data_blob() -> str: @beartype -def _blob_dataset_request() -> dict[str, Any]: +def _blob_dataset_request() -> dict[str, Any]: # pyrefly: ignore [explicit-any] """Return a standard dataset request with inline CAD data.""" return { "name": f"dataset-{uuid4().hex}", @@ -104,25 +104,25 @@ def _blob_dataset_request() -> dict[str, Any]: } -_MODEL: dict[str, Any] = { +_MODEL: dict[str, Any] = { # pyrefly: ignore [explicit-any] "name": "model-name", "cadDataUrl": "https://example.com/model.glb", "views": [_VIEW], } -_MODEL_WITHOUT_CAD_DATA: dict[str, Any] = { +_MODEL_WITHOUT_CAD_DATA: dict[str, Any] = { # pyrefly: ignore [explicit-any] key: value for key, value in _MODEL.items() if key != "cadDataUrl" } -_EMPTY_MODEL: dict[str, Any] = {} +_EMPTY_MODEL: dict[str, Any] = {} # pyrefly: ignore [explicit-any] -_EMPTY_VIEW: dict[str, Any] = {} +_EMPTY_VIEW: dict[str, Any] = {} # pyrefly: ignore [explicit-any] -_EMPTY_GUIDE_VIEW_POSITION: list[Any] = [] +_EMPTY_GUIDE_VIEW_POSITION: list[Any] = [] # pyrefly: ignore [explicit-any] -_EMPTY_GUIDE_VIEW_POSITION_OBJECT: dict[str, Any] = {} +_EMPTY_GUIDE_VIEW_POSITION_OBJECT: dict[str, Any] = {} # pyrefly: ignore [explicit-any] -_UNAUTHENTICATED_DATASET_REQUEST: dict[str, Any] = { +_UNAUTHENTICATED_DATASET_REQUEST: dict[str, Any] = { # pyrefly: ignore [explicit-any] "name": "dataset-name", "targetSdk": "10.18", "models": [_MODEL], @@ -226,7 +226,7 @@ def _assert_unknown_dataset(*, response: Response) -> None: response=response, status_codes=HTTPStatus.NOT_FOUND, ) - error = json.loads(s=response.text)["error"] + error = json.loads(s=response.text)["error"] # pyrefly: ignore [unknown-variable-type] assert error["code"] == "NOT_FOUND" assert error["message"] == ( "Could not find a model-view database with uuid " @@ -470,7 +470,7 @@ def test_client_credentials_management( status_codes=HTTPStatus.CREATED, ) client_id = create_response.json()["client_id"] - client_secret = create_response.json()["client_secret"] + client_secret = create_response.json()["client_secret"] # pyrefly: ignore [unknown-variable-type] list_response = model_target_get( url=f"{_VWS_HOST}/oauth2/clientcredentials", @@ -520,7 +520,7 @@ def test_client_credentials_management( response=client_token_response, status_codes=HTTPStatus.OK, ) - client_access_token = client_token_response.json()["access_token"] + client_access_token = client_token_response.json()["access_token"] # pyrefly: ignore [unknown-variable-type] insufficient_response = requests.post( url=f"{_VWS_HOST}/modeltargets/datasets", headers={ @@ -805,7 +805,7 @@ def test_wrong_content_type( "Authorization": f"Bearer {access_token}", } if content_type is None: - new_headers.pop("Content-Type", None) + _ = new_headers.pop("Content-Type", None) else: new_headers["Content-Type"] = content_type new_endpoint = dataclasses.replace( @@ -823,7 +823,7 @@ def test_wrong_content_type( response=response, status_codes=HTTPStatus.UNSUPPORTED_MEDIA_TYPE, ) - error = json.loads(s=response.text)["error"] + error = json.loads(s=response.text)["error"] # pyrefly: ignore [unknown-variable-type] assert error["code"] == "ERROR" assert error["message"] == ( "Expecting text/json or application/json body" @@ -863,7 +863,7 @@ def test_invalid_json( response=response, status_codes=HTTPStatus.BAD_REQUEST, ) - error = json.loads(s=response.text)["error"] + error = json.loads(s=response.text)["error"] # pyrefly: ignore [unknown-variable-type] assert error["code"] == "ERROR" assert error["message"].startswith("Invalid Json") assert "target" not in error @@ -901,7 +901,7 @@ def test_body_not_utf_8( response=response, status_codes=HTTPStatus.BAD_REQUEST, ) - error = json.loads(s=response.text)["error"] + error = json.loads(s=response.text)["error"] # pyrefly: ignore [unknown-variable-type] assert error["code"] == "ERROR" assert error["message"].startswith("Invalid Json") assert "target" not in error @@ -950,7 +950,7 @@ def test_body_not_json_object( response=response, status_codes=HTTPStatus.BAD_REQUEST, ) - error = json.loads(s=response.text)["error"] + error = json.loads(s=response.text)["error"] # pyrefly: ignore [unknown-variable-type] assert error["code"] == "BAD_REQUEST" assert error["message"] == ( f"Validation error for request {error['target']}" @@ -1493,7 +1493,7 @@ def test_invalid_dataset_request( response=response, status_codes=HTTPStatus.BAD_REQUEST, ) - error = response.json()["error"] + error = response.json()["error"] # pyrefly: ignore [unknown-variable-type] assert error["code"] == "BAD_REQUEST" assert error["message"] == ( f"Validation error for request {error['target']}" @@ -1532,7 +1532,7 @@ def test_advanced_model_count_exceeds_limit( response=response, status_codes=HTTPStatus.BAD_REQUEST, ) - error = response.json()["error"] + error = response.json()["error"] # pyrefly: ignore [unknown-variable-type] assert error["code"] == "BAD_REQUEST" assert {detail["message"] for detail in error["details"]} == { "names of models must be unique within a Target.", @@ -1588,7 +1588,7 @@ def test_unknown_dataset( response=response, status_codes=HTTPStatus.NOT_FOUND, ) - error = response.json()["error"] + error = response.json()["error"] # pyrefly: ignore [unknown-variable-type] assert error["code"] == "NOT_FOUND" assert error["message"] == ( "Could not find a model-view database with uuid " @@ -1705,7 +1705,7 @@ def test_state_based_dataset( response=create_response, status_codes=HTTPStatus.CREATED, ) - dataset_uuid = create_response.json()["uuid"] + dataset_uuid = create_response.json()["uuid"] # pyrefly: ignore [unknown-variable-type] delete_response = requests.delete( url=f"{_VWS_HOST}{dataset_path}/{dataset_uuid}", headers=headers, @@ -1748,7 +1748,7 @@ def test_view_states_are_a_subset( response=response, status_codes=HTTPStatus.BAD_REQUEST, ) - error = response.json()["error"] + error = response.json()["error"] # pyrefly: ignore [unknown-variable-type] assert error["code"] == "BAD_REQUEST" assert [detail["message"] for detail in error["details"]] == [ "states in entrypoint view-name' must be a subset of all states", @@ -1854,7 +1854,7 @@ def test_invalid_state_based_dataset( response=response, status_codes=HTTPStatus.BAD_REQUEST, ) - error = response.json()["error"] + error = response.json()["error"] # pyrefly: ignore [unknown-variable-type] assert error["code"] == "BAD_REQUEST" assert [detail["message"] for detail in error["details"]] == [ expected_message, @@ -1901,7 +1901,7 @@ def test_advanced_realistic_appearance_not_in_enum( response=advanced_response, status_codes=HTTPStatus.BAD_REQUEST, ) - error = advanced_response.json()["error"] + error = advanced_response.json()["error"] # pyrefly: ignore [unknown-variable-type] assert error["code"] == "BAD_REQUEST" assert [detail["message"] for detail in error["details"]] == [ '`realisticAppearance` must be one of "true", "false", "auto".` ', @@ -1951,7 +1951,7 @@ def test_processing_dataset_cannot_be_downloaded() -> None: json=_UNAUTHENTICATED_DATASET_REQUEST, timeout=30, ) - dataset_uuid = create_response.json()["uuid"] + dataset_uuid = create_response.json()["uuid"] # pyrefly: ignore [unknown-variable-type] response = requests.get( url=( f"{_VWS_HOST}/modeltargets/datasets/{dataset_uuid}/dataset" @@ -1964,7 +1964,7 @@ def test_processing_dataset_cannot_be_downloaded() -> None: response=response, status_codes=HTTPStatus.UNPROCESSABLE_ENTITY, ) - error = response.json()["error"] + error = response.json()["error"] # pyrefly: ignore [unknown-variable-type] assert error["code"] == "UNSUPPORTED_STATE" assert error["message"] == ( f"Training status for dataset {dataset_uuid} is " @@ -1993,7 +1993,7 @@ def test_failed_dataset_cannot_be_downloaded() -> None: json=_UNAUTHENTICATED_DATASET_REQUEST, timeout=30, ) - dataset_uuid = create_response.json()["uuid"] + dataset_uuid = create_response.json()["uuid"] # pyrefly: ignore [unknown-variable-type] status_response = requests.get( url=f"{_VWS_HOST}/modeltargets/datasets/{dataset_uuid}/status", headers={"Authorization": f"Bearer {_MOCK_BEARER_TOKEN}"}, @@ -2012,7 +2012,7 @@ def test_failed_dataset_cannot_be_downloaded() -> None: response=response, status_codes=HTTPStatus.UNPROCESSABLE_ENTITY, ) - error = response.json()["error"] + error = response.json()["error"] # pyrefly: ignore [unknown-variable-type] assert error["code"] == "UNSUPPORTED_STATE" assert error["message"] == ( f"Training status for dataset {dataset_uuid} is failed != done" @@ -2150,7 +2150,7 @@ def test_create_status_and_delete( response=create_response, status_codes=HTTPStatus.CREATED, ) - create_response_json: dict[str, Any] = json.loads( + create_response_json: dict[str, Any] = json.loads( # pyrefly: ignore [explicit-any] s=create_response.text, ) dataset_uuid_value = create_response_json["uuid"] @@ -2170,7 +2170,7 @@ def test_create_status_and_delete( response=status_response, status_codes=HTTPStatus.OK, ) - status_response_json: dict[str, Any] = json.loads( + status_response_json: dict[str, Any] = json.loads( # pyrefly: ignore [explicit-any] s=status_response.text, ) assert status_response_json["status"] in { @@ -2277,7 +2277,7 @@ def test_create_with_cad_data_blob( response=create_response, status_codes=HTTPStatus.CREATED, ) - create_response_json: dict[str, Any] = json.loads( + create_response_json: dict[str, Any] = json.loads( # pyrefly: ignore [explicit-any] s=create_response.text, ) dataset_uuid = create_response_json["uuid"] @@ -2513,7 +2513,7 @@ def test_client_credential_validation_errors() -> None: json={"scopes": []}, timeout=30, ) - client_id = created.json()["client_id"] + client_id = created.json()["client_id"] # pyrefly: ignore [unknown-variable-type] for content in (b"{", b'"scope"', b"[1]"): response = requests.put( url=( diff --git a/tests/mock_vws/test_query.py b/tests/mock_vws/test_query.py index 0191fe0bd..7972ebf8b 100644 --- a/tests/mock_vws/test_query.py +++ b/tests/mock_vws/test_query.py @@ -160,7 +160,7 @@ def _query_raw( def _query( *, vuforia_database: CloudDatabase, - body: dict[str, Any], + body: dict[str, Any], # pyrefly: ignore [explicit-any] ) -> Response: """Make a request to the endpoint to make an image recognition query. @@ -362,7 +362,7 @@ def test_incorrect_with_boundary( content=requests_response.content, ) handle_server_errors(response=vws_response) - assert not requests_response.text + assert not bool(requests_response.text) assert_vwq_failure( response=vws_response, status_code=HTTPStatus.UNSUPPORTED_MEDIA_TYPE, @@ -629,7 +629,7 @@ def test_match_exact( "target_timestamp": IsInstance(expected_type=int), }, } - target_timestamp = int(result["target_data"]["target_timestamp"]) + target_timestamp = int(result["target_data"]["target_timestamp"]) # pyrefly: ignore [unknown-argument-type] time_difference = abs(approximate_target_created - target_timestamp) max_time_difference = 5 assert time_difference < max_time_difference @@ -661,7 +661,7 @@ def test_low_quality_image( vws_client.wait_for_target_processed(target_id=target_id) matching_targets = cloud_reco_client.query(image=image_file) - assert not matching_targets + assert not bool(matching_targets) @staticmethod def test_match_similar( @@ -882,7 +882,7 @@ def test_default( assert_query_success(response=response) response_json = json.loads(s=response.text) - assert len(response_json["results"]) == 1 + assert len(response_json["results"]) == 1 # pyrefly: ignore [unknown-argument-type] @staticmethod @pytest.mark.parametrize(argnames="num_results", argvalues=[1, b"1", 50]) @@ -958,7 +958,7 @@ def test_out_of_range( with pytest.raises( expected_exception=MaxNumResultsOutOfRangeError, ) as exc_info: - cloud_reco_client.query( + _ = cloud_reco_client.query( image=high_quality_image, max_num_results=num_results, ) @@ -1499,7 +1499,7 @@ def test_corrupted( given. """ with pytest.raises(expected_exception=BadImageError) as exc_info: - cloud_reco_client.query(image=corrupted_image_file) + _ = cloud_reco_client.query(image=corrupted_image_file) response = exc_info.value.response @@ -1522,7 +1522,7 @@ def test_not_image(cloud_reco_client: CloudRecoService) -> None: not_image_data = b"not_image_data" with pytest.raises(expected_exception=BadImageError) as exc_info: - cloud_reco_client.query( + _ = cloud_reco_client.query( image=io.BytesIO(initial_bytes=not_image_data) ) @@ -1611,7 +1611,7 @@ def test_png(cloud_reco_client: CloudRecoService) -> None: with pytest.raises( expected_exception=RequestEntityTooLargeError ) as exc_info: - cloud_reco_client.query(image=png_too_large) + _ = cloud_reco_client.query(image=png_too_large) response = exc_info.value.response @@ -1670,7 +1670,7 @@ def test_jpeg( with pytest.raises( expected_exception=RequestEntityTooLargeError ) as exc_info: - cloud_reco_client.query(image=jpeg_too_large) + _ = cloud_reco_client.query(image=jpeg_too_large) response = exc_info.value.response @@ -1719,7 +1719,7 @@ def test_max_height( ) with pytest.raises(expected_exception=BadImageError) as exc_info: - cloud_reco_client.query(image=png_too_tall) + _ = cloud_reco_client.query(image=png_too_tall) response = exc_info.value.response @@ -1868,7 +1868,7 @@ def test_unsupported( image_content = image_buffer.getvalue() with pytest.raises(expected_exception=BadImageError) as exc_info: - cloud_reco_client.query( + _ = cloud_reco_client.query( image=io.BytesIO(initial_bytes=image_content) ) @@ -1971,7 +1971,7 @@ def test_updated_target( application_metadata=metadata_encoded, ) - calendar.timegm(tuple=time.gmtime()) + _ = calendar.timegm(tuple=time.gmtime()) vws_client.wait_for_target_processed(target_id=target_id) @@ -2219,7 +2219,7 @@ def test_inactive_project( with pytest.raises( expected_exception=InactiveProjectError ) as exc_info: - inactive_cloud_reco_client.query(image=high_quality_image) + _ = inactive_cloud_reco_client.query(image=high_quality_image) response = exc_info.value.response diff --git a/tests/mock_vws/test_reco_counts_report.py b/tests/mock_vws/test_reco_counts_report.py index 0f4735e76..985a2fea0 100644 --- a/tests/mock_vws/test_reco_counts_report.py +++ b/tests/mock_vws/test_reco_counts_report.py @@ -112,8 +112,8 @@ def test_reco_counts_report( "presigned_url", } assert response_json["result_code"] == ResultCodes.SUCCESS.value - transaction_id = response_json["transaction_id"] - assert all(char in hexdigits for char in transaction_id) + transaction_id = response_json["transaction_id"] # pyrefly: ignore [unknown-variable-type] + assert all(char in hexdigits for char in transaction_id) # pyrefly: ignore [unknown-argument-type] assert response_json["presigned_url"].startswith("https://") @staticmethod @@ -215,14 +215,14 @@ def test_download_report(*, vuforia_database: CloudDatabase) -> None: database_id=vuforia_database.database_id, month=_month_offset_from_now(months=0), ) - presigned_url = json.loads(s=response.text)["presigned_url"] + presigned_url = json.loads(s=response.text)["presigned_url"] # pyrefly: ignore [unknown-variable-type] - not_ready_response = requests.get(url=presigned_url, timeout=30) + not_ready_response = requests.get(url=presigned_url, timeout=30) # pyrefly: ignore [unknown-argument-type] assert not_ready_response.status_code == HTTPStatus.NOT_FOUND time.sleep(_GENERATION_TIME_SECONDS + 1) - ready_response = requests.get(url=presigned_url, timeout=30) + ready_response = requests.get(url=presigned_url, timeout=30) # pyrefly: ignore [unknown-argument-type] assert ready_response.status_code == HTTPStatus.OK assert ready_response.headers["Content-Type"] == "text/plain" assert ready_response.text == "target_id,reco_count\r\n" @@ -279,11 +279,11 @@ def test_seeded_recognition_counts( database_id=vuforia_database.database_id, month=_month_offset_from_now(months=-months_ago), ) - presigned_url = json.loads(s=response.text)["presigned_url"] + presigned_url = json.loads(s=response.text)["presigned_url"] # pyrefly: ignore [unknown-variable-type] time.sleep(_GENERATION_TIME_SECONDS + 1) - ready_response = requests.get(url=presigned_url, timeout=30) + ready_response = requests.get(url=presigned_url, timeout=30) # pyrefly: ignore [unknown-argument-type] assert ready_response.status_code == HTTPStatus.OK assert ready_response.text == ( "target_id,reco_count\r\n" diff --git a/tests/mock_vws/test_requests_mock_usage.py b/tests/mock_vws/test_requests_mock_usage.py index 3e95039bc..07e2e7a66 100644 --- a/tests/mock_vws/test_requests_mock_usage.py +++ b/tests/mock_vws/test_requests_mock_usage.py @@ -122,7 +122,7 @@ def _unused_local_url() -> str: """Return a URL for a local address with nothing listening on it.""" sock = socket.socket() sock.bind(("", 0)) - port = sock.getsockname()[1] + port = sock.getsockname()[1] # pyrefly: ignore [unknown-variable-type] sock.close() return f"http://localhost:{port}" @@ -140,9 +140,9 @@ def request_unmocked_address() -> None: """ sock = socket.socket() sock.bind(("", 0)) - port = sock.getsockname()[1] + port = sock.getsockname()[1] # pyrefly: ignore [unknown-variable-type] sock.close() - requests.get(url=f"http://localhost:{port}", timeout=30) + _ = requests.get(url=f"http://localhost:{port}", timeout=30) @beartype @@ -151,7 +151,7 @@ def request_mocked_address() -> None: Make a request, using `requests` to an address that is mocked by `MockVWS`. """ - requests.get( + _ = requests.get( url="https://vws.vuforia.com/summary", headers={ "Date": rfc_1123_date(), @@ -236,7 +236,7 @@ def test_delay_causes_timeout() -> None: MockVWS(response_delay_seconds=0.5), pytest.raises(expected_exception=requests.exceptions.Timeout), ): - requests.get( + _ = requests.get( url="https://vws.vuforia.com/summary", headers={ "Date": rfc_1123_date(), @@ -300,7 +300,7 @@ def test_delay_with_tuple_timeout() -> None: ): # Tuple timeout: (connect_timeout, read_timeout) # The read timeout (0.1) is less than the delay (0.5) - requests.get( + _ = requests.get( url="https://vws.vuforia.com/summary", headers={ "Date": rfc_1123_date(), @@ -321,7 +321,7 @@ def test_custom_sleep_fn_called_on_delay() -> None: response_delay_seconds=5.0, sleep_fn=calls.append, ): - requests.get( + _ = requests.get( url="https://vws.vuforia.com/summary", headers={ "Date": rfc_1123_date(), @@ -346,7 +346,7 @@ def test_custom_sleep_fn_called_on_timeout() -> None: ), pytest.raises(expected_exception=requests.exceptions.Timeout), ): - requests.get( + _ = requests.get( url="https://vws.vuforia.com/summary", headers={ "Date": rfc_1123_date(), @@ -435,7 +435,7 @@ def test_request_quota_available() -> None: mock.add_cloud_database(cloud_database=database) targets = client.list_targets() - assert not targets + assert not bool(targets) @staticmethod def test_request_quota_reached() -> None: @@ -451,7 +451,7 @@ def test_request_quota_reached() -> None: with pytest.raises( expected_exception=RequestQuotaReachedError, ) as exc_info: - client.list_targets() + _ = client.list_targets() assert_vws_failure( response=exc_info.value.response, @@ -477,7 +477,7 @@ def test_zero_limit() -> None: with pytest.raises( expected_exception=TooManyRequestsError, ) as exc_info: - client.list_targets() + _ = client.list_targets() assert_vws_failure( response=exc_info.value.response, @@ -673,14 +673,14 @@ def test_documented_limits() -> None: with MockVWS() as mock: mock.add_cloud_database(cloud_database=database) # ``GET /targets`` is limited to one request per minute. - client.list_targets() + _ = client.list_targets() with pytest.raises( expected_exception=TooManyRequestsError, ) as exc_info: - client.list_targets() + _ = client.list_targets() # Other endpoints have their own budgets. - client.get_database_summary_report() + _ = client.get_database_summary_report() assert_vws_failure( response=exc_info.value.response, @@ -721,13 +721,13 @@ def test_get_target_and_duplicates_limits( application_metadata=None, active_flag=True, ) - client.get_target_record(target_id=target_id) - client.get_duplicate_targets(target_id=target_id) + _ = client.get_target_record(target_id=target_id) + _ = client.get_duplicate_targets(target_id=target_id) with pytest.raises(expected_exception=TooManyRequestsError): - client.get_duplicate_targets(target_id=target_id) - client.get_target_record(target_id=target_id) + _ = client.get_duplicate_targets(target_id=target_id) + _ = client.get_target_record(target_id=target_id) with pytest.raises(expected_exception=TooManyRequestsError): - client.get_target_record(target_id=target_id) + _ = client.get_target_record(target_id=target_id) class TestAdditionalResultCodes: @@ -750,7 +750,7 @@ def test_target_quota_reached( with pytest.raises( expected_exception=TargetQuotaReachedError, ) as exc_info: - client.add_target( + _ = client.add_target( name="example", width=1, image=image_file_failed_state, @@ -778,7 +778,7 @@ def test_project_suspended() -> None: with pytest.raises( expected_exception=ProjectSuspendedError, ) as exc: - client.list_targets() + _ = client.list_targets() assert_vws_failure( response=exc.value.response, @@ -835,13 +835,15 @@ def test_custom_base_vws_url() -> None: with pytest.raises( expected_exception=requests.exceptions.ConnectionError ): - requests.get(url="https://vws.vuforia.com/summary", timeout=30) + _ = requests.get( + url="https://vws.vuforia.com/summary", timeout=30 + ) - requests.get( + _ = requests.get( url="https://vuforia.vws.example.com/summary", timeout=30, ) - requests.post( + _ = requests.post( url="https://cloudreco.vuforia.com/v1/query", timeout=30, ) @@ -856,16 +858,16 @@ def test_custom_base_vwq_url() -> None: with pytest.raises( expected_exception=requests.exceptions.ConnectionError ): - requests.post( + _ = requests.post( url="https://cloudreco.vuforia.com/v1/query", timeout=30, ) - requests.post( + _ = requests.post( url="https://vuforia.vwq.example.com/v1/query", timeout=30, ) - requests.get( + _ = requests.get( url="https://vws.vuforia.com/summary", timeout=30, ) @@ -882,12 +884,12 @@ def test_custom_base_vws_url_with_path_prefix() -> None: with pytest.raises( expected_exception=requests.exceptions.ConnectionError ): - requests.get( + _ = requests.get( url="https://vuforia.vws.example.com/summary", timeout=30, ) - requests.get( + _ = requests.get( url="https://vuforia.vws.example.com/prefix/summary", timeout=30, ) @@ -904,12 +906,12 @@ def test_custom_base_vwq_url_with_path_prefix() -> None: with pytest.raises( expected_exception=requests.exceptions.ConnectionError ): - requests.post( + _ = requests.post( url="https://vuforia.vwq.example.com/v1/query", timeout=30, ) - requests.post( + _ = requests.post( url="https://vuforia.vwq.example.com/prefix/v1/query", timeout=30, ) @@ -954,7 +956,7 @@ def test_vws_operations_work_with_path_prefix() -> None: def test_no_scheme() -> None: """An error if raised if a URL is given with no scheme.""" with pytest.raises(expected_exception=MissingSchemeError) as vws_exc: - MockVWS(base_vws_url="vuforia.vws.example.com") + _ = MockVWS(base_vws_url="vuforia.vws.example.com") expected = ( 'Invalid URL "vuforia.vws.example.com": No scheme supplied. ' @@ -962,7 +964,7 @@ def test_no_scheme() -> None: ) assert str(object=vws_exc.value) == expected with pytest.raises(expected_exception=MissingSchemeError) as vwq_exc: - MockVWS(base_vwq_url="vuforia.vwq.example.com") + _ = MockVWS(base_vwq_url="vuforia.vwq.example.com") expected = ( 'Invalid URL "vuforia.vwq.example.com": No scheme supplied. ' 'Perhaps you meant "https://vuforia.vwq.example.com".' @@ -988,7 +990,7 @@ def test_to_dict(high_quality_image: io.BytesIO) -> None: with MockVWS() as mock: mock.add_cloud_database(cloud_database=database) - vws_client.add_target( + _ = vws_client.add_target( name="example", width=1, image=high_quality_image, @@ -1002,7 +1004,7 @@ def test_to_dict(high_quality_image: io.BytesIO) -> None: target_dict = target.to_dict() # The dictionary is JSON dump-able - assert json.dumps(obj=target_dict) + assert bool(json.dumps(obj=target_dict)) new_target = ImageTarget.from_dict(target_dict=target_dict) assert new_target == target @@ -1039,7 +1041,7 @@ def test_to_dict_deleted(high_quality_image: io.BytesIO) -> None: target_dict = target.to_dict() # The dictionary is JSON dump-able - assert json.dumps(obj=target_dict) + assert bool(json.dumps(obj=target_dict)) new_target = ImageTarget.from_dict(target_dict=target_dict) assert new_target.delete_date == target.delete_date @@ -1106,7 +1108,7 @@ def test_round_trip_non_default_fields( target_dict = target.to_dict() # The dictionary is JSON dump-able - assert json.dumps(obj=target_dict) + assert bool(json.dumps(obj=target_dict)) new_target = ImageTarget.from_dict(target_dict=target_dict) assert new_target == target @@ -1123,7 +1125,7 @@ def test_vumark_target_to_dict() -> None: ) target_dict = vumark_target.to_dict() - assert json.dumps(obj=target_dict) + assert bool(json.dumps(obj=target_dict)) new_target = VuMarkTarget.from_dict(target_dict=target_dict) assert new_target == vumark_target @@ -1246,7 +1248,7 @@ def test_to_dict(high_quality_image: io.BytesIO) -> None: # We test a database with a target added. with MockVWS() as mock: mock.add_cloud_database(cloud_database=database) - vws_client.add_target( + _ = vws_client.add_target( name="example", width=1, image=high_quality_image, @@ -1256,7 +1258,7 @@ def test_to_dict(high_quality_image: io.BytesIO) -> None: database_dict = database.to_dict() # The dictionary is JSON dump-able - assert json.dumps(obj=database_dict) + assert bool(json.dumps(obj=database_dict)) new_database = CloudDatabase.from_dict(database_dict=database_dict) assert new_database == database @@ -1308,7 +1310,7 @@ def test_custom_request_rate_limits() -> None: ) database_dict = database.to_dict() - assert json.dumps(obj=database_dict) + assert bool(json.dumps(obj=database_dict)) new_database = CloudDatabase.from_dict(database_dict=database_dict) assert ( @@ -1386,7 +1388,7 @@ def test_round_trip_non_default_fields( database_dict = database.to_dict() # The dictionary is JSON dump-able - assert json.dumps(obj=database_dict) + assert bool(json.dumps(obj=database_dict)) new_database = CloudDatabase.from_dict(database_dict=database_dict) assert new_database == database @@ -1405,7 +1407,7 @@ def test_vumark_database_to_dict() -> None: ) database_dict = database.to_dict() - assert json.dumps(obj=database_dict) + assert bool(json.dumps(obj=database_dict)) new_database = VuMarkDatabase.from_dict(database_dict=database_dict) assert new_database == database @@ -1588,7 +1590,7 @@ def test_state_is_kept_between_uses( mock.add_cloud_database(cloud_database=database) with mock: - vws_client.add_target( + _ = vws_client.add_target( name="my-target", width=1, image=high_quality_image, @@ -1638,7 +1640,7 @@ def test_exact_match(high_quality_image: io.BytesIO) -> None: different_image_result = cloud_reco_client.query( image=re_exported_image, ) - assert not different_image_result + assert not bool(different_image_result) @staticmethod def test_custom_matcher(high_quality_image: io.BytesIO) -> None: @@ -1670,7 +1672,7 @@ def test_custom_matcher(high_quality_image: io.BytesIO) -> None: same_image_result = cloud_reco_client.query( image=high_quality_image, ) - assert not same_image_result + assert not bool(same_image_result) different_image_result = cloud_reco_client.query( image=re_exported_image, ) @@ -1721,7 +1723,7 @@ def test_structural_similarity_matcher( different_image_result = cloud_reco_client.query( image=different_high_quality_image, ) - assert not different_image_result + assert not bool(different_image_result) @staticmethod def test_results_are_ordered_by_match_score( @@ -1809,7 +1811,7 @@ def test_bool_matcher(high_quality_image: io.BytesIO) -> None: expected_exception=TypeError, match=expected_message, ): - cloud_reco_client.query(image=high_quality_image) + _ = cloud_reco_client.query(image=high_quality_image) class TestDuplicatesImageMatchers: @@ -2051,10 +2053,10 @@ def test_httpx_unmocked_address_blocked() -> None: """ sock = socket.socket() sock.bind(("", 0)) - port = sock.getsockname()[1] + port = sock.getsockname()[1] # pyrefly: ignore [unknown-variable-type] sock.close() with MockVWS(), pytest.raises(expected_exception=httpx.ConnectError): - httpx.get(url=f"http://localhost:{port}", timeout=30) + _ = httpx.get(url=f"http://localhost:{port}", timeout=30) @staticmethod def test_httpx_real_http() -> None: @@ -2063,13 +2065,13 @@ def test_httpx_real_http() -> None: """ sock = socket.socket() sock.bind(("", 0)) - port = sock.getsockname()[1] + port = sock.getsockname()[1] # pyrefly: ignore [unknown-variable-type] sock.close() with ( MockVWS(real_http=True), pytest.raises(expected_exception=httpx.ConnectError), ): - httpx.get(url=f"http://localhost:{port}", timeout=30) + _ = httpx.get(url=f"http://localhost:{port}", timeout=30) class TestHttpx2AlsoIntercepted: @@ -2114,10 +2116,10 @@ def test_httpx2_unmocked_address_blocked() -> None: """ sock = socket.socket() sock.bind(("", 0)) - port = sock.getsockname()[1] + port = sock.getsockname()[1] # pyrefly: ignore [unknown-variable-type] sock.close() with MockVWS(), pytest.raises(expected_exception=httpx2.ConnectError): - httpx2.get(url=f"http://localhost:{port}", timeout=30) + _ = httpx2.get(url=f"http://localhost:{port}", timeout=30) @staticmethod def test_httpx2_real_http() -> None: @@ -2126,13 +2128,13 @@ def test_httpx2_real_http() -> None: """ sock = socket.socket() sock.bind(("", 0)) - port = sock.getsockname()[1] + port = sock.getsockname()[1] # pyrefly: ignore [unknown-variable-type] sock.close() with ( MockVWS(real_http=True), pytest.raises(expected_exception=httpx2.ConnectError), ): - httpx2.get(url=f"http://localhost:{port}", timeout=30) + _ = httpx2.get(url=f"http://localhost:{port}", timeout=30) class TestModelTargetWebAPI: @@ -2150,7 +2152,7 @@ def test_standard_dataset_workflow() -> None: data={"grant_type": "client_credentials"}, timeout=30, ) - token = token_response.json()["access_token"] + token = token_response.json()["access_token"] # pyrefly: ignore [unknown-variable-type] headers = {"Authorization": f"Bearer {token}"} create_response = requests.post( @@ -2159,7 +2161,7 @@ def test_standard_dataset_workflow() -> None: json=_MODEL_TARGET_DATASET_REQUEST, timeout=30, ) - dataset_uuid = create_response.json()["uuid"] + dataset_uuid = create_response.json()["uuid"] # pyrefly: ignore [unknown-variable-type] status_response = requests.get( url=( @@ -2196,7 +2198,7 @@ def test_advanced_dataset_workflow() -> None: json=_MODEL_TARGET_DATASET_REQUEST, timeout=30, ) - dataset_uuid = response.json()["uuid"] + dataset_uuid = response.json()["uuid"] # pyrefly: ignore [unknown-variable-type] status_response = requests.get( url=( "https://vws.vuforia.com/modeltargets/" @@ -2221,7 +2223,7 @@ def test_dataset_download_is_reproducible() -> None: json=_MODEL_TARGET_DATASET_REQUEST, timeout=30, ) - dataset_uuid = create_response.json()["uuid"] + dataset_uuid = create_response.json()["uuid"] # pyrefly: ignore [unknown-variable-type] dataset_url = ( "https://vws.vuforia.com/modeltargets/datasets/" f"{dataset_uuid}/dataset" @@ -2294,7 +2296,7 @@ def make_request() -> requests.Response: with pytest.raises( expected_exception=requests.exceptions.ConnectionError ): - requests.get(url=summary_url, timeout=30) + _ = requests.get(url=summary_url, timeout=30) @staticmethod def test_httpx_requests_are_mocked() -> None: @@ -2320,7 +2322,7 @@ def make_request() -> httpx.Response: assert response.status_code == HTTPStatus.BAD_REQUEST with pytest.raises(expected_exception=httpx.ConnectError): - httpx.get(url=summary_url, timeout=30) + _ = httpx.get(url=summary_url, timeout=30) @staticmethod def test_httpx2_requests_are_mocked() -> None: @@ -2346,7 +2348,7 @@ def make_request() -> httpx2.Response: assert response.status_code == HTTPStatus.BAD_REQUEST with pytest.raises(expected_exception=httpx2.ConnectError): - httpx2.get(url=summary_url, timeout=30) + _ = httpx2.get(url=summary_url, timeout=30) @staticmethod def test_arguments_and_return_value() -> None: @@ -2487,7 +2489,7 @@ def test_each_call_is_isolated(high_quality_image: io.BytesIO) -> None: @mock def add_one_target() -> None: """Add a target with a name used only once per call.""" - vws_client.add_target( + _ = vws_client.add_target( name="only-one", width=1, image=high_quality_image, @@ -2529,7 +2531,7 @@ def add_inner_target() -> int: Returns: The number of targets, including the one added here. """ - vws_client.add_target( + _ = vws_client.add_target( name="inner", width=1, image=high_quality_image, @@ -2546,7 +2548,7 @@ def add_outer_target() -> tuple[int, int]: The number of targets seen by the inner call, and the number of targets seen here once the inner call has returned. """ - vws_client.add_target( + _ = vws_client.add_target( name="outer", width=1, image=high_quality_image, @@ -2559,7 +2561,7 @@ def add_outer_target() -> tuple[int, int]: inner_count, outer_count = add_outer_target() assert inner_count == targets_seen_by_inner_call assert outer_count == 1 - assert not database.targets + assert not bool(database.targets) @staticmethod def test_database_targets_are_restored( @@ -2581,7 +2583,7 @@ def test_database_targets_are_restored( @mock def add_one_target() -> None: """Add a target and inspect it on the database object.""" - vws_client.add_target( + _ = vws_client.add_target( name="only-one", width=1, image=high_quality_image, @@ -2592,7 +2594,7 @@ def add_one_target() -> None: assert target.name == "only-one" add_one_target() - assert not database.targets + assert not bool(database.targets) @staticmethod def test_exception_restores_database_targets( @@ -2616,7 +2618,7 @@ def add_one_target_then_raise() -> None: Raises: ValueError: Always. """ - vws_client.add_target( + _ = vws_client.add_target( name="only-one", width=1, image=high_quality_image, @@ -2632,7 +2634,7 @@ def add_one_target_then_raise() -> None: ): add_one_target_then_raise() - assert not database.targets + assert not bool(database.targets) @staticmethod def test_query(high_quality_image: io.BytesIO) -> None: diff --git a/tests/mock_vws/test_respx_mock_usage.py b/tests/mock_vws/test_respx_mock_usage.py index eb87fb53d..4ea717566 100644 --- a/tests/mock_vws/test_respx_mock_usage.py +++ b/tests/mock_vws/test_respx_mock_usage.py @@ -69,7 +69,7 @@ def test_response_delay_causes_httpx_timeout() -> None: transport=HTTPXTransport(), ) with pytest.raises(expected_exception=httpx.ReadTimeout): - client.get_database_summary_report() + _ = client.get_database_summary_report() assert calls == [0.1] @@ -122,7 +122,7 @@ def test_add_get_and_delete_target( client.delete_target(target_id=target_id) with pytest.raises(expected_exception=UnknownTargetError): - client.get_target_record(target_id=target_id) + _ = client.get_target_record(target_id=target_id) @staticmethod def test_nested_mocks() -> None: @@ -140,11 +140,11 @@ def test_nested_mocks() -> None: with MockVWS(base_vws_url="https://vuforia.vws.example.com"): inner_response = httpx.get(url=inner_url, timeout=30) with pytest.raises(expected_exception=httpx.ConnectError): - httpx.get(url=outer_url, timeout=30) + _ = httpx.get(url=outer_url, timeout=30) outer_response = httpx.get(url=outer_url, timeout=30) with pytest.raises(expected_exception=httpx.ConnectError): - httpx.get(url=inner_url, timeout=30) + _ = httpx.get(url=inner_url, timeout=30) assert inner_response.status_code == HTTPStatus.UNAUTHORIZED assert outer_response.status_code == HTTPStatus.UNAUTHORIZED @@ -225,7 +225,7 @@ def test_standard_dataset_status() -> None: json=_MODEL_TARGET_DATASET_REQUEST, timeout=30, ) - dataset_uuid = create_response.json()["uuid"] + dataset_uuid = create_response.json()["uuid"] # pyrefly: ignore [unknown-variable-type] status_response = httpx.get( url=( "https://vws.vuforia.com/modeltargets/datasets/" diff --git a/tests/mock_vws/test_target_list.py b/tests/mock_vws/test_target_list.py index 47f7935e7..ffeb6b4be 100644 --- a/tests/mock_vws/test_target_list.py +++ b/tests/mock_vws/test_target_list.py @@ -30,7 +30,7 @@ def test_deleted( ) -> None: """Deleted targets are not returned in the list.""" vws_client.delete_target(target_id=target_id) - assert not vws_client.list_targets() + assert not bool(vws_client.list_targets()) @staticmethod def test_order_is_upload_date_then_target_id( @@ -69,4 +69,4 @@ class TestInactiveProject: def test_inactive_project(inactive_vws_client: VWS) -> None: """The project's active state does not affect the target list.""" # No exception is raised. - inactive_vws_client.list_targets() + _ = inactive_vws_client.list_targets() diff --git a/tests/mock_vws/test_target_summary.py b/tests/mock_vws/test_target_summary.py index 347728f24..09f2bc249 100644 --- a/tests/mock_vws/test_target_summary.py +++ b/tests/mock_vws/test_target_summary.py @@ -263,6 +263,6 @@ class TestInactiveProject: def test_inactive_project(inactive_vws_client: VWS) -> None: """The project's active state does not affect getting a target.""" with pytest.raises(expected_exception=UnknownTargetError): - inactive_vws_client.get_target_summary_report( + _ = inactive_vws_client.get_target_summary_report( target_id=uuid.uuid4().hex, ) diff --git a/tests/mock_vws/test_unexpected_json.py b/tests/mock_vws/test_unexpected_json.py index 497119268..9fb68d2da 100644 --- a/tests/mock_vws/test_unexpected_json.py +++ b/tests/mock_vws/test_unexpected_json.py @@ -72,7 +72,7 @@ def test_does_not_take_data(endpoint: Endpoint) -> None: if netloc == "cloudreco.vuforia.com": # The multipart/formdata boundary is no longer in the given # content. - assert not response.text + assert not bool(response.text) assert_vwq_failure( response=response, status_code=HTTPStatus.UNSUPPORTED_MEDIA_TYPE, @@ -84,5 +84,5 @@ def test_does_not_take_data(endpoint: Endpoint) -> None: return assert response.status_code == HTTPStatus.BAD_REQUEST - assert not response.text + assert not bool(response.text) assert "Content-Type" not in response.headers diff --git a/tests/mock_vws/test_update_target.py b/tests/mock_vws/test_update_target.py index 57b62ebc0..91882f068 100644 --- a/tests/mock_vws/test_update_target.py +++ b/tests/mock_vws/test_update_target.py @@ -37,7 +37,7 @@ def _update_target( *, vws_client: VWS, - data: dict[str, Any], + data: dict[str, Any], # pyrefly: ignore [explicit-any] target_id: str, content_type: str, ) -> Response: @@ -99,7 +99,7 @@ def test_content_types( with pytest.raises( expected_exception=TargetStatusNotSuccessError ) as exc: - _update_target( + _ = _update_target( vws_client=vws_client, data={"name": "Adam"}, target_id=target_id, @@ -135,7 +135,7 @@ def test_empty_content_type( with pytest.raises( expected_exception=AuthenticationFailureError ) as exc: - _update_target( + _ = _update_target( vws_client=vws_client, data={"name": "Adam"}, target_id=target_id, @@ -197,7 +197,7 @@ def test_invalid_extra_data( given. """ with pytest.raises(expected_exception=FailError) as exc: - _update_target( + _ = _update_target( vws_client=vws_client, data={"extra_thing": 1}, target_id=target_id, @@ -232,7 +232,7 @@ def test_width_invalid( original_width = target_details.target_record.width with pytest.raises(expected_exception=FailError) as exc: - _update_target( + _ = _update_target( vws_client=vws_client, data={"width": width}, target_id=target_id, @@ -311,7 +311,7 @@ def test_invalid( flags. """ with pytest.raises(expected_exception=FailError) as exc: - _update_target( + _ = _update_target( vws_client=vws_client, data={"active_flag": desired_active_flag}, target_id=target_id, @@ -363,7 +363,7 @@ def test_invalid_type( ) -> None: """Non-string values cannot be given as valid application metadata.""" with pytest.raises(expected_exception=FailError) as exc: - _update_target( + _ = _update_target( vws_client=vws_client, data={"application_metadata": invalid_metadata}, target_id=target_id, @@ -526,7 +526,7 @@ def test_name_invalid( ) -> None: """A target's name must be a string of length 0 < N < 65.""" with pytest.raises(expected_exception=VWSError) as exc: - _update_target( + _ = _update_target( vws_client=vws_client, data={"name": name}, target_id=target_id, @@ -745,7 +745,7 @@ def test_not_base64_encoded_processable( not a valid image. """ with pytest.raises(expected_exception=BadImageError) as exc: - _update_target( + _ = _update_target( vws_client=vws_client, data={"image": not_base64_encoded_processable}, target_id=target_id, @@ -772,7 +772,7 @@ def test_not_base64_encoded_not_processable( a "Fail" response. """ with pytest.raises(expected_exception=FailError) as exc: - _update_target( + _ = _update_target( vws_client=vws_client, data={"image": not_base64_encoded_not_processable}, target_id=target_id, @@ -817,7 +817,7 @@ def test_invalid_type( ) -> None: """If the given image is not a string, a `Fail` result is returned.""" with pytest.raises(expected_exception=FailError) as exc: - _update_target( + _ = _update_target( vws_client=vws_client, data={"image": invalid_type_image}, target_id=target_id, diff --git a/tests/mock_vws/test_vumark_generation_api.py b/tests/mock_vws/test_vumark_generation_api.py index 4421eb763..16cd715bf 100644 --- a/tests/mock_vws/test_vumark_generation_api.py +++ b/tests/mock_vws/test_vumark_generation_api.py @@ -190,7 +190,7 @@ def test_empty_instance_id( server_secret_key=vumark_vuforia_database.server_secret_key, ) with pytest.raises(expected_exception=InvalidInstanceIdError) as exc: - vumark_client.generate_vumark_instance( + _ = vumark_client.generate_vumark_instance( target_id=vumark_vuforia_database.target_id, instance_id="", accept=VuMarkAccept.PNG, @@ -288,7 +288,7 @@ def test_non_vumark_database( application_metadata=None, ) with pytest.raises(expected_exception=InvalidTargetTypeError) as exc: - vumark_client.generate_vumark_instance( + _ = vumark_client.generate_vumark_instance( target_id=target_id, instance_id=uuid4().hex, accept=VuMarkAccept.PNG, @@ -349,7 +349,7 @@ def test_processing_target( with pytest.raises( expected_exception=TargetStatusNotSuccessError, ) as exc: - vumark_client.generate_vumark_instance( + _ = vumark_client.generate_vumark_instance( target_id=vumark_vuforia_database.processing_target_id, instance_id=uuid4().hex, accept=VuMarkAccept.PNG, diff --git a/tests/mock_vws/utils/__init__.py b/tests/mock_vws/utils/__init__.py index 29419400e..072bd212e 100644 --- a/tests/mock_vws/utils/__init__.py +++ b/tests/mock_vws/utils/__init__.py @@ -203,7 +203,7 @@ def make_image_file( ) image.save(fp=image_buffer, format=file_format) - image_buffer.seek(0) + _ = image_buffer.seek(0) return image_buffer @@ -224,7 +224,7 @@ def make_single_color_image_file(*, width: int, height: int) -> io.BytesIO: image_buffer = io.BytesIO() image = Image.new(mode="L", size=(width, height)) image.save(fp=image_buffer, format="PNG") - image_buffer.seek(0) + _ = image_buffer.seek(0) return image_buffer diff --git a/tests/mock_vws/utils/assertions.py b/tests/mock_vws/utils/assertions.py index 6c2fc4f22..db98e9769 100644 --- a/tests/mock_vws/utils/assertions.py +++ b/tests/mock_vws/utils/assertions.py @@ -95,10 +95,10 @@ def assert_valid_transaction_id( Raises: AssertionError: The response does not include a valid transaction ID. """ - transaction_id = json.loads(s=response.text)["transaction_id"] + transaction_id = json.loads(s=response.text)["transaction_id"] # pyrefly: ignore [unknown-variable-type] expected_transaction_id_length = 32 - assert len(transaction_id) == expected_transaction_id_length - assert all(char in hexdigits for char in transaction_id) + assert len(transaction_id) == expected_transaction_id_length # pyrefly: ignore [unknown-argument-type] + assert all(char in hexdigits for char in transaction_id) # pyrefly: ignore [unknown-argument-type] @beartype @@ -143,7 +143,7 @@ def assert_vws_response( given codes. """ assert response.status_code == status_code - response_result_code = json.loads(s=response.text)["result_code"] + response_result_code = json.loads(s=response.text)["result_code"] # pyrefly: ignore [unknown-variable-type] assert response_result_code == result_code.value response_header_keys = { "connection", @@ -285,15 +285,15 @@ def assert_query_success(*, response: Response) -> None: "query_id", } - query_id = json.loads(s=response.text)["query_id"] + query_id = json.loads(s=response.text)["query_id"] # pyrefly: ignore [unknown-variable-type] expected_query_id_length = 32 - assert len(query_id) == expected_query_id_length - assert all(char in hexdigits for char in query_id) + assert len(query_id) == expected_query_id_length # pyrefly: ignore [unknown-argument-type] + assert all(char in hexdigits for char in query_id) # pyrefly: ignore [unknown-argument-type] assert json.loads(s=response.text)["result_code"] == "Success" assert_valid_date_header(response=response) copied_response_headers = response.headers.copy() - copied_response_headers.pop("Date") + _ = copied_response_headers.pop("Date") # In the mock, all responses have the ``Content-Encoding`` ``gzip``. # In the real Vuforia, some do and some do not. From 214d1a12f7b7b14d2eba7a37c50a9c1f064ea581 Mon Sep 17 00:00:00 2001 From: Adam Dangoor Date: Tue, 8 Sep 2026 10:43:53 +0100 Subject: [PATCH 2/4] Reconcile validator context refactor --- src/mock_vws/_services_validators/active_flag_validators.py | 4 ++-- src/mock_vws/_services_validators/context.py | 4 ++-- src/mock_vws/_services_validators/image_validators.py | 4 ++-- src/mock_vws/_services_validators/metadata_validators.py | 6 +++--- src/mock_vws/_services_validators/width_validators.py | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/mock_vws/_services_validators/active_flag_validators.py b/src/mock_vws/_services_validators/active_flag_validators.py index e84171b55..58eab5c40 100644 --- a/src/mock_vws/_services_validators/active_flag_validators.py +++ b/src/mock_vws/_services_validators/active_flag_validators.py @@ -26,9 +26,9 @@ def validate_active_flag(*, context: ValidatorContext) -> None: if "active_flag" not in request_json: return - active_flag = request_json["active_flag"] # pyrefly: ignore [unknown-variable-type] + active_flag = request_json["active_flag"] - if active_flag in {True, False, None}: # pyrefly: ignore [unknown-argument-type] + if active_flag in {True, False, None}: return _LOGGER.warning( diff --git a/src/mock_vws/_services_validators/context.py b/src/mock_vws/_services_validators/context.py index 8f85bd760..62d9aafba 100644 --- a/src/mock_vws/_services_validators/context.py +++ b/src/mock_vws/_services_validators/context.py @@ -16,7 +16,7 @@ @beartype -def _is_json_object(value: object, /) -> TypeIs[dict[str, Any]]: +def _is_json_object(value: object, /) -> TypeIs[dict[str, Any]]: # pyrefly: ignore [explicit-any] """Return whether a decoded JSON value is an object. JSON object keys are always strings, so a ``dict`` from ``json.loads`` @@ -77,7 +77,7 @@ class ValidatorContext: allowed_for_inactive_cloud_project: bool @cached_property - def request_json(self) -> dict[str, Any]: + def request_json(self) -> dict[str, Any]: # pyrefly: ignore [explicit-any] """The request body parsed as a JSON object. A route's JSON validator runs before any validator which reads this, diff --git a/src/mock_vws/_services_validators/image_validators.py b/src/mock_vws/_services_validators/image_validators.py index a0f5782c6..ee12cfafe 100644 --- a/src/mock_vws/_services_validators/image_validators.py +++ b/src/mock_vws/_services_validators/image_validators.py @@ -32,12 +32,12 @@ def validate_image_data_type(*, context: ValidatorContext) -> None: if "image" not in request_json: return - image = request_json["image"] # pyrefly: ignore [unknown-variable-type] + image = request_json["image"] if isinstance(image, str): return - _LOGGER.warning('Image data is not a string: "%s"', image) # pyrefly: ignore [unknown-argument-type] + _LOGGER.warning('Image data is not a string: "%s"', image) raise FailError(status_code=HTTPStatus.BAD_REQUEST) diff --git a/src/mock_vws/_services_validators/metadata_validators.py b/src/mock_vws/_services_validators/metadata_validators.py index d898800a2..1568efaef 100644 --- a/src/mock_vws/_services_validators/metadata_validators.py +++ b/src/mock_vws/_services_validators/metadata_validators.py @@ -33,7 +33,7 @@ def validate_metadata_size(*, context: ValidatorContext) -> None: application_metadata = request_json.get("application_metadata") if application_metadata is None: return - decoded = decode_base64(encoded_data=application_metadata) # pyrefly: ignore [unknown-argument-type] + decoded = decode_base64(encoded_data=application_metadata) max_metadata_bytes = 1024 * 1024 - 1 if len(decoded) <= max_metadata_bytes: @@ -61,7 +61,7 @@ def validate_metadata_encoding(*, context: ValidatorContext) -> None: return try: - _ = decode_base64(encoded_data=application_metadata) # pyrefly: ignore [unknown-argument-type] + _ = decode_base64(encoded_data=application_metadata) except binascii.Error as exc: _LOGGER.warning(msg="The application metadata is not base64 encoded.") raise FailError(status_code=HTTPStatus.UNPROCESSABLE_ENTITY) from exc @@ -82,7 +82,7 @@ def validate_metadata_type(*, context: ValidatorContext) -> None: if "application_metadata" not in request_json: return - application_metadata = request_json["application_metadata"] # pyrefly: ignore [unknown-variable-type] + application_metadata = request_json["application_metadata"] if application_metadata is None or isinstance(application_metadata, str): return diff --git a/src/mock_vws/_services_validators/width_validators.py b/src/mock_vws/_services_validators/width_validators.py index 454141359..fa5b7bbdc 100644 --- a/src/mock_vws/_services_validators/width_validators.py +++ b/src/mock_vws/_services_validators/width_validators.py @@ -25,7 +25,7 @@ def validate_width(*, context: ValidatorContext) -> None: if "width" not in request_json: return - width = request_json["width"] # pyrefly: ignore [unknown-variable-type] + width = request_json["width"] width_is_number = isinstance(width, int | float) width_positive = width_is_number and width > 0 From 862f6b6983c1d51e5a6a9438c74c4c52fd91ab9d Mon Sep 17 00:00:00 2001 From: Adam Dangoor Date: Tue, 8 Sep 2026 11:00:57 +0100 Subject: [PATCH 3/4] Preserve runtime normalization under Pyrefly all --- src/mock_vws/decorators.py | 3 ++- src/mock_vws/target.py | 10 +++++----- tests/mock_vws/test_docker.py | 8 ++++---- tests/mock_vws/test_flask_app_usage.py | 6 +++--- tests/mock_vws/test_model_target_retries.py | 10 ++++++---- tests/mock_vws/test_requests_mock_usage.py | 16 ++++++++-------- tests/mock_vws/utils/retries.py | 3 ++- 7 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/mock_vws/decorators.py b/src/mock_vws/decorators.py index 9447e0bc2..dc957c623 100644 --- a/src/mock_vws/decorators.py +++ b/src/mock_vws/decorators.py @@ -206,7 +206,8 @@ def __init__( cloud_query_failure_response=cloud_query_failure_response, duplicate_match_checker=duplicate_match_checker, query_match_checker=query_match_checker, - processing_time_seconds=processing_time_seconds, + # Runtime callers may pass integers accepted by the numeric tower. + processing_time_seconds=float(processing_time_seconds), # pyrefly: ignore [unnecessary-type-conversion] model_target_generation_failure=model_target_generation_failure, model_target_failure_response=model_target_failure_response, model_target_generation_warning=model_target_generation_warning, diff --git a/src/mock_vws/target.py b/src/mock_vws/target.py index a70622cbc..4cbe420d0 100644 --- a/src/mock_vws/target.py +++ b/src/mock_vws/target.py @@ -127,7 +127,7 @@ def status(self) -> str: suitable the target is for detection. """ processing_time = datetime.timedelta( - seconds=self.processing_time_seconds, + seconds=float(self.processing_time_seconds), # pyrefly: ignore [unnecessary-type-conversion] ) timezone = self.upload_date.tzinfo @@ -151,7 +151,7 @@ def tracking_rating(self) -> int: # That this is half of the total processing time is unrealistic. # In VWS it is not a constant percentage: it was observed as # roughly one second of a roughly thirty second processing time. - seconds=self.processing_time_seconds / 2, + seconds=float(self.processing_time_seconds) / 2, # pyrefly: ignore [unnecessary-type-conversion] ) timezone = self.upload_date.tzinfo @@ -231,7 +231,7 @@ def to_dict(self) -> ImageTargetDict: "width": self.width, "image_base64": image_base64, "active_flag": self.active_flag, - "processing_time_seconds": self.processing_time_seconds, + "processing_time_seconds": float(self.processing_time_seconds), # pyrefly: ignore [unnecessary-type-conversion] "application_metadata": self.application_metadata, "target_id": self.target_id, "last_modified_date": self.last_modified_date.isoformat(), @@ -268,7 +268,7 @@ def status(self) -> str: VuMark targets always succeed after processing. """ processing_time = datetime.timedelta( - seconds=self.processing_time_seconds, + seconds=float(self.processing_time_seconds), # pyrefly: ignore [unnecessary-type-conversion] ) timezone = self.upload_date.tzinfo @@ -305,7 +305,7 @@ def to_dict(self) -> VuMarkTargetDict: return { "target_id": self.target_id, "name": self.name, - "processing_time_seconds": self.processing_time_seconds, + "processing_time_seconds": float(self.processing_time_seconds), # pyrefly: ignore [unnecessary-type-conversion] "last_modified_date": self.last_modified_date.isoformat(), "upload_date": self.upload_date.isoformat(), } diff --git a/tests/mock_vws/test_docker.py b/tests/mock_vws/test_docker.py index 1117aabae..46609f658 100644 --- a/tests/mock_vws/test_docker.py +++ b/tests/mock_vws/test_docker.py @@ -643,18 +643,18 @@ def test_request_rate_limit(*, mock_deployment: _MockDeployment) -> None: _create_cloud_database(deployment=mock_deployment, database=database) vws_client = _vws_client(deployment=mock_deployment, database=database) - _ = vws_client.list_targets() + _targets = vws_client.list_targets() with pytest.raises(expected_exception=TooManyRequestsError): - _ = vws_client.list_targets() + _targets = vws_client.list_targets() # Other endpoints are not limited. - _ = vws_client.get_database_summary_report() + _summary = vws_client.get_database_summary_report() mock_deployment.vws_container.restart() wait_for_health_check(container=mock_deployment.vws_container) - _ = vws_client.list_targets() + _targets = vws_client.list_targets() def test_deleted_database(*, mock_deployment: _MockDeployment) -> None: diff --git a/tests/mock_vws/test_flask_app_usage.py b/tests/mock_vws/test_flask_app_usage.py index d980768a9..b5c4dda34 100644 --- a/tests/mock_vws/test_flask_app_usage.py +++ b/tests/mock_vws/test_flask_app_usage.py @@ -258,12 +258,12 @@ def test_per_endpoint_limits() -> None: server_secret_key=database.server_secret_key, ) - _ = client.list_targets() + _targets = client.list_targets() with pytest.raises(expected_exception=TooManyRequestsError): - _ = client.list_targets() + _targets = client.list_targets() # Other endpoints are not limited. - _ = client.get_database_summary_report() + _summary = client.get_database_summary_report() class TestRecognitionCounts: diff --git a/tests/mock_vws/test_model_target_retries.py b/tests/mock_vws/test_model_target_retries.py index a89c8c10f..c4e100dc7 100644 --- a/tests/mock_vws/test_model_target_retries.py +++ b/tests/mock_vws/test_model_target_retries.py @@ -184,10 +184,10 @@ def test_endpoint_send() -> None: This is the path which the cross-cutting Model Target endpoint tests take, and it is where a gateway failure has been seen. """ - _ = responses.add( + responses.add( # pyrefly: ignore [unused-call-result] method=responses.GET, url=_URL, status=HTTPStatus.BAD_GATEWAY ) - _ = responses.add( + responses.add( # pyrefly: ignore [unused-call-result] method=responses.GET, url=_URL, status=HTTPStatus.UNAUTHORIZED ) endpoint = ModelTargetEndpoint( @@ -208,10 +208,12 @@ def test_endpoint_send() -> None: @responses.activate def test_model_target_get() -> None: """``model_target_get`` retries a transient failure.""" - _ = responses.add( + responses.add( # pyrefly: ignore [unused-call-result] method=responses.GET, url=_URL, status=HTTPStatus.GATEWAY_TIMEOUT ) - _ = responses.add(method=responses.GET, url=_URL, body=b"dataset") + responses.add( # pyrefly: ignore [unused-call-result] + method=responses.GET, url=_URL, body=b"dataset" + ) with retrying_transient_real_backend_failures(): response = model_target_get(url=_URL, headers={}, timeout=30) diff --git a/tests/mock_vws/test_requests_mock_usage.py b/tests/mock_vws/test_requests_mock_usage.py index 07e2e7a66..35ab0698a 100644 --- a/tests/mock_vws/test_requests_mock_usage.py +++ b/tests/mock_vws/test_requests_mock_usage.py @@ -673,14 +673,14 @@ def test_documented_limits() -> None: with MockVWS() as mock: mock.add_cloud_database(cloud_database=database) # ``GET /targets`` is limited to one request per minute. - _ = client.list_targets() + _targets = client.list_targets() with pytest.raises( expected_exception=TooManyRequestsError, ) as exc_info: - _ = client.list_targets() + _targets = client.list_targets() # Other endpoints have their own budgets. - _ = client.get_database_summary_report() + _summary = client.get_database_summary_report() assert_vws_failure( response=exc_info.value.response, @@ -721,13 +721,13 @@ def test_get_target_and_duplicates_limits( application_metadata=None, active_flag=True, ) - _ = client.get_target_record(target_id=target_id) - _ = client.get_duplicate_targets(target_id=target_id) + _target = client.get_target_record(target_id=target_id) + _duplicates = client.get_duplicate_targets(target_id=target_id) with pytest.raises(expected_exception=TooManyRequestsError): - _ = client.get_duplicate_targets(target_id=target_id) - _ = client.get_target_record(target_id=target_id) + _duplicates = client.get_duplicate_targets(target_id=target_id) + _target = client.get_target_record(target_id=target_id) with pytest.raises(expected_exception=TooManyRequestsError): - _ = client.get_target_record(target_id=target_id) + _target = client.get_target_record(target_id=target_id) class TestAdditionalResultCodes: diff --git a/tests/mock_vws/utils/retries.py b/tests/mock_vws/utils/retries.py index f89525c31..c6e4826bd 100644 --- a/tests/mock_vws/utils/retries.py +++ b/tests/mock_vws/utils/retries.py @@ -17,7 +17,8 @@ # ``pytest-retry`` checks whether the type of the exception which failed a # test is *in* this tuple, so a subclass of a listed type is not retried. -# ``requests`` raises the ``Timeout`` subclasses below, never ``Timeout`` +# ``requests`` raises the derived ``Timeout`` exceptions below, never +# ``Timeout`` # itself, so each one is listed. ``Timeout`` and ``ConnectionError`` stay # for the ``tenacity`` retries, which do use ``isinstance``. TRANSIENT_VWS_EXCEPTIONS = ( From 9f13ce8354ed72abe126d50d1c006f3d30eacec6 Mon Sep 17 00:00:00 2001 From: Adam Dangoor Date: Tue, 8 Sep 2026 11:10:04 +0100 Subject: [PATCH 4/4] Use documented call results --- README.rst | 6 +++--- docs/source/basic-example.rst | 4 ++-- docs/source/httpx-example.rst | 2 +- docs/source/httpx2-example.rst | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.rst b/README.rst index 2f94c5e77..7b17a0999 100644 --- a/README.rst +++ b/README.rst @@ -32,7 +32,7 @@ This requires Python |minimum-python-version|\+. database = CloudDatabase() mock.add_cloud_database(cloud_database=database) # This will use the Vuforia mock. - requests.get(url="https://vws.vuforia.com/summary", timeout=30) + _ = requests.get(url="https://vws.vuforia.com/summary", timeout=30) ``MockVWS`` also intercepts `httpx`_ requests: @@ -49,7 +49,7 @@ This requires Python |minimum-python-version|\+. database = CloudDatabase() mock.add_cloud_database(cloud_database=database) # This will use the Vuforia mock. - httpx.get(url="https://vws.vuforia.com/summary", timeout=30) + _ = httpx.get(url="https://vws.vuforia.com/summary", timeout=30) ``MockVWS`` also intercepts `HTTPX2`_ requests, with no need for ``httpx2.alias_httpx()``: @@ -66,7 +66,7 @@ This requires Python |minimum-python-version|\+. database = CloudDatabase() mock.add_cloud_database(cloud_database=database) # This will use the Vuforia mock. - httpx2.get(url="https://vws.vuforia.com/summary", timeout=30) + _ = httpx2.get(url="https://vws.vuforia.com/summary", timeout=30) Asynchronous ``httpx`` and `HTTPX2`_ clients are intercepted as well. diff --git a/docs/source/basic-example.rst b/docs/source/basic-example.rst index f15d2cc4f..55a51e5ec 100644 --- a/docs/source/basic-example.rst +++ b/docs/source/basic-example.rst @@ -13,7 +13,7 @@ database = CloudDatabase() mock.add_cloud_database(cloud_database=database) # This will use the Vuforia mock. - requests.get(url="https://vws.vuforia.com/summary", timeout=30) + _ = requests.get(url="https://vws.vuforia.com/summary", timeout=30) By default, an exception will be raised if any requests to unmocked addresses are made. @@ -35,7 +35,7 @@ A ``MockVWS`` instance can also decorate a function: @mock def get_summary() -> None: """Make a request which uses the Vuforia mock.""" - requests.get(url="https://vws.vuforia.com/summary", timeout=30) + _ = requests.get(url="https://vws.vuforia.com/summary", timeout=30) get_summary() diff --git a/docs/source/httpx-example.rst b/docs/source/httpx-example.rst index 0a74e9c82..980d994f2 100644 --- a/docs/source/httpx-example.rst +++ b/docs/source/httpx-example.rst @@ -13,6 +13,6 @@ database = CloudDatabase() mock.add_cloud_database(cloud_database=database) # This will use the Vuforia mock. - httpx.get(url="https://vws.vuforia.com/summary", timeout=30) + _ = httpx.get(url="https://vws.vuforia.com/summary", timeout=30) .. _httpx: https://pypi.org/project/httpx/ diff --git a/docs/source/httpx2-example.rst b/docs/source/httpx2-example.rst index 9d131406b..ecb774a18 100644 --- a/docs/source/httpx2-example.rst +++ b/docs/source/httpx2-example.rst @@ -13,7 +13,7 @@ database = CloudDatabase() mock.add_cloud_database(cloud_database=database) # This will use the Vuforia mock. - httpx2.get(url="https://vws.vuforia.com/summary", timeout=30) + _ = httpx2.get(url="https://vws.vuforia.com/summary", timeout=30) Asynchronous ``httpx`` and `HTTPX2`_ clients are intercepted as well.