From e39f78c96f1e9255c00b9140db886adbe4ab0745 Mon Sep 17 00:00:00 2001 From: Adam Dangoor Date: Tue, 8 Sep 2026 10:16:49 +0100 Subject: [PATCH 1/3] Use the pyrefly all preset --- conftest.py | 2 +- docs/source/index.rst | 4 +- pyproject.toml | 2 +- spelling_private_dict.txt | 1 + src/vws/_image_utils.py | 4 +- src/vws/_model_targets.py | 8 +-- src/vws/async_model_target_service.py | 3 +- src/vws/async_query.py | 10 +-- src/vws/async_vumark_service.py | 5 +- src/vws/async_vws.py | 13 ++-- src/vws/exceptions/model_target_exceptions.py | 15 ++-- src/vws/exceptions/vws_exceptions.py | 8 ++- src/vws/model_target_service.py | 5 +- src/vws/query.py | 10 +-- src/vws/reports.py | 20 +++--- src/vws/transports.py | 15 ++-- src/vws/vumark_service.py | 5 +- src/vws/vws.py | 17 +++-- tests/conftest.py | 2 +- tests/test_async_cloud_reco_exceptions.py | 2 +- tests/test_async_model_targets.py | 14 ++-- tests/test_async_vws.py | 6 +- tests/test_cloud_reco_exceptions.py | 14 ++-- tests/test_model_targets.py | 72 ++++++++++--------- tests/test_query.py | 8 +-- tests/test_transports.py | 26 +++---- tests/test_vws.py | 32 ++++----- tests/test_vws_exceptions.py | 36 +++++----- 28 files changed, 187 insertions(+), 172 deletions(-) diff --git a/conftest.py b/conftest.py index e4c927947..1fb508556 100644 --- a/conftest.py +++ b/conftest.py @@ -28,7 +28,7 @@ def fixture_make_image_file( """ new_image = Path("high_quality_image.jpg") buffer = high_quality_image.getvalue() - new_image.write_bytes(data=buffer) + _ = new_image.write_bytes(data=buffer) yield new_image.unlink() diff --git a/docs/source/index.rst b/docs/source/index.rst index 017bfb52f..e1c26ba02 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -108,7 +108,7 @@ The report is generated in the background, and the URL it is served from expires } # This database has no targets, so nothing has been recognized. - assert not reco_counts_by_target_id + assert reco_counts_by_target_id == {} Model Targets ------------- @@ -218,7 +218,7 @@ Transports are available for `requests`_, `httpx`_ and `HTTPX2`_. ) # This database has no targets. - assert not vws_client.list_targets() + assert vws_client.list_targets() == [] .. _requests: https://pypi.org/project/requests/ .. _httpx: https://pypi.org/project/httpx/ diff --git a/pyproject.toml b/pyproject.toml index 5a31062ed..acf5b440b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -405,7 +405,7 @@ plugins = [ [tool.pyrefly] errors.non-exhaustive-match = "error" -preset = "strict" +preset = "all" [tool.pyright] typeCheckingMode = "strict" diff --git a/spelling_private_dict.txt b/spelling_private_dict.txt index 49fd5ec46..a3e84d77c 100644 --- a/spelling_private_dict.txt +++ b/spelling_private_dict.txt @@ -91,6 +91,7 @@ plugins png pragma py +pyrefly pyright pytest readme diff --git a/src/vws/_image_utils.py b/src/vws/_image_utils.py index 58ab58bfb..6f2997741 100644 --- a/src/vws/_image_utils.py +++ b/src/vws/_image_utils.py @@ -12,7 +12,7 @@ def get_image_data(image: ImageType) -> bytes: """Get the data of an image file.""" original_tell = image.tell() - image.seek(0) + _ = image.seek(0) image_data = image.read() - image.seek(original_tell) + _ = image.seek(original_tell) return image_data diff --git a/src/vws/_model_targets.py b/src/vws/_model_targets.py index b0027a702..b8f52615f 100644 --- a/src/vws/_model_targets.py +++ b/src/vws/_model_targets.py @@ -162,7 +162,7 @@ def dataset_download_path( @beartype(conf=BeartypeConf(is_pep484_tower=True)) -def _view_dict(*, view: ModelTargetView) -> dict[str, Any]: +def _view_dict(*, view: ModelTargetView) -> dict[str, Any]: # pyrefly: ignore [explicit-any] """Get the request representation of a guide view. Args: @@ -171,7 +171,7 @@ def _view_dict(*, view: ModelTargetView) -> dict[str, Any]: Returns: The guide view, as it is sent to Vuforia. """ - view_dict: dict[str, Any] = { + view_dict: dict[str, Any] = { # pyrefly: ignore [explicit-any] "name": view.name, "guideViewPosition": { "rotation": list(view.guide_view_position.rotation), @@ -185,7 +185,7 @@ def _view_dict(*, view: ModelTargetView) -> dict[str, Any]: @beartype(conf=BeartypeConf(is_pep484_tower=True)) -def _model_dict(*, model: ModelTargetModel) -> dict[str, Any]: +def _model_dict(*, model: ModelTargetModel) -> dict[str, Any]: # pyrefly: ignore [explicit-any] """Get the request representation of a model. Args: @@ -194,7 +194,7 @@ def _model_dict(*, model: ModelTargetModel) -> dict[str, Any]: Returns: The model, as it is sent to Vuforia. """ - model_dict: dict[str, Any] = {"name": model.name} + model_dict: dict[str, Any] = {"name": model.name} # pyrefly: ignore [explicit-any] optional_values: dict[str, str | None] = { "automaticColoring": model.automatic_coloring, "cadDataBlob": model.cad_data_blob, diff --git a/src/vws/async_model_target_service.py b/src/vws/async_model_target_service.py index 67a5e901c..1a87aa0dd 100644 --- a/src/vws/async_model_target_service.py +++ b/src/vws/async_model_target_service.py @@ -165,9 +165,10 @@ async def make_request( Vuforia is rate limiting access. """ access_token = await self.get_access_token() + request_headers = extra_headers if extra_headers is not None else {} headers = { "Authorization": f"Bearer {access_token}", - **(extra_headers or {}), + **request_headers, } response = await self._transport( diff --git a/src/vws/async_query.py b/src/vws/async_query.py index ec0704ef4..7cc4d1d76 100644 --- a/src/vws/async_query.py +++ b/src/vws/async_query.py @@ -130,7 +130,7 @@ async def query( targets. """ image_content = _get_image_data(image=image) - body: dict[str, Any] = { + body: dict[str, Any] = { # pyrefly: ignore [explicit-any] "image": ( "image.jpeg", image_content, @@ -138,7 +138,7 @@ async def query( ), "max_num_results": ( None, - int(max_num_results), + max_num_results, "text/plain", ), "include_target_data": ( @@ -207,7 +207,7 @@ async def query( raise CloudRecoError(response=response) from exc raise - result_code = response_body["result_code"] + result_code = response_body["result_code"] # pyrefly: ignore [unknown-variable-type] if result_code != "Success": exception = { "AuthenticationFailure": (AuthenticationFailureError), @@ -217,8 +217,8 @@ async def query( }[result_code] raise exception(response=response) - result_list = list(response_body["results"]) + result_list = list(response_body["results"]) # pyrefly: ignore [unknown-argument-type] return [ - QueryResult.from_response_dict(response_dict=item) + QueryResult.from_response_dict(response_dict=item) # pyrefly: ignore [unknown-argument-type] for item in result_list ] diff --git a/src/vws/async_vumark_service.py b/src/vws/async_vumark_service.py index 6575f7716..2de1db7ba 100644 --- a/src/vws/async_vumark_service.py +++ b/src/vws/async_vumark_service.py @@ -147,9 +147,8 @@ async def generate_vumark_instance( if response.status_code == HTTPStatus.OK: return response.content - result_code = json.loads(s=response.text)["result_code"] - + result_code = json.loads(s=response.text)["result_code"] # pyrefly: ignore [unknown-variable-type] raise VWSError.from_result_code( - result_code=result_code, + result_code=result_code, # pyrefly: ignore [unknown-argument-type] response=response, ) diff --git a/src/vws/async_vws.py b/src/vws/async_vws.py index d2306a63b..c35e55207 100644 --- a/src/vws/async_vws.py +++ b/src/vws/async_vws.py @@ -137,7 +137,7 @@ async def make_request( request_path=request_path, base_vws_url=self._base_vws_url, request_timeout_seconds=self._request_timeout_seconds, - extra_headers=extra_headers or {}, + extra_headers=(extra_headers if extra_headers is not None else {}), transport=self._transport, ) @@ -152,13 +152,12 @@ async def make_request( ): # pragma: no cover raise ServerError(response=response) - result_code = json.loads(s=response.text)["result_code"] - + result_code = json.loads(s=response.text)["result_code"] # pyrefly: ignore [unknown-variable-type] if result_code == expected_result_code: return response raise VWSError.from_result_code( - result_code=result_code, + result_code=result_code, # pyrefly: ignore [unknown-argument-type] response=response, ) @@ -239,7 +238,7 @@ async def add_target( content_type="application/json", ) - return str(object=json.loads(s=response.text)["target_id"]) + return str(object=json.loads(s=response.text)["target_id"]) # pyrefly: ignore [unknown-argument-type] async def get_target_record(self, target_id: str) -> TargetStatusAndRecord: """Get a given target's target record from the Target @@ -374,7 +373,7 @@ async def list_targets(self) -> list[str]: content_type="application/json", ) - return list(json.loads(s=response.text)["results"]) + return list(json.loads(s=response.text)["results"]) # pyrefly: ignore [unknown-argument-type] async def get_target_summary_report( self, target_id: str @@ -659,7 +658,7 @@ async def get_duplicate_targets(self, target_id: str) -> list[str]: ) return list( - json.loads(s=response.text)["similar_targets"], + json.loads(s=response.text)["similar_targets"], # pyrefly: ignore [unknown-argument-type] ) async def update_target( diff --git a/src/vws/exceptions/model_target_exceptions.py b/src/vws/exceptions/model_target_exceptions.py index 8eaf09878..cbbf80a0d 100644 --- a/src/vws/exceptions/model_target_exceptions.py +++ b/src/vws/exceptions/model_target_exceptions.py @@ -27,7 +27,7 @@ def _is_json_object(*, value: object) -> bool: @beartype -def _json_object(*, value: str) -> dict[str, Any]: +def _json_object(*, value: str) -> dict[str, Any]: # pyrefly: ignore [explicit-any] """Get a JSON object from a string. Args: @@ -38,19 +38,19 @@ def _json_object(*, value: str) -> dict[str, Any]: JSON object. """ try: - loaded: Any = json.loads(s=value) + loaded: Any = json.loads(s=value) # pyrefly: ignore [explicit-any] except json.JSONDecodeError: return {} if not _is_json_object(value=loaded): return {} - json_object: dict[str, Any] = loaded + json_object: dict[str, Any] = loaded # pyrefly: ignore [explicit-any] return json_object @beartype -def _error_dict(*, response: Response) -> dict[str, Any]: +def _error_dict(*, response: Response) -> dict[str, Any]: # pyrefly: ignore [explicit-any] """Get the error object of a Model Target Web API error response. Args: @@ -66,11 +66,11 @@ def _error_dict(*, response: Response) -> dict[str, Any]: if "error" not in body: return {} - error: Any = body["error"] + error: Any = body["error"] # pyrefly: ignore [explicit-any] if not _is_json_object(value=error): return {} - error_dict: dict[str, Any] = error + error_dict: dict[str, Any] = error # pyrefly: ignore [explicit-any] return error_dict @@ -122,7 +122,8 @@ def details(self) -> list[ModelTargetGenerationDetail]: return [ ModelTargetGenerationDetail( - code=detail["code"], + code=detail["code"], # pyrefly: ignore [unknown-argument-type] + # pyrefly: ignore [unknown-argument-type] message=detail["message"], ) for detail in error["details"] diff --git a/src/vws/exceptions/vws_exceptions.py b/src/vws/exceptions/vws_exceptions.py index 216677f15..47b098c77 100644 --- a/src/vws/exceptions/vws_exceptions.py +++ b/src/vws/exceptions/vws_exceptions.py @@ -21,7 +21,7 @@ def _target_id_from_url(*, url: str) -> str: path segment after ``targets``, ``summary``, or ``duplicates``. """ path = urlparse(url=url).path - parts = [part for part in path.split(sep="/") if part] + parts = [part for part in path.split(sep="/") if bool(part)] for marker in ("targets", "summary", "duplicates"): try: marker_index = parts.index(marker) @@ -143,9 +143,11 @@ class TargetNameExistError(VWSError): @property def target_name(self) -> str: """The target name which already exists.""" - response_body = self.response.request_body or b"" + response_body = self.response.request_body + if response_body is None or response_body in {"", b""}: + response_body = b"" request_json = json.loads(s=response_body) - return str(object=request_json["name"]) + return str(object=request_json["name"]) # pyrefly: ignore [unknown-argument-type] @beartype diff --git a/src/vws/model_target_service.py b/src/vws/model_target_service.py index 70b116d0a..11ef75ed7 100644 --- a/src/vws/model_target_service.py +++ b/src/vws/model_target_service.py @@ -150,9 +150,10 @@ def make_request( ~vws.exceptions.vws_exceptions.TooManyRequestsError: Vuforia is rate limiting access. """ + request_headers = extra_headers if extra_headers is not None else {} headers = { "Authorization": f"Bearer {self.get_access_token()}", - **(extra_headers or {}), + **request_headers, } response = self._transport( @@ -356,7 +357,7 @@ def delete_dataset( ~vws.exceptions.model_target_exceptions.ModelTargetOAuth2Error: Vuforia did not give an access token. """ - self.make_request( + _ = self.make_request( method=HTTPMethod.DELETE, data=b"", request_path=dataset_path( diff --git a/src/vws/query.py b/src/vws/query.py index 3f69261ef..f5c173355 100644 --- a/src/vws/query.py +++ b/src/vws/query.py @@ -111,9 +111,9 @@ def query( An ordered list of target details of matching targets. """ image_content = _get_image_data(image=image) - body: dict[str, Any] = { + body: dict[str, Any] = { # pyrefly: ignore [explicit-any] "image": ("image.jpeg", image_content, "image/jpeg"), - "max_num_results": (None, int(max_num_results), "text/plain"), + "max_num_results": (None, max_num_results, "text/plain"), "include_target_data": ( None, include_target_data.value, @@ -177,7 +177,7 @@ def query( raise CloudRecoError(response=response) from exc raise - result_code = response_body["result_code"] + result_code = response_body["result_code"] # pyrefly: ignore [unknown-variable-type] if result_code != "Success": exception = { "AuthenticationFailure": AuthenticationFailureError, @@ -187,8 +187,8 @@ def query( }[result_code] raise exception(response=response) - result_list = list(response_body["results"]) + result_list = list(response_body["results"]) # pyrefly: ignore [unknown-argument-type] return [ - QueryResult.from_response_dict(response_dict=item) + QueryResult.from_response_dict(response_dict=item) # pyrefly: ignore [unknown-argument-type] for item in result_list ] diff --git a/src/vws/reports.py b/src/vws/reports.py index 2be447b03..b18ffb9b4 100644 --- a/src/vws/reports.py +++ b/src/vws/reports.py @@ -34,7 +34,7 @@ class DatabaseSummaryReport: total_recos: int @classmethod - def from_response_dict(cls, response_dict: dict[str, Any]) -> Self: + def from_response_dict(cls, response_dict: dict[str, Any]) -> Self: # pyrefly: ignore [explicit-any] """Construct from a VWS API response dict.""" return cls( active_images=int(response_dict["active_images"]), @@ -86,7 +86,7 @@ class TargetSummaryReport: previous_month_recos: int @classmethod - def from_response_dict(cls, response_dict: dict[str, Any]) -> Self: + def from_response_dict(cls, response_dict: dict[str, Any]) -> Self: # pyrefly: ignore [explicit-any] """Construct from a VWS API response dict.""" return cls( status=TargetStatuses(value=response_dict["status"]), @@ -143,17 +143,18 @@ class QueryResult: target_data: TargetData | None @classmethod - def from_response_dict(cls, response_dict: dict[str, Any]) -> Self: + def from_response_dict(cls, response_dict: dict[str, Any]) -> Self: # pyrefly: ignore [explicit-any] """Construct from a VWS API query result item dict.""" target_data: TargetData | None = None if "target_data" in response_dict: target_data_dict = response_dict["target_data"] target_timestamp = datetime.datetime.fromtimestamp( - timestamp=target_data_dict["target_timestamp"], + timestamp=target_data_dict["target_timestamp"], # pyrefly: ignore [unknown-argument-type] tz=datetime.UTC, ) target_data = TargetData( - name=target_data_dict["name"], + name=target_data_dict["name"], # pyrefly: ignore [unknown-argument-type] + # pyrefly: ignore [unknown-argument-type] application_metadata=target_data_dict["application_metadata"], target_timestamp=target_timestamp, ) @@ -176,7 +177,7 @@ class TargetStatusAndRecord: target_record: TargetRecord @classmethod - def from_response_dict(cls, response_dict: dict[str, Any]) -> Self: + def from_response_dict(cls, response_dict: dict[str, Any]) -> Self: # pyrefly: ignore [explicit-any] """Construct from a VWS API response dict.""" status = TargetStatuses(value=response_dict["status"]) target_record_dict = dict(response_dict["target_record"]) @@ -209,7 +210,7 @@ class RecoCountsReportRequest: """ @classmethod - def from_response_dict(cls, response_dict: dict[str, Any]) -> Self: + def from_response_dict(cls, response_dict: dict[str, Any]) -> Self: # pyrefly: ignore [explicit-any] """Construct from a VWS API response dict.""" return cls( transaction_id=response_dict["transaction_id"], @@ -300,7 +301,7 @@ class ModelTargetDatasetStatusReport: """ @classmethod - def from_response_dict(cls, response_dict: dict[str, Any]) -> Self: + def from_response_dict(cls, response_dict: dict[str, Any]) -> Self: # pyrefly: ignore [explicit-any] """Construct from a Model Target Web API response dict.""" error: ModelTargetGenerationError | None = None if "error" in response_dict: @@ -319,7 +320,8 @@ def from_response_dict(cls, response_dict: dict[str, Any]) -> Self: target=warning_dict["target"], details=[ ModelTargetGenerationDetail( - code=detail["code"], + code=detail["code"], # pyrefly: ignore [unknown-argument-type] + # pyrefly: ignore [unknown-argument-type] message=detail["message"], ) for detail in warning_dict["details"] diff --git a/src/vws/transports.py b/src/vws/transports.py index 7c1b04d52..93331b3d7 100644 --- a/src/vws/transports.py +++ b/src/vws/transports.py @@ -194,15 +194,16 @@ def __call__( follow_redirects=True, ) - content = bytes(httpx_response.content) + content = httpx_response.content request_content = httpx_response.request.content + request_body = request_content return Response( text=httpx_response.text, url=str(object=httpx_response.url), status_code=httpx_response.status_code, headers=dict(httpx_response.headers), - request_body=bytes(request_content) or None, + request_body=request_body if request_body != b"" else None, tell_position=len(content), content=content, ) @@ -248,15 +249,16 @@ def _response_from_httpx2(*, httpx2_response: httpx2.Response) -> Response: Returns: A Response populated from the ``httpx2`` response. """ - content = bytes(httpx2_response.content) + content = httpx2_response.content request_content = httpx2_response.request.content + request_body = request_content return Response( text=httpx2_response.text, url=str(object=httpx2_response.url), status_code=httpx2_response.status_code, headers=dict(httpx2_response.headers), - request_body=bytes(request_content) or None, + request_body=request_body if request_body != b"" else None, tell_position=len(content), content=content, ) @@ -432,15 +434,16 @@ async def __call__( follow_redirects=True, ) - content = bytes(httpx_response.content) + content = httpx_response.content request_content = httpx_response.request.content + request_body = request_content return Response( text=httpx_response.text, url=str(object=httpx_response.url), status_code=httpx_response.status_code, headers=dict(httpx_response.headers), - request_body=bytes(request_content) or None, + request_body=request_body if request_body != b"" else None, tell_position=len(content), content=content, ) diff --git a/src/vws/vumark_service.py b/src/vws/vumark_service.py index 168e8b6f8..7764c1624 100644 --- a/src/vws/vumark_service.py +++ b/src/vws/vumark_service.py @@ -130,9 +130,8 @@ def generate_vumark_instance( if response.status_code == HTTPStatus.OK: return response.content - result_code = json.loads(s=response.text)["result_code"] - + result_code = json.loads(s=response.text)["result_code"] # pyrefly: ignore [unknown-variable-type] raise VWSError.from_result_code( - result_code=result_code, + result_code=result_code, # pyrefly: ignore [unknown-argument-type] response=response, ) diff --git a/src/vws/vws.py b/src/vws/vws.py index 2b241ab1d..5e977af4a 100644 --- a/src/vws/vws.py +++ b/src/vws/vws.py @@ -123,7 +123,7 @@ def make_request( request_path=request_path, base_vws_url=self._base_vws_url, request_timeout_seconds=self._request_timeout_seconds, - extra_headers=extra_headers or {}, + extra_headers=(extra_headers if extra_headers is not None else {}), transport=self._transport, ) @@ -138,13 +138,12 @@ def make_request( ): # pragma: no cover raise ServerError(response=response) - result_code = json.loads(s=response.text)["result_code"] - + result_code = json.loads(s=response.text)["result_code"] # pyrefly: ignore [unknown-variable-type] if result_code == expected_result_code: return response raise VWSError.from_result_code( - result_code=result_code, + result_code=result_code, # pyrefly: ignore [unknown-argument-type] response=response, ) @@ -225,7 +224,7 @@ def add_target( content_type="application/json", ) - return str(object=json.loads(s=response.text)["target_id"]) + return str(object=json.loads(s=response.text)["target_id"]) # pyrefly: ignore [unknown-argument-type] def get_target_record(self, target_id: str) -> TargetStatusAndRecord: """Get a given target's target record from the Target Management @@ -352,7 +351,7 @@ def list_targets(self) -> list[str]: content_type="application/json", ) - return list(json.loads(s=response.text)["results"]) + return list(json.loads(s=response.text)["results"]) # pyrefly: ignore [unknown-argument-type] def get_target_summary_report(self, target_id: str) -> TargetSummaryReport: """Get a summary report for a target. @@ -585,7 +584,7 @@ def delete_target(self, target_id: str) -> None: ~vws.exceptions.vws_exceptions.TooManyRequestsError: Vuforia is rate limiting access. """ - self.make_request( + _ = self.make_request( method=HTTPMethod.DELETE, data=b"", request_path=f"/targets/{target_id}", @@ -631,7 +630,7 @@ def get_duplicate_targets(self, target_id: str) -> list[str]: content_type="application/json", ) - return list(json.loads(s=response.text)["similar_targets"]) + return list(json.loads(s=response.text)["similar_targets"]) # pyrefly: ignore [unknown-argument-type] def update_target( self, @@ -710,7 +709,7 @@ def update_target( content = json.dumps(obj=data).encode(encoding="utf-8") - self.make_request( + _ = self.make_request( method=HTTPMethod.PUT, data=content, request_path=f"/targets/{target_id}", diff --git a/tests/conftest.py b/tests/conftest.py index 74d4137be..0c682da3d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -224,7 +224,7 @@ def fixture_image_file( """An image file object.""" file = tmp_path / "image.jpg" buffer = high_quality_image.getvalue() - file.write_bytes(data=buffer) + _ = file.write_bytes(data=buffer) mode: Literal["r+b", "rb"] = request.param with file.open(mode=mode) as file_obj: yield file_obj diff --git a/tests/test_async_cloud_reco_exceptions.py b/tests/test_async_cloud_reco_exceptions.py index d18b1ddf3..67c2637dc 100644 --- a/tests/test_async_cloud_reco_exceptions.py +++ b/tests/test_async_cloud_reco_exceptions.py @@ -168,7 +168,7 @@ async def test_non_json_client_error( key.lower(): value for key, value in response.headers.items() } assert response_headers["x-query-failure"] == headers["X-Query-Failure"] - assert response.request_body + assert bool(response.request_body) @pytest.mark.asyncio diff --git a/tests/test_async_model_targets.py b/tests/test_async_model_targets.py index c29101e8e..9c8d48ada 100644 --- a/tests/test_async_model_targets.py +++ b/tests/test_async_model_targets.py @@ -87,7 +87,7 @@ async def test_token_is_a_bearer_token( async_model_target_client: AsyncModelTargetService, ) -> None: """An access token is given for valid credentials.""" - assert await async_model_target_client.get_access_token() + assert bool(await async_model_target_client.get_access_token()) @staticmethod @pytest.mark.asyncio @@ -313,11 +313,13 @@ async def test_advanced_dataset_takes_multiple_models( views=[], ) - assert await async_model_target_client.create_dataset( - name="dataset", - target_sdk="11.0", - models=[model_target_model, other_model], - dataset_type=ModelTargetDatasetType.ADVANCED, + assert bool( + await async_model_target_client.create_dataset( + name="dataset", + target_sdk="11.0", + models=[model_target_model, other_model], + dataset_type=ModelTargetDatasetType.ADVANCED, + ) ) diff --git a/tests/test_async_vws.py b/tests/test_async_vws.py index c99644bec..166224a25 100644 --- a/tests/test_async_vws.py +++ b/tests/test_async_vws.py @@ -519,15 +519,15 @@ async def test_reco_counts_report( year=report_month.year, month=calendar.Month(value=report_month.month), ) - assert report_request.transaction_id - assert report_request.presigned_url + assert bool(report_request.transaction_id) + assert bool(report_request.presigned_url) report = await client.wait_for_reco_counts_report( presigned_url=report_request.presigned_url, ) # No targets have been recognized, so the report has no rows. - assert not report.reco_counts + assert not bool(report.reco_counts) assert report.raw_csv.startswith(b"target_id,reco_count") @staticmethod diff --git a/tests/test_cloud_reco_exceptions.py b/tests/test_cloud_reco_exceptions.py index 9af560ec6..92727fa14 100644 --- a/tests/test_cloud_reco_exceptions.py +++ b/tests/test_cloud_reco_exceptions.py @@ -34,7 +34,7 @@ def test_too_many_max_results( ``max_num_results`` is out of range. """ with pytest.raises(expected_exception=MaxNumResultsOutOfRangeError) as exc: - cloud_reco_client.query( + _ = cloud_reco_client.query( image=high_quality_image, max_num_results=51, ) @@ -57,7 +57,7 @@ def test_image_too_large( large is given. """ with pytest.raises(expected_exception=RequestEntityTooLargeError) as exc: - cloud_reco_client.query(image=jpeg_too_large) + _ = cloud_reco_client.query(image=jpeg_too_large) assert ( exc.value.response.status_code == HTTPStatus.REQUEST_ENTITY_TOO_LARGE @@ -99,7 +99,7 @@ def test_authentication_failure( with pytest.raises( expected_exception=AuthenticationFailureError ) as exc: - cloud_reco_client.query(image=high_quality_image) + _ = cloud_reco_client.query(image=high_quality_image) assert exc.value.response.status_code == HTTPStatus.UNAUTHORIZED @@ -120,7 +120,7 @@ def test_inactive_project( ) with pytest.raises(expected_exception=InactiveProjectError) as exc: - cloud_reco_client.query(image=high_quality_image) + _ = cloud_reco_client.query(image=high_quality_image) response = exc.value.response assert response.status_code == HTTPStatus.FORBIDDEN @@ -164,7 +164,7 @@ def test_non_json_client_error( with MockVWS(cloud_query_failure_response=failure_response) as mock: mock.add_cloud_database(cloud_database=database) with pytest.raises(expected_exception=CloudRecoError) as exc: - cloud_reco_client.query(image=high_quality_image) + _ = cloud_reco_client.query(image=high_quality_image) response = exc.value.response assert response.status_code == HTTPStatus.BAD_REQUEST @@ -174,7 +174,7 @@ def test_non_json_client_error( key.lower(): value for key, value in response.headers.items() } assert response_headers["x-query-failure"] == headers["X-Query-Failure"] - assert response.request_body + assert bool(response.request_body) def test_non_json_success_response( @@ -196,4 +196,4 @@ def test_non_json_success_response( with MockVWS(cloud_query_failure_response=failure_response) as mock: mock.add_cloud_database(cloud_database=database) with pytest.raises(expected_exception=json.JSONDecodeError): - cloud_reco_client.query(image=high_quality_image) + _ = cloud_reco_client.query(image=high_quality_image) diff --git a/tests/test_model_targets.py b/tests/test_model_targets.py index 23a73cb46..fc8f9d4d4 100644 --- a/tests/test_model_targets.py +++ b/tests/test_model_targets.py @@ -132,7 +132,7 @@ def test_token_is_a_bearer_token() -> None: client_secret=_CLIENT_SECRET, ) - assert client.get_access_token() + assert bool(client.get_access_token()) @staticmethod @pytest.mark.usefixtures("_mock_model_targets") @@ -149,7 +149,7 @@ def test_token_is_reused( ) for _ in range(2): - client.create_dataset( + _ = client.create_dataset( name="dataset", target_sdk="11.0", models=[model_target_model], @@ -175,15 +175,15 @@ def test_expired_token_is_replaced( ) with freeze_time(time_to_freeze="2026-01-01") as frozen_time: - client.create_dataset( + _ = client.create_dataset( name="dataset", target_sdk="11.0", models=[model_target_model], dataset_type=ModelTargetDatasetType.STANDARD, ) # Mock tokens last an hour. - frozen_time.tick(delta=60 * 60 + 1) - client.create_dataset( + _ = frozen_time.tick(delta=60 * 60 + 1) + _ = client.create_dataset( name="dataset", target_sdk="11.0", models=[model_target_model], @@ -206,11 +206,11 @@ def test_invalid_credentials() -> None: with pytest.raises( expected_exception=ModelTargetOAuth2Error, ) as exc: - client.get_access_token() + _ = client.get_access_token() assert exc.value.response.status_code == HTTPStatus.UNAUTHORIZED assert exc.value.error == "invalid_client" - assert not exc.value.error_description + assert not bool(exc.value.error_description) @staticmethod @pytest.mark.parametrize( @@ -271,7 +271,7 @@ def test_dataset_error_response( MockVWS(model_target_failure_response=failure), pytest.raises(expected_exception=expected_exception) as exc, ): - client.create_dataset( + _ = client.create_dataset( name="dataset", target_sdk="11.0", models=[model_target_model], @@ -334,7 +334,7 @@ def test_create_wait_download_delete( ) with pytest.raises(expected_exception=UnknownModelTargetDatasetError): - model_target_client.get_dataset_status( + _ = model_target_client.get_dataset_status( dataset_uuid=dataset_uuid, dataset_type=dataset_type, ) @@ -380,7 +380,7 @@ def test_download_while_processing( with pytest.raises( expected_exception=ModelTargetDatasetNotDoneError, ) as exc: - model_target_client.download_dataset( + _ = model_target_client.download_dataset( dataset_uuid=dataset_uuid, dataset_type=ModelTargetDatasetType.STANDARD, ) @@ -434,7 +434,7 @@ def test_advanced_dataset_takes_multiple_models( dataset_type=ModelTargetDatasetType.ADVANCED, ) - assert dataset_uuid + assert bool(dataset_uuid) @staticmethod def test_state_based_model( @@ -460,11 +460,13 @@ def test_state_based_model( ], ) - assert model_target_client.create_dataset( - name="dataset", - target_sdk="11.0", - models=[model], - dataset_type=ModelTargetDatasetType.STANDARD, + assert bool( + model_target_client.create_dataset( + name="dataset", + target_sdk="11.0", + models=[model], + dataset_type=ModelTargetDatasetType.STANDARD, + ) ) @@ -478,7 +480,7 @@ def test_get_status(*, model_target_client: ModelTargetService) -> None: with pytest.raises( expected_exception=UnknownModelTargetDatasetError, ) as exc: - model_target_client.get_dataset_status( + _ = model_target_client.get_dataset_status( dataset_uuid=dataset_uuid, dataset_type=ModelTargetDatasetType.STANDARD, ) @@ -491,7 +493,7 @@ def test_get_status(*, model_target_client: ModelTargetService) -> None: def test_download(*, model_target_client: ModelTargetService) -> None: """An exception is raised for an unknown dataset.""" with pytest.raises(expected_exception=UnknownModelTargetDatasetError): - model_target_client.download_dataset( + _ = model_target_client.download_dataset( dataset_uuid=uuid.uuid4().hex, dataset_type=ModelTargetDatasetType.STANDARD, ) @@ -518,7 +520,7 @@ def test_no_cad_data( with pytest.raises( expected_exception=ModelTargetValidationError, ) as exc: - model_target_client.create_dataset( + _ = model_target_client.create_dataset( name="dataset", target_sdk="11.0", models=[ModelTargetModel(name="model", views=[])], @@ -544,7 +546,7 @@ def test_two_cad_data_sources( ) with pytest.raises(expected_exception=ModelTargetValidationError): - model_target_client.create_dataset( + _ = model_target_client.create_dataset( name="dataset", target_sdk="11.0", models=[model], @@ -561,7 +563,7 @@ def test_two_models_in_a_standard_dataset( with pytest.raises( expected_exception=ModelTargetValidationError, ) as exc: - model_target_client.create_dataset( + _ = model_target_client.create_dataset( name="dataset", target_sdk="11.0", models=[model_target_model, model_target_model], @@ -611,7 +613,7 @@ def test_generation_failure( with pytest.raises( expected_exception=ModelTargetDatasetNotDoneError, ): - client.download_dataset( + _ = client.download_dataset( dataset_uuid=dataset_uuid, dataset_type=ModelTargetDatasetType.STANDARD, ) @@ -653,9 +655,11 @@ def test_generation_warning( (detail,) = report.warning.details assert detail.code == "LOW_RECOGNITION_QUALITY" - assert client.download_dataset( - dataset_uuid=dataset_uuid, - dataset_type=ModelTargetDatasetType.STANDARD, + assert bool( + client.download_dataset( + dataset_uuid=dataset_uuid, + dataset_type=ModelTargetDatasetType.STANDARD, + ) ) @@ -680,7 +684,7 @@ def test_timeout(*, model_target_model: ModelTargetModel) -> None: with pytest.raises( expected_exception=ModelTargetDatasetTimeoutError, ): - client.wait_for_dataset_generated( + _ = client.wait_for_dataset_generated( dataset_uuid=dataset_uuid, dataset_type=ModelTargetDatasetType.STANDARD, seconds_between_requests=0.01, @@ -711,10 +715,10 @@ def test_unknown_error_shape(*, text: str) -> None: """ error = ModelTargetError(response=_response(text=text)) - assert not error.code - assert not error.message - assert not error.target - assert not error.details + assert not bool(error.code) + assert not bool(error.message) + assert not bool(error.target) + assert not bool(error.details) @staticmethod def test_error_without_details() -> None: @@ -724,8 +728,8 @@ def test_error_without_details() -> None: assert error.code == "ERROR" assert error.message == "No" - assert not error.target - assert not error.details + assert not bool(error.target) + assert not bool(error.details) @staticmethod @pytest.mark.parametrize( @@ -736,8 +740,8 @@ def test_unknown_oauth2_error_shape(*, text: str) -> None: """An OAuth2 error without an error code gives empty values.""" error = ModelTargetOAuth2Error(response=_response(text=text)) - assert not error.error - assert not error.error_description + assert not bool(error.error) + assert not bool(error.error_description) @staticmethod def test_oauth2_error_description() -> None: diff --git a/tests/test_query.py b/tests/test_query.py index dac206b25..b77d1385d 100644 --- a/tests/test_query.py +++ b/tests/test_query.py @@ -88,10 +88,10 @@ def test_default_timeout( with pytest.raises( expected_exception=requests.exceptions.Timeout, ): - cloud_reco_client.query(image=image) + _ = cloud_reco_client.query(image=image) else: matches = cloud_reco_client.query(image=image) - assert not matches + assert not bool(matches) class TestCustomRequestTimeout: @@ -143,10 +143,10 @@ def test_custom_timeout( with pytest.raises( expected_exception=requests.exceptions.Timeout, ): - cloud_reco_client.query(image=image) + _ = cloud_reco_client.query(image=image) else: matches = cloud_reco_client.query(image=image) - assert not matches + assert not bool(matches) class TestCustomBaseVWQURL: diff --git a/tests/test_transports.py b/tests/test_transports.py index 09c8bf2a0..a3494b67c 100644 --- a/tests/test_transports.py +++ b/tests/test_transports.py @@ -356,21 +356,21 @@ def test_falsy_sync_transport_is_retained( access_key = uuid.uuid4().hex secret_key = uuid.uuid4().hex transport = _FalsyTransport() - assert not transport + assert not bool(transport) targets = VWS( server_access_key=access_key, server_secret_key=secret_key, transport=transport, ).list_targets() - assert not targets + assert not bool(targets) query_results = CloudRecoService( client_access_key=access_key, client_secret_key=secret_key, transport=transport, ).query(image=high_quality_image) - assert not query_results + assert not bool(query_results) vumark_bytes = VuMarkService( server_access_key=access_key, @@ -392,21 +392,23 @@ async def test_falsy_async_transport_is_retained( access_key = uuid.uuid4().hex secret_key = uuid.uuid4().hex transport = _FalsyAsyncTransport() - assert not transport + assert not bool(transport) async with AsyncVWS( server_access_key=access_key, server_secret_key=secret_key, transport=transport, ) as vws_client: - assert not await vws_client.list_targets() + assert not bool(await vws_client.list_targets()) async with AsyncCloudRecoService( client_access_key=access_key, client_secret_key=secret_key, transport=transport, ) as cloud_reco_client: - assert not await cloud_reco_client.query(image=high_quality_image) + assert not bool( + await cloud_reco_client.query(image=high_quality_image) + ) async with AsyncVuMarkService( server_access_key=access_key, @@ -606,7 +608,7 @@ def test_context_manager(httpx2_requests: list[httpx2.Request]) -> None: expected_exception=RuntimeError, match="client has been closed", ): - transport( + _ = transport( method="POST", url=_HTTPX2_URL, headers={"Content-Type": "text/plain"}, @@ -623,14 +625,14 @@ def test_close(httpx2_requests: list[httpx2.Request]) -> None: expected_exception=RuntimeError, match="client has been closed", ): - transport( + _ = transport( method="POST", url=_HTTPX2_URL, headers={"Content-Type": "text/plain"}, data=b"hello", request_timeout=30.0, ) - assert not httpx2_requests + assert not bool(httpx2_requests) @staticmethod def test_httpx2_exceptions(httpx2_requests: list[httpx2.Request]) -> None: @@ -639,7 +641,7 @@ def test_httpx2_exceptions(httpx2_requests: list[httpx2.Request]) -> None: """ transport = HTTPX2Transport() with pytest.raises(expected_exception=httpx2.ConnectError) as exc: - transport( + _ = transport( method="GET", url=_HTTPX2_REFUSED_URL, headers={}, @@ -806,7 +808,7 @@ async def test_aclose(httpx2_requests: list[httpx2.Request]) -> None: data=b"hello", request_timeout=30.0, ) - assert not httpx2_requests + assert not bool(httpx2_requests) @staticmethod @pytest.mark.asyncio @@ -943,7 +945,7 @@ def test_timeout(custom_timeout: float | tuple[float, float]) -> None: transport=transport, ) with pytest.raises(expected_exception=httpx2.ReadTimeout): - vws_client.list_targets() + _ = vws_client.list_targets() # The mock sleeps for the read timeout before raising. assert sleeps == [0.1] diff --git a/tests/test_vws.py b/tests/test_vws.py index db6d05fd8..3a4de94e9 100644 --- a/tests/test_vws.py +++ b/tests/test_vws.py @@ -102,7 +102,7 @@ def test_add_two_targets( This demonstrates that the image seek position is not changed. """ for name in ("a", "b"): - vws_client.add_target( + _ = vws_client.add_target( name=name, width=1, image=image, @@ -151,7 +151,7 @@ def test_default_timeout( with pytest.raises( expected_exception=requests.exceptions.Timeout, ): - vws_client.add_target( + _ = vws_client.add_target( name="x", width=1, image=image, @@ -159,7 +159,7 @@ def test_default_timeout( application_metadata=None, ) else: - vws_client.add_target( + _ = vws_client.add_target( name="x", width=1, image=image, @@ -217,7 +217,7 @@ def test_custom_timeout( with pytest.raises( expected_exception=requests.exceptions.Timeout, ): - vws_client.add_target( + _ = vws_client.add_target( name="x", width=1, image=image, @@ -225,7 +225,7 @@ def test_custom_timeout( application_metadata=None, ) else: - vws_client.add_target( + _ = vws_client.add_target( name="x", width=1, image=image, @@ -254,7 +254,7 @@ def test_custom_base_url(image: io.BytesIO | BinaryIO) -> None: base_vws_url=base_vws_url, ) - vws_client.add_target( + _ = vws_client.add_target( name="x", width=1, image=image, @@ -278,7 +278,7 @@ def test_custom_base_url_with_path_prefix() -> None: base_vws_url=base_vws_url, ) - assert not vws_client.list_targets() + assert not bool(vws_client.list_targets()) class TestListTargets: @@ -821,15 +821,15 @@ def test_reco_counts_report( year=report_month.year, month=calendar.Month(value=report_month.month), ) - assert report_request.transaction_id - assert report_request.presigned_url + assert bool(report_request.transaction_id) + assert bool(report_request.presigned_url) report = vws_client.wait_for_reco_counts_report( presigned_url=report_request.presigned_url, ) # No targets have been recognized, so the report has no rows. - assert not report.reco_counts + assert not bool(report.reco_counts) assert report.raw_csv.startswith(b"target_id,reco_count") @staticmethod @@ -853,7 +853,7 @@ def test_not_ready(*, current_month: datetime.date) -> None: with pytest.raises( expected_exception=RecoCountsReportNotReadyError, ) as exc: - vws_client.download_reco_counts_report( + _ = vws_client.download_reco_counts_report( presigned_url=report_request.presigned_url, ) @@ -883,7 +883,7 @@ def test_wait_timeout(*, current_month: datetime.date) -> None: with pytest.raises( expected_exception=RecoCountsReportTimeoutError, ): - vws_client.wait_for_reco_counts_report( + _ = vws_client.wait_for_reco_counts_report( presigned_url=report_request.presigned_url, seconds_between_requests=0.01, timeout_seconds=0.05, @@ -914,7 +914,7 @@ def test_month_not_accepted( rejected. """ with pytest.raises(expected_exception=FailError) as exc: - vws_client.request_database_reco_counts_report( + _ = vws_client.request_database_reco_counts_report( year=year, month=month, ) @@ -941,7 +941,7 @@ def test_database_id_does_not_match_keys( with pytest.raises( expected_exception=AuthenticationFailureError, ) as exc: - vws_client.request_database_reco_counts_report( + _ = vws_client.request_database_reco_counts_report( year=current_month.year, month=calendar.Month(value=current_month.month), ) @@ -960,7 +960,7 @@ def test_download_error() -> None: with pytest.raises( expected_exception=RecoCountsReportDownloadError, ) as exc: - vws_client.download_reco_counts_report( + _ = vws_client.download_reco_counts_report( presigned_url="https://example.com/reports/recoCounts/x", ) @@ -977,7 +977,7 @@ def test_no_database_id(*, current_month: datetime.date) -> None: ) with pytest.raises(expected_exception=DatabaseIdNotSetError): - vws_client.request_database_reco_counts_report( + _ = vws_client.request_database_reco_counts_report( year=current_month.year, month=calendar.Month(value=current_month.month), ) diff --git a/tests/test_vws_exceptions.py b/tests/test_vws_exceptions.py index 31d30b940..594ba858c 100644 --- a/tests/test_vws_exceptions.py +++ b/tests/test_vws_exceptions.py @@ -57,7 +57,7 @@ def test_image_too_large( raised. """ with pytest.raises(expected_exception=ImageTooLargeError) as exc: - vws_client.add_target( + _ = vws_client.add_target( name="x", width=1, image=png_too_large, @@ -97,7 +97,7 @@ def test_add_bad_name( with pytest.raises( expected_exception=ServerError, ) as exc: - vws_client.add_target( + _ = vws_client.add_target( name=bad_name, width=1, image=high_quality_image, @@ -119,7 +119,7 @@ def test_request_quota_reached() -> None: ) with pytest.raises(expected_exception=RequestQuotaReachedError) as exc: - vws_client.list_targets() + _ = vws_client.list_targets() assert exc.value.response.status_code == HTTPStatus.FORBIDDEN @@ -135,7 +135,7 @@ def test_target_quota_reached(high_quality_image: io.BytesIO) -> None: ) with pytest.raises(expected_exception=TargetQuotaReachedError) as exc: - vws_client.add_target( + _ = vws_client.add_target( name="x", width=1, image=high_quality_image, @@ -168,7 +168,7 @@ def test_project_state_error( ) with pytest.raises(expected_exception=expected_exception) as exc: - vws_client.list_targets() + _ = vws_client.list_targets() assert exc.value.response.status_code == HTTPStatus.FORBIDDEN @@ -184,7 +184,7 @@ def test_fail(high_quality_image: io.BytesIO) -> None: ) with pytest.raises(expected_exception=FailError) as exc: - vws_client.add_target( + _ = vws_client.add_target( name="x", width=1, image=high_quality_image, @@ -199,7 +199,7 @@ def test_bad_image(vws_client: VWS) -> None: """A ``BadImage`` exception is raised when a non-image is given.""" not_an_image = io.BytesIO(initial_bytes=b"Not an image") with pytest.raises(expected_exception=BadImageError) as exc: - vws_client.add_target( + _ = vws_client.add_target( name="x", width=1, image=not_an_image, @@ -221,7 +221,7 @@ def test_target_name_exist( the same name. """ - vws_client.add_target( + _ = vws_client.add_target( name="x", width=1, image=high_quality_image, @@ -229,7 +229,7 @@ def test_target_name_exist( application_metadata=None, ) with pytest.raises(expected_exception=TargetNameExistError) as exc: - vws_client.add_target( + _ = vws_client.add_target( name="x", width=1, image=high_quality_image, @@ -258,7 +258,7 @@ def test_project_inactive( ) with pytest.raises(expected_exception=ProjectInactiveError) as exc: - vws_client.add_target( + _ = vws_client.add_target( name="x", width=1, image=high_quality_image, @@ -312,7 +312,7 @@ def test_metadata_too_large( s=decoded_metadata + b"x", ).decode(encoding="ascii") with pytest.raises(expected_exception=MetadataTooLargeError) as exc: - vws_client.add_target( + _ = vws_client.add_target( name="x", width=1, image=high_quality_image, @@ -355,7 +355,7 @@ def test_request_time_too_skewed( freeze_time(auto_tick_seconds=time_difference_from_now), pytest.raises(expected_exception=RequestTimeTooSkewedError) as exc, ): - vws_client.get_target_record(target_id=target_id) + _ = vws_client.get_target_record(target_id=target_id) assert exc.value.response.status_code == HTTPStatus.FORBIDDEN @@ -383,7 +383,7 @@ def test_authentication_failure( with pytest.raises( expected_exception=AuthenticationFailureError ) as exc: - vws_client.add_target( + _ = vws_client.add_target( name="x", width=1, image=high_quality_image, @@ -460,7 +460,7 @@ def test_invalid_instance_id( ID is given. """ with pytest.raises(expected_exception=InvalidInstanceIdError) as exc: - vumark_service_client.generate_vumark_instance( + _ = vumark_service_client.generate_vumark_instance( target_id=vumark_target_id, instance_id="", accept=VuMarkAccept.PNG, @@ -497,7 +497,7 @@ def test_invalid_target_type( with pytest.raises( expected_exception=InvalidTargetTypeError, ) as exc: - vumark_service.generate_vumark_instance( + _ = vumark_service.generate_vumark_instance( target_id=target_id, instance_id="example_instance_id", accept=VuMarkAccept.PNG, @@ -540,7 +540,7 @@ def test_documented_vumark_error_codes( ) with pytest.raises(expected_exception=exception_type) as exc: - vumark_service.generate_vumark_instance( + _ = vumark_service.generate_vumark_instance( target_id="exampletargetid", instance_id="example_instance_id", accept=VuMarkAccept.PNG, @@ -557,11 +557,11 @@ def test_base_exception( ) -> None: """``VWSException``s has a response property.""" with pytest.raises(expected_exception=VWSError) as exc: - vws_client.get_target_record(target_id="a") + _ = vws_client.get_target_record(target_id="a") assert exc.value.response.status_code == HTTPStatus.NOT_FOUND - vws_client.add_target( + _ = vws_client.add_target( name="x", width=1, image=high_quality_image, From 303b4a73a402ad8e39e646c8964f3041932b4bd7 Mon Sep 17 00:00:00 2001 From: Adam Dangoor Date: Tue, 8 Sep 2026 10:39:17 +0100 Subject: [PATCH 2/3] Keep documentation and coverage gates green --- docs/source/index.rst | 2 +- src/vws/exceptions/vws_exceptions.py | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index e1c26ba02..ebe92c10e 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -218,7 +218,7 @@ Transports are available for `requests`_, `httpx`_ and `HTTPX2`_. ) # This database has no targets. - assert vws_client.list_targets() == [] + assert len(vws_client.list_targets()) == 0 .. _requests: https://pypi.org/project/requests/ .. _httpx: https://pypi.org/project/httpx/ diff --git a/src/vws/exceptions/vws_exceptions.py b/src/vws/exceptions/vws_exceptions.py index 47b098c77..7341330ff 100644 --- a/src/vws/exceptions/vws_exceptions.py +++ b/src/vws/exceptions/vws_exceptions.py @@ -7,6 +7,7 @@ """ import json +from typing import cast from urllib.parse import urlparse from beartype import beartype @@ -143,9 +144,7 @@ class TargetNameExistError(VWSError): @property def target_name(self) -> str: """The target name which already exists.""" - response_body = self.response.request_body - if response_body is None or response_body in {"", b""}: - response_body = b"" + response_body = cast("str | bytes", self.response.request_body) request_json = json.loads(s=response_body) return str(object=request_json["name"]) # pyrefly: ignore [unknown-argument-type] From eb442cf594cd93cfcca9b88c8ca3c9d5b05f1097 Mon Sep 17 00:00:00 2001 From: Adam Dangoor Date: Tue, 8 Sep 2026 10:52:52 +0100 Subject: [PATCH 3/3] Enable all Pyrefly checks --- src/vws/exceptions/vws_exceptions.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vws/exceptions/vws_exceptions.py b/src/vws/exceptions/vws_exceptions.py index 7341330ff..9916dfe7f 100644 --- a/src/vws/exceptions/vws_exceptions.py +++ b/src/vws/exceptions/vws_exceptions.py @@ -7,7 +7,6 @@ """ import json -from typing import cast from urllib.parse import urlparse from beartype import beartype @@ -144,7 +143,10 @@ class TargetNameExistError(VWSError): @property def target_name(self) -> str: """The target name which already exists.""" - response_body = cast("str | bytes", self.response.request_body) + response_body = self.response.request_body + if not isinstance(response_body, str | bytes): # pragma: no cover + msg = "A target-name error response must have a request body." + raise TypeError(msg) request_json = json.loads(s=response_body) return str(object=request_json["name"]) # pyrefly: ignore [unknown-argument-type]