arkindex-base-worker 0.5.0rc1__tar.gz → 0.5.1b1__tar.gz

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 (65) hide show
  1. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/PKG-INFO +3 -3
  2. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/arkindex_base_worker.egg-info/PKG-INFO +3 -3
  3. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/arkindex_base_worker.egg-info/requires.txt +2 -2
  4. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/arkindex_worker/worker/__init__.py +75 -6
  5. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/arkindex_worker/worker/element.py +9 -0
  6. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/pyproject.toml +3 -3
  7. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/conftest.py +33 -0
  8. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_elements_worker/test_worker.py +94 -0
  9. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/LICENSE +0 -0
  10. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/README.md +0 -0
  11. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/arkindex_base_worker.egg-info/SOURCES.txt +0 -0
  12. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/arkindex_base_worker.egg-info/dependency_links.txt +0 -0
  13. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/arkindex_base_worker.egg-info/top_level.txt +0 -0
  14. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/arkindex_worker/__init__.py +0 -0
  15. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/arkindex_worker/cache.py +0 -0
  16. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/arkindex_worker/image.py +0 -0
  17. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/arkindex_worker/models.py +0 -0
  18. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/arkindex_worker/utils.py +0 -0
  19. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/arkindex_worker/worker/base.py +0 -0
  20. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/arkindex_worker/worker/classification.py +0 -0
  21. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/arkindex_worker/worker/corpus.py +0 -0
  22. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/arkindex_worker/worker/dataset.py +0 -0
  23. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/arkindex_worker/worker/entity.py +0 -0
  24. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/arkindex_worker/worker/image.py +0 -0
  25. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/arkindex_worker/worker/metadata.py +0 -0
  26. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/arkindex_worker/worker/process.py +0 -0
  27. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/arkindex_worker/worker/task.py +0 -0
  28. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/arkindex_worker/worker/training.py +0 -0
  29. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/arkindex_worker/worker/transcription.py +0 -0
  30. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/examples/standalone/python/worker.py +0 -0
  31. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/examples/tooled/python/worker.py +0 -0
  32. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/hooks/pre_gen_project.py +0 -0
  33. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/setup.cfg +0 -0
  34. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/__init__.py +0 -0
  35. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_base_worker.py +0 -0
  36. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_cache.py +0 -0
  37. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_dataset_worker.py +0 -0
  38. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_element.py +0 -0
  39. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_elements_worker/__init__.py +0 -0
  40. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_elements_worker/test_classification.py +0 -0
  41. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_elements_worker/test_cli.py +0 -0
  42. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_elements_worker/test_corpus.py +0 -0
  43. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_elements_worker/test_dataset.py +0 -0
  44. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_elements_worker/test_element.py +0 -0
  45. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_elements_worker/test_element_create_multiple.py +0 -0
  46. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_elements_worker/test_element_create_single.py +0 -0
  47. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_elements_worker/test_element_list_children.py +0 -0
  48. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_elements_worker/test_element_list_parents.py +0 -0
  49. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_elements_worker/test_entity.py +0 -0
  50. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_elements_worker/test_image.py +0 -0
  51. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_elements_worker/test_metadata.py +0 -0
  52. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_elements_worker/test_process.py +0 -0
  53. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_elements_worker/test_task.py +0 -0
  54. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_elements_worker/test_training.py +0 -0
  55. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_elements_worker/test_transcription_create.py +0 -0
  56. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_elements_worker/test_transcription_create_with_elements.py +0 -0
  57. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_elements_worker/test_transcription_list.py +0 -0
  58. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_image.py +0 -0
  59. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_merge.py +0 -0
  60. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/tests/test_utils.py +0 -0
  61. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/worker-demo/tests/__init__.py +0 -0
  62. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/worker-demo/tests/conftest.py +0 -0
  63. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/worker-demo/tests/test_worker.py +0 -0
  64. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/worker-demo/worker_demo/__init__.py +0 -0
  65. {arkindex_base_worker-0.5.0rc1 → arkindex_base_worker-0.5.1b1}/worker-demo/worker_demo/worker.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arkindex-base-worker
3
- Version: 0.5.0rc1
3
+ Version: 0.5.1b1
4
4
  Summary: Base Worker to easily build Arkindex ML workflows
5
5
  Author-email: Teklia <contact@teklia.com>
6
6
  Maintainer-email: Teklia <contact@teklia.com>
@@ -43,10 +43,10 @@ Description-Content-Type: text/markdown
43
43
  License-File: LICENSE
44
44
  Requires-Dist: humanize==4.12.3
45
45
  Requires-Dist: peewee~=3.17
46
- Requires-Dist: Pillow==11.2.1
46
+ Requires-Dist: Pillow==11.3.0
47
47
  Requires-Dist: python-gnupg==0.5.4
