From 1343ed80deddbe08d8c01bd2d715a00dace4e56e Mon Sep 17 00:00:00 2001 From: Valentin Rigal <rigal@teklia.com> Date: Wed, 14 Aug 2024 14:19:56 +0000 Subject: [PATCH] Remove Repository, Revision and GitRef models --- arkindex/documents/api/elements.py | 4 +- arkindex/documents/export/structure.sql | 5 +- arkindex/documents/export/worker_version.sql | 4 +- arkindex/documents/fixtures/data.json | 1555 ++++++++--------- .../management/commands/bootstrap.py | 37 +- .../management/commands/build_fixtures.py | 7 - .../management/commands/load_export.py | 30 +- .../documents/tests/commands/test_cleanup.py | 38 +- .../tests/commands/test_load_export.py | 7 +- .../tests/tasks/test_corpus_delete.py | 12 - arkindex/ponos/tests/test_api.py | 3 +- arkindex/process/admin.py | 38 +- arkindex/process/api.py | 113 +- arkindex/process/builder.py | 2 +- arkindex/process/managers.py | 5 +- arkindex/process/migrations/0001_initial.py | 8 +- ...url_workerversion_revision_url_and_more.py | 11 +- .../0041_drop_old_git_references.py | 87 + arkindex/process/models.py | 117 +- arkindex/process/serializers/git.py | 39 - arkindex/process/serializers/worker_runs.py | 26 +- arkindex/process/serializers/workers.py | 238 +-- .../commands/test_fake_worker_version.py | 21 +- .../process/tests/test_corpus_worker_runs.py | 2 - arkindex/process/tests/test_create_process.py | 2 +- .../tests/test_docker_worker_version.py | 885 ---------- .../process/tests/test_user_workerruns.py | 21 +- arkindex/process/tests/test_workerruns.py | 139 +- .../process/tests/test_workerruns_use_gpu.py | 3 - arkindex/process/tests/test_workers.py | 194 +- arkindex/project/api_v1.py | 2 - arkindex/project/argparse.py | 7 +- arkindex/project/tests/test_acl_mixin.py | 29 +- arkindex/project/tests/test_checks.py | 4 - arkindex/sql_validation/indexer_prefetch.sql | 4 - 35 files changed, 1001 insertions(+), 2698 deletions(-) create mode 100644 arkindex/process/migrations/0041_drop_old_git_references.py delete mode 100644 arkindex/process/serializers/git.py delete mode 100644 arkindex/process/tests/test_docker_worker_version.py diff --git a/arkindex/documents/api/elements.py b/arkindex/documents/api/elements.py index 831f54678d..79a1611358 100644 --- a/arkindex/documents/api/elements.py +++ b/arkindex/documents/api/elements.py @@ -2332,8 +2332,8 @@ class WorkerResultsDestroy(CorpusACLMixin, DestroyAPIView): errors["worker_version_id"].append("Invalid UUID.") else: try: - # Includes the worker and revision to get a nice job display name - worker_version = WorkerVersion.objects.select_related("worker", "revision").get(id=worker_version_id) + # Includes the worker to get a nice job display name + worker_version = WorkerVersion.objects.select_related("worker").get(id=worker_version_id) except WorkerVersion.DoesNotExist: errors["worker_version_id"].append("This worker version does not exist.") diff --git a/arkindex/documents/export/structure.sql b/arkindex/documents/export/structure.sql index da2bafd292..61cb727841 100644 --- a/arkindex/documents/export/structure.sql +++ b/arkindex/documents/export/structure.sql @@ -31,11 +31,10 @@ CREATE TABLE worker_version ( slug VARCHAR(100) NOT NULL, type VARCHAR(50) NOT NULL, version INTEGER, - revision VARCHAR(50), + revision VARCHAR(200), repository_url TEXT, PRIMARY KEY (id), - CHECK ((version IS NULL) <> (revision IS NULL)), - CHECK ((revision IS NULL) == (repository_url IS NULL)) + CHECK ((version IS NULL) <> (revision IS NULL)) ); CREATE TABLE worker_run ( diff --git a/arkindex/documents/export/worker_version.sql b/arkindex/documents/export/worker_version.sql index b99e66ea6a..98f10f00b0 100644 --- a/arkindex/documents/export/worker_version.sql +++ b/arkindex/documents/export/worker_version.sql @@ -3,13 +3,11 @@ -- fills up the RAM. Adding DISTINCT to all the SELECT queries of the UNION -- slows this query down by ~20%. Using multiple INs instead of a UNION makes -- this query twice as slow. -SELECT DISTINCT version.id, worker.name, worker.slug, workertype.slug, version.version, revision.hash, repository.url +SELECT DISTINCT version.id, worker.name, worker.slug, workertype.slug, version.version, version.revision_url, worker.repository_url FROM process_workerrun run INNER JOIN process_workerversion version ON (run.version_id = version.id) INNER JOIN process_worker worker ON (version.worker_id = worker.id) INNER JOIN process_workertype workertype ON (worker.type_id = workertype.id) -LEFT JOIN process_repository repository ON (worker.repository_id = repository.id) -LEFT JOIN process_revision revision ON (version.revision_id = revision.id) WHERE run.id IN ( SELECT worker_run_id FROM documents_element WHERE corpus_id = '{corpus_id}'::uuid UNION diff --git a/arkindex/documents/fixtures/data.json b/arkindex/documents/fixtures/data.json index d94044f342..5adf99eabd 100644 --- a/arkindex/documents/fixtures/data.json +++ b/arkindex/documents/fixtures/data.json @@ -1,7 +1,7 @@ [ { "model": "process.process", - "pk": "0be71517-084c-435b-be54-8dba120c86fd", + "pk": "374c483b-62b1-4565-8834-0ab2c4960c25", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", @@ -29,18 +29,18 @@ }, { "model": "process.process", - "pk": "74b5620c-6d18-4ac6-b685-f900c5d6c19d", + "pk": "38e459b9-2ffa-4bc6-b389-03a9a76d9deb", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "name": null, + "name": "Process fixture", "creator": 2, - "corpus": null, - "mode": "local", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "mode": "workers", "activity_state": "disabled", "started": null, "finished": null, - "farm": null, + "farm": "f2a2e1cb-2090-4b69-b204-1a40440e2619", "element": null, "folder_type": null, "element_type": null, @@ -57,18 +57,18 @@ }, { "model": "process.process", - "pk": "d4cada0d-d5b3-48ed-bffc-db53c8cf5e75", + "pk": "da1ca18e-736e-4123-8d66-27385205494d", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "name": "Process fixture", + "name": null, "creator": 2, - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "mode": "workers", + "corpus": null, + "mode": "local", "activity_state": "disabled", "started": null, "finished": null, - "farm": "283c0517-96d3-4f61-8847-7245b131ad32", + "farm": null, "element": null, "folder_type": null, "element_type": null, @@ -85,128 +85,128 @@ }, { "model": "process.worker", - "pk": "25d91339-d832-4d88-a9f9-a1888577964a", + "pk": "2666efcd-09df-49e5-9504-92953561ba23", "fields": { - "name": "Custom worker", - "slug": "custom", - "type": "e50aaede-98de-439a-bc81-30996d467a35", + "name": "Generic worker with a Model", + "slug": "generic", + "type": "32060b55-22ca-447b-bc7a-1aafd38d6521", "description": "", - "repository": null, "public": false, - "archived": null + "archived": null, + "repository_url": null } }, { "model": "process.worker", - "pk": "373d2b71-e62c-48d5-bbbb-5ad0a7b350db", + "pk": "aa0da253-2300-4b80-9403-1247b1c473ba", "fields": { - "name": "Recognizer", - "slug": "reco", - "type": "9a219473-8d92-4dfe-8888-5a4b447581e3", + "name": "File import", + "slug": "file_import", + "type": "5ad90007-3888-4973-8ce8-98515a66f640", "description": "", - "repository": null, "public": false, - "archived": null + "archived": null, + "repository_url": null } }, { "model": "process.worker", - "pk": "39e29762-5353-4cde-b909-964a87584224", + "pk": "b391fd40-ca4b-4963-b49b-96ac34ad2e1d", "fields": { - "name": "Document layout analyser", - "slug": "dla", - "type": "0137a4d7-e9fa-4e5c-b91c-7d3cdb16f53c", + "name": "Custom worker", + "slug": "custom", + "type": "39b4a530-423d-4f0d-9729-a010279bb2d0", "description": "", - "repository": null, "public": false, - "archived": null + "archived": null, + "repository_url": null } }, { "model": "process.worker", - "pk": "3d6138ea-96cd-47ad-bb51-02eae6120a37", + "pk": "c3a739d0-024e-4405-bc07-f8736d701623", "fields": { - "name": "Elements Initialisation Worker", - "slug": "initialisation", - "type": "30c46054-6ef6-407e-8490-1c9e0e80e29b", + "name": "Document layout analyser", + "slug": "dla", + "type": "8e44b24b-205c-4eda-b41f-37ca0f802e27", "description": "", - "repository": null, "public": false, - "archived": null + "archived": null, + "repository_url": null } }, { "model": "process.worker", - "pk": "5cd08382-8a64-499a-a648-12c5bc0509d2", + "pk": "cbaebcd5-3c7b-4e9a-9b93-1a2ff6521273", "fields": { - "name": "Worker requiring a GPU", - "slug": "worker-gpu", - "type": "09be5419-06d7-44ef-9147-692290f9d6f1", + "name": "Recognizer", + "slug": "reco", + "type": "32060b55-22ca-447b-bc7a-1aafd38d6521", "description": "", - "repository": null, "public": false, - "archived": null + "archived": null, + "repository_url": null } }, { "model": "process.worker", - "pk": "651dd631-7904-4ba7-a1f7-f4789f938e63", + "pk": "d99d8050-297c-41db-85b1-8760ae6875b7", "fields": { - "name": "File import", - "slug": "file_import", - "type": "627f9595-3f0c-4ca1-bc7a-f8274de8030c", + "name": "Elements Initialisation Worker", + "slug": "initialisation", + "type": "b3376082-2033-4dde-a834-8829445baaf6", "description": "", - "repository": null, "public": false, - "archived": null + "archived": null, + "repository_url": null } }, { "model": "process.worker", - "pk": "7d080fa4-f74c-40c2-8b30-b20da5a459c2", + "pk": "fb83b17c-c9cf-43e5-9ef8-e1362381dd09", "fields": { - "name": "Generic worker with a Model", - "slug": "generic", - "type": "9a219473-8d92-4dfe-8888-5a4b447581e3", + "name": "Worker requiring a GPU", + "slug": "worker-gpu", + "type": "44c4defd-0619-4982-8e52-5663cfec9e1f", "description": "", - "repository": null, "public": false, - "archived": null + "archived": null, + "repository_url": null } }, { "model": "process.workertype", - "pk": "0137a4d7-e9fa-4e5c-b91c-7d3cdb16f53c", + "pk": "32060b55-22ca-447b-bc7a-1aafd38d6521", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "slug": "dla", - "display_name": "Document Layout Analysis" + "slug": "recognizer", + "display_name": "Recognizer" } }, { "model": "process.workertype", - "pk": "09be5419-06d7-44ef-9147-692290f9d6f1", + "pk": "39b4a530-423d-4f0d-9729-a010279bb2d0", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "slug": "worker", - "display_name": "Worker requiring a GPU" + "slug": "custom", + "display_name": "Custom" } }, { "model": "process.workertype", - "pk": "30c46054-6ef6-407e-8490-1c9e0e80e29b", + "pk": "44c4defd-0619-4982-8e52-5663cfec9e1f", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "slug": "init", - "display_name": "Elements Initialisation" + "slug": "worker", + "display_name": "Worker requiring a GPU" } }, { "model": "process.workertype", - "pk": "627f9595-3f0c-4ca1-bc7a-f8274de8030c", + "pk": "5ad90007-3888-4973-8ce8-98515a66f640", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", @@ -216,156 +216,163 @@ }, { "model": "process.workertype", - "pk": "9a219473-8d92-4dfe-8888-5a4b447581e3", + "pk": "8e44b24b-205c-4eda-b41f-37ca0f802e27", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "slug": "recognizer", - "display_name": "Recognizer" + "slug": "dla", + "display_name": "Document Layout Analysis" } }, { "model": "process.workertype", - "pk": "e50aaede-98de-439a-bc81-30996d467a35", + "pk": "b3376082-2033-4dde-a834-8829445baaf6", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "slug": "custom", - "display_name": "Custom" + "slug": "init", + "display_name": "Elements Initialisation" } }, { "model": "process.workerversion", - "pk": "07b1e1b0-ff6a-4a34-bb18-84aef5b07b98", + "pk": "221791c3-7fa9-4669-9399-0ca05220b7c0", "fields": { - "worker": "5cd08382-8a64-499a-a648-12c5bc0509d2", - "revision": null, + "worker": "2666efcd-09df-49e5-9504-92953561ba23", "version": 1, "configuration": { "test": 42 }, "state": "available", - "gpu_usage": "required", - "model_usage": "disabled", + "gpu_usage": "disabled", + "model_usage": "required", "docker_image_iid": "registry.somewhere.com/something:latest", + "revision_url": null, + "tag": null, "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z" } }, { "model": "process.workerversion", - "pk": "2de8eb65-a6c6-4fff-b42d-d37915cb20e3", + "pk": "282dd426-0828-46cd-b15c-7da00c3b6279", "fields": { - "worker": "7d080fa4-f74c-40c2-8b30-b20da5a459c2", - "revision": null, + "worker": "c3a739d0-024e-4405-bc07-f8736d701623", "version": 1, "configuration": { "test": 42 }, "state": "available", "gpu_usage": "disabled", - "model_usage": "required", + "model_usage": "disabled", "docker_image_iid": "registry.somewhere.com/something:latest", + "revision_url": null, + "tag": null, "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z" } }, { "model": "process.workerversion", - "pk": "397bb48a-6832-44cc-929a-b3984bb9597f", + "pk": "5e755c30-57f6-4e19-8e3a-6b5a7f09f2ee", "fields": { - "worker": "39e29762-5353-4cde-b909-964a87584224", - "revision": null, + "worker": "b391fd40-ca4b-4963-b49b-96ac34ad2e1d", "version": 1, "configuration": { - "test": 42 + "custom": "value" }, - "state": "available", + "state": "created", "gpu_usage": "disabled", "model_usage": "disabled", - "docker_image_iid": "registry.somewhere.com/something:latest", + "docker_image_iid": null, + "revision_url": null, + "tag": null, "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z" } }, { "model": "process.workerversion", - "pk": "5a4732e0-0313-4d5f-aa2e-5200336184e3", + "pk": "821770c1-6438-49a8-a200-8662fa2a607d", "fields": { - "worker": "651dd631-7904-4ba7-a1f7-f4789f938e63", - "revision": null, + "worker": "fb83b17c-c9cf-43e5-9ef8-e1362381dd09", "version": 1, - "configuration": {}, + "configuration": { + "test": 42 + }, "state": "available", - "gpu_usage": "disabled", + "gpu_usage": "required", "model_usage": "disabled", "docker_image_iid": "registry.somewhere.com/something:latest", + "revision_url": null, + "tag": null, "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z" } }, { "model": "process.workerversion", - "pk": "631e4733-829f-47c7-b841-69f32fa62a52", + "pk": "9a5ae4ee-ebff-40bd-8582-b2f1f244ac15", "fields": { - "worker": "3d6138ea-96cd-47ad-bb51-02eae6120a37", - "revision": null, + "worker": "aa0da253-2300-4b80-9403-1247b1c473ba", "version": 1, - "configuration": { - "docker": { - "command": "worker-init-elements" - } - }, + "configuration": {}, "state": "available", "gpu_usage": "disabled", "model_usage": "disabled", - "docker_image_iid": "registry.gitlab.teklia.com/arkindex/workers/init-elements:latest", + "docker_image_iid": "registry.somewhere.com/something:latest", + "revision_url": null, + "tag": null, "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z" } }, { "model": "process.workerversion", - "pk": "dc3e5c0d-52a4-4d7d-8f84-7102c4e8d9d2", + "pk": "ccf2a96f-ed15-495c-886b-b5068b01b9f8", "fields": { - "worker": "25d91339-d832-4d88-a9f9-a1888577964a", - "revision": null, + "worker": "cbaebcd5-3c7b-4e9a-9b93-1a2ff6521273", "version": 1, "configuration": { - "custom": "value" + "test": 42 }, - "state": "created", + "state": "available", "gpu_usage": "disabled", "model_usage": "disabled", - "docker_image_iid": null, + "docker_image_iid": "registry.somewhere.com/something:latest", + "revision_url": null, + "tag": null, "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z" } }, { "model": "process.workerversion", - "pk": "e7d35774-1afa-4b51-af32-40b350b12832", + "pk": "f5857b3b-8330-4735-a619-4a0ddde14b0f", "fields": { - "worker": "373d2b71-e62c-48d5-bbbb-5ad0a7b350db", - "revision": null, + "worker": "d99d8050-297c-41db-85b1-8760ae6875b7", "version": 1, "configuration": { - "test": 42 + "docker": { + "command": "worker-init-elements" + } }, "state": "available", "gpu_usage": "disabled", "model_usage": "disabled", - "docker_image_iid": "registry.somewhere.com/something:latest", + "docker_image_iid": "registry.gitlab.teklia.com/arkindex/workers/init-elements:latest", + "revision_url": null, + "tag": null, "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z" } }, { "model": "process.workerrun", - "pk": "0813e0b8-64c7-409e-8223-a347ddf3c64a", + "pk": "00794041-a034-477e-8dc8-ad6d4eae7f11", "fields": { - "process": "d4cada0d-d5b3-48ed-bffc-db53c8cf5e75", - "version": "631e4733-829f-47c7-b841-69f32fa62a52", + "process": "38e459b9-2ffa-4bc6-b389-03a9a76d9deb", + "version": "f5857b3b-8330-4735-a619-4a0ddde14b0f", "model_version": null, "parents": "[]", "configuration": null, @@ -378,14 +385,14 @@ }, { "model": "process.workerrun", - "pk": "5af05ed4-874c-43bc-85df-00544ea40fb7", + "pk": "75d5400c-650f-4870-a23c-6dfbb5c51cab", "fields": { - "process": "0be71517-084c-435b-be54-8dba120c86fd", - "version": "dc3e5c0d-52a4-4d7d-8f84-7102c4e8d9d2", + "process": "38e459b9-2ffa-4bc6-b389-03a9a76d9deb", + "version": "282dd426-0828-46cd-b15c-7da00c3b6279", "model_version": null, - "parents": "[]", + "parents": "[\"00794041-a034-477e-8dc8-ad6d4eae7f11\"]", "configuration": null, - "summary": "Worker Custom worker @ version 1", + "summary": "Worker Document layout analyser @ version 1", "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", "has_results": false, @@ -394,14 +401,14 @@ }, { "model": "process.workerrun", - "pk": "83c242f7-03f3-4c33-962d-83147b7ddf63", + "pk": "a3adcf61-c7ce-48e1-8488-541ba1373740", "fields": { - "process": "d4cada0d-d5b3-48ed-bffc-db53c8cf5e75", - "version": "397bb48a-6832-44cc-929a-b3984bb9597f", + "process": "38e459b9-2ffa-4bc6-b389-03a9a76d9deb", + "version": "ccf2a96f-ed15-495c-886b-b5068b01b9f8", "model_version": null, - "parents": "[\"0813e0b8-64c7-409e-8223-a347ddf3c64a\"]", + "parents": "[\"75d5400c-650f-4870-a23c-6dfbb5c51cab\"]", "configuration": null, - "summary": "Worker Document layout analyser @ version 1", + "summary": "Worker Recognizer @ version 1", "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", "has_results": false, @@ -410,10 +417,10 @@ }, { "model": "process.workerrun", - "pk": "f3bad6e3-9188-4433-ac9e-e06b5f958d5b", + "pk": "b2a718fc-bf5c-4a56-8b07-d7f10328c07c", "fields": { - "process": "74b5620c-6d18-4ac6-b685-f900c5d6c19d", - "version": "dc3e5c0d-52a4-4d7d-8f84-7102c4e8d9d2", + "process": "374c483b-62b1-4565-8834-0ab2c4960c25", + "version": "5e755c30-57f6-4e19-8e3a-6b5a7f09f2ee", "model_version": null, "parents": "[]", "configuration": null, @@ -426,14 +433,14 @@ }, { "model": "process.workerrun", - "pk": "fc83b191-fb73-4f8c-a37d-d07e3de33a4e", + "pk": "cda74349-cb8d-49ed-bf43-9a06a9e17d79", "fields": { - "process": "d4cada0d-d5b3-48ed-bffc-db53c8cf5e75", - "version": "e7d35774-1afa-4b51-af32-40b350b12832", + "process": "da1ca18e-736e-4123-8d66-27385205494d", + "version": "5e755c30-57f6-4e19-8e3a-6b5a7f09f2ee", "model_version": null, - "parents": "[\"83c242f7-03f3-4c33-962d-83147b7ddf63\"]", + "parents": "[]", "configuration": null, - "summary": "Worker Recognizer @ version 1", + "summary": "Worker Custom worker @ version 1", "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", "has_results": false, @@ -442,7 +449,7 @@ }, { "model": "documents.corpus", - "pk": "12944eab-1b0e-4653-aa66-4c0231e722bf", + "pk": "b1be7812-a2b1-4d26-a031-8d85869228df", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", @@ -455,23 +462,11 @@ }, { "model": "documents.elementtype", - "pk": "2c577a34-0084-494c-9555-52bc5b74a89b", - "fields": { - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "slug": "surface", - "display_name": "Surface", - "folder": false, - "indexable": false, - "color": "28b62c" - } -}, -{ - "model": "documents.elementtype", - "pk": "2d308dfa-ab53-4e37-b534-e5b1f9c48c83", + "pk": "0f9084ac-d62f-435e-8dd2-c66052dca93b", "fields": { - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "slug": "word", - "display_name": "Word", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "slug": "page", + "display_name": "Page", "folder": false, "indexable": false, "color": "28b62c" @@ -479,11 +474,11 @@ }, { "model": "documents.elementtype", - "pk": "b06e116b-d9d3-4a86-a4f2-f680ed34179e", + "pk": "4ae753e7-ddf9-4500-a72f-9efdd71ba37c", "fields": { - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "slug": "text_line", - "display_name": "Line", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "slug": "surface", + "display_name": "Surface", "folder": false, "indexable": false, "color": "28b62c" @@ -491,9 +486,9 @@ }, { "model": "documents.elementtype", - "pk": "b70df426-120d-4938-a100-7819e5366ac5", + "pk": "71849ae9-9235-4c55-a627-d5a98af53ea4", "fields": { - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", "slug": "volume", "display_name": "Volume", "folder": true, @@ -503,11 +498,11 @@ }, { "model": "documents.elementtype", - "pk": "b7aa6340-4883-4fe0-93d8-89a01611caad", + "pk": "8f16a5a3-4dfb-4851-a05a-36d95bb1cc0c", "fields": { - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "slug": "page", - "display_name": "Page", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "slug": "word", + "display_name": "Word", "folder": false, "indexable": false, "color": "28b62c" @@ -515,9 +510,9 @@ }, { "model": "documents.elementtype", - "pk": "dceeed29-83b0-4ab9-b161-c4fcc402ca05", + "pk": "90463352-3033-4f98-9b4b-b01d463ede34", "fields": { - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", "slug": "act", "display_name": "Act", "folder": false, @@ -526,280 +521,292 @@ } }, { - "model": "documents.elementpath", - "pk": "0ff047bc-cefb-485e-aa34-b963702bd400", + "model": "documents.elementtype", + "pk": "d11fd6b0-37c7-4566-abee-1283803bf546", "fields": { - "element": "2e6fdf3b-f6ef-491b-ac48-8e7aecce7014", - "path": "[\"2a437eca-2495-4717-92d2-0ca98f32641f\", \"6e739e39-da6a-4535-9160-23eab0604f83\"]", - "ordering": 0 + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "slug": "text_line", + "display_name": "Line", + "folder": false, + "indexable": false, + "color": "28b62c" } }, { "model": "documents.elementpath", - "pk": "17f0675b-2c21-492b-8a4b-7ce9c748651e", + "pk": "07cf4470-ce10-4bb3-b624-8693b7d830aa", "fields": { - "element": "57428dc4-260a-4463-a11e-f9e9884d97b6", - "path": "[\"2a437eca-2495-4717-92d2-0ca98f32641f\", \"51ce7553-ad98-4092-838d-ad778dcb2a92\"]", - "ordering": 1 + "element": "c77fbfa2-1edc-4c83-bb60-a59773be6f39", + "path": "[\"71287d83-8628-48ac-9e3f-40f2f6daf136\"]", + "ordering": 4 } }, { "model": "documents.elementpath", - "pk": "26e1a979-d695-4746-b58f-e5c1460c9806", + "pk": "2299e751-efbc-44f9-928d-eae11419bf08", "fields": { - "element": "57dc759a-b8be-4411-bfa3-cd884c24b37f", - "path": "[\"2a437eca-2495-4717-92d2-0ca98f32641f\"]", - "ordering": 0 + "element": "809a018e-3b3e-4ba0-9e10-7378df428f8b", + "path": "[\"71287d83-8628-48ac-9e3f-40f2f6daf136\"]", + "ordering": 5 } }, { "model": "documents.elementpath", - "pk": "389a2fe8-bf7f-403f-a71a-5be706fcbf99", + "pk": "24d60fd8-fd8a-4199-9892-7502dcbca1b7", "fields": { - "element": "b728983a-ec3e-4f4d-b1ad-b71c31e39868", - "path": "[\"2a437eca-2495-4717-92d2-0ca98f32641f\"]", - "ordering": 3 + "element": "92edae95-97fd-44c9-a8f3-86aaabd3e685", + "path": "[\"71287d83-8628-48ac-9e3f-40f2f6daf136\", \"30211bbd-f970-46f2-8010-6a03afa219d4\"]", + "ordering": 2 } }, { "model": "documents.elementpath", - "pk": "4132b920-47bd-4f7e-9ccd-25d6fd942b5d", + "pk": "2b3baf15-7c24-4824-be6e-023a6b918b8d", "fields": { - "element": "fc22eb47-6281-4a56-b474-b91993e9eead", - "path": "[\"90852275-3fb0-463d-a11f-0f131bfb9cce\"]", + "element": "6c2b3553-a182-41e7-86b7-d074ee38ef3a", + "path": "[\"71287d83-8628-48ac-9e3f-40f2f6daf136\", \"bd5a671f-ca17-476e-a43d-25b4aa386abf\"]", "ordering": 0 } }, { "model": "documents.elementpath", - "pk": "455bbb86-c1e2-4648-b987-4f15c2576379", + "pk": "2f5a38d5-1c15-4be2-8540-4f69e37a0b6a", "fields": { - "element": "2a437eca-2495-4717-92d2-0ca98f32641f", - "path": "[]", + "element": "9475daba-8eb1-4553-a400-3fb117528bb3", + "path": "[\"71287d83-8628-48ac-9e3f-40f2f6daf136\", \"7f3bbf36-2f96-4297-adc3-4258e3456c29\"]", "ordering": 0 } }, { "model": "documents.elementpath", - "pk": "662acc1d-f714-43c6-b1b8-9193719fd0fa", - "fields": { - "element": "bab1b193-41c7-4202-838d-7c4d430746ad", - "path": "[\"2a437eca-2495-4717-92d2-0ca98f32641f\", \"6e739e39-da6a-4535-9160-23eab0604f83\"]", - "ordering": 1 - } -}, -{ - "model": "documents.elementpath", - "pk": "7147ecb2-019b-4e04-a84e-e7259ec85393", + "pk": "43e2ccf3-7bba-40e7-98c6-93737541a0f2", "fields": { - "element": "b42aa9f3-9347-45a5-9771-c0fe64d7014c", - "path": "[\"90852275-3fb0-463d-a11f-0f131bfb9cce\"]", - "ordering": 2 + "element": "bd5a671f-ca17-476e-a43d-25b4aa386abf", + "path": "[\"71287d83-8628-48ac-9e3f-40f2f6daf136\"]", + "ordering": 3 } }, { "model": "documents.elementpath", - "pk": "7d22c577-6fc2-4c7e-9857-994bf17673cc", + "pk": "46a19bee-37af-48cd-bc88-0839541e35bf", "fields": { - "element": "cdcd154e-eccc-4a12-98bd-64d991bc3eee", - "path": "[\"90852275-3fb0-463d-a11f-0f131bfb9cce\"]", - "ordering": 1 + "element": "26ac9c54-10e9-4996-8cfa-9df1434774f6", + "path": "[\"71287d83-8628-48ac-9e3f-40f2f6daf136\", \"76a56cff-9680-4c5a-8a01-53b43700b093\"]", + "ordering": 0 } }, { "model": "documents.elementpath", - "pk": "81573e8d-e906-433a-9205-65b4b4c67a4c", + "pk": "4761a077-d4de-48b2-9477-3520907439e9", "fields": { - "element": "36fd659e-9c36-4532-b5a1-ecf08f05e139", - "path": "[\"2a437eca-2495-4717-92d2-0ca98f32641f\"]", - "ordering": 7 + "element": "30211bbd-f970-46f2-8010-6a03afa219d4", + "path": "[\"71287d83-8628-48ac-9e3f-40f2f6daf136\"]", + "ordering": 0 } }, { "model": "documents.elementpath", - "pk": "87c56fe2-28c3-46d7-80d9-09a8fb9deacc", + "pk": "5a917257-c667-4f13-80e6-106380a8b3ea", "fields": { - "element": "78546795-a66d-4e94-bc65-9f78221992d0", - "path": "[\"2a437eca-2495-4717-92d2-0ca98f32641f\", \"57dc759a-b8be-4411-bfa3-cd884c24b37f\"]", + "element": "7fa801e7-2b7a-46b5-9c2a-19a227ba56d6", + "path": "[\"bd6e6b59-cfb5-41f6-b333-794accb8eff9\"]", "ordering": 2 } }, { "model": "documents.elementpath", - "pk": "96ef9196-b83d-48d0-bfa5-674dae27aa03", + "pk": "655bca20-7dc6-4c03-ae5b-a0099d124281", "fields": { - "element": "81343790-315a-4121-8ff1-70f2757993d5", - "path": "[\"2a437eca-2495-4717-92d2-0ca98f32641f\", \"36fd659e-9c36-4532-b5a1-ecf08f05e139\"]", + "element": "ee14b7ed-9fee-49c6-9983-9d52b2a59343", + "path": "[\"71287d83-8628-48ac-9e3f-40f2f6daf136\", \"c77fbfa2-1edc-4c83-bb60-a59773be6f39\"]", "ordering": 0 } }, { "model": "documents.elementpath", - "pk": "9757c057-a114-4841-b9da-3f8e391d17ff", + "pk": "74242843-2aec-455b-8dce-87b8ce562f3d", "fields": { - "element": "2a643cde-c821-429d-aae7-b6d7ef974c8b", - "path": "[\"2a437eca-2495-4717-92d2-0ca98f32641f\", \"51ce7553-ad98-4092-838d-ad778dcb2a92\"]", + "element": "71287d83-8628-48ac-9e3f-40f2f6daf136", + "path": "[]", "ordering": 0 } }, { "model": "documents.elementpath", - "pk": "9b6c268f-e328-4a36-bb2d-3d74d518efe3", + "pk": "77e0cddf-b8c5-4af2-aa7a-437341876530", "fields": { - "element": "36f889af-a83b-47b7-ab80-fbf7bdd5c08d", - "path": "[\"2a437eca-2495-4717-92d2-0ca98f32641f\"]", - "ordering": 4 + "element": "a317a77b-9ddd-4f48-82cf-17d25aec30f6", + "path": "[\"71287d83-8628-48ac-9e3f-40f2f6daf136\", \"b786da45-c90c-4569-aa31-1b4351bc9e34\"]", + "ordering": 2 } }, { "model": "documents.elementpath", - "pk": "a1888d2c-d953-478f-b027-476f9e597164", + "pk": "8d008ef2-d1c3-4615-9c8b-43aace76b30b", "fields": { - "element": "876a65aa-6179-453e-a2e2-d558cc3dc3ce", - "path": "[\"2a437eca-2495-4717-92d2-0ca98f32641f\"]", - "ordering": 5 + "element": "7f3bbf36-2f96-4297-adc3-4258e3456c29", + "path": "[\"71287d83-8628-48ac-9e3f-40f2f6daf136\"]", + "ordering": 7 } }, { "model": "documents.elementpath", - "pk": "a21aa2d1-cb06-4715-8445-ed65ff1aa8ea", + "pk": "978c2b40-fbb4-415d-ae51-65641826153f", "fields": { - "element": "73277712-ccbc-4bc1-b2ad-6fa75571a705", - "path": "[\"2a437eca-2495-4717-92d2-0ca98f32641f\", \"57dc759a-b8be-4411-bfa3-cd884c24b37f\"]", + "element": "6fb612a7-e337-4538-8ca9-f79d7b1c80f3", + "path": "[\"71287d83-8628-48ac-9e3f-40f2f6daf136\", \"76a56cff-9680-4c5a-8a01-53b43700b093\"]", "ordering": 1 } }, { "model": "documents.elementpath", - "pk": "ab9fcc5b-d06a-4397-9b9f-9d9edd6e93b7", + "pk": "9eaa2e45-241f-494d-8135-dacdcb36e4fe", "fields": { - "element": "51ce7553-ad98-4092-838d-ad778dcb2a92", - "path": "[\"2a437eca-2495-4717-92d2-0ca98f32641f\"]", + "element": "b826c0e5-4877-487e-bd77-b4198cf76f4c", + "path": "[\"71287d83-8628-48ac-9e3f-40f2f6daf136\", \"76a56cff-9680-4c5a-8a01-53b43700b093\"]", "ordering": 2 } }, { "model": "documents.elementpath", - "pk": "b43356f8-aa58-4a16-bb5d-d7a9400d65f6", + "pk": "9f0b10d4-7c88-4f54-a308-4652618790c0", "fields": { - "element": "85bc5401-69a7-4d96-bea3-cc47bc6e651c", - "path": "[\"2a437eca-2495-4717-92d2-0ca98f32641f\"]", - "ordering": 6 + "element": "38cafdb6-bb8a-45bc-b514-f19cb27ac7a9", + "path": "[\"71287d83-8628-48ac-9e3f-40f2f6daf136\", \"b786da45-c90c-4569-aa31-1b4351bc9e34\"]", + "ordering": 1 } }, { "model": "documents.elementpath", - "pk": "ba4e53f2-cf3a-4c2c-9d6a-2b1e17ff691b", + "pk": "a57189bd-d29f-4dab-b66c-d06876f59118", "fields": { - "element": "41a9fb39-6df5-45b6-8348-d1c866595432", - "path": "[\"2a437eca-2495-4717-92d2-0ca98f32641f\", \"36f889af-a83b-47b7-ab80-fbf7bdd5c08d\"]", + "element": "9afab3a6-e895-4c0a-807d-d31354bd8b0a", + "path": "[\"71287d83-8628-48ac-9e3f-40f2f6daf136\", \"30211bbd-f970-46f2-8010-6a03afa219d4\"]", "ordering": 0 } }, { "model": "documents.elementpath", - "pk": "c989185f-863c-4c84-8914-f9980416b5c7", + "pk": "aecdcf26-7dd1-4186-b872-300918e92658", "fields": { - "element": "90852275-3fb0-463d-a11f-0f131bfb9cce", - "path": "[]", - "ordering": 0 + "element": "4bb67850-d7ba-459e-a106-b2cf48f9f6cb", + "path": "[\"bd6e6b59-cfb5-41f6-b333-794accb8eff9\"]", + "ordering": 1 } }, { "model": "documents.elementpath", - "pk": "d334d7aa-18c2-40b2-8717-9aae460b3159", + "pk": "b93d6025-9349-439d-bd65-992c13db4010", "fields": { - "element": "e67230f0-028c-4ed0-bf9c-7a1c94f2a733", - "path": "[\"2a437eca-2495-4717-92d2-0ca98f32641f\", \"6e739e39-da6a-4535-9160-23eab0604f83\"]", - "ordering": 2 + "element": "9d026bbe-71d7-4ed0-8291-c00cad083f3b", + "path": "[\"71287d83-8628-48ac-9e3f-40f2f6daf136\", \"c77fbfa2-1edc-4c83-bb60-a59773be6f39\"]", + "ordering": 1 } }, { "model": "documents.elementpath", - "pk": "d7771c3c-ff0d-4d0a-8ed2-90409b464bc1", + "pk": "ba4dc25d-1878-4327-ba75-babaccaf3edc", "fields": { - "element": "6e739e39-da6a-4535-9160-23eab0604f83", - "path": "[\"2a437eca-2495-4717-92d2-0ca98f32641f\"]", - "ordering": 1 + "element": "dc730372-6e7a-4baf-9d0a-7f1ca89802f9", + "path": "[\"71287d83-8628-48ac-9e3f-40f2f6daf136\"]", + "ordering": 6 } }, { "model": "documents.elementpath", - "pk": "e03f286f-fd42-413f-a265-f456aab57254", + "pk": "c2d77a3f-16c3-435b-989a-94202960561f", "fields": { - "element": "0f7d6bc9-1195-467d-9651-76ed97b30707", - "path": "[\"2a437eca-2495-4717-92d2-0ca98f32641f\", \"57dc759a-b8be-4411-bfa3-cd884c24b37f\"]", - "ordering": 3 + "element": "bd6e6b59-cfb5-41f6-b333-794accb8eff9", + "path": "[]", + "ordering": 0 } }, { "model": "documents.elementpath", - "pk": "e43f7440-7bc7-47e4-bd56-788c671e59ca", + "pk": "c8acfd35-3fd9-4b79-9a38-b503e262c46c", "fields": { - "element": "dc29c21d-52c1-4e9b-83f5-74d71e5b41bd", - "path": "[\"2a437eca-2495-4717-92d2-0ca98f32641f\", \"85bc5401-69a7-4d96-bea3-cc47bc6e651c\"]", + "element": "e247c22a-4e83-4997-a284-5d1fda37a82f", + "path": "[\"71287d83-8628-48ac-9e3f-40f2f6daf136\", \"dc730372-6e7a-4baf-9d0a-7f1ca89802f9\"]", "ordering": 0 } }, { "model": "documents.elementpath", - "pk": "e81bac50-dcea-461a-a3a5-86391186d90d", + "pk": "caf5c422-7d5f-451f-aeda-ad0239c6b880", "fields": { - "element": "a75d3f97-41bc-4587-82aa-c3d065e2fe29", - "path": "[\"2a437eca-2495-4717-92d2-0ca98f32641f\", \"876a65aa-6179-453e-a2e2-d558cc3dc3ce\"]", - "ordering": 0 + "element": "be2b81f0-dec4-41fd-a720-e8383244ee91", + "path": "[\"71287d83-8628-48ac-9e3f-40f2f6daf136\", \"30211bbd-f970-46f2-8010-6a03afa219d4\"]", + "ordering": 1 + } +}, +{ + "model": "documents.elementpath", + "pk": "d967f4ee-b387-4b62-a140-9273de9b1f42", + "fields": { + "element": "76a56cff-9680-4c5a-8a01-53b43700b093", + "path": "[\"71287d83-8628-48ac-9e3f-40f2f6daf136\"]", + "ordering": 1 } }, { "model": "documents.elementpath", - "pk": "ef600b5f-4a2c-45ac-826c-133c645f463e", + "pk": "e61e9861-4e60-4459-839d-8dfe0803ab3d", "fields": { - "element": "bdee8f49-2fa8-4168-928e-d73f4ce672f2", - "path": "[\"2a437eca-2495-4717-92d2-0ca98f32641f\", \"b728983a-ec3e-4f4d-b1ad-b71c31e39868\"]", + "element": "ae67b0f1-dfee-464d-8c96-fa3150eb924f", + "path": "[\"71287d83-8628-48ac-9e3f-40f2f6daf136\", \"b786da45-c90c-4569-aa31-1b4351bc9e34\"]", "ordering": 0 } }, { "model": "documents.elementpath", - "pk": "f386ac6b-1749-4ca3-bf25-bec671d29057", + "pk": "eb20eb41-0d8a-4950-a838-24c98e707315", "fields": { - "element": "9190e5ca-153a-44b2-b339-ae9e0befb4c0", - "path": "[\"2a437eca-2495-4717-92d2-0ca98f32641f\", \"36f889af-a83b-47b7-ab80-fbf7bdd5c08d\"]", - "ordering": 1 + "element": "b8d55a9f-f3d6-4778-8eda-5b6b85d458b1", + "path": "[\"71287d83-8628-48ac-9e3f-40f2f6daf136\", \"30211bbd-f970-46f2-8010-6a03afa219d4\"]", + "ordering": 3 } }, { "model": "documents.elementpath", - "pk": "f7a52461-4758-455a-81bb-eafc50482b49", + "pk": "f27d02e0-2cdb-4c7b-a3a0-dbb21603424b", "fields": { - "element": "ff8c551d-28a2-479d-b33e-561cd258498a", - "path": "[\"2a437eca-2495-4717-92d2-0ca98f32641f\", \"51ce7553-ad98-4092-838d-ad778dcb2a92\"]", + "element": "b786da45-c90c-4569-aa31-1b4351bc9e34", + "path": "[\"71287d83-8628-48ac-9e3f-40f2f6daf136\"]", "ordering": 2 } }, { "model": "documents.elementpath", - "pk": "fcb8f15c-65ad-44af-bd18-2c95be36ae70", + "pk": "f577406b-f31d-4fd6-801d-1b1385700304", + "fields": { + "element": "590d69b1-95c8-4ba0-8617-9c0b022a4ba8", + "path": "[\"bd6e6b59-cfb5-41f6-b333-794accb8eff9\"]", + "ordering": 0 + } +}, +{ + "model": "documents.elementpath", + "pk": "f68d74c1-7b5d-43fc-a259-98eb8500a827", "fields": { - "element": "308f43b9-325c-442e-8f82-a21a8c46c9a7", - "path": "[\"2a437eca-2495-4717-92d2-0ca98f32641f\", \"57dc759a-b8be-4411-bfa3-cd884c24b37f\"]", + "element": "02fd8dce-00b9-4895-93b6-94f8026a8a41", + "path": "[\"71287d83-8628-48ac-9e3f-40f2f6daf136\", \"809a018e-3b3e-4ba0-9e10-7378df428f8b\"]", "ordering": 0 } }, { "model": "documents.element", - "pk": "0f7d6bc9-1195-467d-9651-76ed97b30707", + "pk": "02fd8dce-00b9-4895-93b6-94f8026a8a41", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "b06e116b-d9d3-4a86-a4f2-f680ed34179e", - "name": "Text line", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "4ae753e7-ddf9-4500-a72f-9efdd71ba37c", + "name": "Surface D", "creator": null, "worker_version": null, "worker_run": null, - "image": "0a404dd6-7b53-4f10-ab8e-601ef5f22f97", - "polygon": "LINEARRING (400 400, 400 500, 500 500, 500 400, 400 400)", + "image": "e7b06b72-703b-45aa-9c91-12eba0f1e9d9", + "polygon": "LINEARRING (0 0, 0 300, 300 300, 300 0, 0 0)", "rotation_angle": 0, "mirrored": false, "confidence": null @@ -807,18 +814,18 @@ }, { "model": "documents.element", - "pk": "2a437eca-2495-4717-92d2-0ca98f32641f", + "pk": "26ac9c54-10e9-4996-8cfa-9df1434774f6", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "b70df426-120d-4938-a100-7819e5366ac5", - "name": "Volume 1", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "8f16a5a3-4dfb-4851-a05a-36d95bb1cc0c", + "name": "PARIS", "creator": null, "worker_version": null, "worker_run": null, - "image": null, - "polygon": null, + "image": "da507478-8d0a-41d5-8ad7-5b062521e984", + "polygon": "LINEARRING (100 100, 100 200, 200 200, 200 100, 100 100)", "rotation_angle": 0, "mirrored": false, "confidence": null @@ -826,18 +833,18 @@ }, { "model": "documents.element", - "pk": "2a643cde-c821-429d-aae7-b6d7ef974c8b", + "pk": "30211bbd-f970-46f2-8010-6a03afa219d4", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "2d308dfa-ab53-4e37-b534-e5b1f9c48c83", - "name": "PARIS", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "0f9084ac-d62f-435e-8dd2-c66052dca93b", + "name": "Volume 1, page 1r", "creator": null, "worker_version": null, "worker_run": null, - "image": "30d880ab-43c1-4f62-955f-41bb2f1a0802", - "polygon": "LINEARRING (100 100, 100 200, 200 200, 200 100, 100 100)", + "image": "b6ac34ae-c245-4bf5-8c24-cee3b25a8498", + "polygon": "LINEARRING (0 0, 0 1000, 1000 1000, 1000 0, 0 0)", "rotation_angle": 0, "mirrored": false, "confidence": null @@ -845,18 +852,18 @@ }, { "model": "documents.element", - "pk": "2e6fdf3b-f6ef-491b-ac48-8e7aecce7014", + "pk": "38cafdb6-bb8a-45bc-b514-f19cb27ac7a9", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "2d308dfa-ab53-4e37-b534-e5b1f9c48c83", - "name": "PARIS", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "8f16a5a3-4dfb-4851-a05a-36d95bb1cc0c", + "name": "ROY", "creator": null, "worker_version": null, "worker_run": null, - "image": "f2a146eb-9cab-4bfb-b97b-59b16137c200", - "polygon": "LINEARRING (100 100, 100 200, 200 200, 200 100, 100 100)", + "image": "e7b06b72-703b-45aa-9c91-12eba0f1e9d9", + "polygon": "LINEARRING (400 400, 400 500, 500 500, 500 400, 400 400)", "rotation_angle": 0, "mirrored": false, "confidence": null @@ -864,18 +871,18 @@ }, { "model": "documents.element", - "pk": "308f43b9-325c-442e-8f82-a21a8c46c9a7", + "pk": "4bb67850-d7ba-459e-a106-b2cf48f9f6cb", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "2d308dfa-ab53-4e37-b534-e5b1f9c48c83", - "name": "PARIS", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "0f9084ac-d62f-435e-8dd2-c66052dca93b", + "name": "Volume 2, page 1v", "creator": null, "worker_version": null, "worker_run": null, - "image": "0a404dd6-7b53-4f10-ab8e-601ef5f22f97", - "polygon": "LINEARRING (100 100, 100 200, 200 200, 200 100, 100 100)", + "image": "6358303d-1167-489c-b456-2ad6f80b7909", + "polygon": "LINEARRING (0 0, 0 1000, 1000 1000, 1000 0, 0 0)", "rotation_angle": 0, "mirrored": false, "confidence": null @@ -883,18 +890,18 @@ }, { "model": "documents.element", - "pk": "36f889af-a83b-47b7-ab80-fbf7bdd5c08d", + "pk": "590d69b1-95c8-4ba0-8617-9c0b022a4ba8", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "dceeed29-83b0-4ab9-b161-c4fcc402ca05", - "name": "Act 2", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "0f9084ac-d62f-435e-8dd2-c66052dca93b", + "name": "Volume 2, page 1r", "creator": null, "worker_version": null, "worker_run": null, - "image": null, - "polygon": null, + "image": "0d4b917a-4b05-412e-9a32-78da2031dd70", + "polygon": "LINEARRING (0 0, 0 1000, 1000 1000, 1000 0, 0 0)", "rotation_angle": 0, "mirrored": false, "confidence": null @@ -902,18 +909,18 @@ }, { "model": "documents.element", - "pk": "36fd659e-9c36-4532-b5a1-ecf08f05e139", + "pk": "6c2b3553-a182-41e7-86b7-d074ee38ef3a", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "dceeed29-83b0-4ab9-b161-c4fcc402ca05", - "name": "Act 5", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "4ae753e7-ddf9-4500-a72f-9efdd71ba37c", + "name": "Surface A", "creator": null, "worker_version": null, "worker_run": null, - "image": null, - "polygon": null, + "image": "b6ac34ae-c245-4bf5-8c24-cee3b25a8498", + "polygon": "LINEARRING (0 0, 0 600, 600 600, 600 0, 0 0)", "rotation_angle": 0, "mirrored": false, "confidence": null @@ -921,18 +928,18 @@ }, { "model": "documents.element", - "pk": "41a9fb39-6df5-45b6-8348-d1c866595432", + "pk": "6fb612a7-e337-4538-8ca9-f79d7b1c80f3", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "2c577a34-0084-494c-9555-52bc5b74a89b", - "name": "Surface B", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "8f16a5a3-4dfb-4851-a05a-36d95bb1cc0c", + "name": "ROY", "creator": null, "worker_version": null, "worker_run": null, - "image": "0a404dd6-7b53-4f10-ab8e-601ef5f22f97", - "polygon": "LINEARRING (600 600, 600 1000, 1000 1000, 1000 600, 600 600)", + "image": "da507478-8d0a-41d5-8ad7-5b062521e984", + "polygon": "LINEARRING (400 400, 400 500, 500 500, 500 400, 400 400)", "rotation_angle": 0, "mirrored": false, "confidence": null @@ -940,18 +947,18 @@ }, { "model": "documents.element", - "pk": "51ce7553-ad98-4092-838d-ad778dcb2a92", + "pk": "71287d83-8628-48ac-9e3f-40f2f6daf136", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "b7aa6340-4883-4fe0-93d8-89a01611caad", - "name": "Volume 1, page 2r", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "71849ae9-9235-4c55-a627-d5a98af53ea4", + "name": "Volume 1", "creator": null, "worker_version": null, "worker_run": null, - "image": "30d880ab-43c1-4f62-955f-41bb2f1a0802", - "polygon": "LINEARRING (0 0, 0 1000, 1000 1000, 1000 0, 0 0)", + "image": null, + "polygon": null, "rotation_angle": 0, "mirrored": false, "confidence": null @@ -959,18 +966,18 @@ }, { "model": "documents.element", - "pk": "57428dc4-260a-4463-a11e-f9e9884d97b6", + "pk": "76a56cff-9680-4c5a-8a01-53b43700b093", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "2d308dfa-ab53-4e37-b534-e5b1f9c48c83", - "name": "ROY", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "0f9084ac-d62f-435e-8dd2-c66052dca93b", + "name": "Volume 1, page 1v", "creator": null, "worker_version": null, "worker_run": null, - "image": "30d880ab-43c1-4f62-955f-41bb2f1a0802", - "polygon": "LINEARRING (400 400, 400 500, 500 500, 500 400, 400 400)", + "image": "da507478-8d0a-41d5-8ad7-5b062521e984", + "polygon": "LINEARRING (0 0, 0 1000, 1000 1000, 1000 0, 0 0)", "rotation_angle": 0, "mirrored": false, "confidence": null @@ -978,18 +985,18 @@ }, { "model": "documents.element", - "pk": "57dc759a-b8be-4411-bfa3-cd884c24b37f", + "pk": "7f3bbf36-2f96-4297-adc3-4258e3456c29", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "b7aa6340-4883-4fe0-93d8-89a01611caad", - "name": "Volume 1, page 1r", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "90463352-3033-4f98-9b4b-b01d463ede34", + "name": "Act 5", "creator": null, "worker_version": null, "worker_run": null, - "image": "0a404dd6-7b53-4f10-ab8e-601ef5f22f97", - "polygon": "LINEARRING (0 0, 0 1000, 1000 1000, 1000 0, 0 0)", + "image": null, + "polygon": null, "rotation_angle": 0, "mirrored": false, "confidence": null @@ -997,17 +1004,17 @@ }, { "model": "documents.element", - "pk": "6e739e39-da6a-4535-9160-23eab0604f83", + "pk": "7fa801e7-2b7a-46b5-9c2a-19a227ba56d6", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "b7aa6340-4883-4fe0-93d8-89a01611caad", - "name": "Volume 1, page 1v", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "0f9084ac-d62f-435e-8dd2-c66052dca93b", + "name": "Volume 2, page 2r", "creator": null, "worker_version": null, "worker_run": null, - "image": "f2a146eb-9cab-4bfb-b97b-59b16137c200", + "image": "fa147dd6-f548-478d-a2ce-de54e28aeda9", "polygon": "LINEARRING (0 0, 0 1000, 1000 1000, 1000 0, 0 0)", "rotation_angle": 0, "mirrored": false, @@ -1016,18 +1023,18 @@ }, { "model": "documents.element", - "pk": "73277712-ccbc-4bc1-b2ad-6fa75571a705", + "pk": "809a018e-3b3e-4ba0-9e10-7378df428f8b", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "2d308dfa-ab53-4e37-b534-e5b1f9c48c83", - "name": "ROY", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "90463352-3033-4f98-9b4b-b01d463ede34", + "name": "Act 3", "creator": null, "worker_version": null, "worker_run": null, - "image": "0a404dd6-7b53-4f10-ab8e-601ef5f22f97", - "polygon": "LINEARRING (400 400, 400 500, 500 500, 500 400, 400 400)", + "image": null, + "polygon": null, "rotation_angle": 0, "mirrored": false, "confidence": null @@ -1035,17 +1042,17 @@ }, { "model": "documents.element", - "pk": "78546795-a66d-4e94-bc65-9f78221992d0", + "pk": "92edae95-97fd-44c9-a8f3-86aaabd3e685", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "2d308dfa-ab53-4e37-b534-e5b1f9c48c83", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "8f16a5a3-4dfb-4851-a05a-36d95bb1cc0c", "name": "DATUM", "creator": null, "worker_version": null, "worker_run": null, - "image": "0a404dd6-7b53-4f10-ab8e-601ef5f22f97", + "image": "b6ac34ae-c245-4bf5-8c24-cee3b25a8498", "polygon": "LINEARRING (700 700, 700 800, 800 800, 800 700, 700 700)", "rotation_angle": 0, "mirrored": false, @@ -1054,17 +1061,17 @@ }, { "model": "documents.element", - "pk": "81343790-315a-4121-8ff1-70f2757993d5", + "pk": "9475daba-8eb1-4553-a400-3fb117528bb3", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "2c577a34-0084-494c-9555-52bc5b74a89b", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "4ae753e7-ddf9-4500-a72f-9efdd71ba37c", "name": "Surface F", "creator": null, "worker_version": null, "worker_run": null, - "image": "30d880ab-43c1-4f62-955f-41bb2f1a0802", + "image": "e7b06b72-703b-45aa-9c91-12eba0f1e9d9", "polygon": "LINEARRING (600 600, 600 1000, 1000 1000, 1000 600, 600 600)", "rotation_angle": 0, "mirrored": false, @@ -1073,18 +1080,18 @@ }, { "model": "documents.element", - "pk": "85bc5401-69a7-4d96-bea3-cc47bc6e651c", + "pk": "9afab3a6-e895-4c0a-807d-d31354bd8b0a", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "dceeed29-83b0-4ab9-b161-c4fcc402ca05", - "name": "Act 4", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "8f16a5a3-4dfb-4851-a05a-36d95bb1cc0c", + "name": "PARIS", "creator": null, "worker_version": null, "worker_run": null, - "image": null, - "polygon": null, + "image": "b6ac34ae-c245-4bf5-8c24-cee3b25a8498", + "polygon": "LINEARRING (100 100, 100 200, 200 200, 200 100, 100 100)", "rotation_angle": 0, "mirrored": false, "confidence": null @@ -1092,18 +1099,18 @@ }, { "model": "documents.element", - "pk": "876a65aa-6179-453e-a2e2-d558cc3dc3ce", + "pk": "9d026bbe-71d7-4ed0-8291-c00cad083f3b", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "dceeed29-83b0-4ab9-b161-c4fcc402ca05", - "name": "Act 3", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "4ae753e7-ddf9-4500-a72f-9efdd71ba37c", + "name": "Surface C", "creator": null, "worker_version": null, "worker_run": null, - "image": null, - "polygon": null, + "image": "da507478-8d0a-41d5-8ad7-5b062521e984", + "polygon": "LINEARRING (0 0, 0 1000, 1000 1000, 1000 0, 0 0)", "rotation_angle": 0, "mirrored": false, "confidence": null @@ -1111,18 +1118,18 @@ }, { "model": "documents.element", - "pk": "90852275-3fb0-463d-a11f-0f131bfb9cce", + "pk": "a317a77b-9ddd-4f48-82cf-17d25aec30f6", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "b70df426-120d-4938-a100-7819e5366ac5", - "name": "Volume 2", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "8f16a5a3-4dfb-4851-a05a-36d95bb1cc0c", + "name": "DATUM", "creator": null, "worker_version": null, "worker_run": null, - "image": null, - "polygon": null, + "image": "e7b06b72-703b-45aa-9c91-12eba0f1e9d9", + "polygon": "LINEARRING (700 700, 700 800, 800 800, 800 700, 700 700)", "rotation_angle": 0, "mirrored": false, "confidence": null @@ -1130,18 +1137,18 @@ }, { "model": "documents.element", - "pk": "9190e5ca-153a-44b2-b339-ae9e0befb4c0", + "pk": "ae67b0f1-dfee-464d-8c96-fa3150eb924f", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "2c577a34-0084-494c-9555-52bc5b74a89b", - "name": "Surface C", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "8f16a5a3-4dfb-4851-a05a-36d95bb1cc0c", + "name": "PARIS", "creator": null, "worker_version": null, "worker_run": null, - "image": "f2a146eb-9cab-4bfb-b97b-59b16137c200", - "polygon": "LINEARRING (0 0, 0 1000, 1000 1000, 1000 0, 0 0)", + "image": "e7b06b72-703b-45aa-9c91-12eba0f1e9d9", + "polygon": "LINEARRING (100 100, 100 200, 200 200, 200 100, 100 100)", "rotation_angle": 0, "mirrored": false, "confidence": null @@ -1149,18 +1156,18 @@ }, { "model": "documents.element", - "pk": "a75d3f97-41bc-4587-82aa-c3d065e2fe29", + "pk": "b786da45-c90c-4569-aa31-1b4351bc9e34", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "2c577a34-0084-494c-9555-52bc5b74a89b", - "name": "Surface D", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "0f9084ac-d62f-435e-8dd2-c66052dca93b", + "name": "Volume 1, page 2r", "creator": null, "worker_version": null, "worker_run": null, - "image": "30d880ab-43c1-4f62-955f-41bb2f1a0802", - "polygon": "LINEARRING (0 0, 0 300, 300 300, 300 0, 0 0)", + "image": "e7b06b72-703b-45aa-9c91-12eba0f1e9d9", + "polygon": "LINEARRING (0 0, 0 1000, 1000 1000, 1000 0, 0 0)", "rotation_angle": 0, "mirrored": false, "confidence": null @@ -1168,18 +1175,18 @@ }, { "model": "documents.element", - "pk": "b42aa9f3-9347-45a5-9771-c0fe64d7014c", + "pk": "b826c0e5-4877-487e-bd77-b4198cf76f4c", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "b7aa6340-4883-4fe0-93d8-89a01611caad", - "name": "Volume 2, page 2r", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "8f16a5a3-4dfb-4851-a05a-36d95bb1cc0c", + "name": "DATUM", "creator": null, "worker_version": null, "worker_run": null, - "image": "a68a053f-ef37-4f96-bd06-08bb2f31a978", - "polygon": "LINEARRING (0 0, 0 1000, 1000 1000, 1000 0, 0 0)", + "image": "da507478-8d0a-41d5-8ad7-5b062521e984", + "polygon": "LINEARRING (700 700, 700 800, 800 800, 800 700, 700 700)", "rotation_angle": 0, "mirrored": false, "confidence": null @@ -1187,18 +1194,18 @@ }, { "model": "documents.element", - "pk": "b728983a-ec3e-4f4d-b1ad-b71c31e39868", + "pk": "b8d55a9f-f3d6-4778-8eda-5b6b85d458b1", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "dceeed29-83b0-4ab9-b161-c4fcc402ca05", - "name": "Act 1", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "d11fd6b0-37c7-4566-abee-1283803bf546", + "name": "Text line", "creator": null, "worker_version": null, "worker_run": null, - "image": null, - "polygon": null, + "image": "b6ac34ae-c245-4bf5-8c24-cee3b25a8498", + "polygon": "LINEARRING (400 400, 400 500, 500 500, 500 400, 400 400)", "rotation_angle": 0, "mirrored": false, "confidence": null @@ -1206,18 +1213,18 @@ }, { "model": "documents.element", - "pk": "bab1b193-41c7-4202-838d-7c4d430746ad", + "pk": "bd5a671f-ca17-476e-a43d-25b4aa386abf", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "2d308dfa-ab53-4e37-b534-e5b1f9c48c83", - "name": "ROY", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "90463352-3033-4f98-9b4b-b01d463ede34", + "name": "Act 1", "creator": null, "worker_version": null, "worker_run": null, - "image": "f2a146eb-9cab-4bfb-b97b-59b16137c200", - "polygon": "LINEARRING (400 400, 400 500, 500 500, 500 400, 400 400)", + "image": null, + "polygon": null, "rotation_angle": 0, "mirrored": false, "confidence": null @@ -1225,18 +1232,18 @@ }, { "model": "documents.element", - "pk": "bdee8f49-2fa8-4168-928e-d73f4ce672f2", + "pk": "bd6e6b59-cfb5-41f6-b333-794accb8eff9", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "2c577a34-0084-494c-9555-52bc5b74a89b", - "name": "Surface A", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "71849ae9-9235-4c55-a627-d5a98af53ea4", + "name": "Volume 2", "creator": null, "worker_version": null, "worker_run": null, - "image": "0a404dd6-7b53-4f10-ab8e-601ef5f22f97", - "polygon": "LINEARRING (0 0, 0 600, 600 600, 600 0, 0 0)", + "image": null, + "polygon": null, "rotation_angle": 0, "mirrored": false, "confidence": null @@ -1244,18 +1251,18 @@ }, { "model": "documents.element", - "pk": "cdcd154e-eccc-4a12-98bd-64d991bc3eee", + "pk": "be2b81f0-dec4-41fd-a720-e8383244ee91", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "b7aa6340-4883-4fe0-93d8-89a01611caad", - "name": "Volume 2, page 1v", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "8f16a5a3-4dfb-4851-a05a-36d95bb1cc0c", + "name": "ROY", "creator": null, "worker_version": null, "worker_run": null, - "image": "8ec1120e-29b7-43cd-b298-1d3ec7144f4f", - "polygon": "LINEARRING (0 0, 0 1000, 1000 1000, 1000 0, 0 0)", + "image": "b6ac34ae-c245-4bf5-8c24-cee3b25a8498", + "polygon": "LINEARRING (400 400, 400 500, 500 500, 500 400, 400 400)", "rotation_angle": 0, "mirrored": false, "confidence": null @@ -1263,18 +1270,18 @@ }, { "model": "documents.element", - "pk": "dc29c21d-52c1-4e9b-83f5-74d71e5b41bd", + "pk": "c77fbfa2-1edc-4c83-bb60-a59773be6f39", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "2c577a34-0084-494c-9555-52bc5b74a89b", - "name": "Surface E", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "90463352-3033-4f98-9b4b-b01d463ede34", + "name": "Act 2", "creator": null, "worker_version": null, "worker_run": null, - "image": "30d880ab-43c1-4f62-955f-41bb2f1a0802", - "polygon": "LINEARRING (300 300, 300 600, 600 600, 600 300, 300 300)", + "image": null, + "polygon": null, "rotation_angle": 0, "mirrored": false, "confidence": null @@ -1282,18 +1289,18 @@ }, { "model": "documents.element", - "pk": "e67230f0-028c-4ed0-bf9c-7a1c94f2a733", + "pk": "dc730372-6e7a-4baf-9d0a-7f1ca89802f9", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "2d308dfa-ab53-4e37-b534-e5b1f9c48c83", - "name": "DATUM", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "90463352-3033-4f98-9b4b-b01d463ede34", + "name": "Act 4", "creator": null, "worker_version": null, "worker_run": null, - "image": "f2a146eb-9cab-4bfb-b97b-59b16137c200", - "polygon": "LINEARRING (700 700, 700 800, 800 800, 800 700, 700 700)", + "image": null, + "polygon": null, "rotation_angle": 0, "mirrored": false, "confidence": null @@ -1301,18 +1308,18 @@ }, { "model": "documents.element", - "pk": "fc22eb47-6281-4a56-b474-b91993e9eead", + "pk": "e247c22a-4e83-4997-a284-5d1fda37a82f", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "b7aa6340-4883-4fe0-93d8-89a01611caad", - "name": "Volume 2, page 1r", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "4ae753e7-ddf9-4500-a72f-9efdd71ba37c", + "name": "Surface E", "creator": null, "worker_version": null, "worker_run": null, - "image": "0775b12d-856e-417f-8ab2-b80dceb11e13", - "polygon": "LINEARRING (0 0, 0 1000, 1000 1000, 1000 0, 0 0)", + "image": "e7b06b72-703b-45aa-9c91-12eba0f1e9d9", + "polygon": "LINEARRING (300 300, 300 600, 600 600, 600 300, 300 300)", "rotation_angle": 0, "mirrored": false, "confidence": null @@ -1320,18 +1327,18 @@ }, { "model": "documents.element", - "pk": "ff8c551d-28a2-479d-b33e-561cd258498a", + "pk": "ee14b7ed-9fee-49c6-9983-9d52b2a59343", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", - "type": "2d308dfa-ab53-4e37-b534-e5b1f9c48c83", - "name": "DATUM", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", + "type": "4ae753e7-ddf9-4500-a72f-9efdd71ba37c", + "name": "Surface B", "creator": null, "worker_version": null, "worker_run": null, - "image": "30d880ab-43c1-4f62-955f-41bb2f1a0802", - "polygon": "LINEARRING (700 700, 700 800, 800 800, 800 700, 700 700)", + "image": "b6ac34ae-c245-4bf5-8c24-cee3b25a8498", + "polygon": "LINEARRING (600 600, 600 1000, 1000 1000, 1000 600, 600 600)", "rotation_angle": 0, "mirrored": false, "confidence": null @@ -1339,204 +1346,204 @@ }, { "model": "documents.entitytype", - "pk": "1d33aeb5-e74a-4ab8-87ec-87a70c01e32d", + "pk": "1af77054-dd36-4b06-ba8a-49e3d91863e0", "fields": { - "name": "number", + "name": "location", "color": "ff0000", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf" + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df" } }, { "model": "documents.entitytype", - "pk": "632e0ab8-cd7e-421e-b0a1-0dac4b82c30e", + "pk": "63f1a5d7-b449-4f63-890f-3a6f54202e38", "fields": { - "name": "location", + "name": "number", "color": "ff0000", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf" + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df" } }, { "model": "documents.entitytype", - "pk": "a77409be-80c0-4b9c-b36f-b5c8d002898b", + "pk": "6fba3f08-f987-41f2-97dd-579d6a4595f3", "fields": { - "name": "organization", + "name": "date", "color": "ff0000", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf" + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df" } }, { "model": "documents.entitytype", - "pk": "e43239b3-2313-4d91-8ddf-5ac1d6f65e71", + "pk": "a6e74713-9506-4aac-a826-1d293185953d", "fields": { "name": "person", "color": "ff0000", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf" + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df" } }, { "model": "documents.entitytype", - "pk": "f025012c-e72b-44d5-971d-5e25906bdb15", + "pk": "b6a370db-6d54-446d-96ad-f5244105da45", "fields": { - "name": "date", + "name": "organization", "color": "ff0000", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf" + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df" } }, { "model": "documents.transcription", - "pk": "0ed2e41b-c334-48bd-9d78-c1295b3169d7", + "pk": "348d340d-e8ae-4a6e-8a1c-cc71d9f554d7", "fields": { - "element": "57428dc4-260a-4463-a11e-f9e9884d97b6", - "worker_version": "e7d35774-1afa-4b51-af32-40b350b12832", - "worker_run": "fc83b191-fb73-4f8c-a37d-d07e3de33a4e", - "text": "ROY", + "element": "26ac9c54-10e9-4996-8cfa-9df1434774f6", + "worker_version": "ccf2a96f-ed15-495c-886b-b5068b01b9f8", + "worker_run": "a3adcf61-c7ce-48e1-8488-541ba1373740", + "text": "PARIS", "orientation": "horizontal-lr", "confidence": 1.0 } }, { "model": "documents.transcription", - "pk": "2422c008-aeb8-4a52-ae47-c51f83619bd8", + "pk": "3b5850fc-cc4a-4200-8639-b23d360c69f8", "fields": { - "element": "2a643cde-c821-429d-aae7-b6d7ef974c8b", - "worker_version": "e7d35774-1afa-4b51-af32-40b350b12832", - "worker_run": "fc83b191-fb73-4f8c-a37d-d07e3de33a4e", - "text": "PARIS", + "element": "be2b81f0-dec4-41fd-a720-e8383244ee91", + "worker_version": "ccf2a96f-ed15-495c-886b-b5068b01b9f8", + "worker_run": "a3adcf61-c7ce-48e1-8488-541ba1373740", + "text": "ROY", "orientation": "horizontal-lr", "confidence": 1.0 } }, { "model": "documents.transcription", - "pk": "45b9462a-1f97-4c03-b059-ad0618f9e858", + "pk": "560159b2-6563-48ec-8ce4-9c600e346d71", "fields": { - "element": "57dc759a-b8be-4411-bfa3-cd884c24b37f", - "worker_version": "e7d35774-1afa-4b51-af32-40b350b12832", - "worker_run": "fc83b191-fb73-4f8c-a37d-d07e3de33a4e", - "text": "Lorem ipsum dolor sit amet", + "element": "b826c0e5-4877-487e-bd77-b4198cf76f4c", + "worker_version": "ccf2a96f-ed15-495c-886b-b5068b01b9f8", + "worker_run": "a3adcf61-c7ce-48e1-8488-541ba1373740", + "text": "DATUM", "orientation": "horizontal-lr", "confidence": 1.0 } }, { "model": "documents.transcription", - "pk": "52de6ce3-c61e-4c61-9adc-eb0f207008d5", + "pk": "72a44064-b773-40c6-9984-9b205540ac13", "fields": { - "element": "78546795-a66d-4e94-bc65-9f78221992d0", - "worker_version": "e7d35774-1afa-4b51-af32-40b350b12832", - "worker_run": "fc83b191-fb73-4f8c-a37d-d07e3de33a4e", - "text": "DATUM", + "element": "6fb612a7-e337-4538-8ca9-f79d7b1c80f3", + "worker_version": "ccf2a96f-ed15-495c-886b-b5068b01b9f8", + "worker_run": "a3adcf61-c7ce-48e1-8488-541ba1373740", + "text": "ROY", "orientation": "horizontal-lr", "confidence": 1.0 } }, { "model": "documents.transcription", - "pk": "9eda35bb-7541-45d0-aa54-24300574407b", + "pk": "bac52ae2-6303-4a67-92b9-b872436e6815", "fields": { - "element": "e67230f0-028c-4ed0-bf9c-7a1c94f2a733", - "worker_version": "e7d35774-1afa-4b51-af32-40b350b12832", - "worker_run": "fc83b191-fb73-4f8c-a37d-d07e3de33a4e", - "text": "DATUM", + "element": "38cafdb6-bb8a-45bc-b514-f19cb27ac7a9", + "worker_version": "ccf2a96f-ed15-495c-886b-b5068b01b9f8", + "worker_run": "a3adcf61-c7ce-48e1-8488-541ba1373740", + "text": "ROY", "orientation": "horizontal-lr", "confidence": 1.0 } }, { "model": "documents.transcription", - "pk": "a7e27520-0b55-49e9-bf39-9c9054568289", + "pk": "c526a613-ea9d-4351-a6df-4a83d83b9383", "fields": { - "element": "bab1b193-41c7-4202-838d-7c4d430746ad", - "worker_version": "e7d35774-1afa-4b51-af32-40b350b12832", - "worker_run": "fc83b191-fb73-4f8c-a37d-d07e3de33a4e", - "text": "ROY", + "element": "30211bbd-f970-46f2-8010-6a03afa219d4", + "worker_version": "ccf2a96f-ed15-495c-886b-b5068b01b9f8", + "worker_run": "a3adcf61-c7ce-48e1-8488-541ba1373740", + "text": "Lorem ipsum dolor sit amet", "orientation": "horizontal-lr", "confidence": 1.0 } }, { "model": "documents.transcription", - "pk": "ca3288be-4c17-4b9c-a0e8-f14a6aa2d111", + "pk": "cc171391-89d2-4ed8-a3c6-70b588f41153", "fields": { - "element": "73277712-ccbc-4bc1-b2ad-6fa75571a705", - "worker_version": "e7d35774-1afa-4b51-af32-40b350b12832", - "worker_run": "fc83b191-fb73-4f8c-a37d-d07e3de33a4e", - "text": "ROY", + "element": "ae67b0f1-dfee-464d-8c96-fa3150eb924f", + "worker_version": "ccf2a96f-ed15-495c-886b-b5068b01b9f8", + "worker_run": "a3adcf61-c7ce-48e1-8488-541ba1373740", + "text": "PARIS", "orientation": "horizontal-lr", "confidence": 1.0 } }, { "model": "documents.transcription", - "pk": "e004e6dd-4e9a-43b8-aa27-23cf1fca158e", + "pk": "cc5df7ac-a137-4fa4-8a71-0e152133bf48", "fields": { - "element": "2e6fdf3b-f6ef-491b-ac48-8e7aecce7014", - "worker_version": "e7d35774-1afa-4b51-af32-40b350b12832", - "worker_run": "fc83b191-fb73-4f8c-a37d-d07e3de33a4e", - "text": "PARIS", + "element": "92edae95-97fd-44c9-a8f3-86aaabd3e685", + "worker_version": "ccf2a96f-ed15-495c-886b-b5068b01b9f8", + "worker_run": "a3adcf61-c7ce-48e1-8488-541ba1373740", + "text": "DATUM", "orientation": "horizontal-lr", "confidence": 1.0 } }, { "model": "documents.transcription", - "pk": "e816de90-1c2a-4762-bf23-41bc11cf4530", + "pk": "e6c64593-5211-4787-997c-cdaa57ef8527", "fields": { - "element": "308f43b9-325c-442e-8f82-a21a8c46c9a7", - "worker_version": "e7d35774-1afa-4b51-af32-40b350b12832", - "worker_run": "fc83b191-fb73-4f8c-a37d-d07e3de33a4e", - "text": "PARIS", + "element": "a317a77b-9ddd-4f48-82cf-17d25aec30f6", + "worker_version": "ccf2a96f-ed15-495c-886b-b5068b01b9f8", + "worker_run": "a3adcf61-c7ce-48e1-8488-541ba1373740", + "text": "DATUM", "orientation": "horizontal-lr", "confidence": 1.0 } }, { "model": "documents.transcription", - "pk": "fa224809-6a5f-4257-b534-96990902e7cb", + "pk": "f16d07b9-5431-4613-974b-fa9a275b96eb", "fields": { - "element": "ff8c551d-28a2-479d-b33e-561cd258498a", - "worker_version": "e7d35774-1afa-4b51-af32-40b350b12832", - "worker_run": "fc83b191-fb73-4f8c-a37d-d07e3de33a4e", - "text": "DATUM", + "element": "9afab3a6-e895-4c0a-807d-d31354bd8b0a", + "worker_version": "ccf2a96f-ed15-495c-886b-b5068b01b9f8", + "worker_run": "a3adcf61-c7ce-48e1-8488-541ba1373740", + "text": "PARIS", "orientation": "horizontal-lr", "confidence": 1.0 } }, { "model": "documents.allowedmetadata", - "pk": "85b1275b-bb58-4c69-9c82-ae5d3aa7586c", + "pk": "abf0de31-f528-42af-a3d3-6951ba9a59a2", "fields": { - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", "type": "location", "name": "location" } }, { "model": "documents.allowedmetadata", - "pk": "adeb590d-3024-4dce-8403-0c3baa52bd9a", + "pk": "eb4ccf3c-1b4c-42c5-acad-ec0b40f8ae3b", "fields": { - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", "type": "text", "name": "folio" } }, { "model": "documents.allowedmetadata", - "pk": "c51d1752-ea5b-4f0f-954f-19ef89e4755e", + "pk": "faf366c7-66e3-4702-9d0f-69f165ff2730", "fields": { - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", "type": "date", "name": "date" } }, { "model": "documents.metadata", - "pk": "114ad13d-68a1-42a4-9488-3f41303a12e6", + "pk": "041e2100-3e15-4898-83cc-cdb6ff86bc86", "fields": { - "element": "36fd659e-9c36-4532-b5a1-ecf08f05e139", + "element": "bd5a671f-ca17-476e-a43d-25b4aa386abf", "name": "number", "type": "text", - "value": "5", + "value": "1", "entity": null, "worker_version": null, "worker_run": null @@ -1544,9 +1551,9 @@ }, { "model": "documents.metadata", - "pk": "36351208-9b63-48a2-ba61-f3cd4e61b508", + "pk": "11b19ba3-6b0d-48b5-a68b-aac627227e11", "fields": { - "element": "b42aa9f3-9347-45a5-9771-c0fe64d7014c", + "element": "7fa801e7-2b7a-46b5-9c2a-19a227ba56d6", "name": "folio", "type": "text", "value": "2r", @@ -1557,12 +1564,12 @@ }, { "model": "documents.metadata", - "pk": "4b2c9758-14f1-4dfb-8f10-980d4b6674ab", + "pk": "52abcc33-23b7-4482-9607-786bc789e578", "fields": { - "element": "cdcd154e-eccc-4a12-98bd-64d991bc3eee", + "element": "b786da45-c90c-4569-aa31-1b4351bc9e34", "name": "folio", "type": "text", - "value": "1v", + "value": "2r", "entity": null, "worker_version": null, "worker_run": null @@ -1570,12 +1577,12 @@ }, { "model": "documents.metadata", - "pk": "85eee757-c23e-4660-b8f6-3f6fcb5cc8ef", + "pk": "765f5186-16dc-4bf6-88c6-80d47d1db628", "fields": { - "element": "51ce7553-ad98-4092-838d-ad778dcb2a92", - "name": "folio", + "element": "7f3bbf36-2f96-4297-adc3-4258e3456c29", + "name": "number", "type": "text", - "value": "2r", + "value": "5", "entity": null, "worker_version": null, "worker_run": null @@ -1583,12 +1590,12 @@ }, { "model": "documents.metadata", - "pk": "8790d53b-c209-474a-9bb4-e7005356fb26", + "pk": "806431c0-093d-4172-884f-8b3e83ea84be", "fields": { - "element": "876a65aa-6179-453e-a2e2-d558cc3dc3ce", + "element": "c77fbfa2-1edc-4c83-bb60-a59773be6f39", "name": "number", "type": "text", - "value": "3", + "value": "2", "entity": null, "worker_version": null, "worker_run": null @@ -1596,12 +1603,12 @@ }, { "model": "documents.metadata", - "pk": "879dded1-10be-43a7-9b25-d0b008792294", + "pk": "8e37aaf1-5ba2-4188-98aa-11667f36ac10", "fields": { - "element": "6e739e39-da6a-4535-9160-23eab0604f83", - "name": "folio", + "element": "dc730372-6e7a-4baf-9d0a-7f1ca89802f9", + "name": "number", "type": "text", - "value": "1v", + "value": "4", "entity": null, "worker_version": null, "worker_run": null @@ -1609,12 +1616,12 @@ }, { "model": "documents.metadata", - "pk": "98140d77-ba6b-4b2d-9c13-d7c8e2c9194a", + "pk": "92fa129a-e147-46f0-9a98-400c78619844", "fields": { - "element": "fc22eb47-6281-4a56-b474-b91993e9eead", - "name": "folio", + "element": "809a018e-3b3e-4ba0-9e10-7378df428f8b", + "name": "number", "type": "text", - "value": "1r", + "value": "3", "entity": null, "worker_version": null, "worker_run": null @@ -1622,12 +1629,12 @@ }, { "model": "documents.metadata", - "pk": "a31ae1f2-a1f3-4b2d-88ac-045361a21ff2", + "pk": "a5569b70-8f9a-4f21-83e6-de0841aeeb4b", "fields": { - "element": "85bc5401-69a7-4d96-bea3-cc47bc6e651c", - "name": "number", + "element": "4bb67850-d7ba-459e-a106-b2cf48f9f6cb", + "name": "folio", "type": "text", - "value": "4", + "value": "1v", "entity": null, "worker_version": null, "worker_run": null @@ -1635,12 +1642,12 @@ }, { "model": "documents.metadata", - "pk": "c72ed6c2-24ee-4b50-951c-3a2f4714592e", + "pk": "a7b28339-a1e9-4d31-bf9d-a24296bb8105", "fields": { - "element": "36f889af-a83b-47b7-ab80-fbf7bdd5c08d", - "name": "number", + "element": "76a56cff-9680-4c5a-8a01-53b43700b093", + "name": "folio", "type": "text", - "value": "2", + "value": "1v", "entity": null, "worker_version": null, "worker_run": null @@ -1648,12 +1655,12 @@ }, { "model": "documents.metadata", - "pk": "d102c307-bd1a-492e-8dd4-d04d9bdbf439", + "pk": "c17618a2-8b96-4b61-9361-1559540a4871", "fields": { - "element": "b728983a-ec3e-4f4d-b1ad-b71c31e39868", - "name": "number", + "element": "590d69b1-95c8-4ba0-8617-9c0b022a4ba8", + "name": "folio", "type": "text", - "value": "1", + "value": "1r", "entity": null, "worker_version": null, "worker_run": null @@ -1661,9 +1668,9 @@ }, { "model": "documents.metadata", - "pk": "e41db6a4-1800-4848-b528-a747e0bcc66e", + "pk": "d1c624a7-e32e-4473-ab71-d5c39e449a76", "fields": { - "element": "57dc759a-b8be-4411-bfa3-cd884c24b37f", + "element": "30211bbd-f970-46f2-8010-6a03afa219d4", "name": "folio", "type": "text", "value": "1r", @@ -1689,7 +1696,7 @@ }, { "model": "images.image", - "pk": "0775b12d-856e-417f-8ab2-b80dceb11e13", + "pk": "0d4b917a-4b05-412e-9a32-78da2031dd70", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", @@ -1703,12 +1710,12 @@ }, { "model": "images.image", - "pk": "0a404dd6-7b53-4f10-ab8e-601ef5f22f97", + "pk": "6358303d-1167-489c-b456-2ad6f80b7909", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", "server": 1, - "path": "img1", + "path": "img5", "width": 1000, "height": 1000, "hash": null, @@ -1717,12 +1724,12 @@ }, { "model": "images.image", - "pk": "30d880ab-43c1-4f62-955f-41bb2f1a0802", + "pk": "b6ac34ae-c245-4bf5-8c24-cee3b25a8498", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", "server": 1, - "path": "img3", + "path": "img1", "width": 1000, "height": 1000, "hash": null, @@ -1731,12 +1738,12 @@ }, { "model": "images.image", - "pk": "8ec1120e-29b7-43cd-b298-1d3ec7144f4f", + "pk": "da507478-8d0a-41d5-8ad7-5b062521e984", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", "server": 1, - "path": "img5", + "path": "img2", "width": 1000, "height": 1000, "hash": null, @@ -1745,12 +1752,12 @@ }, { "model": "images.image", - "pk": "a68a053f-ef37-4f96-bd06-08bb2f31a978", + "pk": "e7b06b72-703b-45aa-9c91-12eba0f1e9d9", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", "server": 1, - "path": "img6", + "path": "img3", "width": 1000, "height": 1000, "hash": null, @@ -1759,12 +1766,12 @@ }, { "model": "images.image", - "pk": "f2a146eb-9cab-4bfb-b97b-59b16137c200", + "pk": "fa147dd6-f548-478d-a2ce-de54e28aeda9", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", "server": 1, - "path": "img2", + "path": "img6", "width": 1000, "height": 1000, "hash": null, @@ -1773,64 +1780,64 @@ }, { "model": "users.right", - "pk": "84d8e8fe-54dc-4fd8-9029-6c1a177bfafa", + "pk": "552b002f-df32-4a69-ba96-cb55735c5c88", "fields": { "user": 2, "group": null, "content_type": 21, - "content_id": "12944eab-1b0e-4653-aa66-4c0231e722bf", + "content_id": "b1be7812-a2b1-4d26-a031-8d85869228df", "level": 100 } }, { "model": "users.right", - "pk": "c8f5b27a-a329-452f-80d4-4e3b06cd5aab", + "pk": "a2e659c9-bb9e-4c5a-9667-44b393da48e0", "fields": { "user": 4, "group": null, "content_type": 34, - "content_id": "9f46c025-7bfb-4322-b5bb-76fded823477", + "content_id": "3bb20c38-2a86-4504-be0f-e63e3b94d65b", "level": 10 } }, { "model": "users.right", - "pk": "d9dd9193-316d-4a74-99a8-31ed99c7ef9d", + "pk": "de2d22ca-2dc3-4037-8048-f2344eeefd26", "fields": { - "user": 3, + "user": 2, "group": null, "content_type": 34, - "content_id": "9f46c025-7bfb-4322-b5bb-76fded823477", - "level": 50 + "content_id": "3bb20c38-2a86-4504-be0f-e63e3b94d65b", + "level": 100 } }, { "model": "users.right", - "pk": "ebc94e97-90e8-4990-afbd-6bd9fdfe286a", + "pk": "e13f9b34-4e97-4f99-8453-65f29520e680", "fields": { "user": 2, "group": null, "content_type": 13, - "content_id": "283c0517-96d3-4f61-8847-7245b131ad32", + "content_id": "f2a2e1cb-2090-4b69-b204-1a40440e2619", "level": 10 } }, { "model": "users.right", - "pk": "fd4b1f5f-03bf-4f08-84bc-acd5eb7da40e", + "pk": "e2d2fa8c-3a28-4b9b-a93b-5fba3d9e7157", "fields": { - "user": 2, + "user": 3, "group": null, "content_type": 34, - "content_id": "9f46c025-7bfb-4322-b5bb-76fded823477", - "level": 100 + "content_id": "3bb20c38-2a86-4504-be0f-e63e3b94d65b", + "level": 50 } }, { "model": "users.user", "pk": 1, "fields": { - "password": "pbkdf2_sha256$720000$86ridKIpMBH5NW2YIPeV87$cNItTxjDwpROD4YpvGIJ1v3KtDbuizX88BeAj6iS9X0=", + "password": "pbkdf2_sha256$720000$35EvN3z9hMVfoshEvJCX17$HTH5LH72xqd/ym03bfkdq93US3a2MKqzicyei5/zZQI=", "last_login": null, "email": "root@root.fr", "display_name": "Admin", @@ -1845,7 +1852,7 @@ "model": "users.user", "pk": 2, "fields": { - "password": "pbkdf2_sha256$720000$rQFnfpWrnGXT4tUT6T2UF5$gmOmD5LFgYwELEKHmAT3BKTPvq7ssh+sSzGLZjMzsHc=", + "password": "pbkdf2_sha256$720000$wmZ5ZDkcvtlXOcUgtAm6sv$Y1Wl6SzWPGbKEsLFBSuQ4snL7RsKdUQsrfFDTWQVIro=", "last_login": null, "email": "user@user.fr", "display_name": "Test user", @@ -1888,7 +1895,7 @@ }, { "model": "users.group", - "pk": "9f46c025-7bfb-4322-b5bb-76fded823477", + "pk": "3bb20c38-2a86-4504-be0f-e63e3b94d65b", "fields": { "name": "User group", "public": false, @@ -3167,186 +3174,78 @@ { "model": "auth.permission", "pk": 142, - "fields": { - "name": "Can add git ref", - "content_type": 39, - "codename": "add_gitref" - } -}, -{ - "model": "auth.permission", - "pk": 143, - "fields": { - "name": "Can change git ref", - "content_type": 39, - "codename": "change_gitref" - } -}, -{ - "model": "auth.permission", - "pk": 144, - "fields": { - "name": "Can delete git ref", - "content_type": 39, - "codename": "delete_gitref" - } -}, -{ - "model": "auth.permission", - "pk": 145, - "fields": { - "name": "Can view git ref", - "content_type": 39, - "codename": "view_gitref" - } -}, -{ - "model": "auth.permission", - "pk": 146, "fields": { "name": "Can add process", - "content_type": 40, + "content_type": 39, "codename": "add_process" } }, { "model": "auth.permission", - "pk": 147, + "pk": 143, "fields": { "name": "Can change process", - "content_type": 40, + "content_type": 39, "codename": "change_process" } }, { "model": "auth.permission", - "pk": 148, + "pk": 144, "fields": { "name": "Can delete process", - "content_type": 40, + "content_type": 39, "codename": "delete_process" } }, { "model": "auth.permission", - "pk": 149, + "pk": 145, "fields": { "name": "Can view process", - "content_type": 40, + "content_type": 39, "codename": "view_process" } }, { "model": "auth.permission", - "pk": 150, + "pk": 146, "fields": { "name": "Can add process element", - "content_type": 41, + "content_type": 40, "codename": "add_processelement" } }, { "model": "auth.permission", - "pk": 151, + "pk": 147, "fields": { "name": "Can change process element", - "content_type": 41, + "content_type": 40, "codename": "change_processelement" } }, { "model": "auth.permission", - "pk": 152, + "pk": 148, "fields": { "name": "Can delete process element", - "content_type": 41, + "content_type": 40, "codename": "delete_processelement" } }, { "model": "auth.permission", - "pk": 153, + "pk": 149, "fields": { "name": "Can view process element", - "content_type": 41, + "content_type": 40, "codename": "view_processelement" } }, { "model": "auth.permission", - "pk": 154, - "fields": { - "name": "Can add repository", - "content_type": 1, - "codename": "add_repository" - } -}, -{ - "model": "auth.permission", - "pk": 155, - "fields": { - "name": "Can change repository", - "content_type": 1, - "codename": "change_repository" - } -}, -{ - "model": "auth.permission", - "pk": 156, - "fields": { - "name": "Can delete repository", - "content_type": 1, - "codename": "delete_repository" - } -}, -{ - "model": "auth.permission", - "pk": 157, - "fields": { - "name": "Can view repository", - "content_type": 1, - "codename": "view_repository" - } -}, -{ - "model": "auth.permission", - "pk": 158, - "fields": { - "name": "Can add revision", - "content_type": 42, - "codename": "add_revision" - } -}, -{ - "model": "auth.permission", - "pk": 159, - "fields": { - "name": "Can change revision", - "content_type": 42, - "codename": "change_revision" - } -}, -{ - "model": "auth.permission", - "pk": 160, - "fields": { - "name": "Can delete revision", - "content_type": 42, - "codename": "delete_revision" - } -}, -{ - "model": "auth.permission", - "pk": 161, - "fields": { - "name": "Can view revision", - "content_type": 42, - "codename": "view_revision" - } -}, -{ - "model": "auth.permission", - "pk": 162, + "pk": 150, "fields": { "name": "Can add worker", "content_type": 2, @@ -3355,7 +3254,7 @@ }, { "model": "auth.permission", - "pk": 163, + "pk": 151, "fields": { "name": "Can change worker", "content_type": 2, @@ -3364,7 +3263,7 @@ }, { "model": "auth.permission", - "pk": 164, + "pk": 152, "fields": { "name": "Can delete worker", "content_type": 2, @@ -3373,7 +3272,7 @@ }, { "model": "auth.permission", - "pk": 165, + "pk": 153, "fields": { "name": "Can view worker", "content_type": 2, @@ -3382,556 +3281,556 @@ }, { "model": "auth.permission", - "pk": 166, + "pk": 154, "fields": { "name": "Can add worker activity", - "content_type": 43, + "content_type": 41, "codename": "add_workeractivity" } }, { "model": "auth.permission", - "pk": 167, + "pk": 155, "fields": { "name": "Can change worker activity", - "content_type": 43, + "content_type": 41, "codename": "change_workeractivity" } }, { "model": "auth.permission", - "pk": 168, + "pk": 156, "fields": { "name": "Can delete worker activity", - "content_type": 43, + "content_type": 41, "codename": "delete_workeractivity" } }, { "model": "auth.permission", - "pk": 169, + "pk": 157, "fields": { "name": "Can view worker activity", - "content_type": 43, + "content_type": 41, "codename": "view_workeractivity" } }, { "model": "auth.permission", - "pk": 170, + "pk": 158, "fields": { "name": "Can add worker configuration", - "content_type": 44, + "content_type": 42, "codename": "add_workerconfiguration" } }, { "model": "auth.permission", - "pk": 171, + "pk": 159, "fields": { "name": "Can change worker configuration", - "content_type": 44, + "content_type": 42, "codename": "change_workerconfiguration" } }, { "model": "auth.permission", - "pk": 172, + "pk": 160, "fields": { "name": "Can delete worker configuration", - "content_type": 44, + "content_type": 42, "codename": "delete_workerconfiguration" } }, { "model": "auth.permission", - "pk": 173, + "pk": 161, "fields": { "name": "Can view worker configuration", - "content_type": 44, + "content_type": 42, "codename": "view_workerconfiguration" } }, { "model": "auth.permission", - "pk": 174, + "pk": 162, "fields": { "name": "Can add worker type", - "content_type": 45, + "content_type": 43, "codename": "add_workertype" } }, { "model": "auth.permission", - "pk": 175, + "pk": 163, "fields": { "name": "Can change worker type", - "content_type": 45, + "content_type": 43, "codename": "change_workertype" } }, { "model": "auth.permission", - "pk": 176, + "pk": 164, "fields": { "name": "Can delete worker type", - "content_type": 45, + "content_type": 43, "codename": "delete_workertype" } }, { "model": "auth.permission", - "pk": 177, + "pk": 165, "fields": { "name": "Can view worker type", - "content_type": 45, + "content_type": 43, "codename": "view_workertype" } }, { "model": "auth.permission", - "pk": 178, + "pk": 166, "fields": { "name": "Can add worker version", - "content_type": 46, + "content_type": 44, "codename": "add_workerversion" } }, { "model": "auth.permission", - "pk": 179, + "pk": 167, "fields": { "name": "Can change worker version", - "content_type": 46, + "content_type": 44, "codename": "change_workerversion" } }, { "model": "auth.permission", - "pk": 180, + "pk": 168, "fields": { "name": "Can delete worker version", - "content_type": 46, + "content_type": 44, "codename": "delete_workerversion" } }, { "model": "auth.permission", - "pk": 181, + "pk": 169, "fields": { "name": "Can view worker version", - "content_type": 46, + "content_type": 44, "codename": "view_workerversion" } }, { "model": "auth.permission", - "pk": 182, + "pk": 170, "fields": { "name": "Can add worker run", - "content_type": 47, + "content_type": 45, "codename": "add_workerrun" } }, { "model": "auth.permission", - "pk": 183, + "pk": 171, "fields": { "name": "Can change worker run", - "content_type": 47, + "content_type": 45, "codename": "change_workerrun" } }, { "model": "auth.permission", - "pk": 184, + "pk": 172, "fields": { "name": "Can delete worker run", - "content_type": 47, + "content_type": 45, "codename": "delete_workerrun" } }, { "model": "auth.permission", - "pk": 185, + "pk": 173, "fields": { "name": "Can view worker run", - "content_type": 47, + "content_type": 45, "codename": "view_workerrun" } }, { "model": "auth.permission", - "pk": 186, + "pk": 174, "fields": { "name": "Can add process dataset set", - "content_type": 48, + "content_type": 46, "codename": "add_processdatasetset" } }, { "model": "auth.permission", - "pk": 187, + "pk": 175, "fields": { "name": "Can change process dataset set", - "content_type": 48, + "content_type": 46, "codename": "change_processdatasetset" } }, { "model": "auth.permission", - "pk": 188, + "pk": 176, "fields": { "name": "Can delete process dataset set", - "content_type": 48, + "content_type": 46, "codename": "delete_processdatasetset" } }, { "model": "auth.permission", - "pk": 189, + "pk": 177, "fields": { "name": "Can view process dataset set", - "content_type": 48, + "content_type": 46, "codename": "view_processdatasetset" } }, { "model": "auth.permission", - "pk": 190, + "pk": 178, "fields": { "name": "Can add dataset", - "content_type": 49, + "content_type": 47, "codename": "add_dataset" } }, { "model": "auth.permission", - "pk": 191, + "pk": 179, "fields": { "name": "Can change dataset", - "content_type": 49, + "content_type": 47, "codename": "change_dataset" } }, { "model": "auth.permission", - "pk": 192, + "pk": 180, "fields": { "name": "Can delete dataset", - "content_type": 49, + "content_type": 47, "codename": "delete_dataset" } }, { "model": "auth.permission", - "pk": 193, + "pk": 181, "fields": { "name": "Can view dataset", - "content_type": 49, + "content_type": 47, "codename": "view_dataset" } }, { "model": "auth.permission", - "pk": 194, + "pk": 182, "fields": { "name": "Can add metric key", - "content_type": 50, + "content_type": 48, "codename": "add_metrickey" } }, { "model": "auth.permission", - "pk": 195, + "pk": 183, "fields": { "name": "Can change metric key", - "content_type": 50, + "content_type": 48, "codename": "change_metrickey" } }, { "model": "auth.permission", - "pk": 196, + "pk": 184, "fields": { "name": "Can delete metric key", - "content_type": 50, + "content_type": 48, "codename": "delete_metrickey" } }, { "model": "auth.permission", - "pk": 197, + "pk": 185, "fields": { "name": "Can view metric key", - "content_type": 50, + "content_type": 48, "codename": "view_metrickey" } }, { "model": "auth.permission", - "pk": 198, + "pk": 186, "fields": { "name": "Can add model", - "content_type": 51, + "content_type": 49, "codename": "add_model" } }, { "model": "auth.permission", - "pk": 199, + "pk": 187, "fields": { "name": "Can change model", - "content_type": 51, + "content_type": 49, "codename": "change_model" } }, { "model": "auth.permission", - "pk": 200, + "pk": 188, "fields": { "name": "Can delete model", - "content_type": 51, + "content_type": 49, "codename": "delete_model" } }, { "model": "auth.permission", - "pk": 201, + "pk": 189, "fields": { "name": "Can view model", - "content_type": 51, + "content_type": 49, "codename": "view_model" } }, { "model": "auth.permission", - "pk": 202, + "pk": 190, "fields": { "name": "Can add model version", - "content_type": 52, + "content_type": 50, "codename": "add_modelversion" } }, { "model": "auth.permission", - "pk": 203, + "pk": 191, "fields": { "name": "Can change model version", - "content_type": 52, + "content_type": 50, "codename": "change_modelversion" } }, { "model": "auth.permission", - "pk": 204, + "pk": 192, "fields": { "name": "Can delete model version", - "content_type": 52, + "content_type": 50, "codename": "delete_modelversion" } }, { "model": "auth.permission", - "pk": 205, + "pk": 193, "fields": { "name": "Can view model version", - "content_type": 52, + "content_type": 50, "codename": "view_modelversion" } }, { "model": "auth.permission", - "pk": 206, + "pk": 194, "fields": { "name": "Can add metric value", - "content_type": 53, + "content_type": 51, "codename": "add_metricvalue" } }, { "model": "auth.permission", - "pk": 207, + "pk": 195, "fields": { "name": "Can change metric value", - "content_type": 53, + "content_type": 51, "codename": "change_metricvalue" } }, { "model": "auth.permission", - "pk": 208, + "pk": 196, "fields": { "name": "Can delete metric value", - "content_type": 53, + "content_type": 51, "codename": "delete_metricvalue" } }, { "model": "auth.permission", - "pk": 209, + "pk": 197, "fields": { "name": "Can view metric value", - "content_type": 53, + "content_type": 51, "codename": "view_metricvalue" } }, { "model": "auth.permission", - "pk": 210, + "pk": 198, "fields": { "name": "Can add dataset element", - "content_type": 54, + "content_type": 52, "codename": "add_datasetelement" } }, { "model": "auth.permission", - "pk": 211, + "pk": 199, "fields": { "name": "Can change dataset element", - "content_type": 54, + "content_type": 52, "codename": "change_datasetelement" } }, { "model": "auth.permission", - "pk": 212, + "pk": 200, "fields": { "name": "Can delete dataset element", - "content_type": 54, + "content_type": 52, "codename": "delete_datasetelement" } }, { "model": "auth.permission", - "pk": 213, + "pk": 201, "fields": { "name": "Can view dataset element", - "content_type": 54, + "content_type": 52, "codename": "view_datasetelement" } }, { "model": "auth.permission", - "pk": 214, + "pk": 202, "fields": { "name": "Can add dataset set", - "content_type": 55, + "content_type": 53, "codename": "add_datasetset" } }, { "model": "auth.permission", - "pk": 215, + "pk": 203, "fields": { "name": "Can change dataset set", - "content_type": 55, + "content_type": 53, "codename": "change_datasetset" } }, { "model": "auth.permission", - "pk": 216, + "pk": 204, "fields": { "name": "Can delete dataset set", - "content_type": 55, + "content_type": 53, "codename": "delete_datasetset" } }, { "model": "auth.permission", - "pk": 217, + "pk": 205, "fields": { "name": "Can view dataset set", - "content_type": 55, + "content_type": 53, "codename": "view_datasetset" } }, { "model": "ponos.farm", - "pk": "283c0517-96d3-4f61-8847-7245b131ad32", + "pk": "f2a2e1cb-2090-4b69-b204-1a40440e2619", "fields": { "name": "Wheat farm", - "seed": "744e8c9a9b201cccdfdaf543db13c2775a9c3dd0d17fb4cf8ba19707a1bf3f14" + "seed": "c04bde99f4349c3c806e4e82dc60c42163fc3820a421ce82c4055d67ae4ec4bb" } }, { "model": "training.dataset", - "pk": "9894c9f7-be52-4cb7-8e3a-193a518184ee", + "pk": "673cba70-7596-4a91-9921-49eebe97f63f", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", "creator": 2, "task": null, - "name": "Second Dataset", - "description": "dataset number two", + "name": "First Dataset", + "description": "dataset number one", "state": "open", "unique_elements": true } }, { "model": "training.dataset", - "pk": "b9152505-b3e9-473a-b1c4-e277f564a6d9", + "pk": "da0300a9-55e5-4a0d-90a2-4fb42d0a4744", "fields": { "created": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z", - "corpus": "12944eab-1b0e-4653-aa66-4c0231e722bf", + "corpus": "b1be7812-a2b1-4d26-a031-8d85869228df", "creator": 2, "task": null, - "name": "First Dataset", - "description": "dataset number one", + "name": "Second Dataset", + "description": "dataset number two", "state": "open", "unique_elements": true } }, { "model": "training.datasetset", - "pk": "19cbad25-ec14-4ea4-adcb-8963c59d892a", + "pk": "3cd3cbbd-6454-4977-814c-42fc1a4c858a", "fields": { - "name": "train", - "dataset": "b9152505-b3e9-473a-b1c4-e277f564a6d9" + "name": "dev", + "dataset": "da0300a9-55e5-4a0d-90a2-4fb42d0a4744" } }, { "model": "training.datasetset", - "pk": "881a2377-9c28-48ac-a148-0f5926b88c25", + "pk": "3e1573e3-044b-47b0-b2b3-27eda5b4e441", "fields": { "name": "test", - "dataset": "9894c9f7-be52-4cb7-8e3a-193a518184ee" + "dataset": "673cba70-7596-4a91-9921-49eebe97f63f" } }, { "model": "training.datasetset", - "pk": "9861921d-ea65-4ec9-9d2e-063187ef38e9", + "pk": "4454e41b-c60c-4d68-b428-d07c74af1f17", "fields": { "name": "dev", - "dataset": "9894c9f7-be52-4cb7-8e3a-193a518184ee" + "dataset": "673cba70-7596-4a91-9921-49eebe97f63f" } }, { "model": "training.datasetset", - "pk": "c62b45a1-864b-4be0-a642-0e36ae068edf", + "pk": "5333a80b-ff91-4a6b-9703-b26b8f472118", "fields": { "name": "test", - "dataset": "b9152505-b3e9-473a-b1c4-e277f564a6d9" + "dataset": "da0300a9-55e5-4a0d-90a2-4fb42d0a4744" } }, { "model": "training.datasetset", - "pk": "d8b49d2f-85d6-402f-a45c-7ce0977ca93c", + "pk": "94c3d754-21ad-49e3-90d0-3874e54aa029", "fields": { - "name": "dev", - "dataset": "b9152505-b3e9-473a-b1c4-e277f564a6d9" + "name": "train", + "dataset": "da0300a9-55e5-4a0d-90a2-4fb42d0a4744" } }, { "model": "training.datasetset", - "pk": "f901c2a3-0520-4357-a1e9-9dd4926f9061", + "pk": "d2e394b1-6a76-4b83-8966-392422317d2b", "fields": { "name": "train", - "dataset": "9894c9f7-be52-4cb7-8e3a-193a518184ee" + "dataset": "673cba70-7596-4a91-9921-49eebe97f63f" } } ] diff --git a/arkindex/documents/management/commands/bootstrap.py b/arkindex/documents/management/commands/bootstrap.py index d2a90f2dc0..1336b37c41 100644 --- a/arkindex/documents/management/commands/bootstrap.py +++ b/arkindex/documents/management/commands/bootstrap.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -from uuid import uuid4 from django.conf import settings from django.core.management.base import BaseCommand @@ -9,7 +8,7 @@ from django.db.utils import IntegrityError from arkindex.images.models import ImageServer from arkindex.ponos.models import Farm -from arkindex.process.models import FeatureUsage, Repository, Worker, WorkerType, WorkerVersion, WorkerVersionState +from arkindex.process.models import FeatureUsage, Worker, WorkerType, WorkerVersion, WorkerVersionState # Constants used in architecture project UPLOADS_IMAGE_SERVER_ID = 12345 @@ -25,10 +24,7 @@ PONOS_FARM_NAME = "Bootstrap farm" PONOS_FARM_SEED = "b12868101dab84984481741663d809d2393784894d6e807ceee0bd95051bf971" IMPORT_WORKER_VERSION_ID = "f2bb8dd7-55e9-49ae-9bd9-b1d2e5d491b9" IMPORT_WORKER_SLUG = "file_import" -IMPORT_WORKER_REPO = "https://gitlab.teklia.com/arkindex/tasks" -IMPORT_WORKER_REVISION_MESSAGE = "File import worker bootstrap" -IMPORT_WORKER_REVISION_AUTHOR = "Dev Bootstrap" - +IMPORT_WORKER_REPO_URL = "https://gitlab.teklia.com/arkindex/tasks" class Command(BaseCommand): help = "Build required Database model instances for local development." @@ -136,51 +132,26 @@ class Command(BaseCommand): except ImageServer.DoesNotExist: pass - # Create a fake worker version on a fake worker on a fake repo with a fake revision for file imports - repo, created = Repository.objects.get_or_create( - url=IMPORT_WORKER_REPO, - ) - if created: - self.success(f"Created Git repository for {IMPORT_WORKER_REPO}") - else: - self.success(f"Repository for {IMPORT_WORKER_REPO} exists") - + # Create a fake worker version on a fake worker for file imports worker_type, _ = WorkerType.objects.get_or_create( slug="import", defaults={"display_name": "Import"} ) worker, created = Worker.objects.update_or_create( - repository=repo, slug=IMPORT_WORKER_SLUG, defaults={"name": "File import", "type": worker_type}, + repository_url=IMPORT_WORKER_REPO_URL, ) if created: self.success(f"Created {IMPORT_WORKER_SLUG} worker") else: self.success(f"Updated {IMPORT_WORKER_SLUG} worker") - revision = repo.revisions.filter( - Q(message=IMPORT_WORKER_REVISION_MESSAGE) - | Q(author=IMPORT_WORKER_REVISION_AUTHOR) - ).first() - if revision: - revision.message = IMPORT_WORKER_REVISION_MESSAGE - revision.author = IMPORT_WORKER_REVISION_AUTHOR - self.success(f"Updated revision {revision.hash}") - else: - revision = repo.revisions.create( - hash=uuid4().hex, - message=IMPORT_WORKER_REVISION_MESSAGE, - author=IMPORT_WORKER_REVISION_AUTHOR, - ) - self.success(f"Created revision {revision.hash}") - try: version = WorkerVersion.objects.get(id=IMPORT_WORKER_VERSION_ID) created = False except WorkerVersion.DoesNotExist: version, created = worker.versions.get_or_create( - revision=revision, defaults={ "id": IMPORT_WORKER_VERSION_ID, "configuration": {}, diff --git a/arkindex/documents/management/commands/build_fixtures.py b/arkindex/documents/management/commands/build_fixtures.py index 4d8c3a089a..ff5049a195 100644 --- a/arkindex/documents/management/commands/build_fixtures.py +++ b/arkindex/documents/management/commands/build_fixtures.py @@ -86,7 +86,6 @@ class Command(BaseCommand): slug="initialisation", type=init_type, ), - revision=None, version=1, configuration={ "docker": { @@ -104,7 +103,6 @@ class Command(BaseCommand): slug="reco", type=recognizer_worker_type, ), - revision=None, version=1, configuration={"test": 42}, state=WorkerVersionState.Available, @@ -117,7 +115,6 @@ class Command(BaseCommand): slug="dla", type=dla_worker_type, ), - revision=None, version=1, configuration={"test": 42}, state=WorkerVersionState.Available, @@ -131,7 +128,6 @@ class Command(BaseCommand): slug="file_import", type=import_worker_type, ), - revision=None, version=1, configuration={}, state=WorkerVersionState.Available, @@ -145,7 +141,6 @@ class Command(BaseCommand): slug="worker-gpu", type=gpu_worker_type, ), - revision=None, version=1, configuration={"test": 42}, state=WorkerVersionState.Available, @@ -161,7 +156,6 @@ class Command(BaseCommand): slug="generic", type=recognizer_worker_type, ), - revision=None, version=1, configuration={"test": 42}, state=WorkerVersionState.Available, @@ -177,7 +171,6 @@ class Command(BaseCommand): slug="custom", type=custom_worker_type, ), - revision=None, version=1, configuration={"custom": "value"}, state=WorkerVersionState.Created, diff --git a/arkindex/documents/management/commands/load_export.py b/arkindex/documents/management/commands/load_export.py index d3240d55f1..d93cc04269 100644 --- a/arkindex/documents/management/commands/load_export.py +++ b/arkindex/documents/management/commands/load_export.py @@ -27,8 +27,6 @@ from arkindex.documents.models import ( from arkindex.images.models import Image, ImageServer from arkindex.process.models import ( ProcessMode, - Repository, - Revision, Worker, WorkerConfiguration, WorkerRun, @@ -70,12 +68,6 @@ SQL_ELEMENT_TYPE_QUERY = """ SQL_ML_CLASS_QUERY = "SELECT DISTINCT class_name FROM classification" -SQL_REPOSITORY_QUERY = "SELECT DISTINCT repository_url FROM worker_version WHERE repository_url IS NOT NULL" -SQL_REVISION_QUERY = """ - SELECT DISTINCT revision, repository_url - FROM worker_version - WHERE revision IS NOT NULL AND repository_url IS NOT NULL -""" SQL_WORKER_TYPE_QUERY = "SELECT DISTINCT type FROM worker_version" SQL_WORKER_VERSION_QUERY = "SELECT * FROM worker_version" SQL_WORKER_RUN_QUERY = "SELECT * FROM worker_run" @@ -395,22 +387,6 @@ class Command(BaseCommand): def create_ml_class(self, row): return self.corpus.ml_classes.get_or_create(name=row["class_name"]) - def create_repository(self, row): - repo, created = Repository.objects.get_or_create( - url=row["repository_url"], - ) - return repo, created - - def create_revision(self, row): - return Revision.objects.get_or_create( - repo_id=self.repository_map[row["repository_url"]], - hash=row["revision"], - defaults={ - "message": "Fake revision", - "author": self.user.display_name, - } - ) - def create_worker_type(self, row): return WorkerType.objects.get_or_create( slug=row["type"], @@ -422,7 +398,7 @@ class Command(BaseCommand): def create_worker(self, row): return Worker.objects.get_or_create( slug=row["slug"], - repository_id=row["repository_url"] and self.repository_map[row["repository_url"]], + repository_url=row["repository_url"], defaults={ "name": row["name"], "type_id": self.worker_type_map[row["type"]], @@ -432,7 +408,7 @@ class Command(BaseCommand): def create_worker_version(self, row): return WorkerVersion.objects.get_or_create( worker_id=self.worker_map[row["id"]], - revision_id=row["revision"] and self.revision_map[row["revision"]], + revision_url=row["revision"], version=row["version"], defaults={ "configuration": {"configuration": {}} @@ -564,8 +540,6 @@ class Command(BaseCommand): self.ml_class_map = self.create_objects(MLClass, self.create_ml_class, SQL_ML_CLASS_QUERY) # Create worker versions - self.repository_map = self.create_objects(Repository, self.create_repository, SQL_REPOSITORY_QUERY) - self.revision_map = self.create_objects(Revision, self.create_revision, SQL_REVISION_QUERY) self.worker_type_map = self.create_objects(WorkerType, self.create_worker_type, SQL_WORKER_TYPE_QUERY) self.worker_map = self.create_objects(Worker, self.create_worker, SQL_WORKER_VERSION_QUERY) self.worker_version_map = self.create_objects(WorkerVersion, self.create_worker_version, SQL_WORKER_VERSION_QUERY) diff --git a/arkindex/documents/tests/commands/test_cleanup.py b/arkindex/documents/tests/commands/test_cleanup.py index 9592bcf042..9c016911af 100644 --- a/arkindex/documents/tests/commands/test_cleanup.py +++ b/arkindex/documents/tests/commands/test_cleanup.py @@ -1,4 +1,3 @@ -import uuid from datetime import datetime, timedelta, timezone from io import StringIO from textwrap import dedent @@ -13,10 +12,8 @@ from arkindex.images.models import Image, ImageServer from arkindex.ponos.models import Artifact, Farm, Task from arkindex.process.models import ( DataFile, - GitRefType, Process, ProcessMode, - Repository, Worker, WorkerRun, WorkerType, @@ -34,16 +31,11 @@ class TestCleanupCommand(FixtureTestCase): @classmethod def setUpTestData(cls): super().setUpTestData() - cls.repo = Repository.objects.create(url="http://nerv.co.jp/nerv/eva/") - cls.revision = cls.repo.revisions.create( - hash=str(uuid.uuid4()), - message="A revision", - author="Someone", - ) - cls.worker = cls.repo.workers.create( + cls.worker = Worker.objects.create( name="A worker", slug="test_worker", - type=WorkerType.objects.first() + type=WorkerType.objects.first(), + repository_url="http://nerv.co.jp/nerv/eva/", ) def cleanup(self, args=[]): @@ -583,27 +575,11 @@ class TestCleanupCommand(FixtureTestCase): def test_cleanup_expired_processes_null(self, s3_mock, rq_mock): # This revision on the `main` branch does not have any WorkerVersions. # Improper handling of NULL values in the queries looking for expired processes and - # excluding revisions that should not be deleted based on the GitRefs could lead to + # excluding revisions that should not be deleted could lead to # this revision causing no expired processes to ever be found. - empty_revision = self.repo.revisions.create( - hash=str(uuid.uuid4()), - message="A revision with no worker versions", - author="Someone", - ) - empty_revision.refs.create(repository=self.repo, type=GitRefType.Branch, name="main") - unavailable_worker_revision = self.repo.revisions.create( - hash=str(uuid.uuid4()), - message="A revision with a worker version with no artifact", - author="Someone", - ) - unavailable_worker_revision.refs.create(repository=self.repo, type=GitRefType.Tag, name="1.2.3-rc4") - - # Same as above: this WorkerVersion with no docker_image could break the query. - self.worker.versions.create( - revision=unavailable_worker_revision, - configuration={}, - ) + # This WorkerVersion with no docker_image could break the query. + self.worker.versions.create(configuration={}, version=1) # These artifacts should be cleaned up lonely_artifact = self._make_artifact() @@ -665,8 +641,6 @@ class TestCleanupCommand(FixtureTestCase): # Those still exist, refreshing works lonely_artifact.task.process.refresh_from_db() lonely_artifact_2.task.process.refresh_from_db() - empty_revision.refresh_from_db() - unavailable_worker_revision.refresh_from_db() self.assertEqual(s3_mock.Object().delete.call_count, 4) diff --git a/arkindex/documents/tests/commands/test_load_export.py b/arkindex/documents/tests/commands/test_load_export.py index ff43bf2fe3..383c1bc7ef 100644 --- a/arkindex/documents/tests/commands/test_load_export.py +++ b/arkindex/documents/tests/commands/test_load_export.py @@ -12,7 +12,7 @@ from arkindex.documents.management.commands.load_export import Command from arkindex.documents.models import Corpus, Element, ElementPath, EntityType, Transcription from arkindex.documents.tasks import corpus_delete from arkindex.images.models import Image, ImageServer -from arkindex.process.models import ProcessMode, Repository, Worker, WorkerRun, WorkerType, WorkerVersion +from arkindex.process.models import ProcessMode, Worker, WorkerRun, WorkerType, WorkerVersion from arkindex.project.tests import FixtureTestCase, force_constraints_immediate from arkindex.training.models import Dataset, DatasetElement @@ -34,7 +34,6 @@ class TestLoadExport(FixtureTestCase): unexpected_fields_by_model = { "documents.elementtype": ["display_name", "indexable"], "documents.mlclass": [], - "process.repository": ["git_ref_revisions"], "process.worker": [], "process.revision": ["message", "author"], "process.workerversion": ["created", "updated", "configuration", "state", "docker_image_iid"], @@ -319,11 +318,7 @@ class TestLoadExport(FixtureTestCase): self.assertEqual(corpus.entities.all().count(), 0) def test_create_worker(self): - repo_uuid = Repository.objects.create(url="http://my_repo.fake/workers/worker").id command = Command() - command.repository_map = { - "http://my_repo.fake/workers/worker": repo_uuid - } command.worker_type_map = { "recognizer": WorkerType.objects.get(slug="recognizer").id } diff --git a/arkindex/documents/tests/tasks/test_corpus_delete.py b/arkindex/documents/tests/tasks/test_corpus_delete.py index 906523cf88..24a03fd478 100644 --- a/arkindex/documents/tests/tasks/test_corpus_delete.py +++ b/arkindex/documents/tests/tasks/test_corpus_delete.py @@ -8,7 +8,6 @@ from arkindex.process.models import ( Process, ProcessDatasetSet, ProcessMode, - Repository, WorkerVersion, ) from arkindex.project.tests import FixtureTestCase, force_constraints_immediate @@ -104,9 +103,6 @@ class TestDeleteCorpus(FixtureTestCase): ) # Create a separate corpus that should not get anything deleted - cls.repo = Repository.objects.create( - url="http://lol.git", - ) cls.corpus2 = Corpus.objects.create(name="Other corpus") dataset1 = Dataset.objects.get(name="First Dataset") @@ -130,11 +126,6 @@ class TestDeleteCorpus(FixtureTestCase): cls.dataset_process3 = cls.corpus2.processes.create(creator=cls.user, mode=ProcessMode.Dataset) ProcessDatasetSet.objects.create(process=cls.dataset_process3, set=cls.dataset2.sets.get(name="validation")) - cls.rev = cls.repo.revisions.create( - hash="42", - message="oh", - author="me", - ) cls.process = Process.objects.create( creator=cls.user, corpus=cls.corpus2, @@ -198,15 +189,12 @@ class TestDeleteCorpus(FixtureTestCase): self.assertEqual(self.corpus2.elements.count(), 2) self.assertEqual(Element.objects.count(), 2) - self.repo.refresh_from_db() - self.rev.refresh_from_db() self.process.refresh_from_db() self.df.refresh_from_db() self.vol.refresh_from_db() self.page.refresh_from_db() self.dataset_process3.refresh_from_db() - self.assertTrue(self.repo.revisions.filter(id=self.rev.id).exists()) self.assertEqual(self.process.files.get(), self.df) self.assertTrue(Element.objects.get_descending(self.vol.id).filter(id=self.page.id).exists()) self.assertTrue(self.corpus2.datasets.filter(id=self.dataset2.id).exists()) diff --git a/arkindex/ponos/tests/test_api.py b/arkindex/ponos/tests/test_api.py index 5bbcdf05bf..1c1db1bee7 100644 --- a/arkindex/ponos/tests/test_api.py +++ b/arkindex/ponos/tests/test_api.py @@ -12,7 +12,7 @@ from rest_framework import status from arkindex.documents.models import Corpus from arkindex.ponos.models import Agent, AgentMode, Farm, State, Task -from arkindex.process.models import Process, ProcessMode, Revision, WorkerVersion +from arkindex.process.models import Process, ProcessMode, WorkerVersion from arkindex.project.tests import FixtureAPITestCase from arkindex.users.models import Right, Role, User @@ -25,7 +25,6 @@ class TestAPI(FixtureAPITestCase): super().setUpTestData() cls.page_1 = cls.corpus.elements.get(name="Volume 1, page 1r") cls.page_2 = cls.corpus.elements.get(name="Volume 1, page 2r") - cls.rev = Revision.objects.first() cls.process = Process.objects.get(mode=ProcessMode.Workers) cls.process.run() cls.task1, cls.task2, cls.task3 = cls.process.tasks.all().order_by("depth") diff --git a/arkindex/process/admin.py b/arkindex/process/admin.py index 667dff48c9..14becfab77 100644 --- a/arkindex/process/admin.py +++ b/arkindex/process/admin.py @@ -5,8 +5,6 @@ from enumfields.admin import EnumFieldListFilter from arkindex.process.models import ( DataFile, Process, - Repository, - Revision, Worker, WorkerConfiguration, WorkerType, @@ -61,38 +59,23 @@ class DataFileAdmin(admin.ModelAdmin): inlines = [DataFileInline, ] -class RevisionAdmin(admin.ModelAdmin): - list_display = ("id", "hash", "message", "author", "repo") - list_filter = ("repo", ) - fields = ("id", "hash", "message", "author", "repo") - readonly_fields = ("id", ) - search_fields = ("hash", "message", ) - - class WorkerInline(admin.StackedInline): model = Worker -class RepositoryAdmin(admin.ModelAdmin): - list_display = ("id", "url") - fields = ("id", "url") - readonly_fields = ("id", ) - inlines = [WorkerInline, ] - - class WorkerVersionInline(admin.StackedInline): show_change_link = True model = WorkerVersion - fields = ("revision", "state", "configuration", "docker_image_iid") - readonly_fields = ("revision", "state", "configuration", "docker_image_iid") + fields = ("state", "configuration", "docker_image_iid") + readonly_fields = ("state", "configuration", "docker_image_iid") def get_queryset(self, *args, **kwargs): """ - Prefetch worker and revision as they are used in versions inline labels. + Prefetch workers as they are used in versions inline labels. Using a proxy model to override `__str__` is possible but removes the Change link as the model does not appear as registered. """ - return super().get_queryset(*args, **kwargs).prefetch_related("worker", "revision") + return super().get_queryset(*args, **kwargs).prefetch_related("worker") class WorkerConfigurationInline(admin.StackedInline): @@ -101,14 +84,14 @@ class WorkerConfigurationInline(admin.StackedInline): class WorkerAdmin(admin.ModelAdmin): - list_display = ("name", "slug", "archived", "type", "repository") + list_display = ("name", "slug", "archived", "type") list_filter = (ArchivedListFilter, ) - fields = ("id", "name", "slug", "type", "description", "repository", "public", "archived") + fields = ("id", "name", "slug", "type", "description", "public", "archived") readonly_fields = ("id", ) inlines = [WorkerVersionInline, WorkerConfigurationInline] def get_queryset(self, *args, **kwargs): - return super().get_queryset(*args, **kwargs).select_related("repository", "type") + return super().get_queryset(*args, **kwargs).select_related("type") class WorkerTypeAdmin(admin.ModelAdmin): @@ -118,11 +101,10 @@ class WorkerTypeAdmin(admin.ModelAdmin): class WorkerVersionAdmin(admin.ModelAdmin): - list_display = ("id", "worker", "revision", "version") + list_display = ("id", "worker", "version") list_filter = ("worker", ) - fields = ("id", "worker", "revision", "version", "configuration", "model_usage", "gpu_usage", "docker_image_iid") + fields = ("id", "worker", "version", "configuration", "model_usage", "gpu_usage", "docker_image_iid") readonly_fields = ("id", ) - raw_id_fields = ("revision", ) class WorkerConfigurationAdmin(admin.ModelAdmin): @@ -133,8 +115,6 @@ class WorkerConfigurationAdmin(admin.ModelAdmin): admin.site.register(Process, ProcessAdmin) admin.site.register(DataFile, DataFileAdmin) -admin.site.register(Revision, RevisionAdmin) -admin.site.register(Repository, RepositoryAdmin) admin.site.register(Worker, WorkerAdmin) admin.site.register(WorkerType, WorkerTypeAdmin) admin.site.register(WorkerVersion, WorkerVersionAdmin) diff --git a/arkindex/process/api.py b/arkindex/process/api.py index cd56db41de..717948917c 100644 --- a/arkindex/process/api.py +++ b/arkindex/process/api.py @@ -34,7 +34,6 @@ from drf_spectacular.utils import ( inline_serializer, ) from rest_framework import permissions, serializers, status -from rest_framework.authentication import SessionAuthentication, TokenAuthentication from rest_framework.exceptions import NotFound, PermissionDenied, ValidationError from rest_framework.generics import ( CreateAPIView, @@ -55,8 +54,6 @@ from arkindex.ponos.permissions import IsTask, IsVerifiedOrAgent from arkindex.process.models import ( ActivityState, DataFile, - GitRef, - GitRefType, Process, ProcessDatasetSet, ProcessMode, @@ -92,7 +89,6 @@ from arkindex.process.serializers.worker_runs import ( ) from arkindex.process.serializers.workers import ( CorpusWorkerVersionSerializer, - DockerWorkerVersionSerializer, ExistingWorkerException, WorkerActivitySerializer, WorkerConfigurationExistsErrorSerializer, @@ -558,7 +554,7 @@ class StartProcess(CorpusACLMixin, CreateAPIView): .select_related("corpus") .filter(corpus_id__isnull=False) .prefetch_related(Prefetch("worker_runs", queryset=WorkerRun.objects.select_related( - "version__worker__repository", + "version__worker", "model_version__model", "configuration", ))) @@ -773,12 +769,6 @@ class ProcessDatasetSetManage(CreateAPIView, DestroyAPIView): get=extend_schema( description="List workers for which the user has an execution access.", parameters=[ - OpenApiParameter( - "repository_id", - type=UUID, - description="Filter workers by repository ID.", - required=False, - ), OpenApiParameter( "name", type=str, @@ -842,15 +832,6 @@ class WorkerList(ListCreateAPIView): else: filters &= Q(models=compatible_model) - repo_id = self.request.query_params.get("repository_id") - if repo_id: - try: - repo_id = UUID(repo_id) - except (TypeError, ValueError): - errors["repository_id"].append("Invalid UUID") - else: - filters &= Q(repository_id=repo_id) - name_filter = self.request.query_params.get("name") if name_filter: filters &= Q(name__icontains=name_filter) @@ -904,7 +885,7 @@ class WorkerTypesList(ListAPIView): @extend_schema_view( get=extend_schema( description=( - "List versions for a given worker ID with their revision and associated git references.\n\n" + "List versions for a given worker ID.\n\n" "Requires an **execution** access to the worker." ), parameters=[ @@ -912,7 +893,7 @@ class WorkerTypesList(ListAPIView): "mode", type=str, default="complete", - description=("If set to `simple`, exclude versions other than master/main or with no tag") + description=("If set to `simple`, exclude versions with no tag") ) ], ), @@ -937,10 +918,7 @@ class WorkerVersionList(ListCreateAPIView): @cached_property def worker(self): - worker = get_object_or_404( - Worker.objects.select_related("repository"), - pk=self.kwargs["pk"] - ) + worker = get_object_or_404(Worker, pk=self.kwargs["pk"]) if self.request.method in permissions.SAFE_METHODS and not worker.is_executable(self.request.user): raise PermissionDenied(detail="You do not have an execution access to this worker.") if ( @@ -959,17 +937,14 @@ class WorkerVersionList(ListCreateAPIView): def get_queryset(self): filters = Q() if self.simple_mode: - # Limit output to versions with tags or master/main branches - filters = ( - Q(revision__refs__type=GitRefType.Tag) - | Q(revision__refs__type=GitRefType.Branch, revision__refs__name__in=["master", "main"]) - ) + # Limit output to versions with tags + filters = Q(tag__isnull=False) return self.worker.versions \ .using("default") \ .filter(filters) \ - .prefetch_related("revision__repo", "revision__refs", "worker__type") \ + .select_related("worker__type") \ .distinct() \ - .order_by("-revision__created", "-created") + .order_by("-created") @extend_schema_view( @@ -998,20 +973,17 @@ class CorpusWorkerVersionList(CorpusACLMixin, ListAPIView): self.corpus.worker_version_cache .select_related( "worker_version__worker__type", - "worker_version__worker__repository", - "worker_version__revision__repo", "model_version__model", "worker_configuration", ) .order_by( "worker_version__worker__name", - "worker_version__revision__hash", "model_version__model__name", "worker_configuration__name", "id", ) .prefetch_related( - "worker_version__revision__refs", + "worker_version", ) ) @@ -1048,18 +1020,10 @@ class CorpusWorkerRunList(ListAPIView): WorkerRun.objects.select_related("process__corpus") .select_related( "version__worker__type", - "version__worker__repository", - "version__revision__repo", "configuration", "model_version__model", ) - .prefetch_related( - Prefetch( - "version__revision__refs", - queryset=GitRef.objects.select_related("repository") - ), - "process__tasks", - ) + .prefetch_related("process__tasks") .filter(Q(process__corpus_id=self.corpus.id) | Q(process__creator_id=self.request.user.id, process__mode=ProcessMode.Local), has_results=True) .annotate(process_element_count=Count("process__elements")) .order_by("summary") @@ -1137,7 +1101,7 @@ class WorkerRetrieve(RetrieveUpdateAPIView): queryset = Worker.objects.none() def get_queryset(self): - return Worker.objects.executable(self.request.user).select_related("repository", "type") + return Worker.objects.executable(self.request.user).select_related("type") def check_object_permissions(self, request, worker): if self.request.method not in permissions.SAFE_METHODS and not worker.is_editable(self.request.user): @@ -1187,10 +1151,7 @@ class WorkerConfigurationList(ListCreateAPIView): @cached_property def worker(self): - worker = get_object_or_404( - Worker.objects.select_related("repository"), - pk=self.kwargs["pk"] - ) + worker = get_object_or_404(Worker, pk=self.kwargs["pk"]) if self.request.method in permissions.SAFE_METHODS and not worker.is_readable(self.request.user): raise PermissionDenied(detail="You do not have a contributor access to this worker.") if self.request.method not in permissions.SAFE_METHODS and not worker.is_executable(self.request.user): @@ -1242,7 +1203,7 @@ class WorkerConfigurationRetrieve(RetrieveUpdateAPIView): serializer_class = WorkerConfigurationSerializer def get_queryset(self): - return WorkerConfiguration.objects.select_related("worker__repository") + return WorkerConfiguration.objects.select_related("worker") def check_object_permissions(self, request, obj): if request.method in permissions.SAFE_METHODS: @@ -1294,15 +1255,9 @@ class WorkerRunList(ProcessACLMixin, ListCreateAPIView): def get_queryset(self): return self.process.worker_runs \ .select_related( - "version__worker__repository", "version__worker__type", - "version__revision__repo", "model_version__model", ) \ - .prefetch_related(Prefetch( - "version__revision__refs", - queryset=GitRef.objects.select_related("repository") - )) \ .order_by("id") def get_serializer_context(self): @@ -1380,16 +1335,10 @@ class UserWorkerRunList(ProcessACLMixin, ListAPIView): return self.local_process.worker_runs \ .using("default") \ .select_related( - "version__worker__repository", "version__worker__type", - "version__revision__repo", "configuration", "model_version__model", ) \ - .prefetch_related(Prefetch( - "version__revision__refs", - queryset=GitRef.objects.select_related("repository") - )) \ .order_by("-created") @@ -1490,7 +1439,6 @@ class WorkerRunDetails(ProcessACLMixin, RetrieveUpdateDestroyAPIView): queryset .select_related( "version__worker__type", - "version__revision__repo", "configuration", "model_version__model", "process__element__corpus", @@ -1499,10 +1447,6 @@ class WorkerRunDetails(ProcessACLMixin, RetrieveUpdateDestroyAPIView): "process__folder_type", "process__element_type", ) - .prefetch_related(Prefetch( - "version__revision__refs", - queryset=GitRef.objects.select_related("repository") - )) ) return queryset @@ -2242,37 +2186,6 @@ class SelectProcessFailures(ProcessACLMixin, CreateAPIView): ) -@extend_schema_view( - post=extend_schema( - responses={201: WorkerVersionSerializer}, - tags=["process"], - ) -) -class CreateDockerWorkerVersion(CreateAPIView): - """ - Create a worker version tied to a remote docker image. The worker version is directly tagged as available. - - Causes an HTTP 400 error if the worker version already exists, unless a new Git reference has been - added to the existing worker version. - - Cannot be used with Ponos task or agent authentication. Requires the `CreateDockerWorkerVersion` scope. - """ - permission_classes = (IsVerified, ) - serializer_class = DockerWorkerVersionSerializer - # Only user accounts can call that endpoint - authentication_classes = (SessionAuthentication, TokenAuthentication) - scopes = (Scope.CreateDockerWorkerVersion,) - - def create(self, request, *args, **kwargs): - serializer = self.get_serializer(data=request.data) - serializer.is_valid(raise_exception=True) - self.perform_create(serializer) - return Response( - status=status.HTTP_201_CREATED, - data=WorkerVersionSerializer(serializer.instance, context={"request": self.request}).data, - ) - - @extend_schema_view( post=extend_schema( operation_id="CreateProcessFailures", diff --git a/arkindex/process/builder.py b/arkindex/process/builder.py index ee650b0e67..ce03ec5e0f 100644 --- a/arkindex/process/builder.py +++ b/arkindex/process/builder.py @@ -41,7 +41,7 @@ class ProcessBuilder: queryset=( WorkerRun.objects .using("default") - .select_related("version__worker__repository", "model_version__model") + .select_related("version__worker", "model_version__model") ), ) ) diff --git a/arkindex/process/managers.py b/arkindex/process/managers.py index 5685e1567c..44e89ce0b2 100644 --- a/arkindex/process/managers.py +++ b/arkindex/process/managers.py @@ -162,8 +162,7 @@ class WorkerVersionManager(Manager): from arkindex.process.models import WorkerVersionState version = ( self - .select_related("worker", "revision") - .prefetch_related("revision__refs") + .select_related("worker") .get(docker_image_iid=docker_image_iid) ) if version.state != WorkerVersionState.Available: @@ -192,7 +191,7 @@ class WorkerVersionManager(Manager): return ( self # Required by WorkerRun.build_summary - .select_related("worker", "revision") + .select_related("worker") .get(id=settings.IMPORTS_WORKER_VERSION) ) diff --git a/arkindex/process/migrations/0001_initial.py b/arkindex/process/migrations/0001_initial.py index 2b708d227a..f575874c99 100644 --- a/arkindex/process/migrations/0001_initial.py +++ b/arkindex/process/migrations/0001_initial.py @@ -6,12 +6,18 @@ import django.core.validators import django.db.models.deletion import enumfields.fields from django.db import migrations, models +from enumfields import Enum import arkindex.process.models import arkindex.project.aws import arkindex.project.fields +class GitRefType(Enum): + Branch = "branch" + Tag = "tag" + + class Migration(migrations.Migration): initial = True @@ -47,7 +53,7 @@ class Migration(migrations.Migration): name="GitRef", fields=[ ("id", models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), - ("type", enumfields.fields.EnumField(enum=arkindex.process.models.GitRefType, max_length=10)), + ("type", enumfields.fields.EnumField(enum=GitRefType, max_length=10)), ("name", models.CharField(max_length=250)), ], ), diff --git a/arkindex/process/migrations/0040_worker_repository_url_workerversion_revision_url_and_more.py b/arkindex/process/migrations/0040_worker_repository_url_workerversion_revision_url_and_more.py index 6b6d09d77d..bbaed0378b 100644 --- a/arkindex/process/migrations/0040_worker_repository_url_workerversion_revision_url_and_more.py +++ b/arkindex/process/migrations/0040_worker_repository_url_workerversion_revision_url_and_more.py @@ -3,11 +3,16 @@ from django.db import migrations, models from django.db.models import CharField, F, OuterRef, Subquery, Value from django.db.models.functions import Concat +from enumfields import Enum -from arkindex.process.models import GitRefType from arkindex.project.tools import RTrimChr +class GitRefType(Enum): + Branch = "branch" + Tag = "tag" + + def update_git_refs(apps, schema): Worker = apps.get_model("process", "Worker") WorkerVersion = apps.get_model("process", "WorkerVersion") @@ -24,6 +29,8 @@ def update_git_refs(apps, schema): revision_url=Subquery( WorkerVersion.objects .filter(pk=OuterRef("pk")) + .exclude(worker__repository_id=None) + .exclude(revision_id=None) .annotate( rev_url=Concat( RTrimChr("worker__repository__url", Value("/")), @@ -38,7 +45,7 @@ def update_git_refs(apps, schema): WorkerVersion.objects .filter( pk=OuterRef("pk"), - revision__refs__type=GitRefType.Tag, + revision__refs__type=GitRefType.Tag.value, ) .order_by("-revision__refs__name") [:1] diff --git a/arkindex/process/migrations/0041_drop_old_git_references.py b/arkindex/process/migrations/0041_drop_old_git_references.py new file mode 100644 index 0000000000..6ae6567614 --- /dev/null +++ b/arkindex/process/migrations/0041_drop_old_git_references.py @@ -0,0 +1,87 @@ +# Generated by Django 5.0.6 on 2024-08-05 14:14 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("documents", "0012_alter_transcriptionentity_id"), + ("process", "0040_worker_repository_url_workerversion_revision_url_and_more"), + ] + + operations = [ + migrations.AlterUniqueTogether( + name="gitref", + unique_together=None, + ), + migrations.AlterUniqueTogether( + name="revision", + unique_together=None, + ), + migrations.RemoveConstraint( + model_name="worker", + name="workerversion_unique_slug_per_repo", + ), + migrations.RemoveConstraint( + model_name="worker", + name="workerversion_unique_slug_local", + ), + migrations.RemoveConstraint( + model_name="workerversion", + name="workerversion_revision_xor_version", + ), + migrations.RemoveConstraint( + model_name="workerversion", + name="workerversion_unique_revision", + ), + migrations.AddConstraint( + model_name="worker", + constraint=models.UniqueConstraint(condition=models.Q(("repository_url__isnull", False)), fields=("slug", "repository_url"), name="workerversion_unique_slug_per_repository_url"), + ), + migrations.AddConstraint( + model_name="worker", + constraint=models.UniqueConstraint(models.F("slug"), condition=models.Q(("repository_url__isnull", True)), name="workerversion_unique_slug_local"), + ), + migrations.AddConstraint( + model_name="workerversion", + constraint=models.CheckConstraint(check=models.Q(("revision_url__isnull", True), ("version__isnull", True), _connector="XOR"), name="workerversion_revision_url_xor_version"), + ), + migrations.AddConstraint( + model_name="workerversion", + constraint=models.UniqueConstraint(condition=models.Q(("revision_url__isnull", False)), fields=("worker", "revision_url"), name="workerversion_unique_revision_url"), + ), + migrations.RemoveField( + model_name="workerversion", + name="revision", + ), + migrations.RemoveField( + model_name="gitref", + name="repository", + ), + migrations.RemoveField( + model_name="gitref", + name="revision", + ), + migrations.RemoveField( + model_name="repository", + name="git_ref_revisions", + ), + migrations.RemoveField( + model_name="worker", + name="repository", + ), + migrations.RemoveField( + model_name="revision", + name="repo", + ), + migrations.DeleteModel( + name="GitRef", + ), + migrations.DeleteModel( + name="Repository", + ), + migrations.DeleteModel( + name="Revision", + ), + ] diff --git a/arkindex/process/models.py b/arkindex/process/models.py index 379de8af11..abece7478f 100644 --- a/arkindex/process/models.py +++ b/arkindex/process/models.py @@ -514,95 +514,12 @@ class DataFile(S3FileMixin, models.Model): self.save() -class Repository(models.Model): - id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) - url = models.URLField() - git_ref_revisions = models.ManyToManyField("process.Revision", through="process.GitRef") - memberships = GenericRelation("users.Right", "content_id") - - class Meta: - verbose_name_plural = "repositories" - constraints = [ - models.UniqueConstraint( - "url", - name="unique_repository_url", - ) - ] - - def __str__(self): - return f"{self.url}" - - def is_executable(self, user) -> bool: - """ - Whether a user can execute any worker within this repository. - - When a user cannot execute all workers of this repository, some workers may still have - some individual rights assigned to them; see Worker.is_executable. - """ - if user.is_anonymous or getattr(user, "is_agent", False): - return False - - # Allow admins to execute anything - if user.is_admin: - return True - - from arkindex.users.utils import get_max_level - level = get_max_level(user, self) - - # Otherwise, users will need contributor access to the repository - return level is not None and level >= Role.Contributor.value - - -class GitRefType(Enum): - Branch = "branch" - Tag = "tag" - - -class GitRef(models.Model): - id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) - type = EnumField(GitRefType) - name = models.CharField(max_length=250) - repository = models.ForeignKey("process.Repository", on_delete=models.CASCADE, related_name="refs") - revision = models.ForeignKey("process.Revision", on_delete=models.CASCADE, related_name="refs") - - class Meta: - unique_together = (("name", "repository"), ) - - -class Revision(IndexableModel): - id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) - repo = models.ForeignKey("process.Repository", on_delete=models.CASCADE, related_name="revisions") - hash = models.CharField(max_length=50) - message = models.TextField() - author = models.CharField(max_length=50) - - class Meta: - unique_together = (("repo", "hash"), ) - - @property - def commit_url(self): - return "{}/commit/{}".format(self.repo.url.rstrip("/"), self.hash) - - def __str__(self): - message = f' "{self.message.splitlines()[0]}"' if self.message else "" - return f"{self.hash[:8]}{message} by {self.author}" - - class Worker(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) name = models.CharField(max_length=100) slug = models.CharField(max_length=100) type = models.ForeignKey("process.WorkerType", on_delete=models.PROTECT, related_name="type") description = models.TextField(default="", blank=True) - # Repository can be left blank for a custom worker. - # Its versions will not be created automatically from Git nor be linked to a revision. - repository = models.ForeignKey( - "process.Repository", - on_delete=models.CASCADE, - related_name="workers", - null=True, - blank=True, - ) memberships = GenericRelation("users.Right", "content_id") # Allow any authentified user to see and execute this worker @@ -617,14 +534,14 @@ class Worker(models.Model): class Meta: constraints = [ models.UniqueConstraint( - fields=["slug", "repository"], - name="workerversion_unique_slug_per_repo", - condition=Q(repository__isnull=False), + fields=["slug", "repository_url"], + name="workerversion_unique_slug_per_repository_url", + condition=Q(repository_url__isnull=False), ), models.UniqueConstraint( "slug", name="workerversion_unique_slug_local", - condition=Q(repository__isnull=True), + condition=Q(repository_url__isnull=True), ), ] @@ -739,13 +656,6 @@ class FeatureUsage(Enum): class WorkerVersion(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) worker = models.ForeignKey("process.Worker", on_delete=models.CASCADE, related_name="versions") - revision = models.ForeignKey( - "process.Revision", - on_delete=models.CASCADE, - related_name="versions", - null=True, - blank=True, - ) version = models.PositiveIntegerField( validators=[MinValueValidator(1)], null=True, @@ -781,19 +691,18 @@ class WorkerVersion(models.Model): check=~models.Q(state=WorkerVersionState.Available) | ~Q(docker_image_iid=None), name="workerversion_available_requires_docker_image", ), - # Require exactly one of revision or version is set models.CheckConstraint( - check=Q(revision__isnull=True) ^ Q(version__isnull=True), - name="workerversion_revision_xor_version", + check=Q(revision_url__isnull=True) ^ Q(version__isnull=True), + name="workerversion_revision_url_xor_version", ), models.CheckConstraint( check=models.Q(configuration__typeof="object"), name="worker_version_configuration_objects", ), models.UniqueConstraint( - fields=["worker", "revision"], - name="workerversion_unique_revision", - condition=Q(revision__isnull=False), + fields=["worker", "revision_url"], + name="workerversion_unique_revision_url", + condition=Q(revision_url__isnull=False), ), models.UniqueConstraint( fields=["worker", "version"], @@ -808,9 +717,9 @@ class WorkerVersion(models.Model): ] def __str__(self): - if self.revision is None: + if self.revision_url is None: return f"{self.worker} for version {self.version}" - return f"{self.worker} for revision {self.revision}" + return f"{self.worker} for revision {self.revision_url}" @property def slug(self): @@ -1015,12 +924,12 @@ class WorkerRun(models.Model): summary_text = f"Worker {self.version.worker.name} @ " if self.version.tag is not None: summary_text += f"{self.version.tag} " - if self.version.revision is not None: + if self.version.revision_url is not None: summary_text += f"({self.version.truncated_id})" else: summary_text += f"(version {self.version.version})" else: - if self.version.revision is not None: + if self.version.revision_url is not None: summary_text += self.version.truncated_id else: summary_text += f"version {self.version.version}" diff --git a/arkindex/process/serializers/git.py b/arkindex/process/serializers/git.py deleted file mode 100644 index cb59c9eae3..0000000000 --- a/arkindex/process/serializers/git.py +++ /dev/null @@ -1,39 +0,0 @@ -from rest_framework import serializers - -from arkindex.process.models import GitRef, GitRefType, Revision -from arkindex.project.serializer_fields import EnumField - - -class GitRefSerializer(serializers.ModelSerializer): - """ - Serialize a git reference for a repository - """ - type = EnumField(GitRefType) - - class Meta: - model = GitRef - fields = ( - "id", - "name", - "type", - ) - - -class RevisionWithRefsSerializer(serializers.ModelSerializer): - """ - Serialize a repository revision with its associated references - """ - refs = GitRefSerializer(many=True, read_only=True) - commit_url = serializers.URLField(read_only=True) - - class Meta: - model = Revision - fields = ( - "id", - "hash", - "author", - "message", - "created", - "commit_url", - "refs", - ) diff --git a/arkindex/process/serializers/worker_runs.py b/arkindex/process/serializers/worker_runs.py index dcef111fcb..e77cfbcff5 100644 --- a/arkindex/process/serializers/worker_runs.py +++ b/arkindex/process/serializers/worker_runs.py @@ -1,14 +1,12 @@ from collections import defaultdict from textwrap import dedent -from django.db.models import Prefetch from rest_framework import serializers from rest_framework.exceptions import ValidationError from arkindex.documents.serializers.elements import ElementTinySerializer from arkindex.process.models import ( FeatureUsage, - GitRef, Process, ProcessMode, WorkerConfiguration, @@ -42,18 +40,8 @@ class WorkerRunSerializer(serializers.ModelSerializer): queryset=( WorkerVersion .objects - .select_related( - # Used by the WorkerVersionSerializer - "worker__type", - "revision__repo", - ) - .prefetch_related( - # Used by the WorkerVersionSerializer - Prefetch( - "revision__refs", - queryset=GitRef.objects.select_related("repository") - ) - ) + # Used by the WorkerVersionSerializer + .select_related("worker__type") ), help_text="UUID of the WorkerVersion for this WorkerRun. " "Only WorkerVersions in an `available` state and on non-archived workers may be set. " @@ -229,8 +217,8 @@ class UserWorkerRunSerializer(serializers.ModelSerializer): help_text=dedent(""" ID of a worker version to create the worker run from. - This worker version must not have a Git revision, and its worker must not be linked to a Git repository - and must not be archived. + This worker version must not have a revision URL, its worker must not be linked to a repository URL + nor be archived. You must have **contributor** access to this worker. """), ) @@ -263,9 +251,9 @@ class UserWorkerRunSerializer(serializers.ModelSerializer): raise ValidationError(detail="You do not have contributor access to this worker.") # Check that the version doesn't have a revision, and the related worker is not linked to a repository - if worker_version.revision_id: - raise ValidationError(detail="The worker version used to create a local worker run must not have a revision set.") - if worker_version.worker.repository_id: + if worker_version.revision_url: + raise ValidationError(detail="The worker version used to create a local worker run must not have a revision URL set.") + if worker_version.worker.repository_url: raise ValidationError(detail="The worker used to create a local worker run must not be linked to a repository.") if worker_version.worker.archived: diff --git a/arkindex/process/serializers/workers.py b/arkindex/process/serializers/workers.py index a0f7a348c3..ace723d780 100644 --- a/arkindex/process/serializers/workers.py +++ b/arkindex/process/serializers/workers.py @@ -12,10 +12,7 @@ from arkindex.ponos.models import Task from arkindex.process.models import ( CorpusWorkerVersion, FeatureUsage, - GitRef, Process, - Repository, - Revision, Worker, WorkerActivity, WorkerActivityState, @@ -24,7 +21,6 @@ from arkindex.process.models import ( WorkerVersion, WorkerVersionState, ) -from arkindex.process.serializers.git import GitRefSerializer, RevisionWithRefsSerializer from arkindex.process.utils import hash_object from arkindex.project.serializer_fields import ArchivedField, EnumField from arkindex.training.models import Model @@ -55,8 +51,8 @@ class WorkerSerializer(WorkerLightSerializer): archived = ArchivedField(required=False) class Meta(WorkerLightSerializer.Meta): - fields = ("id", "name", "description", "type", "slug", "repository_id", "repository_url", "archived") - read_only_fields = ("id", "repository_id") + fields = ("id", "name", "description", "type", "slug", "repository_url", "archived") + read_only_fields = ("id",) extra_kwargs = { "description": { "style": {"base_template": "textarea.html"}, @@ -65,8 +61,8 @@ class WorkerSerializer(WorkerLightSerializer): validators = [ serializers.UniqueTogetherValidator( queryset=Worker.objects.all(), - fields=["repository_id", "slug"], - message="A worker with the same repository and slug already exists.", + fields=["repository_url", "slug"], + message="A worker with the same repository URL and slug already exists.", ), ] @@ -84,7 +80,7 @@ class WorkerCreateSerializer(WorkerSerializer): archived = ArchivedField(read_only=True) class Meta(WorkerSerializer.Meta): - # Remove the validator for unique slugs/repos since we do custom handling + # Remove the validator for unique slugs/repo URL since we can return an existing worker validators = [] def create(self, validated_data): @@ -93,16 +89,22 @@ class WorkerCreateSerializer(WorkerSerializer): """ request = self.context["request"] with transaction.atomic(using="default"): - # First ensure no worker exists with the given slug and no repository + # First check no worker exists with the given slug and repository URL existing_worker = ( Worker.objects .using("default") - .filter(repository_id=None, slug=validated_data["slug"]) + .filter( + repository_url=validated_data["repository_url"], + slug=validated_data["slug"], + ) .first() ) if existing_worker: if not existing_worker.is_executable(user=request.user): - raise ValidationError({"slug": ["You cannot use this value."]}) + raise ValidationError({ + "repository_url": ["You cannot use this value."], + "slug": ["You cannot use this value."], + }) raise ExistingWorkerException(existing_worker) # Get or create the worker and its type @@ -232,7 +234,6 @@ class WorkerVersionSerializer(serializers.ModelSerializer): # State defaults to created when instantiating a WorkerVersion state = EnumField(WorkerVersionState, required=False) worker = WorkerLightSerializer(read_only=True) - revision = RevisionWithRefsSerializer(required=False, read_only=True, allow_null=True) revision_url = serializers.URLField(required=False, read_only=True, allow_null=True) gpu_usage = EnumField(FeatureUsage, required=False, default=FeatureUsage.Disabled) model_usage = EnumField(FeatureUsage, required=False, default=FeatureUsage.Disabled) @@ -246,7 +247,6 @@ class WorkerVersionSerializer(serializers.ModelSerializer): fields = ( "id", "configuration", - "revision", "revision_url", "version", "docker_image_iid", @@ -257,11 +257,7 @@ class WorkerVersionSerializer(serializers.ModelSerializer): "created", "tag", ) - read_only_fields = ("revision", "revision_url", "version") - # Avoid loading all revisions and all Ponos artifacts when opening this endpoint in a browser - extra_kwargs = { - "revision": {"style": {"base_template": "input.html"}}, - } + read_only_fields = ("revision_url", "version") def validate_tag(self, tag): worker = self.instance.worker if self.instance else self.context["worker"] @@ -334,8 +330,9 @@ class WorkerVersionCreateSerializer(WorkerVersionSerializer): raise ValidationError(errors) # Define a version number - last_version = worker.versions.using("default").aggregate(last_version=Max("version"))["last_version"] - data["version"] = last_version + 1 if last_version else 1 + if not revision_url: + last_version = worker.versions.using("default").aggregate(last_version=Max("version"))["last_version"] + data["version"] = last_version + 1 if last_version else 1 data["worker_id"] = worker.id return data @@ -534,202 +531,3 @@ class WorkerStatisticsSerializer(serializers.Serializer): Format: `[DD ]HH:MM:ss[.uuuuuu]` """), ) - - -class DockerWorkerVersionSerializer(serializers.ModelSerializer): - - repository_url = serializers.CharField( - max_length=100, - help_text="URL of the worker's repository. If the repository does not exist, it will be created." - ) - worker_slug = serializers.CharField( - max_length=100, - help_text=dedent(""" - The slug of the worker to which a new version will be published. - If such a worker does not exist, it will be created. - """), - ) - worker_name = serializers.CharField( - max_length=100, - help_text="The name of the worker to which a new version will be published.", - ) - worker_type = serializers.CharField( - max_length=100, - help_text="The slug of the worker type of the worker to which a new version will be published.", - ) - worker_description = serializers.CharField( - required=False, - allow_null=True, - allow_blank=True, - style={"base_template": "textarea.html"}, - ) - revision_hash = serializers.CharField(max_length=50) - revision_message = serializers.CharField(required=False, default="created from docker image") - revision_author = serializers.CharField(max_length=50, required=False, default="default") - revision_references = GitRefSerializer( - many=True, - required=False, - help_text="Optional list of types and names to create GitRefs", - ) - gpu_usage = EnumField(FeatureUsage, required=False, default=FeatureUsage.Disabled) - model_usage = EnumField(FeatureUsage, required=False, default=FeatureUsage.Disabled) - configuration = serializers.DictField(required=False, default={}) - - class Meta: - model = WorkerVersion - fields = ( - "configuration", - "docker_image_iid", - "gpu_usage", - "model_usage", - # Related fields - "repository_url", - "worker_slug", - "worker_name", - "worker_type", - "worker_description", - "revision_hash", - "revision_message", - "revision_author", - "revision_references", - ) - extra_kwargs = { - # The Docker image tag is required in this endpoint - "docker_image_iid": { - "required": True, - "allow_null": False, - "allow_blank": False, - } - } - - def validate_configuration(self, configuration): - errors = defaultdict(list) - user_configuration = configuration.get("user_configuration") - if not user_configuration: - return configuration - field = serializers.DictField(child=UserConfigurationFieldSerializer()) - try: - field.to_internal_value(user_configuration) - except ValidationError as e: - errors["user_configuration"].append(e.detail) - if errors: - raise ValidationError(errors) - return configuration - - @transaction.atomic - def create(self, validated_data): - """ - Retrieve or create the entire git stack in order to build a - worker version corresponding to a given revision on the repository. - """ - # Retrieve or create the Git repository - repository, created_repo = Repository.objects.using("default").get_or_create( - url=validated_data["repository_url"] - ) - # Grant an admin access to the repository in case it got created - if created_repo: - repository.memberships.create(user=self.context["request"].user, level=Role.Admin.value) - - # Retrieve or create the revision (multiple workers may reference a same revision) - revision, created = ( - Revision - .objects - .using("default") - # The prefetch will only occur for an existing revision - .prefetch_related("refs") - .get_or_create( - repo=repository, - hash=validated_data["revision_hash"], - defaults={ - "message": validated_data["revision_message"], - "author": validated_data["revision_author"], - }, - ) - ) - - if created: - existing_git_refs = set() - else: - existing_git_refs = {(ref.type, ref.name) for ref in revision.refs.all()} - - # Add Git references to the created revision - new_git_refs = { - (ref["type"], ref["name"]) - for ref in validated_data.get("revision_references", []) - } - existing_git_refs - - GitRef.objects.bulk_create( - ( - GitRef(revision=revision, repository=repository, type=ref_type, name=ref_name) - for ref_type, ref_name in new_git_refs - ), - # When a GitRef already exists on the repo, update its revision to the current one. - # If the revision already exists, this could mean that an earlier revision - # could get a ref that it shouldn't have, for example when retrying a CI pipeline. - update_conflicts=True, - update_fields=["revision"], - # With PostgreSQL, Django also requires specifying the fields - # of the unique constraint that will cause a conflict. - # Note that GitRefs are unique per name and repository, but not by type. - # This means that a branch and a tag cannot have the same name, - # or one of the two will be skipped without any error. - unique_fields=["repository", "name"], - ) - - # Retrieve or create the worker type - worker_type, _ = WorkerType.objects.using("default").get_or_create(slug=validated_data["worker_type"], defaults={"display_name": validated_data["worker_type"]}) - - # Retrieve or create the worker - worker, created = repository.workers.using("default").get_or_create( - slug=validated_data["worker_slug"], - repository=repository, - defaults={ - "name": validated_data["worker_name"], - "type_id": worker_type.id, - "description": validated_data.get("worker_description", "") - }, - ) - if worker.archived: - raise ValidationError({"worker_slug": ["This worker is archived."]}) - # Grant an admin access to the worker if it was created - if created: - worker.memberships.create(user=self.context["request"].user, level=Role.Admin.value) - # Update the worker if required - if not created: - description = validated_data.get("worker_description") - if worker.name != validated_data["worker_name"] or worker.type_id != worker_type.id or (description is not None and worker.description != description): - worker.name = validated_data["worker_name"] - worker.type_id = worker_type.id - if description is not None: - worker.description = description - worker.save() - - # Finally, create the worker version and mark it as available - # If we are about to return an existing worker version, fetch the required data for the response - version, created = ( - WorkerVersion - .objects - .using("default") - .select_related("worker__type", "worker__repository", "revision__repo") - .prefetch_related("revision__refs") - .get_or_create( - revision=revision, - worker=worker, - defaults={ - "configuration": validated_data["configuration"], - "docker_image_iid": validated_data["docker_image_iid"], - "gpu_usage": validated_data["gpu_usage"], - "model_usage": validated_data["model_usage"], - "state": WorkerVersionState.Available, - }, - ) - ) - - # Abort in case a version already exists with that revision and worker, - # unless this API call has caused some new GitRefs to be added on the existing revision. - if not created and not new_git_refs: - raise ValidationError({ - "__all__": ["A worker version already exists on this revision and this worker slug."] - }) - - return version diff --git a/arkindex/process/tests/commands/test_fake_worker_version.py b/arkindex/process/tests/commands/test_fake_worker_version.py index aa2559af5f..d5079e314e 100644 --- a/arkindex/process/tests/commands/test_fake_worker_version.py +++ b/arkindex/process/tests/commands/test_fake_worker_version.py @@ -1,7 +1,7 @@ from django.core.management import call_command from django.core.management.base import CommandError -from arkindex.process.models import Repository, Worker, WorkerType, WorkerVersion, WorkerVersionState +from arkindex.process.models import Worker, WorkerType, WorkerVersion, WorkerVersionState from arkindex.project.tests import FixtureTestCase @@ -27,7 +27,6 @@ class TestFakeWorker(FixtureTestCase): self.assertEqual(worker.slug, slug) self.assertEqual(worker.type.slug, "classifier") - self.assertIsNone(version.revision_id) self.assertEqual(version.worker, worker) self.assertEqual(version.state, WorkerVersionState.Created) @@ -55,26 +54,10 @@ class TestFakeWorker(FixtureTestCase): new_versions_id = list(new_versions.values_list("id", flat=True).distinct()) self.assertEqual(old_versions_id, new_versions_id) - def test_repository_already_exists(self): - slug = "myslug" - name = "My name" - - with self.assertNumQueries(11): - call_command( - "fake_worker_version", - slug=slug, - name=name, - ) - - version = WorkerVersion.objects.get(worker__slug=slug) - self.assertIsNone(version.worker.repository_id) - def test_worker_already_exists(self): slug = "myslug" name = "My name" - repo = Repository.objects.create(url="http://test") - worker_type = WorkerType.objects.create( slug="classifier" ) @@ -83,7 +66,6 @@ class TestFakeWorker(FixtureTestCase): name=name, slug=slug, type=worker_type, - repository=repo ) with self.assertNumQueries(5): @@ -94,5 +76,4 @@ class TestFakeWorker(FixtureTestCase): ) version = WorkerVersion.objects.get(worker__slug=slug) - self.assertEqual(version.worker.repository.id, repo.id) self.assertEqual(version.worker.id, worker.id) diff --git a/arkindex/process/tests/test_corpus_worker_runs.py b/arkindex/process/tests/test_corpus_worker_runs.py index fa5d1f8184..4f35934cfb 100644 --- a/arkindex/process/tests/test_corpus_worker_runs.py +++ b/arkindex/process/tests/test_corpus_worker_runs.py @@ -125,7 +125,6 @@ class TestCorpusWorkerRuns(FixtureAPITestCase): "gpu_usage": "disabled", "id": str(self.local_worker_version.id), "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "state": "created", "version": 1, @@ -147,7 +146,6 @@ class TestCorpusWorkerRuns(FixtureAPITestCase): "docker_image_iid": self.dla_worker_version.docker_image_iid, "gpu_usage": "disabled", "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "version": 1, "tag": None, diff --git a/arkindex/process/tests/test_create_process.py b/arkindex/process/tests/test_create_process.py index dca1828a3f..8ebe63a0a7 100644 --- a/arkindex/process/tests/test_create_process.py +++ b/arkindex/process/tests/test_create_process.py @@ -671,7 +671,7 @@ class TestCreateProcess(FixtureAPITestCase): A worker version without a revision but with a Docker image should be usable in a process """ custom_version = WorkerVersion.objects.get(worker__slug="custom") - self.assertIsNone(custom_version.revision_id) + self.assertIsNone(custom_version.revision_url) custom_version.docker_image_iid = "alpine:latest" custom_version.state = WorkerVersionState.Available custom_version.save() diff --git a/arkindex/process/tests/test_docker_worker_version.py b/arkindex/process/tests/test_docker_worker_version.py deleted file mode 100644 index 08ea29e1fa..0000000000 --- a/arkindex/process/tests/test_docker_worker_version.py +++ /dev/null @@ -1,885 +0,0 @@ -import uuid -from datetime import datetime, timezone - -from django.urls import reverse -from rest_framework import status - -from arkindex.ponos.models import Farm -from arkindex.process.models import ( - FeatureUsage, - GitRefType, - Process, - ProcessMode, - Repository, - WorkerType, - WorkerVersionState, -) -from arkindex.project.tests import FixtureAPITestCase -from arkindex.training.models import Model -from arkindex.users.models import Role, Scope - - -class TestDockerWorkerVersion(FixtureAPITestCase): - """ - Test endpoint to create a worker version from a docker image - """ - - @classmethod - def setUpTestData(cls): - super().setUpTestData() - cls.repo = Repository.objects.create(url="http://my_repo.fake/workers/worker") - cls.rev = cls.repo.revisions.create( - hash=str(uuid.uuid4()), - message="A revision", - author="Someone", - ) - cls.repo.workers.create( - slug="test_worker", - type=WorkerType.objects.first(), - description="it's a-me a workerio", - name="Workerio" - ) - cls.worker = cls.repo.workers.filter(slug="test_worker").select_related("type").get() - cls.worker.versions.create( - revision=cls.rev, - configuration={}, - docker_image_iid="registry.fake.com/workers/worker:02564", - state=WorkerVersionState.Available - ) - cls.version = cls.worker.versions.select_related("revision").get(revision_id=cls.rev.id) - cls.user.user_scopes.create(scope=Scope.CreateDockerWorkerVersion) - cls.worker_type = WorkerType.objects.create(slug="docker", display_name="Docker") - - def test_create_requires_login(self): - response = self.client.post(reverse("api:version-from-docker")) - self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) - self.assertDictEqual(response.json(), {"detail": "Authentication credentials were not provided."}) - - def test_create_deny_ponos_auth(self): - """ - Ponos task authentication is disabled on that endpoint - """ - process = Process.objects.create( - mode=ProcessMode.Workers, - creator=self.user, - farm=Farm.objects.first(), - corpus=self.corpus, - ) - process.run() - task = process.tasks.get() - response = self.client.post( - reverse("api:version-from-docker"), - HTTP_AUTHORIZATION=f"Ponos {task.token}", - ) - self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) - self.assertDictEqual(response.json(), {"detail": "Authentication credentials were not provided."}) - - def test_create_requires_verified(self): - self.user.verified_email = False - self.user.save() - self.client.force_login(self.user) - response = self.client.post(reverse("api:version-from-docker")) - self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) - self.assertDictEqual(response.json(), {"detail": "You do not have permission to perform this action."}) - - def test_create_requires_scope(self): - """ - A specific user scope is required to create a worker version from a docker image - """ - self.user.user_scopes.get(scope=Scope.CreateDockerWorkerVersion).delete() - self.client.force_login(self.user) - with self.assertNumQueries(3): - response = self.client.post(reverse("api:version-from-docker")) - self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) - - self.assertDictEqual(response.json(), { - "detail": "You do not have permission to perform this action.", - "missing_scopes": [Scope.CreateDockerWorkerVersion.value], - }) - - def test_create_admin_no_scope(self): - """ - User scope is not required for instance admins - """ - self.assertEqual(self.superuser.user_scopes.count(), 0) - self.client.force_login(self.superuser) - response = self.client.post( - reverse("api:version-from-docker"), - data={ - "configuration": {"test": "A"}, - "docker_image_iid": "a_docker_image", - "repository_url": self.repo.url, - "revision_hash": "new_revision_hash", - "worker_slug": self.worker.slug, - "worker_name": self.worker.name, - "worker_type": self.worker.type.slug, - }, - format="json", - ) - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - - def test_create_required_fields(self): - self.client.force_login(self.user) - with self.assertNumQueries(3): - response = self.client.post(reverse("api:version-from-docker")) - self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) - self.assertDictEqual( - response.json(), - { - "docker_image_iid": ["This field is required."], - "repository_url": ["This field is required."], - "revision_hash": ["This field is required."], - "worker_slug": ["This field is required."], - "worker_name": ["This field is required."], - "worker_type": ["This field is required."], - }, - ) - - def test_create_fields_validation(self): - self.client.force_login(self.user) - with self.assertNumQueries(3): - response = self.client.post( - reverse("api:version-from-docker"), - data={ - "configuration": "str", - "docker_image_iid": [], - "repository_url": [], - "revision_hash": "", - "worker_slug": [], - "worker_name": [], - "worker_type": [], - "worker_description": [], - "revision_message": [], - "revision_author": [], - "revision_references": [{"a": 133}], - "gpu_usage": "AAAAAAAA", - "model_usage": [], - # Only revision can be set using this endpoint - "version": 42, - }, - format="json", - ) - self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) - self.assertDictEqual(response.json(), { - "configuration": ['Expected a dictionary of items but got type "str".'], - "docker_image_iid": ["Not a valid string."], - "gpu_usage": ["Value is not of type FeatureUsage"], - "model_usage": ["Value is not of type FeatureUsage"], - "repository_url": ["Not a valid string."], - "revision_author": ["Not a valid string."], - "revision_hash": ["This field may not be blank."], - "revision_message": ["Not a valid string."], - "revision_references": [{ - "name": ["This field is required."], - "type": ["This field is required."] - }], - "worker_slug": ["Not a valid string."], - "worker_name": ["Not a valid string."], - "worker_type": ["Not a valid string."], - "worker_description": ["Not a valid string."], - }) - - def test_create_duplicated(self): - """ - No worker version can be created with an existing revision hash and worker slug - """ - self.client.force_login(self.user) - with self.assertNumQueries(13): - response = self.client.post( - reverse("api:version-from-docker"), - data={ - "configuration": {}, - "docker_image_iid": "some_docker_image", - "repository_url": self.repo.url, - "revision_hash": self.version.revision.hash, - "worker_slug": self.worker.slug, - "worker_name": self.worker.name, - "worker_type": self.worker.type.slug, - }, - format="json", - ) - self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) - self.assertDictEqual(response.json(), { - "__all__": ["A worker version already exists on this revision and this worker slug."] - }) - - def test_create_archived(self): - self.client.force_login(self.user) - self.worker.archived = datetime.now(timezone.utc) - self.worker.save() - - with self.assertNumQueries(13): - response = self.client.post( - reverse("api:version-from-docker"), - data={ - "configuration": {"test": "A"}, - "docker_image_iid": "a_docker_image", - "repository_url": self.repo.url, - "revision_hash": "new_revision_hash", - "worker_slug": self.worker.slug, - "worker_name": self.worker.name, - "worker_type": self.worker.type.slug, - }, - format="json", - ) - self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) - - self.assertDictEqual(response.json(), { - "worker_slug": ["This worker is archived."], - }) - - def test_create_default_message(self): - """ - A new version can be published with only the required fields - """ - self.client.force_login(self.user) - - with self.assertNumQueries(18): - response = self.client.post( - reverse("api:version-from-docker"), - data={ - "configuration": {"test": "A"}, - "docker_image_iid": "a_docker_image", - "repository_url": self.repo.url, - "revision_hash": "new_revision_hash", - "worker_slug": self.worker.slug, - "worker_name": self.worker.name, - "worker_type": self.worker.type.slug, - }, - format="json", - ) - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - new_revision = self.repo.revisions.get(hash="new_revision_hash") - new_version = new_revision.versions.get() - self.assertEqual(new_version.worker, self.worker) - self.assertDictEqual(response.json(), { - "id": str(new_version.id), - "configuration": {"test": "A"}, - "docker_image_iid": "a_docker_image", - "gpu_usage": FeatureUsage.Disabled.value, - "model_usage": FeatureUsage.Disabled.value, - "revision": { - "id": str(new_revision.id), - "author": "default", - "commit_url": "http://my_repo.fake/workers/worker/commit/new_revision_hash", - "created": new_revision.created.isoformat().replace("+00:00", "Z"), - "hash": "new_revision_hash", - "message": "created from docker image", - "refs": [] - }, - "revision_url": None, - "version": None, - "tag": None, - "created": new_version.created.isoformat().replace("+00:00", "Z"), - "state": "available", - "worker": { - "id": str(self.worker.id), - "name": self.worker.name, - "slug": self.worker.slug, - "type": self.worker.type.slug - } - }) - - def test_create(self): - """ - A new version can be published with the optional values - """ - self.client.force_login(self.user) - - with self.assertNumQueries(19): - response = self.client.post( - reverse("api:version-from-docker"), - data={ - "configuration": {"test": "A"}, - "docker_image_iid": "e" * 512, - "repository_url": self.repo.url, - "revision_hash": "new_revision_hash", - "worker_slug": self.worker.slug, - "worker_name": self.worker.name, - "worker_type": self.worker.type.slug, - "revision_message": "Bruce was very clever", - "revision_author": "Iwan Roberts", - "revision_references": [ - {"type": "branch", "name": "master"}, - {"type": "tag", "name": "2.0"}, - ], - "gpu_usage": FeatureUsage.Required.value, - "model_usage": FeatureUsage.Supported.value, - }, - format="json", - ) - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - new_revision = self.repo.revisions.get(hash="new_revision_hash") - refs = list(new_revision.refs.all()) - self.assertDictEqual( - {ref.type: ref.name for ref in refs}, - {GitRefType.Branch: "master", GitRefType.Tag: "2.0"}, - ) - new_version = new_revision.versions.get() - self.assertDictEqual(response.json(), { - "id": str(new_version.id), - "configuration": {"test": "A"}, - "docker_image_iid": "e" * 512, - "gpu_usage": FeatureUsage.Required.value, - "model_usage": FeatureUsage.Supported.value, - "revision": { - "id": str(new_revision.id), - "author": "Iwan Roberts", - "commit_url": "http://my_repo.fake/workers/worker/commit/new_revision_hash", - "created": new_revision.created.isoformat().replace("+00:00", "Z"), - "hash": "new_revision_hash", - "message": "Bruce was very clever", - "refs": [ - {"id": str(ref.id), "name": ref.name, "type": ref.type.value} - for ref in refs - ], - }, - "revision_url": None, - "version": None, - "tag": None, - "created": new_version.created.isoformat().replace("+00:00", "Z"), - "state": "available", - "worker": { - "id": str(self.worker.id), - "name": self.worker.name, - "slug": self.worker.slug, - "type": self.worker.type.slug - } - }) - # Existing repository memberships are not updated - self.assertFalse(self.repo.memberships.exists()) - - def test_create_update_worker(self): - """ - Creating a new worker version can update the worker, and create a new worker type - """ - self.client.force_login(self.user) - - with self.assertNumQueries(23): - response = self.client.post( - reverse("api:version-from-docker"), - data={ - "configuration": {"test": "A"}, - "docker_image_iid": "e" * 512, - "repository_url": self.repo.url, - "revision_hash": "new_revision_hash", - "worker_slug": self.worker.slug, - "worker_name": "A New Name", - "worker_type": "new_worker_type", - "worker_description": "C'est un petit val qui mousse de rayons.", - "revision_message": "Bruce was very clever", - "revision_author": "Iwan Roberts", - "revision_references": [ - {"type": "branch", "name": "master"}, - {"type": "tag", "name": "2.0"}, - ], - "gpu_usage": FeatureUsage.Required.value, - "model_usage": FeatureUsage.Supported.value, - }, - format="json", - ) - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - new_worker_type = WorkerType.objects.get(slug="new_worker_type") - new_revision = self.repo.revisions.get(hash="new_revision_hash") - self.worker.refresh_from_db() - self.assertEqual(self.worker.description, "C'est un petit val qui mousse de rayons.") - refs = list(new_revision.refs.all()) - self.assertDictEqual( - {ref.type: ref.name for ref in refs}, - {GitRefType.Branch: "master", GitRefType.Tag: "2.0"}, - ) - new_version = new_revision.versions.get() - self.assertDictEqual(response.json(), { - "id": str(new_version.id), - "configuration": {"test": "A"}, - "docker_image_iid": "e" * 512, - "gpu_usage": FeatureUsage.Required.value, - "model_usage": FeatureUsage.Supported.value, - "revision": { - "id": str(new_revision.id), - "author": "Iwan Roberts", - "commit_url": "http://my_repo.fake/workers/worker/commit/new_revision_hash", - "created": new_revision.created.isoformat().replace("+00:00", "Z"), - "hash": "new_revision_hash", - "message": "Bruce was very clever", - "refs": [ - {"id": str(ref.id), "name": ref.name, "type": ref.type.value} - for ref in refs - ], - }, - "revision_url": None, - "version": None, - "tag": None, - "created": new_version.created.isoformat().replace("+00:00", "Z"), - "state": "available", - "worker": { - "id": str(self.worker.id), - "name": "A New Name", - "slug": self.worker.slug, - "type": new_worker_type.slug - } - }) - # Existing repository memberships are not updated - self.assertFalse(self.repo.memberships.exists()) - - def test_create_update_git_ref(self): - """ - Existing GitRefs on the repository on a different revision - are updated to the new revision - """ - self.assertFalse(self.repo.refs.exists()) - branch_ref = self.repo.refs.create( - revision=self.rev, - type=GitRefType.Branch, - name="master", - ) - tag_ref = self.repo.refs.create( - revision=self.rev, - type=GitRefType.Tag, - name="2.0", - ) - - self.client.force_login(self.user) - with self.assertNumQueries(19): - response = self.client.post( - reverse("api:version-from-docker"), - data={ - "configuration": {"test": "A"}, - "docker_image_iid": "a_docker_image", - "repository_url": self.repo.url, - "revision_hash": "new_revision_hash", - "worker_slug": self.worker.slug, - "worker_name": self.worker.name, - "worker_type": self.worker.type.slug, - "revision_message": "Bruce was very clever", - "revision_author": "Iwan Roberts", - "revision_references": [ - {"type": "branch", "name": "master"}, - {"type": "tag", "name": "2.0"}, - ], - "gpu_usage": FeatureUsage.Required.value, - "model_usage": FeatureUsage.Required.value, - }, - format="json", - ) - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - - new_revision = self.repo.revisions.get(hash="new_revision_hash") - - branch_ref.refresh_from_db() - tag_ref.refresh_from_db() - self.assertEqual(branch_ref.revision, new_revision) - self.assertEqual(tag_ref.revision, new_revision) - - # No new refs were created - self.assertEqual(self.repo.refs.count(), 2) - - data = response.json() - # GitRefs are not sorted in the API output, so we have to assert separately - refs_data = data["revision"].pop("refs") - self.assertCountEqual(refs_data, [ - { - "id": str(tag_ref.id), - "name": "2.0", - "type": "tag", - }, - { - "id": str(branch_ref.id), - "name": "master", - "type": "branch", - }, - ]) - - new_version = new_revision.versions.get() - self.assertDictEqual(response.json(), { - "id": str(new_version.id), - "configuration": {"test": "A"}, - "docker_image_iid": "a_docker_image", - "gpu_usage": FeatureUsage.Required.value, - "model_usage": FeatureUsage.Required.value, - "revision": { - "id": str(new_revision.id), - "author": "Iwan Roberts", - "commit_url": "http://my_repo.fake/workers/worker/commit/new_revision_hash", - "created": new_revision.created.isoformat().replace("+00:00", "Z"), - "hash": "new_revision_hash", - "message": "Bruce was very clever", - }, - "revision_url": None, - "version": None, - "tag": None, - "created": new_version.created.isoformat().replace("+00:00", "Z"), - "state": "available", - "worker": { - "id": str(self.worker.id), - "name": self.worker.name, - "slug": self.worker.slug, - "type": self.worker.type.slug - } - }) - # Existing repository memberships are not updated - self.assertFalse(self.repo.memberships.exists()) - - def test_create_add_git_ref(self): - """ - If a worker version already exists, the call still succeeds - when it creates a new GitRef - """ - self.client.force_login(self.user) - self.assertFalse(self.version.revision.refs.exists()) - branch_ref = self.version.revision.refs.create( - name="fix-typo", - type=GitRefType.Branch, - repository=self.version.revision.repo, - ) - - with self.assertNumQueries(13): - response = self.client.post( - reverse("api:version-from-docker"), - data={ - "configuration": {}, - "docker_image_iid": "some_docker_image", - "repository_url": self.repo.url, - "revision_hash": self.version.revision.hash, - "worker_slug": self.worker.slug, - "worker_name": self.worker.name, - "worker_type": self.worker.type.slug, - "revision_references": [ - {"type": "tag", "name": "9.9.9.9.9.9"}, - ], - }, - format="json", - ) - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - - tag_ref = self.version.revision.refs.get(type=GitRefType.Tag) - - self.assertDictEqual(response.json(), { - "id": str(self.version.id), - "configuration": {}, - "docker_image_iid": self.version.docker_image_iid, - "gpu_usage": FeatureUsage.Disabled.value, - "model_usage": FeatureUsage.Disabled.value, - "revision": { - "id": str(self.version.revision.id), - "author": "Someone", - "commit_url": f"http://my_repo.fake/workers/worker/commit/{self.version.revision.hash}", - "created": self.version.revision.created.isoformat().replace("+00:00", "Z"), - "hash": self.version.revision.hash, - "message": "A revision", - "refs": [ - { - "id": str(branch_ref.id), - "name": "fix-typo", - "type": "branch", - }, - { - "id": str(tag_ref.id), - "name": "9.9.9.9.9.9", - "type": "tag", - }, - ], - }, - "revision_url": None, - "version": None, - "tag": None, - "created": self.version.created.isoformat().replace("+00:00", "Z"), - "state": "available", - "worker": { - "id": str(self.worker.id), - "name": self.worker.name, - "slug": self.worker.slug, - "type": self.worker.type.slug - } - }) - - def test_create_git_stack(self): - """ - All git references can be created including repository, revision, gitrefs and worker - and worker type - """ - self.worker_type.delete() - self.client.force_login(self.user) - with self.assertNumQueries(32): - response = self.client.post( - reverse("api:version-from-docker"), - data={ - "configuration": {"key": "value"}, - "docker_image_iid": "docker_image_42", - "repository_url": "https://gitlab.test.arkindex.org/project/", - "revision_hash": "deadbeef", - "worker_slug": "new_gen_classifier", - "worker_name": "Classifier New Generation", - "worker_type": "a_new_type", - "revision_references": [ - {"type": "branch", "name": "master"}, - ], - }, - format="json", - ) - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - new_repo = Repository.objects.get(url="https://gitlab.test.arkindex.org/project/") - new_revision = new_repo.revisions.get(hash="deadbeef") - new_ref = new_revision.refs.get() - new_version = new_revision.versions.get() - new_worker_type = new_version.worker.type - self.assertDictEqual(response.json(), { - "id": str(new_version.id), - "configuration": {"key": "value"}, - "docker_image_iid": "docker_image_42", - "gpu_usage": FeatureUsage.Disabled.value, - "model_usage": FeatureUsage.Disabled.value, - "revision": { - "id": str(new_revision.id), - "author": "default", - "commit_url": "https://gitlab.test.arkindex.org/project/commit/deadbeef", - "created": new_revision.created.isoformat().replace("+00:00", "Z"), - "hash": "deadbeef", - "message": "created from docker image", - "refs": [{"id": str(new_ref.id), "name": new_ref.name, "type": new_ref.type.value}], - }, - "state": "available", - "revision_url": None, - "version": None, - "tag": None, - "created": new_version.created.isoformat().replace("+00:00", "Z"), - "worker": { - "id": str(new_version.worker.id), - "name": "Classifier New Generation", - "slug": "new_gen_classifier", - "type": str(new_worker_type), - } - }) - # Check attributes directly from the DB - self.assertEqual(new_repo.url, "https://gitlab.test.arkindex.org/project/") - self.assertEqual(new_revision.author, "default") - self.assertEqual(new_revision.message, "created from docker image") - self.assertEqual(new_revision.repo, new_repo) - self.assertEqual(new_ref.name, "master") - self.assertEqual(new_ref.repository, new_repo) - self.assertEqual(new_version.worker.name, "Classifier New Generation") - self.assertEqual(new_version.worker.slug, "new_gen_classifier") - self.assertEqual(new_version.worker.public, False) - self.assertEqual(new_version.worker.repository, new_repo) - self.assertEqual(new_version.configuration, {"key": "value"}) - self.assertEqual(new_version.docker_image_iid, "docker_image_42") - self.assertEqual(new_version.gpu_usage, FeatureUsage.Disabled) - self.assertEqual(new_version.model_usage, FeatureUsage.Disabled) - self.assertEqual(new_worker_type.slug, "a_new_type") - self.assertEqual(new_worker_type.display_name, "a_new_type") - # User is granted an admin role on the repository - self.assertListEqual(list(new_repo.memberships.values_list("user", "level")), [ - (self.user.id, Role.Admin.value) - ]) - - # Test user configuration - - def test_create_version_valid_user_configuration(self): - test_model = Model.objects.create( - name="Generic model", - public=False, - ) - self.client.force_login(self.user) - response = self.client.post( - reverse("api:version-from-docker"), - data={ - "docker_image_iid": "a_docker_image", - "repository_url": self.repo.url, - "revision_hash": "new_revision_hash", - "worker_slug": self.worker.slug, - "worker_name": self.worker.name, - "worker_type": self.worker.type.slug, - "configuration": { - "user_configuration": { - "demo_integer": {"title": "Demo Integer", "type": "int", "required": True, "default": 1}, - "demo_boolean": {"title": "Demo Boolean", "type": "bool", "required": False, "default": True}, - "demo_dict": {"title": "Demo Dict", "type": "dict", "required": True, "default": {"a": "b", "c": "d"}}, - "demo_choice": {"title": "Decisions", "type": "enum", "required": True, "default": 1, "choices": [1, 2, 3]}, - "demo_list": {"title": "Demo List", "type": "list", "required": True, "subtype": "int", "default": [1, 2, 3, 4]}, - "boolean_list": {"title": "It's a list of booleans", "type": "list", "required": False, "subtype": "bool", "default": [True, False, False]}, - "demo_model": {"title": "Model for training", "type": "model", "required": True}, - "other_model": {"title": "Model the second", "type": "model", "default": str(test_model.id)} - } - }, - }, - format="json", - ) - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - self.assertEqual(response.json()["configuration"], { - "user_configuration": { - "demo_integer": { - "title": "Demo Integer", - "type": "int", - "required": True, - "default": 1 - }, - "demo_boolean": { - "title": "Demo Boolean", - "type": "bool", - "required": False, - "default": True - }, - "demo_dict": { - "title": "Demo Dict", - "type": "dict", - "required": True, - "default": {"a": "b", "c": "d"} - }, - "demo_choice": { - "title": "Decisions", - "type": "enum", - "required": True, - "default": 1, - "choices": [1, 2, 3] - }, - "demo_list": { - "title": "Demo List", - "type": "list", - "subtype": "int", - "required": True, - "default": [1, 2, 3, 4] - }, - "boolean_list": { - "title": "It's a list of booleans", - "type": "list", - "subtype": "bool", - "required": False, - "default": [True, False, False] - }, - "demo_model": { - "title": "Model for training", - "type": "model", - "required": True - }, - "other_model": { - "title": "Model the second", - "type": "model", - "default": str(test_model.id) - } - } - }) - - def test_create_invalid_user_configuration(self): - cases = [ - ( - "non", - ['Expected a dictionary of items but got type "str".'] - ), - ( - {"demo_list": {"title": "Demo List", "type": "list", "required": True, "default": [1, 2, 3, 4]}}, - {"demo_list": { - "subtype": ['The "subtype" field must be set for "list" type properties.'] - }} - ), - ( - {"demo_list": {"title": "Demo List", "type": "list", "required": True, "subtype": "dict", "default": [1, 2, 3, 4]}}, - {"demo_list": { - "subtype": ["Subtype can only be int, float, bool or string."] - }} - ), - ( - {"demo_list": {"title": "Demo List", "type": "list", "required": True, "subtype": "int", "default": [1, 2, "three", 4]}}, - {"demo_list": { - "default": ["All items in the default value must be of type int."] - }} - ), - ( - {"demo_choice": {"title": "Decisions", "type": "enum", "required": True, "default": 1, "choices": "eeee"}}, - {"demo_choice": { - "choices": ['Expected a list of items but got type "str".'] - }} - ), - ( - {"secrets": ["aaaaaa"]}, - {"secrets": {"__all__": ["User configuration field definitions should be of type dict, not list."]}} - ), - ( - {"something": {"title": "some thing", "type": "uh oh", "required": 2}}, - {"something": { - "required": ["Must be a valid boolean."], - "type": ["Value is not of type UserConfigurationFieldType"] - }} - ), - ( - {"something": {"title": "some thing", "type": "int", "required": False, "choices": [1, 2, 3]}}, - {"something": { - "choices": ['The "choices" field can only be set for an "enum" type property.'] - }} - ), - ( - {"demo_integer": {"type": "int", "required": True, "default": 1}}, - {"demo_integer": {"title": ["This field is required."]}} - ), - ( - {"demo_integer": {"title": "an integer", "type": "int", "required": True, "default": 1, "some_key": "oh no"}}, - {"demo_integer": { - "some_key": ["Configurable properties can only be defined using the following keys: title, type, required, default, subtype, choices."] - }} - ), - ( - {"param": {"title": "Model to train", "type": "model", "default": "12341234-1234-1234-1234-123412341234"}}, - {"param": {"default": ["Model 12341234-1234-1234-1234-123412341234 not found."]}} - ) - ] - - self.client.force_login(self.user) - for user_configuration, error in cases: - with self.subTest(user_configuration=user_configuration, error=error): - response = self.client.post( - reverse("api:version-from-docker"), - data={ - "docker_image_iid": "a_docker_image", - "repository_url": self.repo.url, - "revision_hash": "new_revision_hash", - "worker_slug": self.worker.slug, - "worker_name": self.worker.name, - "worker_type": self.worker.type.slug, - "configuration": { - "user_configuration": user_configuration - }, - }, - format="json", - ) - self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) - self.assertEqual(response.json(), { - "configuration": { - "user_configuration": [error] - } - }) - - def test_create_version_invalid_user_configuration_default_value(self): - self.client.force_login(self.user) - cases = [ - ({"type": "int", "default": False}, "int"), - ({"type": "int", "default": True}, "int"), - ({"type": "float", "default": False}, "float"), - ({"type": "float", "default": True}, "float"), - ({"type": "bool", "default": 0}, "bool"), - ({"type": "bool", "default": 1}, "bool"), - ({"type": "string", "default": 1}, "string"), - ({"type": "dict", "default": ["a", "b"]}, "dict"), - ({"type": "model", "default": "gigi hadid"}, "model"), - ({"type": "model", "default": False}, "model"), - ({"type": "list", "subtype": "int", "default": 12}, "list") - ] - for params, expected in cases: - with self.subTest(**params): - response = self.client.post( - reverse("api:version-from-docker"), - data={ - "docker_image_iid": "a_docker_image", - "repository_url": self.repo.url, - "revision_hash": "new_revision_hash", - "worker_slug": self.worker.slug, - "worker_name": self.worker.name, - "worker_type": self.worker.type.slug, - "configuration": { - "user_configuration": { - "param": {"title": "param", **params} - } - }, - }, - format="json", - ) - self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) - self.assertEqual(response.json(), {"configuration": {"user_configuration": [{"param": {"default": [f"This is not a valid value for a field of type {expected}."]}}]}}) diff --git a/arkindex/process/tests/test_user_workerruns.py b/arkindex/process/tests/test_user_workerruns.py index 4a76ae878d..59e377ca51 100644 --- a/arkindex/process/tests/test_user_workerruns.py +++ b/arkindex/process/tests/test_user_workerruns.py @@ -1,4 +1,3 @@ -import uuid from datetime import datetime, timezone from unittest.mock import call, patch @@ -9,7 +8,6 @@ from arkindex.process.models import ( FeatureUsage, Process, ProcessMode, - Repository, WorkerConfiguration, WorkerRun, WorkerVersion, @@ -29,7 +27,6 @@ class TestUserWorkerRuns(FixtureAPITestCase): cls.custom_version = WorkerVersion.objects.get(worker__slug="custom") cls.other_version = WorkerVersion.objects.create( worker=cls.custom_version.worker, - revision=None, version=2, configuration={ "name": "bartimaeus", @@ -100,7 +97,6 @@ class TestUserWorkerRuns(FixtureAPITestCase): "gpu_usage": "disabled", "id": str(self.version_1.id), "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "state": "available", "version": 1, @@ -138,7 +134,6 @@ class TestUserWorkerRuns(FixtureAPITestCase): "gpu_usage": "disabled", "id": str(self.custom_version.id), "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "state": "created", "version": 1, @@ -221,7 +216,6 @@ class TestUserWorkerRuns(FixtureAPITestCase): "gpu_usage": "disabled", "id": str(self.other_version.id), "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "state": "created", "version": 2, @@ -273,14 +267,8 @@ class TestUserWorkerRuns(FixtureAPITestCase): self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(response.json(), {"worker_version_id": ["Worker version aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa does not exist."]}) - def test_create_user_run_wv_has_revision(self): - self.version_1.worker.repository = Repository.objects.create(url="http://nerv.co.jp/eva/") - self.version_1.worker.save() - self.version_1.revision = self.version_1.worker.repository.revisions.create( - hash=str(uuid.uuid4()), - message="A revision", - author="Someone", - ) + def test_create_user_run_wv_has_revision_url(self): + self.version_1.revision_url = "revision_url" self.version_1.version = None self.version_1.save() self.client.force_login(self.user) @@ -290,10 +278,10 @@ class TestUserWorkerRuns(FixtureAPITestCase): data={"worker_version_id": str(self.version_1.id)} ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) - self.assertEqual(response.json(), {"worker_version_id": ["The worker version used to create a local worker run must not have a revision set."]}) + self.assertEqual(response.json(), {"worker_version_id": ["The worker version used to create a local worker run must not have a revision URL set."]}) def test_create_user_run_worker_has_repository(self): - self.version_1.worker.repository = Repository.objects.create(url="http://nerv.co.jp/eva/") + self.version_1.worker.repository_url = "repo_url" self.version_1.worker.save() test_version = self.version_1.worker.versions.create(configuration={}, version=7) self.client.force_login(self.user) @@ -438,7 +426,6 @@ class TestUserWorkerRuns(FixtureAPITestCase): "gpu_usage": "disabled", "id": str(self.other_version.id), "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "state": "created", "version": 2, diff --git a/arkindex/process/tests/test_workerruns.py b/arkindex/process/tests/test_workerruns.py index 47387dac7e..886e09ce5c 100644 --- a/arkindex/process/tests/test_workerruns.py +++ b/arkindex/process/tests/test_workerruns.py @@ -2,7 +2,7 @@ import uuid from datetime import datetime, timezone from unittest.mock import call, patch -from django.test import override_settings +from django.db import transaction from django.urls import reverse from rest_framework import status from rest_framework.exceptions import ValidationError @@ -10,11 +10,7 @@ from rest_framework.exceptions import ValidationError from arkindex.ponos.models import Agent, Farm, State from arkindex.process.models import ( FeatureUsage, - GitRef, - GitRefType, ProcessMode, - Repository, - Revision, Worker, WorkerRun, WorkerVersion, @@ -135,7 +131,6 @@ class TestWorkerRuns(FixtureAPITestCase): "docker_image_iid": self.version_1.docker_image_iid, "gpu_usage": "disabled", "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "version": 1, "tag": None, @@ -405,7 +400,6 @@ class TestWorkerRuns(FixtureAPITestCase): "docker_image_iid": self.version_1.docker_image_iid, "gpu_usage": "disabled", "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "version": 1, "tag": None, @@ -479,7 +473,6 @@ class TestWorkerRuns(FixtureAPITestCase): "docker_image_iid": self.version_1.docker_image_iid, "gpu_usage": "disabled", "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "version": 1, "tag": None, @@ -532,13 +525,6 @@ class TestWorkerRuns(FixtureAPITestCase): def test_summary(self): self.client.force_login(self.user) - repo = Repository.objects.create(url="http://nerv.co.jp/nerv/eva/") - revision = Revision.objects.create( - repo=repo, - hash="1", - message="commit message", - author="bob", - ) test_version = self.worker_1.versions.create( version=2, state=WorkerVersionState.Available, @@ -547,12 +533,12 @@ class TestWorkerRuns(FixtureAPITestCase): ) cases = [ - ("eva-01", revision, self.model_version_1, self.configuration_1, f"Worker Recognizer @ eva-01 ({str(test_version.id)[:6]}) with model My model @ {str(self.model_version_1.id)[:6]} using configuration 'My config'"), - (None, revision, self.model_version_1, self.configuration_1, f"Worker Recognizer @ {str(test_version.id)[:6]} with model My model @ {str(self.model_version_1.id)[:6]} using configuration 'My config'"), - ("eva-01", revision, None, self.configuration_1, f"Worker Recognizer @ eva-01 ({str(test_version.id)[:6]}) using configuration 'My config'"), - (None, revision, self.model_version_1, None, f"Worker Recognizer @ {str(test_version.id)[:6]} with model My model @ {str(self.model_version_1.id)[:6]}"), - ("eva-01", revision, None, None, f"Worker Recognizer @ eva-01 ({str(test_version.id)[:6]})"), - (None, revision, None, None, f"Worker Recognizer @ {str(test_version.id)[:6]}"), + ("eva-01", "revision_url", self.model_version_1, self.configuration_1, f"Worker Recognizer @ eva-01 ({str(test_version.id)[:6]}) with model My model @ {str(self.model_version_1.id)[:6]} using configuration 'My config'"), + (None, "revision_url", self.model_version_1, self.configuration_1, f"Worker Recognizer @ {str(test_version.id)[:6]} with model My model @ {str(self.model_version_1.id)[:6]} using configuration 'My config'"), + ("eva-01", "revision_url", None, self.configuration_1, f"Worker Recognizer @ eva-01 ({str(test_version.id)[:6]}) using configuration 'My config'"), + (None, "revision_url", self.model_version_1, None, f"Worker Recognizer @ {str(test_version.id)[:6]} with model My model @ {str(self.model_version_1.id)[:6]}"), + ("eva-01", "revision_url", None, None, f"Worker Recognizer @ eva-01 ({str(test_version.id)[:6]})"), + (None, "revision_url", None, None, f"Worker Recognizer @ {str(test_version.id)[:6]}"), ("eva-01", None, self.model_version_1, self.configuration_1, f"Worker Recognizer @ eva-01 (version 2) with model My model @ {str(self.model_version_1.id)[:6]} using configuration 'My config'"), (None, None, self.model_version_1, self.configuration_1, f"Worker Recognizer @ version 2 with model My model @ {str(self.model_version_1.id)[:6]} using configuration 'My config'"), ("eva-01", None, None, self.configuration_1, "Worker Recognizer @ eva-01 (version 2) using configuration 'My config'"), @@ -561,21 +547,18 @@ class TestWorkerRuns(FixtureAPITestCase): (None, None, None, None, "Worker Recognizer @ version 2"), ] - for tag, revision, model_version, config, expected_summary in cases: - with self.subTest(tag=tag, revision=revision, model_version=model_version, config=config): + for tag, revision_url, model_version, config, expected_summary in cases: + with self.subTest(tag=tag, model_version=model_version, config=config), transaction.atomic(): # Clear the process of worker runs self.process_2.worker_runs.all().delete() num_queries = 6 + test_version.version = None test_version.tag = tag - test_version.revision = None - test_version.version = 2 - if revision: - test_version.revision = revision - test_version.version = None - # If there is a revision, it adds a query - num_queries += 1 + test_version.revision_url = revision_url + if not revision_url: + test_version.version = 2 test_version.save() payload = { @@ -647,7 +630,6 @@ class TestWorkerRuns(FixtureAPITestCase): "docker_image_iid": self.version_1.docker_image_iid, "gpu_usage": "disabled", "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "version": 1, "tag": None, @@ -705,7 +687,6 @@ class TestWorkerRuns(FixtureAPITestCase): "docker_image_iid": self.version_1.docker_image_iid, "gpu_usage": "disabled", "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "version": 1, "tag": None, @@ -792,7 +773,6 @@ class TestWorkerRuns(FixtureAPITestCase): "docker_image_iid": None, "gpu_usage": "disabled", "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "version": 1, "tag": None, @@ -809,85 +789,6 @@ class TestWorkerRuns(FixtureAPITestCase): "use_gpu": False, }) - @override_settings(PUBLIC_HOSTNAME="https://arkindex.localhost") - def test_gitrefs_are_retrieved(self): - """ - Check the GitRefs are retrieved with the revision - """ - repo = Repository.objects.create(url="http://nerv.co.jp/nerv/eva/") - # Create gitrefs and check they were created - commit_refs = [ - {"name": "refs/tags/v0.1.0", "type": "tag"}, - {"name": "refs/heads/branch1", "type": "branch"}, - {"name": "refs/heads/branch2", "type": "branch"}, - ] - revision = Revision.objects.create( - repo=repo, - hash="1", - message="commit message", - author="bob", - ) - - for ref in commit_refs: - GitRef.objects.create(repository=repo, revision=revision, name=ref["name"], type=ref["type"]) - - refs = [ - {"name": ref.name, "type": ref.type, "repo": ref.repository} - for ref in revision.refs.all() - ] - self.assertListEqual(refs, [ - {"name": "refs/tags/v0.1.0", "type": GitRefType.Tag, "repo": repo}, - {"name": "refs/heads/branch1", "type": GitRefType.Branch, "repo": repo}, - {"name": "refs/heads/branch2", "type": GitRefType.Branch, "repo": repo}, - ]) - self.assertEqual(repo.refs.count(), 3) - - # Assign the revision with gitrefs to the worker version - self.version_1.revision = revision - self.version_1.version = None - self.version_1.save() - self.assertTrue(revision.refs.exists()) - - # Check that the gitrefs are retrieved with RetrieveWorkerRun - self.client.force_login(self.user) - with self.assertNumQueries(5): - response = self.client.get(reverse("api:worker-run-details", kwargs={"pk": str(self.run_1.id)})) - self.assertEqual(response.status_code, status.HTTP_200_OK) - - version_revision = response.json()["worker_version"]["revision"] - refs = version_revision.pop("refs") - # Only asserting on the name and type of the refs since they were created in bulk using - # GitLabProvider.update_or_create_ref, ignoring the IDs. - refs_no_id = [ - { - "name": item["name"], - "type": item["type"] - } - for item in refs - ] - self.assertDictEqual(version_revision, { - "author": "bob", - "commit_url": "http://nerv.co.jp/nerv/eva/commit/1", - "created": revision.created.isoformat().replace("+00:00", "Z"), - "hash": "1", - "id": str(revision.id), - "message": "commit message", - }) - self.assertCountEqual(refs_no_id, [ - { - "name": "refs/tags/v0.1.0", - "type": "tag" - }, - { - "name": "refs/heads/branch1", - "type": "branch" - }, - { - "name": "refs/heads/branch2", - "type": "branch" - } - ]) - def test_retrieve_local(self): """ A user can retrieve a run on their own local process @@ -909,7 +810,6 @@ class TestWorkerRuns(FixtureAPITestCase): "docker_image_iid": self.version_1.docker_image_iid, "gpu_usage": "disabled", "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "version": 1, "tag": None, @@ -978,7 +878,6 @@ class TestWorkerRuns(FixtureAPITestCase): "docker_image_iid": self.version_1.docker_image_iid, "gpu_usage": "disabled", "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "version": 1, "tag": None, @@ -1217,7 +1116,6 @@ class TestWorkerRuns(FixtureAPITestCase): "docker_image_iid": self.version_1.docker_image_iid, "gpu_usage": "disabled", "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "version": 1, "tag": None, @@ -1277,7 +1175,6 @@ class TestWorkerRuns(FixtureAPITestCase): "docker_image_iid": self.version_1.docker_image_iid, "gpu_usage": "disabled", "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "version": 1, "tag": None, @@ -1345,7 +1242,6 @@ class TestWorkerRuns(FixtureAPITestCase): "docker_image_iid": self.version_1.docker_image_iid, "gpu_usage": "disabled", "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "version": 1, "tag": None, @@ -1714,7 +1610,6 @@ class TestWorkerRuns(FixtureAPITestCase): "docker_image_iid": None, "gpu_usage": "disabled", "model_usage": FeatureUsage.Supported.value, - "revision": None, "revision_url": None, "version": version_with_model.version, "tag": None, @@ -1806,7 +1701,6 @@ class TestWorkerRuns(FixtureAPITestCase): "docker_image_iid": None, "gpu_usage": "disabled", "model_usage": FeatureUsage.Required.value, - "revision": None, "revision_url": None, "version": version_with_model.version, "tag": None, @@ -1874,7 +1768,6 @@ class TestWorkerRuns(FixtureAPITestCase): "docker_image_iid": self.version_1.docker_image_iid, "gpu_usage": "disabled", "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "version": 1, "tag": None, @@ -2094,7 +1987,6 @@ class TestWorkerRuns(FixtureAPITestCase): "docker_image_iid": self.version_1.docker_image_iid, "gpu_usage": "disabled", "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "version": 1, "tag": None, @@ -2154,7 +2046,6 @@ class TestWorkerRuns(FixtureAPITestCase): "docker_image_iid": self.version_1.docker_image_iid, "gpu_usage": "disabled", "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "version": 1, "tag": None, @@ -2219,7 +2110,6 @@ class TestWorkerRuns(FixtureAPITestCase): "docker_image_iid": self.version_1.docker_image_iid, "gpu_usage": "disabled", "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "version": 1, "tag": None, @@ -2575,7 +2465,6 @@ class TestWorkerRuns(FixtureAPITestCase): "docker_image_iid": None, "gpu_usage": "disabled", "model_usage": FeatureUsage.Required.value, - "revision": None, "revision_url": None, "version": version_with_model.version, "tag": None, @@ -2664,7 +2553,6 @@ class TestWorkerRuns(FixtureAPITestCase): "docker_image_iid": None, "gpu_usage": "disabled", "model_usage": FeatureUsage.Required.value, - "revision": None, "revision_url": None, "version": version_with_model.version, "tag": None, @@ -2731,7 +2619,6 @@ class TestWorkerRuns(FixtureAPITestCase): "docker_image_iid": self.version_1.docker_image_iid, "gpu_usage": "disabled", "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "version": 1, "tag": None, diff --git a/arkindex/process/tests/test_workerruns_use_gpu.py b/arkindex/process/tests/test_workerruns_use_gpu.py index cc9e66b7de..af3fe90a68 100644 --- a/arkindex/process/tests/test_workerruns_use_gpu.py +++ b/arkindex/process/tests/test_workerruns_use_gpu.py @@ -76,7 +76,6 @@ class TestWorkerRunsGPU(FixtureAPITestCase): "docker_image_iid": "registry.nerv.co.jp/neon-genesis:evangelion", "gpu_usage": worker_version.gpu_usage.value, "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "version": worker_version.version, "tag": None, @@ -130,7 +129,6 @@ class TestWorkerRunsGPU(FixtureAPITestCase): "docker_image_iid": "registry.nerv.co.jp/neon-genesis:evangelion", "gpu_usage": FeatureUsage.Required.value, "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "version": 2, "tag": None, @@ -225,7 +223,6 @@ class TestWorkerRunsGPU(FixtureAPITestCase): "docker_image_iid": "registry.nerv.co.jp/neon-genesis:evangelion", "gpu_usage": worker_version.gpu_usage.value, "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "version": worker_version.version, "tag": None, diff --git a/arkindex/process/tests/test_workers.py b/arkindex/process/tests/test_workers.py index d68b4d5939..2fa5dc428e 100644 --- a/arkindex/process/tests/test_workers.py +++ b/arkindex/process/tests/test_workers.py @@ -9,9 +9,7 @@ from arkindex.ponos.models import Farm from arkindex.process.models import ( CorpusWorkerVersion, FeatureUsage, - GitRefType, ProcessMode, - Repository, Worker, WorkerConfiguration, WorkerType, @@ -31,7 +29,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): @classmethod def setUpTestData(cls): super().setUpTestData() - cls.repo = Repository.objects.create(url="https://nerv.co.jp/nerv/eva") cls.worker_type_dla = WorkerType.objects.get(slug="dla") cls.worker_reco = Worker.objects.get(slug="reco") @@ -91,7 +88,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "results": [ { "id": str(self.worker_custom.id), - "repository_id": None, "repository_url": None, "name": "Custom worker", "description": "", @@ -101,7 +97,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): }, { "id": str(self.worker_dla.id), - "repository_id": None, "repository_url": None, "name": "Document layout analyser", "description": "", @@ -111,7 +106,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): }, { "id": str(self.init_worker.id), - "repository_id": None, "repository_url": None, "name": "Elements Initialisation Worker", "description": "", @@ -121,7 +115,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): }, { "id": str(self.worker_file_import.id), - "repository_id": None, "repository_url": None, "name": "File import", "description": "", @@ -131,7 +124,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): }, { "id": str(self.worker_generic.id), - "repository_id": None, "repository_url": None, "name": "Generic worker with a Model", "description": "", @@ -141,7 +133,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): }, { "id": str(self.worker_reco.id), - "repository_id": None, "repository_url": None, "name": "Recognizer", "description": "", @@ -151,7 +142,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): }, { "id": str(self.worker_gpu.id), - "repository_id": None, "repository_url": None, "name": "Worker requiring a GPU", "description": "", @@ -185,7 +175,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "results": [ { "id": str(self.worker_generic.id), - "repository_id": None, "repository_url": None, "name": "Generic worker with a Model", "description": "", @@ -215,7 +204,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "previous": None, "results": [{ "id": str(self.worker_reco.id), - "repository_id": None, "repository_url": None, "name": "Recognizer", "description": "", @@ -257,16 +245,12 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): with self.assertNumQueries(2): response = self.client.get( reverse("api:workers-list"), - { - "compatible_model": "A", - "repository_id": "A", - }, + {"compatible_model": "A"}, ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(response.json(), { "compatible_model": ["Invalid UUID"], - "repository_id": ["Invalid UUID"], }) def test_workers_list_filter_type_slug(self): @@ -287,7 +271,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "results": [ { "id": str(self.worker_dla.id), - "repository_id": None, "repository_url": None, "name": "Document layout analyser", "description": "", @@ -315,7 +298,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "results": [ { "id": str(self.worker_dla.id), - "repository_id": None, "repository_url": None, "name": "Document layout analyser", "description": "", @@ -344,7 +326,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "results": [ { "id": str(self.worker_dla.id), - "repository_id": None, "repository_url": None, "name": "Document layout analyser", "description": "", @@ -385,7 +366,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "results": [ { "id": str(self.worker_dla.id), - "repository_id": None, "repository_url": None, "name": "Document layout analyser", "description": "", @@ -437,7 +417,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "results": [ { "id": str(self.worker_dla.id), - "repository_id": None, "repository_url": None, "name": "Document layout analyser", "description": "", @@ -448,47 +427,11 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): ] }) - def test_workers_list_filter_repository(self): - repo2 = Repository.objects.create( - url="http://gitlab/repo2" - ) - worker_2 = Worker.objects.create( - repository=repo2, - name="Worker 2", - slug="worker_2", - type=self.worker_type_dla - ) - worker_2.memberships.create(user=self.user, level=Role.Contributor.value) - self.client.force_login(self.user) - - with self.assertNumQueries(4): - response = self.client.get(reverse("api:workers-list"), {"repository_id": str(repo2.id)}) - self.assertEqual(response.status_code, status.HTTP_200_OK) - - self.assertDictEqual(response.json(), { - "count": 1, - "next": None, - "number": 1, - "previous": None, - "results": [ - { - "id": str(worker_2.id), - "repository_id": str(repo2.id), - "repository_url": None, - "name": "Worker 2", - "description": "", - "slug": "worker_2", - "type": self.worker_type_dla.slug, - "archived": False, - } - ] - }) - def test_workers_retrieve_required_login(self): response = self.client.get(reverse("api:worker-retrieve", kwargs={"pk": str(self.worker_reco.id)})) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) - def test_workers_retrieve_no_revision(self): + def test_workers_retrieve(self): self.client.force_login(self.user) with self.assertNumQueries(3): @@ -497,7 +440,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): self.assertDictEqual(response.json(), { "id": str(self.worker_custom.id), - "repository_id": None, "repository_url": None, "name": "Custom worker", "description": "", @@ -575,7 +517,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): data = response.json() worker = Worker.objects.get(id=data["id"]) self.assertEqual(worker.type, self.worker_type_dla) - self.assertIsNone(worker.repository) self.assertQuerySetEqual(worker.memberships.values_list("user_id", "level"), [ (self.user.id, Role.Admin.value) ]) @@ -583,7 +524,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "id": str(worker.id), "name": "Worker post", "description": "", - "repository_id": None, "repository_url": "https://gitlab.com/NERV/eva/", "slug": "worker_post", "type": "dla", @@ -605,6 +545,7 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): data={ "name": "Worker post", "slug": self.worker_custom.slug, + "repository_url": "", "type": "new_type" } ) @@ -614,7 +555,10 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): self.assertQuerySetEqual(self.worker_custom.memberships.values_list("user_id", "level"), [ (self.user.id, Role.Guest.value) ]) - self.assertDictEqual(response.json(), {"slug": ["You cannot use this value."]}) + self.assertDictEqual(response.json(), { + "repository_url": ["You cannot use this value."], + "slug": ["You cannot use this value."], + }) self.assertEqual(get_max_level_mock.call_count, 1) self.assertEqual(get_max_level_mock.call_args, call(self.user, self.worker_custom)) @@ -633,7 +577,8 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): data={ "name": "Progressive Knife", "slug": "prog_knife", - "type": self.worker_type_dla.slug + "type": self.worker_type_dla.slug, + "repository_url": "", }, HTTP_AUTHORIZATION=f"Ponos {self.task.token}", ) @@ -644,6 +589,8 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): self.assertEqual(data["name"], "Prog Knife") self.assertEqual(data["slug"], "prog_knife") self.assertEqual(data["type"], "recognizer") + self.assertEqual(data["repository_url"], None) + self.assertEqual(test_worker.repository_url, None) def test_worker_create_task_new_type(self): """ @@ -658,7 +605,8 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): data={ "name": "Worker post", "slug": "worker_post", - "type": "newType" + "type": "newType", + "repository_url": "", }, HTTP_AUTHORIZATION=f"Ponos {self.task.token}", ) @@ -670,6 +618,7 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): self.assertEqual(data["name"], "Worker post") self.assertEqual(data["slug"], "worker_post") self.assertEqual(data["type"], "newType") + self.assertEqual(data["repository_url"], None) def test_update_requires_login(self): with self.assertNumQueries(0): @@ -760,7 +709,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "slug": "new_slug", "description": "New description", "type": "dla", - "repository_id": None, "repository_url": "https://gitlab.com/NERV/eva", "archived": False, }) @@ -770,7 +718,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): self.assertEqual(self.worker_reco.slug, "new_slug") self.assertEqual(self.worker_reco.description, "New description") self.assertEqual(self.worker_reco.type, self.worker_type_dla) - self.assertEqual(self.worker_reco.repository, None) self.assertEqual(self.worker_reco.repository_url, "https://gitlab.com/NERV/eva") self.assertListEqual(filter_rights_mock.call_args_list, [ call(self.user, Worker, Role.Contributor.value), @@ -779,6 +726,7 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): def test_update_unique_slug(self): self.client.force_login(self.user) + self.assertEqual(self.worker_reco.repository_url, None) with self.assertNumQueries(5): response = self.client.put( reverse("api:worker-retrieve", kwargs={"pk": str(self.worker_reco.id)}), @@ -793,7 +741,7 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(response.json(), { - "non_field_errors": ["A worker with the same repository and slug already exists."], + "non_field_errors": ["A worker with the same repository URL and slug already exists."], }) @patch("arkindex.users.utils.get_max_level", return_value=Role.Contributor.value) @@ -865,7 +813,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "slug": "new_slug", "description": "New description", "type": "dla", - "repository_id": None, "repository_url": None, "archived": new_value, }) @@ -945,7 +892,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "slug": "reco", "description": "New description", "type": "dla", - "repository_id": None, "repository_url": None, "archived": False, }) @@ -955,7 +901,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): self.assertEqual(self.worker_reco.slug, "reco") self.assertEqual(self.worker_reco.description, "New description") self.assertEqual(self.worker_reco.type, self.worker_type_dla) - self.assertEqual(self.worker_reco.repository, None) self.assertListEqual(filter_rights_mock.call_args_list, [ call(self.user, Worker, Role.Contributor.value), @@ -974,7 +919,7 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(response.json(), { - "non_field_errors": ["A worker with the same repository and slug already exists."], + "non_field_errors": ["A worker with the same repository URL and slug already exists."], }) @patch("arkindex.users.utils.get_max_level", return_value=Role.Contributor.value) @@ -1038,7 +983,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "slug": "reco", "description": "", "type": "recognizer", - "repository_id": None, "repository_url": None, "archived": new_value, }) @@ -1052,7 +996,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): def test_versions_list(self): self.client.force_login(self.user) last_version = self.worker_reco.versions.create( - version=2, configuration={"a": "bc"}, state=WorkerVersionState.Error, revision_url="https://gitlab.com/NERV/eva/commit/63e377e7f88c743d8428fc4e4eaedfc1c9356754" @@ -1060,7 +1003,7 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): last_version.created = "2050-09-09T09:09:09.090909Z" last_version.save() - with self.assertNumQueries(6): + with self.assertNumQueries(5): response = self.client.get(reverse("api:worker-versions", kwargs={"pk": str(self.worker_reco.id)})) self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -1083,9 +1026,8 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "type": self.worker_reco.type.slug, "slug": self.worker_reco.slug, }, - "version": 2, + "version": None, "tag": None, - "revision": None, "revision_url": "https://gitlab.com/NERV/eva/commit/63e377e7f88c743d8428fc4e4eaedfc1c9356754", "created": "2050-09-09T09:09:09.090909Z", }, @@ -1104,7 +1046,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): }, "version": 1, "tag": None, - "revision": None, "revision_url": None, "created": self.version_1.created.isoformat().replace("+00:00", "Z"), } @@ -1141,7 +1082,7 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): self.worker_reco.save() self.client.force_login(user) - with self.assertNumQueries(6): + with self.assertNumQueries(5): response = self.client.get(reverse("api:worker-versions", kwargs={"pk": str(self.worker_reco.id)})) self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -1163,7 +1104,7 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): gpu_usage=FeatureUsage.Disabled ) - with self.assertNumQueries(6): + with self.assertNumQueries(5): response = self.client.get(reverse("api:worker-versions", kwargs={"pk": str(worker_2.id)})) self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -1174,44 +1115,33 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): def test_versions_list_simple_mode(self): """ - With the mode attribute set to simple, worker versions older than master/main - or with no tag are excluded from the results + With the mode attribute set to simple, worker versions with no tag are excluded """ - # An old branch revision - non_tagged_rev = self.repo.revisions.create(hash="001", message="random", author="A1ice") - non_tagged_rev.refs.create(name="a-second-branch", type=GitRefType.Branch, repository=self.repo) - # An old tagged branch revision - tagged_rev = self.repo.revisions.create(hash="002", message="v0.1", author="Bob") - tagged_rev.refs.create(name="a-branch", type=GitRefType.Branch, repository=self.repo) - tagged_rev.refs.create(name="0.1", type=GitRefType.Tag, repository=self.repo) - # Master branch revision - master_rev = self.repo.revisions.create(hash="003", message="up-to-date", author="B0b") - master_rev.refs.create(name="master", type=GitRefType.Branch, repository=self.repo) - # Main branch revision - main_rev = self.repo.revisions.create(hash="004", message="up-to-date", author="B0b") - main_rev.refs.create(name="main", type=GitRefType.Branch, repository=self.repo) - # A recent revision with no reference - recent_rev = self.repo.revisions.create(hash="005", message="up-to-date", author="AL1C3") WorkerVersion.objects.bulk_create([ WorkerVersion( worker=self.worker_reco, - revision=rev, - configuration={"test": "42"} - ) for rev in (non_tagged_rev, tagged_rev, master_rev, main_rev, recent_rev) + configuration={"test": "42"}, + tag=tag, + version=i, + ) for i, tag in enumerate((None, "v0.1", "test"), start=2) ]) - # Complete mode - with self.subTest(mode="complete"), self.assertNumQueries(8): + with self.subTest(mode="complete"), self.assertNumQueries(4): response = self.client.get( reverse("api:worker-versions", kwargs={"pk": str(self.worker_reco.id)}), {"mode": "complete"}, HTTP_AUTHORIZATION=f"Ponos {self.task.token}", ) self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(response.json()["count"], 6) + data = response.json() + self.assertEqual(data["count"], 4) + self.assertCountEqual( + [version["tag"] for version in data["results"]], + ["v0.1", "test", None, None], + ) - # Simple mode - with self.subTest(mode="simple"), self.assertNumQueries(8): + # Simple mode filters out versions without a tag + with self.subTest(mode="simple"), self.assertNumQueries(4): response = self.client.get( reverse("api:worker-versions", kwargs={"pk": str(self.worker_reco.id)}), {"mode": "simple"}, @@ -1219,10 +1149,10 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): ) self.assertEqual(response.status_code, status.HTTP_200_OK) data = response.json() - self.assertEqual(data["count"], 3) + self.assertEqual(data["count"], 2) self.assertCountEqual( - [version["revision"]["id"] for version in data["results"]], - [str(tagged_rev.id), str(master_rev.id), str(main_rev.id)] + [version["tag"] for version in data["results"]], + ["v0.1", "test"], ) def test_create_version_non_existing_worker(self): @@ -1362,7 +1292,7 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): self.worker_dla.repository_url = "https://gitlab.com/NERV/eva" self.worker_dla.save() - with self.assertNumQueries(7): + with self.assertNumQueries(6): response = self.client.post( reverse("api:worker-versions", kwargs={"pk": str(self.worker_dla.id)}), data={"revision_url": "https://gitlab.com/NERV/eva/commit/eva-01", "configuration": {"test": "test2"}, "model_usage": FeatureUsage.Required.value}, @@ -1379,10 +1309,9 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "docker_image_iid": None, "gpu_usage": FeatureUsage.Disabled.value, "model_usage": FeatureUsage.Required.value, - "revision": None, "revision_url": "https://gitlab.com/NERV/eva/commit/eva-01", "state": WorkerVersionState.Created.value, - "version": 2, + "version": None, "tag": None, "worker": { "id": str(self.worker_dla.id), @@ -1415,7 +1344,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "docker_image_iid": None, "gpu_usage": FeatureUsage.Disabled.value, "model_usage": FeatureUsage.Required.value, - "revision": None, "revision_url": None, "state": WorkerVersionState.Created.value, "version": 42, @@ -1445,7 +1373,11 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): def test_create_version(self): response = self.client.post( reverse("api:worker-versions", kwargs={"pk": str(self.worker_reco.id)}), - data={"configuration": {"test": "test2"}, "model_usage": FeatureUsage.Required.value, "revision_url": "https://gitlab.com/NERV/eva/commit/eva-01"}, + data={ + "configuration": {"test": "test2"}, + "model_usage": FeatureUsage.Required.value, + "revision_url": "https://gitlab.com/NERV/eva/commit/eva-01", + }, format="json", HTTP_AUTHORIZATION=f"Ponos {self.task.token}", ) @@ -1454,16 +1386,22 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): data = response.json() self.assertNotEqual(data["id"], str(self.version_1.id)) self.assertEqual(data["configuration"], {"test": "test2"}) - self.assertEqual(data["version"], 2) + self.assertEqual(data["version"], None) + self.assertEqual(data["revision_url"], "https://gitlab.com/NERV/eva/commit/eva-01") self.assertEqual(data["state"], "created") self.assertEqual(data["gpu_usage"], "disabled") self.assertEqual(data["model_usage"], FeatureUsage.Required.value) def test_create_version_with_tag(self): - with self.assertNumQueries(7): + with self.assertNumQueries(6): response = self.client.post( reverse("api:worker-versions", kwargs={"pk": str(self.worker_reco.id)}), - data={"configuration": {"test": "test2"}, "model_usage": FeatureUsage.Required.value, "revision_url": "https://gitlab.com/NERV/eva/commit/eva-01", "tag": "eva-01"}, + data={ + "configuration": {"test": "test2"}, + "model_usage": FeatureUsage.Required.value, + "revision_url": "https://gitlab.com/NERV/eva/commit/eva-01", + "tag": "eva-01", + }, format="json", HTTP_AUTHORIZATION=f"Ponos {self.task.token}", ) @@ -1472,7 +1410,8 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): data = response.json() self.assertNotEqual(data["id"], str(self.version_1.id)) self.assertEqual(data["configuration"], {"test": "test2"}) - self.assertEqual(data["version"], 2) + self.assertEqual(data["version"], None) + self.assertEqual(data["revision_url"], "https://gitlab.com/NERV/eva/commit/eva-01") self.assertEqual(data["state"], "created") self.assertEqual(data["gpu_usage"], "disabled") self.assertEqual(data["model_usage"], FeatureUsage.Required.value) @@ -2082,7 +2021,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "state": "available", "gpu_usage": "disabled", "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "version": 1, "tag": None, @@ -2107,7 +2045,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "state": "available", "gpu_usage": "disabled", "model_usage": FeatureUsage.Disabled.value, - "revision": None, "revision_url": None, "version": 1, "tag": None, @@ -2232,27 +2169,25 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): self.assertDictEqual(response.json(), {"tag": ["This field may not be blank."]}) def test_cannot_update_worker_version_revision_ignored(self): - rev = self.repo.revisions.create(hash="001", message="something", author="someone") - rev2 = self.repo.revisions.create(hash="002", message="something else", author="someone else") - self.version_1.revision = rev + self.version_1.revision_url = "url" self.version_1.version = None self.version_1.state = WorkerVersionState.Created self.version_1.save() - with self.assertNumQueries(7): + with self.assertNumQueries(4): response = self.client.patch( reverse("api:version-retrieve", kwargs={"pk": str(self.version_1.id)}), data={ - "revision_id": str(rev2.id) + "revision_url": "updated" }, format="json", HTTP_AUTHORIZATION=f"Ponos {self.task.token}", ) - # revision_id just gets ignored self.assertEqual(response.status_code, status.HTTP_200_OK) data = response.json() self.assertEqual(data["id"], str(self.version_1.id)) self.version_1.refresh_from_db() - self.assertEqual(self.version_1.revision.id, rev.id) + # revision_url just gets ignored + self.assertEqual(self.version_1.revision_url, "url") def test_cannot_update_worker_version_revision_url_ignored(self): with self.assertNumQueries(4): @@ -2333,7 +2268,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "worker_version": { "id": str(self.version_2.id), "configuration": {"test": 42}, - "revision": None, "revision_url": None, "version": 1, "tag": None, @@ -2356,7 +2290,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "worker_version": { "id": str(self.version_1.id), "configuration": {"test": 42}, - "revision": None, "revision_url": None, "version": 1, "tag": None, @@ -2411,7 +2344,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "worker_version": { "id": str(self.version_2.id), "configuration": {"test": 42}, - "revision": None, "revision_url": None, "version": 1, "tag": None, @@ -2434,7 +2366,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "worker_version": { "id": str(self.version_1.id), "configuration": {"test": 42}, - "revision": None, "revision_url": None, "version": 1, "tag": None, @@ -2485,7 +2416,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "worker_version": { "id": str(self.version_2.id), "configuration": {"test": 42}, - "revision": None, "revision_url": None, "version": 1, "tag": None, @@ -2523,7 +2453,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "worker_version": { "id": str(self.version_1.id), "configuration": {"test": 42}, - "revision": None, "revision_url": None, "version": 1, "tag": None, @@ -2580,7 +2509,6 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): "worker_version": { "id": str(self.version_1.id), "configuration": {"test": 42}, - "revision": None, "revision_url": None, "version": 1, "tag": None, diff --git a/arkindex/project/api_v1.py b/arkindex/project/api_v1.py index c65d036fc6..7b2deb75ba 100644 --- a/arkindex/project/api_v1.py +++ b/arkindex/project/api_v1.py @@ -66,7 +66,6 @@ from arkindex.process.api import ( CorpusWorkerRunList, CorpusWorkersActivity, CorpusWorkerVersionList, - CreateDockerWorkerVersion, CreateProcessTemplate, DataFileCreate, DataFileList, @@ -243,7 +242,6 @@ api = [ path("workers/<uuid:pk>/configurations/", WorkerConfigurationList.as_view(), name="worker-configurations"), path("workers/<uuid:pk>/versions/", WorkerVersionList.as_view(), name="worker-versions"), path("workers/versions/<uuid:pk>/", WorkerVersionRetrieve.as_view(), name="version-retrieve"), - path("workers/versions/docker/", CreateDockerWorkerVersion.as_view(), name="version-from-docker"), path("workers/versions/<uuid:pk>/activity/", UpdateWorkerActivity.as_view(), name="update-worker-activity"), path("workers/configurations/<uuid:pk>/", WorkerConfigurationRetrieve.as_view(), name="configuration-retrieve"), diff --git a/arkindex/project/argparse.py b/arkindex/project/argparse.py index d308011199..b0fb16cbef 100644 --- a/arkindex/project/argparse.py +++ b/arkindex/project/argparse.py @@ -3,7 +3,7 @@ from django.core.management.base import CommandError from django.db.models import Model from arkindex.documents.models import Corpus, Element -from arkindex.process.models import Process, Repository, WorkerVersion +from arkindex.process.models import Process, WorkerVersion from arkindex.users.models import User @@ -53,11 +53,6 @@ class ProcessArgument(ModelArgument): text_search_field = None -class RepositoryArgument(ModelArgument): - model = Repository - text_search_field = "url" - - class UserArgument(ModelArgument): model = User text_search_field = "email" diff --git a/arkindex/project/tests/test_acl_mixin.py b/arkindex/project/tests/test_acl_mixin.py index ae1884d2ac..46c857e37e 100644 --- a/arkindex/project/tests/test_acl_mixin.py +++ b/arkindex/project/tests/test_acl_mixin.py @@ -5,7 +5,7 @@ from django.contrib.auth.models import AnonymousUser from django.contrib.contenttypes.models import ContentType from arkindex.documents.models import Corpus -from arkindex.process.models import Process, ProcessMode, Repository, WorkerType +from arkindex.process.models import Process, ProcessMode, Worker, WorkerType from arkindex.project.mixins import ACLMixin, CorpusACLMixin, ProcessACLMixin, TrainingModelMixin from arkindex.project.tests import FixtureTestCase from arkindex.training.models import Model @@ -18,18 +18,18 @@ class TestACLMixin(FixtureTestCase): @classmethod def setUpClass(cls): r""" - Create user and groups with rights on a Corpus, a Repository and a Model + Create user and groups with rights on a Corpus, and a Model We use a simple rights configuration for those tests User1 User2 User3 User4 User5 / | \ / | / | | / | | 100 10 | 100 | | 100 50 100 \ / 90 | 75 100 | - | | Group1 | Group2 | | Group3 - | Worker / \ | /\ | | / \ - | | 80 75 | 100 50 | | 10 100 - \ | / \ | / \ | | / \ - Repo1 Corpus1 Corpus2 Model1 Model2 + | Group1 | Group2 | | Group3 + Worker / \ | /\ | | / \ + 80 75 | 100 50 | | 10 100 + \ | / \ | | / \ + Corpus1 Corpus2 Model1 Model2 """ super().setUpClass() @@ -43,9 +43,8 @@ class TestACLMixin(FixtureTestCase): cls.group2 = Group.objects.create(name="Group2") cls.group3 = Group.objects.create(name="Group3") - cls.repo1 = Repository.objects.create(url="http://repo1") cls.worker_type = WorkerType.objects.create(display_name="ner", slug="ner") - cls.worker = cls.repo1.workers.create(name="repo1 worker", slug="worker", type=cls.worker_type) + cls.worker = Worker.objects.create(name="Worker", slug="worker", type=cls.worker_type) cls.corpus1 = Corpus.objects.create(name="Corpus1", id=uuid.UUID("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb")) cls.corpus2 = Corpus.objects.create(name="Corpus2", id=uuid.UUID("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")) @@ -55,7 +54,6 @@ class TestACLMixin(FixtureTestCase): Right.objects.bulk_create([ Right(user=cls.user1, content_object=cls.group1, level=100), - Right(user=cls.user1, content_object=cls.repo1, level=50), Right(user=cls.user1, content_object=cls.worker, level=100), Right(user=cls.user2, content_object=cls.group1, level=10), Right(user=cls.user2, content_object=cls.corpus1, level=90), @@ -63,7 +61,6 @@ class TestACLMixin(FixtureTestCase): Right(user=cls.user3, content_object=cls.corpus2, level=75), Right(user=cls.user4, content_object=cls.model1, level=100), Right(user=cls.user5, content_object=cls.group3, level=100), - Right(group=cls.group1, content_object=cls.repo1, level=80), Right(group=cls.group1, content_object=cls.corpus1, level=75), Right(group=cls.group2, content_object=cls.corpus1, level=100), Right(group=cls.group2, content_object=cls.corpus2, level=50), @@ -171,16 +168,6 @@ class TestACLMixin(FixtureTestCase): with self.assertNumQueries(3): self.assertEqual(get_max_level(self.user1, self.corpus2), None) - @expectedFailure - def test_max_level_user1(self): - with self.assertNumQueries(3): - self.assertEqual(get_max_level(self.user1, self.repo1), 80) - - @expectedFailure - def test_max_level_user2(self): - with self.assertNumQueries(3): - self.assertEqual(get_max_level(self.user2, self.repo1), 10) - @expectedFailure def test_max_level_user3(self): with self.assertNumQueries(3): diff --git a/arkindex/project/tests/test_checks.py b/arkindex/project/tests/test_checks.py index 98e42f4196..de9fa369b9 100644 --- a/arkindex/project/tests/test_checks.py +++ b/arkindex/project/tests/test_checks.py @@ -388,7 +388,6 @@ class ChecksTestCase(TestCase): slug="initialisation", type=init_type, ), - revision=None, version=1, configuration={ "docker": { @@ -443,7 +442,6 @@ class ChecksTestCase(TestCase): slug="initialisation", type=init_type, ), - revision=None, version=1, configuration={ "docker": { @@ -483,7 +481,6 @@ class ChecksTestCase(TestCase): slug="initialisation", type=init_type, ), - revision=None, version=1, configuration={ "docker": { @@ -499,7 +496,6 @@ class ChecksTestCase(TestCase): slug="shineaqua", type=init_type, ), - revision=None, version=1, configuration={ "docker": { diff --git a/arkindex/sql_validation/indexer_prefetch.sql b/arkindex/sql_validation/indexer_prefetch.sql index 8a5be55e93..1ee14c2bd6 100644 --- a/arkindex/sql_validation/indexer_prefetch.sql +++ b/arkindex/sql_validation/indexer_prefetch.sql @@ -62,7 +62,6 @@ WHERE "process_workerrun"."id" IN ('{worker_run_id}'::uuid); SELECT "process_workerversion"."id", "process_workerversion"."worker_id", - "process_workerversion"."revision_id", "process_workerversion"."version", "process_workerversion"."configuration", "process_workerversion"."state", @@ -81,7 +80,6 @@ SELECT "process_worker"."id", "process_worker"."slug", "process_worker"."type_id", "process_worker"."description", - "process_worker"."repository_id", "process_worker"."public", "process_worker"."archived", "process_worker"."repository_url" @@ -154,7 +152,6 @@ WHERE "process_workerrun"."id" IN ('{worker_run_id}'::uuid); SELECT "process_workerversion"."id", "process_workerversion"."worker_id", - "process_workerversion"."revision_id", "process_workerversion"."version", "process_workerversion"."configuration", "process_workerversion"."state", @@ -173,7 +170,6 @@ SELECT "process_worker"."id", "process_worker"."slug", "process_worker"."type_id", "process_worker"."description", - "process_worker"."repository_id", "process_worker"."public", "process_worker"."archived", "process_worker"."repository_url" -- GitLab