arkindex-base-worker 0.4.0rc5__py3-none-any.whl → 0.5.0__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 (41) hide show
  1. {arkindex_base_worker-0.4.0rc5.dist-info → arkindex_base_worker-0.5.0.dist-info}/METADATA +10 -13
  2. arkindex_base_worker-0.5.0.dist-info/RECORD +60 -0
  3. {arkindex_base_worker-0.4.0rc5.dist-info → arkindex_base_worker-0.5.0.dist-info}/WHEEL +1 -1
  4. {arkindex_base_worker-0.4.0rc5.dist-info → arkindex_base_worker-0.5.0.dist-info}/top_level.txt +1 -0
  5. arkindex_worker/__init__.py +3 -0
  6. arkindex_worker/cache.py +6 -25
  7. arkindex_worker/image.py +105 -66
  8. arkindex_worker/utils.py +2 -1
  9. arkindex_worker/worker/__init__.py +22 -32
  10. arkindex_worker/worker/base.py +16 -9
  11. arkindex_worker/worker/classification.py +36 -34
  12. arkindex_worker/worker/corpus.py +3 -3
  13. arkindex_worker/worker/dataset.py +9 -9
  14. arkindex_worker/worker/element.py +261 -231
  15. arkindex_worker/worker/entity.py +137 -206
  16. arkindex_worker/worker/image.py +3 -3
  17. arkindex_worker/worker/metadata.py +27 -38
  18. arkindex_worker/worker/process.py +24 -0
  19. arkindex_worker/worker/task.py +9 -9
  20. arkindex_worker/worker/training.py +15 -11
  21. arkindex_worker/worker/transcription.py +77 -71
  22. examples/standalone/python/worker.py +171 -0
  23. examples/tooled/python/worker.py +50 -0
  24. tests/conftest.py +22 -36
  25. tests/test_base_worker.py +1 -1
  26. tests/test_cache.py +1 -2
  27. tests/test_dataset_worker.py +1 -1
  28. tests/test_elements_worker/test_element.py +200 -26
  29. tests/test_elements_worker/{test_entity_create.py → test_entity.py} +220 -227
  30. tests/test_elements_worker/test_metadata.py +0 -47
  31. tests/test_elements_worker/test_process.py +89 -0
  32. tests/test_elements_worker/test_training.py +8 -8
  33. tests/test_elements_worker/test_worker.py +61 -14
  34. tests/test_image.py +244 -126
  35. tests/test_merge.py +0 -7
  36. tests/test_utils.py +37 -0
  37. arkindex_base_worker-0.4.0rc5.dist-info/RECORD +0 -60
  38. arkindex_worker/worker/version.py +0 -58
  39. tests/test_elements_worker/test_entity_list_and_check.py +0 -160
  40. tests/test_elements_worker/test_version.py +0 -60
  41. {arkindex_base_worker-0.4.0rc5.dist-info → arkindex_base_worker-0.5.0.dist-info/licenses}/LICENSE +0 -0
tests/conftest.py CHANGED
@@ -3,7 +3,6 @@ import json
3
3
  import os
4
4
  import sys
5
5
  import time
6
- from pathlib import Path
7
6
  from uuid import UUID
8
7
 
9
8
  import pytest
@@ -46,7 +45,7 @@ def _disable_sleep(monkeypatch):
46
45
  monkeypatch.setattr(time, "sleep", lambda x: None)
47
46
 
48
47
 
49
- @pytest.fixture()
48
+ @pytest.fixture
50
49
  def _cache_yaml(monkeypatch):
