Skip to content

Commit 6c8d6e1

Browse files
committed
Merge branch 'more-file-types' into more-beartype
2 parents 4eecd9c + 4480f97 commit 6c8d6e1

File tree

8 files changed

+71
-61
lines changed

8 files changed

+71
-61
lines changed

README.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ Getting Started
3030
from mock_vws import MockVWS
3131
from mock_vws.database import VuforiaDatabase
3232
33-
mock = MockVWS(real_http=False)
33+
# We use a low processing time so that tests run quickly.
34+
mock = MockVWS(processing_time_seconds=0.2)
3435
database = VuforiaDatabase(
3536
server_access_key='[server-access-key]',
3637
server_secret_key='[server-secret-key]',

src/vws/query.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
"""
44

55
import datetime
6+
import io
67
import json
78
from http import HTTPMethod, HTTPStatus
8-
from io import BufferedRandom, BytesIO
9-
from typing import Any
9+
from typing import Any, BinaryIO
1010
from urllib.parse import urljoin
1111

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

32+
_ImageType = io.BytesIO | BinaryIO
33+
3234

3335
@beartype
34-
def _get_image_data(image: BytesIO | BufferedRandom) -> bytes:
36+
def _get_image_data(image: _ImageType) -> bytes:
3537
"""Get the data of an image file."""
3638
original_tell = image.tell()
3739
image.seek(0)
@@ -64,7 +66,7 @@ def __init__(
6466

6567
def query(
6668
self,
67-
image: BytesIO | BufferedRandom,
69+
image: _ImageType,
6870
max_num_results: int = 1,
6971
include_target_data: CloudRecoIncludeTargetData = (
7072
CloudRecoIncludeTargetData.TOP

src/vws/vws.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import time
99
from datetime import date
1010
from http import HTTPMethod, HTTPStatus
11-
from io import BufferedRandom, BytesIO
11+
from typing import BinaryIO
1212
from urllib.parse import urljoin
1313

1414
import requests
@@ -49,9 +49,11 @@
4949

5050
from .exceptions.response import Response
5151

52+
_ImageType = io.BytesIO | BinaryIO
53+
5254

5355
@beartype
54-
def _get_image_data(image: BytesIO | BufferedRandom) -> bytes:
56+
def _get_image_data(image: _ImageType) -> bytes:
5557
"""Get the data of an image file."""
5658
original_tell = image.tell()
5759
image.seek(0)
@@ -238,7 +240,7 @@ def add_target(
238240
self,
239241
name: str,
240242
width: float,
241-
image: BytesIO | BufferedRandom,
243+
image: _ImageType,
242244
application_metadata: str | None,
243245
*,
244246
active_flag: bool,
@@ -621,7 +623,7 @@ def update_target(
621623
target_id: str,
622624
name: str | None = None,
623625
width: float | None = None,
624-
image: io.BytesIO | io.BufferedRandom | None = None,
626+
image: _ImageType | None = None,
625627
active_flag: bool | None = None,
626628
application_metadata: str | None = None,
627629
) -> None:

tests/conftest.py

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import io
66
from collections.abc import Generator
77
from pathlib import Path
8+
from typing import BinaryIO, Literal
89

910
import pytest
1011
from mock_vws import MockVWS
@@ -18,7 +19,8 @@ def mock_database() -> Generator[VuforiaDatabase, None, None]:
1819
"""
1920
Yield a mock ``VuforiaDatabase``.
2021
"""
21-
with MockVWS() as mock:
22+
# We use a low processing time so that tests run quickly.
23+
with MockVWS(processing_time_seconds=0.2) as mock:
2224
database = VuforiaDatabase()
2325
mock.add_database(database=database)
2426
yield database
@@ -46,25 +48,28 @@ def cloud_reco_client(_mock_database: VuforiaDatabase) -> CloudRecoService:
4648
)
4749

4850

49-
@pytest.fixture
50-
def image_file(
51+
@pytest.fixture(name="image_file", params=["r+b", "rb"])
52+
def image_file_fixture(
5153
high_quality_image: io.BytesIO,
5254
tmp_path: Path,
53-
) -> Generator[io.BufferedRandom, None, None]:
55+
request: pytest.FixtureRequest,
56+
) -> Generator[BinaryIO, None, None]:
5457
"""An image file object."""
5558
file = tmp_path / "image.jpg"
56-
file.touch()
57-
with file.open("r+b") as fileobj:
58-
buffer = high_quality_image.getvalue()
59-
fileobj.write(buffer)
60-
yield fileobj
59+
buffer = high_quality_image.getvalue()
60+
file.write_bytes(data=buffer)
61+
mode: Literal["r+b", "rb"] = request.param
62+
with file.open(mode=mode) as file_obj:
63+
yield file_obj
6164

6265

6366
@pytest.fixture(params=["high_quality_image", "image_file"])
6467
def image(
6568
request: pytest.FixtureRequest,
66-
) -> io.BytesIO | io.BufferedRandom:
69+
high_quality_image: io.BytesIO,
70+
image_file: BinaryIO,
71+
) -> io.BytesIO | BinaryIO:
6772
"""An image in any of the types that the API accepts."""
68-
result = request.getfixturevalue(request.param)
69-
assert isinstance(result, io.BytesIO | io.BufferedRandom)
70-
return result
73+
if request.param == "high_quality_image":
74+
return high_quality_image
75+
return image_file

tests/test_cloud_reco_exceptions.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
def test_too_many_max_results(
2929
cloud_reco_client: CloudRecoService,
30-
high_quality_image: io.BytesIO | io.BufferedRandom,
30+
high_quality_image: io.BytesIO,
3131
) -> None:
3232
"""
3333
A ``MaxNumResultsOutOfRange`` error is raised if the given
@@ -78,7 +78,7 @@ def test_cloudrecoexception_inheritance() -> None:
7878

7979

8080
def test_authentication_failure(
81-
high_quality_image: io.BytesIO | io.BufferedRandom,
81+
high_quality_image: io.BytesIO,
8282
) -> None:
8383
"""
8484
An ``AuthenticationFailure`` exception is raised when the client access key
@@ -99,7 +99,7 @@ def test_authentication_failure(
9999

100100

101101
def test_inactive_project(
102-
high_quality_image: io.BytesIO | io.BufferedRandom,
102+
high_quality_image: io.BytesIO,
103103
) -> None:
104104
"""
105105
An ``InactiveProject`` exception is raised when querying an inactive

tests/test_query.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import io
66
import uuid
7+
from typing import BinaryIO
78

89
from mock_vws import MockVWS
910
from mock_vws.database import VuforiaDatabase
@@ -20,7 +21,7 @@ class TestQuery:
2021
@staticmethod
2122
def test_no_matches(
2223
cloud_reco_client: CloudRecoService,
23-
image: io.BytesIO | io.BufferedRandom,
24+
image: io.BytesIO | BinaryIO,
2425
) -> None:
2526
"""
2627
An empty list is returned if there are no matches.
@@ -32,7 +33,7 @@ def test_no_matches(
3233
def test_match(
3334
vws_client: VWS,
3435
cloud_reco_client: CloudRecoService,
35-
image: io.BytesIO | io.BufferedRandom,
36+
image: io.BytesIO | BinaryIO,
3637
) -> None:
3738
"""
3839
Details of matching targets are returned.
@@ -55,7 +56,7 @@ class TestCustomBaseVWQURL:
5556
"""
5657

5758
@staticmethod
58-
def test_custom_base_url(image: io.BytesIO | io.BufferedRandom) -> None:
59+
def test_custom_base_url(image: io.BytesIO | BinaryIO) -> None:
5960
"""
6061
It is possible to use query a target to a database under a custom VWQ
6162
URL.
@@ -100,7 +101,7 @@ class TestMaxNumResults:
100101
def test_default(
101102
vws_client: VWS,
102103
cloud_reco_client: CloudRecoService,
103-
image: io.BytesIO | io.BufferedRandom,
104+
image: io.BytesIO | BinaryIO,
104105
) -> None:
105106
"""
106107
By default the maximum number of results is 1.
@@ -128,7 +129,7 @@ def test_default(
128129
def test_custom(
129130
vws_client: VWS,
130131
cloud_reco_client: CloudRecoService,
131-
image: io.BytesIO | io.BufferedRandom,
132+
image: io.BytesIO | BinaryIO,
132133
) -> None:
133134
"""
134135
It is possible to set a custom ``max_num_results``.
@@ -174,7 +175,7 @@ class TestIncludeTargetData:
174175
def test_default(
175176
vws_client: VWS,
176177
cloud_reco_client: CloudRecoService,
177-
image: io.BytesIO | io.BufferedRandom,
178+
image: io.BytesIO | BinaryIO,
178179
) -> None:
179180
"""
180181
By default, target data is only returned in the top match.
@@ -206,7 +207,7 @@ def test_default(
206207
def test_top(
207208
vws_client: VWS,
208209
cloud_reco_client: CloudRecoService,
209-
image: io.BytesIO | io.BufferedRandom,
210+
image: io.BytesIO | BinaryIO,
210211
) -> None:
211212
"""
212213
When ``CloudRecoIncludeTargetData.TOP`` is given, target data is only
@@ -240,7 +241,7 @@ def test_top(
240241
def test_none(
241242
vws_client: VWS,
242243
cloud_reco_client: CloudRecoService,
243-
image: io.BytesIO | io.BufferedRandom,
244+
image: io.BytesIO | BinaryIO,
244245
) -> None:
245246
"""
246247
When ``CloudRecoIncludeTargetData.NONE`` is given, target data is not
@@ -274,7 +275,7 @@ def test_none(
274275
def test_all(
275276
vws_client: VWS,
276277
cloud_reco_client: CloudRecoService,
277-
image: io.BytesIO | io.BufferedRandom,
278+
image: io.BytesIO | BinaryIO,
278279
) -> None:
279280
"""
280281
When ``CloudRecoIncludeTargetData.ALL`` is given, target data is

tests/test_vws.py

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import io
88
import secrets
99
import uuid
10+
from typing import BinaryIO
1011

1112
import pytest
1213
from freezegun import freeze_time
@@ -33,7 +34,7 @@ class TestAddTarget:
3334
@pytest.mark.parametrize("active_flag", [True, False])
3435
def test_add_target(
3536
vws_client: VWS,
36-
image: io.BytesIO | io.BufferedRandom,
37+
image: io.BytesIO | BinaryIO,
3738
application_metadata: bytes | None,
3839
cloud_reco_client: CloudRecoService,
3940
*,
@@ -77,7 +78,7 @@ def test_add_target(
7778
@staticmethod
7879
def test_add_two_targets(
7980
vws_client: VWS,
80-
image: io.BytesIO | io.BufferedRandom,
81+
image: io.BytesIO | BinaryIO,
8182
) -> None:
8283
"""
8384
No exception is raised when adding two targets with different names.
@@ -100,7 +101,7 @@ class TestCustomBaseVWSURL:
100101
"""
101102

102103
@staticmethod
103-
def test_custom_base_url(image: io.BytesIO | io.BufferedRandom) -> None:
104+
def test_custom_base_url(image: io.BytesIO | BinaryIO) -> None:
104105
"""
105106
It is possible to use add a target to a database under a custom VWS
106107
URL.
@@ -132,7 +133,7 @@ class TestListTargets:
132133
@staticmethod
133134
def test_list_targets(
134135
vws_client: VWS,
135-
image: io.BytesIO | io.BufferedRandom,
136+
image: io.BytesIO | BinaryIO,
136137
) -> None:
137138
"""
138139
It is possible to get a list of target IDs.
@@ -162,7 +163,7 @@ class TestDelete:
162163
@staticmethod
163164
def test_delete_target(
164165
vws_client: VWS,
165-
image: io.BytesIO | io.BufferedRandom,
166+
image: io.BytesIO | BinaryIO,
166167
) -> None:
167168
"""
168169
It is possible to delete a target.
@@ -189,7 +190,7 @@ class TestGetTargetSummaryReport:
189190
@staticmethod
190191
def test_get_target_summary_report(
191192
vws_client: VWS,
192-
image: io.BytesIO | io.BufferedRandom,
193+
image: io.BytesIO | BinaryIO,
193194
) -> None:
194195
"""
195196
Details of a target are returned by ``get_target_summary_report``.
@@ -258,7 +259,7 @@ class TestGetTargetRecord:
258259
@staticmethod
259260
def test_get_target_record(
260261
vws_client: VWS,
261-
image: io.BytesIO | io.BufferedRandom,
262+
image: io.BytesIO | BinaryIO,
262263
) -> None:
263264
"""
264265
Details of a target are returned by ``get_target_record``.
@@ -293,7 +294,7 @@ class TestWaitForTargetProcessed:
293294
@staticmethod
294295
def test_wait_for_target_processed(
295296
vws_client: VWS,
296-
image: io.BytesIO | io.BufferedRandom,
297+
image: io.BytesIO | BinaryIO,
297298
) -> None:
298299
"""
299300
It is possible to wait until a target is processed.
@@ -313,7 +314,7 @@ def test_wait_for_target_processed(
313314

314315
@staticmethod
315316
def test_default_seconds_between_requests(
316-
image: io.BytesIO | io.BufferedRandom,
317+
image: io.BytesIO | BinaryIO,
317318
) -> None:
318319
"""
319320
By default, 0.2 seconds are waited between polling requests.
@@ -365,7 +366,7 @@ def test_default_seconds_between_requests(
365366

366367
@staticmethod
367368
def test_custom_seconds_between_requests(
368-
image: io.BytesIO | io.BufferedRandom,
369+
image: io.BytesIO | BinaryIO,
369370
) -> None:
370371
"""
371372
It is possible to customize the time waited between polling requests.
@@ -416,7 +417,7 @@ def test_custom_seconds_between_requests(
416417
assert report.request_usage == expected_requests
417418

418419
@staticmethod
419-
def test_custom_timeout(image: io.BytesIO | io.BufferedRandom) -> None:
420+
def test_custom_timeout(image: io.BytesIO | BinaryIO) -> None:
420421
"""
421422
It is possible to set a maximum timeout.
422423
"""
@@ -460,7 +461,7 @@ class TestGetDuplicateTargets:
460461
@staticmethod
461462
def test_get_duplicate_targets(
462463
vws_client: VWS,
463-
image: io.BytesIO | io.BufferedRandom,
464+
image: io.BytesIO | BinaryIO,
464465
) -> None:
465466
"""
466467
It is possible to get the IDs of similar targets.
@@ -494,8 +495,8 @@ class TestUpdateTarget:
494495
@staticmethod
495496
def test_update_target(
496497
vws_client: VWS,
497-
image: io.BytesIO | io.BufferedRandom,
498-
different_high_quality_image: io.BytesIO | io.BufferedRandom,
498+
image: io.BytesIO | BinaryIO,
499+
different_high_quality_image: io.BytesIO,
499500
cloud_reco_client: CloudRecoService,
500501
) -> None:
501502
"""
@@ -553,7 +554,7 @@ def test_update_target(
553554
@staticmethod
554555
def test_no_fields_given(
555556
vws_client: VWS,
556-
image: io.BytesIO | io.BufferedRandom,
557+
image: io.BytesIO | BinaryIO,
557558
) -> None:
558559
"""
559560
It is possible to give no update fields.

0 commit comments

Comments
 (0)