arkindex-base-worker 0.3.7rc5__py3-none-any.whl → 0.5.0a1__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.
Files changed (60) hide show
  1. {arkindex_base_worker-0.3.7rc5.dist-info → arkindex_base_worker-0.5.0a1.dist-info}/METADATA +18 -19
  2. arkindex_base_worker-0.5.0a1.dist-info/RECORD +61 -0
  3. {arkindex_base_worker-0.3.7rc5.dist-info → arkindex_base_worker-0.5.0a1.dist-info}/WHEEL +1 -1
  4. {arkindex_base_worker-0.3.7rc5.dist-info → arkindex_base_worker-0.5.0a1.dist-info}/top_level.txt +2 -0
  5. arkindex_worker/cache.py +1 -1
  6. arkindex_worker/image.py +167 -2
  7. arkindex_worker/models.py +18 -0
  8. arkindex_worker/utils.py +98 -4
  9. arkindex_worker/worker/__init__.py +117 -218
  10. arkindex_worker/worker/base.py +39 -46
  11. arkindex_worker/worker/classification.py +34 -18
  12. arkindex_worker/worker/corpus.py +86 -0
  13. arkindex_worker/worker/dataset.py +89 -26
  14. arkindex_worker/worker/element.py +352 -91
  15. arkindex_worker/worker/entity.py +13 -11
  16. arkindex_worker/worker/image.py +21 -0
  17. arkindex_worker/worker/metadata.py +26 -16
  18. arkindex_worker/worker/process.py +92 -0
  19. arkindex_worker/worker/task.py +5 -4
  20. arkindex_worker/worker/training.py +25 -10
  21. arkindex_worker/worker/transcription.py +89 -68
  22. arkindex_worker/worker/version.py +3 -1
  23. hooks/pre_gen_project.py +3 -0
  24. tests/__init__.py +8 -0
  25. tests/conftest.py +47 -58
  26. tests/test_base_worker.py +212 -12
  27. tests/test_dataset_worker.py +294 -437
  28. tests/test_elements_worker/{test_classifications.py → test_classification.py} +216 -100
  29. tests/test_elements_worker/test_cli.py +3 -11
  30. tests/test_elements_worker/test_corpus.py +168 -0
  31. tests/test_elements_worker/test_dataset.py +106 -157
  32. tests/test_elements_worker/test_element.py +427 -0
  33. tests/test_elements_worker/test_element_create_multiple.py +715 -0
  34. tests/test_elements_worker/test_element_create_single.py +528 -0
  35. tests/test_elements_worker/test_element_list_children.py +969 -0
  36. tests/test_elements_worker/test_element_list_parents.py +530 -0
  37. tests/test_elements_worker/{test_entities.py → test_entity_create.py} +37 -195
  38. tests/test_elements_worker/test_entity_list_and_check.py +160 -0
  39. tests/test_elements_worker/test_image.py +66 -0
  40. tests/test_elements_worker/test_metadata.py +252 -161
  41. tests/test_elements_worker/test_process.py +89 -0
  42. tests/test_elements_worker/test_task.py +8 -18
  43. tests/test_elements_worker/test_training.py +17 -8
  44. tests/test_elements_worker/test_transcription_create.py +873 -0
  45. tests/test_elements_worker/test_transcription_create_with_elements.py +951 -0
  46. tests/test_elements_worker/test_transcription_list.py +450 -0
  47. tests/test_elements_worker/test_version.py +60 -0
  48. tests/test_elements_worker/test_worker.py +578 -293
  49. tests/test_image.py +542 -209
  50. tests/test_merge.py +1 -2
  51. tests/test_utils.py +89 -4
  52. worker-demo/tests/__init__.py +0 -0
  53. worker-demo/tests/conftest.py +32 -0
  54. worker-demo/tests/test_worker.py +12 -0
  55. worker-demo/worker_demo/__init__.py +6 -0
  56. worker-demo/worker_demo/worker.py +19 -0
  57. arkindex_base_worker-0.3.7rc5.dist-info/RECORD +0 -41
  58. tests/test_elements_worker/test_elements.py +0 -2713
  59. tests/test_elements_worker/test_transcriptions.py +0 -2119
  60. {arkindex_base_worker-0.3.7rc5.dist-info → arkindex_base_worker-0.5.0a1.dist-info}/LICENSE +0 -0
