Skip to content

Commit e351090

Browse files
Merge pull request #1597 from VWS-Python/test-deleted-fix-hang
Test deleted fix hang
2 parents db352c7 + 9630db0 commit e351090

File tree

14 files changed

+30
-699
lines changed

14 files changed

+30
-699
lines changed

docs/source/differences-to-vws.rst

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,6 @@ The criteria for these images is not defined by the Vuforia documentation.
3737
The mock is more forgiving than the real Vuforia Web Services.
3838
Therefore, an image given a 'success' status by the mock may not be given a 'success' status by the real Vuforia Web Services.
3939

40-
Matching targets in the processing state
41-
----------------------------------------
42-
43-
Matching a target which is in the processing state sometimes returns a successful response with no results.
44-
Sometimes a 500 (``INTERNAL SERVER ERROR``) response is given.
45-
The mock always gives a 500 response.
46-
47-
Matching deleted targets
48-
------------------------
49-
50-
Matching a target which has been deleted returns a 500 (``INTERNAL SERVER ERROR``) response within the first few seconds.
51-
This time frame is not consistent on the real Vuforia Web Services.
52-
On the mock, this time frame is three seconds by default.
53-
:py:class:`~mock_vws.MockVWS` takes a parameter :paramref:`~mock_vws.MockVWS.query_processes_deletion_seconds` to change this.
54-
5540
Accepted date formats for the Query API
5641
---------------------------------------
5742

docs/source/docker.rst

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -118,20 +118,6 @@ Target manager container
118118
Query container
119119
~~~~~~~~~~~~~~~
120120

121-
.. envvar:: DELETION_PROCESSING_SECONDS
122-
123-
The number of seconds after a target deletion is recognized that the
124-
query endpoint will return a 500 response on a match.
125-
126-
Default: 3.0
127-
128-
.. envvar:: DELETION_RECOGNITION_SECONDS
129-
130-
The number of seconds after a target has been deleted that the query
131-
endpoint will still recognize the target for.
132-
133-
Default: 2.0
134-
135121
.. envvar:: QUERY_IMAGE_MATCHER
136122

137123
The matcher to use for the query endpoint.

pyproject.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,6 @@ dependencies = [
277277
"requests-mock",
278278
"tzdata; sys_platform == 'win32'",
279279
"vws-auth-tools",
280-
"werkzeug",
281280
]
282281

283282
[project.optional-dependencies]
@@ -319,7 +318,10 @@ dev = [
319318
"types-PyYAML==6.0.12.9",
320319
"types-Pillow==9.5.0.4",
321320
"types-requests==2.30.0.0",
322-
"urllib3==2.0.2",
321+
# We need urllib3 < 2.0.0 for pdm to work.
322+
# After we can bump urllib3, we can remove types-urllib.
323+
"types-urllib3==1.26.25.13",
324+
"urllib3<2.0.0",
323325
"vulture==2.7",
324326
"vws-python==2023.3.25",
325327
]

src/mock_vws/_flask_server/vwq.py

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,14 @@
1010
from http import HTTPStatus
1111

1212
import requests
13-
import werkzeug
1413
from flask import Flask, Response, request
1514
from pydantic import BaseSettings
1615

1716
from mock_vws._query_tools import (
18-
ActiveMatchingTargetsDeleteProcessing,
1917
get_query_match_response_text,
2018
)
2119
from mock_vws._query_validators import run_query_validators
2220
from mock_vws._query_validators.exceptions import (
23-
DeletedTargetMatched,
2421
ValidatorException,
2522
)
2623
from mock_vws.database import VuforiaDatabase
@@ -55,8 +52,6 @@ class VWQSettings(BaseSettings):
5552

5653
vwq_host: str = ""
5754
target_manager_base_url: str
58-
deletion_processing_seconds: float = 3.0
59-
deletion_recognition_seconds: float = 2.0
6055
query_image_matcher: _ImageMatcherChoice = _ImageMatcherChoice.AVERAGE_HASH
6156

6257

@@ -105,7 +100,8 @@ def handle_exceptions(exc: ValidatorException) -> Response:
105100
headers=exc.headers,
106101
)
107102

108-
response.headers = werkzeug.datastructures.Headers(exc.headers)
103+
response.headers.clear()
104+
response.headers.extend(exc.headers)
109105
return response
110106

