arkindex-base-worker 0.4.0rc3__py3-none-any.whl → 0.4.0rc5__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.0rc5.dist-info}/METADATA +15 -14
- {arkindex_base_worker-0.4.0rc3.dist-info → arkindex_base_worker-0.4.0rc5.dist-info}/RECORD +24 -16
- {arkindex_base_worker-0.4.0rc3.dist-info → arkindex_base_worker-0.4.0rc5.dist-info}/WHEEL +1 -1
- arkindex_worker/cache.py +1 -1
- arkindex_worker/worker/__init__.py +6 -2
- arkindex_worker/worker/entity.py +8 -19
- arkindex_worker/worker/process.py +5 -0
- 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} +42 -245
- 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.0rc5.dist-info}/LICENSE +0 -0
- {arkindex_base_worker-0.4.0rc3.dist-info → arkindex_base_worker-0.4.0rc5.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,715 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import re
|
|
3
|
+
from uuid import UUID
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from arkindex.exceptions import ErrorResponse
|
|
8
|
+
from arkindex_worker.cache import (
|
|
9
|
+
CachedElement,
|
|
10
|
+
CachedImage,
|
|
11
|
+
)
|
|
12
|
+
from arkindex_worker.models import Element
|
|
13
|
+
from arkindex_worker.utils import DEFAULT_BATCH_SIZE
|
|
14
|
+
|
|
15
|
+
from . import BASE_API_CALLS
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_create_elements_wrong_parent(mock_elements_worker):
|
|
19
|
+
with pytest.raises(
|
|
20
|
+
TypeError, match="Parent element should be an Element or CachedElement instance"
|
|
21
|
+
):
|
|
22
|
+
mock_elements_worker.create_elements(
|
|
23
|
+
parent=None,
|
|
24
|
+
elements=[],
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
with pytest.raises(
|
|
28
|
+
TypeError, match="Parent element should be an Element or CachedElement instance"
|
|
29
|
+
):
|
|
30
|
+
mock_elements_worker.create_elements(
|
|
31
|
+
parent="not element type",
|
|
32
|
+
elements=[],
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_create_elements_no_zone(mock_elements_worker):
|
|
37
|
+
elt = Element({"zone": None})
|
|
38
|
+
with pytest.raises(
|
|
39
|
+
AssertionError, match="create_elements cannot be used on parents without zones"
|
|
40
|
+
):
|
|
41
|
+
mock_elements_worker.create_elements(
|
|
42
|
+
parent=elt,
|
|
43
|
+
elements=None,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
elt = CachedElement(
|
|
47
|
+
id="11111111-1111-1111-1111-1111111111", name="blah", type="blah"
|
|
48
|
+
)
|
|
49
|
+
with pytest.raises(
|
|
50
|
+
AssertionError, match="create_elements cannot be used on parents without images"
|
|
51
|
+
):
|
|
52
|
+
mock_elements_worker.create_elements(
|
|
53
|
+
parent=elt,
|
|
54
|
+
elements=None,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_create_elements_wrong_elements(mock_elements_worker):
|
|
59
|
+
elt = Element({"zone": {"image": {"id": "image_id"}}})
|
|
60
|
+
|
|
61
|
+
with pytest.raises(
|
|
62
|
+
AssertionError, match="elements shouldn't be null and should be of type list"
|
|
63
|
+
):
|
|
64
|
+
mock_elements_worker.create_elements(
|
|
65
|
+
parent=elt,
|
|
66
|
+
elements=None,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
with pytest.raises(
|
|
70
|
+
AssertionError, match="elements shouldn't be null and should be of type list"
|
|
71
|
+
):
|
|
72
|
+
mock_elements_worker.create_elements(
|
|
73
|
+
parent=elt,
|
|
74
|
+
elements="not a list",
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def test_create_elements_wrong_elements_instance(mock_elements_worker):
|
|
79
|
+
elt = Element({"zone": {"image": {"id": "image_id"}}})
|
|
80
|
+
|
|
81
|
+
with pytest.raises(
|
|
82
|
+
AssertionError, match="Element at index 0 in elements: Should be of type dict"
|
|
83
|
+
):
|
|
84
|
+
mock_elements_worker.create_elements(
|
|
85
|
+
parent=elt,
|
|
86
|
+
elements=["not a dict"],
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def test_create_elements_wrong_elements_name(mock_elements_worker):
|
|
91
|
+
elt = Element({"zone": {"image": {"id": "image_id"}}})
|
|
92
|
+
|
|
93
|
+
with pytest.raises(
|
|
94
|
+
AssertionError,
|
|
95
|
+
match="Element at index 0 in elements: name shouldn't be null and should be of type str",
|
|
96
|
+
):
|
|
97
|
+
mock_elements_worker.create_elements(
|
|
98
|
+
parent=elt,
|
|
99
|
+
elements=[
|
|
100
|
+
{
|
|
101
|
+
"name": None,
|
|
102
|
+
"type": "something",
|
|
103
|
+
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
104
|
+
}
|
|
105
|
+
],
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
with pytest.raises(
|
|
109
|
+
AssertionError,
|
|
110
|
+
match="Element at index 0 in elements: name shouldn't be null and should be of type str",
|
|
111
|
+
):
|
|
112
|
+
mock_elements_worker.create_elements(
|
|
113
|
+
parent=elt,
|
|
114
|
+
elements=[
|
|
115
|
+
{
|
|
116
|
+
"name": 1234,
|
|
117
|
+
"type": "something",
|
|
118
|
+
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
119
|
+
}
|
|
120
|
+
],
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def test_create_elements_wrong_elements_type(mock_elements_worker):
|
|
125
|
+
elt = Element({"zone": {"image": {"id": "image_id"}}})
|
|
126
|
+
|
|
127
|
+
with pytest.raises(
|
|
128
|
+
AssertionError,
|
|
129
|
+
match="Element at index 0 in elements: type shouldn't be null and should be of type str",
|
|
130
|
+
):
|
|
131
|
+
mock_elements_worker.create_elements(
|
|
132
|
+
parent=elt,
|
|
133
|
+
elements=[
|
|
134
|
+
{
|
|
135
|
+
"name": "0",
|
|
136
|
+
"type": None,
|
|
137
|
+
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
138
|
+
}
|
|
139
|
+
],
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
with pytest.raises(
|
|
143
|
+
AssertionError,
|
|
144
|
+
match="Element at index 0 in elements: type shouldn't be null and should be of type str",
|
|
145
|
+
):
|
|
146
|
+
mock_elements_worker.create_elements(
|
|
147
|
+
parent=elt,
|
|
148
|
+
elements=[
|
|
149
|
+
{
|
|
150
|
+
"name": "0",
|
|
151
|
+
"type": 1234,
|
|
152
|
+
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
153
|
+
}
|
|
154
|
+
],
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def test_create_elements_wrong_elements_polygon(mock_elements_worker):
|
|
159
|
+
elt = Element({"zone": {"image": {"id": "image_id"}}})
|
|
160
|
+
|
|
161
|
+
with pytest.raises(
|
|
162
|
+
AssertionError,
|
|
163
|
+
match="Element at index 0 in elements: polygon shouldn't be null and should be of type list",
|
|
164
|
+
):
|
|
165
|
+
mock_elements_worker.create_elements(
|
|
166
|
+
parent=elt,
|
|
167
|
+
elements=[
|
|
168
|
+
{
|
|
169
|
+
"name": "0",
|
|
170
|
+
"type": "something",
|
|
171
|
+
"polygon": None,
|
|
172
|
+
}
|
|
173
|
+
],
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
with pytest.raises(
|
|
177
|
+
AssertionError,
|
|
178
|
+
match="Element at index 0 in elements: polygon shouldn't be null and should be of type list",
|
|
179
|
+
):
|
|
180
|
+
mock_elements_worker.create_elements(
|
|
181
|
+
parent=elt,
|
|
182
|
+
elements=[
|
|
183
|
+
{
|
|
184
|
+
"name": "0",
|
|
185
|
+
"type": "something",
|
|
186
|
+
"polygon": "not a polygon",
|
|
187
|
+
}
|
|
188
|
+
],
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
with pytest.raises(
|
|
192
|
+
AssertionError,
|
|
193
|
+
match="Element at index 0 in elements: polygon should have at least three points",
|
|
194
|
+
):
|
|
195
|
+
mock_elements_worker.create_elements(
|
|
196
|
+
parent=elt,
|
|
197
|
+
elements=[
|
|
198
|
+
{
|
|
199
|
+
"name": "0",
|
|
200
|
+
"type": "something",
|
|
201
|
+
"polygon": [[1, 1], [2, 2]],
|
|
202
|
+
}
|
|
203
|
+
],
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
with pytest.raises(
|
|
207
|
+
AssertionError,
|
|
208
|
+
match="Element at index 0 in elements: polygon points should be lists of two items",
|
|
209
|
+
):
|
|
210
|
+
mock_elements_worker.create_elements(
|
|
211
|
+
parent=elt,
|
|
212
|
+
elements=[
|
|
213
|
+
{
|
|
214
|
+
"name": "0",
|
|
215
|
+
"type": "something",
|
|
216
|
+
"polygon": [[1, 1, 1], [2, 2, 1], [2, 1, 1], [1, 2, 1]],
|
|
217
|
+
}
|
|
218
|
+
],
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
with pytest.raises(
|
|
222
|
+
AssertionError,
|
|
223
|
+
match="Element at index 0 in elements: polygon points should be lists of two items",
|
|
224
|
+
):
|
|
225
|
+
mock_elements_worker.create_elements(
|
|
226
|
+
parent=elt,
|
|
227
|
+
elements=[
|
|
228
|
+
{
|
|
229
|
+
"name": "0",
|
|
230
|
+
"type": "something",
|
|
231
|
+
"polygon": [[1], [2], [2], [1]],
|
|
232
|
+
}
|
|
233
|
+
],
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
with pytest.raises(
|
|
237
|
+
AssertionError,
|
|
238
|
+
match="Element at index 0 in elements: polygon points should be lists of two numbers",
|
|
239
|
+
):
|
|
240
|
+
mock_elements_worker.create_elements(
|
|
241
|
+
parent=elt,
|
|
242
|
+
elements=[
|
|
243
|
+
{
|
|
244
|
+
"name": "0",
|
|
245
|
+
"type": "something",
|
|
246
|
+
"polygon": [["not a coord", 1], [2, 2], [2, 1], [1, 2]],
|
|
247
|
+
}
|
|
248
|
+
],
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
@pytest.mark.parametrize("confidence", ["lol", "0.2", -1.0, 1.42, float("inf")])
|
|
253
|
+
def test_create_elements_wrong_elements_confidence(mock_elements_worker, confidence):
|
|
254
|
+
with pytest.raises(
|
|
255
|
+
AssertionError,
|
|
256
|
+
match=re.escape(
|
|
257
|
+
"Element at index 0 in elements: confidence should be None or a float in [0..1] range"
|
|
258
|
+
),
|
|
259
|
+
):
|
|
260
|
+
mock_elements_worker.create_elements(
|
|
261
|
+
parent=Element({"zone": {"image": {"id": "image_id"}}}),
|
|
262
|
+
elements=[
|
|
263
|
+
{
|
|
264
|
+
"name": "a",
|
|
265
|
+
"type": "something",
|
|
266
|
+
"polygon": [[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]],
|
|
267
|
+
"confidence": confidence,
|
|
268
|
+
}
|
|
269
|
+
],
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def test_create_elements_api_error(responses, mock_elements_worker):
|
|
274
|
+
elt = Element(
|
|
275
|
+
{
|
|
276
|
+
"id": "12341234-1234-1234-1234-123412341234",
|
|
277
|
+
"zone": {
|
|
278
|
+
"image": {
|
|
279
|
+
"id": "c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
|
|
280
|
+
"width": 42,
|
|
281
|
+
"height": 42,
|
|
282
|
+
"url": "http://aaaa",
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
}
|
|
286
|
+
)
|
|
287
|
+
responses.add(
|
|
288
|
+
responses.POST,
|
|
289
|
+
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
290
|
+
status=418,
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
with pytest.raises(ErrorResponse):
|
|
294
|
+
mock_elements_worker.create_elements(
|
|
295
|
+
parent=elt,
|
|
296
|
+
elements=[
|
|
297
|
+
{
|
|
298
|
+
"name": "0",
|
|
299
|
+
"type": "something",
|
|
300
|
+
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
301
|
+
}
|
|
302
|
+
],
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
assert len(responses.calls) == len(BASE_API_CALLS) + 1
|
|
306
|
+
assert [
|
|
307
|
+
(call.request.method, call.request.url) for call in responses.calls
|
|
308
|
+
] == BASE_API_CALLS + [
|
|
309
|
+
(
|
|
310
|
+
"POST",
|
|
311
|
+
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
312
|
+
)
|
|
313
|
+
]
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
@pytest.mark.parametrize("batch_size", [DEFAULT_BATCH_SIZE, 1])
|
|
317
|
+
def test_create_elements_cached_element(
|
|
318
|
+
batch_size, responses, mock_elements_worker_with_cache
|
|
319
|
+
):
|
|
320
|
+
image = CachedImage.create(
|
|
321
|
+
id=UUID("c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe"),
|
|
322
|
+
width=42,
|
|
323
|
+
height=42,
|
|
324
|
+
url="http://aaaa",
|
|
325
|
+
)
|
|
326
|
+
elt = CachedElement.create(
|
|
327
|
+
id=UUID("12341234-1234-1234-1234-123412341234"),
|
|
328
|
+
type="parent",
|
|
329
|
+
image_id=image.id,
|
|
330
|
+
polygon="[[0, 0], [0, 1000], [1000, 1000], [1000, 0], [0, 0]]",
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
if batch_size > 1:
|
|
334
|
+
responses.add(
|
|
335
|
+
responses.POST,
|
|
336
|
+
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
337
|
+
status=200,
|
|
338
|
+
json=[
|
|
339
|
+
{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"},
|
|
340
|
+
{"id": "5468c358-b9c4-499d-8b92-d6349c58e88d"},
|
|
341
|
+
],
|
|
342
|
+
)
|
|
343
|
+
else:
|
|
344
|
+
for elt_id in [
|
|
345
|
+
"497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
|
346
|
+
"5468c358-b9c4-499d-8b92-d6349c58e88d",
|
|
347
|
+
]:
|
|
348
|
+
responses.add(
|
|
349
|
+
responses.POST,
|
|
350
|
+
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
351
|
+
status=200,
|
|
352
|
+
json=[{"id": elt_id}],
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
created_ids = mock_elements_worker_with_cache.create_elements(
|
|
356
|
+
parent=elt,
|
|
357
|
+
elements=[
|
|
358
|
+
{
|
|
359
|
+
"name": "0",
|
|
360
|
+
"type": "something",
|
|
361
|
+
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
"name": "1",
|
|
365
|
+
"type": "something",
|
|
366
|
+
"polygon": [[4, 4], [5, 5], [5, 4], [4, 5]],
|
|
367
|
+
},
|
|
368
|
+
],
|
|
369
|
+
batch_size=batch_size,
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
bulk_api_calls = [
|
|
373
|
+
(
|
|
374
|
+
"POST",
|
|
375
|
+
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
376
|
+
)
|
|
377
|
+
]
|
|
378
|
+
if batch_size != DEFAULT_BATCH_SIZE:
|
|
379
|
+
bulk_api_calls.append(
|
|
380
|
+
(
|
|
381
|
+
"POST",
|
|
382
|
+
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
383
|
+
)
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
assert len(responses.calls) == len(BASE_API_CALLS) + len(bulk_api_calls)
|
|
387
|
+
assert [
|
|
388
|
+
(call.request.method, call.request.url) for call in responses.calls
|
|
389
|
+
] == BASE_API_CALLS + bulk_api_calls
|
|
390
|
+
|
|
391
|
+
first_elt = {
|
|
392
|
+
"name": "0",
|
|
393
|
+
"type": "something",
|
|
394
|
+
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
395
|
+
}
|
|
396
|
+
second_elt = {
|
|
397
|
+
"name": "1",
|
|
398
|
+
"type": "something",
|
|
399
|
+
"polygon": [[4, 4], [5, 5], [5, 4], [4, 5]],
|
|
400
|
+
}
|
|
401
|
+
empty_payload = {
|
|
402
|
+
"elements": [],
|
|
403
|
+
"worker_run_id": "56785678-5678-5678-5678-567856785678",
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
bodies = []
|
|
407
|
+
first_call_idx = None
|
|
408
|
+
if batch_size > 1:
|
|
409
|
+
first_call_idx = -1
|
|
410
|
+
bodies.append({**empty_payload, "elements": [first_elt, second_elt]})
|
|
411
|
+
else:
|
|
412
|
+
first_call_idx = -2
|
|
413
|
+
bodies.append({**empty_payload, "elements": [first_elt]})
|
|
414
|
+
bodies.append({**empty_payload, "elements": [second_elt]})
|
|
415
|
+
|
|
416
|
+
assert [
|
|
417
|
+
json.loads(bulk_call.request.body)
|
|
418
|
+
for bulk_call in responses.calls[first_call_idx:]
|
|
419
|
+
] == bodies
|
|
420
|
+
|
|
421
|
+
assert created_ids == [
|
|
422
|
+
{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"},
|
|
423
|
+
{"id": "5468c358-b9c4-499d-8b92-d6349c58e88d"},
|
|
424
|
+
]
|
|
425
|
+
|
|
426
|
+
# Check that created elements were properly stored in SQLite cache
|
|
427
|
+
assert list(CachedElement.select().order_by(CachedElement.id)) == [
|
|
428
|
+
elt,
|
|
429
|
+
CachedElement(
|
|
430
|
+
id=UUID("497f6eca-6276-4993-bfeb-53cbbbba6f08"),
|
|
431
|
+
parent_id=elt.id,
|
|
432
|
+
type="something",
|
|
433
|
+
image_id="c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
|
|
434
|
+
polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
435
|
+
worker_run_id=UUID("56785678-5678-5678-5678-567856785678"),
|
|
436
|
+
confidence=None,
|
|
437
|
+
),
|
|
438
|
+
CachedElement(
|
|
439
|
+
id=UUID("5468c358-b9c4-499d-8b92-d6349c58e88d"),
|
|
440
|
+
parent_id=elt.id,
|
|
441
|
+
type="something",
|
|
442
|
+
image_id="c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
|
|
443
|
+
polygon=[[4, 4], [5, 5], [5, 4], [4, 5]],
|
|
444
|
+
worker_run_id=UUID("56785678-5678-5678-5678-567856785678"),
|
|
445
|
+
confidence=None,
|
|
446
|
+
),
|
|
447
|
+
]
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
@pytest.mark.parametrize("batch_size", [DEFAULT_BATCH_SIZE, 1])
|
|
451
|
+
def test_create_elements(
|
|
452
|
+
batch_size, responses, mock_elements_worker_with_cache, tmp_path
|
|
453
|
+
):
|
|
454
|
+
elt = Element(
|
|
455
|
+
{
|
|
456
|
+
"id": "12341234-1234-1234-1234-123412341234",
|
|
457
|
+
"zone": {
|
|
458
|
+
"image": {
|
|
459
|
+
"id": "c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
|
|
460
|
+
"width": 42,
|
|
461
|
+
"height": 42,
|
|
462
|
+
"url": "http://aaaa",
|
|
463
|
+
}
|
|
464
|
+
},
|
|
465
|
+
}
|
|
466
|
+
)
|
|
467
|
+
|
|
468
|
+
if batch_size > 1:
|
|
469
|
+
responses.add(
|
|
470
|
+
responses.POST,
|
|
471
|
+
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
472
|
+
status=200,
|
|
473
|
+
json=[
|
|
474
|
+
{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"},
|
|
475
|
+
{"id": "5468c358-b9c4-499d-8b92-d6349c58e88d"},
|
|
476
|
+
],
|
|
477
|
+
)
|
|
478
|
+
else:
|
|
479
|
+
for elt_id in [
|
|
480
|
+
"497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
|
481
|
+
"5468c358-b9c4-499d-8b92-d6349c58e88d",
|
|
482
|
+
]:
|
|
483
|
+
responses.add(
|
|
484
|
+
responses.POST,
|
|
485
|
+
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
486
|
+
status=200,
|
|
487
|
+
json=[{"id": elt_id}],
|
|
488
|
+
)
|
|
489
|
+
|
|
490
|
+
created_ids = mock_elements_worker_with_cache.create_elements(
|
|
491
|
+
parent=elt,
|
|
492
|
+
elements=[
|
|
493
|
+
{
|
|
494
|
+
"name": "0",
|
|
495
|
+
"type": "something",
|
|
496
|
+
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
497
|
+
},
|
|
498
|
+
{
|
|
499
|
+
"name": "1",
|
|
500
|
+
"type": "something",
|
|
501
|
+
"polygon": [[4, 4], [5, 5], [5, 4], [4, 5]],
|
|
502
|
+
},
|
|
503
|
+
],
|
|
504
|
+
batch_size=batch_size,
|
|
505
|
+
)
|
|
506
|
+
|
|
507
|
+
bulk_api_calls = [
|
|
508
|
+
(
|
|
509
|
+
"POST",
|
|
510
|
+
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
511
|
+
)
|
|
512
|
+
]
|
|
513
|
+
if batch_size != DEFAULT_BATCH_SIZE:
|
|
514
|
+
bulk_api_calls.append(
|
|
515
|
+
(
|
|
516
|
+
"POST",
|
|
517
|
+
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
518
|
+
)
|
|
519
|
+
)
|
|
520
|
+
|
|
521
|
+
assert len(responses.calls) == len(BASE_API_CALLS) + len(bulk_api_calls)
|
|
522
|
+
assert [
|
|
523
|
+
(call.request.method, call.request.url) for call in responses.calls
|
|
524
|
+
] == BASE_API_CALLS + bulk_api_calls
|
|
525
|
+
|
|
526
|
+
first_elt = {
|
|
527
|
+
"name": "0",
|
|
528
|
+
"type": "something",
|
|
529
|
+
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
530
|
+
}
|
|
531
|
+
second_elt = {
|
|
532
|
+
"name": "1",
|
|
533
|
+
"type": "something",
|
|
534
|
+
"polygon": [[4, 4], [5, 5], [5, 4], [4, 5]],
|
|
535
|
+
}
|
|
536
|
+
empty_payload = {
|
|
537
|
+
"elements": [],
|
|
538
|
+
"worker_run_id": "56785678-5678-5678-5678-567856785678",
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
bodies = []
|
|
542
|
+
first_call_idx = None
|
|
543
|
+
if batch_size > 1:
|
|
544
|
+
first_call_idx = -1
|
|
545
|
+
bodies.append({**empty_payload, "elements": [first_elt, second_elt]})
|
|
546
|
+
else:
|
|
547
|
+
first_call_idx = -2
|
|
548
|
+
bodies.append({**empty_payload, "elements": [first_elt]})
|
|
549
|
+
bodies.append({**empty_payload, "elements": [second_elt]})
|
|
550
|
+
|
|
551
|
+
assert [
|
|
552
|
+
json.loads(bulk_call.request.body)
|
|
553
|
+
for bulk_call in responses.calls[first_call_idx:]
|
|
554
|
+
] == bodies
|
|
555
|
+
|
|
556
|
+
assert created_ids == [
|
|
557
|
+
{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"},
|
|
558
|
+
{"id": "5468c358-b9c4-499d-8b92-d6349c58e88d"},
|
|
559
|
+
]
|
|
560
|
+
|
|
561
|
+
# Check that created elements were properly stored in SQLite cache
|
|
562
|
+
assert (tmp_path / "db.sqlite").is_file()
|
|
563
|
+
|
|
564
|
+
assert list(CachedElement.select()) == [
|
|
565
|
+
CachedElement(
|
|
566
|
+
id=UUID("497f6eca-6276-4993-bfeb-53cbbbba6f08"),
|
|
567
|
+
parent_id=UUID("12341234-1234-1234-1234-123412341234"),
|
|
568
|
+
type="something",
|
|
569
|
+
image_id="c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
|
|
570
|
+
polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
571
|
+
worker_run_id=UUID("56785678-5678-5678-5678-567856785678"),
|
|
572
|
+
confidence=None,
|
|
573
|
+
),
|
|
574
|
+
CachedElement(
|
|
575
|
+
id=UUID("5468c358-b9c4-499d-8b92-d6349c58e88d"),
|
|
576
|
+
parent_id=UUID("12341234-1234-1234-1234-123412341234"),
|
|
577
|
+
type="something",
|
|
578
|
+
image_id="c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
|
|
579
|
+
polygon=[[4, 4], [5, 5], [5, 4], [4, 5]],
|
|
580
|
+
worker_run_id=UUID("56785678-5678-5678-5678-567856785678"),
|
|
581
|
+
confidence=None,
|
|
582
|
+
),
|
|
583
|
+
]
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
def test_create_elements_confidence(
|
|
587
|
+
responses, mock_elements_worker_with_cache, tmp_path
|
|
588
|
+
):
|
|
589
|
+
elt = Element(
|
|
590
|
+
{
|
|
591
|
+
"id": "12341234-1234-1234-1234-123412341234",
|
|
592
|
+
"zone": {
|
|
593
|
+
"image": {
|
|
594
|
+
"id": "c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
|
|
595
|
+
"width": 42,
|
|
596
|
+
"height": 42,
|
|
597
|
+
"url": "http://aaaa",
|
|
598
|
+
}
|
|
599
|
+
},
|
|
600
|
+
}
|
|
601
|
+
)
|
|
602
|
+
responses.add(
|
|
603
|
+
responses.POST,
|
|
604
|
+
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
605
|
+
status=200,
|
|
606
|
+
json=[{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"}],
|
|
607
|
+
)
|
|
608
|
+
|
|
609
|
+
created_ids = mock_elements_worker_with_cache.create_elements(
|
|
610
|
+
parent=elt,
|
|
611
|
+
elements=[
|
|
612
|
+
{
|
|
613
|
+
"name": "0",
|
|
614
|
+
"type": "something",
|
|
615
|
+
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
616
|
+
"confidence": 0.42,
|
|
617
|
+
}
|
|
618
|
+
],
|
|
619
|
+
)
|
|
620
|
+
|
|
621
|
+
assert len(responses.calls) == len(BASE_API_CALLS) + 1
|
|
622
|
+
assert [
|
|
623
|
+
(call.request.method, call.request.url) for call in responses.calls
|
|
624
|
+
] == BASE_API_CALLS + [
|
|
625
|
+
(
|
|
626
|
+
"POST",
|
|
627
|
+
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
628
|
+
),
|
|
629
|
+
]
|
|
630
|
+
assert json.loads(responses.calls[-1].request.body) == {
|
|
631
|
+
"elements": [
|
|
632
|
+
{
|
|
633
|
+
"name": "0",
|
|
634
|
+
"type": "something",
|
|
635
|
+
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
636
|
+
"confidence": 0.42,
|
|
637
|
+
}
|
|
638
|
+
],
|
|
639
|
+
"worker_run_id": "56785678-5678-5678-5678-567856785678",
|
|
640
|
+
}
|
|
641
|
+
assert created_ids == [{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"}]
|
|
642
|
+
|
|
643
|
+
# Check that created elements were properly stored in SQLite cache
|
|
644
|
+
assert (tmp_path / "db.sqlite").is_file()
|
|
645
|
+
|
|
646
|
+
assert list(CachedElement.select()) == [
|
|
647
|
+
CachedElement(
|
|
648
|
+
id=UUID("497f6eca-6276-4993-bfeb-53cbbbba6f08"),
|
|
649
|
+
parent_id=UUID("12341234-1234-1234-1234-123412341234"),
|
|
650
|
+
type="something",
|
|
651
|
+
image_id="c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
|
|
652
|
+
polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
653
|
+
worker_run_id=UUID("56785678-5678-5678-5678-567856785678"),
|
|
654
|
+
confidence=0.42,
|
|
655
|
+
)
|
|
656
|
+
]
|
|
657
|
+
|
|
658
|
+
|
|
659
|
+
def test_create_elements_integrity_error(
|
|
660
|
+
responses, mock_elements_worker_with_cache, caplog
|
|
661
|
+
):
|
|
662
|
+
elt = Element(
|
|
663
|
+
{
|
|
664
|
+
"id": "12341234-1234-1234-1234-123412341234",
|
|
665
|
+
"zone": {
|
|
666
|
+
"image": {
|
|
667
|
+
"id": "c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
|
|
668
|
+
"width": 42,
|
|
669
|
+
"height": 42,
|
|
670
|
+
"url": "http://aaaa",
|
|
671
|
+
}
|
|
672
|
+
},
|
|
673
|
+
}
|
|
674
|
+
)
|
|
675
|
+
responses.add(
|
|
676
|
+
responses.POST,
|
|
677
|
+
"http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
|
|
678
|
+
status=200,
|
|
679
|
+
json=[
|
|
680
|
+
# Duplicate IDs, which will cause an IntegrityError when stored in the cache
|
|
681
|
+
{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"},
|
|
682
|
+
{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"},
|
|
683
|
+
],
|
|
684
|
+
)
|
|
685
|
+
|
|
686
|
+
elements = [
|
|
687
|
+
{
|
|
688
|
+
"name": "0",
|
|
689
|
+
"type": "something",
|
|
690
|
+
"polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
|
|
691
|
+
},
|
|
692
|
+
{
|
|
693
|
+
"name": "1",
|
|
694
|
+
"type": "something",
|
|
695
|
+
"polygon": [[1, 1], [3, 3], [3, 1], [1, 3]],
|
|
696
|
+
},
|
|
697
|
+
]
|
|
698
|
+
|
|
699
|
+
created_ids = mock_elements_worker_with_cache.create_elements(
|
|
700
|
+
parent=elt,
|
|
701
|
+
elements=elements,
|
|
702
|
+
)
|
|
703
|
+
|
|
704
|
+
assert created_ids == [
|
|
705
|
+
{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"},
|
|
706
|
+
{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"},
|
|
707
|
+
]
|
|
708
|
+
|
|
709
|
+
assert len(caplog.records) == 3
|
|
710
|
+
assert caplog.records[-1].levelname == "WARNING"
|
|
711
|
+
assert caplog.records[-1].message.startswith(
|
|
712
|
+
"Couldn't save created elements in local cache:"
|
|
713
|
+
)
|
|
714
|
+
|
|
715
|
+
assert list(CachedElement.select()) == []
|