48
48
  Requires-Dist: shapely==2.0.6
49
- Requires-Dist: teklia-toolbox==0.1.9
49
+ Requires-Dist: teklia-toolbox==0.1.11
50
50
  Requires-Dist: zstandard==0.23.0
51
51
  Provides-Extra: tests
52
52
  Requires-Dist: pytest==8.3.5; extra == "tests"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arkindex-base-worker
3
- Version: 0.5.0rc1
3
+ Version: 0.5.1b1
4
4
  Summary: Base Worker to easily build Arkindex ML workflows
5
5
  Author-email: Teklia <contact@teklia.com>
6
6
  Maintainer-email: Teklia <contact@teklia.com>
@@ -43,10 +43,10 @@ Description-Content-Type: text/markdown
43
43
  License-File: LICENSE
44
44
  Requires-Dist: humanize==4.12.3
45
45
  Requires-Dist: peewee~=3.17
46
- Requires-Dist: Pillow==11.2.1
46
+ Requires-Dist: Pillow==11.3.0
47
47
  Requires-Dist: python-gnupg==0.5.4
48
48
  Requires-Dist: shapely==2.0.6
49
- Requires-Dist: teklia-toolbox==0.1.9
49
+ Requires-Dist: teklia-toolbox==0.1.11
50
50
  Requires-Dist: zstandard==0.23.0
51
51
  Provides-Extra: tests
52
52
  Requires-Dist: pytest==8.3.5; extra == "tests"
@@ -1,9 +1,9 @@
1
1
  humanize==4.12.3
2
2
  peewee~=3.17
3
- Pillow==11.2.1
3
+ Pillow==11.3.0
4
4
  python-gnupg==0.5.4
5
5
  shapely==2.0.6
6
- teklia-toolbox==0.1.9
6
+ teklia-toolbox==0.1.11
7
7
  zstandard==0.23.0
8
8
 
9
9
  [tests]
@@ -32,6 +32,49 @@ from arkindex_worker.worker.task import TaskMixin
32
32
  from arkindex_worker.worker.transcription import TranscriptionMixin
33
33
 
34
34
 