111107

@@ -128,21 +124,14 @@ def query() -> Response:
128124
)
129125
date = email.utils.formatdate(None, localtime=False, usegmt=True)
130126

131-
try:
132-
response_text = get_query_match_response_text(
133-
request_headers=dict(request.headers),
134-
request_body=request_body,
135-
request_method=request.method,
136-
request_path=request.path,
137-
databases=databases,
138-
query_processes_deletion_seconds=settings.deletion_processing_seconds,
139-
query_recognizes_deletion_seconds=(
140-
settings.deletion_recognition_seconds
141-
),
142-
query_match_checker=query_match_checker,
143-
)
144-
except ActiveMatchingTargetsDeleteProcessing as exc:
145-
raise DeletedTargetMatched from exc
127+
response_text = get_query_match_response_text(
128+
request_headers=dict(request.headers),
129+
request_body=request_body,
130+
request_method=request.method,
131+
request_path=request.path,
132+
databases=databases,
133+
query_match_checker=query_match_checker,
134+
)
146135

147136
headers = {
148137
"Content-Type": "application/json",

src/mock_vws/_flask_server/vws.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
from http import HTTPStatus
1515

1616
import requests
17-
import werkzeug
1817
from flask import Flask, Response, request
1918
from pydantic import BaseSettings
2019

@@ -134,7 +133,8 @@ def handle_exceptions(exc: ValidatorException) -> Response:
134133
headers=exc.headers,
135134
)
136135

137-
response.headers = werkzeug.datastructures.Headers(exc.headers)
136+
response.headers.clear()
137+
response.headers.extend(exc.headers)
138138
return response
139139

140140

src/mock_vws/_query_tools.py

Lines changed: 2 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,12 @@
2424
from mock_vws.image_matchers import ImageMatcher
2525

2626

27-
class ActiveMatchingTargetsDeleteProcessing(Exception):
28-
"""
29-
There is at least one active target which matches and was recently deleted.
30-
"""
31-
32-
3327
def get_query_match_response_text(
3428
request_headers: dict[str, str],
3529
request_body: bytes,
3630
request_method: str,
3731
request_path: str,
3832
databases: set[VuforiaDatabase],
39-
query_processes_deletion_seconds: int | float,
40-
query_recognizes_deletion_seconds: int | float,
4133
query_match_checker: ImageMatcher,
4234
) -> str:
4335
"""
@@ -47,21 +39,11 @@ def get_query_match_response_text(
4739
request_body: The body of the request.
4840
request_method: The HTTP method of the request.
4941
databases: All Vuforia databases.
50-
query_recognizes_deletion_seconds: The number of seconds after a target
51-
has been deleted that the query endpoint will still recognize the
52-
target for.
53-
query_processes_deletion_seconds: The number of seconds after a target
54-
deletion is recognized that the query endpoint will return a 500
55-
response on a match.
5642
query_match_checker: A callable which takes two image values and
5743
returns whether they match.
5844
5945
Returns:
6046
The response text for a query endpoint request.
61-
62-
Raises:
63-
ActiveMatchingTargetsDeleteProcessing: There is at least one active
64-
target which matches and was recently deleted.
6547
"""
6648
body_file = io.BytesIO(request_body)
6749