51
50
  """
52
51
  Cache all calls to yaml.safe_load in order to speedup
@@ -78,19 +77,6 @@ def _cache_yaml(monkeypatch):
78
77
  def _setup_api(responses, monkeypatch, _cache_yaml):
79
78
  # Always use the environment variable first
80
79
  schema_url = os.environ.get("ARKINDEX_API_SCHEMA_URL")
81
- if schema_url is None:
82
- # Try to load a local schema as the current developer of base-worker
83
- # may also work on the backend nearby
84
- paths = [
85
- "~/dev/ark/backend/schema.yml",
86
- "~/dev/ark/backend/output/schema.yml",
87
- ]
88
- for path in paths:
89
- path = Path(path).expanduser().absolute()
90
- if path.exists():
91
- monkeypatch.setenv("ARKINDEX_API_SCHEMA_URL", str(path))
92
- schema_url = str(path)
93
- break
94
80
 
95
81
  # Fallback to prod environment
96
82
  if schema_url is None:
@@ -111,7 +97,7 @@ def _give_env_variable(monkeypatch):
111
97
  monkeypatch.setenv("ARKINDEX_WORKER_RUN_ID", "56785678-5678-5678-5678-567856785678")
112
98
 
113
99
 
114
- @pytest.fixture()
100
+ @pytest.fixture
115
101
  def _mock_worker_run_api(responses):
116
102
  """Provide a mock API response to get worker run information"""
117
103
  payload = {
@@ -180,7 +166,7 @@ def _mock_worker_run_api(responses):
180
166
  )
181
167
 
182
168
 
183
- @pytest.fixture()
169
+ @pytest.fixture
184
170
  def _mock_worker_run_no_revision_api(responses):
185
171
  """Provide a mock API response to get worker run not linked to a revision information"""
186
172
  payload = {
@@ -247,7 +233,7 @@ def _mock_worker_run_no_revision_api(responses):
247
233
  )
248
234
 
249
235
 
250
- @pytest.fixture()
236
+ @pytest.fixture
251
237
  def _mock_activity_calls(responses):
252
238
  """
253
239
  Mock responses when updating the activity state for multiple element of the same version
@@ -259,7 +245,7 @@ def _mock_activity_calls(responses):
259
245
  )
260
246
 
261
247
 
262
- @pytest.fixture()
248
+ @pytest.fixture
263
249
  def mock_elements_worker(monkeypatch, _mock_worker_run_api):
264
250
  """Build and configure an ElementsWorker with fixed CLI parameters to avoid issues with pytest"""
265
251
  monkeypatch.setattr(sys, "argv", ["worker"])
@@ -268,7 +254,7 @@ def mock_elements_worker(monkeypatch, _mock_worker_run_api):
268
254
  return worker
269
255
 
270
256
 
271
- @pytest.fixture()
257
+ @pytest.fixture
272
258
  def mock_elements_worker_read_only(monkeypatch):
273
259
  """Build and configure an ElementsWorker with fixed CLI parameters to avoid issues with pytest"""
274
260
  monkeypatch.setattr(sys, "argv", ["worker", "--dev"])
@@ -277,7 +263,7 @@ def mock_elements_worker_read_only(monkeypatch):
277
263
  return worker
278
264
 
279
265
 
280
- @pytest.fixture()
266
+ @pytest.fixture
281
267
  def mock_elements_worker_with_list(monkeypatch, responses, mock_elements_worker):