35
+ class WorkerActivityIterator:
36
+ def __init__(self, api_client, types):
37
+ # Use same api client as main class
38
+ self.api_client = api_client
39
+
40
+ # Index element types by ID
41
+ self.types = {t["id"]: t["slug"] for t in types}
42
+
43
+ logger.info(
44
+ "Using StartWorkerActivity instead of reading init_elements JSON file"
45
+ )
46
+
47
+ def __bool__(self):
48
+ # Needed to bypass `not elements` check
49
+ return True
50
+
51
+ def __iter__(self):
52
+ return self
53
+
54
+ def __next__(self):
55
+ """
56
+ Provide a new element from a worker activity upon each iteration
57
+ """
58
+ try:
59
+ data = self.api_client.request("StartWorkerActivity")
60
+ except ErrorResponse as e:
61
+ # Arkindex will provide a 404 or 400 when there are no worker activities left or the task has completed
62
+ if e.status_code in (400, 404):
63
+ raise StopIteration from e
64
+
65
+ logger.warning(
66
+ f"Failed to start a new worker activity of element due to an API error: {e.content}"
67
+ )
68
+ raise e
69
+
70
+ # Find the type slug using API provided type_id
71
+ type_id = data["type_id"]
72
+ if type_id not in self.types:
73
+ raise Exception(f"Unknown type {type_id}")
74
+
75
+ return Element(type=self.types[type_id], **data)
76
+
77
+
35
78
  class ElementsWorker(
36
79
  ElementMixin,
37
80
  DatasetMixin,
@@ -60,7 +103,9 @@ class ElementsWorker(
60
103
  """
61
104
  super().__init__(description, support_cache)
62
105
 
63
- def get_elements(self) -> Iterable[CachedElement] | list[str] | list[Element]:
106
+ def get_elements(
107
+ self,
108
+ ) -> Iterable[CachedElement] | list[str] | list[Element] | WorkerActivityIterator:
64
109
  """
65
110
  List the elements to be processed, either from the CLI arguments or
66
111
  the cache database when enabled.
@@ -109,6 +154,14 @@ class ElementsWorker(
109
154
  elif self.process_mode == ProcessMode.Export:
110
155
  # For export mode processes, use list_process_elements and return element IDs
111
156
  return {item["id"] for item in self.list_process_elements()}
157
+ elif self.args.consume_worker_activities:
158
+ # We need to list corpus types as the StartWorkerActivity endpoint only provide type_id
159
+ self.list_corpus_types()
160
+
161
+ # Consume worker activitives one by one
162
+ return WorkerActivityIterator(
163
+ self.api_client, types=self.corpus_types.values()
164
+ )
112
165
 
113
166
  invalid_element_ids = list(filter(invalid_element_id, out))
114
167
  assert not invalid_element_ids, (
@@ -135,6 +188,15 @@ class ElementsWorker(
135
188
  )
136
189
  return self.process_information.get("activity_state") == "ready"
137
190
 
191
+ @property
192
+ def unknown_nb_elements(self) -> bool:
193
+ """
194
+ Whether or not the worker knows the total number of elements to process
195
+ - when running with init_elements, we have a known list
196
+ - when running with StartWorkerActivity, we have a queue of unknown size
197
+ """
198
+ return self.args.consume_worker_activities
199
+
138
200
  def run(self):
139
201
  """
140
202
  Implements an Arkindex worker that goes through each element returned by
@@ -157,7 +219,8 @@ class ElementsWorker(
157
219
  )
158
220
 
159
221
  # Process every element
160
- count = len(elements)
222
+ # We cannot know the number of elements when consuming a list of worker activities
223
+ count = None if self.unknown_nb_elements else len(elements)
161
224
  failed = 0
162
225
  for i, item in enumerate(elements, start=1):
163
226
  element = None
@@ -171,10 +234,16 @@ class ElementsWorker(
171
234
  **self.api_client.request("RetrieveElement", id=item)
172
235
  )
173
236
 
174
- logger.info(f"Processing {element} ({i}/{count})")
237
+ if self.unknown_nb_elements:
238
+ logger.info(f"Processing {element} (n°{i})")
239
+ else:
240
+ logger.info(f"Processing {element} ({i}/{count})")
175
241
 
176
242
  # Process the element and report its progress if activities are enabled
177
- if self.update_activity(element.id, ActivityState.Started):
243
+ # We do not update the worker activity to "Started" state when consuming them
244
+ if self.args.consume_worker_activities or self.update_activity(
245
+ element.id, ActivityState.Started
246
+ ):
178
247
  self.process_element(element)
179
248
  self.update_activity(element.id, ActivityState.Processed)
180
249
  else:
@@ -207,10 +276,10 @@ class ElementsWorker(
207
276
  with contextlib.suppress(Exception):
208
277
  self.update_activity(element.id, ActivityState.Error)
209
278
 
210
- message = f"Ran on {count} {pluralize('element', count)}: {count - failed} completed, {failed} failed"
279
+ message = f"Ran on {i} {pluralize('element', i)}: {i - failed} completed, {failed} failed"
211
280
  if failed:
212
281
  logger.error(message)
213
- if failed >= count: # Everything failed!
282
+ if failed >= i: # Everything failed!
214
283
  sys.exit(1)
215
284
  else:
216
285
  logger.info(message)
@@ -38,6 +38,15 @@ class ElementMixin:
38
38
  type=open,
39
39
  default=os.environ.get("TASK_ELEMENTS"),
40
40
  )
41
+ self.parser.add_argument(
42
+ "--no-elements-list",
43
+ help=(
44
+ "Consume worker activities from Arkindex API instead of using a static elements list"
45
+ ),
46
+ dest="consume_worker_activities",
47
+ action="store_true",
48
+ default=os.environ.get("SKIP_TASK_ELEMENTS") is not None,
49
+ )
41
50
  self.parser.add_argument(
42
51
  "--element",
43
52
  type=str,
@@ -4,16 +4,16 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "arkindex-base-worker"
7
- version = "0.5.0rc1"
7
+ version = "0.5.1b1"
8
8
  description = "Base Worker to easily build Arkindex ML workflows"
9
9
  license = { file = "LICENSE" }
10
10
  dependencies = [
11
11
  "humanize==4.12.3",
12
12
  "peewee~=3.17",
13
- "Pillow==11.2.1",
13
+ "Pillow==11.3.0",
14
14
  "python-gnupg==0.5.4",
15
15
  "shapely==2.0.6",
16
- "teklia-toolbox==0.1.9",
16
+ "teklia-toolbox==0.1.11",
17
17
  "zstandard==0.23.0",
18
18
  ]
19
19
  authors = [
@@ -282,6 +282,39 @@ def mock_elements_worker_with_list(monkeypatch, responses, mock_elements_worker)
282
282
  return mock_elements_worker
283
283
 
284
284
 
285
+ @pytest.fixture
286
+ def mock_elements_worker_consume_wa(monkeypatch, responses, mock_elements_worker):
287
+ """
288
+ Mock a worker instance to use StartWorkerActivity to consume worker activities
289
+ instead of reading a JSON file
290
+ """
291
+
292
+ # Enable consume worker activities mode from CLI args
293
+ mock_elements_worker.args.consume_worker_activities = True
294
+
295
+ # Worker requires element types from corpus details as they are not provided by StartWorkerActivity
296
+ responses.add(
297
+ responses.GET,
298
+ "http://testserver/api/v1/corpus/11111111-1111-1111-1111-111111111111/",
299
+ status=200,
300
+ json={
301
+ "id": "11111111-1111-1111-1111-111111111111",
302
+ "name": "Test corpus",
303
+ "types": [
304
+ {
305
+ "id": "page-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
306
+ "slug": "page",
307
+ "display_name": "Page",
308
+ "folder": False,
309
+ "color": "28b62c",
310
+ }
311
+ ],
312
+ },
313
+ )
314
+
315
+ return mock_elements_worker
316
+
317
+
285
318
  @pytest.fixture
286
319
  def mock_cache_db(tmp_path):
287
320
  cache_path = tmp_path / "db.sqlite"
@@ -685,6 +685,100 @@ def test_run_cache(monkeypatch, mocker, mock_elements_worker_with_cache):
685
685
  ]
686
686
 
687
687
 
688
+ def test_run_consuming_worker_activities(
689
+ monkeypatch,
690
+ mock_elements_worker_consume_wa,
691
+ responses,
692
+ caplog,
693
+ ):
694
+ """Check the consuming worker activities runtime uses StartWorkerActivity + UpdateWorkerActivity"""
695
+ # Disable second configure call from run()
696
+ monkeypatch.setattr(mock_elements_worker_consume_wa, "configure", lambda: None)
697
+
698
+ assert mock_elements_worker_consume_wa.is_read_only is False
699
+
700
+ # Provide 2 worker activities to run and the corresponding update call
701
+ for elt_id in ("page_1", "page_2"):
702
+ responses.add(
703
+ responses.POST,
704
+ "http://testserver/api/v1/process/start-activity/",
705
+ status=200,
706
+ json={
707
+ "id": elt_id,
708
+ "type_id": "page-aaaa-aaaa-aaaa-aaaaaaaaaaaa", # Element type provided by mock corpus
709
+ "name": "Page XXX",
710
+ },
711
+ )
712
+ responses.add(
713
+ responses.PUT,
714
+ "http://testserver/api/v1/workers/versions/56785678-5678-5678-5678-567856785678/activity/",
715
+ status=200,
716
+ )
717
+
718
+ # Then a 404 to stop iterating
719
+ responses.add(
720
+ responses.POST,
721
+ "http://testserver/api/v1/process/start-activity/",
722
+ status=404,
723
+ )
724
+
725
+ # Simply run the process
726
+ mock_elements_worker_consume_wa.run()
727
+
728
+ assert len(responses.calls) == len(BASE_API_CALLS) + 6
729
+ assert [
730
+ (call.request.method, call.request.url) for call in responses.calls
731
+ ] == BASE_API_CALLS + [
732
+ (
733
+ "GET",
734
+ "http://testserver/api/v1/corpus/11111111-1111-1111-1111-111111111111/",
735
+ ),
736
+ (
737
+ "POST",
738
+ "http://testserver/api/v1/process/start-activity/",
739
+ ),
740
+ (
741
+ "PUT",
742
+ "http://testserver/api/v1/workers/versions/56785678-5678-5678-5678-567856785678/activity/",
743
+ ),
744
+ (
745
+ "POST",
746
+ "http://testserver/api/v1/process/start-activity/",
747
+ ),
748
+ (
749
+ "PUT",
750
+ "http://testserver/api/v1/workers/versions/56785678-5678-5678-5678-567856785678/activity/",
751
+ ),
752
+ (
753
+ "POST",
754
+ "http://testserver/api/v1/process/start-activity/",
755
+ ),
756
+ ]
757
+
758
+ assert [(record.levelno, record.message) for record in caplog.records] == [
759
+ (
760
+ logging.INFO,
761
+ "Loaded 1 element type in corpus (11111111-1111-1111-1111-111111111111).",
762
+ ),
763
+ (
764
+ logging.INFO,
765
+ "Using StartWorkerActivity instead of reading init_elements JSON file",
766
+ ),
767
+ (
768
+ logging.INFO,
769
+ "Processing page Page XXX (page_1) (n°1)",
770
+ ),
771
+ (
772
+ logging.INFO,
773
+ "Processing page Page XXX (page_2) (n°2)",
774
+ ),
775
+ (
776
+ logging.INFO,
777
+ "Ran on 2 elements: 2 completed, 0 failed",
778
+ ),
779
+ ]
780
+
781
+
688
782
  def test_start_activity_conflict(
689
783
  monkeypatch, responses, mock_elements_worker_with_list, caplog
690
784
  ):