@@ -88,15 +70,7 @@ def get_query_match_response_text(
8870
assert image_part is not None
8971
image_value = image_part.raw
9072
gmt = ZoneInfo("GMT")
91-
now = datetime.datetime.now(tz=gmt)
92-
93-
processing_timedelta = datetime.timedelta(
94-
seconds=query_processes_deletion_seconds,
95-
)
96-
97-
recognition_timedelta = datetime.timedelta(
98-
seconds=query_recognizes_deletion_seconds,
99-
)
73+
datetime.datetime.now(tz=gmt)
10074

10175
database = get_database_matching_client_keys(
10276
request_headers=request_headers,
@@ -125,28 +99,7 @@ def get_query_match_response_text(
12599
and target.status == TargetStatuses.SUCCESS.value
126100
]
127101

128-
deletion_not_recognized_matches = [
129-
target
130-
for target in matching_targets
131-
if target.active_flag
132-
and target.delete_date
133-
and (now - target.delete_date) < recognition_timedelta
134-
]
135-
136-
active_matching_targets_delete_processing = [
137-
target
138-
for target in matching_targets
139-
if target.active_flag
140-
and target.delete_date
141-
and (now - target.delete_date)
142-
< (recognition_timedelta + processing_timedelta)
143-
and target not in deletion_not_recognized_matches
144-
]
145-
146-
if active_matching_targets_delete_processing:
147-
raise ActiveMatchingTargetsDeleteProcessing
148-
149-
all_quality_matches = not_deleted_matches + deletion_not_recognized_matches
102+
all_quality_matches = not_deleted_matches
150103
minimum_rating = 0
151104
matches = [
152105
match

src/mock_vws/_query_validators/exceptions.py

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import textwrap
77
import uuid
88
from http import HTTPStatus
9-
from pathlib import Path
109

1110
from mock_vws._constants import ResultCodes
1211
from mock_vws._mock_common import json_dump
@@ -628,45 +627,6 @@ def __init__(self) -> None: # pragma: no cover
628627
}
629628

630629

631-
class DeletedTargetMatched(ValidatorException):
632-
"""
633-
Exception raised when target which was recently deleted is matched.
634-
"""
635-
636-
def __init__(self) -> None:
637-
"""
638-
Attributes:
639-
status_code: The status code to use in a response if this is
640-
raised.
641-
response_text: The response text to use in a response if this is
642-
raised.
643-
"""
644-
super().__init__()
645-
self.status_code = HTTPStatus.INTERNAL_SERVER_ERROR
646-
date = email.utils.formatdate(None, localtime=False, usegmt=True)
647-
# We return an example 500 response.
648-
# Each response given by Vuforia is different.
649-
#
650-
# Sometimes Vuforia will ignore matching targets with the
651-
# processing status, but we choose to:
652-
# * Do the most unexpected thing.
653-
# * Be consistent with every response.
654-
resources_dir = Path(__file__).parent.parent / "resources"
655-
filename = "deleted_target_matched_response.html"
656-
deleted_target_matched_resp_file = resources_dir / filename
657-
self.response_text = Path(deleted_target_matched_resp_file).read_text(
658-
encoding="utf-8",
659-
)
660-
self.headers = {
661-
"Connection": "keep-alive",
662-
"Content-Type": "text/html;charset=iso-8859-1",
663-
"Server": "nginx",
664-
"Cache-Control": "must-revalidate,no-cache,no-store",
665-
"Date": date,
666-
"Content-Length": str(len(self.response_text)),
667-
}
668-
669-
670630
class NoContentType(ValidatorException):
671631
"""
672632
Exception raised when a content type is either not given or is empty.

src/mock_vws/_requests_mock_server/decorators.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ def __init__(
4343
duplicate_match_checker: ImageMatcher = _AVERAGE_HASH_MATCHER,
4444
query_match_checker: ImageMatcher = _AVERAGE_HASH_MATCHER,
4545
processing_time_seconds: int | float = 2,
46-
query_recognizes_deletion_seconds: int | float = 2,
47-
query_processes_deletion_seconds: int | float = 3,
4846
target_tracking_rater: TargetTrackingRater = _BRISQUE_TRACKING_RATER,
4947
*,
5048
real_http: bool = False,
@@ -62,12 +60,6 @@ def __init__(
6260
In the real Vuforia Web Services, this is not deterministic.
6361
base_vwq_url: The base URL for the VWQ API.
6462
base_vws_url: The base URL for the VWS API.
65-
query_recognizes_deletion_seconds: The number
66-
of seconds after a target has been deleted that the query
67-
endpoint will still recognize the target for.
68-
query_processes_deletion_seconds: The number of
69-
seconds after a target deletion is recognized that the query
70-
endpoint will return a 500 response on a match.
7163
query_match_checker: A callable which takes two image values and
7264
returns whether they will match in a query request.
7365
duplicate_match_checker: A callable which takes two image values
@@ -104,12 +96,6 @@ def __init__(
10496

10597
self._mock_vwq_api = MockVuforiaWebQueryAPI(
10698
target_manager=self._target_manager,
107-
query_processes_deletion_seconds=(
108-
query_processes_deletion_seconds
109-
),
110-
query_recognizes_deletion_seconds=(
111-
query_recognizes_deletion_seconds
112-
),
11399
query_match_checker=query_match_checker,
114100
)
115101

0 commit comments

Comments
 (0)