282
268
  """
283
269
  Mock a worker instance to list and retrieve a single element
@@ -296,7 +282,7 @@ def mock_elements_worker_with_list(monkeypatch, responses, mock_elements_worker)
296
282
  return mock_elements_worker
297
283
 
298
284
 
299
- @pytest.fixture()
285
+ @pytest.fixture
300
286
  def mock_cache_db(tmp_path):
301
287
  cache_path = tmp_path / "db.sqlite"
302
288
 
@@ -307,7 +293,7 @@ def mock_cache_db(tmp_path):
307
293
  return cache_path
308
294
 
309
295
 
310
- @pytest.fixture()
296
+ @pytest.fixture
311
297
  def mock_base_worker_with_cache(monkeypatch, _mock_worker_run_api):
312
298
  """Build a BaseWorker using SQLite cache, also mocking a PONOS_TASK"""
313
299
  monkeypatch.setattr(sys, "argv", ["worker"])
@@ -318,7 +304,7 @@ def mock_base_worker_with_cache(monkeypatch, _mock_worker_run_api):
318
304
  return worker
319
305
 
320
306
 
321
- @pytest.fixture()
307
+ @pytest.fixture
322
308
  def mock_elements_worker_with_cache(monkeypatch, mock_cache_db, _mock_worker_run_api):
323
309
  """Build and configure an ElementsWorker using SQLite cache with fixed CLI parameters to avoid issues with pytest"""
324
310
  monkeypatch.setattr(sys, "argv", ["worker", "-d", str(mock_cache_db)])
@@ -329,17 +315,17 @@ def mock_elements_worker_with_cache(monkeypatch, mock_cache_db, _mock_worker_run
329
315
  return worker
330
316
 
331
317
 
332
- @pytest.fixture()
318
+ @pytest.fixture
333
319
  def model_file_dir():
334
320
  return SAMPLES_DIR / "model_files"
335
321
 
336
322
 
337
- @pytest.fixture()
323
+ @pytest.fixture
338
324
  def model_file_dir_with_subfolder():
339
325
  return SAMPLES_DIR / "root_folder"
340
326
 
341
327
 
342
- @pytest.fixture()
328
+ @pytest.fixture
343
329
  def fake_dummy_worker():
344
330
  api_client = MockApiClient()
345
331
  worker = ElementsWorker()
@@ -347,7 +333,7 @@ def fake_dummy_worker():
347
333
  return worker
348
334
 
349
335
 
350
- @pytest.fixture()
336
+ @pytest.fixture
351
337
  def _mock_cached_elements(mock_cache_db):
352
338
  """Insert few elements in local cache"""
353
339
  CachedElement.create(
@@ -392,7 +378,7 @@ def _mock_cached_elements(mock_cache_db):
392
378
  assert CachedElement.select().count() == 5
393
379
 
394
380
 
395
- @pytest.fixture()
381
+ @pytest.fixture
396
382
  def _mock_cached_images(mock_cache_db):
397
383
  """Insert few elements in local cache"""
398
384
  CachedImage.create(
@@ -404,7 +390,7 @@ def _mock_cached_images(mock_cache_db):
404
390
  assert CachedImage.select().count() == 1
405
391
 
406
392
 
407
- @pytest.fixture()
393
+ @pytest.fixture
408
394
  def _mock_cached_transcriptions(mock_cache_db):
409
395
  """Insert few transcriptions in local cache, on a shared element"""
410
396
  CachedElement.create(
@@ -493,7 +479,7 @@ def _mock_cached_transcriptions(mock_cache_db):
493
479
  )
494
480
 
495
481
 
496
- @pytest.fixture()
482
+ @pytest.fixture
497
483
  def mock_databases(tmp_path):
498
484
  """
499
485
  Initialize several temporary databases
@@ -576,7 +562,7 @@ def mock_databases(tmp_path):
576
562
  return out
577
563
 
578
564
 
579
- @pytest.fixture()
565
+ @pytest.fixture
580
566
  def default_dataset():