@@ -1,2713 +0,0 @@
1
- import json
2
- import re
3
- from argparse import Namespace
4
- from uuid import UUID
5
-
6
- import pytest
7
- from apistar.exceptions import ErrorResponse
8
- from responses import matchers
9
-
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.worker import ElementsWorker
19
- from arkindex_worker.worker.element import MissingTypeError
20
-
21
- from . import BASE_API_CALLS
22
-
23
-
24
- def test_check_required_types_argument_types(mock_elements_worker):
25
- with pytest.raises(
26
- AssertionError, match="At least one element type slug is required."
27
- ):
28
- mock_elements_worker.check_required_types()
29
-
30
- with pytest.raises(AssertionError, match="Element type slugs must be strings."):
31
- mock_elements_worker.check_required_types("lol", 42)
32
-
33
-
34
- def test_check_required_types(responses, mock_elements_worker):
35
- corpus_id = "11111111-1111-1111-1111-111111111111"
36
- responses.add(
37
- responses.GET,
38
- f"http://testserver/api/v1/corpus/{corpus_id}/",
39
- json={
40
- "id": corpus_id,
41
- "name": "Some Corpus",
42
- "types": [{"slug": "folder"}, {"slug": "page"}],
43
- },
44
- )
45
- mock_elements_worker.setup_api_client()
46
-
47
- assert mock_elements_worker.check_required_types("page")
48
- assert mock_elements_worker.check_required_types("page", "folder")
49
-
50
- with pytest.raises(
51
- MissingTypeError,
52
- match=re.escape(
53
- "Element type(s) act, text_line were not found in the Some Corpus corpus (11111111-1111-1111-1111-111111111111)."
54
- ),
55
- ):
56
- assert mock_elements_worker.check_required_types("page", "text_line", "act")
57
-
58
-
59
- def test_create_missing_types(responses, mock_elements_worker):
60
- corpus_id = "11111111-1111-1111-1111-111111111111"
61
-
62
- responses.add(
63
- responses.GET,
64
- f"http://testserver/api/v1/corpus/{corpus_id}/",
65
- json={
66
- "id": corpus_id,
67
- "name": "Some Corpus",
68
- "types": [{"slug": "folder"}, {"slug": "page"}],
69
- },
70
- )
71
- responses.add(
72
- responses.POST,
73
- "http://testserver/api/v1/elements/type/",
74
- match=[
75
- matchers.json_params_matcher(
76
- {
77
- "slug": "text_line",
78
- "display_name": "text_line",
79
- "folder": False,
80
- "corpus": corpus_id,
81
- }
82
- )
83
- ],
84
- )
85
- responses.add(
86
- responses.POST,
87
- "http://testserver/api/v1/elements/type/",
88
- match=[
89
- matchers.json_params_matcher(
90
- {
91
- "slug": "act",
92
- "display_name": "act",
93
- "folder": False,
94
- "corpus": corpus_id,
95
- }
96
- )
97
- ],
98
- )
99
- mock_elements_worker.setup_api_client()
100
-
101
- assert mock_elements_worker.check_required_types(
102
- "page", "text_line", "act", create_missing=True
103
- )
104
-
105
-
106
- def test_list_elements_elements_list_arg_wrong_type(
107
- monkeypatch, tmp_path, mock_elements_worker
108
- ):
109
- elements_path = tmp_path / "elements.json"
110
- elements_path.write_text("{}")
111
-
112
- monkeypatch.setenv("TASK_ELEMENTS", str(elements_path))
113
- worker = ElementsWorker()
114
- worker.configure()
115
-
116
- with pytest.raises(AssertionError, match="Elements list must be a list"):
117
- worker.list_elements()
118
-
119
-
120
- def test_list_elements_elements_list_arg_empty_list(
121
- monkeypatch, tmp_path, mock_elements_worker
122
- ):
123
- elements_path = tmp_path / "elements.json"
124
- elements_path.write_text("[]")
125
-
126
- monkeypatch.setenv("TASK_ELEMENTS", str(elements_path))
127
- worker = ElementsWorker()
128
- worker.configure()
129
-
130
- with pytest.raises(AssertionError, match="No elements in elements list"):
131
- worker.list_elements()
132
-
133
-
134
- def test_list_elements_elements_list_arg_missing_id(
135
- monkeypatch, tmp_path, mock_elements_worker
136
- ):
137
- elements_path = tmp_path / "elements.json"
138
- with elements_path.open("w") as f:
139
- json.dump([{"type": "volume"}], f)
140
-
141
- monkeypatch.setenv("TASK_ELEMENTS", str(elements_path))
142
- worker = ElementsWorker()
143
- worker.configure()
144
-
145
- elt_list = worker.list_elements()
146
-
147
- assert elt_list == []
148
-
149
-
150
- def test_list_elements_elements_list_arg(monkeypatch, tmp_path, mock_elements_worker):
151
- elements_path = tmp_path / "elements.json"
152
- with elements_path.open("w") as f:
153
- json.dump(
154
- [
155
- {"id": "volumeid", "type": "volume"},
156
- {"id": "pageid", "type": "page"},
157
- {"id": "actid", "type": "act"},
158
- {"id": "surfaceid", "type": "surface"},
159
- ],
160
- f,
161
- )
162
-
163
- monkeypatch.setenv("TASK_ELEMENTS", str(elements_path))
164
- worker = ElementsWorker()
165
- worker.configure()
166
-
167
- elt_list = worker.list_elements()
168
-
169
- assert elt_list == ["volumeid", "pageid", "actid", "surfaceid"]
170
-
171
-
172
- def test_list_elements_element_arg(mocker, mock_elements_worker):
173
- mocker.patch(
174
- "arkindex_worker.worker.base.argparse.ArgumentParser.parse_args",
175
- return_value=Namespace(
176
- element=["volumeid", "pageid"],
177
- verbose=False,
178
- elements_list=None,
179
- database=None,
180
- dev=False,
181
- ),
182
- )
183
-
184
- worker = ElementsWorker()
185
- worker.configure()
186
-
187
- elt_list = worker.list_elements()
188
-
189
- assert elt_list == ["volumeid", "pageid"]
190
-
191
-
192
- def test_list_elements_both_args_error(mocker, mock_elements_worker, tmp_path):
193
- elements_path = tmp_path / "elements.json"
194
- with elements_path.open("w") as f:
195
- json.dump(
196
- [
197
- {"id": "volumeid", "type": "volume"},
198
- {"id": "pageid", "type": "page"},
199
- {"id": "actid", "type": "act"},
200
- {"id": "surfaceid", "type": "surface"},
201
- ],
202
- f,
203
- )
204
- mocker.patch(
205
- "arkindex_worker.worker.base.argparse.ArgumentParser.parse_args",
206
- return_value=Namespace(
207
- element=["anotherid", "againanotherid"],
208
- verbose=False,
209
- elements_list=elements_path.open(),
210
- database=None,
211
- dev=False,
212
- ),
213
- )
214
-
215
- worker = ElementsWorker()
216
- worker.configure()
217
-
218
- with pytest.raises(
219
- AssertionError, match="elements-list and element CLI args shouldn't be both set"
220
- ):
221
- worker.list_elements()
222
-
223
-
224
- def test_database_arg(mocker, mock_elements_worker, tmp_path):
225
- database_path = tmp_path / "my_database.sqlite"
226
- init_cache_db(database_path)
227
- create_version_table()
228
-
229
- mocker.patch(
230
- "arkindex_worker.worker.base.argparse.ArgumentParser.parse_args",
231
- return_value=Namespace(
232
- element=["volumeid", "pageid"],
233
- verbose=False,
234
- elements_list=None,
235
- database=database_path,
236
- dev=False,
237
- ),
238
- )
239
-
240
- worker = ElementsWorker(support_cache=True)
241
- worker.configure()
242
-
243
- assert worker.use_cache is True
244
- assert worker.cache_path == database_path
245
-
246
-
247
- def test_database_arg_cache_missing_version_table(
248
- mocker, mock_elements_worker, tmp_path
249
- ):
250
- database_path = tmp_path / "my_database.sqlite"
251
- database_path.touch()
252
-
253
- mocker.patch(
254
- "arkindex_worker.worker.base.argparse.ArgumentParser.parse_args",
255
- return_value=Namespace(
256
- element=["volumeid", "pageid"],
257
- verbose=False,
258
- elements_list=None,
259
- database=database_path,
260
- dev=False,
261
- ),
262
- )
263
-
264
- worker = ElementsWorker(support_cache=True)
265
- with pytest.raises(
266
- AssertionError,
267
- match=f"The SQLite database {database_path} does not have the correct cache version, it should be {SQL_VERSION}",
268
- ):
269
- worker.configure()
270
-
271
-
272
- def test_load_corpus_classes_api_error(responses, mock_elements_worker):
273
- responses.add(
274
- responses.GET,
275
- "http://testserver/api/v1/corpus/11111111-1111-1111-1111-111111111111/classes/",
276
- status=500,
277
- )
278
-
279
- assert not mock_elements_worker.classes
280
- with pytest.raises(
281
- Exception, match="Stopping pagination as data will be incomplete"
282
- ):
283
- mock_elements_worker.load_corpus_classes()
284
-
285
- assert len(responses.calls) == len(BASE_API_CALLS) + 5
286
- assert [
287
- (call.request.method, call.request.url) for call in responses.calls
288
- ] == BASE_API_CALLS + [
289
- # We do 5 retries
290
- (
291
- "GET",
292
- "http://testserver/api/v1/corpus/11111111-1111-1111-1111-111111111111/classes/",
293
- ),
294
- (
295
- "GET",
296
- "http://testserver/api/v1/corpus/11111111-1111-1111-1111-111111111111/classes/",
297
- ),
298
- (
299
- "GET",
300
- "http://testserver/api/v1/corpus/11111111-1111-1111-1111-111111111111/classes/",
301
- ),
302
- (
303
- "GET",
304
- "http://testserver/api/v1/corpus/11111111-1111-1111-1111-111111111111/classes/",
305
- ),
306
- (
307
- "GET",
308
- "http://testserver/api/v1/corpus/11111111-1111-1111-1111-111111111111/classes/",
309
- ),
310
- ]
311
- assert not mock_elements_worker.classes
312
-
313
-
314
- def test_load_corpus_classes(responses, mock_elements_worker):
315
- responses.add(
316
- responses.GET,
317
- "http://testserver/api/v1/corpus/11111111-1111-1111-1111-111111111111/classes/",
318
- status=200,
319
- json={
320
- "count": 3,
321
- "next": None,
322
- "results": [
323
- {
324
- "id": "0000",
325
- "name": "good",
326
- },
327
- {
328
- "id": "1111",
329
- "name": "average",
330
- },
331
- {
332
- "id": "2222",
333
- "name": "bad",
334
- },
335
- ],
336
- },
337
- )
338
-
339
- assert not mock_elements_worker.classes
340
- mock_elements_worker.load_corpus_classes()
341
-
342
- assert len(responses.calls) == len(BASE_API_CALLS) + 1
343
- assert [
344
- (call.request.method, call.request.url) for call in responses.calls
345
- ] == BASE_API_CALLS + [
346
- (
347
- "GET",
348
- "http://testserver/api/v1/corpus/11111111-1111-1111-1111-111111111111/classes/",
349
- ),
350
- ]
351
- assert mock_elements_worker.classes == {
352
- "good": "0000",
353
- "average": "1111",
354
- "bad": "2222",
355
- }
356
-
357
-
358
- def test_create_sub_element_wrong_element(mock_elements_worker):
359
- with pytest.raises(
360
- AssertionError, match="element shouldn't be null and should be of type Element"
361
- ):
362
- mock_elements_worker.create_sub_element(
363
- element=None,
364
- type="something",
365
- name="0",
366
- polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
367
- )
368
-
369
- with pytest.raises(
370
- AssertionError, match="element shouldn't be null and should be of type Element"
371
- ):
372
- mock_elements_worker.create_sub_element(
373
- element="not element type",
374
- type="something",
375
- name="0",
376
- polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
377
- )
378
-
379
-
380
- def test_create_sub_element_wrong_type(mock_elements_worker):
381
- elt = Element({"zone": None})
382
-
383
- with pytest.raises(
384
- AssertionError, match="type shouldn't be null and should be of type str"
385
- ):
386
- mock_elements_worker.create_sub_element(
387
- element=elt,
388
- type=None,
389
- name="0",
390
- polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
391
- )
392
-
393
- with pytest.raises(
394
- AssertionError, match="type shouldn't be null and should be of type str"
395
- ):
396
- mock_elements_worker.create_sub_element(
397
- element=elt,
398
- type=1234,
399
- name="0",
400
- polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
401
- )
402
-
403
-
404
- def test_create_sub_element_wrong_name(mock_elements_worker):
405
- elt = Element({"zone": None})
406
-
407
- with pytest.raises(
408
- AssertionError, match="name shouldn't be null and should be of type str"
409
- ):
410
- mock_elements_worker.create_sub_element(
411
- element=elt,
412
- type="something",
413
- name=None,
414
- polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
415
- )
416
-
417
- with pytest.raises(
418
- AssertionError, match="name shouldn't be null and should be of type str"
419
- ):
420
- mock_elements_worker.create_sub_element(
421
- element=elt,
422
- type="something",
423
- name=1234,
424
- polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
425
- )
426
-
427
-
428
- def test_create_sub_element_wrong_polygon(mock_elements_worker):
429
- elt = Element({"zone": None})
430
-
431
- with pytest.raises(AssertionError, match="polygon should be None or a list"):
432
- mock_elements_worker.create_sub_element(
433
- element=elt,
434
- type="something",
435
- name="O",
436
- polygon="not a polygon",
437
- )
438
-
439
- with pytest.raises(
440
- AssertionError, match="polygon should have at least three points"
441
- ):
442
- mock_elements_worker.create_sub_element(
443
- element=elt,
444
- type="something",
445
- name="O",
446
- polygon=[[1, 1], [2, 2]],
447
- )
448
-
449
- with pytest.raises(
450
- AssertionError, match="polygon points should be lists of two items"
451
- ):
452
- mock_elements_worker.create_sub_element(
453
- element=elt,
454
- type="something",
455
- name="O",
456
- polygon=[[1, 1, 1], [2, 2, 1], [2, 1, 1], [1, 2, 1]],
457
- )
458
-
459
- with pytest.raises(
460
- AssertionError, match="polygon points should be lists of two items"
461
- ):
462
- mock_elements_worker.create_sub_element(
463
- element=elt,
464
- type="something",
465
- name="O",
466
- polygon=[[1], [2], [2], [1]],
467
- )
468
-
469
- with pytest.raises(
470
- AssertionError, match="polygon points should be lists of two numbers"
471
- ):
472
- mock_elements_worker.create_sub_element(
473
- element=elt,
474
- type="something",
475
- name="O",
476
- polygon=[["not a coord", 1], [2, 2], [2, 1], [1, 2]],
477
- )
478
-
479
-
480
- @pytest.mark.parametrize("confidence", ["lol", "0.2", -1.0, 1.42, float("inf")])
481
- def test_create_sub_element_wrong_confidence(mock_elements_worker, confidence):
482
- with pytest.raises(
483
- AssertionError,
484
- match=re.escape("confidence should be None or a float in [0..1] range"),
485
- ):
486
- mock_elements_worker.create_sub_element(
487
- element=Element({"zone": None}),
488
- type="something",
489
- name="blah",
490
- polygon=[[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]],
491
- confidence=confidence,
492
- )
493
-
494
-
495
- @pytest.mark.parametrize(
496
- ("image", "error_type", "error_message"),
497
- [
498
- (1, AssertionError, "image should be None or string"),
499
- ("not a uuid", ValueError, "image is not a valid uuid."),
500
- ],
501
- )
502
- def test_create_sub_element_wrong_image(
503
- mock_elements_worker, image, error_type, error_message
504
- ):
505
- with pytest.raises(error_type, match=re.escape(error_message)):
506
- mock_elements_worker.create_sub_element(
507
- element=Element({"zone": None}),
508
- type="something",
509
- name="blah",
510
- polygon=[[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]],
511
- image=image,
512
- )
513
-
514
-
515
- def test_create_sub_element_wrong_image_and_polygon(mock_elements_worker):
516
- with pytest.raises(
517
- AssertionError,
518
- match=re.escape(
519
- "An image or a parent with an image is required to create an element with a polygon."
520
- ),
521
- ):
522
- mock_elements_worker.create_sub_element(
523
- element=Element({"zone": None}),
524
- type="something",
525
- name="blah",
526
- polygon=[[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]],
527
- image=None,
528
- )
529
-
530
-
531
- def test_create_sub_element_api_error(responses, mock_elements_worker):
532
- elt = Element(
533
- {
534
- "id": "12341234-1234-1234-1234-123412341234",
535
- "corpus": {"id": "11111111-1111-1111-1111-111111111111"},
536
- "zone": {"image": {"id": "22222222-2222-2222-2222-222222222222"}},
537
- }
538
- )
539
- responses.add(
540
- responses.POST,
541
- "http://testserver/api/v1/elements/create/",
542
- status=500,
543
- )
544
-
545
- with pytest.raises(ErrorResponse):
546
- mock_elements_worker.create_sub_element(
547
- element=elt,
548
- type="something",
549
- name="0",
550
- polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
551
- )
552
-
553
- assert len(responses.calls) == len(BASE_API_CALLS) + 5
554
- assert [
555
- (call.request.method, call.request.url) for call in responses.calls
556
- ] == BASE_API_CALLS + [
557
- # We retry 5 times the API call
558
- ("POST", "http://testserver/api/v1/elements/create/"),
559
- ("POST", "http://testserver/api/v1/elements/create/"),
560
- ("POST", "http://testserver/api/v1/elements/create/"),
561
- ("POST", "http://testserver/api/v1/elements/create/"),
562
- ("POST", "http://testserver/api/v1/elements/create/"),
563
- ]
564
-
565
-
566
- @pytest.mark.parametrize("slim_output", [True, False])
567
- def test_create_sub_element(responses, mock_elements_worker, slim_output):
568
- elt = Element(
569
- {
570
- "id": "12341234-1234-1234-1234-123412341234",
571
- "corpus": {"id": "11111111-1111-1111-1111-111111111111"},
572
- "zone": {"image": {"id": "22222222-2222-2222-2222-222222222222"}},
573
- }
574
- )
575
- child_elt = {
576
- "id": "12345678-1234-1234-1234-123456789123",
577
- "corpus": {"id": "11111111-1111-1111-1111-111111111111"},
578
- "zone": {"image": {"id": "22222222-2222-2222-2222-222222222222"}},
579
- }
580
- responses.add(
581
- responses.POST,
582
- "http://testserver/api/v1/elements/create/",
583
- status=200,
584
- json=child_elt,
585
- )
586
-
587
- element_creation_response = mock_elements_worker.create_sub_element(
588
- element=elt,
589
- type="something",
590
- name="0",
591
- polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
592
- slim_output=slim_output,
593
- )
594
-
595
- assert len(responses.calls) == len(BASE_API_CALLS) + 1
596
- assert [
597
- (call.request.method, call.request.url) for call in responses.calls
598
- ] == BASE_API_CALLS + [
599
- (
600
- "POST",
601
- "http://testserver/api/v1/elements/create/",
602
- ),
603
- ]
604
- assert json.loads(responses.calls[-1].request.body) == {
605
- "type": "something",
606
- "name": "0",
607
- "image": None,
608
- "corpus": "11111111-1111-1111-1111-111111111111",
609
- "polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
610
- "parent": "12341234-1234-1234-1234-123412341234",
611
- "worker_run_id": "56785678-5678-5678-5678-567856785678",
612
- "confidence": None,
613
- }
614
- if slim_output:
615
- assert element_creation_response == "12345678-1234-1234-1234-123456789123"
616
- else:
617
- assert Element(element_creation_response) == Element(child_elt)
618
-
619
-
620
- def test_create_sub_element_confidence(responses, mock_elements_worker):
621
- elt = Element(
622
- {
623
- "id": "12341234-1234-1234-1234-123412341234",
624
- "corpus": {"id": "11111111-1111-1111-1111-111111111111"},
625
- "zone": {"image": {"id": "22222222-2222-2222-2222-222222222222"}},
626
- }
627
- )
628
- responses.add(
629
- responses.POST,
630
- "http://testserver/api/v1/elements/create/",
631
- status=200,
632
- json={"id": "12345678-1234-1234-1234-123456789123"},
633
- )
634
-
635
- sub_element_id = mock_elements_worker.create_sub_element(
636
- element=elt,
637
- type="something",
638
- name="0",
639
- polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
640
- confidence=0.42,
641
- )
642
-
643
- assert len(responses.calls) == len(BASE_API_CALLS) + 1
644
- assert [
645
- (call.request.method, call.request.url) for call in responses.calls
646
- ] == BASE_API_CALLS + [
647
- ("POST", "http://testserver/api/v1/elements/create/"),
648
- ]
649
- assert json.loads(responses.calls[-1].request.body) == {
650
- "type": "something",
651
- "name": "0",
652
- "image": None,
653
- "corpus": "11111111-1111-1111-1111-111111111111",
654
- "polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
655
- "parent": "12341234-1234-1234-1234-123412341234",
656
- "worker_run_id": "56785678-5678-5678-5678-567856785678",
657
- "confidence": 0.42,
658
- }
659
- assert sub_element_id == "12345678-1234-1234-1234-123456789123"
660
-
661
-
662
- def test_create_elements_wrong_parent(mock_elements_worker):
663
- with pytest.raises(
664
- TypeError, match="Parent element should be an Element or CachedElement instance"
665
- ):
666
- mock_elements_worker.create_elements(
667
- parent=None,
668
- elements=[],
669
- )
670
-
671
- with pytest.raises(
672
- TypeError, match="Parent element should be an Element or CachedElement instance"
673
- ):
674
- mock_elements_worker.create_elements(
675
- parent="not element type",
676
- elements=[],
677
- )
678
-
679
-
680
- def test_create_elements_no_zone(mock_elements_worker):
681
- elt = Element({"zone": None})
682
- with pytest.raises(
683
- AssertionError, match="create_elements cannot be used on parents without zones"
684
- ):
685
- mock_elements_worker.create_elements(
686
- parent=elt,
687
- elements=None,
688
- )
689
-
690
- elt = CachedElement(
691
- id="11111111-1111-1111-1111-1111111111", name="blah", type="blah"
692
- )
693
- with pytest.raises(
694
- AssertionError, match="create_elements cannot be used on parents without images"
695
- ):
696
- mock_elements_worker.create_elements(
697
- parent=elt,
698
- elements=None,
699
- )
700
-
701
-
702
- def test_create_elements_wrong_elements(mock_elements_worker):
703
- elt = Element({"zone": {"image": {"id": "image_id"}}})
704
-
705
- with pytest.raises(
706
- AssertionError, match="elements shouldn't be null and should be of type list"
707
- ):
708
- mock_elements_worker.create_elements(
709
- parent=elt,
710
- elements=None,
711
- )
712
-
713
- with pytest.raises(
714
- AssertionError, match="elements shouldn't be null and should be of type list"
715
- ):
716
- mock_elements_worker.create_elements(
717
- parent=elt,
718
- elements="not a list",
719
- )
720
-
721
-
722
- def test_create_elements_wrong_elements_instance(mock_elements_worker):
723
- elt = Element({"zone": {"image": {"id": "image_id"}}})
724
-
725
- with pytest.raises(
726
- AssertionError, match="Element at index 0 in elements: Should be of type dict"
727
- ):
728
- mock_elements_worker.create_elements(
729
- parent=elt,
730
- elements=["not a dict"],
731
- )
732
-
733
-
734
- def test_create_elements_wrong_elements_name(mock_elements_worker):
735
- elt = Element({"zone": {"image": {"id": "image_id"}}})
736
-
737
- with pytest.raises(
738
- AssertionError,
739
- match="Element at index 0 in elements: name shouldn't be null and should be of type str",
740
- ):
741
- mock_elements_worker.create_elements(
742
- parent=elt,
743
- elements=[
744
- {
745
- "name": None,
746
- "type": "something",
747
- "polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
748
- }
749
- ],
750
- )
751
-
752
- with pytest.raises(
753
- AssertionError,
754
- match="Element at index 0 in elements: name shouldn't be null and should be of type str",
755
- ):
756
- mock_elements_worker.create_elements(
757
- parent=elt,
758
- elements=[
759
- {
760
- "name": 1234,
761
- "type": "something",
762
- "polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
763
- }
764
- ],
765
- )
766
-
767
-
768
- def test_create_elements_wrong_elements_type(mock_elements_worker):
769
- elt = Element({"zone": {"image": {"id": "image_id"}}})
770
-
771
- with pytest.raises(
772
- AssertionError,
773
- match="Element at index 0 in elements: type shouldn't be null and should be of type str",
774
- ):
775
- mock_elements_worker.create_elements(
776
- parent=elt,
777
- elements=[
778
- {
779
- "name": "0",
780
- "type": None,
781
- "polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
782
- }
783
- ],
784
- )
785
-
786
- with pytest.raises(
787
- AssertionError,
788
- match="Element at index 0 in elements: type shouldn't be null and should be of type str",
789
- ):
790
- mock_elements_worker.create_elements(
791
- parent=elt,
792
- elements=[
793
- {
794
- "name": "0",
795
- "type": 1234,
796
- "polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
797
- }
798
- ],
799
- )
800
-
801
-
802
- def test_create_elements_wrong_elements_polygon(mock_elements_worker):
803
- elt = Element({"zone": {"image": {"id": "image_id"}}})
804
-
805
- with pytest.raises(
806
- AssertionError,
807
- match="Element at index 0 in elements: polygon shouldn't be null and should be of type list",
808
- ):
809
- mock_elements_worker.create_elements(
810
- parent=elt,
811
- elements=[
812
- {
813
- "name": "0",
814
- "type": "something",
815
- "polygon": None,
816
- }
817
- ],
818
- )
819
-
820
- with pytest.raises(
821
- AssertionError,
822
- match="Element at index 0 in elements: polygon shouldn't be null and should be of type list",
823
- ):
824
- mock_elements_worker.create_elements(
825
- parent=elt,
826
- elements=[
827
- {
828
- "name": "0",
829
- "type": "something",
830
- "polygon": "not a polygon",
831
- }
832
- ],
833
- )
834
-
835
- with pytest.raises(
836
- AssertionError,
837
- match="Element at index 0 in elements: polygon should have at least three points",
838
- ):
839
- mock_elements_worker.create_elements(
840
- parent=elt,
841
- elements=[
842
- {
843
- "name": "0",
844
- "type": "something",
845
- "polygon": [[1, 1], [2, 2]],
846
- }
847
- ],
848
- )
849
-
850
- with pytest.raises(
851
- AssertionError,
852
- match="Element at index 0 in elements: polygon points should be lists of two items",
853
- ):
854
- mock_elements_worker.create_elements(
855
- parent=elt,
856
- elements=[
857
- {
858
- "name": "0",
859
- "type": "something",
860
- "polygon": [[1, 1, 1], [2, 2, 1], [2, 1, 1], [1, 2, 1]],
861
- }
862
- ],
863
- )
864
-
865
- with pytest.raises(
866
- AssertionError,
867
- match="Element at index 0 in elements: polygon points should be lists of two items",
868
- ):
869
- mock_elements_worker.create_elements(
870
- parent=elt,
871
- elements=[
872
- {
873
- "name": "0",
874
- "type": "something",
875
- "polygon": [[1], [2], [2], [1]],
876
- }
877
- ],
878
- )
879
-
880
- with pytest.raises(
881
- AssertionError,
882
- match="Element at index 0 in elements: polygon points should be lists of two numbers",
883
- ):
884
- mock_elements_worker.create_elements(
885
- parent=elt,
886
- elements=[
887
- {
888
- "name": "0",
889
- "type": "something",
890
- "polygon": [["not a coord", 1], [2, 2], [2, 1], [1, 2]],
891
- }
892
- ],
893
- )
894
-
895
-
896
- @pytest.mark.parametrize("confidence", ["lol", "0.2", -1.0, 1.42, float("inf")])
897
- def test_create_elements_wrong_elements_confidence(mock_elements_worker, confidence):
898
- with pytest.raises(
899
- AssertionError,
900
- match=re.escape(
901
- "Element at index 0 in elements: confidence should be None or a float in [0..1] range"
902
- ),
903
- ):
904
- mock_elements_worker.create_elements(
905
- parent=Element({"zone": {"image": {"id": "image_id"}}}),
906
- elements=[
907
- {
908
- "name": "a",
909
- "type": "something",
910
- "polygon": [[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]],
911
- "confidence": confidence,
912
- }
913
- ],
914
- )
915
-
916
-
917
- def test_create_elements_api_error(responses, mock_elements_worker):
918
- elt = Element(
919
- {
920
- "id": "12341234-1234-1234-1234-123412341234",
921
- "zone": {
922
- "image": {
923
- "id": "c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
924
- "width": 42,
925
- "height": 42,
926
- "url": "http://aaaa",
927
- }
928
- },
929
- }
930
- )
931
- responses.add(
932
- responses.POST,
933
- "http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
934
- status=500,
935
- )
936
-
937
- with pytest.raises(ErrorResponse):
938
- mock_elements_worker.create_elements(
939
- parent=elt,
940
- elements=[
941
- {
942
- "name": "0",
943
- "type": "something",
944
- "polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
945
- }
946
- ],
947
- )
948
-
949
- assert len(responses.calls) == len(BASE_API_CALLS) + 5
950
- assert [
951
- (call.request.method, call.request.url) for call in responses.calls
952
- ] == BASE_API_CALLS + [
953
- # We retry 5 times the API call
954
- (
955
- "POST",
956
- "http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
957
- ),
958
- (
959
- "POST",
960
- "http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
961
- ),
962
- (
963
- "POST",
964
- "http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
965
- ),
966
- (
967
- "POST",
968
- "http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
969
- ),
970
- (
971
- "POST",
972
- "http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
973
- ),
974
- ]
975
-
976
-
977
- def test_create_elements_cached_element(responses, mock_elements_worker_with_cache):
978
- image = CachedImage.create(
979
- id=UUID("c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe"),
980
- width=42,
981
- height=42,
982
- url="http://aaaa",
983
- )
984
- elt = CachedElement.create(
985
- id=UUID("12341234-1234-1234-1234-123412341234"),
986
- type="parent",
987
- image_id=image.id,
988
- polygon="[[0, 0], [0, 1000], [1000, 1000], [1000, 0], [0, 0]]",
989
- )
990
- responses.add(
991
- responses.POST,
992
- "http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
993
- status=200,
994
- json=[{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"}],
995
- )
996
-
997
- created_ids = mock_elements_worker_with_cache.create_elements(
998
- parent=elt,
999
- elements=[
1000
- {
1001
- "name": "0",
1002
- "type": "something",
1003
- "polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
1004
- }
1005
- ],
1006
- )
1007
-
1008
- assert len(responses.calls) == len(BASE_API_CALLS) + 1
1009
- assert [
1010
- (call.request.method, call.request.url) for call in responses.calls
1011
- ] == BASE_API_CALLS + [
1012
- (
1013
- "POST",
1014
- "http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
1015
- ),
1016
- ]
1017
- assert json.loads(responses.calls[-1].request.body) == {
1018
- "elements": [
1019
- {
1020
- "name": "0",
1021
- "type": "something",
1022
- "polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
1023
- }
1024
- ],
1025
- "worker_run_id": "56785678-5678-5678-5678-567856785678",
1026
- }
1027
- assert created_ids == [{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"}]
1028
-
1029
- # Check that created elements were properly stored in SQLite cache
1030
- assert list(CachedElement.select().order_by(CachedElement.id)) == [
1031
- elt,
1032
- CachedElement(
1033
- id=UUID("497f6eca-6276-4993-bfeb-53cbbbba6f08"),
1034
- parent_id=elt.id,
1035
- type="something",
1036
- image_id="c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
1037
- polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
1038
- worker_run_id=UUID("56785678-5678-5678-5678-567856785678"),
1039
- ),
1040
- ]
1041
-
1042
-
1043
- def test_create_elements(responses, mock_elements_worker_with_cache, tmp_path):
1044
- elt = Element(
1045
- {
1046
- "id": "12341234-1234-1234-1234-123412341234",
1047
- "zone": {
1048
- "image": {
1049
- "id": "c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
1050
- "width": 42,
1051
- "height": 42,
1052
- "url": "http://aaaa",
1053
- }
1054
- },
1055
- }
1056
- )
1057
- responses.add(
1058
- responses.POST,
1059
- "http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
1060
- status=200,
1061
- json=[{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"}],
1062
- )
1063
-
1064
- created_ids = mock_elements_worker_with_cache.create_elements(
1065
- parent=elt,
1066
- elements=[
1067
- {
1068
- "name": "0",
1069
- "type": "something",
1070
- "polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
1071
- }
1072
- ],
1073
- )
1074
-
1075
- assert len(responses.calls) == len(BASE_API_CALLS) + 1
1076
- assert [
1077
- (call.request.method, call.request.url) for call in responses.calls
1078
- ] == BASE_API_CALLS + [
1079
- (
1080
- "POST",
1081
- "http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
1082
- ),
1083
- ]
1084
- assert json.loads(responses.calls[-1].request.body) == {
1085
- "elements": [
1086
- {
1087
- "name": "0",
1088
- "type": "something",
1089
- "polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
1090
- }
1091
- ],
1092
- "worker_run_id": "56785678-5678-5678-5678-567856785678",
1093
- }
1094
- assert created_ids == [{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"}]
1095
-
1096
- # Check that created elements were properly stored in SQLite cache
1097
- assert (tmp_path / "db.sqlite").is_file()
1098
-
1099
- assert list(CachedElement.select()) == [
1100
- CachedElement(
1101
- id=UUID("497f6eca-6276-4993-bfeb-53cbbbba6f08"),
1102
- parent_id=UUID("12341234-1234-1234-1234-123412341234"),
1103
- type="something",
1104
- image_id="c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
1105
- polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
1106
- worker_run_id=UUID("56785678-5678-5678-5678-567856785678"),
1107
- confidence=None,
1108
- )
1109
- ]
1110
-
1111
-
1112
- def test_create_elements_confidence(
1113
- responses, mock_elements_worker_with_cache, tmp_path
1114
- ):
1115
- elt = Element(
1116
- {
1117
- "id": "12341234-1234-1234-1234-123412341234",
1118
- "zone": {
1119
- "image": {
1120
- "id": "c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
1121
- "width": 42,
1122
- "height": 42,
1123
- "url": "http://aaaa",
1124
- }
1125
- },
1126
- }
1127
- )
1128
- responses.add(
1129
- responses.POST,
1130
- "http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
1131
- status=200,
1132
- json=[{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"}],
1133
- )
1134
-
1135
- created_ids = mock_elements_worker_with_cache.create_elements(
1136
- parent=elt,
1137
- elements=[
1138
- {
1139
- "name": "0",
1140
- "type": "something",
1141
- "polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
1142
- "confidence": 0.42,
1143
- }
1144
- ],
1145
- )
1146
-
1147
- assert len(responses.calls) == len(BASE_API_CALLS) + 1
1148
- assert [
1149
- (call.request.method, call.request.url) for call in responses.calls
1150
- ] == BASE_API_CALLS + [
1151
- (
1152
- "POST",
1153
- "http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
1154
- ),
1155
- ]
1156
- assert json.loads(responses.calls[-1].request.body) == {
1157
- "elements": [
1158
- {
1159
- "name": "0",
1160
- "type": "something",
1161
- "polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
1162
- "confidence": 0.42,
1163
- }
1164
- ],
1165
- "worker_run_id": "56785678-5678-5678-5678-567856785678",
1166
- }
1167
- assert created_ids == [{"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"}]
1168
-
1169
- # Check that created elements were properly stored in SQLite cache
1170
- assert (tmp_path / "db.sqlite").is_file()
1171
-
1172
- assert list(CachedElement.select()) == [
1173
- CachedElement(
1174
- id=UUID("497f6eca-6276-4993-bfeb-53cbbbba6f08"),
1175
- parent_id=UUID("12341234-1234-1234-1234-123412341234"),
1176
- type="something",
1177
- image_id="c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
1178
- polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
1179
- worker_run_id=UUID("56785678-5678-5678-5678-567856785678"),
1180
- confidence=0.42,
1181
- )
1182
- ]
1183
-
1184
-
1185
- def test_create_elements_integrity_error(
1186
- responses, mock_elements_worker_with_cache, caplog
1187
- ):
1188
- elt = Element(
1189
- {
1190
- "id": "12341234-1234-1234-1234-123412341234",
1191
- "zone": {
1192
- "image": {
1193
- "id": "c0fec0fe-c0fe-c0fe-c0fe-c0fec0fec0fe",
1194
- "width": 42,
1195
- "height": 42,
1196
- "url": "http://aaaa",
1197
- }
1198
- },
1199
- }
1200
- )
1201
- responses.add(
1202
- responses.POST,
1203
- "http://testserver/api/v1/element/12341234-1234-1234-1234-123412341234/children/bulk/",
1204
- status=200,
1205
- json=[
1206
- # Duplicate IDs, which will cause an IntegrityError when stored in the cache
1207
- {"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"},
1208
- {"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"},
1209
- ],
1210
- )
1211
-
1212
- elements = [
1213
- {
1214
- "name": "0",
1215
- "type": "something",
1216
- "polygon": [[1, 1], [2, 2], [2, 1], [1, 2]],
1217
- },
1218
- {
1219
- "name": "1",
1220
- "type": "something",
1221
- "polygon": [[1, 1], [3, 3], [3, 1], [1, 3]],
1222
- },
1223
- ]
1224
-
1225
- created_ids = mock_elements_worker_with_cache.create_elements(
1226
- parent=elt,
1227
- elements=elements,
1228
- )
1229
-
1230
- assert created_ids == [
1231
- {"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"},
1232
- {"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"},
1233
- ]
1234
-
1235
- assert len(caplog.records) == 1
1236
- assert caplog.records[0].levelname == "WARNING"
1237
- assert caplog.records[0].message.startswith(
1238
- "Couldn't save created elements in local cache:"
1239
- )
1240
-
1241
- assert list(CachedElement.select()) == []
1242
-
1243
-
1244
- @pytest.mark.parametrize(
1245
- ("params", "error_message"),
1246
- [
1247
- (
1248
- {"parent": None, "child": None},
1249
- "parent shouldn't be null and should be of type Element",
1250
- ),
1251
- (
1252
- {"parent": "not an element", "child": None},
1253
- "parent shouldn't be null and should be of type Element",
1254
- ),
1255
- (
1256
- {"parent": Element(zone=None), "child": None},
1257
- "child shouldn't be null and should be of type Element",
1258
- ),
1259
- (
1260
- {"parent": Element(zone=None), "child": "not an element"},
1261
- "child shouldn't be null and should be of type Element",
1262
- ),
1263
- ],
1264
- )
1265
- def test_create_element_parent_invalid_params(
1266
- mock_elements_worker, params, error_message
1267
- ):
1268
- with pytest.raises(AssertionError, match=re.escape(error_message)):
1269
- mock_elements_worker.create_element_parent(**params)
1270
-
1271
-
1272
- def test_create_element_parent_api_error(responses, mock_elements_worker):
1273
- parent = Element({"id": "12341234-1234-1234-1234-123412341234"})
1274
- child = Element({"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"})
1275
- responses.add(
1276
- responses.POST,
1277
- "http://testserver/api/v1/element/497f6eca-6276-4993-bfeb-53cbbbba6f08/parent/12341234-1234-1234-1234-123412341234/",
1278
- status=500,
1279
- )
1280
-
1281
- with pytest.raises(ErrorResponse):
1282
- mock_elements_worker.create_element_parent(
1283
- parent=parent,
1284
- child=child,
1285
- )
1286
-
1287
- assert len(responses.calls) == len(BASE_API_CALLS) + 5
1288
- assert [
1289
- (call.request.method, call.request.url) for call in responses.calls
1290
- ] == BASE_API_CALLS + [
1291
- # We retry 5 times the API call
1292
- (
1293
- "POST",
1294
- "http://testserver/api/v1/element/497f6eca-6276-4993-bfeb-53cbbbba6f08/parent/12341234-1234-1234-1234-123412341234/",
1295
- ),
1296
- ] * 5
1297
-
1298
-
1299
- def test_create_element_parent(responses, mock_elements_worker):
1300
- parent = Element({"id": "12341234-1234-1234-1234-123412341234"})
1301
- child = Element({"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"})
1302
- responses.add(
1303
- responses.POST,
1304
- "http://testserver/api/v1/element/497f6eca-6276-4993-bfeb-53cbbbba6f08/parent/12341234-1234-1234-1234-123412341234/",
1305
- status=200,
1306
- json={
1307
- "parent": "12341234-1234-1234-1234-123412341234",
1308
- "child": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
1309
- },
1310
- )
1311
-
1312
- created_element_parent = mock_elements_worker.create_element_parent(
1313
- parent=parent,
1314
- child=child,
1315
- )
1316
-
1317
- assert len(responses.calls) == len(BASE_API_CALLS) + 1
1318
- assert [
1319
- (call.request.method, call.request.url) for call in responses.calls
1320
- ] == BASE_API_CALLS + [
1321
- (
1322
- "POST",
1323
- "http://testserver/api/v1/element/497f6eca-6276-4993-bfeb-53cbbbba6f08/parent/12341234-1234-1234-1234-123412341234/",
1324
- ),
1325
- ]
1326
- assert created_element_parent == {
1327
- "parent": "12341234-1234-1234-1234-123412341234",
1328
- "child": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
1329
- }
1330
-
1331
-
1332
- @pytest.mark.parametrize(
1333
- ("payload", "error"),
1334
- [
1335
- # Element
1336
- (
1337
- {"element": None},
1338
- "element shouldn't be null and should be an Element or CachedElement",
1339
- ),
1340
- (
1341
- {"element": "not element type"},
1342
- "element shouldn't be null and should be an Element or CachedElement",
1343
- ),
1344
- ],
1345
- )
1346
- def test_partial_update_element_wrong_param_element(
1347
- mock_elements_worker, payload, error
1348
- ):
1349
- api_payload = {
1350
- "element": Element({"zone": None}),
1351
- **payload,
1352
- }
1353
-
1354
- with pytest.raises(AssertionError, match=error):
1355
- mock_elements_worker.partial_update_element(
1356
- **api_payload,
1357
- )
1358
-
1359
-
1360
- @pytest.mark.parametrize(
1361
- ("payload", "error"),
1362
- [
1363
- # Type
1364
- ({"type": 1234}, "type should be a str"),
1365
- ({"type": None}, "type should be a str"),
1366
- ],
1367
- )
1368
- def test_partial_update_element_wrong_param_type(mock_elements_worker, payload, error):
1369
- api_payload = {
1370
- "element": Element({"zone": None}),
1371
- **payload,
1372
- }
1373
-
1374
- with pytest.raises(AssertionError, match=error):
1375
- mock_elements_worker.partial_update_element(
1376
- **api_payload,
1377
- )
1378
-
1379
-
1380
- @pytest.mark.parametrize(
1381
- ("payload", "error"),
1382
- [
1383
- # Name
1384
- ({"name": 1234}, "name should be a str"),
1385
- ({"name": None}, "name should be a str"),
1386
- ],
1387
- )
1388
- def test_partial_update_element_wrong_param_name(mock_elements_worker, payload, error):
1389
- api_payload = {
1390
- "element": Element({"zone": None}),
1391
- **payload,
1392
- }
1393
-
1394
- with pytest.raises(AssertionError, match=error):
1395
- mock_elements_worker.partial_update_element(
1396
- **api_payload,
1397
- )
1398
-
1399
-
1400
- @pytest.mark.parametrize(
1401
- ("payload", "error"),
1402
- [
1403
- # Polygon
1404
- ({"polygon": "not a polygon"}, "polygon should be a list"),
1405
- ({"polygon": None}, "polygon should be a list"),
1406
- ({"polygon": [[1, 1], [2, 2]]}, "polygon should have at least three points"),
1407
- (
1408
- {"polygon": [[1, 1, 1], [2, 2, 1], [2, 1, 1], [1, 2, 1]]},
1409
- "polygon points should be lists of two items",
1410
- ),
1411
- (
1412
- {"polygon": [[1], [2], [2], [1]]},
1413
- "polygon points should be lists of two items",
1414
- ),
1415
- (
1416
- {"polygon": [["not a coord", 1], [2, 2], [2, 1], [1, 2]]},
1417
- "polygon points should be lists of two numbers",
1418
- ),
1419
- ],
1420
- )
1421
- def test_partial_update_element_wrong_param_polygon(
1422
- mock_elements_worker, payload, error
1423
- ):
1424
- api_payload = {
1425
- "element": Element({"zone": None}),
1426
- **payload,
1427
- }
1428
-
1429
- with pytest.raises(AssertionError, match=error):
1430
- mock_elements_worker.partial_update_element(
1431
- **api_payload,
1432
- )
1433
-
1434
-
1435
- @pytest.mark.parametrize(
1436
- ("payload", "error"),
1437
- [
1438
- # Confidence
1439
- ({"confidence": "lol"}, "confidence should be None or a float in [0..1] range"),
1440
- ({"confidence": "0.2"}, "confidence should be None or a float in [0..1] range"),
1441
- ({"confidence": -1.0}, "confidence should be None or a float in [0..1] range"),
1442
- ({"confidence": 1.42}, "confidence should be None or a float in [0..1] range"),
1443
- (
1444
- {"confidence": float("inf")},
1445
- "confidence should be None or a float in [0..1] range",
1446
- ),
1447
- ],
1448
- )
1449
- def test_partial_update_element_wrong_param_conf(mock_elements_worker, payload, error):
1450
- api_payload = {
1451
- "element": Element({"zone": None}),
1452
- **payload,
1453
- }
1454
-
1455
- with pytest.raises(AssertionError, match=re.escape(error)):
1456
- mock_elements_worker.partial_update_element(
1457
- **api_payload,
1458
- )
1459
-
1460
-
1461
- @pytest.mark.parametrize(
1462
- ("payload", "error"),
1463
- [
1464
- # Rotation angle
1465
- ({"rotation_angle": "lol"}, "rotation_angle should be a positive integer"),
1466
- ({"rotation_angle": -1}, "rotation_angle should be a positive integer"),
1467
- ({"rotation_angle": 0.5}, "rotation_angle should be a positive integer"),
1468
- ({"rotation_angle": None}, "rotation_angle should be a positive integer"),
1469
- ],
1470
- )
1471
- def test_partial_update_element_wrong_param_rota(mock_elements_worker, payload, error):
1472
- api_payload = {
1473
- "element": Element({"zone": None}),
1474
- **payload,
1475
- }
1476
-
1477
- with pytest.raises(AssertionError, match=error):
1478
- mock_elements_worker.partial_update_element(
1479
- **api_payload,
1480
- )
1481
-
1482
-
1483
- @pytest.mark.parametrize(
1484
- ("payload", "error"),
1485
- [
1486
- # Mirrored
1487
- ({"mirrored": "lol"}, "mirrored should be a boolean"),
1488
- ({"mirrored": 1234}, "mirrored should be a boolean"),
1489
- ({"mirrored": None}, "mirrored should be a boolean"),
1490
- ],
1491
- )
1492
- def test_partial_update_element_wrong_param_mir(mock_elements_worker, payload, error):
1493
- api_payload = {
1494
- "element": Element({"zone": None}),
1495
- **payload,
1496
- }
1497
-
1498
- with pytest.raises(AssertionError, match=error):
1499
- mock_elements_worker.partial_update_element(
1500
- **api_payload,
1501
- )
1502
-
1503
-
1504
- @pytest.mark.parametrize(
1505
- ("payload", "error"),
1506
- [
1507
- # Image
1508
- ({"image": "lol"}, "image should be a UUID"),
1509
- ({"image": 1234}, "image should be a UUID"),
1510
- ({"image": None}, "image should be a UUID"),
1511
- ],
1512
- )
1513
- def test_partial_update_element_wrong_param_image(mock_elements_worker, payload, error):
1514
- api_payload = {
1515
- "element": Element({"zone": None}),
1516
- **payload,
1517
- }
1518
-
1519
- with pytest.raises(AssertionError, match=error):
1520
- mock_elements_worker.partial_update_element(
1521
- **api_payload,
1522
- )
1523
-
1524
-
1525
- def test_partial_update_element_api_error(responses, mock_elements_worker):
1526
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
1527
- responses.add(
1528
- responses.PATCH,
1529
- f"http://testserver/api/v1/element/{elt.id}/",
1530
- status=500,
1531
- )
1532
-
1533
- with pytest.raises(ErrorResponse):
1534
- mock_elements_worker.partial_update_element(
1535
- element=elt,
1536
- type="something",
1537
- name="0",
1538
- polygon=[[1, 1], [2, 2], [2, 1], [1, 2]],
1539
- )
1540
-
1541
- assert len(responses.calls) == len(BASE_API_CALLS) + 5
1542
- assert [
1543
- (call.request.method, call.request.url) for call in responses.calls
1544
- ] == BASE_API_CALLS + [
1545
- # We retry 5 times the API call
1546
- ("PATCH", f"http://testserver/api/v1/element/{elt.id}/"),
1547
- ("PATCH", f"http://testserver/api/v1/element/{elt.id}/"),
1548
- ("PATCH", f"http://testserver/api/v1/element/{elt.id}/"),
1549
- ("PATCH", f"http://testserver/api/v1/element/{elt.id}/"),
1550
- ("PATCH", f"http://testserver/api/v1/element/{elt.id}/"),
1551
- ]
1552
-
1553
-
1554
- @pytest.mark.usefixtures("_mock_cached_elements", "_mock_cached_images")
1555
- @pytest.mark.parametrize(
1556
- "payload",
1557
- [
1558
- (
1559
- {
1560
- "polygon": [[10, 10], [20, 20], [20, 10], [10, 20]],
1561
- "confidence": None,
1562
- }
1563
- ),
1564
- (
1565
- {
1566
- "rotation_angle": 45,
1567
- "mirrored": False,
1568
- }
1569
- ),
1570
- (
1571
- {
1572
- "polygon": [[10, 10], [20, 20], [20, 10], [10, 20]],
1573
- "confidence": None,
1574
- "rotation_angle": 45,
1575
- "mirrored": False,
1576
- }
1577
- ),
1578
- ],
1579
- )
1580
- def test_partial_update_element(responses, mock_elements_worker_with_cache, payload):
1581
- elt = CachedElement.select().first()
1582
- new_image = CachedImage.select().first()
1583
-
1584
- elt_response = {
1585
- "image": str(new_image.id),
1586
- **payload,
1587
- }
1588
- responses.add(
1589
- responses.PATCH,
1590
- f"http://testserver/api/v1/element/{elt.id}/",
1591
- status=200,
1592
- # UUID not allowed in JSON
1593
- json=elt_response,
1594
- )
1595
-
1596
- element_update_response = mock_elements_worker_with_cache.partial_update_element(
1597
- element=elt,
1598
- **{**elt_response, "image": new_image.id},
1599
- )
1600
-
1601
- assert len(responses.calls) == len(BASE_API_CALLS) + 1
1602
- assert [
1603
- (call.request.method, call.request.url) for call in responses.calls
1604
- ] == BASE_API_CALLS + [
1605
- (
1606
- "PATCH",
1607
- f"http://testserver/api/v1/element/{elt.id}/",
1608
- ),
1609
- ]
1610
- assert json.loads(responses.calls[-1].request.body) == elt_response
1611
- assert element_update_response == elt_response
1612
-
1613
- cached_element = CachedElement.get(CachedElement.id == elt.id)
1614
- # Always present in payload
1615
- assert str(cached_element.image_id) == elt_response["image"]
1616
- # Optional params
1617
- if "polygon" in payload:
1618
- # Cast to string as this is the only difference compared to model
1619
- elt_response["polygon"] = str(elt_response["polygon"])
1620
-
1621
- for param in payload:
1622
- assert getattr(cached_element, param) == elt_response[param]
1623
-
1624
-
1625
- @pytest.mark.usefixtures("_mock_cached_elements")
1626
- @pytest.mark.parametrize("confidence", [None, 0.42])
1627
- def test_partial_update_element_confidence(
1628
- responses, mock_elements_worker_with_cache, confidence
1629
- ):
1630
- elt = CachedElement.select().first()
1631
- elt_response = {
1632
- "polygon": [[10, 10], [20, 20], [20, 10], [10, 20]],
1633
- "confidence": confidence,
1634
- }
1635
- responses.add(
1636
- responses.PATCH,
1637
- f"http://testserver/api/v1/element/{elt.id}/",
1638
- status=200,
1639
- json=elt_response,
1640
- )
1641
-
1642
- element_update_response = mock_elements_worker_with_cache.partial_update_element(
1643
- element=elt,
1644
- **elt_response,
1645
- )
1646
-
1647
- assert len(responses.calls) == len(BASE_API_CALLS) + 1
1648
- assert [
1649
- (call.request.method, call.request.url) for call in responses.calls
1650
- ] == BASE_API_CALLS + [
1651
- (
1652
- "PATCH",
1653
- f"http://testserver/api/v1/element/{elt.id}/",
1654
- ),
1655
- ]
1656
- assert json.loads(responses.calls[-1].request.body) == elt_response
1657
- assert element_update_response == elt_response
1658
-
1659
- cached_element = CachedElement.get(CachedElement.id == elt.id)
1660
- assert cached_element.polygon == str(elt_response["polygon"])
1661
- assert cached_element.confidence == confidence
1662
-
1663
-
1664
- def test_list_element_children_wrong_element(mock_elements_worker):
1665
- with pytest.raises(
1666
- AssertionError,
1667
- match="element shouldn't be null and should be an Element or CachedElement",
1668
- ):
1669
- mock_elements_worker.list_element_children(element=None)
1670
-
1671
- with pytest.raises(
1672
- AssertionError,
1673
- match="element shouldn't be null and should be an Element or CachedElement",
1674
- ):
1675
- mock_elements_worker.list_element_children(element="not element type")
1676
-
1677
-
1678
- def test_list_element_children_wrong_folder(mock_elements_worker):
1679
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
1680
-
1681
- with pytest.raises(AssertionError, match="folder should be of type bool"):
1682
- mock_elements_worker.list_element_children(
1683
- element=elt,
1684
- folder="not bool",
1685
- )
1686
-
1687
-
1688
- def test_list_element_children_wrong_name(mock_elements_worker):
1689
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
1690
-
1691
- with pytest.raises(AssertionError, match="name should be of type str"):
1692
- mock_elements_worker.list_element_children(
1693
- element=elt,
1694
- name=1234,
1695
- )
1696
-
1697
-
1698
- def test_list_element_children_wrong_recursive(mock_elements_worker):
1699
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
1700
-
1701
- with pytest.raises(AssertionError, match="recursive should be of type bool"):
1702
- mock_elements_worker.list_element_children(
1703
- element=elt,
1704
- recursive="not bool",
1705
- )
1706
-
1707
-
1708
- def test_list_element_children_wrong_type(mock_elements_worker):
1709
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
1710
-
1711
- with pytest.raises(AssertionError, match="type should be of type str"):
1712
- mock_elements_worker.list_element_children(
1713
- element=elt,
1714
- type=1234,
1715
- )
1716
-
1717
-
1718
- def test_list_element_children_wrong_with_classes(mock_elements_worker):
1719
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
1720
-
1721
- with pytest.raises(AssertionError, match="with_classes should be of type bool"):
1722
- mock_elements_worker.list_element_children(
1723
- element=elt,
1724
- with_classes="not bool",
1725
- )
1726
-
1727
-
1728
- def test_list_element_children_wrong_with_corpus(mock_elements_worker):
1729
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
1730
-
1731
- with pytest.raises(AssertionError, match="with_corpus should be of type bool"):
1732
- mock_elements_worker.list_element_children(
1733
- element=elt,
1734
- with_corpus="not bool",
1735
- )
1736
-
1737
-
1738
- def test_list_element_children_wrong_with_has_children(mock_elements_worker):
1739
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
1740
-
1741
- with pytest.raises(
1742
- AssertionError, match="with_has_children should be of type bool"
1743
- ):
1744
- mock_elements_worker.list_element_children(
1745
- element=elt,
1746
- with_has_children="not bool",
1747
- )
1748
-
1749
-
1750
- def test_list_element_children_wrong_with_zone(mock_elements_worker):
1751
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
1752
-
1753
- with pytest.raises(AssertionError, match="with_zone should be of type bool"):
1754
- mock_elements_worker.list_element_children(
1755
- element=elt,
1756
- with_zone="not bool",
1757
- )
1758
-
1759
-
1760
- def test_list_element_children_wrong_with_metadata(mock_elements_worker):
1761
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
1762
-
1763
- with pytest.raises(AssertionError, match="with_metadata should be of type bool"):
1764
- mock_elements_worker.list_element_children(
1765
- element=elt,
1766
- with_metadata="not bool",
1767
- )
1768
-
1769
-
1770
- @pytest.mark.parametrize(
1771
- ("param", "value"),
1772
- [
1773
- ("worker_run", 1234),
1774
- ("transcription_worker_run", 1234),
1775
- ],
1776
- )
1777
- def test_list_element_children_wrong_worker_run(mock_elements_worker, param, value):
1778
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
1779
-
1780
- with pytest.raises(AssertionError, match=f"{param} should be of type str or bool"):
1781
- mock_elements_worker.list_element_children(
1782
- element=elt,
1783
- **{param: value},
1784
- )
1785
-
1786
-
1787
- @pytest.mark.parametrize(
1788
- ("param", "alternative", "value"),
1789
- [
1790
- ("worker_version", "worker_run", 1234),
1791
- ("transcription_worker_version", "transcription_worker_run", 1234),
1792
- ],
1793
- )
1794
- def test_list_element_children_wrong_worker_version(
1795
- mock_elements_worker, param, alternative, value
1796
- ):
1797
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
1798
-
1799
- # WARNING: pytest.deprecated_call must be placed BEFORE pytest.raises, otherwise `match` argument won't be checked
1800
- with (
1801
- pytest.deprecated_call(
1802
- match=f"`{param}` usage is deprecated. Consider using `{alternative}` instead."
1803
- ),
1804
- pytest.raises(AssertionError, match=f"{param} should be of type str or bool"),
1805
- ):
1806
- mock_elements_worker.list_element_children(
1807
- element=elt,
1808
- **{param: value},
1809
- )
1810
-
1811
-
1812
- @pytest.mark.parametrize(
1813
- "param",
1814
- [
1815
- "worker_run",
1816
- "transcription_worker_run",
1817
- ],
1818
- )
1819
- def test_list_element_children_wrong_bool_worker_run(mock_elements_worker, param):
1820
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
1821
-
1822
- with pytest.raises(
1823
- AssertionError, match=f"if of type bool, {param} can only be set to False"
1824
- ):
1825
- mock_elements_worker.list_element_children(
1826
- element=elt,
1827
- **{param: True},
1828
- )
1829
-
1830
-
1831
- @pytest.mark.parametrize(
1832
- ("param", "alternative"),
1833
- [
1834
- ("worker_version", "worker_run"),
1835
- ("transcription_worker_version", "transcription_worker_run"),
1836
- ],
1837
- )
1838
- def test_list_element_children_wrong_bool_worker_version(
1839
- mock_elements_worker, param, alternative
1840
- ):
1841
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
1842
-
1843
- # WARNING: pytest.deprecated_call must be placed BEFORE pytest.raises, otherwise `match` argument won't be checked
1844
- with (
1845
- pytest.deprecated_call(
1846
- match=f"`{param}` usage is deprecated. Consider using `{alternative}` instead."
1847
- ),
1848
- pytest.raises(
1849
- AssertionError, match=f"if of type bool, {param} can only be set to False"
1850
- ),
1851
- ):
1852
- mock_elements_worker.list_element_children(
1853
- element=elt,
1854
- **{param: True},
1855
- )
1856
-
1857
-
1858
- def test_list_element_children_api_error(responses, mock_elements_worker):
1859
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
1860
- responses.add(
1861
- responses.GET,
1862
- "http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/children/",
1863
- status=500,
1864
- )
1865
-
1866
- with pytest.raises(
1867
- Exception, match="Stopping pagination as data will be incomplete"
1868
- ):
1869
- next(mock_elements_worker.list_element_children(element=elt))
1870
-
1871
- assert len(responses.calls) == len(BASE_API_CALLS) + 5
1872
- assert [
1873
- (call.request.method, call.request.url) for call in responses.calls
1874
- ] == BASE_API_CALLS + [
1875
- # We do 5 retries
1876
- (
1877
- "GET",
1878
- "http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/children/",
1879
- ),
1880
- (
1881
- "GET",
1882
- "http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/children/",
1883
- ),
1884
- (
1885
- "GET",
1886
- "http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/children/",
1887
- ),
1888
- (
1889
- "GET",
1890
- "http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/children/",
1891
- ),
1892
- (
1893
- "GET",
1894
- "http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/children/",
1895
- ),
1896
- ]
1897
-
1898
-
1899
- def test_list_element_children(responses, mock_elements_worker):
1900
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
1901
- expected_children = [
1902
- {
1903
- "id": "0000",
1904
- "type": "page",
1905
- "name": "Test",
1906
- "corpus": {},
1907
- "thumbnail_url": None,
1908
- "zone": {},
1909
- "best_classes": None,
1910
- "has_children": None,
1911
- "worker_version_id": None,
1912
- "worker_run_id": None,
1913
- },
1914
- {
1915
- "id": "1111",
1916
- "type": "page",
1917
- "name": "Test 2",
1918
- "corpus": {},
1919
- "thumbnail_url": None,
1920
- "zone": {},
1921
- "best_classes": None,
1922
- "has_children": None,
1923
- "worker_version_id": None,
1924
- "worker_run_id": None,
1925
- },
1926
- {
1927
- "id": "2222",
1928
- "type": "page",
1929
- "name": "Test 3",
1930
- "corpus": {},
1931
- "thumbnail_url": None,
1932
- "zone": {},
1933
- "best_classes": None,
1934
- "has_children": None,
1935
- "worker_version_id": None,
1936
- "worker_run_id": None,
1937
- },
1938
- ]
1939
- responses.add(
1940
- responses.GET,
1941
- "http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/children/",
1942
- status=200,
1943
- json={
1944
- "count": 3,
1945
- "next": None,
1946
- "results": expected_children,
1947
- },
1948
- )
1949
-
1950
- for idx, child in enumerate(
1951
- mock_elements_worker.list_element_children(element=elt)
1952
- ):
1953
- assert child == expected_children[idx]
1954
-
1955
- assert len(responses.calls) == len(BASE_API_CALLS) + 1
1956
- assert [
1957
- (call.request.method, call.request.url) for call in responses.calls
1958
- ] == BASE_API_CALLS + [
1959
- (
1960
- "GET",
1961
- "http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/children/",
1962
- ),
1963
- ]
1964
-
1965
-
1966
- def test_list_element_children_manual_worker_version(responses, mock_elements_worker):
1967
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
1968
- expected_children = [
1969
- {
1970
- "id": "0000",
1971
- "type": "page",
1972
- "name": "Test",
1973
- "corpus": {},
1974
- "thumbnail_url": None,
1975
- "zone": {},
1976
- "best_classes": None,
1977
- "has_children": None,
1978
- "worker_version_id": None,
1979
- "worker_run_id": None,
1980
- }
1981
- ]
1982
- responses.add(
1983
- responses.GET,
1984
- "http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/children/?worker_version=False",
1985
- status=200,
1986
- json={
1987
- "count": 1,
1988
- "next": None,
1989
- "results": expected_children,
1990
- },
1991
- )
1992
-
1993
- with pytest.deprecated_call(
1994
- match="`worker_version` usage is deprecated. Consider using `worker_run` instead."
1995
- ):
1996
- for idx, child in enumerate(
1997
- mock_elements_worker.list_element_children(
1998
- element=elt, worker_version=False
1999
- )
2000
- ):
2001
- assert child == expected_children[idx]
2002
-
2003
- assert len(responses.calls) == len(BASE_API_CALLS) + 1
2004
- assert [
2005
- (call.request.method, call.request.url) for call in responses.calls
2006
- ] == BASE_API_CALLS + [
2007
- (
2008
- "GET",
2009
- "http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/children/?worker_version=False",
2010
- ),
2011
- ]
2012
-
2013
-
2014
- def test_list_element_children_manual_worker_run(responses, mock_elements_worker):
2015
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
2016
- expected_children = [
2017
- {
2018
- "id": "0000",
2019
- "type": "page",
2020
- "name": "Test",
2021
- "corpus": {},
2022
- "thumbnail_url": None,
2023
- "zone": {},
2024
- "best_classes": None,
2025
- "has_children": None,
2026
- "worker_version_id": None,
2027
- "worker_run_id": None,
2028
- }
2029
- ]
2030
- responses.add(
2031
- responses.GET,
2032
- "http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/children/?worker_run=False",
2033
- status=200,
2034
- json={
2035
- "count": 1,
2036
- "next": None,
2037
- "results": expected_children,
2038
- },
2039
- )
2040
-
2041
- for idx, child in enumerate(
2042
- mock_elements_worker.list_element_children(element=elt, worker_run=False)
2043
- ):
2044
- assert child == expected_children[idx]
2045
-
2046
- assert len(responses.calls) == len(BASE_API_CALLS) + 1
2047
- assert [
2048
- (call.request.method, call.request.url) for call in responses.calls
2049
- ] == BASE_API_CALLS + [
2050
- (
2051
- "GET",
2052
- "http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/children/?worker_run=False",
2053
- ),
2054
- ]
2055
-
2056
-
2057
- def test_list_element_children_with_cache_unhandled_param(
2058
- mock_elements_worker_with_cache,
2059
- ):
2060
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
2061
-
2062
- with pytest.raises(
2063
- AssertionError,
2064
- match="When using the local cache, you can only filter by 'type' and/or 'worker_version' and/or 'worker_run'",
2065
- ):
2066
- mock_elements_worker_with_cache.list_element_children(
2067
- element=elt, with_corpus=True
2068
- )
2069
-
2070
-
2071
- @pytest.mark.usefixtures("_mock_cached_elements")
2072
- @pytest.mark.parametrize(
2073
- ("filters", "expected_ids"),
2074
- [
2075
- # Filter on element should give all elements inserted
2076
- (
2077
- {
2078
- "element": CachedElement(id="12341234-1234-1234-1234-123412341234"),
2079
- },
2080
- (
2081
- "11111111-1111-1111-1111-111111111111",
2082
- "22222222-2222-2222-2222-222222222222",
2083
- "33333333-3333-3333-3333-333333333333",
2084
- ),
2085
- ),
2086
- # Filter on element and page should give the second element
2087
- (
2088
- {
2089
- "element": CachedElement(id="12341234-1234-1234-1234-123412341234"),
2090
- "type": "page",
2091
- },
2092
- ("22222222-2222-2222-2222-222222222222",),
2093
- ),
2094
- # Filter on element and worker run should give second
2095
- (
2096
- {
2097
- "element": CachedElement(id="12341234-1234-1234-1234-123412341234"),
2098
- "worker_run": "56785678-5678-5678-5678-567856785678",
2099
- },
2100
- ("22222222-2222-2222-2222-222222222222",),
2101
- ),
2102
- # Filter on element, manual worker run should give first and third
2103
- (
2104
- {
2105
- "element": CachedElement(id="12341234-1234-1234-1234-123412341234"),
2106
- "worker_run": False,
2107
- },
2108
- (
2109
- "11111111-1111-1111-1111-111111111111",
2110
- "33333333-3333-3333-3333-333333333333",
2111
- ),
2112
- ),
2113
- ],
2114
- )
2115
- def test_list_element_children_with_cache(
2116
- responses,
2117
- mock_elements_worker_with_cache,
2118
- filters,
2119
- expected_ids,
2120
- ):
2121
- # Check we have 5 elements already present in database
2122
- assert CachedElement.select().count() == 5
2123
-
2124
- # Query database through cache
2125
- elements = mock_elements_worker_with_cache.list_element_children(**filters)
2126
- assert elements.count() == len(expected_ids)
2127
- for child, expected_id in zip(elements.order_by("id"), expected_ids, strict=True):
2128
- assert child.id == UUID(expected_id)
2129
-
2130
- # Check the worker never hits the API for elements
2131
- assert len(responses.calls) == len(BASE_API_CALLS)
2132
- assert [
2133
- (call.request.method, call.request.url) for call in responses.calls
2134
- ] == BASE_API_CALLS
2135
-
2136
-
2137
- @pytest.mark.usefixtures("_mock_cached_elements")
2138
- @pytest.mark.parametrize(
2139
- ("filters", "expected_ids"),
2140
- [
2141
- # Filter on element and worker version
2142
- (
2143
- {
2144
- "element": CachedElement(id="12341234-1234-1234-1234-123412341234"),
2145
- "worker_version": "56785678-5678-5678-5678-567856785678",
2146
- },
2147
- (
2148
- "11111111-1111-1111-1111-111111111111",
2149
- "22222222-2222-2222-2222-222222222222",
2150
- ),
2151
- ),
2152
- # Filter on element, type double_page and worker version
2153
- (
2154
- {
2155
- "element": CachedElement(id="12341234-1234-1234-1234-123412341234"),
2156
- "type": "page",
2157
- "worker_version": "56785678-5678-5678-5678-567856785678",
2158
- },
2159
- ("22222222-2222-2222-2222-222222222222",),
2160
- ),
2161
- # Filter on element, manual worker version
2162
- (
2163
- {
2164
- "element": CachedElement(id="12341234-1234-1234-1234-123412341234"),
2165
- "worker_version": False,
2166
- },
2167
- ("33333333-3333-3333-3333-333333333333",),
2168
- ),
2169
- ],
2170
- )
2171
- def test_list_element_children_with_cache_deprecation(
2172
- responses,
2173
- mock_elements_worker_with_cache,
2174
- filters,
2175
- expected_ids,
2176
- ):
2177
- # Check we have 5 elements already present in database
2178
- assert CachedElement.select().count() == 5
2179
-
2180
- with pytest.deprecated_call(
2181
- match="`worker_version` usage is deprecated. Consider using `worker_run` instead."
2182
- ):
2183
- # Query database through cache
2184
- elements = mock_elements_worker_with_cache.list_element_children(**filters)
2185
- assert elements.count() == len(expected_ids)
2186
- for child, expected_id in zip(elements.order_by("id"), expected_ids, strict=True):
2187
- assert child.id == UUID(expected_id)
2188
-
2189
- # Check the worker never hits the API for elements
2190
- assert len(responses.calls) == len(BASE_API_CALLS)
2191
- assert [
2192
- (call.request.method, call.request.url) for call in responses.calls
2193
- ] == BASE_API_CALLS
2194
-
2195
-
2196
- def test_list_element_parents_wrong_element(mock_elements_worker):
2197
- with pytest.raises(
2198
- AssertionError,
2199
- match="element shouldn't be null and should be an Element or CachedElement",
2200
- ):
2201
- mock_elements_worker.list_element_parents(element=None)
2202
-
2203
- with pytest.raises(
2204
- AssertionError,
2205
- match="element shouldn't be null and should be an Element or CachedElement",
2206
- ):
2207
- mock_elements_worker.list_element_parents(element="not element type")
2208
-
2209
-
2210
- def test_list_element_parents_wrong_folder(mock_elements_worker):
2211
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
2212
-
2213
- with pytest.raises(AssertionError, match="folder should be of type bool"):
2214
- mock_elements_worker.list_element_parents(
2215
- element=elt,
2216
- folder="not bool",
2217
- )
2218
-
2219
-
2220
- def test_list_element_parents_wrong_name(mock_elements_worker):
2221
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
2222
-
2223
- with pytest.raises(AssertionError, match="name should be of type str"):
2224
- mock_elements_worker.list_element_parents(
2225
- element=elt,
2226
- name=1234,
2227
- )
2228
-
2229
-
2230
- def test_list_element_parents_wrong_recursive(mock_elements_worker):
2231
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
2232
-
2233
- with pytest.raises(AssertionError, match="recursive should be of type bool"):
2234
- mock_elements_worker.list_element_parents(
2235
- element=elt,
2236
- recursive="not bool",
2237
- )
2238
-
2239
-
2240
- def test_list_element_parents_wrong_type(mock_elements_worker):
2241
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
2242
-
2243
- with pytest.raises(AssertionError, match="type should be of type str"):
2244
- mock_elements_worker.list_element_parents(
2245
- element=elt,
2246
- type=1234,
2247
- )
2248
-
2249
-
2250
- def test_list_element_parents_wrong_with_classes(mock_elements_worker):
2251
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
2252
-
2253
- with pytest.raises(AssertionError, match="with_classes should be of type bool"):
2254
- mock_elements_worker.list_element_parents(
2255
- element=elt,
2256
- with_classes="not bool",
2257
- )
2258
-
2259
-
2260
- def test_list_element_parents_wrong_with_corpus(mock_elements_worker):
2261
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
2262
-
2263
- with pytest.raises(AssertionError, match="with_corpus should be of type bool"):
2264
- mock_elements_worker.list_element_parents(
2265
- element=elt,
2266
- with_corpus="not bool",
2267
- )
2268
-
2269
-
2270
- def test_list_element_parents_wrong_with_has_children(mock_elements_worker):
2271
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
2272
-
2273
- with pytest.raises(
2274
- AssertionError, match="with_has_children should be of type bool"
2275
- ):
2276
- mock_elements_worker.list_element_parents(
2277
- element=elt,
2278
- with_has_children="not bool",
2279
- )
2280
-
2281
-
2282
- def test_list_element_parents_wrong_with_zone(mock_elements_worker):
2283
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
2284
-
2285
- with pytest.raises(AssertionError, match="with_zone should be of type bool"):
2286
- mock_elements_worker.list_element_parents(
2287
- element=elt,
2288
- with_zone="not bool",
2289
- )
2290
-
2291
-
2292
- def test_list_element_parents_wrong_with_metadata(mock_elements_worker):
2293
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
2294
-
2295
- with pytest.raises(AssertionError, match="with_metadata should be of type bool"):
2296
- mock_elements_worker.list_element_parents(
2297
- element=elt,
2298
- with_metadata="not bool",
2299
- )
2300
-
2301
-
2302
- @pytest.mark.parametrize(
2303
- ("param", "value"),
2304
- [
2305
- ("worker_run", 1234),
2306
- ("transcription_worker_run", 1234),
2307
- ],
2308
- )
2309
- def test_list_element_parents_wrong_worker_run(mock_elements_worker, param, value):
2310
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
2311
-
2312
- with pytest.raises(AssertionError, match=f"{param} should be of type str or bool"):
2313
- mock_elements_worker.list_element_parents(
2314
- element=elt,
2315
- **{param: value},
2316
- )
2317
-
2318
-
2319
- @pytest.mark.parametrize(
2320
- ("param", "alternative", "value"),
2321
- [
2322
- ("worker_version", "worker_run", 1234),
2323
- ("transcription_worker_version", "transcription_worker_run", 1234),
2324
- ],
2325
- )
2326
- def test_list_element_parents_wrong_worker_version(
2327
- mock_elements_worker, param, alternative, value
2328
- ):
2329
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
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(AssertionError, match=f"{param} should be of type str or bool"),
2337
- ):
2338
- mock_elements_worker.list_element_parents(
2339
- element=elt,
2340
- **{param: value},
2341
- )
2342
-
2343
-
2344
- @pytest.mark.parametrize(
2345
- "param",
2346
- [
2347
- "worker_run",
2348
- "transcription_worker_run",
2349
- ],
2350
- )
2351
- def test_list_element_parents_wrong_bool_worker_run(mock_elements_worker, param):
2352
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
2353
-
2354
- with pytest.raises(
2355
- AssertionError, match=f"if of type bool, {param} can only be set to False"
2356
- ):
2357
- mock_elements_worker.list_element_parents(
2358
- element=elt,
2359
- **{param: True},
2360
- )
2361
-
2362
-
2363
- @pytest.mark.parametrize(
2364
- ("param", "alternative"),
2365
- [
2366
- ("worker_version", "worker_run"),
2367
- ("transcription_worker_version", "transcription_worker_run"),
2368
- ],
2369
- )
2370
- def test_list_element_parents_wrong_bool_worker_version(
2371
- mock_elements_worker, param, alternative
2372
- ):
2373
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
2374
-
2375
- # WARNING: pytest.deprecated_call must be placed BEFORE pytest.raises, otherwise `match` argument won't be checked
2376
- with (
2377
- pytest.deprecated_call(
2378
- match=f"`{param}` usage is deprecated. Consider using `{alternative}` instead."
2379
- ),
2380
- pytest.raises(
2381
- AssertionError, match=f"if of type bool, {param} can only be set to False"
2382
- ),
2383
- ):
2384
- mock_elements_worker.list_element_parents(
2385
- element=elt,
2386
- **{param: True},
2387
- )
2388
-
2389
-
2390
- def test_list_element_parents_api_error(responses, mock_elements_worker):
2391
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
2392
- responses.add(
2393
- responses.GET,
2394
- "http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/parents/",
2395
- status=500,
2396
- )
2397
-
2398
- with pytest.raises(
2399
- Exception, match="Stopping pagination as data will be incomplete"
2400
- ):
2401
- next(mock_elements_worker.list_element_parents(element=elt))
2402
-
2403
- assert len(responses.calls) == len(BASE_API_CALLS) + 5
2404
- assert [
2405
- (call.request.method, call.request.url) for call in responses.calls
2406
- ] == BASE_API_CALLS + [
2407
- # We do 5 retries
2408
- (
2409
- "GET",
2410
- "http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/parents/",
2411
- ),
2412
- (
2413
- "GET",
2414
- "http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/parents/",
2415
- ),
2416
- (
2417
- "GET",
2418
- "http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/parents/",
2419
- ),
2420
- (
2421
- "GET",
2422
- "http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/parents/",
2423
- ),
2424
- (
2425
- "GET",
2426
- "http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/parents/",
2427
- ),
2428
- ]
2429
-
2430
-
2431
- def test_list_element_parents(responses, mock_elements_worker):
2432
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
2433
- expected_parents = [
2434
- {
2435
- "id": "0000",
2436
- "type": "page",
2437
- "name": "Test",
2438
- "corpus": {},
2439
- "thumbnail_url": None,
2440
- "zone": {},
2441
- "best_classes": None,
2442
- "has_children": None,
2443
- "worker_version_id": None,
2444
- "worker_run_id": None,
2445
- },
2446
- {
2447
- "id": "1111",
2448
- "type": "page",
2449
- "name": "Test 2",
2450
- "corpus": {},
2451
- "thumbnail_url": None,
2452
- "zone": {},
2453
- "best_classes": None,
2454
- "has_children": None,
2455
- "worker_version_id": None,
2456
- "worker_run_id": None,
2457
- },
2458
- {
2459
- "id": "2222",
2460
- "type": "page",
2461
- "name": "Test 3",
2462
- "corpus": {},
2463
- "thumbnail_url": None,
2464
- "zone": {},
2465
- "best_classes": None,
2466
- "has_children": None,
2467
- "worker_version_id": None,
2468
- "worker_run_id": None,
2469
- },
2470
- ]
2471
- responses.add(
2472
- responses.GET,
2473
- "http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/parents/",
2474
- status=200,
2475
- json={
2476
- "count": 3,
2477
- "next": None,
2478
- "results": expected_parents,
2479
- },
2480
- )
2481
-
2482
- for idx, parent in enumerate(
2483
- mock_elements_worker.list_element_parents(element=elt)
2484
- ):
2485
- assert parent == expected_parents[idx]
2486
-
2487
- assert len(responses.calls) == len(BASE_API_CALLS) + 1
2488
- assert [
2489
- (call.request.method, call.request.url) for call in responses.calls
2490
- ] == BASE_API_CALLS + [
2491
- (
2492
- "GET",
2493
- "http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/parents/",
2494
- ),
2495
- ]
2496
-
2497
-
2498
- def test_list_element_parents_manual_worker_version(responses, mock_elements_worker):
2499
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
2500
- expected_parents = [
2501
- {
2502
- "id": "0000",
2503
- "type": "page",
2504
- "name": "Test",
2505
- "corpus": {},
2506
- "thumbnail_url": None,
2507
- "zone": {},
2508
- "best_classes": None,
2509
- "has_children": None,
2510
- "worker_version_id": None,
2511
- "worker_run_id": None,
2512
- }
2513
- ]
2514
- responses.add(
2515
- responses.GET,
2516
- "http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/parents/?worker_version=False",
2517
- status=200,
2518
- json={
2519
- "count": 1,
2520
- "next": None,
2521
- "results": expected_parents,
2522
- },
2523
- )
2524
-
2525
- with pytest.deprecated_call(
2526
- match="`worker_version` usage is deprecated. Consider using `worker_run` instead."
2527
- ):
2528
- for idx, parent in enumerate(
2529
- mock_elements_worker.list_element_parents(element=elt, worker_version=False)
2530
- ):
2531
- assert parent == expected_parents[idx]
2532
-
2533
- assert len(responses.calls) == len(BASE_API_CALLS) + 1
2534
- assert [
2535
- (call.request.method, call.request.url) for call in responses.calls
2536
- ] == BASE_API_CALLS + [
2537
- (
2538
- "GET",
2539
- "http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/parents/?worker_version=False",
2540
- ),
2541
- ]
2542
-
2543
-
2544
- def test_list_element_parents_manual_worker_run(responses, mock_elements_worker):
2545
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
2546
- expected_parents = [
2547
- {
2548
- "id": "0000",
2549
- "type": "page",
2550
- "name": "Test",
2551
- "corpus": {},
2552
- "thumbnail_url": None,
2553
- "zone": {},
2554
- "best_classes": None,
2555
- "has_children": None,
2556
- "worker_version_id": None,
2557
- "worker_run_id": None,
2558
- }
2559
- ]
2560
- responses.add(
2561
- responses.GET,
2562
- "http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/parents/?worker_run=False",
2563
- status=200,
2564
- json={
2565
- "count": 1,
2566
- "next": None,
2567
- "results": expected_parents,
2568
- },
2569
- )
2570
-
2571
- for idx, parent in enumerate(
2572
- mock_elements_worker.list_element_parents(element=elt, worker_run=False)
2573
- ):
2574
- assert parent == expected_parents[idx]
2575
-
2576
- assert len(responses.calls) == len(BASE_API_CALLS) + 1
2577
- assert [
2578
- (call.request.method, call.request.url) for call in responses.calls
2579
- ] == BASE_API_CALLS + [
2580
- (
2581
- "GET",
2582
- "http://testserver/api/v1/elements/12341234-1234-1234-1234-123412341234/parents/?worker_run=False",
2583
- ),
2584
- ]
2585
-
2586
-
2587
- def test_list_element_parents_with_cache_unhandled_param(
2588
- mock_elements_worker_with_cache,
2589
- ):
2590
- elt = Element({"id": "12341234-1234-1234-1234-123412341234"})
2591
-
2592
- with pytest.raises(
2593
- AssertionError,
2594
- match="When using the local cache, you can only filter by 'type' and/or 'worker_version' and/or 'worker_run'",
2595
- ):
2596
- mock_elements_worker_with_cache.list_element_parents(
2597
- element=elt, with_corpus=True
2598
- )
2599
-
2600
-
2601
- @pytest.mark.usefixtures("_mock_cached_elements")
2602
- @pytest.mark.parametrize(
2603
- ("filters", "expected_id"),
2604
- [
2605
- # Filter on element
2606
- (
2607
- {
2608
- "element": CachedElement(id="11111111-1111-1111-1111-111111111111"),
2609
- },
2610
- "12341234-1234-1234-1234-123412341234",
2611
- ),
2612
- # Filter on element and double_page
2613
- (
2614
- {
2615
- "element": CachedElement(id="22222222-2222-2222-2222-222222222222"),
2616
- "type": "double_page",
2617
- },
2618
- "12341234-1234-1234-1234-123412341234",
2619
- ),
2620
- # Filter on element and worker run
2621
- (
2622
- {
2623
- "element": CachedElement(id="22222222-2222-2222-2222-222222222222"),
2624
- "worker_run": "56785678-5678-5678-5678-567856785678",
2625
- },
2626
- "12341234-1234-1234-1234-123412341234",
2627
- ),
2628
- # Filter on element, manual worker run
2629
- (
2630
- {
2631
- "element": CachedElement(id="12341234-1234-1234-1234-123412341234"),
2632
- "worker_run": False,
2633
- },
2634
- "99999999-9999-9999-9999-999999999999",
2635
- ),
2636
- ],
2637
- )
2638
- def test_list_element_parents_with_cache(
2639
- responses,
2640
- mock_elements_worker_with_cache,
2641
- filters,
2642
- expected_id,
2643
- ):
2644
- # Check we have 5 elements already present in database
2645
- assert CachedElement.select().count() == 5
2646
-
2647
- # Query database through cache
2648
- elements = mock_elements_worker_with_cache.list_element_parents(**filters)
2649
- assert elements.count() == 1
2650
- for parent in elements.order_by("id"):
2651
- assert parent.id == UUID(expected_id)
2652
-
2653
- # Check the worker never hits the API for elements
2654
- assert len(responses.calls) == len(BASE_API_CALLS)
2655
- assert [
2656
- (call.request.method, call.request.url) for call in responses.calls
2657
- ] == BASE_API_CALLS
2658
-
2659
-
2660
- @pytest.mark.usefixtures("_mock_cached_elements")
2661
- @pytest.mark.parametrize(
2662
- ("filters", "expected_id"),
2663
- [
2664
- # Filter on element and worker version
2665
- (
2666
- {
2667
- "element": CachedElement(id="33333333-3333-3333-3333-333333333333"),
2668
- "worker_version": "56785678-5678-5678-5678-567856785678",
2669
- },
2670
- "12341234-1234-1234-1234-123412341234",
2671
- ),
2672
- # Filter on element, type double_page and worker version
2673
- (
2674
- {
2675
- "element": CachedElement(id="11111111-1111-1111-1111-111111111111"),
2676
- "type": "double_page",
2677
- "worker_version": "56785678-5678-5678-5678-567856785678",
2678
- },
2679
- "12341234-1234-1234-1234-123412341234",
2680
- ),
2681
- # Filter on element, manual worker version
2682
- (
2683
- {
2684
- "element": CachedElement(id="12341234-1234-1234-1234-123412341234"),
2685
- "worker_version": False,
2686
- },
2687
- "99999999-9999-9999-9999-999999999999",
2688
- ),
2689
- ],
2690
- )
2691
- def test_list_element_parents_with_cache_deprecation(
2692
- responses,
2693
- mock_elements_worker_with_cache,
2694
- filters,
2695
- expected_id,
2696
- ):
2697
- # Check we have 5 elements already present in database
2698
- assert CachedElement.select().count() == 5
2699
-
2700
- with pytest.deprecated_call(
2701
- match="`worker_version` usage is deprecated. Consider using `worker_run` instead."
2702
- ):
2703
- # Query database through cache
2704
- elements = mock_elements_worker_with_cache.list_element_parents(**filters)
2705
- assert elements.count() == 1
2706
- for parent in elements.order_by("id"):
2707
- assert parent.id == UUID(expected_id)
2708
-
2709
- # Check the worker never hits the API for elements
2710
- assert len(responses.calls) == len(BASE_API_CALLS)
2711
- assert [
2712
- (call.request.method, call.request.url) for call in responses.calls
2713
- ] == BASE_API_CALLS