arkindex-base-worker 0.4.0rc3__py3-none-any.whl → 0.4.0rc4__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.
- {arkindex_base_worker-0.4.0rc3.dist-info → arkindex_base_worker-0.4.0rc4.dist-info}/METADATA +15 -14
- {arkindex_base_worker-0.4.0rc3.dist-info → arkindex_base_worker-0.4.0rc4.dist-info}/RECORD +21 -13
- {arkindex_base_worker-0.4.0rc3.dist-info → arkindex_base_worker-0.4.0rc4.dist-info}/WHEEL +1 -1
- arkindex_worker/cache.py +1 -1
- tests/test_elements_worker/{test_classifications.py → test_classification.py} +86 -0
- tests/test_elements_worker/test_corpus.py +31 -31
- tests/test_elements_worker/test_element.py +427 -0
- tests/test_elements_worker/test_element_create_multiple.py +715 -0
- tests/test_elements_worker/test_element_create_single.py +528 -0
- tests/test_elements_worker/test_element_list_children.py +969 -0
- tests/test_elements_worker/test_element_list_parents.py +530 -0
- tests/test_elements_worker/{test_entities.py → test_entity_create.py} +0 -153
- tests/test_elements_worker/test_entity_list_and_check.py +160 -0
- tests/test_elements_worker/test_transcription_create.py +873 -0
- tests/test_elements_worker/test_transcription_create_with_elements.py +951 -0
- tests/test_elements_worker/test_transcription_list.py +450 -0
- tests/test_elements_worker/test_version.py +60 -0
- tests/test_elements_worker/test_worker.py +525 -88
- tests/test_image.py +181 -198
- tests/test_elements_worker/test_elements.py +0 -3704
- tests/test_elements_worker/test_transcriptions.py +0 -2252
- {arkindex_base_worker-0.4.0rc3.dist-info → arkindex_base_worker-0.4.0rc4.dist-info}/LICENSE +0 -0
- {arkindex_base_worker-0.4.0rc3.dist-info → arkindex_base_worker-0.4.0rc4.dist-info}/top_level.txt +0 -0
|
@@ -1,3704 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import re
|
|
3
|
-
from argparse import Namespace
|
|
4
|
-
from uuid import UUID
|
|
5
|
-
|
|
6
|
-
import pytest
|
|
7
|
-
from responses import matchers
|
|
8
|
-
|
|
9
|
-
from arkindex.exceptions import ErrorResponse
|
|
10
|
-
from arkindex_worker.cache import (
|
|
11
|
-
SQL_VERSION,
|
|
12
|
-
CachedElement,
|
|
13
|
-
CachedImage,
|
|
14
|
-
create_version_table,
|
|
15
|
-
init_cache_db,
|
|
16
|
-
)
|
|
17
|
-
from arkindex_worker.models import Element
|
|
18
|
-
from arkindex_worker.utils import DEFAULT_BATCH_SIZE
|
|
19
|
-
from arkindex_worker.worker import ElementsWorker
|
|
20
|
-
from arkindex_worker.worker.dataset import DatasetState
|
|
21
|
-
from arkindex_worker.worker.element import MissingTypeError
|
|
22
|
-
from arkindex_worker.worker.process import ProcessMode
|
|
23
|
-
from tests import CORPUS_ID
|
|
24
|
-
|
|
25
|
-
from . import BASE_API_CALLS
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
def test_list_corpus_types(responses, mock_elements_worker):
|
|
29
|
-
responses.add(
|
|
30
|
-
responses.GET,
|
|
31
|
-
f"http://testserver/api/v1/corpus/{CORPUS_ID}/",
|
|
32
|
-
json={
|
|
33
|
-
"id": CORPUS_ID,
|
|
34
|
-
"types": [{"slug": "folder"}, {"slug": "page"}],
|
|
35
|
-
},
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
mock_elements_worker.list_corpus_types()
|
|
39
|
-
|
|
40
|
-
assert mock_elements_worker.corpus_types == {
|
|
41
|
-
"folder": {"slug": "folder"},
|
|
42
|
-
"page": {"slug": "page"},
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
def test_check_required_types_argument_types(mock_elements_worker):
|
|
47
|
-
with pytest.raises(
|
|
48
|
-
AssertionError, match="At least one element type slug is required."
|
|
49
|
-
):
|
|
50
|
-
mock_elements_worker.check_required_types()
|
|
51
|
-
|
|
52
|
-
with pytest.raises(AssertionError, match="Element type slugs must be strings."):
|
|
53
|
-
mock_elements_worker.check_required_types("lol", 42)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def test_check_required_types(mock_elements_worker):
|
|
57
|
-
mock_elements_worker.corpus_types = {
|
|
58
|
-
"folder": {"slug": "folder"},
|
|
59
|
-
"page": {"slug": "page"},
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
assert mock_elements_worker.check_required_types("page")
|
|
63
|
-
assert mock_elements_worker.check_required_types("page", "folder")
|
|
64
|
-
|
|
65
|
-
with pytest.raises(
|
|
66
|
-
MissingTypeError,
|
|
67
|
-
match=re.escape(
|
|
68
|
-
"Element types act, text_line were not found in corpus (11111111-1111-1111-1111-111111111111)."
|
|
69
|
-
),
|
|
70
|
-
):
|
|
71
|
-
assert mock_elements_worker.check_required_types("page", "text_line", "act")
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
def test_create_missing_types(responses, mock_elements_worker):
|
|
75
|
-
mock_elements_worker.corpus_types = {
|
|
76
|
-
"folder": {"slug": "folder"},
|
|
77
|
-
"page": {"slug": "page"},
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
responses.add(
|
|
81
|
-
responses.POST,
|
|
82
|
-
"http://testserver/api/v1/elements/type/",
|
|
83
|
-
match=[
|
|
84
|
-
matchers.json_params_matcher(
|
|
85
|
-
{
|
|
86
|
-
"slug": "text_line",
|
|
87
|
-
"display_name": "text_line",
|
|
88
|
-
"folder": False,
|
|
89
|
-
"corpus": CORPUS_ID,
|
|
90
|
-
}
|
|
91
|
-
)
|
|
92
|
-
],
|
|
93
|
-
)
|
|
94
|
-
responses.add(
|
|
95
|
-
responses.POST,
|
|
96
|
-
"http://testserver/api/v1/elements/type/",
|
|
97
|
-
match=[
|
|
98
|
-
matchers.json_params_matcher(
|
|
99
|
-
{
|
|
100
|
-
"slug": "act",
|
|
101
|
-
"display_name": "act",
|
|
102
|
-
"folder": False,
|
|
103
|
-
"corpus": CORPUS_ID,
|
|
104
|
-
}
|
|
105
|
-
)
|
|
106
|
-
],
|
|
107
|
-
)
|
|
108
|
-
|
|
109
|
-
assert mock_elements_worker.check_required_types(
|
|
110
|
-
"page", "text_line", "act", create_missing=True
|
|
111
|
-
)
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
def test_get_elements_elements_list_arg_wrong_type(
|
|
115
|
-
monkeypatch, tmp_path, mock_elements_worker
|
|
116
|
-
):
|
|
117
|
-
elements_path = tmp_path / "elements.json"
|
|
118
|
-
elements_path.write_text("{}")
|
|
119
|
-
|
|
120
|
-
monkeypatch.setenv("TASK_ELEMENTS", str(elements_path))
|
|
121
|
-
worker = ElementsWorker()
|
|
122
|
-
worker.configure()
|
|
123
|
-
|
|
124
|
-
with pytest.raises(AssertionError, match="Elements list must be a list"):
|
|
125
|
-
worker.get_elements()
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
def test_get_elements_elements_list_arg_empty_list(
|
|
129
|
-
monkeypatch, tmp_path, mock_elements_worker
|
|
130
|
-
):
|
|
131
|
-
elements_path = tmp_path / "elements.json"
|
|
132
|
-
elements_path.write_text("[]")
|
|
133
|
-
|
|
134
|
-
monkeypatch.setenv("TASK_ELEMENTS", str(elements_path))
|
|
135
|
-
worker = ElementsWorker()
|
|
136
|
-
worker.configure()
|
|
137
|
-
|
|
138
|
-
with pytest.raises(AssertionError, match="No elements in elements list"):
|
|
139
|
-
worker.get_elements()
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
def test_get_elements_elements_list_arg_missing_id(
|
|
143
|
-
monkeypatch, tmp_path, mock_elements_worker
|
|
144
|
-
):
|
|
145
|
-
elements_path = tmp_path / "elements.json"
|
|
146
|
-
elements_path.write_text(json.dumps([{"type": "volume"}]))
|
|
147
|
-
|
|
148
|
-
monkeypatch.setenv("TASK_ELEMENTS", str(elements_path))
|
|
149
|
-
worker = ElementsWorker()
|
|
150
|
-
worker.configure()
|
|
151
|
-
|
|
152
|
-
elt_list = worker.get_elements()
|
|
153
|
-
|
|
154
|
-
assert elt_list == []
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
def test_get_elements_elements_list_arg_not_uuid(
|
|
158
|
-
monkeypatch, tmp_path, mock_elements_worker
|
|
159
|
-
):
|
|
160
|
-
elements_path = tmp_path / "elements.json"
|
|
161
|
-
elements_path.write_text(
|
|
162
|
-
json.dumps(
|
|
163
|
-
[
|
|
164
|
-
{"id": "volumeid", "type": "volume"},
|
|
165
|
-
{"id": "pageid", "type": "page"},
|
|
166
|
-
{"id": "actid", "type": "act"},
|
|
167
|
-
{"id": "surfaceid", "type": "surface"},
|
|
168
|
-
]
|
|
169
|
-
)
|
|
170
|
-
)
|
|
171
|
-
|
|
172
|
-
monkeypatch.setenv("TASK_ELEMENTS", str(elements_path))
|
|
173
|
-
worker = ElementsWorker()
|
|
174
|
-
worker.configure()
|
|
175
|
-
|
|
176
|
-
with pytest.raises(
|
|
177
|
-
Exception,
|
|
178
|
-
match="These element IDs are invalid: volumeid, pageid, actid, surfaceid",
|
|
179
|
-
):
|
|
180
|
-
worker.get_elements()
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
def test_get_elements_elements_list_arg(monkeypatch, tmp_path, mock_elements_worker):
|
|
184
|
-
elements_path = tmp_path / "elements.json"
|
|
185
|
-
elements_path.write_text(
|
|
186
|
-
json.dumps(
|
|
187
|
-
[
|
|
188
|
-
{"id": "11111111-1111-1111-1111-111111111111", "type": "volume"},
|
|
189
|
-
{"id": "22222222-2222-2222-2222-222222222222", "type": "page"},
|
|
190
|
-
{"id": "33333333-3333-3333-3333-333333333333", "type": "act"},
|
|
191
|
-
]
|
|
192
|
-
)
|
|
193
|
-
)
|
|
194
|
-
|
|
195
|
-
monkeypatch.setenv("TASK_ELEMENTS", str(elements_path))
|
|
196
|
-
worker = ElementsWorker()
|
|
197
|
-
worker.configure()
|
|
198
|
-
|
|
199
|
-
elt_list = worker.get_elements()
|
|
200
|
-
|
|
201
|
-
assert elt_list == [
|
|
202
|
-
"11111111-1111-1111-1111-111111111111",
|
|
203
|
-
"22222222-2222-2222-2222-222222222222",
|
|
204
|
-
"33333333-3333-3333-3333-333333333333",
|
|
205
|
-
]
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
def test_get_elements_element_arg_not_uuid(mocker, mock_elements_worker):
|
|
209
|
-
mocker.patch(
|
|
210
|
-
"arkindex_worker.worker.base.argparse.ArgumentParser.parse_args",
|
|
211
|
-
return_value=Namespace(
|
|
212
|
-
element=["volumeid", "pageid"],
|
|
213
|
-
config={},
|
|
214
|
-
verbose=False,
|
|
215
|
-
elements_list=None,
|
|
216
|
-
database=None,
|
|
217
|
-
dev=True,
|
|
218
|
-
set=[],
|
|
219
|
-
),
|
|
220
|
-
)
|
|
221
|
-
|
|
222
|
-
worker = ElementsWorker()
|
|
223
|
-
worker.configure()
|
|
224
|
-
|
|
225
|
-
with pytest.raises(
|
|
226
|
-
Exception, match="These element IDs are invalid: volumeid, pageid"
|
|
227
|
-
):
|
|
228
|
-
worker.get_elements()
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
def test_get_elements_element_arg(mocker, mock_elements_worker):
|
|
232
|
-
mocker.patch(
|
|
233
|
-
"arkindex_worker.worker.base.argparse.ArgumentParser.parse_args",
|
|
234
|
-
return_value=Namespace(
|
|
235
|
-
element=[
|
|
236
|
-
"11111111-1111-1111-1111-111111111111",
|
|
237
|
-
"22222222-2222-2222-2222-222222222222",
|
|
238
|
-
],
|
|
239
|
-
config={},
|
|
240
|
-
verbose=False,
|
|
241
|
-
elements_list=None,
|
|
242
|
-
database=None,
|
|
243
|
-
dev=True,
|
|
244
|
-
set=[],
|
|
245
|
-
),
|
|
246
|
-
)
|
|
247
|
-
|
|
248
|
-
worker = ElementsWorker()
|
|
249
|
-
worker.configure()
|
|
250
|
-
|
|
251
|
-
elt_list = worker.get_elements()
|
|
252
|
-
|
|
253
|
-
assert elt_list == [
|
|
254
|
-
"11111111-1111-1111-1111-111111111111",
|
|
255
|
-
"22222222-2222-2222-2222-222222222222",
|
|
256
|
-
]
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
def test_get_elements_dataset_set_arg(responses, mocker, mock_elements_worker):
|
|
260
|
-
mocker.patch(
|
|
261
|
-
"arkindex_worker.worker.base.argparse.ArgumentParser.parse_args",
|
|
262
|
-
return_value=Namespace(
|
|
263
|
-
element=[],
|
|
264
|
-
config={},
|
|
265
|
-
verbose=False,
|
|
266
|
-
elements_list=None,
|
|
267
|
-
database=None,
|
|
268
|
-
dev=True,
|
|
269
|
-
set=[(UUID("11111111-1111-1111-1111-111111111111"), "train")],
|
|
270
|
-
),
|
|
271
|
-
)
|
|
272
|
-
|
|
273
|
-
# Mock RetrieveDataset call
|
|
274
|
-
responses.add(
|
|
275
|
-
responses.GET,
|
|
276
|
-
"http://testserver/api/v1/datasets/11111111-1111-1111-1111-111111111111/",
|
|
277
|
-
status=200,
|
|
278
|
-
json={
|
|
279
|
-
"id": "11111111-1111-1111-1111-111111111111",
|
|
280
|
-
"name": "My dataset",
|
|
281
|
-
"description": "A dataset about cats.",
|
|
282
|
-
"sets": ["train", "dev", "test"],
|
|
283
|
-
"state": DatasetState.Complete.value,
|
|
284
|
-
},
|
|
285
|
-
content_type="application/json",
|
|
286
|
-
)
|
|
287
|
-
|
|
288
|
-
# Mock ListSetElements call
|
|
289
|
-
element = {
|
|
290
|
-
"id": "22222222-2222-2222-2222-222222222222",
|
|
291
|
-
"type": "page",
|
|
292
|
-
"name": "1",
|
|
293
|
-
"corpus": {
|
|
294
|
-
"id": "11111111-1111-1111-1111-111111111111",
|
|
295
|
-
},
|
|
296
|
-
"thumbnail_url": "http://example.com",
|
|
297
|
-
"zone": {
|
|
298
|
-
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
|
299
|
-
"polygon": [[0, 0], [0, 0], [0, 0]],
|
|
300
|
-
"image": {
|
|
301
|
-
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
|
302
|
-
"path": "string",
|
|
303
|
-
"width": 0,
|
|
304
|
-
"height": 0,
|
|
305
|
-
"url": "http://example.com",
|
|
306
|
-
"s3_url": "string",
|
|
307
|
-
"status": "checked",
|
|
308
|
-
"server": {
|
|
309
|
-
"display_name": "string",
|
|
310
|
-
"url": "http://example.com",
|
|
311
|
-
"max_width": 2147483647,
|
|
312
|
-
"max_height": 2147483647,
|
|
313
|
-
},
|
|
314
|
-
},
|
|
315
|
-
"url": "http://example.com",
|
|
316
|
-
},
|
|
317
|
-
"rotation_angle": 0,
|
|
318
|
-
"mirrored": False,
|
|
319
|
-
"created": "2019-08-24T14:15:22Z",
|
|
320
|
-
"classes": [
|
|
321
|
-
{
|
|
322
|
-
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
|
323
|
-
"ml_class": {
|
|
324
|
-
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
|
325
|
-
"name": "string",
|
|
326
|
-
},
|
|
327
|
-
"state": "pending",
|
|
328
|
-
"confidence": 0,
|
|
329
|
-
"high_confidence": True,
|
|
330
|
-
"worker_run": {
|
|
331
|
-
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
|
332
|
-
"summary": "string",
|
|
333
|
-
},
|
|
334
|
-
}
|
|
335
|
-
],
|
|
336
|
-
"metadata": [
|
|
337
|
-
{
|
|
338
|
-
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
|
339
|
-
"type": "text",
|
|
340
|
-
"name": "string",
|
|
341
|
-
"value": "string",
|
|
342
|
-
"dates": [{"type": "exact", "year": 0, "month": 1, "day": 1}],
|
|
343
|
-
}
|
|
344
|
-
],
|
|
345
|
-
"transcriptions": [
|
|
346
|
-
{
|
|
347
|
-
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
|
348
|
-
"text": "string",
|
|
349
|
-
"confidence": 0,
|
|
350
|
-
"orientation": "horizontal-lr",
|
|
351
|
-
"worker_run": {
|
|
352
|
-
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
|
353
|
-
"summary": "string",
|
|
354
|
-
},
|
|
355
|
-
}
|
|
356
|
-
],
|
|
357
|
-
"has_children": True,
|
|
358
|
-
"worker_run": {
|
|
359
|
-
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
|
360
|
-
"summary": "string",
|
|
361
|
-
},
|
|
362
|
-
"confidence": 1,
|
|
363
|
-
}
|
|
364
|
-
responses.add(
|
|
365
|
-
responses.GET,
|
|
366
|
-
"http://testserver/api/v1/datasets/11111111-1111-1111-1111-111111111111/elements/?set=train&with_count=true",
|
|
367
|
-
status=200,
|
|
368
|
-
json={
|
|
369
|
-
"next": None,
|
|
370
|
-
"previous": None,
|
|
371
|
-
"results": [
|
|
372
|
-
{
|
|
373
|
-
"set": "train",
|
|
374
|
-
"element": element,
|
|
375
|
-
}
|
|
376
|
-
],
|
|
377
|
-
"count": 1,
|
|
378
|
-
},
|
|
379
|
-
content_type="application/json",
|
|
380
|
-
)
|
|
381
|
-
|
|
382
|
-
worker = ElementsWorker()
|
|
383
|
-
worker.configure()
|
|
384
|
-
|
|
385
|
-
elt_list = worker.get_elements()
|
|
386
|
-
|
|
387
|
-
assert elt_list == [
|
|
388
|
-
Element(**element),
|
|
389
|
-
]
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
def test_get_elements_dataset_set_api(responses, mocker, mock_elements_worker):
|
|
393
|
-
# Mock ListProcessSets call
|
|
394
|
-
responses.add(
|
|
395
|
-
responses.GET,
|
|
396
|
-
"http://testserver/api/v1/process/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeffff/sets/",
|
|
397
|
-
status=200,
|
|
398
|
-
json={
|
|
399
|
-
"next": None,
|
|
400
|
-
"previous": None,
|
|
401
|
-
"results": [
|
|
402
|
-
{
|
|
403
|
-
"id": "33333333-3333-3333-3333-333333333333",
|
|
404
|
-
"dataset": {"id": "11111111-1111-1111-1111-111111111111"},
|
|
405
|
-
"set_name": "train",
|
|
406
|
-
}
|
|
407
|
-
],
|
|
408
|
-
"count": 1,
|
|
409
|
-
},
|
|
410
|
-
content_type="application/json",
|
|
411
|
-
)
|
|
412
|
-
|
|
413
|
-
# Mock ListSetElements call
|
|
414
|
-
element = {
|
|
415
|
-
"id": "22222222-2222-2222-2222-222222222222",
|
|
416
|
-
"type": "page",
|
|
417
|
-
"name": "1",
|
|
418
|
-
"corpus": {
|
|
419
|
-
"id": "11111111-1111-1111-1111-111111111111",
|
|
420
|
-
},
|
|
421
|
-
"thumbnail_url": "http://example.com",
|
|
422
|
-
"zone": {
|
|
423
|
-
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
|
424
|
-
"polygon": [[0, 0], [0, 0], [0, 0]],
|
|
425
|
-
"image": {
|
|
426
|
-
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
|
427
|
-
"path": "string",
|
|
428
|
-
"width": 0,
|
|
429
|
-
"height": 0,
|
|
430
|
-
"url": "http://example.com",
|
|
431
|
-
"s3_url": "string",
|
|
432
|
-
"status": "checked",
|
|
433
|
-
"server": {
|
|
434
|
-
"display_name": "string",
|
|
435
|
-
"url": "http://example.com",
|
|
436
|
-
"max_width": 2147483647,
|
|
437
|
-
"max_height": 2147483647,
|
|
438
|
-
},
|
|
439
|
-
},
|
|
440
|
-
"url": "http://example.com",
|
|
441
|
-
},
|
|
442
|
-
"rotation_angle": 0,
|
|
443
|
-
"mirrored": False,
|
|
444
|
-
"created": "2019-08-24T14:15:22Z",
|
|
445
|
-
"classes": [
|
|
446
|
-
{
|
|
447
|
-
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
|
448
|
-
"ml_class": {
|
|
449
|
-
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
|
450
|
-
"name": "string",
|
|
451
|
-
},
|
|
452
|
-
"state": "pending",
|
|
453
|
-
"confidence": 0,
|
|
454
|
-
"high_confidence": True,
|
|
455
|
-
"worker_run": {
|
|
456
|
-
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
|
457
|
-
"summary": "string",
|
|
458
|
-
},
|
|
459
|
-
}
|
|
460
|
-
],
|
|
461
|
-
"metadata": [
|
|
462
|
-
{
|
|
463
|
-
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
|
464
|
-
"type": "text",
|
|
465
|
-
"name": "string",
|
|
466
|
-
"value": "string",
|
|
467
|
-
"dates": [{"type": "exact", "year": 0, "month": 1, "day": 1}],
|
|
468
|
-
}
|
|
469
|
-
],
|
|
470
|
-
"transcriptions": [
|
|
471
|
-
{
|
|
472
|
-
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
|
473
|
-
"text": "string",
|
|
474
|
-
"confidence": 0,
|
|
475
|
-
"orientation": "horizontal-lr",
|
|
476
|
-
"worker_run": {
|
|
477
|
-
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
|
478
|
-
"summary": "string",
|
|
479
|
-
},
|
|
480
|
-
}
|
|
481
|
-
],
|
|
482
|
-
"has_children": True,
|
|
483
|
-
"worker_run": {
|
|
484
|
-
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
|
485
|
-
"summary": "string",
|
|
486
|
-
},
|
|
487
|
-
"confidence": 1,
|
|
488
|
-
}
|
|
489
|
-
responses.add(
|
|
490
|
-
responses.GET,
|
|
491
|
-
"http://testserver/api/v1/datasets/11111111-1111-1111-1111-111111111111/elements/?set=train&with_count=true",
|
|
492
|
-
status=200,
|
|
493
|
-
json={
|
|
494
|
-
"next": None,
|
|
495
|
-
"previous": None,
|
|
496
|
-
"results": [
|
|
497
|
-
{
|
|
498
|
-
"set": "train",
|
|
499
|
-
"element": element,
|
|
500
|
-
}
|
|
501
|
-
],
|
|
502
|
-
"count": 1,
|
|
503
|
-
},
|
|
504
|
-
content_type="application/json",
|
|
505
|
-
)
|
|
506
|
-
|
|
507
|
-
# Update ProcessMode to Dataset
|
|
508
|
-
mock_elements_worker.process_information["mode"] = ProcessMode.Dataset
|
|
509
|
-
|
|
510
|
-
elt_list = mock_elements_worker.get_elements()
|
|
511
|
-
|
|
512
|
-
assert elt_list == [
|
|
513
|
-
Element(**element),
|
|
514
|
-
]
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
def test_get_elements_both_args_error(mocker, mock_elements_worker, tmp_path):
|
|
518
|
-
elements_path = tmp_path / "elements.json"
|
|
519
|
-
elements_path.write_text(
|
|
520
|
-
json.dumps(
|
|
521
|
-
[
|
|
522
|
-
{"id": "volumeid", "type": "volume"},
|
|
523
|
-
{"id": "pageid", "type": "page"},
|
|
524
|
-
{"id": "actid", "type": "act"},
|
|
525
|
-
{"id": "surfaceid", "type": "surface"},
|
|
526
|
-
]
|
|
527
|
-
)
|
|
528
|
-
)
|
|
529
|
-
mocker.patch(
|
|
530
|
-
"arkindex_worker.worker.base.argparse.ArgumentParser.parse_args",
|
|
531
|
-
return_value=Namespace(
|
|
532
|
-
element=["anotherid", "againanotherid"],
|
|
533
|
-
verbose=False,
|
|
534
|
-
elements_list=elements_path.open(),
|
|
535
|
-
database=None,
|
|
536
|
-
dev=False,
|
|
537
|
-
set=[],
|
|
538
|
-
),
|
|
539
|
-
)
|
|
540
|
-
|
|
541
|
-
worker = ElementsWorker()
|
|
542
|
-
worker.configure()
|
|
543
|
-
|
|
544
|
-
with pytest.raises(
|
|
545
|
-
AssertionError, match="elements-list and element CLI args shouldn't be both set"
|
|
546
|
-
):
|
|
547
|
-
worker.get_elements()
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
def test_database_arg(mocker, mock_elements_worker, tmp_path):
|
|
551
|
-
database_path = tmp_path / "my_database.sqlite"
|
|
552
|
-
init_cache_db(database_path)
|
|
553
|
-
create_version_table()
|
|
554
|
-
|
|
555
|
-
mocker.patch(
|
|
556
|
-
"arkindex_worker.worker.base.argparse.ArgumentParser.parse_args",
|
|
557
|
-
return_value=Namespace(
|
|
558
|
-
element=["volumeid", "pageid"],
|
|
559
|
-
verbose=False,
|
|
560
|
-
elements_list=None,
|
|
561
|
-
database=database_path,
|
|
562
|
-
dev=False,
|
|
563
|
-
set=[],
|
|
564
|
-
),
|
|
565
|
-
)
|
|
566
|
-
|
|
567
|
-
worker = ElementsWorker(support_cache=True)
|
|
568
|
-
worker.configure()
|
|
569
|
-
|
|
570
|
-
assert worker.use_cache is True
|
|
571
|
-
assert worker.cache_path == database_path
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
def test_database_arg_cache_missing_version_table(
|
|
575
|
-
mocker, mock_elements_worker, tmp_path
|
|
576
|
-
):
|
|
577
|
-
database_path = tmp_path / "my_database.sqlite"
|
|
578
|
-
database_path.touch()
|
|
579
|
-
|
|
580
|
-
mocker.patch(
|
|
581
|
-
"arkindex_worker.worker.base.argparse.ArgumentParser.parse_args",
|
|
582
|
-
return_value=Namespace(
|
|
583
|
-
element=["volumeid", "pageid"],
|
|
584
|
-
verbose=False,
|
|
585
|
-
elements_list=None,
|
|
586
|
-
database=database_path,
|
|
587
|
-
dev=False,
|
|
588
|
-
set=[],
|
|
589
|
-
),
|
|
590
|
-
)
|
|
591
|
-
|
|
592
|
-
worker = ElementsWorker(support_cache=True)
|
|
593
|
-
with pytest.raises(
|
|
594
|
-
AssertionError,
|
|
595
|
-
match=f"The SQLite database {database_path} does not have the correct cache version, it should be {SQL_VERSION}",
|
|
596
|
-
):
|
|
597
|
-
worker.configure()
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
def test_load_corpus_classes_api_error(responses, mock_elements_worker):
|
|
601
|
-
responses.add(
|
|
602
|
-
responses.GET,
|
|
603
|
-
f"http://testserver/api/v1/corpus/{CORPUS_ID}/classes/",
|
|
604
|
-
status=418,
|
|
605
|
-
)
|
|
606
|
-
|
|
607
|
-
assert not mock_elements_worker.classes
|
|
608
|
-
with pytest.raises(
|
|
609
|
-
Exception, match="Stopping pagination as data will be incomplete"
|
|
610
|
-
):
|
|
611
|
-
mock_elements_worker.load_corpus_classes()
|
|
612
|
-
|
|
613
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 5
|
|
614
|
-
assert [
|
|
615
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
616
|
-
] == BASE_API_CALLS + [
|
|
617
|
-
# We do 5 retries
|
|
618
|
-
(
|
|
619
|
-
"GET",
|
|
620
|
-
f"http://testserver/api/v1/corpus/{CORPUS_ID}/classes/",
|
|
621
|
-
),
|
|
622
|
-
(
|
|
623
|
-
"GET",
|
|
624
|
-
f"http://testserver/api/v1/corpus/{CORPUS_ID}/classes/",
|
|
625
|
-
),
|
|
626
|
-
(
|
|
627
|
-
"GET",
|
|
628
|
-
f"http://testserver/api/v1/corpus/{CORPUS_ID}/classes/",
|
|
629
|
-
),
|
|
630
|
-
(
|
|
631
|
-
"GET",
|
|
632
|
-
f"http://testserver/api/v1/corpus/{CORPUS_ID}/classes/",
|
|
633
|
-
),
|
|
634
|
-
(
|
|
635
|
-
"GET",
|
|
636
|
-
f"http://testserver/api/v1/corpus/{CORPUS_ID}/classes/",
|
|
637
|
-
),
|
|
638
|
-
]
|
|
639
|
-
assert not mock_elements_worker.classes
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
def test_load_corpus_classes(responses, mock_elements_worker):
|
|
643
|
-
responses.add(
|
|
644
|
-
responses.GET,
|
|
645
|
-
f"http://testserver/api/v1/corpus/{CORPUS_ID}/classes/",
|
|
646
|
-
status=200,
|
|
647
|
-
json={
|
|
648
|
-
"count": 3,
|
|
649
|
-
"next": None,
|
|
650
|
-
"results": [
|
|
651
|
-
{
|
|
652
|
-
"id": "0000",
|
|
653
|
-
"name": "good",
|
|
654
|
-
},
|
|
655
|
-
{
|
|
656
|
-
"id": "1111",
|
|
657
|
-
"name": "average",
|
|
658
|
-
},
|
|
659
|
-
{
|
|
660
|
-
"id": "2222",
|
|
661
|
-
"name": "bad",
|
|
662
|
-
},
|
|
663
|
-
],
|
|
664
|
-
},
|
|
665
|
-
)
|
|
666
|
-
|
|
667
|
-
assert not mock_elements_worker.classes
|
|
668
|
-
mock_elements_worker.load_corpus_classes()
|
|
669
|
-
|
|
670
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 1
|
|
671
|
-
assert [
|
|
672
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
673
|
-
] == BASE_API_CALLS + [
|
|
674
|
-
(
|
|
675
|
-
"GET",
|
|
676
|
-
f"http://testserver/api/v1/corpus/{CORPUS_ID}/classes/",
|
|
677
|
-
),
|
|
678
|
-
]
|
|
679
|
-
assert mock_elements_worker.classes == {
|
|
680
|
-
"good": "0000",
|
|
681
|
-
"average": "1111",
|
|
682
|
-
"bad": "2222",
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
def test_create_sub_element_wrong_element(mock_elements_worker):
|
|
687
|
-
with pytest.raises(
|
|
688
|
-
AssertionError, match="element shouldn't be null and should be of type Element"
|
|
689
|
-
):
|
|
690
|
-
mock_elements_worker.create_sub_element(
|
|
691
|
-
element=None,
|
|
692
|
-
type="something",
|
|
693
|
-
name="0",
|
|
694
|
-
polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
695
|
-
)
|
|
696
|
-
|
|
697
|
-
with pytest.raises(
|
|
698
|
-
AssertionError, match="element shouldn't be null and should be of type Element"
|
|
699
|
-
):
|
|
700
|
-
mock_elements_worker.create_sub_element(
|
|
701
|
-
element="not element type",
|
|
702
|
-
type="something",
|
|
703
|
-
name="0",
|
|
704
|
-
polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
705
|
-
)
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
def test_create_sub_element_wrong_type(mock_elements_worker):
|
|
709
|
-
elt = Element({"zone": None})
|
|
710
|
-
|
|
711
|
-
with pytest.raises(
|
|
712
|
-
AssertionError, match="type shouldn't be null and should be of type str"
|
|
713
|
-
):
|
|
714
|
-
mock_elements_worker.create_sub_element(
|
|
715
|
-
element=elt,
|
|
716
|
-
type=None,
|
|
717
|
-
name="0",
|
|
718
|
-
polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
719
|
-
)
|
|
720
|
-
|
|
721
|
-
with pytest.raises(
|
|
722
|
-
AssertionError, match="type shouldn't be null and should be of type str"
|
|
723
|
-
):
|
|
724
|
-
mock_elements_worker.create_sub_element(
|
|
725
|
-
element=elt,
|
|
726
|
-
type=1234,
|
|
727
|
-
name="0",
|
|
728
|
-
polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
729
|
-
)
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
def test_create_sub_element_wrong_name(mock_elements_worker):
|
|
733
|
-
elt = Element({"zone": None})
|
|
734
|
-
|
|
735
|
-
with pytest.raises(
|
|
736
|
-
AssertionError, match="name shouldn't be null and should be of type str"
|
|
737
|
-
):
|
|
738
|
-
mock_elements_worker.create_sub_element(
|
|
739
|
-
element=elt,
|
|
740
|
-
type="something",
|
|
741
|
-
name=None,
|
|
742
|
-
polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
743
|
-
)
|
|
744
|
-
|
|
745
|
-
with pytest.raises(
|
|
746
|
-
AssertionError, match="name shouldn't be null and should be of type str"
|
|
747
|
-
):
|
|
748
|
-
mock_elements_worker.create_sub_element(
|
|
749
|
-
element=elt,
|
|
750
|
-
type="something",
|
|
751
|
-
name=1234,
|
|
752
|
-
polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
753
|
-
)
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
def test_create_sub_element_wrong_polygon(mock_elements_worker):
|
|
757
|
-
elt = Element({"zone": None})
|
|
758
|
-
|
|
759
|
-
with pytest.raises(AssertionError, match="polygon should be None or a list"):
|
|
760
|
-
mock_elements_worker.create_sub_element(
|
|
761
|
-
element=elt,
|
|
762
|
-
type="something",
|
|
763
|
-
name="O",
|
|
764
|
-
polygon="not a polygon",
|
|
765
|
-
)
|
|
766
|
-
|
|
767
|
-
with pytest.raises(
|
|
768
|
-
AssertionError, match="polygon should have at least three points"
|
|
769
|
-
):
|
|
770
|
-
mock_elements_worker.create_sub_element(
|
|
771
|
-
element=elt,
|
|
772
|
-
type="something",
|
|
773
|
-
name="O",
|
|
774
|
-
polygon=[[1, 1], [2, 2]],
|
|
775
|
-
)
|
|
776
|
-
|
|
777
|
-
with pytest.raises(
|
|
778
|
-
AssertionError, match="polygon points should be lists of two items"
|
|
779
|
-
):
|
|
780
|
-
mock_elements_worker.create_sub_element(
|
|
781
|
-
element=elt,
|
|
782
|
-
type="something",
|
|
783
|
-
name="O",
|
|
784
|
-
polygon=[[1, 1, 1], [2, 2, 1], [2, 1, 1], [1, 2, 1]],
|
|
785
|
-
)
|
|
786
|
-
|
|
787
|
-
with pytest.raises(
|
|
788
|
-
AssertionError, match="polygon points should be lists of two items"
|
|
789
|
-
):
|
|
790
|
-
mock_elements_worker.create_sub_element(
|
|
791
|
-
element=elt,
|
|
792
|
-
type="something",
|
|
793
|
-
name="O",
|
|
794
|
-
polygon=[[1], [2], [2], [1]],
|
|
795
|
-
)
|
|
796
|
-
|
|
797
|
-
with pytest.raises(
|
|
798
|
-
AssertionError, match="polygon points should be lists of two numbers"
|
|
799
|
-
):
|
|
800
|
-
mock_elements_worker.create_sub_element(
|
|
801
|
-
element=elt,
|
|
802
|
-
type="something",
|
|
803
|
-
name="O",
|
|
804
|
-
polygon=[["not a coord", 1], [2, 2], [2, 1], [1, 2]],
|
|
805
|
-
)
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
@pytest.mark.parametrize("confidence", ["lol", "0.2", -1.0, 1.42, float("inf")])
|
|
809
|
-
def test_create_sub_element_wrong_confidence(mock_elements_worker, confidence):
|
|
810
|
-
with pytest.raises(
|
|
811
|
-
AssertionError,
|
|
812
|
-
match=re.escape("confidence should be None or a float in [0..1] range"),
|
|
813
|
-
):
|
|
814
|
-
mock_elements_worker.create_sub_element(
|
|
815
|
-
element=Element({"zone": None}),
|
|
816
|
-
type="something",
|
|
817
|
-
name="blah",
|
|
818
|
-
polygon=[[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]],
|
|
819
|
-
confidence=confidence,
|
|
820
|
-
)
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
@pytest.mark.parametrize(
|
|
824
|
-
("image", "error_type", "error_message"),
|
|
825
|
-
[
|
|
826
|
-
(1, AssertionError, "image should be None or string"),
|
|
827
|
-
("not a uuid", ValueError, "image is not a valid uuid."),
|
|
828
|
-
],
|
|
829
|
-
)
|
|
830
|
-
def test_create_sub_element_wrong_image(
|
|
831
|
-
mock_elements_worker, image, error_type, error_message
|
|
832
|
-
):
|
|
833
|
-
with pytest.raises(error_type, match=re.escape(error_message)):
|
|
834
|
-
mock_elements_worker.create_sub_element(
|
|
835
|
-
element=Element({"zone": None}),
|
|
836
|
-
type="something",
|
|
837
|
-
name="blah",
|
|
838
|
-
polygon=[[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]],
|
|
839
|
-
image=image,
|
|
840
|
-
)
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
def test_create_sub_element_wrong_image_and_polygon(mock_elements_worker):
|
|
844
|
-
with pytest.raises(
|
|
845
|
-
AssertionError,
|
|
846
|
-
match=re.escape(
|
|
847
|
-
"An image or a parent with an image is required to create an element with a polygon."
|
|
848
|
-
),
|
|
849
|
-
):
|
|
850
|
-
mock_elements_worker.create_sub_element(
|
|
851
|
-
element=Element({"zone": None}),
|
|
852
|
-
type="something",
|
|
853
|
-
name="blah",
|
|
854
|
-
polygon=[[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]],
|
|
855
|
-
image=None,
|
|
856
|
-
)
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
def test_create_sub_element_api_error(responses, mock_elements_worker):
|
|
860
|
-
elt = Element(
|
|
861
|
-
{
|
|
862
|
-
"id": "12341234-1234-1234-1234-123412341234",
|
|
863
|
-
"corpus": {"id": CORPUS_ID},
|
|
864
|
-
"zone": {"image": {"id": "22222222-2222-2222-2222-222222222222"}},
|
|
865
|
-
}
|
|
866
|
-
)
|
|
867
|
-
responses.add(
|
|
868
|
-
responses.POST,
|
|
869
|
-
"http://testserver/api/v1/elements/create/",
|
|
870
|
-
status=418,
|
|
871
|
-
)
|
|
872
|
-
|
|
873
|
-
with pytest.raises(ErrorResponse):
|
|
874
|
-
mock_elements_worker.create_sub_element(
|
|
875
|
-
element=elt,
|
|
876
|
-
type="something",
|
|
877
|
-
name="0",
|
|
878
|
-
polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
879
|
-
)
|
|
880
|
-
|
|
881
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 1
|
|
882
|
-
assert [
|
|
883
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
884
|
-
] == BASE_API_CALLS + [("POST", "http://testserver/api/v1/elements/create/")]
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
@pytest.mark.parametrize("slim_output", [True, False])
|
|
888
|
-
def test_create_sub_element(responses, mock_elements_worker, slim_output):
|
|
889
|
-
elt = Element(
|
|
890
|
-
{
|
|
891
|
-
"id": "12341234-1234-1234-1234-123412341234",
|
|
892
|
-
"corpus": {"id": CORPUS_ID},
|
|
893
|
-
"zone": {"image": {"id": "22222222-2222-2222-2222-222222222222"}},
|
|
894
|
-
}
|
|
895
|
-
)
|
|
896
|
-
child_elt = {
|
|
897
|
-
"id": "12345678-1234-1234-1234-123456789123",
|
|
898
|
-
"corpus": {"id": CORPUS_ID},
|
|
899
|
-
"zone": {"image": {"id": "22222222-2222-2222-2222-222222222222"}},
|
|
900
|
-
}
|
|
901
|
-
responses.add(
|
|
902
|
-
responses.POST,
|
|
903
|
-
"http://testserver/api/v1/elements/create/",
|
|
904
|
-
status=200,
|
|
905
|
-
json=child_elt,
|
|
906
|
-
)
|
|
907
|
-
|
|
908
|
-
element_creation_response = mock_elements_worker.create_sub_element(
|
|
909
|
-
element=elt,
|
|
910
|
-
type="something",
|
|
911
|
-
name="0",
|
|
912
|
-
polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
913
|
-
slim_output=slim_output,
|
|
914
|
-
)
|
|
915
|
-
|
|
916
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 1
|
|
917
|
-
assert [
|
|
918
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
919
|
-
] == BASE_API_CALLS + [
|
|
920
|
-
(
|
|
921
|
-
"POST",
|
|
922
|
-
"http://testserver/api/v1/elements/create/",
|
|
923
|
-
),
|
|
924
|
-
]
|
|
925
|
-
assert json.loads(responses.calls[-1].request.body) == {
|
|
926
|
-
"type": "something",
|
|
927
|
-
"name": "0",
|
|
928
|
-
"image": None,
|
|
929
|
-
"corpus": CORPUS_ID,
|
|
930
|
-
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
931
|
-
"parent": "12341234-1234-1234-1234-123412341234",
|
|
932
|
-
"worker_run_id": "56785678-5678-5678-5678-567856785678",
|
|
933
|
-
"confidence": None,
|
|
934
|
-
}
|
|
935
|
-
if slim_output:
|
|
936
|
-
assert element_creation_response == "12345678-1234-1234-1234-123456789123"
|
|
937
|
-
else:
|
|
938
|
-
assert Element(element_creation_response) == Element(child_elt)
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
def test_create_sub_element_confidence(responses, mock_elements_worker):
|
|
942
|
-
elt = Element(
|
|
943
|
-
{
|
|
944
|
-
"id": "12341234-1234-1234-1234-123412341234",
|
|
945
|
-
"corpus": {"id": CORPUS_ID},
|
|
946
|
-
"zone": {"image": {"id": "22222222-2222-2222-2222-222222222222"}},
|
|
947
|
-
}
|
|
948
|
-
)
|
|
949
|
-
responses.add(
|
|
950
|
-
responses.POST,
|
|
951
|
-
"http://testserver/api/v1/elements/create/",
|
|
952
|
-
status=200,
|
|
953
|
-
json={"id": "12345678-1234-1234-1234-123456789123"},
|
|
954
|
-
)
|
|
955
|
-
|
|
956
|
-
sub_element_id = mock_elements_worker.create_sub_element(
|
|
957
|
-
element=elt,
|
|
958
|
-
type="something",
|
|
959
|
-
name="0",
|
|
960
|
-
polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
961
|
-
confidence=0.42,
|
|
962
|
-
)
|
|
963
|
-
|
|
964
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 1
|
|
965
|
-
assert [
|
|
966
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
967
|
-
] == BASE_API_CALLS + [
|
|
968
|
-
("POST", "http://testserver/api/v1/elements/create/"),
|
|
969
|
-
]
|
|
970
|
-
assert json.loads(responses.calls[-1].request.body) == {
|
|
971
|
-
"type": "something",
|
|
972
|
-
"name": "0",
|
|
973
|
-
"image": None,
|
|
974
|
-
"corpus": CORPUS_ID,
|
|
975
|
-
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
976
|
-
"parent": "12341234-1234-1234-1234-123412341234",
|
|
977
|
-
"worker_run_id": "56785678-5678-5678-5678-567856785678",
|
|
978
|
-
"confidence": 0.42,
|
|
979
|
-
}
|
|
980
|
-
assert sub_element_id == "12345678-1234-1234-1234-123456789123"
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
def test_create_elements_wrong_parent(mock_elements_worker):
|
|
984
|
-
with pytest.raises(
|
|
985
|
-
TypeError, match="Parent element should be an Element or CachedElement instance"
|
|
986
|
-
):
|
|
987
|
-
mock_elements_worker.create_elements(
|
|
988
|
-
parent=None,
|
|
989
|
-
elements=[],
|
|
990
|
-
)
|
|
991
|
-
|
|
992
|
-
with pytest.raises(
|
|
993
|
-
TypeError, match="Parent element should be an Element or CachedElement instance"
|
|
994
|
-
):
|
|
995
|
-
mock_elements_worker.create_elements(
|
|
996
|
-
parent="not element type",
|
|
997
|
-
elements=[],
|
|
998
|
-
)
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
def test_create_elements_no_zone(mock_elements_worker):
|
|
1002
|
-
elt = Element({"zone": None})
|
|
1003
|
-
with pytest.raises(
|
|
1004
|
-
AssertionError, match="create_elements cannot be used on parents without zones"
|
|
1005
|
-
):
|
|
1006
|
-
mock_elements_worker.create_elements(
|
|
1007
|
-
parent=elt,
|
|
1008
|
-
elements=None,
|
|
1009
|
-
)
|
|
1010
|
-
|
|
1011
|
-
elt = CachedElement(
|
|
1012
|
-
id="11111111-1111-1111-1111-1111111111", name="blah", type="blah"
|
|
1013
|
-
)
|
|
1014
|
-
with pytest.raises(
|
|
1015
|
-
AssertionError, match="create_elements cannot be used on parents without images"
|
|
1016
|
-
):
|
|
1017
|
-
mock_elements_worker.create_elements(
|
|
1018
|
-
parent=elt,
|
|
1019
|
-
elements=None,
|
|
1020
|
-
)
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
def test_create_elements_wrong_elements(mock_elements_worker):
|
|
1024
|
-
elt = Element({"zone": {"image": {"id": "image_id"}}})
|
|
1025
|
-
|
|
1026
|
-
with pytest.raises(
|
|
1027
|
-
AssertionError, match="elements shouldn't be null and should be of type list"
|
|
1028
|
-
):
|
|
1029
|
-
mock_elements_worker.create_elements(
|
|
1030
|
-
parent=elt,
|
|
1031
|
-
elements=None,
|
|
1032
|
-
)
|
|
1033
|
-
|
|
1034
|
-
with pytest.raises(
|
|
1035
|
-
AssertionError, match="elements shouldn't be null and should be of type list"
|
|
1036
|
-
):
|
|
1037
|
-
mock_elements_worker.create_elements(
|
|
1038
|
-
parent=elt,
|
|
1039
|
-
elements="not a list",
|
|
1040
|
-
)
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
def test_create_elements_wrong_elements_instance(mock_elements_worker):
|
|
1044
|
-
elt = Element({"zone": {"image": {"id": "image_id"}}})
|
|
1045
|
-
|
|
1046
|
-
with pytest.raises(
|
|
1047
|
-
AssertionError, match="Element at index 0 in elements: Should be of type dict"
|
|
1048
|
-
):
|
|
1049
|
-
mock_elements_worker.create_elements(
|
|
1050
|
-
parent=elt,
|
|
1051
|
-
elements=["not a dict"],
|
|
1052
|
-
)
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
def test_create_elements_wrong_elements_name(mock_elements_worker):
|
|
1056
|
-
elt = Element({"zone": {"image": {"id": "image_id"}}})
|
|
1057
|
-
|
|
1058
|
-
with pytest.raises(
|
|
1059
|
-
AssertionError,
|
|
1060
|
-
match="Element at index 0 in elements: name shouldn't be null and should be of type str",
|
|
1061
|
-
):
|
|
1062
|
-
mock_elements_worker.create_elements(
|
|
1063
|
-
parent=elt,
|
|
1064
|
-
elements=[
|
|
1065
|
-
{
|
|
1066
|
-
"name": None,
|
|
1067
|
-
"type": "something",
|
|
1068
|
-
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
1069
|
-
}
|
|
1070
|
-
],
|
|
1071
|
-
)
|
|
1072
|
-
|
|
1073
|
-
with pytest.raises(
|
|
1074
|
-
AssertionError,
|
|
1075
|
-
match="Element at index 0 in elements: name shouldn't be null and should be of type str",
|
|
1076
|
-
):
|
|
1077
|
-
mock_elements_worker.create_elements(
|
|
1078
|
-
parent=elt,
|
|
1079
|
-
elements=[
|
|
1080
|
-
{
|
|
1081
|
-
"name": 1234,
|
|
1082
|
-
"type": "something",
|
|
1083
|
-
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
1084
|
-
}
|
|
1085
|
-
],
|
|
1086
|
-
)
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
def test_create_elements_wrong_elements_type(mock_elements_worker):
|
|
1090
|
-
elt = Element({"zone": {"image": {"id": "image_id"}}})
|
|
1091
|
-
|
|
1092
|
-
with pytest.raises(
|
|
1093
|
-
AssertionError,
|
|
1094
|
-
match="Element at index 0 in elements: type shouldn't be null and should be of type str",
|
|
1095
|
-
):
|
|
1096
|
-
mock_elements_worker.create_elements(
|
|
1097
|
-
parent=elt,
|
|
1098
|
-
elements=[
|
|
1099
|
-
{
|
|
1100
|
-
"name": "0",
|
|
1101
|
-
"type": None,
|
|
1102
|
-
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
1103
|
-
}
|
|
1104
|
-
],
|
|
1105
|
-
)
|
|
1106
|
-
|
|
1107
|
-
with pytest.raises(
|
|
1108
|
-
AssertionError,
|
|
1109
|
-
match="Element at index 0 in elements: type shouldn't be null and should be of type str",
|
|
1110
|
-
):
|
|
1111
|
-
mock_elements_worker.create_elements(
|
|
1112
|
-
parent=elt,
|
|
1113
|
-
elements=[
|
|
1114
|
-
{
|
|
1115
|
-
"name": "0",
|
|
1116
|
-
"type": 1234,
|
|
1117
|
-
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
1118
|
-
}
|
|
1119
|
-
],
|
|
1120
|
-
)
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
def test_create_elements_wrong_elements_polygon(mock_elements_worker):
|
|
1124
|
-
elt = Element({"zone": {"image": {"id": "image_id"}}})
|
|
1125
|
-
|
|
1126
|
-
with pytest.raises(
|
|
1127
|
-
AssertionError,
|
|
1128
|
-
match="Element at index 0 in elements: polygon shouldn't be null and should be of type list",
|
|
1129
|
-
):
|
|
1130
|
-
mock_elements_worker.create_elements(
|
|
1131
|
-
parent=elt,
|
|
1132
|
-
elements=[
|
|
1133
|
-
{
|
|
1134
|
-
"name": "0",
|
|
1135
|
-
"type": "something",
|
|
1136
|
-
"polygon": None,
|
|
1137
|
-
}
|
|
1138
|
-
],
|
|
1139
|
-
)
|
|
1140
|
-
|
|
1141
|
-
with pytest.raises(
|
|
1142
|
-
AssertionError,
|
|
1143
|
-
match="Element at index 0 in elements: polygon shouldn't be null and should be of type list",
|
|
1144
|
-
):
|
|
1145
|
-
mock_elements_worker.create_elements(
|
|
1146
|
-
parent=elt,
|
|
1147
|
-
elements=[
|
|
1148
|
-
{
|
|
1149
|
-
"name": "0",
|
|
1150
|
-
"type": "something",
|
|
1151
|
-
"polygon": "not a polygon",
|
|
1152
|
-
}
|
|
1153
|
-
],
|
|
1154
|
-
)
|
|
1155
|
-
|
|
1156
|
-
with pytest.raises(
|
|
1157
|
-
AssertionError,
|
|
1158
|
-
match="Element at index 0 in elements: polygon should have at least three points",
|
|
1159
|
-
):
|
|
1160
|
-
mock_elements_worker.create_elements(
|
|
1161
|
-
parent=elt,
|
|
1162
|
-
elements=[
|
|
1163
|
-
{
|
|
1164
|
-
"name": "0",
|
|
1165
|
-
"type": "something",
|
|
1166
|
-
"polygon": [[1, 1], [2, 2]],
|
|
1167
|
-
}
|
|
1168
|
-
],
|
|
1169
|
-
)
|
|
1170
|
-
|
|
1171
|
-
with pytest.raises(
|
|
1172
|
-
AssertionError,
|
|
1173
|
-
match="Element at index 0 in elements: polygon points should be lists of two items",
|
|
1174
|
-
):
|
|
1175
|
-
mock_elements_worker.create_elements(
|
|
1176
|
-
parent=elt,
|
|
1177
|
-
elements=[
|
|
1178
|
-
{
|
|
1179
|
-
"name": "0",
|
|
1180
|
-
"type": "something",
|
|
1181
|
-
"polygon": [[1, 1, 1], [2, 2, 1], [2, 1, 1], [1, 2, 1]],
|
|
1182
|
-
}
|
|
1183
|
-
],
|
|
1184
|
-
)
|
|
1185
|
-
|
|
1186
|
-
with pytest.raises(
|
|
1187
|
-
AssertionError,
|
|
1188
|
-
match="Element at index 0 in elements: polygon points should be lists of two items",
|
|
1189
|
-
):
|
|
1190
|
-
mock_elements_worker.create_elements(
|
|
1191
|
-
parent=elt,
|
|
1192
|
-
elements=[
|
|
1193
|
-
{
|
|
1194
|
-
"name": "0",
|
|
1195
|
-
"type": "something",
|
|
1196
|
-
"polygon": [[1], [2], [2], [1]],
|
|
1197
|
-
}
|
|
1198
|
-
],
|
|
1199
|
-
)
|
|
1200
|
-
|
|
1201
|
-
with pytest.raises(
|
|
1202
|
-
AssertionError,
|
|
1203
|
-
match="Element at index 0 in elements: polygon points should be lists of two numbers",
|
|
1204
|
-
):
|
|
1205
|
-
mock_elements_worker.create_elements(
|
|
1206
|
-
parent=elt,
|
|
1207
|
-
elements=[
|
|
1208
|
-
{
|
|
1209
|
-
"name": "0",
|
|
1210
|
-
"type": "something",
|
|
1211
|
-
"polygon": [["not a coord", 1], [2, 2], [2, 1], [1, 2]],
|
|
1212
|
-
}
|
|
1213
|
-
],
|
|
1214
|
-
)
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
@pytest.mark.parametrize("confidence", ["lol", "0.2", -1.0, 1.42, float("inf")])
|
|
1218
|
-
def test_create_elements_wrong_elements_confidence(mock_elements_worker, confidence):
|
|
1219
|
-
with pytest.raises(
|
|
1220
|
-
AssertionError,
|
|
1221
|
-
match=re.escape(
|
|
1222
|
-
"Element at index 0 in elements: confidence should be None or a float in [0..1] range"
|
|
1223
|
-
),
|
|
1224
|
-
):
|
|
1225
|
-
mock_elements_worker.create_elements(
|
|
1226
|
-
parent=Element({"zone": {"image": {"id": "image_id"}}}),
|
|
1227
|
-
elements=[
|
|
1228
|
-
{
|
|
1229
|
-
"name": "a",
|
|
1230
|
-
"type": "something",
|
|
1231
|
-
"polygon": [[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]],
|
|
1232
|
-
"confidence": confidence,
|
|
1233
|
-
}
|
|
1234
|
-
],
|
|
1235
|
-
)
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
def test_create_elements_api_error(responses, mock_elements_worker):
|
|
1239
|
-
elt = Element(
|
|
1240
|
-
{
|
|
1241
|
-
"id": "12341234-1234-1234-1234-123412341234",
|
|
1242
|
-
"zone": {
|
|
1243
|
-
"image": {
|
|
1244
|
-
"id": "c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
|
|
1245
|
-
"width": 42,
|
|
1246
|
-
"height": 42,
|
|
1247
|
-
"url": "http://aaaa",
|
|
1248
|
-
}
|
|
1249
|
-
},
|
|
1250
|
-
}
|
|
1251
|
-
)
|
|
1252
|
-
responses.add(
|
|
1253
|
-
responses.POST,
|
|
1254
|
-
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
1255
|
-
status=418,
|
|
1256
|
-
)
|
|
1257
|
-
|
|
1258
|
-
with pytest.raises(ErrorResponse):
|
|
1259
|
-
mock_elements_worker.create_elements(
|
|
1260
|
-
parent=elt,
|
|
1261
|
-
elements=[
|
|
1262
|
-
{
|
|
1263
|
-
"name": "0",
|
|
1264
|
-
"type": "something",
|
|
1265
|
-
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
1266
|
-
}
|
|
1267
|
-
],
|
|
1268
|
-
)
|
|
1269
|
-
|
|
1270
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 1
|
|
1271
|
-
assert [
|
|
1272
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
1273
|
-
] == BASE_API_CALLS + [
|
|
1274
|
-
(
|
|
1275
|
-
"POST",
|
|
1276
|
-
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
1277
|
-
)
|
|
1278
|
-
]
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
@pytest.mark.parametrize("batch_size", [DEFAULT_BATCH_SIZE, 1])
|
|
1282
|
-
def test_create_elements_cached_element(
|
|
1283
|
-
batch_size, responses, mock_elements_worker_with_cache
|
|
1284
|
-
):
|
|
1285
|
-
image = CachedImage.create(
|
|
1286
|
-
id=UUID("c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe"),
|
|
1287
|
-
width=42,
|
|
1288
|
-
height=42,
|
|
1289
|
-
url="http://aaaa",
|
|
1290
|
-
)
|
|
1291
|
-
elt = CachedElement.create(
|
|
1292
|
-
id=UUID("12341234-1234-1234-1234-123412341234"),
|
|
1293
|
-
type="parent",
|
|
1294
|
-
image_id=image.id,
|
|
1295
|
-
polygon="[[0, 0], [0, 1000], [1000, 1000], [1000, 0], [0, 0]]",
|
|
1296
|
-
)
|
|
1297
|
-
|
|
1298
|
-
if batch_size > 1:
|
|
1299
|
-
responses.add(
|
|
1300
|
-
responses.POST,
|
|
1301
|
-
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
1302
|
-
status=200,
|
|
1303
|
-
json=[
|
|
1304
|
-
{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"},
|
|
1305
|
-
{"id": "5468c358-b9c4-499d-8b92-d6349c58e88d"},
|
|
1306
|
-
],
|
|
1307
|
-
)
|
|
1308
|
-
else:
|
|
1309
|
-
for elt_id in [
|
|
1310
|
-
"497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
|
1311
|
-
"5468c358-b9c4-499d-8b92-d6349c58e88d",
|
|
1312
|
-
]:
|
|
1313
|
-
responses.add(
|
|
1314
|
-
responses.POST,
|
|
1315
|
-
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
1316
|
-
status=200,
|
|
1317
|
-
json=[{"id": elt_id}],
|
|
1318
|
-
)
|
|
1319
|
-
|
|
1320
|
-
created_ids = mock_elements_worker_with_cache.create_elements(
|
|
1321
|
-
parent=elt,
|
|
1322
|
-
elements=[
|
|
1323
|
-
{
|
|
1324
|
-
"name": "0",
|
|
1325
|
-
"type": "something",
|
|
1326
|
-
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
1327
|
-
},
|
|
1328
|
-
{
|
|
1329
|
-
"name": "1",
|
|
1330
|
-
"type": "something",
|
|
1331
|
-
"polygon": [[4, 4], [5, 5], [5, 4], [4, 5]],
|
|
1332
|
-
},
|
|
1333
|
-
],
|
|
1334
|
-
batch_size=batch_size,
|
|
1335
|
-
)
|
|
1336
|
-
|
|
1337
|
-
bulk_api_calls = [
|
|
1338
|
-
(
|
|
1339
|
-
"POST",
|
|
1340
|
-
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
1341
|
-
)
|
|
1342
|
-
]
|
|
1343
|
-
if batch_size != DEFAULT_BATCH_SIZE:
|
|
1344
|
-
bulk_api_calls.append(
|
|
1345
|
-
(
|
|
1346
|
-
"POST",
|
|
1347
|
-
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
1348
|
-
)
|
|
1349
|
-
)
|
|
1350
|
-
|
|
1351
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + len(bulk_api_calls)
|
|
1352
|
-
assert [
|
|
1353
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
1354
|
-
] == BASE_API_CALLS + bulk_api_calls
|
|
1355
|
-
|
|
1356
|
-
first_elt = {
|
|
1357
|
-
"name": "0",
|
|
1358
|
-
"type": "something",
|
|
1359
|
-
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
1360
|
-
}
|
|
1361
|
-
second_elt = {
|
|
1362
|
-
"name": "1",
|
|
1363
|
-
"type": "something",
|
|
1364
|
-
"polygon": [[4, 4], [5, 5], [5, 4], [4, 5]],
|
|
1365
|
-
}
|
|
1366
|
-
empty_payload = {
|
|
1367
|
-
"elements": [],
|
|
1368
|
-
"worker_run_id": "56785678-5678-5678-5678-567856785678",
|
|
1369
|
-
}
|
|
1370
|
-
|
|
1371
|
-
bodies = []
|
|
1372
|
-
first_call_idx = None
|
|
1373
|
-
if batch_size > 1:
|
|
1374
|
-
first_call_idx = -1
|
|
1375
|
-
bodies.append({**empty_payload, "elements": [first_elt, second_elt]})
|
|
1376
|
-
else:
|
|
1377
|
-
first_call_idx = -2
|
|
1378
|
-
bodies.append({**empty_payload, "elements": [first_elt]})
|
|
1379
|
-
bodies.append({**empty_payload, "elements": [second_elt]})
|
|
1380
|
-
|
|
1381
|
-
assert [
|
|
1382
|
-
json.loads(bulk_call.request.body)
|
|
1383
|
-
for bulk_call in responses.calls[first_call_idx:]
|
|
1384
|
-
] == bodies
|
|
1385
|
-
|
|
1386
|
-
assert created_ids == [
|
|
1387
|
-
{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"},
|
|
1388
|
-
{"id": "5468c358-b9c4-499d-8b92-d6349c58e88d"},
|
|
1389
|
-
]
|
|
1390
|
-
|
|
1391
|
-
# Check that created elements were properly stored in SQLite cache
|
|
1392
|
-
assert list(CachedElement.select().order_by(CachedElement.id)) == [
|
|
1393
|
-
elt,
|
|
1394
|
-
CachedElement(
|
|
1395
|
-
id=UUID("497f6eca-6276-4993-bfeb-53cbbbba6f08"),
|
|
1396
|
-
parent_id=elt.id,
|
|
1397
|
-
type="something",
|
|
1398
|
-
image_id="c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
|
|
1399
|
-
polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
1400
|
-
worker_run_id=UUID("56785678-5678-5678-5678-567856785678"),
|
|
1401
|
-
confidence=None,
|
|
1402
|
-
),
|
|
1403
|
-
CachedElement(
|
|
1404
|
-
id=UUID("5468c358-b9c4-499d-8b92-d6349c58e88d"),
|
|
1405
|
-
parent_id=elt.id,
|
|
1406
|
-
type="something",
|
|
1407
|
-
image_id="c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
|
|
1408
|
-
polygon=[[4, 4], [5, 5], [5, 4], [4, 5]],
|
|
1409
|
-
worker_run_id=UUID("56785678-5678-5678-5678-567856785678"),
|
|
1410
|
-
confidence=None,
|
|
1411
|
-
),
|
|
1412
|
-
]
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
@pytest.mark.parametrize("batch_size", [DEFAULT_BATCH_SIZE, 1])
|
|
1416
|
-
def test_create_elements(
|
|
1417
|
-
batch_size, responses, mock_elements_worker_with_cache, tmp_path
|
|
1418
|
-
):
|
|
1419
|
-
elt = Element(
|
|
1420
|
-
{
|
|
1421
|
-
"id": "12341234-1234-1234-1234-123412341234",
|
|
1422
|
-
"zone": {
|
|
1423
|
-
"image": {
|
|
1424
|
-
"id": "c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
|
|
1425
|
-
"width": 42,
|
|
1426
|
-
"height": 42,
|
|
1427
|
-
"url": "http://aaaa",
|
|
1428
|
-
}
|
|
1429
|
-
},
|
|
1430
|
-
}
|
|
1431
|
-
)
|
|
1432
|
-
|
|
1433
|
-
if batch_size > 1:
|
|
1434
|
-
responses.add(
|
|
1435
|
-
responses.POST,
|
|
1436
|
-
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
1437
|
-
status=200,
|
|
1438
|
-
json=[
|
|
1439
|
-
{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"},
|
|
1440
|
-
{"id": "5468c358-b9c4-499d-8b92-d6349c58e88d"},
|
|
1441
|
-
],
|
|
1442
|
-
)
|
|
1443
|
-
else:
|
|
1444
|
-
for elt_id in [
|
|
1445
|
-
"497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
|
1446
|
-
"5468c358-b9c4-499d-8b92-d6349c58e88d",
|
|
1447
|
-
]:
|
|
1448
|
-
responses.add(
|
|
1449
|
-
responses.POST,
|
|
1450
|
-
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
1451
|
-
status=200,
|
|
1452
|
-
json=[{"id": elt_id}],
|
|
1453
|
-
)
|
|
1454
|
-
|
|
1455
|
-
created_ids = mock_elements_worker_with_cache.create_elements(
|
|
1456
|
-
parent=elt,
|
|
1457
|
-
elements=[
|
|
1458
|
-
{
|
|
1459
|
-
"name": "0",
|
|
1460
|
-
"type": "something",
|
|
1461
|
-
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
1462
|
-
},
|
|
1463
|
-
{
|
|
1464
|
-
"name": "1",
|
|
1465
|
-
"type": "something",
|
|
1466
|
-
"polygon": [[4, 4], [5, 5], [5, 4], [4, 5]],
|
|
1467
|
-
},
|
|
1468
|
-
],
|
|
1469
|
-
batch_size=batch_size,
|
|
1470
|
-
)
|
|
1471
|
-
|
|
1472
|
-
bulk_api_calls = [
|
|
1473
|
-
(
|
|
1474
|
-
"POST",
|
|
1475
|
-
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
1476
|
-
)
|
|
1477
|
-
]
|
|
1478
|
-
if batch_size != DEFAULT_BATCH_SIZE:
|
|
1479
|
-
bulk_api_calls.append(
|
|
1480
|
-
(
|
|
1481
|
-
"POST",
|
|
1482
|
-
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
1483
|
-
)
|
|
1484
|
-
)
|
|
1485
|
-
|
|
1486
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + len(bulk_api_calls)
|
|
1487
|
-
assert [
|
|
1488
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
1489
|
-
] == BASE_API_CALLS + bulk_api_calls
|
|
1490
|
-
|
|
1491
|
-
first_elt = {
|
|
1492
|
-
"name": "0",
|
|
1493
|
-
"type": "something",
|
|
1494
|
-
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
1495
|
-
}
|
|
1496
|
-
second_elt = {
|
|
1497
|
-
"name": "1",
|
|
1498
|
-
"type": "something",
|
|
1499
|
-
"polygon": [[4, 4], [5, 5], [5, 4], [4, 5]],
|
|
1500
|
-
}
|
|
1501
|
-
empty_payload = {
|
|
1502
|
-
"elements": [],
|
|
1503
|
-
"worker_run_id": "56785678-5678-5678-5678-567856785678",
|
|
1504
|
-
}
|
|
1505
|
-
|
|
1506
|
-
bodies = []
|
|
1507
|
-
first_call_idx = None
|
|
1508
|
-
if batch_size > 1:
|
|
1509
|
-
first_call_idx = -1
|
|
1510
|
-
bodies.append({**empty_payload, "elements": [first_elt, second_elt]})
|
|
1511
|
-
else:
|
|
1512
|
-
first_call_idx = -2
|
|
1513
|
-
bodies.append({**empty_payload, "elements": [first_elt]})
|
|
1514
|
-
bodies.append({**empty_payload, "elements": [second_elt]})
|
|
1515
|
-
|
|
1516
|
-
assert [
|
|
1517
|
-
json.loads(bulk_call.request.body)
|
|
1518
|
-
for bulk_call in responses.calls[first_call_idx:]
|
|
1519
|
-
] == bodies
|
|
1520
|
-
|
|
1521
|
-
assert created_ids == [
|
|
1522
|
-
{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"},
|
|
1523
|
-
{"id": "5468c358-b9c4-499d-8b92-d6349c58e88d"},
|
|
1524
|
-
]
|
|
1525
|
-
|
|
1526
|
-
# Check that created elements were properly stored in SQLite cache
|
|
1527
|
-
assert (tmp_path / "db.sqlite").is_file()
|
|
1528
|
-
|
|
1529
|
-
assert list(CachedElement.select()) == [
|
|
1530
|
-
CachedElement(
|
|
1531
|
-
id=UUID("497f6eca-6276-4993-bfeb-53cbbbba6f08"),
|
|
1532
|
-
parent_id=UUID("12341234-1234-1234-1234-123412341234"),
|
|
1533
|
-
type="something",
|
|
1534
|
-
image_id="c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
|
|
1535
|
-
polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
1536
|
-
worker_run_id=UUID("56785678-5678-5678-5678-567856785678"),
|
|
1537
|
-
confidence=None,
|
|
1538
|
-
),
|
|
1539
|
-
CachedElement(
|
|
1540
|
-
id=UUID("5468c358-b9c4-499d-8b92-d6349c58e88d"),
|
|
1541
|
-
parent_id=UUID("12341234-1234-1234-1234-123412341234"),
|
|
1542
|
-
type="something",
|
|
1543
|
-
image_id="c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
|
|
1544
|
-
polygon=[[4, 4], [5, 5], [5, 4], [4, 5]],
|
|
1545
|
-
worker_run_id=UUID("56785678-5678-5678-5678-567856785678"),
|
|
1546
|
-
confidence=None,
|
|
1547
|
-
),
|
|
1548
|
-
]
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
def test_create_elements_confidence(
|
|
1552
|
-
responses, mock_elements_worker_with_cache, tmp_path
|
|
1553
|
-
):
|
|
1554
|
-
elt = Element(
|
|
1555
|
-
{
|
|
1556
|
-
"id": "12341234-1234-1234-1234-123412341234",
|
|
1557
|
-
"zone": {
|
|
1558
|
-
"image": {
|
|
1559
|
-
"id": "c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
|
|
1560
|
-
"width": 42,
|
|
1561
|
-
"height": 42,
|
|
1562
|
-
"url": "http://aaaa",
|
|
1563
|
-
}
|
|
1564
|
-
},
|
|
1565
|
-
}
|
|
1566
|
-
)
|
|
1567
|
-
responses.add(
|
|
1568
|
-
responses.POST,
|
|
1569
|
-
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
1570
|
-
status=200,
|
|
1571
|
-
json=[{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"}],
|
|
1572
|
-
)
|
|
1573
|
-
|
|
1574
|
-
created_ids = mock_elements_worker_with_cache.create_elements(
|
|
1575
|
-
parent=elt,
|
|
1576
|
-
elements=[
|
|
1577
|
-
{
|
|
1578
|
-
"name": "0",
|
|
1579
|
-
"type": "something",
|
|
1580
|
-
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
1581
|
-
"confidence": 0.42,
|
|
1582
|
-
}
|
|
1583
|
-
],
|
|
1584
|
-
)
|
|
1585
|
-
|
|
1586
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 1
|
|
1587
|
-
assert [
|
|
1588
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
1589
|
-
] == BASE_API_CALLS + [
|
|
1590
|
-
(
|
|
1591
|
-
"POST",
|
|
1592
|
-
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
1593
|
-
),
|
|
1594
|
-
]
|
|
1595
|
-
assert json.loads(responses.calls[-1].request.body) == {
|
|
1596
|
-
"elements": [
|
|
1597
|
-
{
|
|
1598
|
-
"name": "0",
|
|
1599
|
-
"type": "something",
|
|
1600
|
-
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
1601
|
-
"confidence": 0.42,
|
|
1602
|
-
}
|
|
1603
|
-
],
|
|
1604
|
-
"worker_run_id": "56785678-5678-5678-5678-567856785678",
|
|
1605
|
-
}
|
|
1606
|
-
assert created_ids == [{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"}]
|
|
1607
|
-
|
|
1608
|
-
# Check that created elements were properly stored in SQLite cache
|
|
1609
|
-
assert (tmp_path / "db.sqlite").is_file()
|
|
1610
|
-
|
|
1611
|
-
assert list(CachedElement.select()) == [
|
|
1612
|
-
CachedElement(
|
|
1613
|
-
id=UUID("497f6eca-6276-4993-bfeb-53cbbbba6f08"),
|
|
1614
|
-
parent_id=UUID("12341234-1234-1234-1234-123412341234"),
|
|
1615
|
-
type="something",
|
|
1616
|
-
image_id="c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
|
|
1617
|
-
polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
1618
|
-
worker_run_id=UUID("56785678-5678-5678-5678-567856785678"),
|
|
1619
|
-
confidence=0.42,
|
|
1620
|
-
)
|
|
1621
|
-
]
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
def test_create_elements_integrity_error(
|
|
1625
|
-
responses, mock_elements_worker_with_cache, caplog
|
|
1626
|
-
):
|
|
1627
|
-
elt = Element(
|
|
1628
|
-
{
|
|
1629
|
-
"id": "12341234-1234-1234-1234-123412341234",
|
|
1630
|
-
"zone": {
|
|
1631
|
-
"image": {
|
|
1632
|
-
"id": "c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
|
|
1633
|
-
"width": 42,
|
|
1634
|
-
"height": 42,
|
|
1635
|
-
"url": "http://aaaa",
|
|
1636
|
-
}
|
|
1637
|
-
},
|
|
1638
|
-
}
|
|
1639
|
-
)
|
|
1640
|
-
responses.add(
|
|
1641
|
-
responses.POST,
|
|
1642
|
-
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
1643
|
-
status=200,
|
|
1644
|
-
json=[
|
|
1645
|
-
# Duplicate IDs, which will cause an IntegrityError when stored in the cache
|
|
1646
|
-
{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"},
|
|
1647
|
-
{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"},
|
|
1648
|
-
],
|
|
1649
|
-
)
|
|
1650
|
-
|
|
1651
|
-
elements = [
|
|
1652
|
-
{
|
|
1653
|
-
"name": "0",
|
|
1654
|
-
"type": "something",
|
|
1655
|
-
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
1656
|
-
},
|
|
1657
|
-
{
|
|
1658
|
-
"name": "1",
|
|
1659
|
-
"type": "something",
|
|
1660
|
-
"polygon": [[1, 1], [3, 3], [3, 1], [1, 3]],
|
|
1661
|
-
},
|
|
1662
|
-
]
|
|
1663
|
-
|
|
1664
|
-
created_ids = mock_elements_worker_with_cache.create_elements(
|
|
1665
|
-
parent=elt,
|
|
1666
|
-
elements=elements,
|
|
1667
|
-
)
|
|
1668
|
-
|
|
1669
|
-
assert created_ids == [
|
|
1670
|
-
{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"},
|
|
1671
|
-
{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"},
|
|
1672
|
-
]
|
|
1673
|
-
|
|
1674
|
-
assert len(caplog.records) == 3
|
|
1675
|
-
assert caplog.records[-1].levelname == "WARNING"
|
|
1676
|
-
assert caplog.records[-1].message.startswith(
|
|
1677
|
-
"Couldn't save created elements in local cache:"
|
|
1678
|
-
)
|
|
1679
|
-
|
|
1680
|
-
assert list(CachedElement.select()) == []
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
@pytest.mark.parametrize(
|
|
1684
|
-
("params", "error_message"),
|
|
1685
|
-
[
|
|
1686
|
-
(
|
|
1687
|
-
{"parent": None, "child": None},
|
|
1688
|
-
"parent shouldn't be null and should be of type Element",
|
|
1689
|
-
),
|
|
1690
|
-
(
|
|
1691
|
-
{"parent": "not an element", "child": None},
|
|
1692
|
-
"parent shouldn't be null and should be of type Element",
|
|
1693
|
-
),
|
|
1694
|
-
(
|
|
1695
|
-
{"parent": Element(zone=None), "child": None},
|
|
1696
|
-
"child shouldn't be null and should be of type Element",
|
|
1697
|
-
),
|
|
1698
|
-
(
|
|
1699
|
-
{"parent": Element(zone=None), "child": "not an element"},
|
|
1700
|
-
"child shouldn't be null and should be of type Element",
|
|
1701
|
-
),
|
|
1702
|
-
],
|
|
1703
|
-
)
|
|
1704
|
-
def test_create_element_parent_invalid_params(
|
|
1705
|
-
mock_elements_worker, params, error_message
|
|
1706
|
-
):
|
|
1707
|
-
with pytest.raises(AssertionError, match=re.escape(error_message)):
|
|
1708
|
-
mock_elements_worker.create_element_parent(**params)
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
def test_create_element_parent_api_error(responses, mock_elements_worker):
|
|
1712
|
-
parent = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
1713
|
-
child = Element({"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"})
|
|
1714
|
-
responses.add(
|
|
1715
|
-
responses.POST,
|
|
1716
|
-
"http://testserver/api/v1/element/497f6eca-6276-4993-bfeb-53cbbbba6f08/parent/12341234-1234-1234-1234-123412341234/",
|
|
1717
|
-
status=418,
|
|
1718
|
-
)
|
|
1719
|
-
|
|
1720
|
-
with pytest.raises(ErrorResponse):
|
|
1721
|
-
mock_elements_worker.create_element_parent(
|
|
1722
|
-
parent=parent,
|
|
1723
|
-
child=child,
|
|
1724
|
-
)
|
|
1725
|
-
|
|
1726
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 1
|
|
1727
|
-
assert [
|
|
1728
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
1729
|
-
] == BASE_API_CALLS + [
|
|
1730
|
-
(
|
|
1731
|
-
"POST",
|
|
1732
|
-
"http://testserver/api/v1/element/497f6eca-6276-4993-bfeb-53cbbbba6f08/parent/12341234-1234-1234-1234-123412341234/",
|
|
1733
|
-
)
|
|
1734
|
-
]
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
def test_create_element_parent(responses, mock_elements_worker):
|
|
1738
|
-
parent = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
1739
|
-
child = Element({"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"})
|
|
1740
|
-
responses.add(
|
|
1741
|
-
responses.POST,
|
|
1742
|
-
"http://testserver/api/v1/element/497f6eca-6276-4993-bfeb-53cbbbba6f08/parent/12341234-1234-1234-1234-123412341234/",
|
|
1743
|
-
status=200,
|
|
1744
|
-
json={
|
|
1745
|
-
"parent": "12341234-1234-1234-1234-123412341234",
|
|
1746
|
-
"child": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
|
1747
|
-
},
|
|
1748
|
-
)
|
|
1749
|
-
|
|
1750
|
-
created_element_parent = mock_elements_worker.create_element_parent(
|
|
1751
|
-
parent=parent,
|
|
1752
|
-
child=child,
|
|
1753
|
-
)
|
|
1754
|
-
|
|
1755
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 1
|
|
1756
|
-
assert [
|
|
1757
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
1758
|
-
] == BASE_API_CALLS + [
|
|
1759
|
-
(
|
|
1760
|
-
"POST",
|
|
1761
|
-
"http://testserver/api/v1/element/497f6eca-6276-4993-bfeb-53cbbbba6f08/parent/12341234-1234-1234-1234-123412341234/",
|
|
1762
|
-
),
|
|
1763
|
-
]
|
|
1764
|
-
assert created_element_parent == {
|
|
1765
|
-
"parent": "12341234-1234-1234-1234-123412341234",
|
|
1766
|
-
"child": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
|
1767
|
-
}
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
@pytest.mark.parametrize(
|
|
1771
|
-
("arg_name", "data", "error_message"),
|
|
1772
|
-
[
|
|
1773
|
-
(
|
|
1774
|
-
"parent",
|
|
1775
|
-
None,
|
|
1776
|
-
"parent shouldn't be null and should be of type Element",
|
|
1777
|
-
),
|
|
1778
|
-
(
|
|
1779
|
-
"parent",
|
|
1780
|
-
"not element type",
|
|
1781
|
-
"parent shouldn't be null and should be of type Element",
|
|
1782
|
-
),
|
|
1783
|
-
(
|
|
1784
|
-
"children",
|
|
1785
|
-
None,
|
|
1786
|
-
"children shouldn't be null and should be of type list",
|
|
1787
|
-
),
|
|
1788
|
-
(
|
|
1789
|
-
"children",
|
|
1790
|
-
"not a list",
|
|
1791
|
-
"children shouldn't be null and should be of type list",
|
|
1792
|
-
),
|
|
1793
|
-
(
|
|
1794
|
-
"children",
|
|
1795
|
-
[
|
|
1796
|
-
Element({"id": "11111111-1111-1111-1111-111111111111"}),
|
|
1797
|
-
"not element type",
|
|
1798
|
-
],
|
|
1799
|
-
"Child at index 1 in children: Should be of type Element",
|
|
1800
|
-
),
|
|
1801
|
-
],
|
|
1802
|
-
)
|
|
1803
|
-
def test_create_element_children_wrong_params(
|
|
1804
|
-
arg_name, data, error_message, mock_elements_worker
|
|
1805
|
-
):
|
|
1806
|
-
with pytest.raises(AssertionError, match=error_message):
|
|
1807
|
-
mock_elements_worker.create_element_children(
|
|
1808
|
-
**{
|
|
1809
|
-
"parent": Element({"id": "12341234-1234-1234-1234-123412341234"}),
|
|
1810
|
-
"children": [
|
|
1811
|
-
Element({"id": "11111111-1111-1111-1111-111111111111"}),
|
|
1812
|
-
Element({"id": "22222222-2222-2222-2222-222222222222"}),
|
|
1813
|
-
],
|
|
1814
|
-
# Overwrite with wrong data
|
|
1815
|
-
arg_name: data,
|
|
1816
|
-
},
|
|
1817
|
-
)
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
def test_create_element_children_api_error(responses, mock_elements_worker):
|
|
1821
|
-
parent = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
1822
|
-
responses.add(
|
|
1823
|
-
responses.POST,
|
|
1824
|
-
f"http://testserver/api/v1/element/parent/{parent.id}/",
|
|
1825
|
-
status=418,
|
|
1826
|
-
)
|
|
1827
|
-
|
|
1828
|
-
with pytest.raises(ErrorResponse):
|
|
1829
|
-
mock_elements_worker.create_element_children(
|
|
1830
|
-
parent=parent,
|
|
1831
|
-
children=[
|
|
1832
|
-
Element({"id": "11111111-1111-1111-1111-111111111111"}),
|
|
1833
|
-
Element({"id": "22222222-2222-2222-2222-222222222222"}),
|
|
1834
|
-
],
|
|
1835
|
-
)
|
|
1836
|
-
|
|
1837
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 1
|
|
1838
|
-
assert [
|
|
1839
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
1840
|
-
] == BASE_API_CALLS + [
|
|
1841
|
-
(
|
|
1842
|
-
"POST",
|
|
1843
|
-
f"http://testserver/api/v1/element/parent/{parent.id}/",
|
|
1844
|
-
)
|
|
1845
|
-
]
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
@pytest.mark.parametrize("batch_size", [DEFAULT_BATCH_SIZE, 1])
|
|
1849
|
-
def test_create_element_children(batch_size, responses, mock_elements_worker):
|
|
1850
|
-
parent = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
1851
|
-
|
|
1852
|
-
first_child = Element({"id": "11111111-1111-1111-1111-111111111111"})
|
|
1853
|
-
second_child = Element({"id": "22222222-2222-2222-2222-222222222222"})
|
|
1854
|
-
|
|
1855
|
-
responses.add(
|
|
1856
|
-
responses.POST,
|
|
1857
|
-
f"http://testserver/api/v1/element/parent/{parent.id}/",
|
|
1858
|
-
status=200,
|
|
1859
|
-
json={"children": []},
|
|
1860
|
-
)
|
|
1861
|
-
|
|
1862
|
-
mock_elements_worker.create_element_children(
|
|
1863
|
-
parent=parent,
|
|
1864
|
-
children=[first_child, second_child],
|
|
1865
|
-
batch_size=batch_size,
|
|
1866
|
-
)
|
|
1867
|
-
|
|
1868
|
-
bulk_api_calls = [
|
|
1869
|
-
(
|
|
1870
|
-
"POST",
|
|
1871
|
-
f"http://testserver/api/v1/element/parent/{parent.id}/",
|
|
1872
|
-
)
|
|
1873
|
-
]
|
|
1874
|
-
if batch_size != DEFAULT_BATCH_SIZE:
|
|
1875
|
-
bulk_api_calls.append(
|
|
1876
|
-
(
|
|
1877
|
-
"POST",
|
|
1878
|
-
f"http://testserver/api/v1/element/parent/{parent.id}/",
|
|
1879
|
-
)
|
|
1880
|
-
)
|
|
1881
|
-
|
|
1882
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + len(bulk_api_calls)
|
|
1883
|
-
assert [
|
|
1884
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
1885
|
-
] == BASE_API_CALLS + bulk_api_calls
|
|
1886
|
-
|
|
1887
|
-
bodies = []
|
|
1888
|
-
first_call_idx = None
|
|
1889
|
-
if batch_size > 1:
|
|
1890
|
-
first_call_idx = -1
|
|
1891
|
-
bodies.append({"children": [first_child.id, second_child.id]})
|
|
1892
|
-
else:
|
|
1893
|
-
first_call_idx = -2
|
|
1894
|
-
bodies.append({"children": [first_child.id]})
|
|
1895
|
-
bodies.append({"children": [second_child.id]})
|
|
1896
|
-
|
|
1897
|
-
assert [
|
|
1898
|
-
json.loads(bulk_call.request.body)
|
|
1899
|
-
for bulk_call in responses.calls[first_call_idx:]
|
|
1900
|
-
] == bodies
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
@pytest.mark.parametrize(
|
|
1904
|
-
("payload", "error"),
|
|
1905
|
-
[
|
|
1906
|
-
# Element
|
|
1907
|
-
(
|
|
1908
|
-
{"element": None},
|
|
1909
|
-
"element shouldn't be null and should be an Element or CachedElement",
|
|
1910
|
-
),
|
|
1911
|
-
(
|
|
1912
|
-
{"element": "not element type"},
|
|
1913
|
-
"element shouldn't be null and should be an Element or CachedElement",
|
|
1914
|
-
),
|
|
1915
|
-
],
|
|
1916
|
-
)
|
|
1917
|
-
def test_partial_update_element_wrong_param_element(
|
|
1918
|
-
mock_elements_worker, payload, error
|
|
1919
|
-
):
|
|
1920
|
-
api_payload = {
|
|
1921
|
-
"element": Element({"zone": None}),
|
|
1922
|
-
**payload,
|
|
1923
|
-
}
|
|
1924
|
-
|
|
1925
|
-
with pytest.raises(AssertionError, match=error):
|
|
1926
|
-
mock_elements_worker.partial_update_element(
|
|
1927
|
-
**api_payload,
|
|
1928
|
-
)
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
@pytest.mark.parametrize(
|
|
1932
|
-
("payload", "error"),
|
|
1933
|
-
[
|
|
1934
|
-
# Type
|
|
1935
|
-
({"type": 1234}, "type should be a str"),
|
|
1936
|
-
({"type": None}, "type should be a str"),
|
|
1937
|
-
],
|
|
1938
|
-
)
|
|
1939
|
-
def test_partial_update_element_wrong_param_type(mock_elements_worker, payload, error):
|
|
1940
|
-
api_payload = {
|
|
1941
|
-
"element": Element({"zone": None}),
|
|
1942
|
-
**payload,
|
|
1943
|
-
}
|
|
1944
|
-
|
|
1945
|
-
with pytest.raises(AssertionError, match=error):
|
|
1946
|
-
mock_elements_worker.partial_update_element(
|
|
1947
|
-
**api_payload,
|
|
1948
|
-
)
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
@pytest.mark.parametrize(
|
|
1952
|
-
("payload", "error"),
|
|
1953
|
-
[
|
|
1954
|
-
# Name
|
|
1955
|
-
({"name": 1234}, "name should be a str"),
|
|
1956
|
-
({"name": None}, "name should be a str"),
|
|
1957
|
-
],
|
|
1958
|
-
)
|
|
1959
|
-
def test_partial_update_element_wrong_param_name(mock_elements_worker, payload, error):
|
|
1960
|
-
api_payload = {
|
|
1961
|
-
"element": Element({"zone": None}),
|
|
1962
|
-
**payload,
|
|
1963
|
-
}
|
|
1964
|
-
|
|
1965
|
-
with pytest.raises(AssertionError, match=error):
|
|
1966
|
-
mock_elements_worker.partial_update_element(
|
|
1967
|
-
**api_payload,
|
|
1968
|
-
)
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
@pytest.mark.parametrize(
|
|
1972
|
-
("payload", "error"),
|
|
1973
|
-
[
|
|
1974
|
-
# Polygon
|
|
1975
|
-
({"polygon": "not a polygon"}, "polygon should be a list"),
|
|
1976
|
-
({"polygon": None}, "polygon should be a list"),
|
|
1977
|
-
({"polygon": [[1, 1], [2, 2]]}, "polygon should have at least three points"),
|
|
1978
|
-
(
|
|
1979
|
-
{"polygon": [[1, 1, 1], [2, 2, 1], [2, 1, 1], [1, 2, 1]]},
|
|
1980
|
-
"polygon points should be lists of two items",
|
|
1981
|
-
),
|
|
1982
|
-
(
|
|
1983
|
-
{"polygon": [[1], [2], [2], [1]]},
|
|
1984
|
-
"polygon points should be lists of two items",
|
|
1985
|
-
),
|
|
1986
|
-
(
|
|
1987
|
-
{"polygon": [["not a coord", 1], [2, 2], [2, 1], [1, 2]]},
|
|
1988
|
-
"polygon points should be lists of two numbers",
|
|
1989
|
-
),
|
|
1990
|
-
],
|
|
1991
|
-
)
|
|
1992
|
-
def test_partial_update_element_wrong_param_polygon(
|
|
1993
|
-
mock_elements_worker, payload, error
|
|
1994
|
-
):
|
|
1995
|
-
api_payload = {
|
|
1996
|
-
"element": Element({"zone": None}),
|
|
1997
|
-
**payload,
|
|
1998
|
-
}
|
|
1999
|
-
|
|
2000
|
-
with pytest.raises(AssertionError, match=error):
|
|
2001
|
-
mock_elements_worker.partial_update_element(
|
|
2002
|
-
**api_payload,
|
|
2003
|
-
)
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
@pytest.mark.parametrize(
|
|
2007
|
-
("payload", "error"),
|
|
2008
|
-
[
|
|
2009
|
-
# Confidence
|
|
2010
|
-
({"confidence": "lol"}, "confidence should be None or a float in [0..1] range"),
|
|
2011
|
-
({"confidence": "0.2"}, "confidence should be None or a float in [0..1] range"),
|
|
2012
|
-
({"confidence": -1.0}, "confidence should be None or a float in [0..1] range"),
|
|
2013
|
-
({"confidence": 1.42}, "confidence should be None or a float in [0..1] range"),
|
|
2014
|
-
(
|
|
2015
|
-
{"confidence": float("inf")},
|
|
2016
|
-
"confidence should be None or a float in [0..1] range",
|
|
2017
|
-
),
|
|
2018
|
-
],
|
|
2019
|
-
)
|
|
2020
|
-
def test_partial_update_element_wrong_param_conf(mock_elements_worker, payload, error):
|
|
2021
|
-
api_payload = {
|
|
2022
|
-
"element": Element({"zone": None}),
|
|
2023
|
-
**payload,
|
|
2024
|
-
}
|
|
2025
|
-
|
|
2026
|
-
with pytest.raises(AssertionError, match=re.escape(error)):
|
|
2027
|
-
mock_elements_worker.partial_update_element(
|
|
2028
|
-
**api_payload,
|
|
2029
|
-
)
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
@pytest.mark.parametrize(
|
|
2033
|
-
("payload", "error"),
|
|
2034
|
-
[
|
|
2035
|
-
# Rotation angle
|
|
2036
|
-
({"rotation_angle": "lol"}, "rotation_angle should be a positive integer"),
|
|
2037
|
-
({"rotation_angle": -1}, "rotation_angle should be a positive integer"),
|
|
2038
|
-
({"rotation_angle": 0.5}, "rotation_angle should be a positive integer"),
|
|
2039
|
-
({"rotation_angle": None}, "rotation_angle should be a positive integer"),
|
|
2040
|
-
],
|
|
2041
|
-
)
|
|
2042
|
-
def test_partial_update_element_wrong_param_rota(mock_elements_worker, payload, error):
|
|
2043
|
-
api_payload = {
|
|
2044
|
-
"element": Element({"zone": None}),
|
|
2045
|
-
**payload,
|
|
2046
|
-
}
|
|
2047
|
-
|
|
2048
|
-
with pytest.raises(AssertionError, match=error):
|
|
2049
|
-
mock_elements_worker.partial_update_element(
|
|
2050
|
-
**api_payload,
|
|
2051
|
-
)
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
@pytest.mark.parametrize(
|
|
2055
|
-
("payload", "error"),
|
|
2056
|
-
[
|
|
2057
|
-
# Mirrored
|
|
2058
|
-
({"mirrored": "lol"}, "mirrored should be a boolean"),
|
|
2059
|
-
({"mirrored": 1234}, "mirrored should be a boolean"),
|
|
2060
|
-
({"mirrored": None}, "mirrored should be a boolean"),
|
|
2061
|
-
],
|
|
2062
|
-
)
|
|
2063
|
-
def test_partial_update_element_wrong_param_mir(mock_elements_worker, payload, error):
|
|
2064
|
-
api_payload = {
|
|
2065
|
-
"element": Element({"zone": None}),
|
|
2066
|
-
**payload,
|
|
2067
|
-
}
|
|
2068
|
-
|
|
2069
|
-
with pytest.raises(AssertionError, match=error):
|
|
2070
|
-
mock_elements_worker.partial_update_element(
|
|
2071
|
-
**api_payload,
|
|
2072
|
-
)
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
@pytest.mark.parametrize(
|
|
2076
|
-
("payload", "error"),
|
|
2077
|
-
[
|
|
2078
|
-
# Image
|
|
2079
|
-
({"image": "lol"}, "image should be a UUID"),
|
|
2080
|
-
({"image": 1234}, "image should be a UUID"),
|
|
2081
|
-
({"image": None}, "image should be a UUID"),
|
|
2082
|
-
],
|
|
2083
|
-
)
|
|
2084
|
-
def test_partial_update_element_wrong_param_image(mock_elements_worker, payload, error):
|
|
2085
|
-
api_payload = {
|
|
2086
|
-
"element": Element({"zone": None}),
|
|
2087
|
-
**payload,
|
|
2088
|
-
}
|
|
2089
|
-
|
|
2090
|
-
with pytest.raises(AssertionError, match=error):
|
|
2091
|
-
mock_elements_worker.partial_update_element(
|
|
2092
|
-
**api_payload,
|
|
2093
|
-
)
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
def test_partial_update_element_api_error(responses, mock_elements_worker):
|
|
2097
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
2098
|
-
responses.add(
|
|
2099
|
-
responses.PATCH,
|
|
2100
|
-
f"http://testserver/api/v1/element/{elt.id}/",
|
|
2101
|
-
status=418,
|
|
2102
|
-
)
|
|
2103
|
-
|
|
2104
|
-
with pytest.raises(ErrorResponse):
|
|
2105
|
-
mock_elements_worker.partial_update_element(
|
|
2106
|
-
element=elt,
|
|
2107
|
-
type="something",
|
|
2108
|
-
name="0",
|
|
2109
|
-
polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
2110
|
-
)
|
|
2111
|
-
|
|
2112
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 1
|
|
2113
|
-
assert [
|
|
2114
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
2115
|
-
] == BASE_API_CALLS + [("PATCH", f"http://testserver/api/v1/element/{elt.id}/")]
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
@pytest.mark.usefixtures("_mock_cached_elements", "_mock_cached_images")
|
|
2119
|
-
@pytest.mark.parametrize(
|
|
2120
|
-
"payload",
|
|
2121
|
-
[
|
|
2122
|
-
(
|
|
2123
|
-
{
|
|
2124
|
-
"polygon": [[10, 10], [20, 20], [20, 10], [10, 20]],
|
|
2125
|
-
"confidence": None,
|
|
2126
|
-
}
|
|
2127
|
-
),
|
|
2128
|
-
(
|
|
2129
|
-
{
|
|
2130
|
-
"rotation_angle": 45,
|
|
2131
|
-
"mirrored": False,
|
|
2132
|
-
}
|
|
2133
|
-
),
|
|
2134
|
-
(
|
|
2135
|
-
{
|
|
2136
|
-
"polygon": [[10, 10], [20, 20], [20, 10], [10, 20]],
|
|
2137
|
-
"confidence": None,
|
|
2138
|
-
"rotation_angle": 45,
|
|
2139
|
-
"mirrored": False,
|
|
2140
|
-
}
|
|
2141
|
-
),
|
|
2142
|
-
],
|
|
2143
|
-
)
|
|
2144
|
-
def test_partial_update_element(responses, mock_elements_worker_with_cache, payload):
|
|
2145
|
-
elt = CachedElement.select().first()
|
|
2146
|
-
new_image = CachedImage.select().first()
|
|
2147
|
-
|
|
2148
|
-
elt_response = {
|
|
2149
|
-
"image": str(new_image.id),
|
|
2150
|
-
**payload,
|
|
2151
|
-
}
|
|
2152
|
-
responses.add(
|
|
2153
|
-
responses.PATCH,
|
|
2154
|
-
f"http://testserver/api/v1/element/{elt.id}/",
|
|
2155
|
-
status=200,
|
|
2156
|
-
# UUID not allowed in JSON
|
|
2157
|
-
json=elt_response,
|
|
2158
|
-
)
|
|
2159
|
-
|
|
2160
|
-
element_update_response = mock_elements_worker_with_cache.partial_update_element(
|
|
2161
|
-
element=elt,
|
|
2162
|
-
**{**elt_response, "image": new_image.id},
|
|
2163
|
-
)
|
|
2164
|
-
|
|
2165
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 1
|
|
2166
|
-
assert [
|
|
2167
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
2168
|
-
] == BASE_API_CALLS + [
|
|
2169
|
-
(
|
|
2170
|
-
"PATCH",
|
|
2171
|
-
f"http://testserver/api/v1/element/{elt.id}/",
|
|
2172
|
-
),
|
|
2173
|
-
]
|
|
2174
|
-
assert json.loads(responses.calls[-1].request.body) == elt_response
|
|
2175
|
-
assert element_update_response == elt_response
|
|
2176
|
-
|
|
2177
|
-
cached_element = CachedElement.get(CachedElement.id == elt.id)
|
|
2178
|
-
# Always present in payload
|
|
2179
|
-
assert str(cached_element.image_id) == elt_response["image"]
|
|
2180
|
-
# Optional params
|
|
2181
|
-
if "polygon" in payload:
|
|
2182
|
-
# Cast to string as this is the only difference compared to model
|
|
2183
|
-
elt_response["polygon"] = str(elt_response["polygon"])
|
|
2184
|
-
|
|
2185
|
-
for param in payload:
|
|
2186
|
-
assert getattr(cached_element, param) == elt_response[param]
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
@pytest.mark.usefixtures("_mock_cached_elements")
|
|
2190
|
-
@pytest.mark.parametrize("confidence", [None, 0.42])
|
|
2191
|
-
def test_partial_update_element_confidence(
|
|
2192
|
-
responses, mock_elements_worker_with_cache, confidence
|
|
2193
|
-
):
|
|
2194
|
-
elt = CachedElement.select().first()
|
|
2195
|
-
elt_response = {
|
|
2196
|
-
"polygon": [[10, 10], [20, 20], [20, 10], [10, 20]],
|
|
2197
|
-
"confidence": confidence,
|
|
2198
|
-
}
|
|
2199
|
-
responses.add(
|
|
2200
|
-
responses.PATCH,
|
|
2201
|
-
f"http://testserver/api/v1/element/{elt.id}/",
|
|
2202
|
-
status=200,
|
|
2203
|
-
json=elt_response,
|
|
2204
|
-
)
|
|
2205
|
-
|
|
2206
|
-
element_update_response = mock_elements_worker_with_cache.partial_update_element(
|
|
2207
|
-
element=elt,
|
|
2208
|
-
**elt_response,
|
|
2209
|
-
)
|
|
2210
|
-
|
|
2211
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 1
|
|
2212
|
-
assert [
|
|
2213
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
2214
|
-
] == BASE_API_CALLS + [
|
|
2215
|
-
(
|
|
2216
|
-
"PATCH",
|
|
2217
|
-
f"http://testserver/api/v1/element/{elt.id}/",
|
|
2218
|
-
),
|
|
2219
|
-
]
|
|
2220
|
-
assert json.loads(responses.calls[-1].request.body) == elt_response
|
|
2221
|
-
assert element_update_response == elt_response
|
|
2222
|
-
|
|
2223
|
-
cached_element = CachedElement.get(CachedElement.id == elt.id)
|
|
2224
|
-
assert cached_element.polygon == str(elt_response["polygon"])
|
|
2225
|
-
assert cached_element.confidence == confidence
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
def test_list_elements_wrong_folder(mock_elements_worker):
|
|
2229
|
-
with pytest.raises(AssertionError, match="folder should be of type bool"):
|
|
2230
|
-
mock_elements_worker.list_elements(folder="not bool")
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
def test_list_elements_wrong_name(mock_elements_worker):
|
|
2234
|
-
with pytest.raises(AssertionError, match="name should be of type str"):
|
|
2235
|
-
mock_elements_worker.list_elements(name=1234)
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
def test_list_elements_wrong_top_level(mock_elements_worker):
|
|
2239
|
-
with pytest.raises(AssertionError, match="top_level should be of type bool"):
|
|
2240
|
-
mock_elements_worker.list_elements(top_level="not bool")
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
def test_list_elements_wrong_type(mock_elements_worker):
|
|
2244
|
-
with pytest.raises(AssertionError, match="type should be of type str"):
|
|
2245
|
-
mock_elements_worker.list_elements(type=1234)
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
def test_list_elements_wrong_with_classes(mock_elements_worker):
|
|
2249
|
-
with pytest.raises(AssertionError, match="with_classes should be of type bool"):
|
|
2250
|
-
mock_elements_worker.list_elements(with_classes="not bool")
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
def test_list_elements_wrong_with_corpus(mock_elements_worker):
|
|
2254
|
-
with pytest.raises(AssertionError, match="with_corpus should be of type bool"):
|
|
2255
|
-
mock_elements_worker.list_elements(with_corpus="not bool")
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
def test_list_elements_wrong_with_has_children(mock_elements_worker):
|
|
2259
|
-
with pytest.raises(
|
|
2260
|
-
AssertionError, match="with_has_children should be of type bool"
|
|
2261
|
-
):
|
|
2262
|
-
mock_elements_worker.list_elements(with_has_children="not bool")
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
def test_list_elements_wrong_with_zone(mock_elements_worker):
|
|
2266
|
-
with pytest.raises(AssertionError, match="with_zone should be of type bool"):
|
|
2267
|
-
mock_elements_worker.list_elements(with_zone="not bool")
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
def test_list_elements_wrong_with_metadata(mock_elements_worker):
|
|
2271
|
-
with pytest.raises(AssertionError, match="with_metadata should be of type bool"):
|
|
2272
|
-
mock_elements_worker.list_elements(with_metadata="not bool")
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
@pytest.mark.parametrize(
|
|
2276
|
-
("param", "value"),
|
|
2277
|
-
[
|
|
2278
|
-
("worker_run", 1234),
|
|
2279
|
-
("transcription_worker_run", 1234),
|
|
2280
|
-
],
|
|
2281
|
-
)
|
|
2282
|
-
def test_list_elements_wrong_worker_run(mock_elements_worker, param, value):
|
|
2283
|
-
with pytest.raises(AssertionError, match=f"{param} should be of type str or bool"):
|
|
2284
|
-
mock_elements_worker.list_elements(**{param: value})
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
@pytest.mark.parametrize(
|
|
2288
|
-
("param", "alternative", "value"),
|
|
2289
|
-
[
|
|
2290
|
-
("worker_version", "worker_run", 1234),
|
|
2291
|
-
("transcription_worker_version", "transcription_worker_run", 1234),
|
|
2292
|
-
],
|
|
2293
|
-
)
|
|
2294
|
-
def test_list_elements_wrong_worker_version(
|
|
2295
|
-
mock_elements_worker, param, alternative, value
|
|
2296
|
-
):
|
|
2297
|
-
# WARNING: pytest.deprecated_call must be placed BEFORE pytest.raises, otherwise `match` argument won't be checked
|
|
2298
|
-
with (
|
|
2299
|
-
pytest.deprecated_call(
|
|
2300
|
-
match=f"`{param}` usage is deprecated. Consider using `{alternative}` instead."
|
|
2301
|
-
),
|
|
2302
|
-
pytest.raises(AssertionError, match=f"{param} should be of type str or bool"),
|
|
2303
|
-
):
|
|
2304
|
-
mock_elements_worker.list_elements(**{param: value})
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
@pytest.mark.parametrize(
|
|
2308
|
-
"param",
|
|
2309
|
-
[
|
|
2310
|
-
"worker_run",
|
|
2311
|
-
"transcription_worker_run",
|
|
2312
|
-
],
|
|
2313
|
-
)
|
|
2314
|
-
def test_list_elements_wrong_bool_worker_run(mock_elements_worker, param):
|
|
2315
|
-
with pytest.raises(
|
|
2316
|
-
AssertionError, match=f"if of type bool, {param} can only be set to False"
|
|
2317
|
-
):
|
|
2318
|
-
mock_elements_worker.list_elements(**{param: True})
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
@pytest.mark.parametrize(
|
|
2322
|
-
("param", "alternative"),
|
|
2323
|
-
[
|
|
2324
|
-
("worker_version", "worker_run"),
|
|
2325
|
-
("transcription_worker_version", "transcription_worker_run"),
|
|
2326
|
-
],
|
|
2327
|
-
)
|
|
2328
|
-
def test_list_elements_wrong_bool_worker_version(
|
|
2329
|
-
mock_elements_worker, param, alternative
|
|
2330
|
-
):
|
|
2331
|
-
# WARNING: pytest.deprecated_call must be placed BEFORE pytest.raises, otherwise `match` argument won't be checked
|
|
2332
|
-
with (
|
|
2333
|
-
pytest.deprecated_call(
|
|
2334
|
-
match=f"`{param}` usage is deprecated. Consider using `{alternative}` instead."
|
|
2335
|
-
),
|
|
2336
|
-
pytest.raises(
|
|
2337
|
-
AssertionError, match=f"if of type bool, {param} can only be set to False"
|
|
2338
|
-
),
|
|
2339
|
-
):
|
|
2340
|
-
mock_elements_worker.list_elements(**{param: True})
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
def test_list_elements_api_error(responses, mock_elements_worker):
|
|
2344
|
-
responses.add(
|
|
2345
|
-
responses.GET,
|
|
2346
|
-
f"http://testserver/api/v1/corpus/{mock_elements_worker.corpus_id}/elements/",
|
|
2347
|
-
status=418,
|
|
2348
|
-
)
|
|
2349
|
-
|
|
2350
|
-
with pytest.raises(
|
|
2351
|
-
Exception, match="Stopping pagination as data will be incomplete"
|
|
2352
|
-
):
|
|
2353
|
-
next(mock_elements_worker.list_elements())
|
|
2354
|
-
|
|
2355
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 5
|
|
2356
|
-
assert [
|
|
2357
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
2358
|
-
] == BASE_API_CALLS + [
|
|
2359
|
-
# We do 5 retries
|
|
2360
|
-
(
|
|
2361
|
-
"GET",
|
|
2362
|
-
f"http://testserver/api/v1/corpus/{mock_elements_worker.corpus_id}/elements/",
|
|
2363
|
-
),
|
|
2364
|
-
(
|
|
2365
|
-
"GET",
|
|
2366
|
-
f"http://testserver/api/v1/corpus/{mock_elements_worker.corpus_id}/elements/",
|
|
2367
|
-
),
|
|
2368
|
-
(
|
|
2369
|
-
"GET",
|
|
2370
|
-
f"http://testserver/api/v1/corpus/{mock_elements_worker.corpus_id}/elements/",
|
|
2371
|
-
),
|
|
2372
|
-
(
|
|
2373
|
-
"GET",
|
|
2374
|
-
f"http://testserver/api/v1/corpus/{mock_elements_worker.corpus_id}/elements/",
|
|
2375
|
-
),
|
|
2376
|
-
(
|
|
2377
|
-
"GET",
|
|
2378
|
-
f"http://testserver/api/v1/corpus/{mock_elements_worker.corpus_id}/elements/",
|
|
2379
|
-
),
|
|
2380
|
-
]
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
def test_list_elements(responses, mock_elements_worker):
|
|
2384
|
-
expected_children = [
|
|
2385
|
-
{
|
|
2386
|
-
"id": "0000",
|
|
2387
|
-
"type": "page",
|
|
2388
|
-
"name": "Test",
|
|
2389
|
-
"corpus": {},
|
|
2390
|
-
"thumbnail_url": None,
|
|
2391
|
-
"zone": {},
|
|
2392
|
-
"best_classes": None,
|
|
2393
|
-
"has_children": None,
|
|
2394
|
-
"worker_version_id": None,
|
|
2395
|
-
"worker_run_id": None,
|
|
2396
|
-
},
|
|
2397
|
-
{
|
|
2398
|
-
"id": "1111",
|
|
2399
|
-
"type": "page",
|
|
2400
|
-
"name": "Test 2",
|
|
2401
|
-
"corpus": {},
|
|
2402
|
-
"thumbnail_url": None,
|
|
2403
|
-
"zone": {},
|
|
2404
|
-
"best_classes": None,
|
|
2405
|
-
"has_children": None,
|
|
2406
|
-
"worker_version_id": None,
|
|
2407
|
-
"worker_run_id": None,
|
|
2408
|
-
},
|
|
2409
|
-
{
|
|
2410
|
-
"id": "2222",
|
|
2411
|
-
"type": "page",
|
|
2412
|
-
"name": "Test 3",
|
|
2413
|
-
"corpus": {},
|
|
2414
|
-
"thumbnail_url": None,
|
|
2415
|
-
"zone": {},
|
|
2416
|
-
"best_classes": None,
|
|
2417
|
-
"has_children": None,
|
|
2418
|
-
"worker_version_id": None,
|
|
2419
|
-
"worker_run_id": None,
|
|
2420
|
-
},
|
|
2421
|
-
]
|
|
2422
|
-
responses.add(
|
|
2423
|
-
responses.GET,
|
|
2424
|
-
f"http://testserver/api/v1/corpus/{mock_elements_worker.corpus_id}/elements/",
|
|
2425
|
-
status=200,
|
|
2426
|
-
json={
|
|
2427
|
-
"count": 3,
|
|
2428
|
-
"next": None,
|
|
2429
|
-
"results": expected_children,
|
|
2430
|
-
},
|
|
2431
|
-
)
|
|
2432
|
-
|
|
2433
|
-
for idx, child in enumerate(mock_elements_worker.list_elements()):
|
|
2434
|
-
assert child == expected_children[idx]
|
|
2435
|
-
|
|
2436
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 1
|
|
2437
|
-
assert [
|
|
2438
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
2439
|
-
] == BASE_API_CALLS + [
|
|
2440
|
-
(
|
|
2441
|
-
"GET",
|
|
2442
|
-
f"http://testserver/api/v1/corpus/{mock_elements_worker.corpus_id}/elements/",
|
|
2443
|
-
),
|
|
2444
|
-
]
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
def test_list_elements_manual_worker_version(responses, mock_elements_worker):
|
|
2448
|
-
expected_children = [
|
|
2449
|
-
{
|
|
2450
|
-
"id": "0000",
|
|
2451
|
-
"type": "page",
|
|
2452
|
-
"name": "Test",
|
|
2453
|
-
"corpus": {},
|
|
2454
|
-
"thumbnail_url": None,
|
|
2455
|
-
"zone": {},
|
|
2456
|
-
"best_classes": None,
|
|
2457
|
-
"has_children": None,
|
|
2458
|
-
"worker_version_id": None,
|
|
2459
|
-
"worker_run_id": None,
|
|
2460
|
-
}
|
|
2461
|
-
]
|
|
2462
|
-
responses.add(
|
|
2463
|
-
responses.GET,
|
|
2464
|
-
f"http://testserver/api/v1/corpus/{mock_elements_worker.corpus_id}/elements/?worker_version=False",
|
|
2465
|
-
status=200,
|
|
2466
|
-
json={
|
|
2467
|
-
"count": 1,
|
|
2468
|
-
"next": None,
|
|
2469
|
-
"results": expected_children,
|
|
2470
|
-
},
|
|
2471
|
-
)
|
|
2472
|
-
|
|
2473
|
-
with pytest.deprecated_call(
|
|
2474
|
-
match="`worker_version` usage is deprecated. Consider using `worker_run` instead."
|
|
2475
|
-
):
|
|
2476
|
-
for idx, child in enumerate(
|
|
2477
|
-
mock_elements_worker.list_elements(worker_version=False)
|
|
2478
|
-
):
|
|
2479
|
-
assert child == expected_children[idx]
|
|
2480
|
-
|
|
2481
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 1
|
|
2482
|
-
assert [
|
|
2483
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
2484
|
-
] == BASE_API_CALLS + [
|
|
2485
|
-
(
|
|
2486
|
-
"GET",
|
|
2487
|
-
f"http://testserver/api/v1/corpus/{mock_elements_worker.corpus_id}/elements/?worker_version=False",
|
|
2488
|
-
),
|
|
2489
|
-
]
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
def test_list_elements_manual_worker_run(responses, mock_elements_worker):
|
|
2493
|
-
expected_children = [
|
|
2494
|
-
{
|
|
2495
|
-
"id": "0000",
|
|
2496
|
-
"type": "page",
|
|
2497
|
-
"name": "Test",
|
|
2498
|
-
"corpus": {},
|
|
2499
|
-
"thumbnail_url": None,
|
|
2500
|
-
"zone": {},
|
|
2501
|
-
"best_classes": None,
|
|
2502
|
-
"has_children": None,
|
|
2503
|
-
"worker_version_id": None,
|
|
2504
|
-
"worker_run_id": None,
|
|
2505
|
-
}
|
|
2506
|
-
]
|
|
2507
|
-
responses.add(
|
|
2508
|
-
responses.GET,
|
|
2509
|
-
f"http://testserver/api/v1/corpus/{mock_elements_worker.corpus_id}/elements/?worker_run=False",
|
|
2510
|
-
status=200,
|
|
2511
|
-
json={
|
|
2512
|
-
"count": 1,
|
|
2513
|
-
"next": None,
|
|
2514
|
-
"results": expected_children,
|
|
2515
|
-
},
|
|
2516
|
-
)
|
|
2517
|
-
|
|
2518
|
-
for idx, child in enumerate(mock_elements_worker.list_elements(worker_run=False)):
|
|
2519
|
-
assert child == expected_children[idx]
|
|
2520
|
-
|
|
2521
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 1
|
|
2522
|
-
assert [
|
|
2523
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
2524
|
-
] == BASE_API_CALLS + [
|
|
2525
|
-
(
|
|
2526
|
-
"GET",
|
|
2527
|
-
f"http://testserver/api/v1/corpus/{mock_elements_worker.corpus_id}/elements/?worker_run=False",
|
|
2528
|
-
),
|
|
2529
|
-
]
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
def test_list_elements_with_cache_unhandled_param(mock_elements_worker_with_cache):
|
|
2533
|
-
with pytest.raises(
|
|
2534
|
-
AssertionError,
|
|
2535
|
-
match="When using the local cache, you can only filter by 'type' and/or 'worker_version' and/or 'worker_run'",
|
|
2536
|
-
):
|
|
2537
|
-
mock_elements_worker_with_cache.list_elements(with_corpus=True)
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
@pytest.mark.usefixtures("_mock_cached_elements")
|
|
2541
|
-
@pytest.mark.parametrize(
|
|
2542
|
-
("filters", "expected_ids"),
|
|
2543
|
-
[
|
|
2544
|
-
# Filter on element should give all elements inserted
|
|
2545
|
-
(
|
|
2546
|
-
{},
|
|
2547
|
-
(
|
|
2548
|
-
"99999999-9999-9999-9999-999999999999",
|
|
2549
|
-
"12341234-1234-1234-1234-123412341234",
|
|
2550
|
-
"11111111-1111-1111-1111-111111111111",
|
|
2551
|
-
"22222222-2222-2222-2222-222222222222",
|
|
2552
|
-
"33333333-3333-3333-3333-333333333333",
|
|
2553
|
-
),
|
|
2554
|
-
),
|
|
2555
|
-
# Filter on element and page should give the second element
|
|
2556
|
-
(
|
|
2557
|
-
{"type": "page"},
|
|
2558
|
-
("22222222-2222-2222-2222-222222222222",),
|
|
2559
|
-
),
|
|
2560
|
-
# Filter on element and worker run should give second
|
|
2561
|
-
(
|
|
2562
|
-
{
|
|
2563
|
-
"worker_run": "56785678-5678-5678-5678-567856785678",
|
|
2564
|
-
},
|
|
2565
|
-
(
|
|
2566
|
-
"12341234-1234-1234-1234-123412341234",
|
|
2567
|
-
"22222222-2222-2222-2222-222222222222",
|
|
2568
|
-
),
|
|
2569
|
-
),
|
|
2570
|
-
# Filter on element, manual worker run should give first and third
|
|
2571
|
-
(
|
|
2572
|
-
{"worker_run": False},
|
|
2573
|
-
(
|
|
2574
|
-
"99999999-9999-9999-9999-999999999999",
|
|
2575
|
-
"11111111-1111-1111-1111-111111111111",
|
|
2576
|
-
"33333333-3333-3333-3333-333333333333",
|
|
2577
|
-
),
|
|
2578
|
-
),
|
|
2579
|
-
],
|
|
2580
|
-
)
|
|
2581
|
-
def test_list_elements_with_cache(
|
|
2582
|
-
responses, mock_elements_worker_with_cache, filters, expected_ids
|
|
2583
|
-
):
|
|
2584
|
-
# Check we have 5 elements already present in database
|
|
2585
|
-
assert CachedElement.select().count() == 5
|
|
2586
|
-
|
|
2587
|
-
# Query database through cache
|
|
2588
|
-
elements = mock_elements_worker_with_cache.list_elements(**filters)
|
|
2589
|
-
assert elements.count() == len(expected_ids)
|
|
2590
|
-
for child, expected_id in zip(elements.order_by("id"), expected_ids, strict=True):
|
|
2591
|
-
assert child.id == UUID(expected_id)
|
|
2592
|
-
|
|
2593
|
-
# Check the worker never hits the API for elements
|
|
2594
|
-
assert len(responses.calls) == len(BASE_API_CALLS)
|
|
2595
|
-
assert [
|
|
2596
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
2597
|
-
] == BASE_API_CALLS
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
@pytest.mark.usefixtures("_mock_cached_elements")
|
|
2601
|
-
@pytest.mark.parametrize(
|
|
2602
|
-
("filters", "expected_ids"),
|
|
2603
|
-
[
|
|
2604
|
-
# Filter on element and worker version
|
|
2605
|
-
(
|
|
2606
|
-
{
|
|
2607
|
-
"worker_version": "56785678-5678-5678-5678-567856785678",
|
|
2608
|
-
},
|
|
2609
|
-
(
|
|
2610
|
-
"12341234-1234-1234-1234-123412341234",
|
|
2611
|
-
"11111111-1111-1111-1111-111111111111",
|
|
2612
|
-
"22222222-2222-2222-2222-222222222222",
|
|
2613
|
-
),
|
|
2614
|
-
),
|
|
2615
|
-
# Filter on element, type double_page and worker version
|
|
2616
|
-
(
|
|
2617
|
-
{"type": "page", "worker_version": "56785678-5678-5678-5678-567856785678"},
|
|
2618
|
-
("22222222-2222-2222-2222-222222222222",),
|
|
2619
|
-
),
|
|
2620
|
-
# Filter on element, manual worker version
|
|
2621
|
-
(
|
|
2622
|
-
{"worker_version": False},
|
|
2623
|
-
(
|
|
2624
|
-
"99999999-9999-9999-9999-999999999999",
|
|
2625
|
-
"33333333-3333-3333-3333-333333333333",
|
|
2626
|
-
),
|
|
2627
|
-
),
|
|
2628
|
-
],
|
|
2629
|
-
)
|
|
2630
|
-
def test_list_elements_with_cache_deprecation(
|
|
2631
|
-
responses,
|
|
2632
|
-
mock_elements_worker_with_cache,
|
|
2633
|
-
filters,
|
|
2634
|
-
expected_ids,
|
|
2635
|
-
):
|
|
2636
|
-
# Check we have 5 elements already present in database
|
|
2637
|
-
assert CachedElement.select().count() == 5
|
|
2638
|
-
|
|
2639
|
-
with pytest.deprecated_call(
|
|
2640
|
-
match="`worker_version` usage is deprecated. Consider using `worker_run` instead."
|
|
2641
|
-
):
|
|
2642
|
-
# Query database through cache
|
|
2643
|
-
elements = mock_elements_worker_with_cache.list_elements(**filters)
|
|
2644
|
-
assert elements.count() == len(expected_ids)
|
|
2645
|
-
for child, expected_id in zip(elements.order_by("id"), expected_ids, strict=True):
|
|
2646
|
-
assert child.id == UUID(expected_id)
|
|
2647
|
-
|
|
2648
|
-
# Check the worker never hits the API for elements
|
|
2649
|
-
assert len(responses.calls) == len(BASE_API_CALLS)
|
|
2650
|
-
assert [
|
|
2651
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
2652
|
-
] == BASE_API_CALLS
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
def test_list_element_children_wrong_element(mock_elements_worker):
|
|
2656
|
-
with pytest.raises(
|
|
2657
|
-
AssertionError,
|
|
2658
|
-
match="element shouldn't be null and should be an Element or CachedElement",
|
|
2659
|
-
):
|
|
2660
|
-
mock_elements_worker.list_element_children(element=None)
|
|
2661
|
-
|
|
2662
|
-
with pytest.raises(
|
|
2663
|
-
AssertionError,
|
|
2664
|
-
match="element shouldn't be null and should be an Element or CachedElement",
|
|
2665
|
-
):
|
|
2666
|
-
mock_elements_worker.list_element_children(element="not element type")
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
def test_list_element_children_wrong_folder(mock_elements_worker):
|
|
2670
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
2671
|
-
|
|
2672
|
-
with pytest.raises(AssertionError, match="folder should be of type bool"):
|
|
2673
|
-
mock_elements_worker.list_element_children(
|
|
2674
|
-
element=elt,
|
|
2675
|
-
folder="not bool",
|
|
2676
|
-
)
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
def test_list_element_children_wrong_name(mock_elements_worker):
|
|
2680
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
2681
|
-
|
|
2682
|
-
with pytest.raises(AssertionError, match="name should be of type str"):
|
|
2683
|
-
mock_elements_worker.list_element_children(
|
|
2684
|
-
element=elt,
|
|
2685
|
-
name=1234,
|
|
2686
|
-
)
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
def test_list_element_children_wrong_recursive(mock_elements_worker):
|
|
2690
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
2691
|
-
|
|
2692
|
-
with pytest.raises(AssertionError, match="recursive should be of type bool"):
|
|
2693
|
-
mock_elements_worker.list_element_children(
|
|
2694
|
-
element=elt,
|
|
2695
|
-
recursive="not bool",
|
|
2696
|
-
)
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
def test_list_element_children_wrong_type(mock_elements_worker):
|
|
2700
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
2701
|
-
|
|
2702
|
-
with pytest.raises(AssertionError, match="type should be of type str"):
|
|
2703
|
-
mock_elements_worker.list_element_children(
|
|
2704
|
-
element=elt,
|
|
2705
|
-
type=1234,
|
|
2706
|
-
)
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
def test_list_element_children_wrong_with_classes(mock_elements_worker):
|
|
2710
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
2711
|
-
|
|
2712
|
-
with pytest.raises(AssertionError, match="with_classes should be of type bool"):
|
|
2713
|
-
mock_elements_worker.list_element_children(
|
|
2714
|
-
element=elt,
|
|
2715
|
-
with_classes="not bool",
|
|
2716
|
-
)
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
def test_list_element_children_wrong_with_corpus(mock_elements_worker):
|
|
2720
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
2721
|
-
|
|
2722
|
-
with pytest.raises(AssertionError, match="with_corpus should be of type bool"):
|
|
2723
|
-
mock_elements_worker.list_element_children(
|
|
2724
|
-
element=elt,
|
|
2725
|
-
with_corpus="not bool",
|
|
2726
|
-
)
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
def test_list_element_children_wrong_with_has_children(mock_elements_worker):
|
|
2730
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
2731
|
-
|
|
2732
|
-
with pytest.raises(
|
|
2733
|
-
AssertionError, match="with_has_children should be of type bool"
|
|
2734
|
-
):
|
|
2735
|
-
mock_elements_worker.list_element_children(
|
|
2736
|
-
element=elt,
|
|
2737
|
-
with_has_children="not bool",
|
|
2738
|
-
)
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
def test_list_element_children_wrong_with_zone(mock_elements_worker):
|
|
2742
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
2743
|
-
|
|
2744
|
-
with pytest.raises(AssertionError, match="with_zone should be of type bool"):
|
|
2745
|
-
mock_elements_worker.list_element_children(
|
|
2746
|
-
element=elt,
|
|
2747
|
-
with_zone="not bool",
|
|
2748
|
-
)
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
def test_list_element_children_wrong_with_metadata(mock_elements_worker):
|
|
2752
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
2753
|
-
|
|
2754
|
-
with pytest.raises(AssertionError, match="with_metadata should be of type bool"):
|
|
2755
|
-
mock_elements_worker.list_element_children(
|
|
2756
|
-
element=elt,
|
|
2757
|
-
with_metadata="not bool",
|
|
2758
|
-
)
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
@pytest.mark.parametrize(
|
|
2762
|
-
("param", "value"),
|
|
2763
|
-
[
|
|
2764
|
-
("worker_run", 1234),
|
|
2765
|
-
("transcription_worker_run", 1234),
|
|
2766
|
-
],
|
|
2767
|
-
)
|
|
2768
|
-
def test_list_element_children_wrong_worker_run(mock_elements_worker, param, value):
|
|
2769
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
2770
|
-
|
|
2771
|
-
with pytest.raises(AssertionError, match=f"{param} should be of type str or bool"):
|
|
2772
|
-
mock_elements_worker.list_element_children(
|
|
2773
|
-
element=elt,
|
|
2774
|
-
**{param: value},
|
|
2775
|
-
)
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
@pytest.mark.parametrize(
|
|
2779
|
-
("param", "alternative", "value"),
|
|
2780
|
-
[
|
|
2781
|
-
("worker_version", "worker_run", 1234),
|
|
2782
|
-
("transcription_worker_version", "transcription_worker_run", 1234),
|
|
2783
|
-
],
|
|
2784
|
-
)
|
|
2785
|
-
def test_list_element_children_wrong_worker_version(
|
|
2786
|
-
mock_elements_worker, param, alternative, value
|
|
2787
|
-
):
|
|
2788
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
2789
|
-
|
|
2790
|
-
# WARNING: pytest.deprecated_call must be placed BEFORE pytest.raises, otherwise `match` argument won't be checked
|
|
2791
|
-
with (
|
|
2792
|
-
pytest.deprecated_call(
|
|
2793
|
-
match=f"`{param}` usage is deprecated. Consider using `{alternative}` instead."
|
|
2794
|
-
),
|
|
2795
|
-
pytest.raises(AssertionError, match=f"{param} should be of type str or bool"),
|
|
2796
|
-
):
|
|
2797
|
-
mock_elements_worker.list_element_children(
|
|
2798
|
-
element=elt,
|
|
2799
|
-
**{param: value},
|
|
2800
|
-
)
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
@pytest.mark.parametrize(
|
|
2804
|
-
"param",
|
|
2805
|
-
[
|
|
2806
|
-
"worker_run",
|
|
2807
|
-
"transcription_worker_run",
|
|
2808
|
-
],
|
|
2809
|
-
)
|
|
2810
|
-
def test_list_element_children_wrong_bool_worker_run(mock_elements_worker, param):
|
|
2811
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
2812
|
-
|
|
2813
|
-
with pytest.raises(
|
|
2814
|
-
AssertionError, match=f"if of type bool, {param} can only be set to False"
|
|
2815
|
-
):
|
|
2816
|
-
mock_elements_worker.list_element_children(
|
|
2817
|
-
element=elt,
|
|
2818
|
-
**{param: True},
|
|
2819
|
-
)
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
@pytest.mark.parametrize(
|
|
2823
|
-
("param", "alternative"),
|
|
2824
|
-
[
|
|
2825
|
-
("worker_version", "worker_run"),
|
|
2826
|
-
("transcription_worker_version", "transcription_worker_run"),
|
|
2827
|
-
],
|
|
2828
|
-
)
|
|
2829
|
-
def test_list_element_children_wrong_bool_worker_version(
|
|
2830
|
-
mock_elements_worker, param, alternative
|
|
2831
|
-
):
|
|
2832
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
2833
|
-
|
|
2834
|
-
# WARNING: pytest.deprecated_call must be placed BEFORE pytest.raises, otherwise `match` argument won't be checked
|
|
2835
|
-
with (
|
|
2836
|
-
pytest.deprecated_call(
|
|
2837
|
-
match=f"`{param}` usage is deprecated. Consider using `{alternative}` instead."
|
|
2838
|
-
),
|
|
2839
|
-
pytest.raises(
|
|
2840
|
-
AssertionError, match=f"if of type bool, {param} can only be set to False"
|
|
2841
|
-
),
|
|
2842
|
-
):
|
|
2843
|
-
mock_elements_worker.list_element_children(
|
|
2844
|
-
element=elt,
|
|
2845
|
-
**{param: True},
|
|
2846
|
-
)
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
def test_list_element_children_api_error(responses, mock_elements_worker):
|
|
2850
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
2851
|
-
responses.add(
|
|
2852
|
-
responses.GET,
|
|
2853
|
-
"http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/children/",
|
|
2854
|
-
status=418,
|
|
2855
|
-
)
|
|
2856
|
-
|
|
2857
|
-
with pytest.raises(
|
|
2858
|
-
Exception, match="Stopping pagination as data will be incomplete"
|
|
2859
|
-
):
|
|
2860
|
-
next(mock_elements_worker.list_element_children(element=elt))
|
|
2861
|
-
|
|
2862
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 5
|
|
2863
|
-
assert [
|
|
2864
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
2865
|
-
] == BASE_API_CALLS + [
|
|
2866
|
-
# We do 5 retries
|
|
2867
|
-
(
|
|
2868
|
-
"GET",
|
|
2869
|
-
"http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/children/",
|
|
2870
|
-
),
|
|
2871
|
-
(
|
|
2872
|
-
"GET",
|
|
2873
|
-
"http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/children/",
|
|
2874
|
-
),
|
|
2875
|
-
(
|
|
2876
|
-
"GET",
|
|
2877
|
-
"http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/children/",
|
|
2878
|
-
),
|
|
2879
|
-
(
|
|
2880
|
-
"GET",
|
|
2881
|
-
"http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/children/",
|
|
2882
|
-
),
|
|
2883
|
-
(
|
|
2884
|
-
"GET",
|
|
2885
|
-
"http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/children/",
|
|
2886
|
-
),
|
|
2887
|
-
]
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
def test_list_element_children(responses, mock_elements_worker):
|
|
2891
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
2892
|
-
expected_children = [
|
|
2893
|
-
{
|
|
2894
|
-
"id": "0000",
|
|
2895
|
-
"type": "page",
|
|
2896
|
-
"name": "Test",
|
|
2897
|
-
"corpus": {},
|
|
2898
|
-
"thumbnail_url": None,
|
|
2899
|
-
"zone": {},
|
|
2900
|
-
"best_classes": None,
|
|
2901
|
-
"has_children": None,
|
|
2902
|
-
"worker_version_id": None,
|
|
2903
|
-
"worker_run_id": None,
|
|
2904
|
-
},
|
|
2905
|
-
{
|
|
2906
|
-
"id": "1111",
|
|
2907
|
-
"type": "page",
|
|
2908
|
-
"name": "Test 2",
|
|
2909
|
-
"corpus": {},
|
|
2910
|
-
"thumbnail_url": None,
|
|
2911
|
-
"zone": {},
|
|
2912
|
-
"best_classes": None,
|
|
2913
|
-
"has_children": None,
|
|
2914
|
-
"worker_version_id": None,
|
|
2915
|
-
"worker_run_id": None,
|
|
2916
|
-
},
|
|
2917
|
-
{
|
|
2918
|
-
"id": "2222",
|
|
2919
|
-
"type": "page",
|
|
2920
|
-
"name": "Test 3",
|
|
2921
|
-
"corpus": {},
|
|
2922
|
-
"thumbnail_url": None,
|
|
2923
|
-
"zone": {},
|
|
2924
|
-
"best_classes": None,
|
|
2925
|
-
"has_children": None,
|
|
2926
|
-
"worker_version_id": None,
|
|
2927
|
-
"worker_run_id": None,
|
|
2928
|
-
},
|
|
2929
|
-
]
|
|
2930
|
-
responses.add(
|
|
2931
|
-
responses.GET,
|
|
2932
|
-
"http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/children/",
|
|
2933
|
-
status=200,
|
|
2934
|
-
json={
|
|
2935
|
-
"count": 3,
|
|
2936
|
-
"next": None,
|
|
2937
|
-
"results": expected_children,
|
|
2938
|
-
},
|
|
2939
|
-
)
|
|
2940
|
-
|
|
2941
|
-
for idx, child in enumerate(
|
|
2942
|
-
mock_elements_worker.list_element_children(element=elt)
|
|
2943
|
-
):
|
|
2944
|
-
assert child == expected_children[idx]
|
|
2945
|
-
|
|
2946
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 1
|
|
2947
|
-
assert [
|
|
2948
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
2949
|
-
] == BASE_API_CALLS + [
|
|
2950
|
-
(
|
|
2951
|
-
"GET",
|
|
2952
|
-
"http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/children/",
|
|
2953
|
-
),
|
|
2954
|
-
]
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
def test_list_element_children_manual_worker_version(responses, mock_elements_worker):
|
|
2958
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
2959
|
-
expected_children = [
|
|
2960
|
-
{
|
|
2961
|
-
"id": "0000",
|
|
2962
|
-
"type": "page",
|
|
2963
|
-
"name": "Test",
|
|
2964
|
-
"corpus": {},
|
|
2965
|
-
"thumbnail_url": None,
|
|
2966
|
-
"zone": {},
|
|
2967
|
-
"best_classes": None,
|
|
2968
|
-
"has_children": None,
|
|
2969
|
-
"worker_version_id": None,
|
|
2970
|
-
"worker_run_id": None,
|
|
2971
|
-
}
|
|
2972
|
-
]
|
|
2973
|
-
responses.add(
|
|
2974
|
-
responses.GET,
|
|
2975
|
-
"http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/children/?worker_version=False",
|
|
2976
|
-
status=200,
|
|
2977
|
-
json={
|
|
2978
|
-
"count": 1,
|
|
2979
|
-
"next": None,
|
|
2980
|
-
"results": expected_children,
|
|
2981
|
-
},
|
|
2982
|
-
)
|
|
2983
|
-
|
|
2984
|
-
with pytest.deprecated_call(
|
|
2985
|
-
match="`worker_version` usage is deprecated. Consider using `worker_run` instead."
|
|
2986
|
-
):
|
|
2987
|
-
for idx, child in enumerate(
|
|
2988
|
-
mock_elements_worker.list_element_children(
|
|
2989
|
-
element=elt, worker_version=False
|
|
2990
|
-
)
|
|
2991
|
-
):
|
|
2992
|
-
assert child == expected_children[idx]
|
|
2993
|
-
|
|
2994
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 1
|
|
2995
|
-
assert [
|
|
2996
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
2997
|
-
] == BASE_API_CALLS + [
|
|
2998
|
-
(
|
|
2999
|
-
"GET",
|
|
3000
|
-
"http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/children/?worker_version=False",
|
|
3001
|
-
),
|
|
3002
|
-
]
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
def test_list_element_children_manual_worker_run(responses, mock_elements_worker):
|
|
3006
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
3007
|
-
expected_children = [
|
|
3008
|
-
{
|
|
3009
|
-
"id": "0000",
|
|
3010
|
-
"type": "page",
|
|
3011
|
-
"name": "Test",
|
|
3012
|
-
"corpus": {},
|
|
3013
|
-
"thumbnail_url": None,
|
|
3014
|
-
"zone": {},
|
|
3015
|
-
"best_classes": None,
|
|
3016
|
-
"has_children": None,
|
|
3017
|
-
"worker_version_id": None,
|
|
3018
|
-
"worker_run_id": None,
|
|
3019
|
-
}
|
|
3020
|
-
]
|
|
3021
|
-
responses.add(
|
|
3022
|
-
responses.GET,
|
|
3023
|
-
"http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/children/?worker_run=False",
|
|
3024
|
-
status=200,
|
|
3025
|
-
json={
|
|
3026
|
-
"count": 1,
|
|
3027
|
-
"next": None,
|
|
3028
|
-
"results": expected_children,
|
|
3029
|
-
},
|
|
3030
|
-
)
|
|
3031
|
-
|
|
3032
|
-
for idx, child in enumerate(
|
|
3033
|
-
mock_elements_worker.list_element_children(element=elt, worker_run=False)
|
|
3034
|
-
):
|
|
3035
|
-
assert child == expected_children[idx]
|
|
3036
|
-
|
|
3037
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 1
|
|
3038
|
-
assert [
|
|
3039
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
3040
|
-
] == BASE_API_CALLS + [
|
|
3041
|
-
(
|
|
3042
|
-
"GET",
|
|
3043
|
-
"http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/children/?worker_run=False",
|
|
3044
|
-
),
|
|
3045
|
-
]
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
def test_list_element_children_with_cache_unhandled_param(
|
|
3049
|
-
mock_elements_worker_with_cache,
|
|
3050
|
-
):
|
|
3051
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
3052
|
-
|
|
3053
|
-
with pytest.raises(
|
|
3054
|
-
AssertionError,
|
|
3055
|
-
match="When using the local cache, you can only filter by 'type' and/or 'worker_version' and/or 'worker_run'",
|
|
3056
|
-
):
|
|
3057
|
-
mock_elements_worker_with_cache.list_element_children(
|
|
3058
|
-
element=elt, with_corpus=True
|
|
3059
|
-
)
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
@pytest.mark.usefixtures("_mock_cached_elements")
|
|
3063
|
-
@pytest.mark.parametrize(
|
|
3064
|
-
("filters", "expected_ids"),
|
|
3065
|
-
[
|
|
3066
|
-
# Filter on element should give all elements inserted
|
|
3067
|
-
(
|
|
3068
|
-
{
|
|
3069
|
-
"element": CachedElement(id="12341234-1234-1234-1234-123412341234"),
|
|
3070
|
-
},
|
|
3071
|
-
(
|
|
3072
|
-
"11111111-1111-1111-1111-111111111111",
|
|
3073
|
-
"22222222-2222-2222-2222-222222222222",
|
|
3074
|
-
"33333333-3333-3333-3333-333333333333",
|
|
3075
|
-
),
|
|
3076
|
-
),
|
|
3077
|
-
# Filter on element and page should give the second element
|
|
3078
|
-
(
|
|
3079
|
-
{
|
|
3080
|
-
"element": CachedElement(id="12341234-1234-1234-1234-123412341234"),
|
|
3081
|
-
"type": "page",
|
|
3082
|
-
},
|
|
3083
|
-
("22222222-2222-2222-2222-222222222222",),
|
|
3084
|
-
),
|
|
3085
|
-
# Filter on element and worker run should give second
|
|
3086
|
-
(
|
|
3087
|
-
{
|
|
3088
|
-
"element": CachedElement(id="12341234-1234-1234-1234-123412341234"),
|
|
3089
|
-
"worker_run": "56785678-5678-5678-5678-567856785678",
|
|
3090
|
-
},
|
|
3091
|
-
("22222222-2222-2222-2222-222222222222",),
|
|
3092
|
-
),
|
|
3093
|
-
# Filter on element, manual worker run should give first and third
|
|
3094
|
-
(
|
|
3095
|
-
{
|
|
3096
|
-
"element": CachedElement(id="12341234-1234-1234-1234-123412341234"),
|
|
3097
|
-
"worker_run": False,
|
|
3098
|
-
},
|
|
3099
|
-
(
|
|
3100
|
-
"11111111-1111-1111-1111-111111111111",
|
|
3101
|
-
"33333333-3333-3333-3333-333333333333",
|
|
3102
|
-
),
|
|
3103
|
-
),
|
|
3104
|
-
],
|
|
3105
|
-
)
|
|
3106
|
-
def test_list_element_children_with_cache(
|
|
3107
|
-
responses,
|
|
3108
|
-
mock_elements_worker_with_cache,
|
|
3109
|
-
filters,
|
|
3110
|
-
expected_ids,
|
|
3111
|
-
):
|
|
3112
|
-
# Check we have 5 elements already present in database
|
|
3113
|
-
assert CachedElement.select().count() == 5
|
|
3114
|
-
|
|
3115
|
-
# Query database through cache
|
|
3116
|
-
elements = mock_elements_worker_with_cache.list_element_children(**filters)
|
|
3117
|
-
assert elements.count() == len(expected_ids)
|
|
3118
|
-
for child, expected_id in zip(elements.order_by("id"), expected_ids, strict=True):
|
|
3119
|
-
assert child.id == UUID(expected_id)
|
|
3120
|
-
|
|
3121
|
-
# Check the worker never hits the API for elements
|
|
3122
|
-
assert len(responses.calls) == len(BASE_API_CALLS)
|
|
3123
|
-
assert [
|
|
3124
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
3125
|
-
] == BASE_API_CALLS
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
@pytest.mark.usefixtures("_mock_cached_elements")
|
|
3129
|
-
@pytest.mark.parametrize(
|
|
3130
|
-
("filters", "expected_ids"),
|
|
3131
|
-
[
|
|
3132
|
-
# Filter on element and worker version
|
|
3133
|
-
(
|
|
3134
|
-
{
|
|
3135
|
-
"element": CachedElement(id="12341234-1234-1234-1234-123412341234"),
|
|
3136
|
-
"worker_version": "56785678-5678-5678-5678-567856785678",
|
|
3137
|
-
},
|
|
3138
|
-
(
|
|
3139
|
-
"11111111-1111-1111-1111-111111111111",
|
|
3140
|
-
"22222222-2222-2222-2222-222222222222",
|
|
3141
|
-
),
|
|
3142
|
-
),
|
|
3143
|
-
# Filter on element, type double_page and worker version
|
|
3144
|
-
(
|
|
3145
|
-
{
|
|
3146
|
-
"element": CachedElement(id="12341234-1234-1234-1234-123412341234"),
|
|
3147
|
-
"type": "page",
|
|
3148
|
-
"worker_version": "56785678-5678-5678-5678-567856785678",
|
|
3149
|
-
},
|
|
3150
|
-
("22222222-2222-2222-2222-222222222222",),
|
|
3151
|
-
),
|
|
3152
|
-
# Filter on element, manual worker version
|
|
3153
|
-
(
|
|
3154
|
-
{
|
|
3155
|
-
"element": CachedElement(id="12341234-1234-1234-1234-123412341234"),
|
|
3156
|
-
"worker_version": False,
|
|
3157
|
-
},
|
|
3158
|
-
("33333333-3333-3333-3333-333333333333",),
|
|
3159
|
-
),
|
|
3160
|
-
],
|
|
3161
|
-
)
|
|
3162
|
-
def test_list_element_children_with_cache_deprecation(
|
|
3163
|
-
responses,
|
|
3164
|
-
mock_elements_worker_with_cache,
|
|
3165
|
-
filters,
|
|
3166
|
-
expected_ids,
|
|
3167
|
-
):
|
|
3168
|
-
# Check we have 5 elements already present in database
|
|
3169
|
-
assert CachedElement.select().count() == 5
|
|
3170
|
-
|
|
3171
|
-
with pytest.deprecated_call(
|
|
3172
|
-
match="`worker_version` usage is deprecated. Consider using `worker_run` instead."
|
|
3173
|
-
):
|
|
3174
|
-
# Query database through cache
|
|
3175
|
-
elements = mock_elements_worker_with_cache.list_element_children(**filters)
|
|
3176
|
-
assert elements.count() == len(expected_ids)
|
|
3177
|
-
for child, expected_id in zip(elements.order_by("id"), expected_ids, strict=True):
|
|
3178
|
-
assert child.id == UUID(expected_id)
|
|
3179
|
-
|
|
3180
|
-
# Check the worker never hits the API for elements
|
|
3181
|
-
assert len(responses.calls) == len(BASE_API_CALLS)
|
|
3182
|
-
assert [
|
|
3183
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
3184
|
-
] == BASE_API_CALLS
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
def test_list_element_parents_wrong_element(mock_elements_worker):
|
|
3188
|
-
with pytest.raises(
|
|
3189
|
-
AssertionError,
|
|
3190
|
-
match="element shouldn't be null and should be an Element or CachedElement",
|
|
3191
|
-
):
|
|
3192
|
-
mock_elements_worker.list_element_parents(element=None)
|
|
3193
|
-
|
|
3194
|
-
with pytest.raises(
|
|
3195
|
-
AssertionError,
|
|
3196
|
-
match="element shouldn't be null and should be an Element or CachedElement",
|
|
3197
|
-
):
|
|
3198
|
-
mock_elements_worker.list_element_parents(element="not element type")
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
def test_list_element_parents_wrong_folder(mock_elements_worker):
|
|
3202
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
3203
|
-
|
|
3204
|
-
with pytest.raises(AssertionError, match="folder should be of type bool"):
|
|
3205
|
-
mock_elements_worker.list_element_parents(
|
|
3206
|
-
element=elt,
|
|
3207
|
-
folder="not bool",
|
|
3208
|
-
)
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
def test_list_element_parents_wrong_name(mock_elements_worker):
|
|
3212
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
3213
|
-
|
|
3214
|
-
with pytest.raises(AssertionError, match="name should be of type str"):
|
|
3215
|
-
mock_elements_worker.list_element_parents(
|
|
3216
|
-
element=elt,
|
|
3217
|
-
name=1234,
|
|
3218
|
-
)
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
def test_list_element_parents_wrong_recursive(mock_elements_worker):
|
|
3222
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
3223
|
-
|
|
3224
|
-
with pytest.raises(AssertionError, match="recursive should be of type bool"):
|
|
3225
|
-
mock_elements_worker.list_element_parents(
|
|
3226
|
-
element=elt,
|
|
3227
|
-
recursive="not bool",
|
|
3228
|
-
)
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
def test_list_element_parents_wrong_type(mock_elements_worker):
|
|
3232
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
3233
|
-
|
|
3234
|
-
with pytest.raises(AssertionError, match="type should be of type str"):
|
|
3235
|
-
mock_elements_worker.list_element_parents(
|
|
3236
|
-
element=elt,
|
|
3237
|
-
type=1234,
|
|
3238
|
-
)
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
def test_list_element_parents_wrong_with_classes(mock_elements_worker):
|
|
3242
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
3243
|
-
|
|
3244
|
-
with pytest.raises(AssertionError, match="with_classes should be of type bool"):
|
|
3245
|
-
mock_elements_worker.list_element_parents(
|
|
3246
|
-
element=elt,
|
|
3247
|
-
with_classes="not bool",
|
|
3248
|
-
)
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
def test_list_element_parents_wrong_with_corpus(mock_elements_worker):
|
|
3252
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
3253
|
-
|
|
3254
|
-
with pytest.raises(AssertionError, match="with_corpus should be of type bool"):
|
|
3255
|
-
mock_elements_worker.list_element_parents(
|
|
3256
|
-
element=elt,
|
|
3257
|
-
with_corpus="not bool",
|
|
3258
|
-
)
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
def test_list_element_parents_wrong_with_has_children(mock_elements_worker):
|
|
3262
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
3263
|
-
|
|
3264
|
-
with pytest.raises(
|
|
3265
|
-
AssertionError, match="with_has_children should be of type bool"
|
|
3266
|
-
):
|
|
3267
|
-
mock_elements_worker.list_element_parents(
|
|
3268
|
-
element=elt,
|
|
3269
|
-
with_has_children="not bool",
|
|
3270
|
-
)
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
def test_list_element_parents_wrong_with_zone(mock_elements_worker):
|
|
3274
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
3275
|
-
|
|
3276
|
-
with pytest.raises(AssertionError, match="with_zone should be of type bool"):
|
|
3277
|
-
mock_elements_worker.list_element_parents(
|
|
3278
|
-
element=elt,
|
|
3279
|
-
with_zone="not bool",
|
|
3280
|
-
)
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
def test_list_element_parents_wrong_with_metadata(mock_elements_worker):
|
|
3284
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
3285
|
-
|
|
3286
|
-
with pytest.raises(AssertionError, match="with_metadata should be of type bool"):
|
|
3287
|
-
mock_elements_worker.list_element_parents(
|
|
3288
|
-
element=elt,
|
|
3289
|
-
with_metadata="not bool",
|
|
3290
|
-
)
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
@pytest.mark.parametrize(
|
|
3294
|
-
("param", "value"),
|
|
3295
|
-
[
|
|
3296
|
-
("worker_run", 1234),
|
|
3297
|
-
("transcription_worker_run", 1234),
|
|
3298
|
-
],
|
|
3299
|
-
)
|
|
3300
|
-
def test_list_element_parents_wrong_worker_run(mock_elements_worker, param, value):
|
|
3301
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
3302
|
-
|
|
3303
|
-
with pytest.raises(AssertionError, match=f"{param} should be of type str or bool"):
|
|
3304
|
-
mock_elements_worker.list_element_parents(
|
|
3305
|
-
element=elt,
|
|
3306
|
-
**{param: value},
|
|
3307
|
-
)
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
@pytest.mark.parametrize(
|
|
3311
|
-
("param", "alternative", "value"),
|
|
3312
|
-
[
|
|
3313
|
-
("worker_version", "worker_run", 1234),
|
|
3314
|
-
("transcription_worker_version", "transcription_worker_run", 1234),
|
|
3315
|
-
],
|
|
3316
|
-
)
|
|
3317
|
-
def test_list_element_parents_wrong_worker_version(
|
|
3318
|
-
mock_elements_worker, param, alternative, value
|
|
3319
|
-
):
|
|
3320
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
3321
|
-
|
|
3322
|
-
# WARNING: pytest.deprecated_call must be placed BEFORE pytest.raises, otherwise `match` argument won't be checked
|
|
3323
|
-
with (
|
|
3324
|
-
pytest.deprecated_call(
|
|
3325
|
-
match=f"`{param}` usage is deprecated. Consider using `{alternative}` instead."
|
|
3326
|
-
),
|
|
3327
|
-
pytest.raises(AssertionError, match=f"{param} should be of type str or bool"),
|
|
3328
|
-
):
|
|
3329
|
-
mock_elements_worker.list_element_parents(
|
|
3330
|
-
element=elt,
|
|
3331
|
-
**{param: value},
|
|
3332
|
-
)
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
@pytest.mark.parametrize(
|
|
3336
|
-
"param",
|
|
3337
|
-
[
|
|
3338
|
-
"worker_run",
|
|
3339
|
-
"transcription_worker_run",
|
|
3340
|
-
],
|
|
3341
|
-
)
|
|
3342
|
-
def test_list_element_parents_wrong_bool_worker_run(mock_elements_worker, param):
|
|
3343
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
3344
|
-
|
|
3345
|
-
with pytest.raises(
|
|
3346
|
-
AssertionError, match=f"if of type bool, {param} can only be set to False"
|
|
3347
|
-
):
|
|
3348
|
-
mock_elements_worker.list_element_parents(
|
|
3349
|
-
element=elt,
|
|
3350
|
-
**{param: True},
|
|
3351
|
-
)
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
@pytest.mark.parametrize(
|
|
3355
|
-
("param", "alternative"),
|
|
3356
|
-
[
|
|
3357
|
-
("worker_version", "worker_run"),
|
|
3358
|
-
("transcription_worker_version", "transcription_worker_run"),
|
|
3359
|
-
],
|
|
3360
|
-
)
|
|
3361
|
-
def test_list_element_parents_wrong_bool_worker_version(
|
|
3362
|
-
mock_elements_worker, param, alternative
|
|
3363
|
-
):
|
|
3364
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
3365
|
-
|
|
3366
|
-
# WARNING: pytest.deprecated_call must be placed BEFORE pytest.raises, otherwise `match` argument won't be checked
|
|
3367
|
-
with (
|
|
3368
|
-
pytest.deprecated_call(
|
|
3369
|
-
match=f"`{param}` usage is deprecated. Consider using `{alternative}` instead."
|
|
3370
|
-
),
|
|
3371
|
-
pytest.raises(
|
|
3372
|
-
AssertionError, match=f"if of type bool, {param} can only be set to False"
|
|
3373
|
-
),
|
|
3374
|
-
):
|
|
3375
|
-
mock_elements_worker.list_element_parents(
|
|
3376
|
-
element=elt,
|
|
3377
|
-
**{param: True},
|
|
3378
|
-
)
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
def test_list_element_parents_api_error(responses, mock_elements_worker):
|
|
3382
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
3383
|
-
responses.add(
|
|
3384
|
-
responses.GET,
|
|
3385
|
-
"http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/parents/",
|
|
3386
|
-
status=418,
|
|
3387
|
-
)
|
|
3388
|
-
|
|
3389
|
-
with pytest.raises(
|
|
3390
|
-
Exception, match="Stopping pagination as data will be incomplete"
|
|
3391
|
-
):
|
|
3392
|
-
next(mock_elements_worker.list_element_parents(element=elt))
|
|
3393
|
-
|
|
3394
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 5
|
|
3395
|
-
assert [
|
|
3396
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
3397
|
-
] == BASE_API_CALLS + [
|
|
3398
|
-
# We do 5 retries
|
|
3399
|
-
(
|
|
3400
|
-
"GET",
|
|
3401
|
-
"http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/parents/",
|
|
3402
|
-
),
|
|
3403
|
-
(
|
|
3404
|
-
"GET",
|
|
3405
|
-
"http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/parents/",
|
|
3406
|
-
),
|
|
3407
|
-
(
|
|
3408
|
-
"GET",
|
|
3409
|
-
"http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/parents/",
|
|
3410
|
-
),
|
|
3411
|
-
(
|
|
3412
|
-
"GET",
|
|
3413
|
-
"http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/parents/",
|
|
3414
|
-
),
|
|
3415
|
-
(
|
|
3416
|
-
"GET",
|
|
3417
|
-
"http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/parents/",
|
|
3418
|
-
),
|
|
3419
|
-
]
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
def test_list_element_parents(responses, mock_elements_worker):
|
|
3423
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
3424
|
-
expected_parents = [
|
|
3425
|
-
{
|
|
3426
|
-
"id": "0000",
|
|
3427
|
-
"type": "page",
|
|
3428
|
-
"name": "Test",
|
|
3429
|
-
"corpus": {},
|
|
3430
|
-
"thumbnail_url": None,
|
|
3431
|
-
"zone": {},
|
|
3432
|
-
"best_classes": None,
|
|
3433
|
-
"has_children": None,
|
|
3434
|
-
"worker_version_id": None,
|
|
3435
|
-
"worker_run_id": None,
|
|
3436
|
-
},
|
|
3437
|
-
{
|
|
3438
|
-
"id": "1111",
|
|
3439
|
-
"type": "page",
|
|
3440
|
-
"name": "Test 2",
|
|
3441
|
-
"corpus": {},
|
|
3442
|
-
"thumbnail_url": None,
|
|
3443
|
-
"zone": {},
|
|
3444
|
-
"best_classes": None,
|
|
3445
|
-
"has_children": None,
|
|
3446
|
-
"worker_version_id": None,
|
|
3447
|
-
"worker_run_id": None,
|
|
3448
|
-
},
|
|
3449
|
-
{
|
|
3450
|
-
"id": "2222",
|
|
3451
|
-
"type": "page",
|
|
3452
|
-
"name": "Test 3",
|
|
3453
|
-
"corpus": {},
|
|
3454
|
-
"thumbnail_url": None,
|
|
3455
|
-
"zone": {},
|
|
3456
|
-
"best_classes": None,
|
|
3457
|
-
"has_children": None,
|
|
3458
|
-
"worker_version_id": None,
|
|
3459
|
-
"worker_run_id": None,
|
|
3460
|
-
},
|
|
3461
|
-
]
|
|
3462
|
-
responses.add(
|
|
3463
|
-
responses.GET,
|
|
3464
|
-
"http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/parents/",
|
|
3465
|
-
status=200,
|
|
3466
|
-
json={
|
|
3467
|
-
"count": 3,
|
|
3468
|
-
"next": None,
|
|
3469
|
-
"results": expected_parents,
|
|
3470
|
-
},
|
|
3471
|
-
)
|
|
3472
|
-
|
|
3473
|
-
for idx, parent in enumerate(
|
|
3474
|
-
mock_elements_worker.list_element_parents(element=elt)
|
|
3475
|
-
):
|
|
3476
|
-
assert parent == expected_parents[idx]
|
|
3477
|
-
|
|
3478
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 1
|
|
3479
|
-
assert [
|
|
3480
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
3481
|
-
] == BASE_API_CALLS + [
|
|
3482
|
-
(
|
|
3483
|
-
"GET",
|
|
3484
|
-
"http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/parents/",
|
|
3485
|
-
),
|
|
3486
|
-
]
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
def test_list_element_parents_manual_worker_version(responses, mock_elements_worker):
|
|
3490
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
3491
|
-
expected_parents = [
|
|
3492
|
-
{
|
|
3493
|
-
"id": "0000",
|
|
3494
|
-
"type": "page",
|
|
3495
|
-
"name": "Test",
|
|
3496
|
-
"corpus": {},
|
|
3497
|
-
"thumbnail_url": None,
|
|
3498
|
-
"zone": {},
|
|
3499
|
-
"best_classes": None,
|
|
3500
|
-
"has_children": None,
|
|
3501
|
-
"worker_version_id": None,
|
|
3502
|
-
"worker_run_id": None,
|
|
3503
|
-
}
|
|
3504
|
-
]
|
|
3505
|
-
responses.add(
|
|
3506
|
-
responses.GET,
|
|
3507
|
-
"http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/parents/?worker_version=False",
|
|
3508
|
-
status=200,
|
|
3509
|
-
json={
|
|
3510
|
-
"count": 1,
|
|
3511
|
-
"next": None,
|
|
3512
|
-
"results": expected_parents,
|
|
3513
|
-
},
|
|
3514
|
-
)
|
|
3515
|
-
|
|
3516
|
-
with pytest.deprecated_call(
|
|
3517
|
-
match="`worker_version` usage is deprecated. Consider using `worker_run` instead."
|
|
3518
|
-
):
|
|
3519
|
-
for idx, parent in enumerate(
|
|
3520
|
-
mock_elements_worker.list_element_parents(element=elt, worker_version=False)
|
|
3521
|
-
):
|
|
3522
|
-
assert parent == expected_parents[idx]
|
|
3523
|
-
|
|
3524
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 1
|
|
3525
|
-
assert [
|
|
3526
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
3527
|
-
] == BASE_API_CALLS + [
|
|
3528
|
-
(
|
|
3529
|
-
"GET",
|
|
3530
|
-
"http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/parents/?worker_version=False",
|
|
3531
|
-
),
|
|
3532
|
-
]
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
def test_list_element_parents_manual_worker_run(responses, mock_elements_worker):
|
|
3536
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
3537
|
-
expected_parents = [
|
|
3538
|
-
{
|
|
3539
|
-
"id": "0000",
|
|
3540
|
-
"type": "page",
|
|
3541
|
-
"name": "Test",
|
|
3542
|
-
"corpus": {},
|
|
3543
|
-
"thumbnail_url": None,
|
|
3544
|
-
"zone": {},
|
|
3545
|
-
"best_classes": None,
|
|
3546
|
-
"has_children": None,
|
|
3547
|
-
"worker_version_id": None,
|
|
3548
|
-
"worker_run_id": None,
|
|
3549
|
-
}
|
|
3550
|
-
]
|
|
3551
|
-
responses.add(
|
|
3552
|
-
responses.GET,
|
|
3553
|
-
"http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/parents/?worker_run=False",
|
|
3554
|
-
status=200,
|
|
3555
|
-
json={
|
|
3556
|
-
"count": 1,
|
|
3557
|
-
"next": None,
|
|
3558
|
-
"results": expected_parents,
|
|
3559
|
-
},
|
|
3560
|
-
)
|
|
3561
|
-
|
|
3562
|
-
for idx, parent in enumerate(
|
|
3563
|
-
mock_elements_worker.list_element_parents(element=elt, worker_run=False)
|
|
3564
|
-
):
|
|
3565
|
-
assert parent == expected_parents[idx]
|
|
3566
|
-
|
|
3567
|
-
assert len(responses.calls) == len(BASE_API_CALLS) + 1
|
|
3568
|
-
assert [
|
|
3569
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
3570
|
-
] == BASE_API_CALLS + [
|
|
3571
|
-
(
|
|
3572
|
-
"GET",
|
|
3573
|
-
"http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/parents/?worker_run=False",
|
|
3574
|
-
),
|
|
3575
|
-
]
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
def test_list_element_parents_with_cache_unhandled_param(
|
|
3579
|
-
mock_elements_worker_with_cache,
|
|
3580
|
-
):
|
|
3581
|
-
elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
|
|
3582
|
-
|
|
3583
|
-
with pytest.raises(
|
|
3584
|
-
AssertionError,
|
|
3585
|
-
match="When using the local cache, you can only filter by 'type' and/or 'worker_version' and/or 'worker_run'",
|
|
3586
|
-
):
|
|
3587
|
-
mock_elements_worker_with_cache.list_element_parents(
|
|
3588
|
-
element=elt, with_corpus=True
|
|
3589
|
-
)
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
@pytest.mark.usefixtures("_mock_cached_elements")
|
|
3593
|
-
@pytest.mark.parametrize(
|
|
3594
|
-
("filters", "expected_id"),
|
|
3595
|
-
[
|
|
3596
|
-
# Filter on element
|
|
3597
|
-
(
|
|
3598
|
-
{
|
|
3599
|
-
"element": CachedElement(id="11111111-1111-1111-1111-111111111111"),
|
|
3600
|
-
},
|
|
3601
|
-
"12341234-1234-1234-1234-123412341234",
|
|
3602
|
-
),
|
|
3603
|
-
# Filter on element and double_page
|
|
3604
|
-
(
|
|
3605
|
-
{
|
|
3606
|
-
"element": CachedElement(id="22222222-2222-2222-2222-222222222222"),
|
|
3607
|
-
"type": "double_page",
|
|
3608
|
-
},
|
|
3609
|
-
"12341234-1234-1234-1234-123412341234",
|
|
3610
|
-
),
|
|
3611
|
-
# Filter on element and worker run
|
|
3612
|
-
(
|
|
3613
|
-
{
|
|
3614
|
-
"element": CachedElement(id="22222222-2222-2222-2222-222222222222"),
|
|
3615
|
-
"worker_run": "56785678-5678-5678-5678-567856785678",
|
|
3616
|
-
},
|
|
3617
|
-
"12341234-1234-1234-1234-123412341234",
|
|
3618
|
-
),
|
|
3619
|
-
# Filter on element, manual worker run
|
|
3620
|
-
(
|
|
3621
|
-
{
|
|
3622
|
-
"element": CachedElement(id="12341234-1234-1234-1234-123412341234"),
|
|
3623
|
-
"worker_run": False,
|
|
3624
|
-
},
|
|
3625
|
-
"99999999-9999-9999-9999-999999999999",
|
|
3626
|
-
),
|
|
3627
|
-
],
|
|
3628
|
-
)
|
|
3629
|
-
def test_list_element_parents_with_cache(
|
|
3630
|
-
responses,
|
|
3631
|
-
mock_elements_worker_with_cache,
|
|
3632
|
-
filters,
|
|
3633
|
-
expected_id,
|
|
3634
|
-
):
|
|
3635
|
-
# Check we have 5 elements already present in database
|
|
3636
|
-
assert CachedElement.select().count() == 5
|
|
3637
|
-
|
|
3638
|
-
# Query database through cache
|
|
3639
|
-
elements = mock_elements_worker_with_cache.list_element_parents(**filters)
|
|
3640
|
-
assert elements.count() == 1
|
|
3641
|
-
for parent in elements.order_by("id"):
|
|
3642
|
-
assert parent.id == UUID(expected_id)
|
|
3643
|
-
|
|
3644
|
-
# Check the worker never hits the API for elements
|
|
3645
|
-
assert len(responses.calls) == len(BASE_API_CALLS)
|
|
3646
|
-
assert [
|
|
3647
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
3648
|
-
] == BASE_API_CALLS
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
@pytest.mark.usefixtures("_mock_cached_elements")
|
|
3652
|
-
@pytest.mark.parametrize(
|
|
3653
|
-
("filters", "expected_id"),
|
|
3654
|
-
[
|
|
3655
|
-
# Filter on element and worker version
|
|
3656
|
-
(
|
|
3657
|
-
{
|
|
3658
|
-
"element": CachedElement(id="33333333-3333-3333-3333-333333333333"),
|
|
3659
|
-
"worker_version": "56785678-5678-5678-5678-567856785678",
|
|
3660
|
-
},
|
|
3661
|
-
"12341234-1234-1234-1234-123412341234",
|
|
3662
|
-
),
|
|
3663
|
-
# Filter on element, type double_page and worker version
|
|
3664
|
-
(
|
|
3665
|
-
{
|
|
3666
|
-
"element": CachedElement(id="11111111-1111-1111-1111-111111111111"),
|
|
3667
|
-
"type": "double_page",
|
|
3668
|
-
"worker_version": "56785678-5678-5678-5678-567856785678",
|
|
3669
|
-
},
|
|
3670
|
-
"12341234-1234-1234-1234-123412341234",
|
|
3671
|
-
),
|
|
3672
|
-
# Filter on element, manual worker version
|
|
3673
|
-
(
|
|
3674
|
-
{
|
|
3675
|
-
"element": CachedElement(id="12341234-1234-1234-1234-123412341234"),
|
|
3676
|
-
"worker_version": False,
|
|
3677
|
-
},
|
|
3678
|
-
"99999999-9999-9999-9999-999999999999",
|
|
3679
|
-
),
|
|
3680
|
-
],
|
|
3681
|
-
)
|
|
3682
|
-
def test_list_element_parents_with_cache_deprecation(
|
|
3683
|
-
responses,
|
|
3684
|
-
mock_elements_worker_with_cache,
|
|
3685
|
-
filters,
|
|
3686
|
-
expected_id,
|
|
3687
|
-
):
|
|
3688
|
-
# Check we have 5 elements already present in database
|
|
3689
|
-
assert CachedElement.select().count() == 5
|
|
3690
|
-
|
|
3691
|
-
with pytest.deprecated_call(
|
|
3692
|
-
match="`worker_version` usage is deprecated. Consider using `worker_run` instead."
|
|
3693
|
-
):
|
|
3694
|
-
# Query database through cache
|
|
3695
|
-
elements = mock_elements_worker_with_cache.list_element_parents(**filters)
|
|
3696
|
-
assert elements.count() == 1
|
|
3697
|
-
for parent in elements.order_by("id"):
|
|
3698
|
-
assert parent.id == UUID(expected_id)
|
|
3699
|
-
|
|
3700
|
-
# Check the worker never hits the API for elements
|
|
3701
|
-
assert len(responses.calls) == len(BASE_API_CALLS)
|
|
3702
|
-
assert [
|
|
3703
|
-
(call.request.method, call.request.url) for call in responses.calls
|
|
3704
|
-
] == BASE_API_CALLS
|