vws-python-mock 2026.8.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mock_vws/__init__.py +9 -0
- mock_vws/_base64_decoding.py +35 -0
- mock_vws/_constants.py +84 -0
- mock_vws/_database_matchers.py +107 -0
- mock_vws/_flask_server/Dockerfile +32 -0
- mock_vws/_flask_server/__init__.py +1 -0
- mock_vws/_flask_server/healthcheck.py +31 -0
- mock_vws/_flask_server/target_manager.py +447 -0
- mock_vws/_flask_server/vwq.py +173 -0
- mock_vws/_flask_server/vws.py +954 -0
- mock_vws/_mock_common.py +75 -0
- mock_vws/_model_target_web_api.py +486 -0
- mock_vws/_query_tools.py +136 -0
- mock_vws/_query_validators/__init__.py +128 -0
- mock_vws/_query_validators/accept_header_validators.py +31 -0
- mock_vws/_query_validators/auth_validators.py +143 -0
- mock_vws/_query_validators/content_length_validators.py +90 -0
- mock_vws/_query_validators/content_type_validators.py +65 -0
- mock_vws/_query_validators/date_validators.py +110 -0
- mock_vws/_query_validators/exceptions.py +769 -0
- mock_vws/_query_validators/fields_validators.py +47 -0
- mock_vws/_query_validators/image_validators.py +197 -0
- mock_vws/_query_validators/include_target_data_validators.py +51 -0
- mock_vws/_query_validators/num_results_validators.py +64 -0
- mock_vws/_query_validators/project_state_validators.py +49 -0
- mock_vws/_requests_mock_server/__init__.py +1 -0
- mock_vws/_requests_mock_server/decorators.py +275 -0
- mock_vws/_requests_mock_server/mock_web_query_api.py +139 -0
- mock_vws/_requests_mock_server/mock_web_services_api.py +954 -0
- mock_vws/_respx_mock_server/__init__.py +1 -0
- mock_vws/_respx_mock_server/decorators.py +186 -0
- mock_vws/_services_validators/__init__.py +186 -0
- mock_vws/_services_validators/active_flag_validators.py +43 -0
- mock_vws/_services_validators/auth_validators.py +124 -0
- mock_vws/_services_validators/content_length_validators.py +102 -0
- mock_vws/_services_validators/content_type_validators.py +42 -0
- mock_vws/_services_validators/date_validators.py +78 -0
- mock_vws/_services_validators/exceptions.py +858 -0
- mock_vws/_services_validators/image_validators.py +220 -0
- mock_vws/_services_validators/json_validators.py +69 -0
- mock_vws/_services_validators/key_validators.py +171 -0
- mock_vws/_services_validators/metadata_validators.py +106 -0
- mock_vws/_services_validators/name_validators.py +235 -0
- mock_vws/_services_validators/project_state_validators.py +76 -0
- mock_vws/_services_validators/request_quota_validators.py +42 -0
- mock_vws/_services_validators/target_quota_validators.py +41 -0
- mock_vws/_services_validators/target_validators.py +69 -0
- mock_vws/_services_validators/width_validators.py +38 -0
- mock_vws/database.py +257 -0
- mock_vws/database_type.py +13 -0
- mock_vws/image_matchers.py +124 -0
- mock_vws/model_target.py +79 -0
- mock_vws/py.typed +0 -0
- mock_vws/states.py +20 -0
- mock_vws/target.py +285 -0
- mock_vws/target_manager.py +178 -0
- mock_vws/target_raters.py +109 -0
- vws_python_mock-2026.8.4.dist-info/METADATA +177 -0
- vws_python_mock-2026.8.4.dist-info/RECORD +62 -0
- vws_python_mock-2026.8.4.dist-info/WHEEL +5 -0
- vws_python_mock-2026.8.4.dist-info/licenses/LICENSE +21 -0
- vws_python_mock-2026.8.4.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,769 @@
|
|
|
1
|
+
"""Exceptions to raise from validators."""
|
|
2
|
+
|
|
3
|
+
import email.utils
|
|
4
|
+
import textwrap
|
|
5
|
+
import uuid
|
|
6
|
+
from collections.abc import Mapping
|
|
7
|
+
from http import HTTPStatus
|
|
8
|
+
|
|
9
|
+
from beartype import beartype
|
|
10
|
+
|
|
11
|
+
from mock_vws._constants import ResultCodes
|
|
12
|
+
from mock_vws._mock_common import json_dump
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@beartype
|
|
16
|
+
class ValidatorError(Exception):
|
|
17
|
+
"""
|
|
18
|
+
A base class for exceptions thrown from mock Vuforia cloud
|
|
19
|
+
recognition
|
|
20
|
+
client endpoints.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
status_code: HTTPStatus
|
|
24
|
+
response_text: str
|
|
25
|
+
headers: Mapping[str, str]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@beartype
|
|
29
|
+
class DateHeaderNotGivenError(ValidatorError):
|
|
30
|
+
"""Exception raised when a date header is not given."""
|
|
31
|
+
|
|
32
|
+
def __init__(self) -> None:
|
|
33
|
+
"""
|
|
34
|
+
Attributes:
|
|
35
|
+
status_code: The status code to use in a response if this is
|
|
36
|
+
raised.
|
|
37
|
+
response_text: The response text to use in a response if this
|
|
38
|
+
is
|
|
39
|
+
raised.
|
|
40
|
+
"""
|
|
41
|
+
super().__init__()
|
|
42
|
+
self.status_code = HTTPStatus.BAD_REQUEST
|
|
43
|
+
self.response_text = "Date header required."
|
|
44
|
+
date = email.utils.formatdate(
|
|
45
|
+
timeval=None,
|
|
46
|
+
localtime=False,
|
|
47
|
+
usegmt=True,
|
|
48
|
+
)
|
|
49
|
+
self.headers = {
|
|
50
|
+
"Content-Type": "text/plain;charset=iso-8859-1",
|
|
51
|
+
"Connection": "keep-alive",
|
|
52
|
+
"Server": "nginx",
|
|
53
|
+
"Date": date,
|
|
54
|
+
"Content-Length": str(object=len(self.response_text)),
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@beartype
|
|
59
|
+
class DateFormatNotValidError(ValidatorError):
|
|
60
|
+
"""Exception raised when the date format is not valid."""
|
|
61
|
+
|
|
62
|
+
def __init__(self) -> None:
|
|
63
|
+
"""
|
|
64
|
+
Attributes:
|
|
65
|
+
status_code: The status code to use in a response if this is
|
|
66
|
+
raised.
|
|
67
|
+
response_text: The response text to use in a response if this
|
|
68
|
+
is
|
|
69
|
+
raised.
|
|
70
|
+
"""
|
|
71
|
+
super().__init__()
|
|
72
|
+
self.status_code = HTTPStatus.UNAUTHORIZED
|
|
73
|
+
self.response_text = "Malformed date header."
|
|
74
|
+
date = email.utils.formatdate(
|
|
75
|
+
timeval=None,
|
|
76
|
+
localtime=False,
|
|
77
|
+
usegmt=True,
|
|
78
|
+
)
|
|
79
|
+
self.headers = {
|
|
80
|
+
"Content-Type": "text/plain;charset=iso-8859-1",
|
|
81
|
+
"Connection": "keep-alive",
|
|
82
|
+
"Server": "nginx",
|
|
83
|
+
"Date": date,
|
|
84
|
+
"WWW-Authenticate": "KWS",
|
|
85
|
+
"Content-Length": str(object=len(self.response_text)),
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@beartype
|
|
90
|
+
class RequestTimeTooSkewedError(ValidatorError):
|
|
91
|
+
"""Exception raised when Vuforia returns a response with a result code
|
|
92
|
+
'RequestTimeTooSkewed'.
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
def __init__(self) -> None:
|
|
96
|
+
"""
|
|
97
|
+
Attributes:
|
|
98
|
+
status_code: The status code to use in a response if this is
|
|
99
|
+
raised.
|
|
100
|
+
response_text: The response text to use in a response if this
|
|
101
|
+
is
|
|
102
|
+
raised.
|
|
103
|
+
"""
|
|
104
|
+
super().__init__()
|
|
105
|
+
self.status_code = HTTPStatus.FORBIDDEN
|
|
106
|
+
body = {
|
|
107
|
+
"transaction_id": uuid.uuid4().hex,
|
|
108
|
+
"result_code": ResultCodes.REQUEST_TIME_TOO_SKEWED.value,
|
|
109
|
+
}
|
|
110
|
+
self.response_text = json_dump(body=body)
|
|
111
|
+
date = email.utils.formatdate(
|
|
112
|
+
timeval=None,
|
|
113
|
+
localtime=False,
|
|
114
|
+
usegmt=True,
|
|
115
|
+
)
|
|
116
|
+
self.headers = {
|
|
117
|
+
"Content-Type": "application/json",
|
|
118
|
+
"Connection": "keep-alive",
|
|
119
|
+
"Server": "nginx",
|
|
120
|
+
"Date": date,
|
|
121
|
+
"Content-Length": str(object=len(self.response_text)),
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@beartype
|
|
126
|
+
class BadImageError(ValidatorError):
|
|
127
|
+
"""Exception raised when Vuforia returns a response with a result code
|
|
128
|
+
'BadImage'.
|
|
129
|
+
"""
|
|
130
|
+
|
|
131
|
+
def __init__(self) -> None:
|
|
132
|
+
"""
|
|
133
|
+
Attributes:
|
|
134
|
+
status_code: The status code to use in a response if this is
|
|
135
|
+
raised.
|
|
136
|
+
response_text: The response text to use in a response if this
|
|
137
|
+
is
|
|
138
|
+
raised.
|
|
139
|
+
"""
|
|
140
|
+
super().__init__()
|
|
141
|
+
self.status_code = HTTPStatus.UNPROCESSABLE_ENTITY
|
|
142
|
+
transaction_id = uuid.uuid4().hex
|
|
143
|
+
result_code = ResultCodes.BAD_IMAGE.value
|
|
144
|
+
|
|
145
|
+
# The response has an unusual format of separators, so we construct it
|
|
146
|
+
# manually.
|
|
147
|
+
self.response_text = (
|
|
148
|
+
'{"transaction_id": '
|
|
149
|
+
f'"{transaction_id}",'
|
|
150
|
+
f'"result_code":"{result_code}"'
|
|
151
|
+
"}"
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
date = email.utils.formatdate(
|
|
155
|
+
timeval=None,
|
|
156
|
+
localtime=False,
|
|
157
|
+
usegmt=True,
|
|
158
|
+
)
|
|
159
|
+
self.headers = {
|
|
160
|
+
"Content-Type": "application/json",
|
|
161
|
+
"Connection": "keep-alive",
|
|
162
|
+
"Server": "nginx",
|
|
163
|
+
"Date": date,
|
|
164
|
+
"Content-Length": str(object=len(self.response_text)),
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
@beartype
|
|
169
|
+
class AuthenticationFailureError(ValidatorError):
|
|
170
|
+
"""Exception raised when Vuforia returns a response with a result code
|
|
171
|
+
'AuthenticationFailure'.
|
|
172
|
+
"""
|
|
173
|
+
|
|
174
|
+
def __init__(self) -> None:
|
|
175
|
+
"""
|
|
176
|
+
Attributes:
|
|
177
|
+
status_code: The status code to use in a response if this is
|
|
178
|
+
raised.
|
|
179
|
+
response_text: The response text to use in a response if this
|
|
180
|
+
is
|
|
181
|
+
raised.
|
|
182
|
+
"""
|
|
183
|
+
super().__init__()
|
|
184
|
+
self.status_code = HTTPStatus.UNAUTHORIZED
|
|
185
|
+
transaction_id = uuid.uuid4().hex
|
|
186
|
+
result_code = ResultCodes.AUTHENTICATION_FAILURE.value
|
|
187
|
+
|
|
188
|
+
# The response has an unusual format of separators, so we construct it
|
|
189
|
+
# manually.
|
|
190
|
+
self.response_text = (
|
|
191
|
+
'{"transaction_id":'
|
|
192
|
+
f'"{transaction_id}",'
|
|
193
|
+
f'"result_code":"{result_code}"'
|
|
194
|
+
"}"
|
|
195
|
+
)
|
|
196
|
+
date = email.utils.formatdate(
|
|
197
|
+
timeval=None,
|
|
198
|
+
localtime=False,
|
|
199
|
+
usegmt=True,
|
|
200
|
+
)
|
|
201
|
+
self.headers = {
|
|
202
|
+
"Content-Type": "application/json",
|
|
203
|
+
"Connection": "keep-alive",
|
|
204
|
+
"Server": "nginx",
|
|
205
|
+
"Date": date,
|
|
206
|
+
"WWW-Authenticate": "VWS",
|
|
207
|
+
"Content-Length": str(object=len(self.response_text)),
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
@beartype
|
|
212
|
+
class AuthenticationFailureGoodFormattingError(ValidatorError):
|
|
213
|
+
"""Exception raised when Vuforia returns a response with a result code
|
|
214
|
+
'AuthenticationFailure' with a standard JSON formatting.
|
|
215
|
+
"""
|
|
216
|
+
|
|
217
|
+
def __init__(self) -> None:
|
|
218
|
+
"""
|
|
219
|
+
Attributes:
|
|
220
|
+
status_code: The status code to use in a response if this is
|
|
221
|
+
raised.
|
|
222
|
+
response_text: The response text to use in a response if this
|
|
223
|
+
is
|
|
224
|
+
raised.
|
|
225
|
+
"""
|
|
226
|
+
super().__init__()
|
|
227
|
+
self.status_code = HTTPStatus.UNAUTHORIZED
|
|
228
|
+
|
|
229
|
+
body = {
|
|
230
|
+
"transaction_id": uuid.uuid4().hex,
|
|
231
|
+
"result_code": ResultCodes.AUTHENTICATION_FAILURE.value,
|
|
232
|
+
}
|
|
233
|
+
self.response_text = json_dump(body=body)
|
|
234
|
+
date = email.utils.formatdate(
|
|
235
|
+
timeval=None,
|
|
236
|
+
localtime=False,
|
|
237
|
+
usegmt=True,
|
|
238
|
+
)
|
|
239
|
+
self.headers = {
|
|
240
|
+
"Content-Type": "application/json",
|
|
241
|
+
"Connection": "keep-alive",
|
|
242
|
+
"Server": "nginx",
|
|
243
|
+
"Date": date,
|
|
244
|
+
"WWW-Authenticate": "VWS",
|
|
245
|
+
"Content-Length": str(object=len(self.response_text)),
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
@beartype
|
|
250
|
+
class ImageNotGivenError(ValidatorError):
|
|
251
|
+
"""Exception raised when an image is not given."""
|
|
252
|
+
|
|
253
|
+
def __init__(self) -> None:
|
|
254
|
+
"""
|
|
255
|
+
Attributes:
|
|
256
|
+
status_code: The status code to use in a response if this is
|
|
257
|
+
raised.
|
|
258
|
+
response_text: The response text to use in a response if this
|
|
259
|
+
is
|
|
260
|
+
raised.
|
|
261
|
+
"""
|
|
262
|
+
super().__init__()
|
|
263
|
+
self.status_code = HTTPStatus.BAD_REQUEST
|
|
264
|
+
self.response_text = "No image."
|
|
265
|
+
|
|
266
|
+
date = email.utils.formatdate(
|
|
267
|
+
timeval=None,
|
|
268
|
+
localtime=False,
|
|
269
|
+
usegmt=True,
|
|
270
|
+
)
|
|
271
|
+
self.headers = {
|
|
272
|
+
"Content-Type": "application/json",
|
|
273
|
+
"Connection": "keep-alive",
|
|
274
|
+
"Server": "nginx",
|
|
275
|
+
"Date": date,
|
|
276
|
+
"Content-Length": str(object=len(self.response_text)),
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
@beartype
|
|
281
|
+
class AuthHeaderMissingError(ValidatorError):
|
|
282
|
+
"""Exception raised when an auth header is not given."""
|
|
283
|
+
|
|
284
|
+
def __init__(self) -> None:
|
|
285
|
+
"""
|
|
286
|
+
Attributes:
|
|
287
|
+
status_code: The status code to use in a response if this is
|
|
288
|
+
raised.
|
|
289
|
+
response_text: The response text to use in a response if this
|
|
290
|
+
is
|
|
291
|
+
raised.
|
|
292
|
+
"""
|
|
293
|
+
super().__init__()
|
|
294
|
+
self.status_code = HTTPStatus.UNAUTHORIZED
|
|
295
|
+
self.response_text = "Authorization header missing."
|
|
296
|
+
|
|
297
|
+
date = email.utils.formatdate(
|
|
298
|
+
timeval=None,
|
|
299
|
+
localtime=False,
|
|
300
|
+
usegmt=True,
|
|
301
|
+
)
|
|
302
|
+
self.headers = {
|
|
303
|
+
"Content-Type": "text/plain;charset=iso-8859-1",
|
|
304
|
+
"Connection": "keep-alive",
|
|
305
|
+
"Server": "nginx",
|
|
306
|
+
"Date": date,
|
|
307
|
+
"WWW-Authenticate": "KWS",
|
|
308
|
+
"Content-Length": str(object=len(self.response_text)),
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
@beartype
|
|
313
|
+
class MalformedAuthHeaderError(ValidatorError):
|
|
314
|
+
"""Exception raised when an auth header is not given."""
|
|
315
|
+
|
|
316
|
+
def __init__(self) -> None:
|
|
317
|
+
"""
|
|
318
|
+
Attributes:
|
|
319
|
+
status_code: The status code to use in a response if this is
|
|
320
|
+
raised.
|
|
321
|
+
response_text: The response text to use in a response if this
|
|
322
|
+
is
|
|
323
|
+
raised.
|
|
324
|
+
www_authenticate: The WWW-Authenticate header value.
|
|
325
|
+
"""
|
|
326
|
+
super().__init__()
|
|
327
|
+
self.status_code = HTTPStatus.UNAUTHORIZED
|
|
328
|
+
self.response_text = "Malformed authorization header."
|
|
329
|
+
|
|
330
|
+
date = email.utils.formatdate(
|
|
331
|
+
timeval=None,
|
|
332
|
+
localtime=False,
|
|
333
|
+
usegmt=True,
|
|
334
|
+
)
|
|
335
|
+
self.headers = {
|
|
336
|
+
"Content-Type": "text/plain;charset=iso-8859-1",
|
|
337
|
+
"Connection": "keep-alive",
|
|
338
|
+
"Server": "nginx",
|
|
339
|
+
"Date": date,
|
|
340
|
+
"WWW-Authenticate": "KWS",
|
|
341
|
+
"Content-Length": str(object=len(self.response_text)),
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
@beartype
|
|
346
|
+
class UnknownParametersError(ValidatorError):
|
|
347
|
+
"""Exception raised when unknown parameters are given."""
|
|
348
|
+
|
|
349
|
+
def __init__(self) -> None:
|
|
350
|
+
"""
|
|
351
|
+
Attributes:
|
|
352
|
+
status_code: The status code to use in a response if this is
|
|
353
|
+
raised.
|
|
354
|
+
response_text: The response text to use in a response if this
|
|
355
|
+
is
|
|
356
|
+
raised.
|
|
357
|
+
"""
|
|
358
|
+
super().__init__()
|
|
359
|
+
self.status_code = HTTPStatus.BAD_REQUEST
|
|
360
|
+
self.response_text = "Unknown parameters in the request."
|
|
361
|
+
|
|
362
|
+
date = email.utils.formatdate(
|
|
363
|
+
timeval=None,
|
|
364
|
+
localtime=False,
|
|
365
|
+
usegmt=True,
|
|
366
|
+
)
|
|
367
|
+
self.headers = {
|
|
368
|
+
"Content-Type": "application/json",
|
|
369
|
+
"Connection": "keep-alive",
|
|
370
|
+
"Server": "nginx",
|
|
371
|
+
"Date": date,
|
|
372
|
+
"Content-Length": str(object=len(self.response_text)),
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
@beartype
|
|
377
|
+
class InactiveProjectError(ValidatorError):
|
|
378
|
+
"""Exception raised when Vuforia returns a response with a result code
|
|
379
|
+
'InactiveProject'.
|
|
380
|
+
"""
|
|
381
|
+
|
|
382
|
+
def __init__(self) -> None:
|
|
383
|
+
"""
|
|
384
|
+
Attributes:
|
|
385
|
+
status_code: The status code to use in a response if this is
|
|
386
|
+
raised.
|
|
387
|
+
response_text: The response text to use in a response if this
|
|
388
|
+
is
|
|
389
|
+
raised.
|
|
390
|
+
"""
|
|
391
|
+
super().__init__()
|
|
392
|
+
self.status_code = HTTPStatus.FORBIDDEN
|
|
393
|
+
transaction_id = uuid.uuid4().hex
|
|
394
|
+
result_code = ResultCodes.INACTIVE_PROJECT.value
|
|
395
|
+
# The response has an unusual format of separators, so we construct it
|
|
396
|
+
# manually.
|
|
397
|
+
self.response_text = (
|
|
398
|
+
'{"transaction_id": '
|
|
399
|
+
f'"{transaction_id}",'
|
|
400
|
+
f'"result_code":"{result_code}"'
|
|
401
|
+
"}"
|
|
402
|
+
)
|
|
403
|
+
|
|
404
|
+
date = email.utils.formatdate(
|
|
405
|
+
timeval=None,
|
|
406
|
+
localtime=False,
|
|
407
|
+
usegmt=True,
|
|
408
|
+
)
|
|
409
|
+
self.headers = {
|
|
410
|
+
"Content-Type": "application/json",
|
|
411
|
+
"Connection": "keep-alive",
|
|
412
|
+
"Server": "nginx",
|
|
413
|
+
"Date": date,
|
|
414
|
+
"Content-Length": str(object=len(self.response_text)),
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
@beartype
|
|
419
|
+
class InvalidMaxNumResultsError(ValidatorError):
|
|
420
|
+
"""Exception raised when an invalid value is given as the
|
|
421
|
+
"max_num_results"
|
|
422
|
+
field.
|
|
423
|
+
"""
|
|
424
|
+
|
|
425
|
+
def __init__(self, given_value: str) -> None:
|
|
426
|
+
"""
|
|
427
|
+
Attributes:
|
|
428
|
+
status_code: The status code to use in a response if this is
|
|
429
|
+
raised.
|
|
430
|
+
response_text: The response text to use in a response if this
|
|
431
|
+
is
|
|
432
|
+
raised.
|
|
433
|
+
"""
|
|
434
|
+
super().__init__()
|
|
435
|
+
self.status_code = HTTPStatus.BAD_REQUEST
|
|
436
|
+
invalid_value_message = (
|
|
437
|
+
f"Invalid value '{given_value}' in form data part 'max_result'. "
|
|
438
|
+
"Expecting integer value in range from 1 to 50 (inclusive)."
|
|
439
|
+
)
|
|
440
|
+
self.response_text = invalid_value_message
|
|
441
|
+
|
|
442
|
+
date = email.utils.formatdate(
|
|
443
|
+
timeval=None,
|
|
444
|
+
localtime=False,
|
|
445
|
+
usegmt=True,
|
|
446
|
+
)
|
|
447
|
+
self.headers = {
|
|
448
|
+
"Content-Type": "application/json",
|
|
449
|
+
"Connection": "keep-alive",
|
|
450
|
+
"Server": "nginx",
|
|
451
|
+
"Date": date,
|
|
452
|
+
"Content-Length": str(object=len(self.response_text)),
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
@beartype
|
|
457
|
+
class MaxNumResultsOutOfRangeError(ValidatorError):
|
|
458
|
+
"""Exception raised when an integer value is given as the
|
|
459
|
+
"max_num_results"
|
|
460
|
+
field which is out of range.
|
|
461
|
+
"""
|
|
462
|
+
|
|
463
|
+
def __init__(self, given_value: str) -> None:
|
|
464
|
+
"""
|
|
465
|
+
Attributes:
|
|
466
|
+
status_code: The status code to use in a response if this is
|
|
467
|
+
raised.
|
|
468
|
+
response_text: The response text to use in a response if this
|
|
469
|
+
is
|
|
470
|
+
raised.
|
|
471
|
+
"""
|
|
472
|
+
super().__init__()
|
|
473
|
+
self.status_code = HTTPStatus.BAD_REQUEST
|
|
474
|
+
integer_out_of_range_message = (
|
|
475
|
+
f"Integer out of range ({given_value}) in form data part "
|
|
476
|
+
"'max_result'. Accepted range is from 1 to 50 (inclusive)."
|
|
477
|
+
)
|
|
478
|
+
self.response_text = integer_out_of_range_message
|
|
479
|
+
|
|
480
|
+
date = email.utils.formatdate(
|
|
481
|
+
timeval=None,
|
|
482
|
+
localtime=False,
|
|
483
|
+
usegmt=True,
|
|
484
|
+
)
|
|
485
|
+
self.headers = {
|
|
486
|
+
"Content-Type": "application/json",
|
|
487
|
+
"Connection": "keep-alive",
|
|
488
|
+
"Server": "nginx",
|
|
489
|
+
"Date": date,
|
|
490
|
+
"Content-Length": str(object=len(self.response_text)),
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
@beartype
|
|
495
|
+
class InvalidIncludeTargetDataError(ValidatorError):
|
|
496
|
+
"""Exception raised when an invalid value is given as the
|
|
497
|
+
"include_target_data" field.
|
|
498
|
+
"""
|
|
499
|
+
|
|
500
|
+
def __init__(self, given_value: str) -> None:
|
|
501
|
+
"""
|
|
502
|
+
Attributes:
|
|
503
|
+
status_code: The status code to use in a response if this is
|
|
504
|
+
raised.
|
|
505
|
+
response_text: The response text to use in a response if this
|
|
506
|
+
is
|
|
507
|
+
raised.
|
|
508
|
+
"""
|
|
509
|
+
super().__init__()
|
|
510
|
+
self.status_code = HTTPStatus.BAD_REQUEST
|
|
511
|
+
unexpected_target_data_message = (
|
|
512
|
+
f"Invalid value '{given_value.lower()}' in form data part "
|
|
513
|
+
"'include_target_data'. "
|
|
514
|
+
"Expecting one of the (unquoted) string values 'all', 'none' or "
|
|
515
|
+
"'top'."
|
|
516
|
+
)
|
|
517
|
+
self.response_text = unexpected_target_data_message
|
|
518
|
+
|
|
519
|
+
date = email.utils.formatdate(
|
|
520
|
+
timeval=None,
|
|
521
|
+
localtime=False,
|
|
522
|
+
usegmt=True,
|
|
523
|
+
)
|
|
524
|
+
self.headers = {
|
|
525
|
+
"Content-Type": "application/json",
|
|
526
|
+
"Connection": "keep-alive",
|
|
527
|
+
"Server": "nginx",
|
|
528
|
+
"Date": date,
|
|
529
|
+
"Content-Length": str(object=len(self.response_text)),
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
@beartype
|
|
534
|
+
class UnsupportedMediaTypeError(ValidatorError):
|
|
535
|
+
"""Exception raised when no boundary is found for multipart data."""
|
|
536
|
+
|
|
537
|
+
def __init__(self) -> None:
|
|
538
|
+
"""
|
|
539
|
+
Attributes:
|
|
540
|
+
status_code: The status code to use in a response if this is
|
|
541
|
+
raised.
|
|
542
|
+
response_text: The response text to use in a response if this
|
|
543
|
+
is
|
|
544
|
+
raised.
|
|
545
|
+
"""
|
|
546
|
+
super().__init__()
|
|
547
|
+
self.status_code = HTTPStatus.UNSUPPORTED_MEDIA_TYPE
|
|
548
|
+
self.response_text = ""
|
|
549
|
+
|
|
550
|
+
date = email.utils.formatdate(
|
|
551
|
+
timeval=None,
|
|
552
|
+
localtime=False,
|
|
553
|
+
usegmt=True,
|
|
554
|
+
)
|
|
555
|
+
self.headers = {
|
|
556
|
+
"Connection": "keep-alive",
|
|
557
|
+
"Server": "nginx",
|
|
558
|
+
"Date": date,
|
|
559
|
+
"Content-Length": str(object=len(self.response_text)),
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
@beartype
|
|
564
|
+
class InvalidAcceptHeaderError(ValidatorError):
|
|
565
|
+
"""Exception raised when there is an invalid accept header given."""
|
|
566
|
+
|
|
567
|
+
def __init__(self) -> None:
|
|
568
|
+
"""
|
|
569
|
+
Attributes:
|
|
570
|
+
status_code: The status code to use in a response if this is
|
|
571
|
+
raised.
|
|
572
|
+
response_text: The response text to use in a response if this
|
|
573
|
+
is
|
|
574
|
+
raised.
|
|
575
|
+
"""
|
|
576
|
+
super().__init__()
|
|
577
|
+
self.status_code = HTTPStatus.NOT_ACCEPTABLE
|
|
578
|
+
self.response_text = ""
|
|
579
|
+
|
|
580
|
+
date = email.utils.formatdate(
|
|
581
|
+
timeval=None,
|
|
582
|
+
localtime=False,
|
|
583
|
+
usegmt=True,
|
|
584
|
+
)
|
|
585
|
+
self.headers = {
|
|
586
|
+
"Connection": "keep-alive",
|
|
587
|
+
"Server": "nginx",
|
|
588
|
+
"Date": date,
|
|
589
|
+
"Content-Length": str(object=len(self.response_text)),
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
@beartype
|
|
594
|
+
class NoBoundaryFoundError(ValidatorError):
|
|
595
|
+
"""Exception raised when an invalid media type is given."""
|
|
596
|
+
|
|
597
|
+
def __init__(self) -> None:
|
|
598
|
+
"""
|
|
599
|
+
Attributes:
|
|
600
|
+
status_code: The status code to use in a response if this is
|
|
601
|
+
raised.
|
|
602
|
+
response_text: The response text to use in a response if this
|
|
603
|
+
is
|
|
604
|
+
raised.
|
|
605
|
+
"""
|
|
606
|
+
super().__init__()
|
|
607
|
+
self.status_code = HTTPStatus.BAD_REQUEST
|
|
608
|
+
self.response_text = "Unable to get boundary for multipart"
|
|
609
|
+
|
|
610
|
+
date = email.utils.formatdate(
|
|
611
|
+
timeval=None,
|
|
612
|
+
localtime=False,
|
|
613
|
+
usegmt=True,
|
|
614
|
+
)
|
|
615
|
+
self.headers = {
|
|
616
|
+
"Content-Type": "text/plain;charset=utf-8",
|
|
617
|
+
"Connection": "keep-alive",
|
|
618
|
+
"Server": "nginx",
|
|
619
|
+
"Date": date,
|
|
620
|
+
"Content-Length": str(object=len(self.response_text)),
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
|
|
624
|
+
@beartype
|
|
625
|
+
class ContentLengthHeaderTooLargeError(ValidatorError):
|
|
626
|
+
"""
|
|
627
|
+
Exception raised when the given content length header is too
|
|
628
|
+
large.
|
|
629
|
+
"""
|
|
630
|
+
|
|
631
|
+
# We skip coverage here as running a test to cover this is very slow.
|
|
632
|
+
def __init__(self) -> None: # pragma: no cover
|
|
633
|
+
"""
|
|
634
|
+
Attributes:
|
|
635
|
+
status_code: The status code to use in a response if this is
|
|
636
|
+
raised.
|
|
637
|
+
response_text: The response text to use in a response if this
|
|
638
|
+
is
|
|
639
|
+
raised.
|
|
640
|
+
"""
|
|
641
|
+
super().__init__()
|
|
642
|
+
self.status_code = HTTPStatus.GATEWAY_TIMEOUT
|
|
643
|
+
self.response_text = ""
|
|
644
|
+
self.headers = {
|
|
645
|
+
"Connection": "keep-alive",
|
|
646
|
+
"Content-Length": str(object=len(self.response_text)),
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
|
|
650
|
+
@beartype
|
|
651
|
+
class ContentLengthHeaderNotIntError(ValidatorError):
|
|
652
|
+
"""
|
|
653
|
+
Exception raised when the given content length header is not an
|
|
654
|
+
integer.
|
|
655
|
+
"""
|
|
656
|
+
|
|
657
|
+
def __init__(self) -> None:
|
|
658
|
+
"""
|
|
659
|
+
Attributes:
|
|
660
|
+
status_code: The status code to use in a response if this is
|
|
661
|
+
raised.
|
|
662
|
+
response_text: The response text to use in a response if this
|
|
663
|
+
is
|
|
664
|
+
raised.
|
|
665
|
+
"""
|
|
666
|
+
super().__init__()
|
|
667
|
+
self.status_code = HTTPStatus.BAD_REQUEST
|
|
668
|
+
self.response_text = ""
|
|
669
|
+
self.headers = {
|
|
670
|
+
"Connection": "Close",
|
|
671
|
+
"Content-Length": str(object=len(self.response_text)),
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
|
|
675
|
+
@beartype
|
|
676
|
+
class RequestEntityTooLargeError(ValidatorError):
|
|
677
|
+
"""Exception raised when the given image file size is too large."""
|
|
678
|
+
|
|
679
|
+
# Ignore coverage on this as there is a bug in urllib3 which means that we
|
|
680
|
+
# do not trigger this exception.
|
|
681
|
+
# See https://github.com/urllib3/urllib3/issues/2733.
|
|
682
|
+
def __init__(self) -> None: # pragma: no cover
|
|
683
|
+
"""
|
|
684
|
+
Attributes:
|
|
685
|
+
status_code: The status code to use in a response if this is
|
|
686
|
+
raised.
|
|
687
|
+
response_text: The response text to use in a response if this
|
|
688
|
+
is
|
|
689
|
+
raised.
|
|
690
|
+
"""
|
|
691
|
+
super().__init__()
|
|
692
|
+
self.status_code = HTTPStatus.REQUEST_ENTITY_TOO_LARGE
|
|
693
|
+
self.response_text = textwrap.dedent(
|
|
694
|
+
text="""\
|
|
695
|
+
<html>\r
|
|
696
|
+
<head><title>413 Request Entity Too Large</title></head>\r
|
|
697
|
+
<body>\r
|
|
698
|
+
<center><h1>413 Request Entity Too Large</h1></center>\r
|
|
699
|
+
<hr><center>nginx</center>\r
|
|
700
|
+
</body>\r
|
|
701
|
+
</html>\r
|
|
702
|
+
""",
|
|
703
|
+
)
|
|
704
|
+
date = email.utils.formatdate(
|
|
705
|
+
timeval=None,
|
|
706
|
+
localtime=False,
|
|
707
|
+
usegmt=True,
|
|
708
|
+
)
|
|
709
|
+
self.headers = {
|
|
710
|
+
"Connection": "Close",
|
|
711
|
+
"Date": date,
|
|
712
|
+
"Server": "nginx",
|
|
713
|
+
"Content-Type": "text/html",
|
|
714
|
+
"Content-Length": str(object=len(self.response_text)),
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
|
|
718
|
+
@beartype
|
|
719
|
+
class NoContentTypeError(ValidatorError):
|
|
720
|
+
"""
|
|
721
|
+
Exception raised when a content type is either not given or is
|
|
722
|
+
empty.
|
|
723
|
+
"""
|
|
724
|
+
|
|
725
|
+
def __init__(self) -> None:
|
|
726
|
+
"""
|
|
727
|
+
Attributes:
|
|
728
|
+
status_code: The status code to use in a response if this is
|
|
729
|
+
raised.
|
|
730
|
+
response_text: The response text to use in a response if this
|
|
731
|
+
is
|
|
732
|
+
raised.
|
|
733
|
+
"""
|
|
734
|
+
super().__init__()
|
|
735
|
+
self.status_code = HTTPStatus.BAD_REQUEST
|
|
736
|
+
date = email.utils.formatdate(
|
|
737
|
+
timeval=None,
|
|
738
|
+
localtime=False,
|
|
739
|
+
usegmt=True,
|
|
740
|
+
)
|
|
741
|
+
jetty_content_type_error = textwrap.dedent(
|
|
742
|
+
text="""\
|
|
743
|
+
<html>
|
|
744
|
+
<head>
|
|
745
|
+
<meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1"/>
|
|
746
|
+
<title>Error 400 Bad Request</title>
|
|
747
|
+
</head>
|
|
748
|
+
<body>
|
|
749
|
+
<h2>HTTP ERROR 400 Bad Request</h2>
|
|
750
|
+
<table>
|
|
751
|
+
<tr><th>URI:</th><td>http://cloudreco.vuforia.com/v1/query</td></tr>
|
|
752
|
+
<tr><th>STATUS:</th><td>400</td></tr>
|
|
753
|
+
<tr><th>MESSAGE:</th><td>Bad Request</td></tr>
|
|
754
|
+
</table>
|
|
755
|
+
<hr/><a href="https://jetty.org/">Powered by Jetty:// 12.0.20</a><hr/>
|
|
756
|
+
|
|
757
|
+
</body>
|
|
758
|
+
</html>
|
|
759
|
+
""", # noqa: E501
|
|
760
|
+
)
|
|
761
|
+
self.response_text = jetty_content_type_error
|
|
762
|
+
self.headers = {
|
|
763
|
+
"Connection": "keep-alive",
|
|
764
|
+
"Content-Type": "text/html;charset=iso-8859-1",
|
|
765
|
+
"Server": "nginx",
|
|
766
|
+
"Cache-Control": "must-revalidate,no-cache,no-store",
|
|
767
|
+
"Date": date,
|
|
768
|
+
"Content-Length": str(object=len(self.response_text)),
|
|
769
|
+
}
|