Skip to content

Commit bdd5c8e

Browse files
committed
Update image type to reflect reality
1 parent f1189c8 commit bdd5c8e

File tree

8 files changed

+64
-49
lines changed

8 files changed

+64
-49
lines changed

CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Next
66

77
* Breaking change: Exception names now end with ``Error``.
88
* Use a timeout (30 seconds) when making requests to the VWS API.
9+
* Type hint changes: images are now ``io.BytesIO`` instances or ``io.BufferedRandom``.
910

1011
2024.02.19
1112
------------

src/vws/query.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import datetime
88
import json
99
from http import HTTPMethod, HTTPStatus
10-
from typing import Any, BinaryIO
10+
from typing import TYPE_CHECKING, Any
1111
from urllib.parse import urljoin
1212

1313
import requests
@@ -29,8 +29,11 @@
2929
from vws.include_target_data import CloudRecoIncludeTargetData
3030
from vws.reports import QueryResult, TargetData
3131

32+
if TYPE_CHECKING:
33+
from io import BufferedRandom, BytesIO
3234

33-
def _get_image_data(image: BinaryIO) -> bytes:
35+
36+
def _get_image_data(image: BytesIO | BufferedRandom) -> bytes:
3437
"""Get the data of an image file."""
3538
original_tell = image.tell()
3639
image.seek(0)
@@ -62,7 +65,7 @@ def __init__(
6265

6366
def query(
6467
self,
65-
image: BinaryIO,
68+
image: BytesIO | BufferedRandom,
6669
max_num_results: int = 1,
6770
include_target_data: CloudRecoIncludeTargetData = (
6871
CloudRecoIncludeTargetData.TOP

src/vws/vws.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import time
1010
from datetime import date
1111
from http import HTTPMethod, HTTPStatus
12-
from typing import TYPE_CHECKING, BinaryIO
12+
from typing import TYPE_CHECKING
1313
from urllib.parse import urljoin
1414

1515
import requests
@@ -51,9 +51,10 @@
5151

5252
if TYPE_CHECKING:
5353
import io
54+
from io import BufferedRandom, BytesIO
5455

5556

56-
def _get_image_data(image: BinaryIO) -> bytes:
57+
def _get_image_data(image: BytesIO | BufferedRandom) -> bytes:
5758
"""Get the data of an image file."""
5859
original_tell = image.tell()
5960
image.seek(0)
@@ -238,7 +239,7 @@ def add_target(
238239
self,
239240
name: str,
240241
width: float,
241-
image: BinaryIO,
242+
image: BytesIO | BufferedRandom,
242243
application_metadata: str | None,
243244
*,
244245
active_flag: bool,
@@ -621,7 +622,7 @@ def update_target(
621622
target_id: str,
622623
name: str | None = None,
623624
width: float | None = None,
624-
image: io.BytesIO | None = None,
625+
image: io.BytesIO | io.BufferedRandom | None = None,
625626
active_flag: bool | None = None,
626627
application_metadata: str | None = None,
627628
) -> None:

tests/conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from __future__ import annotations
66

77
import io
8-
from typing import TYPE_CHECKING, BinaryIO
8+
from typing import TYPE_CHECKING
99

1010
import pytest
1111
from mock_vws import MockVWS
@@ -68,7 +68,7 @@ def image_file(
6868
@pytest.fixture(params=["high_quality_image", "image_file"])
6969
def image(
7070
request: pytest.FixtureRequest,
71-
) -> BinaryIO:
71+
) -> io.BytesIO | io.BufferedRandom:
7272
"""An image in any of the types that the API accepts."""
7373
result = request.getfixturevalue(request.param)
7474
assert isinstance(result, io.BytesIO | io.BufferedRandom)

tests/test_cloud_reco_exceptions.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
def test_too_many_max_results(
3434
cloud_reco_client: CloudRecoService,
35-
high_quality_image: io.BytesIO,
35+
high_quality_image: io.BytesIO | io.BufferedRandom,
3636
) -> None:
3737
"""
3838
A ``MaxNumResultsOutOfRange`` error is raised if the given
@@ -53,7 +53,7 @@ def test_too_many_max_results(
5353

5454
def test_image_too_large(
5555
cloud_reco_client: CloudRecoService,
56-
png_too_large: io.BytesIO,
56+
png_too_large: io.BytesIO | io.BufferedRandom,
5757
) -> None:
5858
"""
5959
A ``RequestEntityTooLarge`` exception is raised if an image which is too
@@ -82,7 +82,9 @@ def test_cloudrecoexception_inheritance() -> None:
8282
assert issubclass(subclass, CloudRecoError)
8383

8484

85-
def test_authentication_failure(high_quality_image: io.BytesIO) -> None:
85+
def test_authentication_failure(
86+
high_quality_image: io.BytesIO | io.BufferedRandom,
87+
) -> None:
8688
"""
8789
An ``AuthenticationFailure`` exception is raised when the client access key
8890
exists but the client secret key is incorrect.
@@ -101,7 +103,9 @@ def test_authentication_failure(high_quality_image: io.BytesIO) -> None:
101103
assert exc.value.response.status_code == HTTPStatus.UNAUTHORIZED
102104

103105

104-
def test_inactive_project(high_quality_image: io.BytesIO) -> None:
106+
def test_inactive_project(
107+
high_quality_image: io.BytesIO | io.BufferedRandom,
108+
) -> None:
105109
"""
106110
An ``InactiveProject`` exception is raised when querying an inactive
107111
database.

tests/test_query.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class TestQuery:
2525
@staticmethod
2626
def test_no_matches(
2727
cloud_reco_client: CloudRecoService,
28-
image: io.BytesIO,
28+
image: io.BytesIO | io.BufferedRandom,
2929
) -> None:
3030
"""
3131
An empty list is returned if there are no matches.
@@ -37,7 +37,7 @@ def test_no_matches(
3737
def test_match(
3838
vws_client: VWS,
3939
cloud_reco_client: CloudRecoService,
40-
image: io.BytesIO,
40+
image: io.BytesIO | io.BufferedRandom,
4141
) -> None:
4242
"""
4343
Details of matching targets are returned.
@@ -60,7 +60,7 @@ class TestCustomBaseVWQURL:
6060
"""
6161

6262
@staticmethod
63-
def test_custom_base_url(image: io.BytesIO) -> None:
63+
def test_custom_base_url(image: io.BytesIO | io.BufferedRandom) -> None:
6464
"""
6565
It is possible to use query a target to a database under a custom VWQ
6666
URL.
@@ -105,7 +105,7 @@ class TestMaxNumResults:
105105
def test_default(
106106
vws_client: VWS,
107107
cloud_reco_client: CloudRecoService,
108-
image: io.BytesIO,
108+
image: io.BytesIO | io.BufferedRandom,
109109
) -> None:
110110
"""
111111
By default the maximum number of results is 1.
@@ -133,7 +133,7 @@ def test_default(
133133
def test_custom(
134134
vws_client: VWS,
135135
cloud_reco_client: CloudRecoService,
136-
image: io.BytesIO,
136+
image: io.BytesIO | io.BufferedRandom,
137137
) -> None:
138138
"""
139139
It is possible to set a custom ``max_num_results``.
@@ -179,7 +179,7 @@ class TestIncludeTargetData:
179179
def test_default(
180180
vws_client: VWS,
181181
cloud_reco_client: CloudRecoService,
182-
image: io.BytesIO,
182+
image: io.BytesIO | io.BufferedRandom,
183183
) -> None:
184184
"""
185185
By default, target data is only returned in the top match.
@@ -211,7 +211,7 @@ def test_default(
211211
def test_top(
212212
vws_client: VWS,
213213
cloud_reco_client: CloudRecoService,
214-
image: io.BytesIO,
214+
image: io.BytesIO | io.BufferedRandom,
215215
) -> None:
216216
"""
217217
When ``CloudRecoIncludeTargetData.TOP`` is given, target data is only
@@ -245,7 +245,7 @@ def test_top(
245245
def test_none(
246246
vws_client: VWS,
247247
cloud_reco_client: CloudRecoService,
248-
image: io.BytesIO,
248+
image: io.BytesIO | io.BufferedRandom,
249249
) -> None:
250250
"""
251251
When ``CloudRecoIncludeTargetData.NONE`` is given, target data is not
@@ -279,7 +279,7 @@ def test_none(
279279
def test_all(
280280
vws_client: VWS,
281281
cloud_reco_client: CloudRecoService,
282-
image: io.BytesIO,
282+
image: io.BytesIO | io.BufferedRandom,
283283
) -> None:
284284
"""
285285
When ``CloudRecoIncludeTargetData.ALL`` is given, target data is

tests/test_vws.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import datetime
99
import secrets
1010
import uuid
11-
from typing import TYPE_CHECKING, BinaryIO
11+
from typing import TYPE_CHECKING
1212

1313
import pytest
1414
from freezegun import freeze_time
@@ -38,7 +38,7 @@ class TestAddTarget:
3838
@pytest.mark.parametrize("active_flag", [True, False])
3939
def test_add_target(
4040
vws_client: VWS,
41-
image: BinaryIO,
41+
image: io.BytesIO | io.BufferedRandom,
4242
application_metadata: bytes | None,
4343
cloud_reco_client: CloudRecoService,
4444
*,
@@ -82,7 +82,7 @@ def test_add_target(
8282
@staticmethod
8383
def test_add_two_targets(
8484
vws_client: VWS,
85-
image: io.BytesIO,
85+
image: io.BytesIO | io.BufferedRandom,
8686
) -> None:
8787
"""
8888
No exception is raised when adding two targets with different names.
@@ -105,7 +105,7 @@ class TestCustomBaseVWSURL:
105105
"""
106106

107107
@staticmethod
108-
def test_custom_base_url(image: io.BytesIO) -> None:
108+
def test_custom_base_url(image: io.BytesIO | io.BufferedRandom) -> None:
109109
"""
110110
It is possible to use add a target to a database under a custom VWS
111111
URL.
@@ -137,7 +137,7 @@ class TestListTargets:
137137
@staticmethod
138138
def test_list_targets(
139139
vws_client: VWS,
140-
image: io.BytesIO,
140+
image: io.BytesIO | io.BufferedRandom,
141141
) -> None:
142142
"""
143143
It is possible to get a list of target IDs.
@@ -167,7 +167,7 @@ class TestDelete:
167167
@staticmethod
168168
def test_delete_target(
169169
vws_client: VWS,
170-
image: io.BytesIO,
170+
image: io.BytesIO | io.BufferedRandom,
171171
) -> None:
172172
"""
173173
It is possible to delete a target.
@@ -194,7 +194,7 @@ class TestGetTargetSummaryReport:
194194
@staticmethod
195195
def test_get_target_summary_report(
196196
vws_client: VWS,
197-
image: io.BytesIO,
197+
image: io.BytesIO | io.BufferedRandom,
198198
) -> None:
199199
"""
200200
Details of a target are returned by ``get_target_summary_report``.
@@ -263,7 +263,7 @@ class TestGetTargetRecord:
263263
@staticmethod
264264
def test_get_target_record(
265265
vws_client: VWS,
266-
image: io.BytesIO,
266+
image: io.BytesIO | io.BufferedRandom,
267267
) -> None:
268268
"""
269269
Details of a target are returned by ``get_target_record``.
@@ -298,7 +298,7 @@ class TestWaitForTargetProcessed:
298298
@staticmethod
299299
def test_wait_for_target_processed(
300300
vws_client: VWS,
301-
image: io.BytesIO,
301+
image: io.BytesIO | io.BufferedRandom,
302302
) -> None:
303303
"""
304304
It is possible to wait until a target is processed.
@@ -318,7 +318,7 @@ def test_wait_for_target_processed(
318318

319319
@staticmethod
320320
def test_default_seconds_between_requests(
321-
image: io.BytesIO,
321+
image: io.BytesIO | io.BufferedRandom,
322322
) -> None:
323323
"""
324324
By default, 0.2 seconds are waited between polling requests.
@@ -370,7 +370,7 @@ def test_default_seconds_between_requests(
370370

371371
@staticmethod
372372
def test_custom_seconds_between_requests(
373-
image: io.BytesIO,
373+
image: io.BytesIO | io.BufferedRandom,
374374
) -> None:
375375
"""
376376
It is possible to customize the time waited between polling requests.
@@ -421,7 +421,7 @@ def test_custom_seconds_between_requests(
421421
assert report.request_usage == expected_requests
422422

423423
@staticmethod
424-
def test_custom_timeout(image: io.BytesIO) -> None:
424+
def test_custom_timeout(image: io.BytesIO | io.BufferedRandom) -> None:
425425
"""
426426
It is possible to set a maximum timeout.
427427
"""
@@ -465,7 +465,7 @@ class TestGetDuplicateTargets:
465465
@staticmethod
466466
def test_get_duplicate_targets(
467467
vws_client: VWS,
468-
image: io.BytesIO,
468+
image: io.BytesIO | io.BufferedRandom,
469469
) -> None:
470470
"""
471471
It is possible to get the IDs of similar targets.
@@ -499,8 +499,8 @@ class TestUpdateTarget:
499499
@staticmethod
500500
def test_update_target(
501501
vws_client: VWS,
502-
image: io.BytesIO,
503-
different_high_quality_image: io.BytesIO,
502+
image: io.BytesIO | io.BufferedRandom,
503+
different_high_quality_image: io.BytesIO | io.BufferedRandom,
504504
cloud_reco_client: CloudRecoService,
505505
) -> None:
506506
"""
@@ -558,7 +558,7 @@ def test_update_target(
558558
@staticmethod
559559
def test_no_fields_given(
560560
vws_client: VWS,
561-
image: io.BytesIO,
561+
image: io.BytesIO | io.BufferedRandom,
562562
) -> None:
563563
"""
564564
It is possible to give no update fields.

0 commit comments

Comments
 (0)