581
567
  return Dataset(
582
568
  {
@@ -594,12 +580,12 @@ def default_dataset():
594
580
  )
595
581
 
596
582
 
597
- @pytest.fixture()
583
+ @pytest.fixture
598
584
  def default_train_set(default_dataset):
599
585
  return Set(name="train", dataset=default_dataset)
600
586
 
601
587
 
602
- @pytest.fixture()
588
+ @pytest.fixture
603
589
  def mock_dataset_worker(monkeypatch, mocker, _mock_worker_run_api):
604
590
  monkeypatch.setenv("PONOS_TASK", "my_task")
605
591
  mocker.patch.object(sys, "argv", ["worker"])
@@ -615,7 +601,7 @@ def mock_dataset_worker(monkeypatch, mocker, _mock_worker_run_api):
615
601
  return dataset_worker
616
602
 
617
603
 
618
- @pytest.fixture()
604
+ @pytest.fixture
619
605
  def mock_dev_dataset_worker(mocker):
620
606
  mocker.patch.object(
621
607
  sys,
@@ -640,7 +626,7 @@ def mock_dev_dataset_worker(mocker):
640
626
  return dataset_worker
641
627
 
642
628
 
643
- @pytest.fixture()
629
+ @pytest.fixture
644
630
  def default_artifact():
645
631
  return Artifact(
646
632
  **{
tests/test_base_worker.py CHANGED
@@ -803,7 +803,7 @@ def test_corpus_id_set_read_only_mode(
803
803
  },
804
804
  {},
805
805
  {},
806
- {"parameter": 0},
806
+ {"parameter": 0, "parameter2": None},
807
807
  ),
808
808
  # Keep parameters from worker version configuration but user_config defaults overrides
809
809
  (
tests/test_cache.py CHANGED
@@ -60,9 +60,8 @@ def test_create_tables(tmp_path):
60
60
  CREATE TABLE "dataset_elements" ("id" TEXT NOT NULL PRIMARY KEY, "element_id" TEXT NOT NULL, "dataset_id" TEXT NOT NULL, "set_name" VARCHAR(255) NOT NULL, FOREIGN KEY ("element_id") REFERENCES "elements" ("id"), FOREIGN KEY ("dataset_id") REFERENCES "datasets" ("id"))
61
61
  CREATE TABLE "datasets" ("id" TEXT NOT NULL PRIMARY KEY, "name" VARCHAR(255) NOT NULL, "state" VARCHAR(255) NOT NULL DEFAULT 'open', "sets" TEXT NOT NULL)
62
62
  CREATE TABLE "elements" ("id" TEXT NOT NULL PRIMARY KEY, "parent_id" TEXT, "type" VARCHAR(50) NOT NULL, "image_id" TEXT, "polygon" text, "rotation_angle" INTEGER NOT NULL, "mirrored" INTEGER NOT NULL, "initial" INTEGER NOT NULL, "worker_version_id" TEXT, "worker_run_id" TEXT, "confidence" REAL, FOREIGN KEY ("image_id") REFERENCES "images" ("id"))
63
- CREATE TABLE "entities" ("id" TEXT NOT NULL PRIMARY KEY, "type" VARCHAR(50) NOT NULL, "name" TEXT NOT NULL, "validated" INTEGER NOT NULL, "metas" text, "worker_run_id" TEXT)
64
63
  CREATE TABLE "images" ("id" TEXT NOT NULL PRIMARY KEY, "width" INTEGER NOT NULL, "height" INTEGER NOT NULL, "url" TEXT NOT NULL)
65
- CREATE TABLE "transcription_entities" ("transcription_id" TEXT NOT NULL, "entity_id" TEXT NOT NULL, "offset" INTEGER NOT NULL CHECK (offset >= 0), "length" INTEGER NOT NULL CHECK (length > 0), "worker_run_id" TEXT, "confidence" REAL, PRIMARY KEY ("transcription_id", "entity_id"), FOREIGN KEY ("transcription_id") REFERENCES "transcriptions" ("id"), FOREIGN KEY ("entity_id") REFERENCES "entities" ("id"))
64
+ CREATE TABLE "transcription_entities" ("transcription_id" TEXT NOT NULL, "type" VARCHAR(50) NOT NULL, "offset" INTEGER NOT NULL CHECK (offset >= 0), "length" INTEGER NOT NULL CHECK (length > 0), "worker_run_id" TEXT, "confidence" REAL, PRIMARY KEY ("transcription_id", "type"), FOREIGN KEY ("transcription_id") REFERENCES "transcriptions" ("id"))
66
65
  CREATE TABLE "transcriptions" ("id" TEXT NOT NULL PRIMARY KEY, "element_id" TEXT NOT NULL, "text" TEXT NOT NULL, "confidence" REAL, "orientation" VARCHAR(50) NOT NULL, "worker_version_id" TEXT, "worker_run_id" TEXT, FOREIGN KEY ("element_id") REFERENCES "elements" ("id"))"""
67
66
 
68
67
  actual_schema = "\n".join(
@@ -17,7 +17,7 @@ from tests.test_elements_worker import BASE_API_CALLS
17
17
  RANDOM_UUID = uuid.uuid4()
18
18
 
19
19
 
20
- @pytest.fixture()
20
+ @pytest.fixture
21
21
  def tmp_archive(tmp_path):
22
22
  archive = tmp_path / "test_archive.tar.zst"
23
23
  archive.touch()
@@ -10,7 +10,7 @@ from arkindex_worker.cache import (
10
10
  CachedImage,
11
11
  )
12
12
  from arkindex_worker.models import Element
13
- from arkindex_worker.worker.element import MissingTypeError
13
+ from arkindex_worker.worker.element import MissingElementType
14
14
  from tests import CORPUS_ID
15
15
 
16
16
  from . import BASE_API_CALLS
@@ -34,73 +34,247 @@ def test_list_corpus_types(responses, mock_elements_worker):
34
34
  }
35
35
 
36
36
 
37
- def test_check_required_types_argument_types(mock_elements_worker):
37
+ def test_create_element_type_wrong_slug(mock_elements_worker):
38
38
  with pytest.raises(
39
- AssertionError, match="At least one element type slug is required."
39
+ AssertionError, match="slug shouldn't be null and should be of type str"
40
40
  ):
41
- mock_elements_worker.check_required_types()
41
+ mock_elements_worker.create_element_type(slug=None, name="page")
42
42
 
43
- with pytest.raises(AssertionError, match="Element type slugs must be strings."):
44
- mock_elements_worker.check_required_types("lol", 42)
43
+ with pytest.raises(
44
+ AssertionError, match="slug shouldn't be null and should be of type str"
45
+ ):
46
+ mock_elements_worker.create_element_type(slug=1234, name="page")
45
47
 
46
48
 
47
- def test_check_required_types(mock_elements_worker):
48
- mock_elements_worker.corpus_types = {
49
- "folder": {"slug": "folder"},
50
- "page": {"slug": "page"},
51
- }
49
+ def test_create_element_type_wrong_name(mock_elements_worker):
50
+ with pytest.raises(
51
+ AssertionError, match="name shouldn't be null and should be of type str"
52
+ ):
53
+ mock_elements_worker.create_element_type(slug="page", name=None)
54
+
55
+ with pytest.raises(
56
+ AssertionError, match="name shouldn't be null and should be of type str"
57
+ ):
58
+ mock_elements_worker.create_element_type(slug="page", name=1234)
52
59
 
53
- assert mock_elements_worker.check_required_types("page")
54
- assert mock_elements_worker.check_required_types("page", "folder")
55
60
 
61
+ def test_create_element_type_wrong_is_folder(mock_elements_worker):
56
62
  with pytest.raises(
57
- MissingTypeError,
58
- match=re.escape(
59
- "Element types act, text_line were not found in corpus (11111111-1111-1111-1111-111111111111)."
60
- ),
63
+ AssertionError, match="is_folder shouldn't be null and should be of type bool"
64
+ ):
65
+ mock_elements_worker.create_element_type(
66
+ slug="page", name="page", is_folder=None
67
+ )
68
+
69
+ with pytest.raises(
70
+ AssertionError, match="is_folder shouldn't be null and should be of type bool"
61
71
  ):
62
- assert mock_elements_worker.check_required_types("page", "text_line", "act")
72
+ mock_elements_worker.create_element_type(
73
+ slug="page", name="page", is_folder=1234
74
+ )
75
+
76
+
77
+ def test_create_element_type_api_error(responses, mock_elements_worker):
78
+ responses.add(
79
+ responses.POST,
80
+ "http://testserver/api/v1/elements/type/",
81
+ status=418,
82
+ )
83
+
84
+ with pytest.raises(ErrorResponse):
85
+ mock_elements_worker.create_element_type(slug="page", name="page")
86
+
87
+ assert len(responses.calls) == len(BASE_API_CALLS) + 1
88
+ assert [
89
+ (call.request.method, call.request.url) for call in responses.calls
90
+ ] == BASE_API_CALLS + [("POST", "http://testserver/api/v1/elements/type/")]
91
+
63
92
 
93
+ def test_create_element_type_already_exists(responses, mock_elements_worker):
94
+ assert mock_elements_worker.corpus_types == {}
64
95
 
65
- def test_check_required_types_create_missing(responses, mock_elements_worker):
66
- mock_elements_worker.corpus_types = {
96
+ responses.add(
97
+ responses.POST,
98
+ "http://testserver/api/v1/elements/type/",
99
+ status=400,
100
+ match=[
101
+ matchers.json_params_matcher(
102
+ {
103
+ "slug": "page",
104
+ "display_name": "page",
105
+ "folder": False,
106
+ "corpus": CORPUS_ID,
107
+ }
108
+ )
109
+ ],
110
+ )
111
+ responses.add(
112
+ responses.GET,
113
+ f"http://testserver/api/v1/corpus/{CORPUS_ID}/",
114
+ status=200,
115
+ json={
116
+ "id": CORPUS_ID,
117
+ "types": [{"slug": "folder"}, {"slug": "page"}],
118
+ },
119
+ )
120
+
121
+ mock_elements_worker.create_element_type(slug="page", name="page")
122
+
123
+ assert len(responses.calls) == len(BASE_API_CALLS) + 2
124
+ assert [
125
+ (call.request.method, call.request.url) for call in responses.calls
126
+ ] == BASE_API_CALLS + [
127
+ ("POST", "http://testserver/api/v1/elements/type/"),
128
+ ("GET", f"http://testserver/api/v1/corpus/{CORPUS_ID}/"),
129
+ ]
130
+
131
+ # Make sure the corpus_types attribute has been updated
132
+ assert mock_elements_worker.corpus_types == {
67
133
  "folder": {"slug": "folder"},
68
134
  "page": {"slug": "page"},
69
135
  }
70
136
 
137
+
138
+ def test_create_element_type(responses, mock_elements_worker):
139
+ assert mock_elements_worker.corpus_types == {}
140
+
71
141
  responses.add(
72
142
  responses.POST,
73
143
  "http://testserver/api/v1/elements/type/",
144
+ status=200,
74
145
  match=[
75
146
  matchers.json_params_matcher(
76
147
  {
77
- "slug": "text_line",
78
- "display_name": "text_line",
148
+ "slug": "page",
149
+ "display_name": "page",
79
150
  "folder": False,
80
151
  "corpus": CORPUS_ID,
81
152
  }
82
153
  )
83
154
  ],
155
+ json={"id": "page-id", "slug": "page", "display_name": "page", "folder": False},
84
156
  )
157
+
158
+ mock_elements_worker.create_element_type(slug="page", name="page")
159
+
160
+ assert len(responses.calls) == len(BASE_API_CALLS) + 1
161
+ assert [
162
+ (call.request.method, call.request.url) for call in responses.calls
163
+ ] == BASE_API_CALLS + [
164
+ ("POST", "http://testserver/api/v1/elements/type/"),
165
+ ]
166
+
167
+ # Make sure the corpus_types attribute has been updated
168
+ assert mock_elements_worker.corpus_types == {
169
+ "page": {
170
+ "id": "page-id",
171
+ "slug": "page",
172
+ "display_name": "page",
173
+ "folder": False,
174
+ }
175
+ }
176
+
177
+
178
+ def test_check_required_types_wrong_type_slugs(mock_elements_worker):
179
+ with pytest.raises(
180
+ AssertionError, match="type_slugs shouldn't be null and should be of type list"
181
+ ):
182
+ mock_elements_worker.check_required_types(type_slugs=None)
183
+
184
+ with pytest.raises(
185
+ AssertionError, match="type_slugs shouldn't be null and should be of type list"
186
+ ):
187
+ mock_elements_worker.check_required_types(type_slugs=1234)
188
+
189
+ with pytest.raises(
190
+ AssertionError,
191
+ match="Element type at index 1 in type_slugs: Should be of type str",
192
+ ):
193
+ mock_elements_worker.check_required_types(type_slugs=["page", 1234])
194
+
195
+
196
+ def test_check_required_types_wrong_create_missing(mock_elements_worker):
197
+ with pytest.raises(
198
+ AssertionError,
199
+ match="create_missing shouldn't be null and should be of type bool",
200
+ ):
201
+ mock_elements_worker.check_required_types(
202
+ type_slugs=["page"], create_missing=None
203
+ )
204
+
205
+ with pytest.raises(
206
+ AssertionError,
207
+ match="create_missing shouldn't be null and should be of type bool",
208
+ ):
209
+ mock_elements_worker.check_required_types(
210
+ type_slugs=["page"], create_missing=1234
211
+ )
212
+
213
+
214
+ def test_check_required_types_do_not_create_missing(responses, mock_elements_worker):
215
+ # Set one element type
216
+ mock_elements_worker.corpus_types = {"folder": {"slug": "folder"}}
217
+
218
+ with pytest.raises(
219
+ MissingElementType, match="Element type `page` was not in the corpus."
220
+ ):
221
+ mock_elements_worker.check_required_types(
222
+ type_slugs=["folder", "page"], create_missing=False
223
+ )
224
+
225
+ assert len(responses.calls) == len(BASE_API_CALLS)
226
+ assert [
227
+ (call.request.method, call.request.url) for call in responses.calls
228
+ ] == BASE_API_CALLS
229
+
230
+
231
+ def test_check_required_types(responses, mock_elements_worker):
232
+ # Set one element type
233
+ mock_elements_worker.corpus_types = {"folder": {"slug": "folder"}}
234
+
235
+ # Call to create a new element type
85
236
  responses.add(
86
237
  responses.POST,
87
238
  "http://testserver/api/v1/elements/type/",
239
+ status=200,
88
240
  match=[
89
241
  matchers.json_params_matcher(
90
242
  {
91
- "slug": "act",
92
- "display_name": "act",
243
+ "slug": "page",
244
+ "display_name": "page",
93
245
  "folder": False,
94
246
  "corpus": CORPUS_ID,
95
247
  }
96
248
  )
97
249
  ],
250
+ json={"id": "page-id", "slug": "page", "display_name": "page", "folder": False},
98
251
  )
99
252
 
100
- assert mock_elements_worker.check_required_types(
101
- "page", "text_line", "act", create_missing=True
253
+ mock_elements_worker.check_required_types(
254
+ type_slugs=["folder", "page"], create_missing=True
102
255
  )
103
256
 
257
+ assert len(responses.calls) == len(BASE_API_CALLS) + 1
258
+ assert [
259
+ (call.request.method, call.request.url) for call in responses.calls
260
+ ] == BASE_API_CALLS + [
261
+ (
262
+ "POST",
263
+ "http://testserver/api/v1/elements/type/",
264
+ ),
265
+ ]
266
+
267
+ # Make sure the element_types attribute has been updated
268
+ assert mock_elements_worker.corpus_types == {
269
+ "folder": {"slug": "folder"},
270
+ "page": {
271
+ "id": "page-id",
272
+ "slug": "page",
273
+ "display_name": "page",
274
+ "folder": False,
275
+ },
276
+ }
277
+
104
278
 
105
279
  @pytest.mark.parametrize(
106
280
  ("payload", "error"),