Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • arkindex/backend
1 result
Show changes
Commits on Source (4)
Showing with 2329 additions and 585 deletions
[
{
"model": "process.process",
<<<<<<< HEAD
"pk": "76506eee-43ab-4caa-966c-9e8e5d10ef93",
=======
"pk": "432278f2-a60e-4865-b474-de83833d0497",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"name": null,
"creator": 1,
"corpus": null,
"mode": "local",
"revision": null,
"activity_state": "disabled",
"started": null,
"finished": null,
"farm": null,
"element": null,
"folder_type": null,
"element_type": null,
"name_contains": null,
"ml_class": null,
"load_children": false,
"generate_thumbnails": false,
"chunks": 1,
"use_cache": false,
"use_gpu": false,
"template": null,
"bucket_name": null,
"prefix": null,
"files": []
}
},
{
"model": "process.process",
"pk": "c914b228-86a6-434b-81d8-f78751f02cf1",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"name": "Process fixture",
"creator": 2,
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"mode": "workers",
"revision": null,
"activity_state": "disabled",
"started": null,
"finished": null,
"farm": "ff732a3f-c9ac-43fe-8b22-c03cf82d2a4e",
"element": null,
"folder_type": null,
"element_type": null,
"name_contains": null,
"ml_class": null,
"load_children": false,
"generate_thumbnails": false,
"chunks": 1,
"use_cache": false,
"use_gpu": false,
"template": null,
"bucket_name": null,
"prefix": null,
"files": []
}
},
{
"model": "process.process",
"pk": "c992f023-baea-4c6d-92ba-e5bac0c2c0b4",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"name": null,
"creator": 2,
"corpus": null,
"mode": "local",
"revision": null,
"activity_state": "disabled",
"started": null,
"finished": null,
"farm": null,
"element": null,
"folder_type": null,
"element_type": null,
"name_contains": null,
"ml_class": null,
"load_children": false,
"generate_thumbnails": false,
"chunks": 1,
"use_cache": false,
"use_gpu": false,
"template": null,
"bucket_name": null,
"prefix": null,
"files": []
}
},
{
"model": "process.process",
"pk": "d6b43bc9-d87c-4c80-9211-f0c807506ad7",
>>>>>>> 7912af40 (wip API endpoints)
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"name": null,
"creator": 1,
"corpus": null,
<<<<<<< HEAD
"mode": "local",
"activity_state": "disabled",
"started": null,
......@@ -73,6 +171,14 @@
"started": null,
"finished": null,
"farm": null,
=======
"mode": "repository",
"revision": null,
"activity_state": "disabled",
"started": null,
"finished": null,
"farm": "ff732a3f-c9ac-43fe-8b22-c03cf82d2a4e",
>>>>>>> 7912af40 (wip API endpoints)
"element": null,
"folder_type": null,
"element_type": null,
......@@ -91,6 +197,7 @@
},
{
"model": "process.repository",
<<<<<<< HEAD
"pk": "bcfed350-d5be-4f27-b66a-042be3e6ee64",
"fields": {
"url": "http://gitlab/repo"
......@@ -99,17 +206,35 @@
{
"model": "process.repository",
"pk": "e3f470b1-fc46-4bc1-8117-30e1c62962b7",
=======
"pk": "565a09bb-0f64-49b5-acbf-8e5fde104cbb",
>>>>>>> 7912af40 (wip API endpoints)
"fields": {
"url": "http://my_repo.fake/workers/worker"
}
},
{
"model": "process.repository",
"pk": "deea5468-0e94-4215-bef3-efb8d18f0065",
"fields": {
"url": "http://gitlab/repo"
}
},
{
"model": "process.revision",
<<<<<<< HEAD
"pk": "2d087aa1-82ba-4ec5-af14-c19e4213f913",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"repo": "e3f470b1-fc46-4bc1-8117-30e1c62962b7",
=======
"pk": "174a7683-f6bb-402b-8ff5-3b22785f35a2",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"repo": "565a09bb-0f64-49b5-acbf-8e5fde104cbb",
>>>>>>> 7912af40 (wip API endpoints)
"hash": "1337",
"message": "My w0rk3r",
"author": "Test user"
......@@ -117,11 +242,19 @@
},
{
"model": "process.revision",
<<<<<<< HEAD
"pk": "7876a435-f3a5-40f8-b30b-f388f22019bf",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"repo": "bcfed350-d5be-4f27-b66a-042be3e6ee64",
=======
"pk": "6b139a49-ae71-4b64-8e69-e67a389e9cfa",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"repo": "deea5468-0e94-4215-bef3-efb8d18f0065",
>>>>>>> 7912af40 (wip API endpoints)
"hash": "42",
"message": "Salve",
"author": "Some user"
......@@ -129,6 +262,7 @@
},
{
"model": "process.worker",
<<<<<<< HEAD
"pk": "12b2344f-4871-40ad-aa1b-efaa70b5823f",
"fields": {
"name": "Document layout analyser",
......@@ -136,12 +270,22 @@
"type": "e84d4893-ae73-4162-acb6-13d606587644",
"description": "",
"repository": "e3f470b1-fc46-4bc1-8117-30e1c62962b7",
=======
"pk": "049370f4-2328-40de-84a0-48e5bb45fcda",
"fields": {
"name": "Generic worker with a Model",
"slug": "generic",
"type": "3c93cbb2-97a1-4b0c-8ddf-98ee99760805",
"description": "",
"repository": "565a09bb-0f64-49b5-acbf-8e5fde104cbb",
>>>>>>> 7912af40 (wip API endpoints)
"public": false,
"archived": null
}
},
{
"model": "process.worker",
<<<<<<< HEAD
"pk": "1a18dc1d-49e3-4724-b1e3-cbc8da483610",
"fields": {
"name": "Worker requiring a GPU",
......@@ -149,12 +293,48 @@
"type": "20d3065e-0ef7-428b-888f-177f59e6ddd0",
"description": "",
"repository": "e3f470b1-fc46-4bc1-8117-30e1c62962b7",
=======
"pk": "04ebb7e9-b8f8-4358-82cb-52bca4f2564b",
"fields": {
"name": "Document layout analyser",
"slug": "dla",
"type": "c2db222a-f974-4c20-979e-9e95e1a80ee7",
"description": "",
"repository": "565a09bb-0f64-49b5-acbf-8e5fde104cbb",
"public": false,
"archived": null
}
},
{
"model": "process.worker",
"pk": "232e3930-353b-4840-b570-7057166ab8a7",
"fields": {
"name": "Recognizer",
"slug": "reco",
"type": "3c93cbb2-97a1-4b0c-8ddf-98ee99760805",
"description": "",
"repository": "565a09bb-0f64-49b5-acbf-8e5fde104cbb",
"public": false,
"archived": null
}
},
{
"model": "process.worker",
"pk": "58c7ea56-3de0-4d49-bdc1-13d2d770202d",
"fields": {
"name": "Worker requiring a GPU",
"slug": "worker-gpu",
"type": "ea560a33-b00e-4fcb-a7fe-5d92827da405",
"description": "",
"repository": "565a09bb-0f64-49b5-acbf-8e5fde104cbb",
>>>>>>> 7912af40 (wip API endpoints)
"public": false,
"archived": null
}
},
{
"model": "process.worker",
<<<<<<< HEAD
"pk": "219444d1-2a84-49f4-94d6-d5c21e36fcb9",
"fields": {
"name": "Generic worker with a Model",
......@@ -173,6 +353,13 @@
"name": "Custom worker",
"slug": "custom",
"type": "64a618df-09d0-47eb-b999-02ceb0a114a4",
=======
"pk": "8cf9ad2e-20da-42b1-8486-1b9b76d094f6",
"fields": {
"name": "Custom worker",
"slug": "custom",
"type": "8f8a02cd-e97f-479c-96d1-8d019f31e25b",
>>>>>>> 7912af40 (wip API endpoints)
"description": "",
"repository": null,
"public": false,
......@@ -181,6 +368,7 @@
},
{
"model": "process.worker",
<<<<<<< HEAD
"pk": "9775f6a1-6238-4943-b245-b69bde621912",
"fields": {
"name": "Recognizer",
......@@ -201,12 +389,22 @@
"type": "3a0b2c85-f53f-4ce7-942d-37c08f356880",
"description": "",
"repository": "e3f470b1-fc46-4bc1-8117-30e1c62962b7",
=======
"pk": "de19f976-30a1-49bb-9dfb-a17300db9ccb",
"fields": {
"name": "File import",
"slug": "file_import",
"type": "1adb460c-149c-4b77-9d56-9a306ab49993",
"description": "",
"repository": "565a09bb-0f64-49b5-acbf-8e5fde104cbb",
>>>>>>> 7912af40 (wip API endpoints)
"public": false,
"archived": null
}
},
{
"model": "process.workertype",
<<<<<<< HEAD
"pk": "20d3065e-0ef7-428b-888f-177f59e6ddd0",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
......@@ -218,6 +416,9 @@
{
"model": "process.workertype",
"pk": "3a0b2c85-f53f-4ce7-942d-37c08f356880",
=======
"pk": "1adb460c-149c-4b77-9d56-9a306ab49993",
>>>>>>> 7912af40 (wip API endpoints)
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
......@@ -227,7 +428,11 @@
},
{
"model": "process.workertype",
<<<<<<< HEAD
"pk": "50729501-d9c4-473d-803f-a7cf25f0f9bd",
=======
"pk": "3c93cbb2-97a1-4b0c-8ddf-98ee99760805",
>>>>>>> 7912af40 (wip API endpoints)
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
......@@ -237,7 +442,11 @@
},
{
"model": "process.workertype",
<<<<<<< HEAD
"pk": "64a618df-09d0-47eb-b999-02ceb0a114a4",
=======
"pk": "8f8a02cd-e97f-479c-96d1-8d019f31e25b",
>>>>>>> 7912af40 (wip API endpoints)
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
......@@ -247,19 +456,118 @@
},
{
"model": "process.workertype",
<<<<<<< HEAD
"pk": "e84d4893-ae73-4162-acb6-13d606587644",
=======
"pk": "c2db222a-f974-4c20-979e-9e95e1a80ee7",
>>>>>>> 7912af40 (wip API endpoints)
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"slug": "dla",
"display_name": "Document Layout Analysis"
<<<<<<< HEAD
=======
}
},
{
"model": "process.workertype",
"pk": "ea560a33-b00e-4fcb-a7fe-5d92827da405",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"slug": "worker",
"display_name": "Worker requiring a GPU"
>>>>>>> 7912af40 (wip API endpoints)
}
},
{
"model": "process.workerversion",
<<<<<<< HEAD
"pk": "229fc630-728b-421b-a2de-9618bd8e401f",
"fields": {
"worker": "667a82ac-a19a-4e97-9239-35a3026246cb",
=======
"pk": "0b84a002-efce-4fd6-b4a6-999376df80fa",
"fields": {
"worker": "04ebb7e9-b8f8-4358-82cb-52bca4f2564b",
"revision": "174a7683-f6bb-402b-8ff5-3b22785f35a2",
"version": null,
"configuration": {
"test": 42
},
"state": "available",
"gpu_usage": "disabled",
"model_usage": "disabled",
"docker_image": "481b42e2-645c-47fe-937f-5b4431f10563",
"docker_image_iid": null,
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z"
}
},
{
"model": "process.workerversion",
"pk": "110fd472-59f4-43fa-a954-0a8dd776c86d",
"fields": {
"worker": "232e3930-353b-4840-b570-7057166ab8a7",
"revision": "174a7683-f6bb-402b-8ff5-3b22785f35a2",
"version": null,
"configuration": {
"test": 42
},
"state": "available",
"gpu_usage": "disabled",
"model_usage": "disabled",
"docker_image": "481b42e2-645c-47fe-937f-5b4431f10563",
"docker_image_iid": null,
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z"
}
},
{
"model": "process.workerversion",
"pk": "2800edff-4e74-4fd0-8f31-a01cddfa4c09",
"fields": {
"worker": "58c7ea56-3de0-4d49-bdc1-13d2d770202d",
"revision": "174a7683-f6bb-402b-8ff5-3b22785f35a2",
"version": null,
"configuration": {
"test": 42
},
"state": "available",
"gpu_usage": "required",
"model_usage": "disabled",
"docker_image": "481b42e2-645c-47fe-937f-5b4431f10563",
"docker_image_iid": null,
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z"
}
},
{
"model": "process.workerversion",
"pk": "5cc66882-dfda-4800-9422-8e0fb28e0287",
"fields": {
"worker": "049370f4-2328-40de-84a0-48e5bb45fcda",
"revision": "174a7683-f6bb-402b-8ff5-3b22785f35a2",
"version": null,
"configuration": {
"test": 42
},
"state": "available",
"gpu_usage": "disabled",
"model_usage": "required",
"docker_image": "481b42e2-645c-47fe-937f-5b4431f10563",
"docker_image_iid": null,
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z"
}
},
{
"model": "process.workerversion",
"pk": "6df3f42d-36fd-4483-8261-d2550938f66e",
"fields": {
"worker": "8cf9ad2e-20da-42b1-8486-1b9b76d094f6",
>>>>>>> 7912af40 (wip API endpoints)
"revision": null,
"version": 1,
"configuration": {
......@@ -276,6 +584,7 @@
},
{
"model": "process.workerversion",
<<<<<<< HEAD
"pk": "57cd018c-43e2-491e-9684-3b939df52921",
"fields": {
"worker": "df6dbbb2-0526-46f9-8da2-5ada8f93826a",
......@@ -354,6 +663,12 @@
"fields": {
"worker": "9775f6a1-6238-4943-b245-b69bde621912",
"revision": "2d087aa1-82ba-4ec5-af14-c19e4213f913",
=======
"pk": "728c1c89-5a6e-4dc9-85fb-4702b760c1f7",
"fields": {
"worker": "de19f976-30a1-49bb-9dfb-a17300db9ccb",
"revision": "174a7683-f6bb-402b-8ff5-3b22785f35a2",
>>>>>>> 7912af40 (wip API endpoints)
"version": null,
"configuration": {
"test": 42
......@@ -361,18 +676,60 @@
"state": "available",
"gpu_usage": "disabled",
"model_usage": "disabled",
<<<<<<< HEAD
"docker_image": null,
"docker_image_iid": "registry.somewhere.com/something:latest",
=======
"docker_image": "481b42e2-645c-47fe-937f-5b4431f10563",
"docker_image_iid": null,
>>>>>>> 7912af40 (wip API endpoints)
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z"
}
},
{
"model": "process.workerrun",
<<<<<<< HEAD
"pk": "14356945-e3a4-4d8b-b9b2-b4bc5e9287cc",
"fields": {
"process": "76506eee-43ab-4caa-966c-9e8e5d10ef93",
"version": "229fc630-728b-421b-a2de-9618bd8e401f",
=======
"pk": "baf81f6a-818a-484e-8d1a-a240b20ab9e3",
"fields": {
"process": "c914b228-86a6-434b-81d8-f78751f02cf1",
"version": "0b84a002-efce-4fd6-b4a6-999376df80fa",
"model_version": null,
"parents": "[]",
"configuration": null,
"summary": "Worker Document layout analyser @ 0b84a0",
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"has_results": false
}
},
{
"model": "process.workerrun",
"pk": "20c4817e-b999-41e0-a061-85deb7df73df",
"fields": {
"process": "c914b228-86a6-434b-81d8-f78751f02cf1",
"version": "110fd472-59f4-43fa-a954-0a8dd776c86d",
"model_version": null,
"parents": "[\"baf81f6a-818a-484e-8d1a-a240b20ab9e3\"]",
"configuration": null,
"summary": "Worker Recognizer @ 110fd4",
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"has_results": false
}
},
{
"model": "process.workerrun",
"pk": "81e444be-04be-47b6-b625-a3f2e61a4456",
"fields": {
"process": "432278f2-a60e-4865-b474-de83833d0497",
"version": "6df3f42d-36fd-4483-8261-d2550938f66e",
>>>>>>> 7912af40 (wip API endpoints)
"model_version": null,
"parents": "[]",
"configuration": null,
......@@ -384,6 +741,7 @@
},
{
"model": "process.workerrun",
<<<<<<< HEAD
"pk": "2f828b7f-c169-4a8e-9555-0b4060e05641",
"fields": {
"process": "7a6fed8c-ed9c-4714-8036-7048462ce0f2",
......@@ -418,6 +776,12 @@
"fields": {
"process": "b6b7dbcb-e134-4274-93fd-9d6d06818c6f",
"version": "229fc630-728b-421b-a2de-9618bd8e401f",
=======
"pk": "ed5aaec9-a928-42ab-8166-81fbe92e7959",
"fields": {
"process": "c992f023-baea-4c6d-92ba-e5bac0c2c0b4",
"version": "6df3f42d-36fd-4483-8261-d2550938f66e",
>>>>>>> 7912af40 (wip API endpoints)
"model_version": null,
"parents": "[]",
"configuration": null,
......@@ -429,7 +793,11 @@
},
{
"model": "documents.corpus",
<<<<<<< HEAD
"pk": "f34313ec-45ec-4ac4-92e5-43d7eb045c12",
=======
"pk": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
>>>>>>> 7912af40 (wip API endpoints)
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
......@@ -442,11 +810,16 @@
},
{
"model": "documents.elementtype",
<<<<<<< HEAD
"pk": "329625fb-1514-492a-9567-e231f7646648",
"fields": {
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12",
"slug": "page",
"display_name": "Page",
=======
"pk": "167b45fd-13a2-4ef8-b937-47f64e2665a8",
"fields": {
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"slug": "word",
"display_name": "Word",
"folder": false,
"indexable": false,
"color": "28b62c"
......@@ -454,23 +827,23 @@
},
{
"model": "documents.elementtype",
"pk": "ab1c133b-71d0-4928-b388-7c12345a8416",
"pk": "18027add-0729-400d-a225-60927f1dd2d9",
"fields": {
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12",
"slug": "text_line",
"display_name": "Line",
"folder": false,
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"slug": "volume",
"display_name": "Volume",
"folder": true,
"indexable": false,
"color": "28b62c"
}
},
{
"model": "documents.elementtype",
"pk": "c196f23a-6843-48e1-a885-c7cda27e64ca",
"pk": "1ca6552d-f876-4d2a-a167-38736ebed338",
"fields": {
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12",
"slug": "act",
"display_name": "Act",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"slug": "text_line",
"display_name": "Line",
"folder": false,
"indexable": false,
"color": "28b62c"
......@@ -478,10 +851,72 @@
},
{
"model": "documents.elementtype",
"pk": "d15930a5-ebb8-40aa-968d-8bd2cf504230",
"pk": "2bee95f7-e16e-41ae-a61d-51b9a22c3fa0",
"fields": {
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12",
"slug": "word",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"slug": "surface",
"display_name": "Surface",
"folder": false,
"indexable": false,
"color": "28b62c"
}
},
{
"model": "documents.elementtype",
"pk": "571f6a9b-e38b-4bd6-b22f-85bd66cc1a5e",
"fields": {
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"slug": "act",
"display_name": "Act",
"folder": false,
"indexable": false,
"color": "28b62c"
}
},
{
"model": "documents.elementtype",
"pk": "a8f287b7-31f2-491a-b13f-cd2aa0c461d4",
"fields": {
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
>>>>>>> 7912af40 (wip API endpoints)
"slug": "page",
"display_name": "Page",
"folder": false,
"indexable": false,
"color": "28b62c"
}
},
{
<<<<<<< HEAD
"model": "documents.elementtype",
"pk": "ab1c133b-71d0-4928-b388-7c12345a8416",
"fields": {
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12",
"slug": "text_line",
"display_name": "Line",
"folder": false,
"indexable": false,
"color": "28b62c"
}
},
{
"model": "documents.elementtype",
"pk": "c196f23a-6843-48e1-a885-c7cda27e64ca",
"fields": {
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12",
"slug": "act",
"display_name": "Act",
"folder": false,
"indexable": false,
"color": "28b62c"
}
},
{
"model": "documents.elementtype",
"pk": "d15930a5-ebb8-40aa-968d-8bd2cf504230",
"fields": {
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12",
"slug": "word",
"display_name": "Word",
"folder": false,
"indexable": false,
......@@ -518,65 +953,217 @@
"fields": {
"element": "9fc5e0a3-9afb-493e-bf0f-fc2998ba4ba4",
"path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\"]",
=======
"model": "documents.elementpath",
"pk": "00bd8cd6-1b43-4703-868a-f6ad29891fee",
"fields": {
"element": "e590e52a-11ec-4e27-b3b1-c67cc589ced8",
"path": "[\"6d6b7b80-6783-42ef-88ec-15bdbe8ffb65\", \"bdea4cf0-63bf-4918-b67d-b879d09f3c95\"]",
>>>>>>> 7912af40 (wip API endpoints)
"ordering": 0
}
},
{
"model": "documents.elementpath",
<<<<<<< HEAD
"pk": "156e125d-4550-4a72-a124-3b5e7fe25e77",
"fields": {
"element": "c8e488da-28d8-467e-a651-7d6f2ad6600d",
"path": "[\"2cd80ca1-7d55-4750-8c90-2b693e14a058\"]",
=======
"pk": "057773ab-6c41-4163-aca8-73e742087b50",
"fields": {
"element": "81938246-57ff-49ad-bc79-d07de4275096",
"path": "[\"6d6b7b80-6783-42ef-88ec-15bdbe8ffb65\", \"3dc4ff7a-9a40-431b-b692-a2b5af381ffd\"]",
"ordering": 1
}
},
{
"model": "documents.elementpath",
"pk": "05a8caeb-f351-4f3b-91c1-d0aff1ab9d73",
"fields": {
"element": "2f7f15c7-c39b-4164-aea0-050c2a0e9d34",
"path": "[\"6d6b7b80-6783-42ef-88ec-15bdbe8ffb65\", \"454b9f6d-8b0d-4313-baa3-82ccf8856d42\"]",
>>>>>>> 7912af40 (wip API endpoints)
"ordering": 2
}
},
{
"model": "documents.elementpath",
<<<<<<< HEAD
"pk": "17526830-1f55-41e1-82c5-6faf34831a0d",
"fields": {
"element": "7ea6161f-62f5-4bdf-9412-bbc4d13b3e6f",
"path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\", \"d9744e02-66ef-424e-a71c-88b94b209688\"]",
"ordering": 0
=======
"pk": "07cd2fbb-2cfd-4b53-86fe-d37fcc6d3bdb",
"fields": {
"element": "7c1ba0f5-1c2a-45d8-8ef1-6217e06e079b",
"path": "[\"6d6b7b80-6783-42ef-88ec-15bdbe8ffb65\", \"2a08be28-27f2-48f8-8d87-437893d389ca\"]",
"ordering": 0
}
},
{
"model": "documents.elementpath",
"pk": "0a010ead-3329-41fc-83a7-b7f2d6d847f2",
"fields": {
"element": "b46d402f-385c-42c8-bca3-4cf732c6b952",
"path": "[\"6d6b7b80-6783-42ef-88ec-15bdbe8ffb65\", \"f3a388d1-9968-4486-9e3b-e5a2a11947b1\"]",
"ordering": 0
}
},
{
"model": "documents.elementpath",
"pk": "1260e6b9-95e3-4667-abc6-d80ab1b6ecc5",
"fields": {
"element": "77ced3ba-7f04-48c7-b5fa-2b101d191c23",
"path": "[\"c348ff6e-786b-445a-a828-a693fb000fe8\"]",
"ordering": 1
>>>>>>> 7912af40 (wip API endpoints)
}
},
{
"model": "documents.elementpath",
<<<<<<< HEAD
"pk": "210c3ff2-1aac-4b1d-bcff-67a76b2bc4f9",
"fields": {
"element": "e7027313-7910-44b4-bdff-28e8d187c0b4",
"path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\"]",
"ordering": 5
=======
"pk": "221540c3-58b4-4839-b842-11dfbc608100",
"fields": {
"element": "fa35b384-692f-4b42-91ba-60d384ef251f",
"path": "[\"6d6b7b80-6783-42ef-88ec-15bdbe8ffb65\", \"1444e97e-4873-4731-9b75-79f931c9dc9e\"]",
"ordering": 1
>>>>>>> 7912af40 (wip API endpoints)
}
},
{
"model": "documents.elementpath",
<<<<<<< HEAD
"pk": "21af7d64-10db-43f4-a0dd-386be73314cd",
"fields": {
"element": "2df1881f-d666-43c9-8af7-507b277c4e23",
"path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\", \"02a6f67e-c7d4-4dec-b3a0-9f9ab3f2ee99\"]",
=======
"pk": "25f13dc7-3bc1-40cf-8c9e-342ca2bc8747",
"fields": {
"element": "454b9f6d-8b0d-4313-baa3-82ccf8856d42",
"path": "[\"6d6b7b80-6783-42ef-88ec-15bdbe8ffb65\"]",
>>>>>>> 7912af40 (wip API endpoints)
"ordering": 1
}
},
{
"model": "documents.elementpath",
<<<<<<< HEAD
"pk": "262709fc-3d1f-46e2-8ba5-5c63b8d2b96f",
"fields": {
"element": "d9744e02-66ef-424e-a71c-88b94b209688",
"path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\"]",
"ordering": 7
=======
"pk": "27ca92e0-f081-4ce4-b23a-cf1a1d5b7f13",
"fields": {
"element": "549a9a87-0632-4846-962d-7799147e0225",
"path": "[\"6d6b7b80-6783-42ef-88ec-15bdbe8ffb65\"]",
"ordering": 4
>>>>>>> 7912af40 (wip API endpoints)
}
},
{
"model": "documents.elementpath",
<<<<<<< HEAD
"pk": "32644adb-c33b-47bd-befe-f5d2142d60ee",
"fields": {
"element": "ec742315-a1e6-4cf2-96c0-abe2b0e0e3fc",
"path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\", \"9fc5e0a3-9afb-493e-bf0f-fc2998ba4ba4\"]",
=======
"pk": "2ed0a5dc-1c04-49c5-b62a-4f07d804e982",
"fields": {
"element": "1f8e08ad-ee8e-4924-a0b3-740722dfae47",
"path": "[\"6d6b7b80-6783-42ef-88ec-15bdbe8ffb65\", \"3dc4ff7a-9a40-431b-b692-a2b5af381ffd\"]",
"ordering": 0
}
},
{
"model": "documents.elementpath",
"pk": "3ceef7ee-c057-459b-b267-3e5f1de2d754",
"fields": {
"element": "d3b1f490-1ac8-430e-b0d3-eb617d90b900",
"path": "[\"6d6b7b80-6783-42ef-88ec-15bdbe8ffb65\", \"454b9f6d-8b0d-4313-baa3-82ccf8856d42\"]",
"ordering": 0
}
},
{
"model": "documents.elementpath",
"pk": "56e3e8b7-7d46-459f-a924-98201890e80b",
"fields": {
"element": "ffffc01b-7577-4a93-9148-02fdc1f80435",
"path": "[\"c348ff6e-786b-445a-a828-a693fb000fe8\"]",
"ordering": 0
}
},
{
"model": "documents.elementpath",
"pk": "6b97040b-ebdb-49b8-9702-367f55ab4e49",
"fields": {
"element": "6d6b7b80-6783-42ef-88ec-15bdbe8ffb65",
"path": "[]",
"ordering": 0
}
},
{
"model": "documents.elementpath",
"pk": "758e2947-eb09-4ac3-9deb-2ff8d910f6b8",
"fields": {
"element": "f3a388d1-9968-4486-9e3b-e5a2a11947b1",
"path": "[\"6d6b7b80-6783-42ef-88ec-15bdbe8ffb65\"]",
"ordering": 3
}
},
{
"model": "documents.elementpath",
"pk": "78069f17-72aa-49c5-a433-2286c4bef207",
"fields": {
"element": "bdea4cf0-63bf-4918-b67d-b879d09f3c95",
"path": "[\"6d6b7b80-6783-42ef-88ec-15bdbe8ffb65\"]",
"ordering": 6
}
},
{
"model": "documents.elementpath",
"pk": "78817bcc-fb50-445a-8fdf-7f0812f2d4f0",
"fields": {
"element": "a9c73703-3711-46ac-957f-25f9bb77af76",
"path": "[\"6d6b7b80-6783-42ef-88ec-15bdbe8ffb65\", \"454b9f6d-8b0d-4313-baa3-82ccf8856d42\"]",
"ordering": 1
}
},
{
"model": "documents.elementpath",
"pk": "9a7a9ea5-1d70-4159-a1cd-76cd03cd1bd3",
"fields": {
"element": "416d13a8-4a15-4641-9b68-36862e80c176",
"path": "[\"6d6b7b80-6783-42ef-88ec-15bdbe8ffb65\", \"549a9a87-0632-4846-962d-7799147e0225\"]",
"ordering": 1
}
},
{
"model": "documents.elementpath",
"pk": "a15f789f-d2aa-43af-b66b-a437ad37c9a2",
"fields": {
"element": "39d46933-549e-40cc-93e4-3535db7ad8a0",
"path": "[\"6d6b7b80-6783-42ef-88ec-15bdbe8ffb65\", \"3dc4ff7a-9a40-431b-b692-a2b5af381ffd\"]",
>>>>>>> 7912af40 (wip API endpoints)
"ordering": 2
}
},
{
"model": "documents.elementpath",
<<<<<<< HEAD
"pk": "3a86e5d2-3c7c-474f-82b1-60dae09a82b4",
"fields": {
"element": "dc66eac3-a4e9-4c55-a4a8-d239bd79f3f6",
......@@ -590,29 +1177,60 @@
"fields": {
"element": "b8d9cf10-dc77-4a41-90f8-badf9718ebb9",
"path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\", \"f530bd2f-d0ab-4f14-9d98-087486c4b1ab\"]",
=======
"pk": "ad4f56ef-cccc-4dc3-8922-5fa338e93fa2",
"fields": {
"element": "1145ba8e-4bd5-4f2f-8bb1-c307295d88a0",
"path": "[\"6d6b7b80-6783-42ef-88ec-15bdbe8ffb65\", \"549a9a87-0632-4846-962d-7799147e0225\"]",
>>>>>>> 7912af40 (wip API endpoints)
"ordering": 0
}
},
{
"model": "documents.elementpath",
<<<<<<< HEAD
"pk": "650ef880-9d63-4164-8d50-b7dff16ca738",
"fields": {
"element": "aec1257f-bcbe-41d5-8983-966da539e912",
"path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\", \"e7027313-7910-44b4-bdff-28e8d187c0b4\"]",
=======
"pk": "b6418b10-676e-4928-9552-921f8de4805e",
"fields": {
"element": "3dc4ff7a-9a40-431b-b692-a2b5af381ffd",
"path": "[\"6d6b7b80-6783-42ef-88ec-15bdbe8ffb65\"]",
"ordering": 2
}
},
{
"model": "documents.elementpath",
"pk": "c4abc40a-c4e2-4910-b62e-7bc95ea064f3",
"fields": {
"element": "2ef2d52a-0316-4eb6-a3f4-a48c4e25ce7c",
"path": "[\"6d6b7b80-6783-42ef-88ec-15bdbe8ffb65\", \"1444e97e-4873-4731-9b75-79f931c9dc9e\"]",
>>>>>>> 7912af40 (wip API endpoints)
"ordering": 0
}
},
{
"model": "documents.elementpath",
<<<<<<< HEAD
"pk": "666416c1-5aa0-4f57-a21f-b7585b10efd2",
"fields": {
"element": "f75ca797-0067-4711-b899-6ed39b0a6f1a",
"path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\"]",
"ordering": 4
=======
"pk": "d4439a5a-5934-4b5a-b956-853ea89dd8d4",
"fields": {
"element": "9e7e2de2-e970-4e4f-81e7-b90008d474c0",
"path": "[\"6d6b7b80-6783-42ef-88ec-15bdbe8ffb65\", \"eed5499a-e95f-4f06-baa0-145d917a5b0c\"]",
"ordering": 0
>>>>>>> 7912af40 (wip API endpoints)
}
},
{
"model": "documents.elementpath",
<<<<<<< HEAD
"pk": "6f42e63d-d4ba-495b-8e22-e059577c669f",
"fields": {
"element": "f530bd2f-d0ab-4f14-9d98-087486c4b1ab",
......@@ -626,19 +1244,78 @@
"fields": {
"element": "39210eb6-70a9-4660-8a45-5c6957508936",
"path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\"]",
=======
"pk": "d5d57a9e-97fb-401f-a128-5fc524946c0e",
"fields": {
"element": "ee161939-65e6-4e1f-be80-ea142dfb0c60",
"path": "[\"6d6b7b80-6783-42ef-88ec-15bdbe8ffb65\", \"1444e97e-4873-4731-9b75-79f931c9dc9e\"]",
>>>>>>> 7912af40 (wip API endpoints)
"ordering": 3
}
},
{
"model": "documents.elementpath",
<<<<<<< HEAD
"pk": "733ddae3-62e2-433a-b322-41bb6502ac93",
"fields": {
"element": "34cd2540-0a05-4812-add5-f24c08d46f73",
"path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\", \"1d0f7ea6-6455-4a8d-ade2-a853f8ab7e08\"]",
=======
"pk": "deb7d260-5c5c-4159-9eeb-4f98e39e1a56",
"fields": {
"element": "c348ff6e-786b-445a-a828-a693fb000fe8",
"path": "[]",
"ordering": 0
}
},
{
"model": "documents.elementpath",
"pk": "ed85c4fa-f853-428c-bd3e-f084e9274f50",
"fields": {
"element": "6953caa3-b8bb-46a8-a222-1f386ff539f5",
"path": "[\"6d6b7b80-6783-42ef-88ec-15bdbe8ffb65\", \"1444e97e-4873-4731-9b75-79f931c9dc9e\"]",
"ordering": 2
}
},
{
"model": "documents.elementpath",
"pk": "f59638f1-17e6-4715-9672-8832bd12c5fb",
"fields": {
"element": "eed5499a-e95f-4f06-baa0-145d917a5b0c",
"path": "[\"6d6b7b80-6783-42ef-88ec-15bdbe8ffb65\"]",
"ordering": 5
}
},
{
"model": "documents.elementpath",
"pk": "f663a425-1981-4c25-9e3c-123a1a025db5",
"fields": {
"element": "2a08be28-27f2-48f8-8d87-437893d389ca",
"path": "[\"6d6b7b80-6783-42ef-88ec-15bdbe8ffb65\"]",
"ordering": 7
}
},
{
"model": "documents.elementpath",
"pk": "ff0bca17-626f-4671-bc4e-70a9f44ad702",
"fields": {
"element": "97394f5f-6146-42be-8038-0d735e12d5f1",
"path": "[\"c348ff6e-786b-445a-a828-a693fb000fe8\"]",
"ordering": 2
}
},
{
"model": "documents.elementpath",
"pk": "ff852e37-1ca6-43dd-b47a-c4530c0d46c1",
"fields": {
"element": "1444e97e-4873-4731-9b75-79f931c9dc9e",
"path": "[\"6d6b7b80-6783-42ef-88ec-15bdbe8ffb65\"]",
>>>>>>> 7912af40 (wip API endpoints)
"ordering": 0
}
},
{
<<<<<<< HEAD
"model": "documents.elementpath",
"pk": "79ecb1ed-8036-4e88-a659-605fb3b5c8aa",
"fields": {
......@@ -844,6 +1521,21 @@
"worker_run": null,
"image": "f5ddf7e0-3dd3-4f4f-ada6-f42de7be869d",
"polygon": "LINEARRING (700 700, 700 800, 800 800, 800 700, 700 700)",
=======
"model": "documents.element",
"pk": "1145ba8e-4bd5-4f2f-8bb1-c307295d88a0",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "2bee95f7-e16e-41ae-a61d-51b9a22c3fa0",
"name": "Surface B",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": "4e80d190-2343-4e72-b60f-fda6b3d70b0d",
"polygon": "LINEARRING (600 600, 600 1000, 1000 1000, 1000 600, 600 600)",
>>>>>>> 7912af40 (wip API endpoints)
"rotation_angle": 0,
"mirrored": false,
"confidence": null
......@@ -851,6 +1543,7 @@
},
{
"model": "documents.element",
<<<<<<< HEAD
"pk": "2cd80ca1-7d55-4750-8c90-2b693e14a058",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
......@@ -858,6 +1551,53 @@
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12",
"type": "e28100cb-49a4-4837-a9ae-81a519ebb43f",
"name": "Volume 2",
=======
"pk": "1444e97e-4873-4731-9b75-79f931c9dc9e",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "a8f287b7-31f2-491a-b13f-cd2aa0c461d4",
"name": "Volume 1, page 1r",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": "4e80d190-2343-4e72-b60f-fda6b3d70b0d",
"polygon": "LINEARRING (0 0, 0 1000, 1000 1000, 1000 0, 0 0)",
"rotation_angle": 0,
"mirrored": false,
"confidence": null
}
},
{
"model": "documents.element",
"pk": "1f8e08ad-ee8e-4924-a0b3-740722dfae47",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "167b45fd-13a2-4ef8-b937-47f64e2665a8",
"name": "PARIS",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": "40210c9c-bf96-4364-a715-17ca2cf675cc",
"polygon": "LINEARRING (100 100, 100 200, 200 200, 200 100, 100 100)",
"rotation_angle": 0,
"mirrored": false,
"confidence": null
}
},
{
"model": "documents.element",
"pk": "2a08be28-27f2-48f8-8d87-437893d389ca",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "571f6a9b-e38b-4bd6-b22f-85bd66cc1a5e",
"name": "Act 5",
>>>>>>> 7912af40 (wip API endpoints)
"creator": null,
"worker_version": null,
"worker_run": null,
......@@ -870,6 +1610,7 @@
},
{
"model": "documents.element",
<<<<<<< HEAD
"pk": "2df1881f-d666-43c9-8af7-507b277c4e23",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
......@@ -882,6 +1623,20 @@
"worker_run": null,
"image": "a38b69a3-a4f8-4dfc-a6b9-38ea2e52c713",
"polygon": "LINEARRING (400 400, 400 500, 500 500, 500 400, 400 400)",
=======
"pk": "2ef2d52a-0316-4eb6-a3f4-a48c4e25ce7c",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "167b45fd-13a2-4ef8-b937-47f64e2665a8",
"name": "PARIS",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": "4e80d190-2343-4e72-b60f-fda6b3d70b0d",
"polygon": "LINEARRING (100 100, 100 200, 200 200, 200 100, 100 100)",
>>>>>>> 7912af40 (wip API endpoints)
"rotation_angle": 0,
"mirrored": false,
"confidence": null
......@@ -889,17 +1644,30 @@
},
{
"model": "documents.element",
<<<<<<< HEAD
"pk": "2e8101c4-6fca-49b6-9b7b-41554facfa01",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12",
"type": "d15930a5-ebb8-40aa-968d-8bd2cf504230",
=======
"pk": "2f7f15c7-c39b-4164-aea0-050c2a0e9d34",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "167b45fd-13a2-4ef8-b937-47f64e2665a8",
>>>>>>> 7912af40 (wip API endpoints)
"name": "DATUM",
"creator": null,
"worker_version": null,
"worker_run": null,
<<<<<<< HEAD
"image": "a38b69a3-a4f8-4dfc-a6b9-38ea2e52c713",
=======
"image": "bd7d9ffd-013c-4970-9df8-1d18bbe88bd5",
>>>>>>> 7912af40 (wip API endpoints)
"polygon": "LINEARRING (700 700, 700 800, 800 800, 800 700, 700 700)",
"rotation_angle": 0,
"mirrored": false,
......@@ -908,6 +1676,7 @@
},
{
"model": "documents.element",
<<<<<<< HEAD
"pk": "344f6b5b-b001-4084-950c-1925fdd2eef4",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
......@@ -920,6 +1689,20 @@
"worker_run": null,
"image": "f250d3f3-bd56-4a2f-bffc-fc3a33cd1902",
"polygon": "LINEARRING (100 100, 100 200, 200 200, 200 100, 100 100)",
=======
"pk": "39d46933-549e-40cc-93e4-3535db7ad8a0",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "167b45fd-13a2-4ef8-b937-47f64e2665a8",
"name": "DATUM",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": "40210c9c-bf96-4364-a715-17ca2cf675cc",
"polygon": "LINEARRING (700 700, 700 800, 800 800, 800 700, 700 700)",
>>>>>>> 7912af40 (wip API endpoints)
"rotation_angle": 0,
"mirrored": false,
"confidence": null
......@@ -927,6 +1710,7 @@
},
{
"model": "documents.element",
<<<<<<< HEAD
"pk": "34cd2540-0a05-4812-add5-f24c08d46f73",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
......@@ -939,6 +1723,20 @@
"worker_run": null,
"image": "a38b69a3-a4f8-4dfc-a6b9-38ea2e52c713",
"polygon": "LINEARRING (300 300, 300 600, 600 600, 600 300, 300 300)",
=======
"pk": "3dc4ff7a-9a40-431b-b692-a2b5af381ffd",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "a8f287b7-31f2-491a-b13f-cd2aa0c461d4",
"name": "Volume 1, page 2r",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": "40210c9c-bf96-4364-a715-17ca2cf675cc",
"polygon": "LINEARRING (0 0, 0 1000, 1000 1000, 1000 0, 0 0)",
>>>>>>> 7912af40 (wip API endpoints)
"rotation_angle": 0,
"mirrored": false,
"confidence": null
......@@ -946,6 +1744,7 @@
},
{
"model": "documents.element",
<<<<<<< HEAD
"pk": "39210eb6-70a9-4660-8a45-5c6957508936",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
......@@ -953,11 +1752,19 @@
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12",
"type": "c196f23a-6843-48e1-a885-c7cda27e64ca",
"name": "Act 1",
=======
"pk": "416d13a8-4a15-4641-9b68-36862e80c176",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "2bee95f7-e16e-41ae-a61d-51b9a22c3fa0",
"name": "Surface C",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": null,
"polygon": null,
"image": "bd7d9ffd-013c-4970-9df8-1d18bbe88bd5",
"polygon": "LINEARRING (0 0, 0 1000, 1000 1000, 1000 0, 0 0)",
"rotation_angle": 0,
"mirrored": false,
"confidence": null
......@@ -965,7 +1772,47 @@
},
{
"model": "documents.element",
"pk": "4fed0e6a-9e3f-4e59-9c70-c5e74cc6d73c",
"pk": "454b9f6d-8b0d-4313-baa3-82ccf8856d42",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "a8f287b7-31f2-491a-b13f-cd2aa0c461d4",
"name": "Volume 1, page 1v",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": "bd7d9ffd-013c-4970-9df8-1d18bbe88bd5",
"polygon": "LINEARRING (0 0, 0 1000, 1000 1000, 1000 0, 0 0)",
"rotation_angle": 0,
"mirrored": false,
"confidence": null
}
},
{
"model": "documents.element",
"pk": "549a9a87-0632-4846-962d-7799147e0225",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "571f6a9b-e38b-4bd6-b22f-85bd66cc1a5e",
"name": "Act 2",
>>>>>>> 7912af40 (wip API endpoints)
"creator": null,
"worker_version": null,
"worker_run": null,
"image": null,
"polygon": null,
"rotation_angle": 0,
"mirrored": false,
"confidence": null
}
},
{
"model": "documents.element",
<<<<<<< HEAD
"pk": "4fed0e6a-9e3f-4e59-9c70-c5e74cc6d73c",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
......@@ -996,6 +1843,20 @@
"worker_run": null,
"image": "a38b69a3-a4f8-4dfc-a6b9-38ea2e52c713",
"polygon": "LINEARRING (600 600, 600 1000, 1000 1000, 1000 600, 600 600)",
=======
"pk": "6953caa3-b8bb-46a8-a222-1f386ff539f5",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "167b45fd-13a2-4ef8-b937-47f64e2665a8",
"name": "DATUM",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": "4e80d190-2343-4e72-b60f-fda6b3d70b0d",
"polygon": "LINEARRING (700 700, 700 800, 800 800, 800 700, 700 700)",
>>>>>>> 7912af40 (wip API endpoints)
"rotation_angle": 0,
"mirrored": false,
"confidence": null
......@@ -1003,6 +1864,7 @@
},
{
"model": "documents.element",
<<<<<<< HEAD
"pk": "86304b47-3d6a-48dd-a903-d0e09cde91ba",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
......@@ -1200,6 +2062,15 @@
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12",
"type": "c196f23a-6843-48e1-a885-c7cda27e64ca",
"name": "Act 5",
=======
"pk": "6d6b7b80-6783-42ef-88ec-15bdbe8ffb65",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "18027add-0729-400d-a225-60927f1dd2d9",
"name": "Volume 1",
>>>>>>> 7912af40 (wip API endpoints)
"creator": null,
"worker_version": null,
"worker_run": null,
......@@ -1212,6 +2083,7 @@
},
{
"model": "documents.element",
<<<<<<< HEAD
"pk": "dc66eac3-a4e9-4c55-a4a8-d239bd79f3f6",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
......@@ -1322,10 +2194,322 @@
"rotation_angle": 0,
"mirrored": false,
"confidence": null
=======
"pk": "77ced3ba-7f04-48c7-b5fa-2b101d191c23",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "a8f287b7-31f2-491a-b13f-cd2aa0c461d4",
"name": "Volume 2, page 1v",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": "d9c10a6b-6d15-4d60-a934-15a79d0b0bce",
"polygon": "LINEARRING (0 0, 0 1000, 1000 1000, 1000 0, 0 0)",
"rotation_angle": 0,
"mirrored": false,
"confidence": null
}
},
{
"model": "documents.element",
"pk": "7c1ba0f5-1c2a-45d8-8ef1-6217e06e079b",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "2bee95f7-e16e-41ae-a61d-51b9a22c3fa0",
"name": "Surface F",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": "40210c9c-bf96-4364-a715-17ca2cf675cc",
"polygon": "LINEARRING (600 600, 600 1000, 1000 1000, 1000 600, 600 600)",
"rotation_angle": 0,
"mirrored": false,
"confidence": null
}
},
{
"model": "documents.element",
"pk": "81938246-57ff-49ad-bc79-d07de4275096",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "167b45fd-13a2-4ef8-b937-47f64e2665a8",
"name": "ROY",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": "40210c9c-bf96-4364-a715-17ca2cf675cc",
"polygon": "LINEARRING (400 400, 400 500, 500 500, 500 400, 400 400)",
"rotation_angle": 0,
"mirrored": false,
"confidence": null
}
},
{
"model": "documents.element",
"pk": "97394f5f-6146-42be-8038-0d735e12d5f1",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "a8f287b7-31f2-491a-b13f-cd2aa0c461d4",
"name": "Volume 2, page 2r",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": "a6d3f3bc-986d-4618-8a87-fb1b86d9b866",
"polygon": "LINEARRING (0 0, 0 1000, 1000 1000, 1000 0, 0 0)",
"rotation_angle": 0,
"mirrored": false,
"confidence": null
}
},
{
"model": "documents.element",
"pk": "9e7e2de2-e970-4e4f-81e7-b90008d474c0",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "2bee95f7-e16e-41ae-a61d-51b9a22c3fa0",
"name": "Surface D",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": "40210c9c-bf96-4364-a715-17ca2cf675cc",
"polygon": "LINEARRING (0 0, 0 300, 300 300, 300 0, 0 0)",
"rotation_angle": 0,
"mirrored": false,
"confidence": null
}
},
{
"model": "documents.element",
"pk": "a9c73703-3711-46ac-957f-25f9bb77af76",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "167b45fd-13a2-4ef8-b937-47f64e2665a8",
"name": "ROY",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": "bd7d9ffd-013c-4970-9df8-1d18bbe88bd5",
"polygon": "LINEARRING (400 400, 400 500, 500 500, 500 400, 400 400)",
"rotation_angle": 0,
"mirrored": false,
"confidence": null
}
},
{
"model": "documents.element",
"pk": "b46d402f-385c-42c8-bca3-4cf732c6b952",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "2bee95f7-e16e-41ae-a61d-51b9a22c3fa0",
"name": "Surface A",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": "4e80d190-2343-4e72-b60f-fda6b3d70b0d",
"polygon": "LINEARRING (0 0, 0 600, 600 600, 600 0, 0 0)",
"rotation_angle": 0,
"mirrored": false,
"confidence": null
}
},
{
"model": "documents.element",
"pk": "bdea4cf0-63bf-4918-b67d-b879d09f3c95",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "571f6a9b-e38b-4bd6-b22f-85bd66cc1a5e",
"name": "Act 4",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": null,
"polygon": null,
"rotation_angle": 0,
"mirrored": false,
"confidence": null
}
},
{
"model": "documents.element",
"pk": "c348ff6e-786b-445a-a828-a693fb000fe8",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "18027add-0729-400d-a225-60927f1dd2d9",
"name": "Volume 2",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": null,
"polygon": null,
"rotation_angle": 0,
"mirrored": false,
"confidence": null
}
},
{
"model": "documents.element",
"pk": "d3b1f490-1ac8-430e-b0d3-eb617d90b900",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "167b45fd-13a2-4ef8-b937-47f64e2665a8",
"name": "PARIS",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": "bd7d9ffd-013c-4970-9df8-1d18bbe88bd5",
"polygon": "LINEARRING (100 100, 100 200, 200 200, 200 100, 100 100)",
"rotation_angle": 0,
"mirrored": false,
"confidence": null
}
},
{
"model": "documents.element",
"pk": "e590e52a-11ec-4e27-b3b1-c67cc589ced8",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "2bee95f7-e16e-41ae-a61d-51b9a22c3fa0",
"name": "Surface E",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": "40210c9c-bf96-4364-a715-17ca2cf675cc",
"polygon": "LINEARRING (300 300, 300 600, 600 600, 600 300, 300 300)",
"rotation_angle": 0,
"mirrored": false,
"confidence": null
}
},
{
"model": "documents.element",
"pk": "ee161939-65e6-4e1f-be80-ea142dfb0c60",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "1ca6552d-f876-4d2a-a167-38736ebed338",
"name": "Text line",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": "4e80d190-2343-4e72-b60f-fda6b3d70b0d",
"polygon": "LINEARRING (400 400, 400 500, 500 500, 500 400, 400 400)",
"rotation_angle": 0,
"mirrored": false,
"confidence": null
}
},
{
"model": "documents.element",
"pk": "eed5499a-e95f-4f06-baa0-145d917a5b0c",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "571f6a9b-e38b-4bd6-b22f-85bd66cc1a5e",
"name": "Act 3",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": null,
"polygon": null,
"rotation_angle": 0,
"mirrored": false,
"confidence": null
}
},
{
"model": "documents.element",
"pk": "f3a388d1-9968-4486-9e3b-e5a2a11947b1",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "571f6a9b-e38b-4bd6-b22f-85bd66cc1a5e",
"name": "Act 1",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": null,
"polygon": null,
"rotation_angle": 0,
"mirrored": false,
"confidence": null
}
},
{
"model": "documents.element",
"pk": "fa35b384-692f-4b42-91ba-60d384ef251f",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "167b45fd-13a2-4ef8-b937-47f64e2665a8",
"name": "ROY",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": "4e80d190-2343-4e72-b60f-fda6b3d70b0d",
"polygon": "LINEARRING (400 400, 400 500, 500 500, 500 400, 400 400)",
"rotation_angle": 0,
"mirrored": false,
"confidence": null
}
},
{
"model": "documents.element",
"pk": "ffffc01b-7577-4a93-9148-02fdc1f80435",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "a8f287b7-31f2-491a-b13f-cd2aa0c461d4",
"name": "Volume 2, page 1r",
"creator": null,
"worker_version": null,
"worker_run": null,
"image": "0e219e81-b8ab-484b-a8f2-cb848a9c8b45",
"polygon": "LINEARRING (0 0, 0 1000, 1000 1000, 1000 0, 0 0)",
"rotation_angle": 0,
"mirrored": false,
"confidence": null
}
},
{
"model": "documents.entitytype",
"pk": "270158cd-aaa6-46c6-b62f-036cdcc77e9b",
"fields": {
"name": "person",
"color": "ff0000",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9"
>>>>>>> 7912af40 (wip API endpoints)
}
},
{
"model": "documents.entitytype",
<<<<<<< HEAD
"pk": "0199d0f3-a2e6-4422-9202-2be9fe6d9dff",
"fields": {
"name": "number",
......@@ -1349,44 +2533,174 @@
"name": "organization",
"color": "ff0000",
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12"
=======
"pk": "2cb12ff7-fc14-4d6b-a0dd-0845333171f5",
"fields": {
"name": "organization",
"color": "ff0000",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9"
>>>>>>> 7912af40 (wip API endpoints)
}
},
{
"model": "documents.entitytype",
<<<<<<< HEAD
"pk": "7051555a-449f-4ebb-a519-f5b65517a520",
"fields": {
"name": "person",
"color": "ff0000",
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12"
=======
"pk": "67190699-79a4-4f85-aaed-60e05adefd1a",
"fields": {
"name": "number",
"color": "ff0000",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9"
>>>>>>> 7912af40 (wip API endpoints)
}
},
{
"model": "documents.entitytype",
<<<<<<< HEAD
"pk": "c6cb242c-688d-484f-87d1-42cabd41f67f",
"fields": {
"name": "date",
"color": "ff0000",
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12"
=======
"pk": "a5e2132e-f991-4ed9-ad10-a9fabd1401df",
"fields": {
"name": "date",
"color": "ff0000",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9"
}
},
{
"model": "documents.entitytype",
"pk": "feaa7348-a77e-4af7-9763-2ca98b22c623",
"fields": {
"name": "location",
"color": "ff0000",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9"
>>>>>>> 7912af40 (wip API endpoints)
}
},
{
"model": "documents.transcription",
<<<<<<< HEAD
"pk": "05882194-0210-441a-a167-f0b58cca0d2e",
"fields": {
"element": "2df1881f-d666-43c9-8af7-507b277c4e23",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60",
"worker_run": null,
"text": "ROY",
"orientation": "horizontal-lr",
"confidence": 1.0
}
},
{
"model": "documents.transcription",
"pk": "29dca1b6-8661-4bb5-933f-0b05ac7c30bb",
"fields": {
"element": "86304b47-3d6a-48dd-a903-d0e09cde91ba",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60",
"worker_run": null,
"text": "ROY",
"orientation": "horizontal-lr",
"confidence": 1.0
}
},
{
"model": "documents.transcription",
"pk": "413a4b08-c496-4925-a440-e9edad4a9dc1",
"fields": {
"element": "b8d9cf10-dc77-4a41-90f8-badf9718ebb9",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60",
"worker_run": null,
"text": "PARIS",
"orientation": "horizontal-lr",
"confidence": 1.0
}
},
{
"model": "documents.transcription",
"pk": "5107512b-9bda-4f59-98e0-a0ff40c76d11",
"fields": {
"element": "ec742315-a1e6-4cf2-96c0-abe2b0e0e3fc",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60",
"worker_run": null,
"text": "DATUM",
"orientation": "horizontal-lr",
"confidence": 1.0
}
},
{
"model": "documents.transcription",
"pk": "5b4bd0f0-63fa-43d1-970f-a79c44784392",
"fields": {
"element": "344f6b5b-b001-4084-950c-1925fdd2eef4",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60",
"worker_run": null,
"text": "PARIS",
"orientation": "horizontal-lr",
"confidence": 1.0
}
},
{
"model": "documents.transcription",
"pk": "7e865edb-f16e-4406-a497-682e5a946593",
"fields": {
"element": "9fc5e0a3-9afb-493e-bf0f-fc2998ba4ba4",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60",
=======
"pk": "0028aefa-a8d3-4a0f-8634-6d1f0b619bb1",
"fields": {
"element": "1444e97e-4873-4731-9b75-79f931c9dc9e",
"worker_version": "110fd472-59f4-43fa-a954-0a8dd776c86d",
>>>>>>> 7912af40 (wip API endpoints)
"worker_run": null,
"text": "Lorem ipsum dolor sit amet",
"orientation": "horizontal-lr",
"confidence": 1.0
}
},
{
"model": "documents.transcription",
<<<<<<< HEAD
"pk": "b3ec03c1-fa36-4347-b3ad-64abf63ce10c",
"fields": {
"element": "2039b7b8-15cb-4b1f-a9e6-c681aa20e13a",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60",
"worker_run": null,
"text": "DATUM",
"orientation": "horizontal-lr",
"confidence": 1.0
}
},
{
"model": "documents.transcription",
"pk": "05882194-0210-441a-a167-f0b58cca0d2e",
"pk": "bf9dddc1-c158-487c-99b4-37e0f7f44759",
"fields": {
"element": "2df1881f-d666-43c9-8af7-507b277c4e23",
"element": "4fed0e6a-9e3f-4e59-9c70-c5e74cc6d73c",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60",
"worker_run": null,
"text": "ROY",
"text": "PARIS",
"orientation": "horizontal-lr",
"confidence": 1.0
}
},
{
"model": "documents.transcription",
"pk": "29dca1b6-8661-4bb5-933f-0b05ac7c30bb",
"pk": "e1978d01-9182-4a42-a76f-7ae776aaaf55",
"fields": {
"element": "86304b47-3d6a-48dd-a903-d0e09cde91ba",
"element": "e9aa6eb2-eb0b-4503-9bbf-c3d27b9cce5f",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60",
=======
"pk": "3db65ed1-320a-4008-a887-747e3a3c6add",
"fields": {
"element": "a9c73703-3711-46ac-957f-25f9bb77af76",
"worker_version": "110fd472-59f4-43fa-a954-0a8dd776c86d",
>>>>>>> 7912af40 (wip API endpoints)
"worker_run": null,
"text": "ROY",
"orientation": "horizontal-lr",
......@@ -1395,10 +2709,16 @@
},
{
"model": "documents.transcription",
"pk": "413a4b08-c496-4925-a440-e9edad4a9dc1",
<<<<<<< HEAD
"pk": "f5b81d19-ebb7-412d-9deb-455d72aaf829",
"fields": {
"element": "b8d9cf10-dc77-4a41-90f8-badf9718ebb9",
"element": "2e8101c4-6fca-49b6-9b7b-41554facfa01",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60",
=======
"pk": "5e252d09-6240-43fe-b531-ea5f8d150c91",
"fields": {
"element": "d3b1f490-1ac8-430e-b0d3-eb617d90b900",
"worker_version": "110fd472-59f4-43fa-a954-0a8dd776c86d",
"worker_run": null,
"text": "PARIS",
"orientation": "horizontal-lr",
......@@ -1407,46 +2727,55 @@
},
{
"model": "documents.transcription",
"pk": "5107512b-9bda-4f59-98e0-a0ff40c76d11",
"pk": "6fb2d310-d2ce-4de8-89fc-2af120735fc1",
"fields": {
"element": "ec742315-a1e6-4cf2-96c0-abe2b0e0e3fc",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60",
"element": "2ef2d52a-0316-4eb6-a3f4-a48c4e25ce7c",
"worker_version": "110fd472-59f4-43fa-a954-0a8dd776c86d",
"worker_run": null,
"text": "DATUM",
"text": "PARIS",
"orientation": "horizontal-lr",
"confidence": 1.0
}
},
{
"model": "documents.transcription",
"pk": "5b4bd0f0-63fa-43d1-970f-a79c44784392",
"pk": "9fd17563-7f50-4073-b286-42ddf7e47fcc",
"fields": {
"element": "344f6b5b-b001-4084-950c-1925fdd2eef4",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60",
"element": "39d46933-549e-40cc-93e4-3535db7ad8a0",
"worker_version": "110fd472-59f4-43fa-a954-0a8dd776c86d",
>>>>>>> 7912af40 (wip API endpoints)
"worker_run": null,
"text": "PARIS",
"text": "DATUM",
"orientation": "horizontal-lr",
"confidence": 1.0
}
},
{
<<<<<<< HEAD
"model": "documents.allowedmetadata",
"pk": "6437fdd1-97c0-4fff-a325-039d0379bdbe",
"fields": {
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12",
"type": "text",
"name": "folio"
=======
"model": "documents.transcription",
"pk": "7e865edb-f16e-4406-a497-682e5a946593",
"pk": "b1260aaa-bcba-43ed-bab9-27a6effa99e0",
"fields": {
"element": "9fc5e0a3-9afb-493e-bf0f-fc2998ba4ba4",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60",
"element": "1f8e08ad-ee8e-4924-a0b3-740722dfae47",
"worker_version": "110fd472-59f4-43fa-a954-0a8dd776c86d",
"worker_run": null,
"text": "Lorem ipsum dolor sit amet",
"text": "PARIS",
"orientation": "horizontal-lr",
"confidence": 1.0
}
},
{
"model": "documents.transcription",
"pk": "b3ec03c1-fa36-4347-b3ad-64abf63ce10c",
"pk": "b58a6fca-0ef0-4a9a-b020-cfc5d2bf0c38",
"fields": {
"element": "2039b7b8-15cb-4b1f-a9e6-c681aa20e13a",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60",
"element": "2f7f15c7-c39b-4164-aea0-050c2a0e9d34",
"worker_version": "110fd472-59f4-43fa-a954-0a8dd776c86d",
"worker_run": null,
"text": "DATUM",
"orientation": "horizontal-lr",
......@@ -1455,22 +2784,22 @@
},
{
"model": "documents.transcription",
"pk": "bf9dddc1-c158-487c-99b4-37e0f7f44759",
"pk": "bfa7949c-ad04-4c20-a92f-2e67006c4b5e",
"fields": {
"element": "4fed0e6a-9e3f-4e59-9c70-c5e74cc6d73c",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60",
"element": "81938246-57ff-49ad-bc79-d07de4275096",
"worker_version": "110fd472-59f4-43fa-a954-0a8dd776c86d",
"worker_run": null,
"text": "PARIS",
"text": "ROY",
"orientation": "horizontal-lr",
"confidence": 1.0
}
},
{
"model": "documents.transcription",
"pk": "e1978d01-9182-4a42-a76f-7ae776aaaf55",
"pk": "e66cc126-2d3c-4419-bd18-c4f8f0cb4bbb",
"fields": {
"element": "e9aa6eb2-eb0b-4503-9bbf-c3d27b9cce5f",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60",
"element": "fa35b384-692f-4b42-91ba-60d384ef251f",
"worker_version": "110fd472-59f4-43fa-a954-0a8dd776c86d",
"worker_run": null,
"text": "ROY",
"orientation": "horizontal-lr",
......@@ -1479,35 +2808,52 @@
},
{
"model": "documents.transcription",
"pk": "f5b81d19-ebb7-412d-9deb-455d72aaf829",
"pk": "ebce2b3b-c593-4a72-bf99-ffd16d552aa0",
"fields": {
"element": "2e8101c4-6fca-49b6-9b7b-41554facfa01",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60",
"element": "6953caa3-b8bb-46a8-a222-1f386ff539f5",
"worker_version": "110fd472-59f4-43fa-a954-0a8dd776c86d",
"worker_run": null,
"text": "DATUM",
"orientation": "horizontal-lr",
"confidence": 1.0
>>>>>>> 7912af40 (wip API endpoints)
}
},
{
"model": "documents.allowedmetadata",
"pk": "6437fdd1-97c0-4fff-a325-039d0379bdbe",
<<<<<<< HEAD
"pk": "89efa0fd-a187-4177-8de5-f3477dde921f",
"fields": {
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12",
=======
"pk": "1645d910-5282-4ea0-8de9-b9495bfc4fd3",
"fields": {
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "date",
"name": "date"
}
},
{
"model": "documents.allowedmetadata",
"pk": "4f1b7592-fd60-41a9-adb1-c31afd86d8b7",
"fields": {
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"type": "text",
"name": "folio"
}
},
{
"model": "documents.allowedmetadata",
"pk": "89efa0fd-a187-4177-8de5-f3477dde921f",
"pk": "e44b9326-0e8c-4e0f-a735-3d701bda3852",
"fields": {
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
>>>>>>> 7912af40 (wip API endpoints)
"type": "location",
"name": "location"
}
},
{
<<<<<<< HEAD
"model": "documents.allowedmetadata",
"pk": "ab34cc71-a15a-40d9-8cc5-f680adca898b",
"fields": {
......@@ -1547,6 +2893,12 @@
"pk": "52139b43-747a-4ffe-9f5c-cd43e0ad2b39",
"fields": {
"element": "e7027313-7910-44b4-bdff-28e8d187c0b4",
=======
"model": "documents.metadata",
"pk": "24d2c357-1f9f-4aeb-b680-b7426144d301",
"fields": {
"element": "549a9a87-0632-4846-962d-7799147e0225",
>>>>>>> 7912af40 (wip API endpoints)
"name": "number",
"type": "text",
"value": "3",
......@@ -1557,9 +2909,54 @@
},
{
"model": "documents.metadata",
<<<<<<< HEAD
"pk": "62347283-e04f-4401-a8a9-ff402766ac2d",
"fields": {
"element": "c8e488da-28d8-467e-a651-7d6f2ad6600d",
=======
"pk": "2d466cc6-bd16-462e-81e3-57f7d3406ed5",
"fields": {
"element": "77ced3ba-7f04-48c7-b5fa-2b101d191c23",
"name": "folio",
"type": "text",
"value": "1v",
"entity": null,
"worker_version": null,
"worker_run": null
}
},
{
"model": "documents.metadata",
"pk": "2ed9bece-59a6-41e3-b7fa-23a17a1fc720",
"fields": {
"element": "f3a388d1-9968-4486-9e3b-e5a2a11947b1",
"name": "number",
"type": "text",
"value": "1",
"entity": null,
"worker_version": null,
"worker_run": null
}
},
{
"model": "documents.metadata",
"pk": "32b3e87e-37b2-43fe-b2e9-5c2720f548fe",
"fields": {
"element": "bdea4cf0-63bf-4918-b67d-b879d09f3c95",
"name": "number",
"type": "text",
"value": "4",
"entity": null,
"worker_version": null,
"worker_run": null
}
},
{
"model": "documents.metadata",
"pk": "4d4ccd74-5144-423b-98ef-ff6f27ef0cde",
"fields": {
"element": "3dc4ff7a-9a40-431b-b692-a2b5af381ffd",
>>>>>>> 7912af40 (wip API endpoints)
"name": "folio",
"type": "text",
"value": "2r",
......@@ -1570,9 +2967,15 @@
},
{
"model": "documents.metadata",
<<<<<<< HEAD
"pk": "660e0182-f139-4a4b-b65e-b60b3051ef4c",
"fields": {
"element": "9c42123c-b940-4695-b083-5b19392f68a6",
=======
"pk": "5935cea1-4176-4ba8-bc7e-7d399427ab86",
"fields": {
"element": "1444e97e-4873-4731-9b75-79f931c9dc9e",
>>>>>>> 7912af40 (wip API endpoints)
"name": "folio",
"type": "text",
"value": "1r",
......@@ -1583,6 +2986,7 @@
},
{
"model": "documents.metadata",
<<<<<<< HEAD
"pk": "af1f94f7-b9a8-4963-9e21-d4a8c34b2627",
"fields": {
"element": "39210eb6-70a9-4660-8a45-5c6957508936",
......@@ -1612,6 +3016,11 @@
"pk": "da44df4c-a8ac-4bdc-a10b-ab6939ac76cd",
"fields": {
"element": "dc66eac3-a4e9-4c55-a4a8-d239bd79f3f6",
=======
"pk": "5e861243-06eb-4e72-b904-86e04bb61fa0",
"fields": {
"element": "454b9f6d-8b0d-4313-baa3-82ccf8856d42",
>>>>>>> 7912af40 (wip API endpoints)
"name": "folio",
"type": "text",
"value": "1v",
......@@ -1622,12 +3031,21 @@
},
{
"model": "documents.metadata",
<<<<<<< HEAD
"pk": "f55c81b9-bc87-4086-8cb1-b3a0eea6d491",
"fields": {
"element": "f530bd2f-d0ab-4f14-9d98-087486c4b1ab",
"name": "folio",
"type": "text",
"value": "1v",
=======
"pk": "752125f4-6e63-46e3-be1d-6a5c74e1acd5",
"fields": {
"element": "2a08be28-27f2-48f8-8d87-437893d389ca",
"name": "number",
"type": "text",
"value": "5",
>>>>>>> 7912af40 (wip API endpoints)
"entity": null,
"worker_version": null,
"worker_run": null
......@@ -1635,9 +3053,28 @@
},
{
"model": "documents.metadata",
<<<<<<< HEAD
"pk": "fb0bedec-cc2d-424e-86bf-05239865e3fd",
"fields": {
"element": "02a6f67e-c7d4-4dec-b3a0-9f9ab3f2ee99",
=======
"pk": "7f85231d-47f9-415d-a0d2-156a58cf70bc",
"fields": {
"element": "eed5499a-e95f-4f06-baa0-145d917a5b0c",
"name": "number",
"type": "text",
"value": "3",
"entity": null,
"worker_version": null,
"worker_run": null
}
},
{
"model": "documents.metadata",
"pk": "abbea23e-5dc2-481c-a34b-2e4bd18bace8",
"fields": {
"element": "97394f5f-6146-42be-8038-0d735e12d5f1",
>>>>>>> 7912af40 (wip API endpoints)
"name": "folio",
"type": "text",
"value": "2r",
......@@ -1648,9 +3085,15 @@
},
{
"model": "documents.metadata",
<<<<<<< HEAD
"pk": "fe60529e-30d4-4824-bb87-3534a652da81",
"fields": {
"element": "9fc5e0a3-9afb-493e-bf0f-fc2998ba4ba4",
=======
"pk": "ad4154e1-2017-4028-9f81-a9611e6a439b",
"fields": {
"element": "ffffc01b-7577-4a93-9148-02fdc1f80435",
>>>>>>> 7912af40 (wip API endpoints)
"name": "folio",
"type": "text",
"value": "1r",
......@@ -1676,6 +3119,7 @@
},
{
"model": "images.image",
<<<<<<< HEAD
"pk": "27c0757d-4d15-4f0e-bfc1-ec63bfada9e7",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
......@@ -1691,6 +3135,9 @@
{
"model": "images.image",
"pk": "468df2f7-e22a-4dba-96d2-9c464ba6c2b0",
=======
"pk": "0e219e81-b8ab-484b-a8f2-cb848a9c8b45",
>>>>>>> 7912af40 (wip API endpoints)
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
......@@ -1704,7 +3151,39 @@
},
{
"model": "images.image",
<<<<<<< HEAD
"pk": "53421855-db25-4abd-aba4-d86710a76d5d",
=======
"pk": "40210c9c-bf96-4364-a715-17ca2cf675cc",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"server": 1,
"path": "img3",
"width": 1000,
"height": 1000,
"hash": null,
"status": "unchecked"
}
},
{
"model": "images.image",
"pk": "4e80d190-2343-4e72-b60f-fda6b3d70b0d",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"server": 1,
"path": "img1",
"width": 1000,
"height": 1000,
"hash": null,
"status": "unchecked"
}
},
{
"model": "images.image",
"pk": "a6d3f3bc-986d-4618-8a87-fb1b86d9b866",
>>>>>>> 7912af40 (wip API endpoints)
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
......@@ -1718,6 +3197,7 @@
},
{
"model": "images.image",
<<<<<<< HEAD
"pk": "a38b69a3-a4f8-4dfc-a6b9-38ea2e52c713",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
......@@ -1767,10 +3247,37 @@
"content_type": 19,
"content_id": "f34313ec-45ec-4ac4-92e5-43d7eb045c12",
"level": 100
=======
"pk": "bd7d9ffd-013c-4970-9df8-1d18bbe88bd5",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"server": 1,
"path": "img2",
"width": 1000,
"height": 1000,
"hash": null,
"status": "unchecked"
}
},
{
"model": "images.image",
"pk": "d9c10a6b-6d15-4d60-a934-15a79d0b0bce",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"server": 1,
"path": "img5",
"width": 1000,
"height": 1000,
"hash": null,
"status": "unchecked"
>>>>>>> 7912af40 (wip API endpoints)
}
},
{
"model": "users.right",
<<<<<<< HEAD
"pk": "2a7d975d-4f18-41f4-964f-817aeae09582",
"fields": {
"user": 2,
......@@ -1783,22 +3290,71 @@
{
"model": "users.right",
"pk": "7e2ea5d2-2408-49b4-b1b4-2ea0e12da7e4",
=======
"pk": "053ed1e1-850b-4554-b0d0-d05576b71696",
>>>>>>> 7912af40 (wip API endpoints)
"fields": {
"user": 2,
"group": null,
"content_type": 34,
<<<<<<< HEAD
"content_id": "8f459bd8-0440-444e-940b-3c14b10bdb0d",
"level": 100
=======
"content_id": "18eabf1f-18b6-43d9-b104-7abfcb5b9baa",
"level": 50
>>>>>>> 7912af40 (wip API endpoints)
}
},
{
"model": "users.right",
<<<<<<< HEAD
"pk": "db08fb62-277f-475c-ae92-cfb4a515b146",
=======
"pk": "09f17812-99b6-4aa0-987b-541efc0d9eab",
"fields": {
"user": 2,
"group": null,
"content_type": 19,
"content_id": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"level": 100
}
},
{
"model": "users.right",
"pk": "0dcde7a7-c2a1-4e91-85c5-f5d392c511a6",
>>>>>>> 7912af40 (wip API endpoints)
"fields": {
"user": 4,
"group": null,
"content_type": 34,
<<<<<<< HEAD
"content_id": "8f459bd8-0440-444e-940b-3c14b10bdb0d",
=======
"content_id": "18eabf1f-18b6-43d9-b104-7abfcb5b9baa",
"level": 10
}
},
{
"model": "users.right",
"pk": "42da1a2f-2ff0-4480-b530-30b0934eb6be",
"fields": {
"user": 2,
"group": null,
"content_type": 34,
"content_id": "18eabf1f-18b6-43d9-b104-7abfcb5b9baa",
"level": 100
}
},
{
"model": "users.right",
"pk": "9323c83d-637f-43b5-8829-03c71505f4fb",
"fields": {
"user": 2,
"group": null,
"content_type": 11,
"content_id": "ff732a3f-c9ac-43fe-8b22-c03cf82d2a4e",
>>>>>>> 7912af40 (wip API endpoints)
"level": 10
}
},
......@@ -1817,7 +3373,11 @@
"model": "users.user",
"pk": 1,
"fields": {
<<<<<<< HEAD
"password": "pbkdf2_sha256$390000$n41pgYuMjEMc9yABOJDuv7$szqrPzEEMyrNyvxRF5ekrtgzLra4rnw09jkS/Rlb65M=",
=======
"password": "pbkdf2_sha256$390000$K7ghXs3mkOALU9T2ri8k6D$Hw9rIqH0Mdlvd2vaMSsj7lH3TLerOKfpkHUVk4ZfZPM=",
>>>>>>> 7912af40 (wip API endpoints)
"last_login": null,
"email": "root@root.fr",
"display_name": "Admin",
......@@ -1832,7 +3392,11 @@
"model": "users.user",
"pk": 2,
"fields": {
<<<<<<< HEAD
"password": "pbkdf2_sha256$390000$82MV7wfiM1CYxnR3JI9dRw$vavB8EAQRE2Z0REJhhWU7bRyrQqZF5wazXjl1rOrvTY=",
=======
"password": "pbkdf2_sha256$390000$4SWGc0rfBPkIHNBjmvIVhM$F81VX9tQd5l9iKOdb970liPhie/hbyyHNsYO7O7fOKE=",
>>>>>>> 7912af40 (wip API endpoints)
"last_login": null,
"email": "user@user.fr",
"display_name": "Test user",
......@@ -1875,7 +3439,11 @@
},
{
"model": "users.group",
<<<<<<< HEAD
"pk": "8f459bd8-0440-444e-940b-3c14b10bdb0d",
=======
"pk": "18eabf1f-18b6-43d9-b104-7abfcb5b9baa",
>>>>>>> 7912af40 (wip API endpoints)
"fields": {
"name": "User group",
"public": false,
......@@ -3871,42 +5439,188 @@
"codename": "view_datasetelement"
}
},
{
"model": "auth.permission",
"pk": 222,
"fields": {
"name": "Can add dataset set",
"content_type": 57,
"codename": "add_datasetset"
}
},
{
"model": "auth.permission",
"pk": 223,
"fields": {
"name": "Can change dataset set",
"content_type": 57,
"codename": "change_datasetset"
}
},
{
"model": "auth.permission",
"pk": 224,
"fields": {
"name": "Can delete dataset set",
"content_type": 57,
"codename": "delete_datasetset"
}
},
{
"model": "auth.permission",
"pk": 225,
"fields": {
"name": "Can view dataset set",
"content_type": 57,
"codename": "view_datasetset"
}
},
{
"model": "ponos.farm",
<<<<<<< HEAD
"pk": "395522d1-94a0-407a-b5cb-347fa68ec2c4",
"fields": {
"name": "Wheat farm",
"seed": "444809637bf8b3088a181de520a02151a99477edd051710e90a2d1fcdf860dbb"
=======
"pk": "ff732a3f-c9ac-43fe-8b22-c03cf82d2a4e",
"fields": {
"name": "Wheat farm",
"seed": "91901d0fec5faf1551277b5c76546b41902b8aefb819c3dbd10c3a643e6bb93c"
}
},
{
"model": "ponos.task",
"pk": "5c722e0d-2a2f-4ee8-9609-6033e450fd53",
"fields": {
"run": 0,
"depth": 0,
"slug": "docker_build",
"priority": 10,
"state": "completed",
"image": "",
"shm_size": null,
"command": null,
"env": "{}",
"has_docker_socket": false,
"image_artifact": null,
"agent": null,
"requires_gpu": false,
"gpu": null,
"process": "d6b43bc9-d87c-4c80-9211-f0c807506ad7",
"worker_run": null,
"container": null,
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"expiry": "2100-12-31T23:59:59.999Z",
"extra_files": "{}",
"token": "OhbumqNZSmuGnj0MZ3lhJYRc3nHBm0WGrv9RNdtYpJk=",
"parents": []
}
},
{
"model": "ponos.artifact",
"pk": "481b42e2-645c-47fe-937f-5b4431f10563",
"fields": {
"task": "5c722e0d-2a2f-4ee8-9609-6033e450fd53",
"path": "/path/to/docker_build",
"size": 42000,
"content_type": "application/octet-stream",
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z"
>>>>>>> 7912af40 (wip API endpoints)
}
},
{
"model": "training.dataset",
<<<<<<< HEAD
"pk": "4a844b36-08bd-4284-918e-5e03d543df13",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12",
=======
"pk": "170bc276-0e11-483a-9486-88a4bf2079b2",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
>>>>>>> 7912af40 (wip API endpoints)
"creator": 2,
"task": null,
"name": "Second Dataset",
"description": "dataset number two",
"state": "open",
"sets": "[\"training\", \"test\", \"validation\"]"
"state": "open"
}
},
{
"model": "training.dataset",
<<<<<<< HEAD
"pk": "630d1cf5-3ba8-4335-b0be-d1be4cb18782",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12",
=======
"pk": "6b32dab0-e3f2-4fff-b0ad-2ea1ee550810",
"fields": {
"created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z",
"corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
>>>>>>> 7912af40 (wip API endpoints)
"creator": 2,
"task": null,
"name": "First Dataset",
"description": "dataset number one",
"state": "open",
"sets": "[\"training\", \"test\", \"validation\"]"
"state": "open"
}
},
{
"model": "training.datasetset",
"pk": "00e3b37b-f1ed-4adb-a1de-a1c103edaa24",
"fields": {
"name": "test",
"dataset": "170bc276-0e11-483a-9486-88a4bf2079b2"
}
},
{
"model": "training.datasetset",
"pk": "95255ff4-7bca-424c-8e7e-d8b5c33c585f",
"fields": {
"name": "training",
"dataset": "170bc276-0e11-483a-9486-88a4bf2079b2"
}
},
{
"model": "training.datasetset",
"pk": "b21e4b31-1dc1-4015-9933-3a8e180cf2e0",
"fields": {
"name": "validation",
"dataset": "170bc276-0e11-483a-9486-88a4bf2079b2"
}
},
{
"model": "training.datasetset",
"pk": "b76d919c-ce7e-4896-94c3-9b47862b997a",
"fields": {
"name": "validation",
"dataset": "6b32dab0-e3f2-4fff-b0ad-2ea1ee550810"
}
},
{
"model": "training.datasetset",
"pk": "d5f4d410-0588-4d19-8d08-b57a11bad67f",
"fields": {
"name": "training",
"dataset": "6b32dab0-e3f2-4fff-b0ad-2ea1ee550810"
}
},
{
"model": "training.datasetset",
"pk": "db70ad8a-8d6b-44c6-b8d3-837bf5a4ab8e",
"fields": {
"name": "test",
"dataset": "6b32dab0-e3f2-4fff-b0ad-2ea1ee550810"
}
}
]
......@@ -20,6 +20,7 @@ from arkindex.process.models import (
WorkerVersionState,
)
from arkindex.project.tools import fake_now
from arkindex.training.models import DatasetSet
from arkindex.users.models import Group, Right, Role, User
......@@ -271,8 +272,15 @@ class Command(BaseCommand):
)
# Create 2 datasets
corpus.datasets.create(name="First Dataset", description="dataset number one", creator=user)
corpus.datasets.create(name="Second Dataset", description="dataset number two", creator=user)
dataset_1 = corpus.datasets.create(name="First Dataset", description="dataset number one", creator=user)
dataset_2 = corpus.datasets.create(name="Second Dataset", description="dataset number two", creator=user)
# Create their sets
DatasetSet.objects.bulk_create(
DatasetSet(name=name, dataset_id=dataset_1.id) for name in ["Train", "Validation", "Test"]
)
DatasetSet.objects.bulk_create(
DatasetSet(name=name, dataset_id=dataset_2.id) for name in ["Train", "Validation", "Test"]
)
# Create 2 volumes
vol1 = Element.objects.create(
......
import django.core.validators
from django.db import migrations, models
import arkindex.process.models
import arkindex.project.fields
import arkindex.training.models
class Migration(migrations.Migration):
......@@ -37,7 +37,7 @@ class Migration(migrations.Migration):
validators=[django.core.validators.MinLengthValidator(1)]
),
size=None,
validators=[django.core.validators.MinLengthValidator(1), arkindex.training.models.validate_unique_set_names]
validators=[django.core.validators.MinLengthValidator(1), arkindex.process.models.validate_unique_set_names]
),
),
]
......@@ -5,6 +5,7 @@ from typing import Optional
from django.conf import settings
from django.contrib.contenttypes.fields import GenericRelation
from django.core.exceptions import ValidationError
from django.core.validators import MinLengthValidator, MinValueValidator
from django.db import models, transaction
from django.db.models import F, Q
......@@ -28,7 +29,7 @@ from arkindex.project.aws import S3FileMixin, S3FileStatus
from arkindex.project.fields import ArrayField, MD5HashField
from arkindex.project.models import IndexableModel
from arkindex.project.validators import MaxValueValidator
from arkindex.training.models import ModelVersion, ModelVersionState, validate_unique_set_names
from arkindex.training.models import ModelVersion, ModelVersionState
from arkindex.users.models import Role
......@@ -40,6 +41,11 @@ def process_max_chunks():
return settings.MAX_CHUNKS
def validate_unique_set_names(sets):
if len(set(sets)) != len(sets):
raise ValidationError("Set names must be unique.")
class ActivityState(Enum):
"""
Store the state of the workers activity tracking for a process.
......
......@@ -109,7 +109,7 @@ from arkindex.training.api import (
DatasetElementDestroy,
DatasetElements,
DatasetUpdate,
ElementDatasets,
ElementDatasetSets,
MetricValueBulkCreate,
MetricValueCreate,
ModelCompatibleWorkerManage,
......@@ -184,7 +184,7 @@ api = [
# Datasets
path("corpus/<uuid:pk>/datasets/", CorpusDataset.as_view(), name="corpus-datasets"),
path("corpus/<uuid:pk>/datasets/selection/", CreateDatasetElementsSelection.as_view(), name="dataset-elements-selection"),
path("element/<uuid:pk>/datasets/", ElementDatasets.as_view(), name="element-datasets"),
path("element/<uuid:pk>/datasets/", ElementDatasetSets.as_view(), name="element-datasets"),
path("datasets/<uuid:pk>/", DatasetUpdate.as_view(), name="dataset-update"),
path("datasets/<uuid:pk>/clone/", DatasetClone.as_view(), name="dataset-clone"),
path("datasets/<uuid:pk>/elements/", DatasetElements.as_view(), name="dataset-elements"),
......
......@@ -12,6 +12,7 @@ from arkindex.documents.models import MetaType
from arkindex.ponos.utils import get_process_from_task_auth
from arkindex.process.models import ProcessMode, WorkerRun
from arkindex.project.gis import ensure_linear_ring
from arkindex.training.models import DatasetElement
class EnumField(serializers.ChoiceField):
......@@ -283,12 +284,12 @@ class DatasetSetsCountField(serializers.DictField):
def get_attribute(self, instance):
if not self.context.get("sets_count", True):
return None
elts_count = {k: 0 for k in instance.sets}
elts_count = {k.name: 0 for k in instance.sets.all()}
elts_count.update(
instance.dataset_elements
.values("set")
DatasetElement.objects.filter(set_id__in=instance.sets.values_list("id"))
.values("set__name")
.annotate(count=Count("id"))
.values_list("set", "count")
.values_list("set__name", "count")
)
return elts_count
......
......@@ -2,7 +2,7 @@ from django.contrib import admin
from enumfields.admin import EnumFieldListFilter
from arkindex.project.admin import ArchivedListFilter
from arkindex.training.models import Dataset, MetricKey, MetricValue, Model, ModelVersion
from arkindex.training.models import Dataset, DatasetSet, MetricKey, MetricValue, Model, ModelVersion
class ModelAdmin(admin.ModelAdmin):
......@@ -31,21 +31,17 @@ class MetricKeyAdmin(admin.ModelAdmin):
inlines = [MetricValueInline, ]
class DatasetSetInLine(admin.StackedInline):
model = DatasetSet
class DatasetAdmin(admin.ModelAdmin):
list_display = ("name", "corpus", "state")
list_filter = (("state", EnumFieldListFilter), "corpus")
search_fields = ("name", "description")
fields = ("id", "name", "created", "updated", "description", "corpus", "creator", "task", "sets")
fields = ("id", "name", "created", "updated", "description", "corpus", "creator", "task")
readonly_fields = ("id", "created", "updated", "task")
def get_form(self, *args, **kwargs):
form = super().get_form(*args, **kwargs)
# Add a help text to mention that the set names should be comma-separated.
# This is only done here and not through the usual `help_text=…` in the model
# because this is only relevant to the Django admin and should not appear in
# DRF serializers or the API docs.
form.base_fields["sets"].help_text = "Comma-separated list of set names"
return form
inlines = [DatasetSetInLine, ]
admin.site.register(Model, ModelAdmin)
......
......@@ -29,6 +29,7 @@ from arkindex.project.tools import BulkMap
from arkindex.training.models import (
Dataset,
DatasetElement,
DatasetSet,
DatasetState,
MetricValue,
Model,
......@@ -40,7 +41,7 @@ from arkindex.training.serializers import (
DatasetElementInfoSerializer,
DatasetElementSerializer,
DatasetSerializer,
ElementDatasetSerializer,
ElementDatasetSetSerializer,
MetricValueBulkSerializer,
MetricValueCreateSerializer,
ModelCompatibleWorkerSerializer,
......@@ -58,7 +59,7 @@ def _fetch_datasetelement_neighbors(datasetelements):
"""
Retrieve the neighbors for a list of DatasetElements, and annotate these DatasetElements
with next and previous attributes.
The ElementDatasets endpoint uses arkindex.project.tools.BulkMap to apply this method and
The ElementDatasetSets endpoint uses arkindex.project.tools.BulkMap to apply this method and
perform the second request *after* DRF's pagination, because there is no way to perform
post-processing after pagination in Django without having to use Django private methods.
"""
......@@ -71,18 +72,18 @@ def _fetch_datasetelement_neighbors(datasetelements):
SELECT
n.id,
lag(element_id) OVER (
partition BY (n.dataset_id, n.set)
partition BY (n.set_id)
order by
n.element_id
) as previous,
lead(element_id) OVER (
partition BY (n.dataset_id, n.set)
partition BY (n.set_id)
order by
n.element_id
) as next
FROM training_datasetelement as n
WHERE (dataset_id, set) IN (
SELECT dataset_id, set
WHERE set_id IN (
SELECT set_id
FROM training_datasetelement
WHERE id IN %(ids)s
)
......@@ -609,6 +610,7 @@ class CorpusDataset(CorpusACLMixin, ListCreateAPIView):
def get_queryset(self):
return Dataset.objects \
.select_related("creator") \
.prefetch_related("sets") \
.filter(corpus=self.corpus) \
.order_by("name")
......@@ -707,7 +709,8 @@ class DatasetUpdate(ACLMixin, RetrieveUpdateDestroyAPIView):
raise ValidationError(detail="This dataset is in complete state and cannot be modified anymore.")
def perform_destroy(self, dataset):
dataset.dataset_elements.all().delete()
DatasetElement.objects.filter(set__dataset_id=dataset.id).delete()
dataset.sets.all().delete()
super().perform_destroy(dataset)
......@@ -768,13 +771,13 @@ class DatasetElements(CorpusACLMixin, ListCreateAPIView):
def get_queryset(self):
qs = (
self.dataset.dataset_elements
.prefetch_related("element")
DatasetElement.objects.filter(set__dataset_id=self.dataset.id)
.prefetch_related("element", "set")
.select_related("element__type", "element__corpus", "element__image__server")
.order_by("element_id", "id")
)
if "set" in self.request.query_params:
qs = qs.filter(set=self.request.query_params["set"])
qs = qs.filter(set__name=self.request.query_params["set"])
return qs
def get_serializer_context(self):
......@@ -787,20 +790,12 @@ class DatasetElements(CorpusACLMixin, ListCreateAPIView):
@extend_schema_view(
delete=extend_schema(
operation_id="DestroyDatasetElement",
parameters=[
OpenApiParameter(
"set",
type=str,
description="Name of the set from which to remove the element.",
required=True,
)
],
tags=["datasets"]
)
)
class DatasetElementDestroy(CorpusACLMixin, DestroyAPIView):
"""
Remove an element from a dataset.
Remove an element from a dataset set.
Elements can only be removed from **open** datasets.
......@@ -811,17 +806,15 @@ class DatasetElementDestroy(CorpusACLMixin, DestroyAPIView):
lookup_url_kwarg = "element"
def destroy(self, request, *args, **kwargs):
if not self.request.query_params.get("set"):
if not (set_name := self.request.query_params.get("set")):
raise ValidationError({"set": ["This field is required."]})
dataset_element = get_object_or_404(
DatasetElement.objects.select_related("dataset__corpus"),
dataset_id=self.kwargs["dataset"],
element_id=self.kwargs["element"],
set=self.request.query_params.get("set")
DatasetElement.objects.select_related("set__dataset__corpus").filter(set__dataset_id=self.kwargs["dataset"], set__name=set_name),
element_id=self.kwargs["element"]
)
if dataset_element.dataset.state != DatasetState.Open:
if dataset_element.set.dataset.state != DatasetState.Open:
raise ValidationError({"dataset": ["Elements can only be removed from open Datasets."]})
if not self.has_write_access(dataset_element.dataset.corpus):
if not self.has_write_access(dataset_element.set.dataset.corpus):
raise PermissionDenied(detail="You need a Contributor access to the dataset to perform this action.")
dataset_element.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
......@@ -896,14 +889,14 @@ class CreateDatasetElementsSelection(CorpusACLMixin, CreateAPIView):
)
],
)
class ElementDatasets(CorpusACLMixin, ListAPIView):
class ElementDatasetSets(CorpusACLMixin, ListAPIView):
"""
List all datasets containing a specific element.
List all dataset sets containing a specific element.
Requires a **guest** access to the element's corpus.
"""
permission_classes = (IsVerifiedOrReadOnly, )
serializer_class = ElementDatasetSerializer
serializer_class = ElementDatasetSetSerializer
@cached_property
def element(self):
......@@ -915,9 +908,10 @@ class ElementDatasets(CorpusACLMixin, ListAPIView):
def get_queryset(self):
qs = (
self.element.dataset_elements.all()
.select_related("dataset__creator")
.order_by("dataset__name", "set", "dataset_id")
self.element.dataset_elements
.select_related("set__dataset__creator")
.prefetch_related("set__dataset__sets")
.order_by("set__dataset__name", "set__name")
)
with_neighbors = self.request.query_params.get("with_neighbors", "false")
......@@ -960,7 +954,9 @@ class DatasetClone(CorpusACLMixin, CreateAPIView):
serializer_class = DatasetSerializer
def get_queryset(self):
return Dataset.objects.filter(corpus__in=Corpus.objects.readable(self.request.user))
return (
Dataset.objects.filter(corpus__in=Corpus.objects.readable(self.request.user))
)
def check_object_permissions(self, request, dataset):
if not self.has_write_access(dataset.corpus):
......@@ -995,11 +991,18 @@ class DatasetClone(CorpusACLMixin, CreateAPIView):
clone.creator = request.user
clone.save()
# Clone dataset sets
cloned_sets = DatasetSet.objects.bulk_create([
DatasetSet(dataset_id=clone.id, name=set.name)
for set in dataset.sets.all()
])
# Associate all elements to the clone
DatasetElement.objects.bulk_create([
DatasetElement(element_id=elt_id, dataset_id=clone.id, set=set_name)
for elt_id, set_name in dataset.dataset_elements.values_list("element_id", "set")
DatasetElement(element_id=elt_id, set=next(new_set for new_set in cloned_sets if new_set.name == set_name))
for elt_id, set_name in DatasetElement.objects.filter(set__dataset_id=dataset.id)
.values_list("element_id", "set__name")
])
return Response(
DatasetSerializer(clone).data,
status=status.HTTP_201_CREATED,
......
......@@ -8,9 +8,13 @@ import django.db.models.deletion
import enumfields.fields
from django.db import migrations, models
import arkindex.process.models
import arkindex.project.aws
import arkindex.project.fields
import arkindex.training.models
def default_sets():
return ["training", "test", "validation"]
class Migration(migrations.Migration):
......@@ -32,7 +36,7 @@ class Migration(migrations.Migration):
("name", models.CharField(max_length=100, validators=[django.core.validators.MinLengthValidator(1)])),
("description", models.TextField(validators=[django.core.validators.MinLengthValidator(1)])),
("state", enumfields.fields.EnumField(default="open", enum=arkindex.training.models.DatasetState, max_length=10)),
("sets", django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=50, validators=[django.core.validators.MinLengthValidator(1)]), default=arkindex.training.models.default_sets, size=None, validators=[django.core.validators.MinLengthValidator(1), arkindex.training.models.validate_unique_set_names])),
("sets", django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=50, validators=[django.core.validators.MinLengthValidator(1)]), default=default_sets, size=None, validators=[django.core.validators.MinLengthValidator(1), arkindex.process.models.validate_unique_set_names])),
("corpus", models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name="datasets", to="documents.corpus")),
],
),
......
# Generated by Django 4.1.7 on 2024-03-05 16:28
import uuid
import django.core.validators
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("training", "0006_model_archived"),
]
operations = [
migrations.CreateModel(
name="DatasetSet",
fields=[
("id", models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
("name", models.CharField(max_length=50, validators=[django.core.validators.MinLengthValidator(1)])),
("dataset", models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name="tmp_sets", to="training.dataset")),
],
),
migrations.AddConstraint(
model_name="datasetset",
constraint=models.UniqueConstraint(fields=("dataset", "name"), name="unique_dataset_sets"),
),
migrations.AddField(
model_name="datasetelement",
name="set_id",
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name="dataset_elements", to="training.datasetset"),
),
migrations.RunSQL(
"""
INSERT INTO training_datasetset (id, dataset_id, name)
SELECT uuid_generate_v4(), ds.id, ds.set
FROM (
SELECT DISTINCT id, unnest(sets) AS set
FROM training_dataset
) ds
""",
reverse_sql=migrations.RunSQL.noop,
),
migrations.RunSQL(
"""
INSERT INTO training_datasetset (id, dataset_id, name)
SELECT uuid_generate_v4(), sets.dataset_id, sets.set
FROM (
SELECT DISTINCT dataset_id, set
FROM training_datasetelement
) sets
ON CONFLICT DO NOTHING
""",
reverse_sql=migrations.RunSQL.noop,
),
migrations.RunSQL(
"""
UPDATE training_datasetelement de
SET set_id_id = ds.id
FROM training_datasetset ds
WHERE de.dataset_id = ds.dataset_id AND de.set = ds.name
""",
reverse_sql=migrations.RunSQL.noop,
),
migrations.RemoveConstraint(
model_name="datasetelement",
name="unique_dataset_elements",
),
migrations.RemoveField(
model_name="datasetelement",
name="dataset"
),
migrations.RemoveField(
model_name="datasetelement",
name="set"
),
migrations.RenameField(
model_name="datasetelement",
old_name="set_id",
new_name="set"
),
migrations.AlterField(
model_name="datasetelement",
name="set",
field=models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name="set_elements", to="training.datasetset"),
),
migrations.AddConstraint(
model_name="datasetelement",
constraint=models.UniqueConstraint(fields=("element_id", "set_id"), name="unique_set_element"),
),
migrations.RemoveField(
model_name="dataset",
name="sets"
),
migrations.RemoveField(
model_name="dataset",
name="elements",
),
migrations.AlterField(
model_name="datasetset",
name="dataset",
field=models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name="sets", to="training.dataset"),
),
]
......@@ -4,8 +4,6 @@ from hashlib import sha256
from django.conf import settings
from django.contrib.contenttypes.fields import GenericRelation
from django.contrib.postgres.fields import ArrayField
from django.core.exceptions import ValidationError
from django.core.validators import MinLengthValidator
from django.db import models
from django.db.models import Q
......@@ -242,15 +240,6 @@ class DatasetState(Enum):
Error = "error"
def validate_unique_set_names(sets):
if len(set(sets)) != len(sets):
raise ValidationError("Set names must be unique.")
def default_sets():
return ["training", "test", "validation"]
class Dataset(models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True, editable=False)
created = models.DateTimeField(auto_now_add=True)
......@@ -278,21 +267,6 @@ class Dataset(models.Model):
description = models.TextField(validators=[MinLengthValidator(1)])
state = EnumField(DatasetState, default=DatasetState.Open, max_length=50)
sets = ArrayField(
models.CharField(max_length=50, validators=[MinLengthValidator(1)]),
validators=[
MinLengthValidator(1),
validate_unique_set_names,
],
default=default_sets,
)
elements = models.ManyToManyField(
"documents.Element",
through="training.DatasetElement",
related_name="datasets",
)
class Meta:
constraints = [
models.UniqueConstraint(
......@@ -305,24 +279,41 @@ class Dataset(models.Model):
return self.name
class DatasetElement(models.Model):
class DatasetSet(models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True, editable=False)
name = models.CharField(max_length=50, validators=[MinLengthValidator(1)])
dataset = models.ForeignKey(
Dataset,
related_name="dataset_elements",
related_name="sets",
on_delete=models.DO_NOTHING,
)
class Meta:
constraints = [
models.UniqueConstraint(
fields=["dataset", "name"],
name="unique_dataset_sets",
),
]
class DatasetElement(models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True, editable=False)
element = models.ForeignKey(
"documents.Element",
related_name="dataset_elements",
on_delete=models.DO_NOTHING,
)
set = models.CharField(max_length=50, validators=[MinLengthValidator(1)])
set = models.ForeignKey(
DatasetSet,
related_name="set_elements",
on_delete=models.DO_NOTHING,
)
class Meta:
constraints = [
models.UniqueConstraint(
fields=["dataset", "element", "set"],
name="unique_dataset_elements",
fields=["element_id", "set_id"],
name="unique_set_element",
),
]
......@@ -6,18 +6,19 @@ from textwrap import dedent
from django.db import transaction
from django.db.models import Count, Q
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers
from rest_framework import permissions, serializers
from rest_framework.exceptions import PermissionDenied, ValidationError
from rest_framework.validators import UniqueTogetherValidator
from arkindex.documents.models import Element
from arkindex.documents.models import Corpus, Element
from arkindex.documents.serializers.elements import ElementListSerializer
from arkindex.ponos.models import Task
from arkindex.process.models import ProcessDataset, Worker
from arkindex.process.models import Worker
from arkindex.project.serializer_fields import ArchivedField, DatasetSetsCountField, EnumField
from arkindex.training.models import (
Dataset,
DatasetElement,
DatasetSet,
DatasetState,
MetricKey,
MetricMode,
......@@ -479,6 +480,12 @@ class MetricValueBulkSerializer(serializers.Serializer):
return validated_data
class DatasetSetSerializer(serializers.ModelSerializer):
class Meta:
model = DatasetSet
fields = ("id", "name",)
class DatasetSerializer(serializers.ModelSerializer):
state = EnumField(
DatasetState,
......@@ -505,6 +512,13 @@ class DatasetSerializer(serializers.ModelSerializer):
help_text="Display name of the user who created the dataset.",
)
set_names = serializers.ListField(
child=serializers.CharField(max_length=50),
write_only=True,
default=serializers.CreateOnlyDefault(["training", "validation", "test"])
)
sets = DatasetSetSerializer(many=True, read_only=True)
# When creating the dataset, the dataset's corpus comes from the URL, so the APIView passes it through
corpus = serializers.HiddenField(default=_corpus_from_context)
......@@ -517,16 +531,6 @@ class DatasetSerializer(serializers.ModelSerializer):
help_text="Distribution of elements in sets. This value is set to null when listing multiple datasets.",
)
def sets_diff(self, new_sets):
"""
Returns a list of removed sets, and a list of added sets for updates
"""
if not isinstance(self.instance, Dataset):
return [], new_sets
current_sets = set(self.instance.sets)
new_sets = set(new_sets)
return list(current_sets - new_sets), list(new_sets - current_sets)
def validate_state(self, state):
"""
Dataset's state update is limited to these transitions:
......@@ -550,27 +554,14 @@ class DatasetSerializer(serializers.ModelSerializer):
raise ValidationError(f"Transition from {self.instance.state} to {state} is not allowed.")
return state
def validate_sets(self, sets):
"""
Ensure sets are updated in a comprehensible way.
It is either possible to add multiple sets,
remove multiple sets or update a single set.
"""
if sets is not None and len(set(sets)) != len(sets):
def validate_set_names(self, set_names):
if self.context["request"].method not in permissions.SAFE_METHODS and self.context["request"].method != "POST":
raise ValidationError("This API endpoint does not allow updating a dataset's sets.")
if set_names is not None and len(set(set_names)) != len(set_names):
raise ValidationError("Set names must be unique.")
removed, added = self.sets_diff(sets)
if removed and ProcessDataset.objects.filter(sets__overlap=removed, dataset_id=self.instance.id).exists():
# Sets that are used in a ProcessDataset cannot be renamed or deleted
raise ValidationError("These sets cannot be updated because one or more are selected in a dataset process.")
if not removed or not added:
# Some sets have either been added or removed, but not both; do nothing
return sets
elif len(removed) == 1 and len(added) == 1:
# A single set has been renamed. Move its elements later, while performing the update
return sets
else:
raise ValidationError("Updating those sets is ambiguous because several have changed.")
if set_names is not None and len(set_names) == 0:
raise ValidationError("Either do not specify set names to use the default values, or specify a non-empty list of names.")
return set_names
def validate(self, data):
data = super().validate(data)
......@@ -598,13 +589,17 @@ class DatasetSerializer(serializers.ModelSerializer):
return data
@transaction.atomic()
def update(self, instance, validated_data):
removed, added = self.sets_diff(validated_data.get("sets", self.instance.sets))
if len(removed) == 1 and len(added) == 1:
set_from, set_to = *removed, *added
instance.dataset_elements.filter(set=set_from).update(set=set_to)
return super().update(instance, validated_data)
@transaction.atomic
def create(self, validated_data):
sets = validated_data.pop("set_names")
dataset = Dataset.objects.create(**validated_data)
DatasetSet.objects.bulk_create(
DatasetSet(
name=set_name,
dataset_id=dataset.id
) for set_name in sets
)
return dataset
class Meta:
model = Dataset
......@@ -613,6 +608,7 @@ class DatasetSerializer(serializers.ModelSerializer):
"name",
"description",
"sets",
"set_names",
"set_elements",
"state",
# Only the corpus ID is actually serialized
......@@ -647,13 +643,7 @@ class DatasetSerializer(serializers.ModelSerializer):
"sets": {
"error_messages": {
"empty": "Either do not specify set names to use the default values, or specify a non-empty list of names."
},
"help_text": dedent(
"""
Updating the sets array must either add or remove sets (in this case nothing specific is done),
or rename a single set within the array (all elements linked to the previous set will be moved).
"""
).strip(),
}
}
}
......@@ -673,6 +663,7 @@ class DatasetElementSerializer(serializers.ModelSerializer):
default=_dataset_from_context,
write_only=True,
)
set = serializers.SlugRelatedField(queryset=DatasetSet.objects.none(), slug_field="name")
class Meta:
model = DatasetElement
......@@ -681,7 +672,7 @@ class DatasetElementSerializer(serializers.ModelSerializer):
validators = [
UniqueTogetherValidator(
queryset=DatasetElement.objects.all(),
fields=["dataset", "element_id", "set"],
fields=["element_id", "set"],
message="This element is already part of this set.",
)
]
......@@ -690,13 +681,12 @@ class DatasetElementSerializer(serializers.ModelSerializer):
super().__init__(*args, **kwargs)
if dataset := self.context.get("dataset"):
self.fields["element_id"].queryset = Element.objects.filter(corpus=dataset.corpus)
self.fields["set"].queryset = dataset.sets.all()
def validate_set(self, value):
# The set must match the `sets` array defined at the dataset level
dataset = self.context["dataset"]
if dataset and value not in dataset.sets:
raise ValidationError(f"This dataset has no set named {value}.")
return value
def validate(self, data):
data = super().validate(data)
data.pop("dataset")
return data
class DatasetElementInfoSerializer(DatasetElementSerializer):
......@@ -714,10 +704,11 @@ class DatasetElementInfoSerializer(DatasetElementSerializer):
fields = DatasetElementSerializer.Meta.fields + ("dataset",)
class ElementDatasetSerializer(serializers.ModelSerializer):
dataset = DatasetSerializer()
class ElementDatasetSetSerializer(serializers.ModelSerializer):
dataset = DatasetSerializer(source="set.dataset")
previous = serializers.UUIDField(allow_null=True, read_only=True)
next = serializers.UUIDField(allow_null=True, read_only=True)
set = serializers.SlugRelatedField(slug_field="name", read_only=True)
class Meta:
model = DatasetElement
......@@ -726,35 +717,29 @@ class ElementDatasetSerializer(serializers.ModelSerializer):
class SelectionDatasetElementSerializer(serializers.Serializer):
dataset_id = serializers.PrimaryKeyRelatedField(
queryset=Dataset.objects.all(),
source="dataset",
set_id = serializers.PrimaryKeyRelatedField(
queryset=DatasetSet.objects.none(),
source="set",
write_only=True,
help_text="UUID of a dataset to add elements from your corpus' selection.",
help_text="UUID of a dataset set the elements will be added to.",
style={"base_template": "input.html"},
)
set = serializers.CharField(
max_length=50,
write_only=True,
help_text="Name of the set elements will be added to.",
)
def validate_dataset_id(self, dataset):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["set_id"].queryset = DatasetSet.objects.filter(
dataset__corpus_id__in=Corpus.objects.readable(self.context["request"].user)
).select_related("dataset")
def validate_set_id(self, set):
if (
(corpus := self.context.get("corpus"))
and dataset.corpus_id != corpus.id
and set.dataset.corpus_id != corpus.id
):
raise ValidationError(f"Dataset {dataset.id} is not part of corpus {corpus.name}.")
if dataset.state == DatasetState.Complete:
raise ValidationError(f"Dataset {dataset.id} is marked as completed.")
return dataset
def validate(self, data):
data = super().validate(data)
dataset = data["dataset"]
if data["set"] not in dataset.sets:
raise ValidationError({"set": [f'This dataset only allows one of {", ".join(dataset.sets)}.']})
return data
raise ValidationError(f"Dataset {set.dataset.id} is not part of corpus {corpus.name}.")
if set.dataset.state == DatasetState.Complete:
raise ValidationError(f"Dataset {set.dataset.id} is marked as completed.")
return set
def create(self, validated_data):
user = self.context["request"].user
......
......@@ -9,7 +9,7 @@ from arkindex.documents.models import Corpus
from arkindex.process.models import Process, ProcessDataset, ProcessMode
from arkindex.project.tests import FixtureAPITestCase
from arkindex.project.tools import fake_now
from arkindex.training.models import Dataset, DatasetState
from arkindex.training.models import Dataset, DatasetElement, DatasetSet, DatasetState
from arkindex.users.models import Role, User
# Using the fake DB fixtures creation date when needed
......@@ -33,6 +33,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
ProcessDataset.objects.create(process=cls.process, dataset=cls.dataset, sets=["training", "test", "validation"])
ProcessDataset.objects.create(process=cls.process, dataset=cls.dataset2, sets=["test"])
cls.private_dataset = Dataset.objects.create(name="Private Dataset", description="Dead Sea Scrolls", corpus=cls.private_corpus, creator=cls.dataset_creator)
cls.private_dataset_set = DatasetSet.objects.create(dataset=cls.private_dataset, name="Private set")
cls.vol = cls.corpus.elements.get(name="Volume 1")
cls.page1 = cls.corpus.elements.get(name="Volume 1, page 1r")
cls.page2 = cls.corpus.elements.get(name="Volume 1, page 1v")
......@@ -75,7 +76,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_list(self):
self.client.force_login(self.user)
with self.assertNumQueries(5):
with self.assertNumQueries(6):
response = self.client.get(reverse("api:corpus-datasets", kwargs={"pk": self.corpus.pk}))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.json()["results"], [
......@@ -83,7 +84,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"name": "First Dataset",
"description": "dataset number one",
"id": str(self.dataset.pk),
"sets": ["training", "test", "validation"],
"sets": [
{
"id": str(ds.id),
"name": ds.name
}
for ds in self.dataset.sets.all()
],
"set_elements": None,
"state": "open",
"creator": "Test user",
......@@ -96,7 +103,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"name": "Second Dataset",
"description": "dataset number two",
"id": str(self.dataset2.pk),
"sets": ["training", "test", "validation"],
"sets": [
{
"id": str(ds.id),
"name": ds.name
}
for ds in self.dataset2.sets.all()
],
"set_elements": None,
"state": "open",
"creator": "Test user",
......@@ -254,7 +267,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_create(self):
self.client.force_login(self.user)
with self.assertNumQueries(6):
with self.assertNumQueries(11):
response = self.client.post(
reverse("api:corpus-datasets", kwargs={"pk": self.corpus.pk}),
data={"name": "My dataset", "description": "My dataset for my experiments."},
......@@ -266,7 +279,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(created_dataset.id),
"name": "My dataset",
"description": "My dataset for my experiments.",
"sets": ["training", "test", "validation"],
"sets": [
{
"id": str(ds.id),
"name": ds.name
}
for ds in created_dataset.sets.all()
],
"set_elements": {
"training": 0,
"test": 0,
......@@ -282,7 +301,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_create_state_ignored(self):
self.client.force_login(self.user)
with self.assertNumQueries(6):
with self.assertNumQueries(11):
response = self.client.post(
reverse("api:corpus-datasets", kwargs={"pk": self.corpus.pk}),
data={"name": "My dataset", "description": "My dataset for my experiments.", "state": "complete"},
......@@ -295,8 +314,18 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(created_dataset.id),
"name": "My dataset",
"description": "My dataset for my experiments.",
"sets": ["training", "test", "validation"],
"set_elements": {"test": 0, "training": 0, "validation": 0},
"sets": [
{
"id": str(ds.id),
"name": ds.name
}
for ds in created_dataset.sets.all()
],
"set_elements": {
"training": 0,
"test": 0,
"validation": 0,
},
"state": "open",
"creator": "Test user",
"task_id": None,
......@@ -307,10 +336,10 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_create_sets(self):
self.client.force_login(self.user)
with self.assertNumQueries(6):
with self.assertNumQueries(11):
response = self.client.post(
reverse("api:corpus-datasets", kwargs={"pk": self.corpus.pk}),
data={"name": "My dataset", "description": "My dataset for my experiments.", "sets": ["a", "b", "c", "d"]},
data={"name": "My dataset", "description": "My dataset for my experiments.", "set_names": ["a", "b", "c", "d"]},
format="json"
)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
......@@ -319,7 +348,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(created_dataset.id),
"name": "My dataset",
"description": "My dataset for my experiments.",
"sets": ["a", "b", "c", "d"],
"sets": [
{
"id": str(ds.id),
"name": ds.name
}
for ds in created_dataset.sets.all()
],
"set_elements": {"a": 0, "b": 0, "c": 0, "d": 0},
"state": "open",
"creator": "Test user",
......@@ -329,39 +364,39 @@ class TestDatasetsAPI(FixtureAPITestCase):
"updated": created_dataset.updated.isoformat().replace("+00:00", "Z"),
})
def test_create_sets_length(self):
def test_create_sets_empty_list(self):
self.client.force_login(self.user)
with self.assertNumQueries(3):
response = self.client.post(
reverse("api:corpus-datasets", kwargs={"pk": self.corpus.pk}),
data={"name": "My dataset", "description": "My dataset for my experiments.", "sets": []},
data={"name": "My dataset", "description": "My dataset for my experiments.", "set_names": []},
format="json"
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), {"sets": ["Either do not specify set names to use the default values, or specify a non-empty list of names."]})
self.assertDictEqual(response.json(), {"set_names": ["Either do not specify set names to use the default values, or specify a non-empty list of names."]})
def test_create_sets_unique_names(self):
self.client.force_login(self.user)
with self.assertNumQueries(3):
response = self.client.post(
reverse("api:corpus-datasets", kwargs={"pk": self.corpus.pk}),
data={"name": "My dataset", "description": "My dataset for my experiments.", "sets": ["a", "a", "b"]},
data={"name": "My dataset", "description": "My dataset for my experiments.", "set_names": ["a", "a", "b"]},
format="json"
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), {"sets": ["Set names must be unique."]})
self.assertDictEqual(response.json(), {"set_names": ["Set names must be unique."]})
def test_create_sets_blank_names(self):
self.client.force_login(self.user)
with self.assertNumQueries(3):
response = self.client.post(
reverse("api:corpus-datasets", kwargs={"pk": self.corpus.pk}),
data={"name": "My dataset", "description": "My dataset for my experiments.", "sets": [" ", " ", "b"]},
data={"name": "My dataset", "description": "My dataset for my experiments.", "set_names": [" ", " ", "b"]},
format="json"
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), {
"sets":
"set_names":
{
"0": ["This field may not be blank."],
"1": ["This field may not be blank."]
......@@ -376,13 +411,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
data={
"name": "My Dataset",
"description": "My dataset for my experiments.",
"sets": ["unit-00", "Etiam accumsan ullamcorper mauris eget mattis. Ut porttitor."]
"set_names": ["unit-00", "Etiam accumsan ullamcorper mauris eget mattis. Ut porttitor."]
},
format="json"
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), {
"sets": {
"set_names": {
"1": ["Ensure this field has no more than 50 characters."]
}
})
......@@ -396,7 +431,6 @@ class TestDatasetsAPI(FixtureAPITestCase):
data={
"name": "Shin Seiki Evangelion",
"description": "Omedeto!",
"sets": ["unit-01", "unit-00", "unit-02"],
},
format="json"
)
......@@ -412,7 +446,6 @@ class TestDatasetsAPI(FixtureAPITestCase):
data={
"name": "Shin Seiki Evangelion",
"description": "Omedeto!",
"sets": ["unit-01", "unit-00", "unit-02"],
},
format="json"
)
......@@ -428,7 +461,6 @@ class TestDatasetsAPI(FixtureAPITestCase):
data={
"name": "Shin Seiki Evangelion",
"description": "Omedeto!",
"sets": ["unit-01", "unit-00", "unit-02"],
},
format="json"
)
......@@ -446,7 +478,6 @@ class TestDatasetsAPI(FixtureAPITestCase):
data={
"name": "Shin Seiki Evangelion",
"description": "Omedeto!",
"sets": ["unit-01", "unit-00", "unit-02"],
},
format="json"
)
......@@ -476,7 +507,6 @@ class TestDatasetsAPI(FixtureAPITestCase):
data={
"name": "Another Dataset",
"description": "My dataset for my experiments.",
"sets": self.dataset.sets,
},
format="json"
)
......@@ -494,199 +524,21 @@ class TestDatasetsAPI(FixtureAPITestCase):
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), {"description": ["This field is required."]})
def test_update_add_sets(self):
def test_update_sets_forbidden(self):
self.client.force_login(self.user)
self.assertIsNone(self.dataset.task_id)
with self.assertNumQueries(8):
response = self.client.put(
reverse("api:dataset-update", kwargs={"pk": self.dataset.pk}),
data={
"name": "Shin Seiki Evangelion",
"description": "Omedeto!",
"sets": self.dataset.sets + ["unit-01", "unit-02"],
},
format="json"
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.dataset.refresh_from_db()
self.assertEqual(self.dataset.state, DatasetState.Open)
self.assertEqual(self.dataset.name, "Shin Seiki Evangelion")
self.assertEqual(self.dataset.description, "Omedeto!")
self.assertListEqual(self.dataset.sets, ["training", "test", "validation", "unit-01", "unit-02"])
self.assertIsNone(self.dataset.task_id)
def test_update_remove_sets(self):
"""
It is possible to remove many sets, no elements are moved
"""
# Remove ProcessDataset relation
ProcessDataset.objects.get(process=self.process, dataset=self.dataset).delete()
self.client.force_login(self.user)
dataset_elt = self.dataset.dataset_elements.create(element=self.page1, set="training")
with self.assertNumQueries(9):
response = self.client.put(
reverse("api:dataset-update", kwargs={"pk": self.dataset.pk}),
data={
"name": "Shin Seiki Evangelion",
"description": "Omedeto!",
# train and validation sets are removed
"sets": ["test"],
},
format="json"
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.dataset.refresh_from_db()
self.assertEqual(self.dataset.state, DatasetState.Open)
self.assertEqual(self.dataset.name, "Shin Seiki Evangelion")
self.assertEqual(self.dataset.description, "Omedeto!")
self.assertListEqual(self.dataset.sets, ["test"])
self.assertIsNone(self.dataset.task_id)
dataset_elt.refresh_from_db()
self.assertEqual(dataset_elt.element, self.page1)
self.assertEqual(dataset_elt.dataset, self.dataset)
# Element is still linked to a set that does not exist anymore on the dataset
self.assertEqual(dataset_elt.set, "training")
def test_update_sets_update_single_set(self):
"""
It is possible to rename a single set, if it is not referenced by a ProcessDataset
"""
ProcessDataset.objects.get(process=self.process, dataset=self.dataset, sets=["training", "test", "validation"]).delete()
self.client.force_login(self.user)
self.dataset.dataset_elements.create(element_id=self.page1.id, set="training")
self.dataset.dataset_elements.create(element_id=self.page2.id, set="validation")
self.dataset.dataset_elements.create(element_id=self.page3.id, set="validation")
with self.assertNumQueries(10):
response = self.client.put(
reverse("api:dataset-update", kwargs={"pk": self.dataset.pk}),
data={
"name": "Shin Seiki Evangelion",
"description": "Omedeto!",
# validation set is renamed to AAAAAAA
"sets": ["test", "training", "AAAAAAA"],
},
format="json"
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.dataset.refresh_from_db()
self.assertEqual(self.dataset.state, DatasetState.Open)
self.assertEqual(self.dataset.name, "Shin Seiki Evangelion")
self.assertEqual(self.dataset.description, "Omedeto!")
self.assertListEqual(self.dataset.sets, ["test", "training", "AAAAAAA"])
self.assertIsNone(self.dataset.task_id)
self.assertQuerysetEqual(
self.dataset.dataset_elements.values_list("set", "element__name").order_by("element__name"),
[
("training", "Volume 1, page 1r"),
("AAAAAAA", "Volume 1, page 1v"),
("AAAAAAA", "Volume 1, page 2r"),
]
)
def test_update_sets_processdataset_reference(self):
"""
If a dataset's sets are referenced by a ProcessDataset, they cannot be updated
"""
self.client.force_login(self.user)
self.dataset.dataset_elements.create(element_id=self.page1.id, set="training")
self.dataset.dataset_elements.create(element_id=self.page2.id, set="validation")
self.dataset.dataset_elements.create(element_id=self.page3.id, set="validation")
with self.assertNumQueries(4):
response = self.client.put(
reverse("api:dataset-update", kwargs={"pk": self.dataset.pk}),
data={
"name": "Shin Seiki Evangelion",
"description": "Omedeto!",
# validation set is renamed to AAAAAAA
"sets": ["test", "training", "AAAAAAA"],
},
format="json"
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), {"sets": ["These sets cannot be updated because one or more are selected in a dataset process."]})
self.dataset.refresh_from_db()
self.assertEqual(self.dataset.state, DatasetState.Open)
self.assertEqual(self.dataset.name, "First Dataset")
self.assertEqual(self.dataset.description, "dataset number one")
self.assertListEqual(self.dataset.sets, ["training", "test", "validation"])
self.assertIsNone(self.dataset.task_id)
self.assertQuerysetEqual(
self.dataset.dataset_elements.values_list("set", "element__name").order_by("element__name"),
[
("training", "Volume 1, page 1r"),
("validation", "Volume 1, page 1v"),
("validation", "Volume 1, page 2r"),
]
)
def test_update_sets_ambiguous(self):
"""
No more than one set can be updated
"""
# Remove ProcessDataset relation
ProcessDataset.objects.get(process=self.process, dataset=self.dataset).delete()
self.client.force_login(self.user)
with self.assertNumQueries(4):
response = self.client.put(
reverse("api:dataset-update", kwargs={"pk": self.dataset.pk}),
data={
"name": "Shin Seiki Evangelion",
"description": "Omedeto!",
"sets": ["test", "AAAAAAA", "BBBBBBB"],
},
format="json"
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.json(), {"sets": ["Updating those sets is ambiguous because several have changed."]})
def test_update_sets_length(self):
self.client.force_login(self.user)
with self.assertNumQueries(3):
response = self.client.put(
reverse("api:dataset-update", kwargs={"pk": self.dataset.pk}),
data={
"name": "Shin Seiki Evangelion",
"description": "Omedeto!",
"sets": []
"set_names": ["unit-01", "unit-02"],
},
format="json"
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), {"sets": ["Either do not specify set names to use the default values, or specify a non-empty list of names."]})
def test_update_sets_unique_names(self):
self.client.force_login(self.user)
with self.assertNumQueries(3):
response = self.client.put(
reverse("api:dataset-update", kwargs={"pk": self.dataset.pk}),
data={
"name": "Shin Seiki Evangelion",
"description": "Omedeto!",
"sets": ["unit-01", "unit-01", "unit-02"]
},
format="json"
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), {"sets": ["Set names must be unique."]})
def test_update_sets_name_too_long(self):
self.client.force_login(self.user)
with self.assertNumQueries(3):
response = self.client.put(
reverse("api:dataset-update", kwargs={"pk": self.dataset.pk}),
data={
"name": "My Dataset",
"description": "My dataset for my experiments.",
"sets": ["unit-00", "Etiam accumsan ullamcorper mauris eget mattis. Ut porttitor."]
},
format="json"
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), {
"sets": {
"1": ["Ensure this field has no more than 50 characters."]
}
})
self.assertDictEqual(response.json(), {"set_names": ["This API endpoint does not allow updating a dataset's sets."]})
def test_update_empty_or_blank_description_or_name(self):
self.client.force_login(self.user)
......@@ -696,15 +548,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
data={
"name": "",
"description": " ",
"sets": "",
},
format="json"
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), {
"name": ["This field may not be blank."],
"description": ["This field may not be blank."],
"sets": ['Expected a list of items but got type "str".'],
"description": ["This field may not be blank."]
})
def test_update_all_errors(self):
......@@ -715,7 +565,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
data={
"name": "",
"description": " ",
"sets": ["unit-00", "unit-00", "unit-02"]
"set_names": ["unit-00", "unit-00", "unit-02"]
},
format="json"
)
......@@ -723,7 +573,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
self.assertDictEqual(response.json(), {
"name": ["This field may not be blank."],
"description": ["This field may not be blank."],
"sets": ["Set names must be unique."]
"set_names": ["This API endpoint does not allow updating a dataset's sets."]
})
def test_update_state_requires_ponos_auth(self):
......@@ -819,7 +669,6 @@ class TestDatasetsAPI(FixtureAPITestCase):
data={
"name": "AA",
"description": "BB",
"sets": self.dataset.sets + ["CC"],
"state": new_state.value,
},
format="json"
......@@ -946,7 +795,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
self.assertEqual(self.dataset.state, DatasetState.Open)
self.assertEqual(self.dataset.name, "First Dataset")
self.assertEqual(self.dataset.description, "Omedeto!")
self.assertListEqual(self.dataset.sets, ["training", "test", "validation"])
self.assertCountEqual(list(self.dataset.sets.values_list("name", flat=True)), ["training", "test", "validation"])
def test_partial_update_empty_or_blank_description_or_name(self):
self.client.force_login(self.user)
......@@ -1022,23 +871,6 @@ class TestDatasetsAPI(FixtureAPITestCase):
self.dataset.refresh_from_db()
self.assertEqual(self.dataset.state, DatasetState.Open)
def test_partial_update_sets_name_too_long(self):
self.client.force_login(self.user)
with self.assertNumQueries(3):
response = self.client.patch(
reverse("api:dataset-update", kwargs={"pk": self.dataset.pk}),
data={
"sets": ["unit-00", "Etiam accumsan ullamcorper mauris eget mattis. Ut porttitor."]
},
format="json"
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), {
"sets": {
"1": ["Ensure this field has no more than 50 characters."]
}
})
def test_partial_update_ponos_task_state_forbidden(self):
"""Dataset's state update is limited to specific transitions"""
op, build, complete, error = [DatasetState[state] for state in ("Open", "Building", "Complete", "Error")]
......@@ -1093,7 +925,6 @@ class TestDatasetsAPI(FixtureAPITestCase):
data={
"name": "AA",
"description": "BB",
"sets": self.dataset.sets + ["CC"],
"state": new_state.value,
},
format="json"
......@@ -1150,7 +981,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_retrieve(self):
self.client.force_login(self.user)
with self.assertNumQueries(4):
with self.assertNumQueries(6):
response = self.client.get(
reverse("api:dataset-update", kwargs={"pk": self.dataset.pk})
)
......@@ -1160,7 +991,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"name": "First Dataset",
"description": "dataset number one",
"state": "open",
"sets": ["training", "test", "validation"],
"sets": [
{
"id": str(ds.id),
"name": ds.name
}
for ds in self.dataset.sets.all()
],
"set_elements": {"test": 0, "training": 0, "validation": 0},
"creator": "Test user",
"task_id": None,
......@@ -1173,7 +1010,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
self.client.force_login(self.user)
self.dataset.task = self.task
self.dataset.save()
with self.assertNumQueries(4):
with self.assertNumQueries(6):
response = self.client.get(
reverse("api:dataset-update", kwargs={"pk": self.dataset.pk})
)
......@@ -1224,7 +1061,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_delete(self):
self.client.force_login(self.user)
with self.assertNumQueries(6):
with self.assertNumQueries(7):
response = self.client.delete(
reverse("api:dataset-update", kwargs={"pk": self.dataset.pk}),
)
......@@ -1250,14 +1087,15 @@ class TestDatasetsAPI(FixtureAPITestCase):
"""
DestroyDataset also deletes DatasetElements
"""
self.dataset.dataset_elements.create(element_id=self.vol.id, set="test")
self.dataset.dataset_elements.create(element_id=self.vol.id, set="training")
self.dataset.dataset_elements.create(element_id=self.page1.id, set="training")
self.dataset.dataset_elements.create(element_id=self.page2.id, set="validation")
self.dataset.dataset_elements.create(element_id=self.page3.id, set="validation")
test_set, train_set, validation_set = self.dataset.sets.all().order_by("name")
test_set.set_elements.create(element_id=self.vol.id)
train_set.set_elements.create(element_id=self.vol.id, set="training")
train_set.set_elements.create(element_id=self.page1.id, set="training")
validation_set.set_elements.create(element_id=self.page2.id, set="validation")
validation_set.set_elements.create(element_id=self.page3.id, set="validation")
self.client.force_login(self.user)
with self.assertNumQueries(6):
with self.assertNumQueries(7):
response = self.client.delete(
reverse("api:dataset-update", kwargs={"pk": self.dataset.pk}),
)
......@@ -1266,7 +1104,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
with self.assertRaises(Dataset.DoesNotExist):
self.dataset.refresh_from_db()
self.assertFalse(self.dataset.dataset_elements.exists())
self.assertFalse(DatasetElement.objects.filter(set__dataset_id=self.dataset.id).exists())
# No elements should have been deleted
self.vol.refresh_from_db()
......@@ -1296,12 +1134,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
self.assertEqual(filter_rights_mock.call_args, call(self.user, Corpus, Role.Guest.value))
def test_list_elements_set_filter_wrong_set(self):
self.dataset.dataset_elements.create(element_id=self.page1.id, set="test")
test_set = self.dataset.sets.order_by("name").first()
test_set.set_elements.create(element_id=self.page1.id)
self.client.force_login(self.user)
with self.assertNumQueries(4):
response = self.client.get(
reverse("api:dataset-elements", kwargs={"pk": str(self.dataset.id)}),
data={"set": "aaaaa"}
data={"set": "training"}
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertDictEqual(response.json(), {
......@@ -1312,10 +1151,11 @@ class TestDatasetsAPI(FixtureAPITestCase):
})
def test_list_elements_set_filter(self):
self.dataset.dataset_elements.create(element_id=self.page1.id, set="test")
self.dataset.dataset_elements.create(element_id=self.page2.id, set="training")
test_set, train_set, _ = self.dataset.sets.all().order_by("name")
test_set.set_elements.create(element_id=self.page1.id)
train_set.set_elements.create(element_id=self.page2.id)
self.client.force_login(self.user)
with self.assertNumQueries(5):
with self.assertNumQueries(6):
response = self.client.get(
reverse("api:dataset-elements", kwargs={"pk": self.dataset.pk}),
data={"set": "training", "with_count": "true"},
......@@ -1326,15 +1166,17 @@ class TestDatasetsAPI(FixtureAPITestCase):
self.assertDictEqual(data, {"count": 1, "next": None, "previous": None})
self.assertEqual(len(results), 1)
dataset_element = results[0]
print(dataset_element)
self.assertEqual(dataset_element["element"]["id"], str(self.page2.id))
self.assertEqual(dataset_element["set"], "training")
@patch("arkindex.documents.models.Element.thumbnail", MagicMock(s3_url="s3_url"))
def test_list_elements(self):
self.dataset.dataset_elements.create(element_id=self.vol.id, set="test")
self.dataset.dataset_elements.create(element_id=self.page1.id, set="training")
self.dataset.dataset_elements.create(element_id=self.page2.id, set="validation")
self.dataset.dataset_elements.create(element_id=self.page3.id, set="validation")
test_set, train_set, validation_set = self.dataset.sets.all().order_by("name")
test_set.set_elements.create(element_id=self.vol.id)
train_set.set_elements.create(element_id=self.page1.id)
validation_set.set_elements.create(element_id=self.page2.id)
validation_set.set_elements.create(element_id=self.page3.id)
self.page3.confidence = 0.42
self.page3.mirrored = True
self.page3.rotation_angle = 42
......@@ -1523,7 +1365,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
self.dataset.state = state
self.dataset.save()
with self.subTest(state=state):
with self.assertNumQueries(4):
with self.assertNumQueries(5):
response = self.client.get(
reverse("api:dataset-elements", kwargs={"pk": self.dataset.pk}),
{"page_size": 3},
......@@ -1589,7 +1431,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_add_element_wrong_element(self):
element = self.private_corpus.elements.create(type=self.private_corpus.types.create(slug="folder"))
self.client.force_login(self.user)
with self.assertNumQueries(4):
with self.assertNumQueries(5):
response = self.client.post(
reverse("api:dataset-elements", kwargs={"pk": self.dataset.id}),
data={"set": "test", "element_id": str(element.id)},
......@@ -1602,7 +1444,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_add_element_wrong_set(self):
self.client.force_login(self.user)
with self.assertNumQueries(4):
with self.assertNumQueries(5):
response = self.client.post(
reverse("api:dataset-elements", kwargs={"pk": self.dataset.id}),
data={"set": "aaaaaaaaaaa", "element_id": str(self.vol.id)},
......@@ -1610,7 +1452,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), {
"set": ["This dataset has no set named aaaaaaaaaaa."],
"set": ["Object with name=aaaaaaaaaaa does not exist."],
})
def test_add_element_dataset_requires_open(self):
......@@ -1627,9 +1469,10 @@ class TestDatasetsAPI(FixtureAPITestCase):
self.assertListEqual(response.json(), ["You can only add elements to a dataset in an open state."])
def test_add_element_already_exists(self):
self.dataset.dataset_elements.create(element=self.page1, set="test")
test_set = self.dataset.sets.order_by("name").first()
test_set.set_elements.create(element=self.page1)
self.client.force_login(self.user)
with self.assertNumQueries(5):
with self.assertNumQueries(6):
response = self.client.post(
reverse("api:dataset-elements", kwargs={"pk": self.dataset.id}),
data={"set": "test", "element_id": str(self.page1.id)},
......@@ -1639,8 +1482,9 @@ class TestDatasetsAPI(FixtureAPITestCase):
self.assertDictEqual(response.json(), {"non_field_errors": ["This element is already part of this set."]})
def test_add_element(self):
train_set = self.dataset.sets.get(name="training")
self.client.force_login(self.user)
with self.assertNumQueries(10):
with self.assertNumQueries(11):
response = self.client.post(
reverse("api:dataset-elements", kwargs={"pk": self.dataset.id}),
data={"set": "training", "element_id": str(self.page1.id)},
......@@ -1648,10 +1492,12 @@ class TestDatasetsAPI(FixtureAPITestCase):
)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertQuerysetEqual(
self.dataset.dataset_elements.values_list("set", "element__name").order_by("element__name"),
train_set.set_elements.values_list("set__name", "element__name").order_by("element__name"),
[("training", "Volume 1, page 1r")]
)
# CreateDatasetElementSelection
def test_add_from_selection_requires_login(self):
with self.assertNumQueries(0):
response = self.client.post(reverse("api:dataset-elements-selection", kwargs={"pk": self.corpus.id}))
......@@ -1710,8 +1556,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
response = self.client.post(reverse("api:dataset-elements-selection", kwargs={"pk": self.corpus.id}))
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), {
"dataset_id": ["This field is required."],
"set": ["This field is required."],
"set_id": ["This field is required."],
})
def test_add_from_selection_wrong_values(self):
......@@ -1719,61 +1564,50 @@ class TestDatasetsAPI(FixtureAPITestCase):
with self.assertNumQueries(3):
response = self.client.post(
reverse("api:dataset-elements-selection", kwargs={"pk": self.corpus.id}),
data={"set": {}, "dataset_id": "AAA"},
data={"set_id": "AAA"},
format="json",
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), {
"dataset_id": ["“AAA” is not a valid UUID."],
"set": ["Not a valid string."],
"set_id": ["“AAA” is not a valid UUID."],
})
def test_add_from_selection_wrong_dataset(self):
self.private_corpus.memberships.create(user=self.user, level=Role.Contributor.value)
self.client.force_login(self.user)
with self.assertNumQueries(4):
response = self.client.post(
reverse("api:dataset-elements-selection", kwargs={"pk": self.corpus.id}),
data={"set": "aaa", "dataset_id": self.private_dataset.id},
data={"set_id": self.private_dataset_set.id},
format="json",
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), {
"dataset_id": [f"Dataset {self.private_dataset.id} is not part of corpus Unit Tests."],
"set_id": [f"Dataset {self.private_dataset.id} is not part of corpus Unit Tests."],
})
def test_add_from_selection_completed_dataset(self):
"""A dataset in the Complete state is immutable"""
test_set = self.dataset.sets.first()
self.client.force_login(self.user)
self.dataset.state = DatasetState.Complete
self.dataset.save()
with self.assertNumQueries(4):
response = self.client.post(
reverse("api:dataset-elements-selection", kwargs={"pk": self.corpus.id}),
data={"set": "aaa", "dataset_id": self.dataset.id},
format="json",
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), {
"dataset_id": [f"Dataset {self.dataset.id} is marked as completed."]
})
def test_add_from_selection_wrong_set(self):
self.client.force_login(self.user)
with self.assertNumQueries(4):
response = self.client.post(
reverse("api:dataset-elements-selection", kwargs={"pk": self.corpus.id}),
data={"set": "aaa", "dataset_id": self.dataset.id},
data={"set_id": test_set.id},
format="json",
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), {
"set": ["This dataset only allows one of training, test, validation."],
"set_id": [f"Dataset {self.dataset.id} is marked as completed."]
})
def test_add_from_selection(self):
self.dataset.dataset_elements.create(element=self.page1, set="training")
train_set = self.dataset.sets.get(name="training")
train_set.set_elements.create(element=self.page1)
self.assertQuerysetEqual(
self.dataset.dataset_elements.values_list("set", "element__name").order_by("element__name"),
train_set.set_elements.values_list("set__name", "element__name").order_by("element__name"),
[("training", "Volume 1, page 1r")]
)
self.user.selected_elements.set([self.vol, self.page1, self.page2])
......@@ -1782,12 +1616,12 @@ class TestDatasetsAPI(FixtureAPITestCase):
with self.assertNumQueries(6):
response = self.client.post(
reverse("api:dataset-elements-selection", kwargs={"pk": self.corpus.id}),
data={"set": "training", "dataset_id": self.dataset.id},
data={"set_id": str(train_set.id)},
format="json",
)
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
self.assertQuerysetEqual(
self.dataset.dataset_elements.values_list("set", "element__name").order_by("element__name"),
train_set.set_elements.values_list("set__name", "element__name").order_by("element__name"),
[
("training", "Volume 1"),
("training", "Volume 1, page 1r"),
......@@ -1819,8 +1653,9 @@ class TestDatasetsAPI(FixtureAPITestCase):
"""
A non authenticated user can list datasets of a public element
"""
self.dataset.dataset_elements.create(element=self.vol, set="train")
with self.assertNumQueries(3):
train_set = self.dataset.sets.get(name="training")
train_set.set_elements.create(element=self.vol)
with self.assertNumQueries(4):
response = self.client.get(reverse("api:element-datasets", kwargs={"pk": str(self.vol.id)}))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertDictEqual(response.json(), {
......@@ -1833,7 +1668,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(self.dataset.id),
"name": "First Dataset",
"description": "dataset number one",
"sets": ["training", "test", "validation"],
"sets": [
{
"id": str(ds.id),
"name": ds.name
}
for ds in self.dataset.sets.all()
],
"set_elements": None,
"state": "open",
"corpus_id": str(self.corpus.id),
......@@ -1842,7 +1683,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
"created": self.dataset.created.isoformat().replace("+00:00", "Z"),
"updated": self.dataset.updated.isoformat().replace("+00:00", "Z"),
},
"set": "train",
"set": "training",
"previous": None,
"next": None
}]
......@@ -1850,10 +1691,12 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_element_datasets(self):
self.client.force_login(self.user)
self.dataset.dataset_elements.create(element=self.page1, set="train")
self.dataset.dataset_elements.create(element=self.page1, set="validation")
self.dataset2.dataset_elements.create(element=self.page1, set="train")
with self.assertNumQueries(5):
_, train_set, validation_set = self.dataset.sets.all().order_by("name")
train_set.set_elements.create(element=self.page1, set="train")
validation_set.set_elements.create(element=self.page1, set="validation")
train_set_2 = self.dataset2.sets.get(name="training")
train_set_2.set_elements.create(element=self.page1, set="train")
with self.assertNumQueries(6):
response = self.client.get(reverse("api:element-datasets", kwargs={"pk": str(self.page1.id)}))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertDictEqual(response.json(), {
......@@ -1866,7 +1709,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(self.dataset.id),
"name": "First Dataset",
"description": "dataset number one",
"sets": ["training", "test", "validation"],
"sets": [
{
"id": str(ds.id),
"name": ds.name
}
for ds in self.dataset.sets.all()
],
"set_elements": None,
"state": "open",
"corpus_id": str(self.corpus.id),
......@@ -1875,7 +1724,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
"created": self.dataset.created.isoformat().replace("+00:00", "Z"),
"updated": self.dataset.updated.isoformat().replace("+00:00", "Z"),
},
"set": "train",
"set": "training",
"previous": None,
"next": None
}, {
......@@ -1883,7 +1732,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(self.dataset.id),
"name": "First Dataset",
"description": "dataset number one",
"sets": ["training", "test", "validation"],
"sets": [
{
"id": str(ds.id),
"name": ds.name
}
for ds in self.dataset.sets.all()
],
"set_elements": None,
"state": "open",
"corpus_id": str(self.corpus.id),
......@@ -1900,7 +1755,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(self.dataset2.id),
"name": "Second Dataset",
"description": "dataset number two",
"sets": ["training", "test", "validation"],
"sets": [
{
"id": str(ds.id),
"name": ds.name
}
for ds in self.dataset2.sets.all()
],
"set_elements": None,
"state": "open",
"corpus_id": str(self.corpus.id),
......@@ -1909,7 +1770,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
"created": self.dataset2.created.isoformat().replace("+00:00", "Z"),
"updated": self.dataset2.updated.isoformat().replace("+00:00", "Z"),
},
"set": "train",
"set": "training",
"previous": None,
"next": None
}]
......@@ -1917,10 +1778,12 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_element_datasets_with_neighbors_false(self):
self.client.force_login(self.user)
self.dataset.dataset_elements.create(element=self.page1, set="train")
self.dataset.dataset_elements.create(element=self.page1, set="validation")
self.dataset2.dataset_elements.create(element=self.page1, set="train")
with self.assertNumQueries(5):
_, train_set, validation_set = self.dataset.sets.all().order_by("name")
train_set_2 = self.dataset2.sets.get(name="training")
train_set.set_elements.create(element=self.page1)
validation_set.set_elements.create(element=self.page1)
train_set_2.set_elements.create(element=self.page1)
with self.assertNumQueries(6):
response = self.client.get(reverse("api:element-datasets", kwargs={"pk": str(self.page1.id)}), {"with_neighbors": False})
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertDictEqual(response.json(), {
......@@ -1933,7 +1796,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(self.dataset.id),
"name": "First Dataset",
"description": "dataset number one",
"sets": ["training", "test", "validation"],
"sets": [
{
"id": str(ds.id),
"name": ds.name
}
for ds in self.dataset.sets.all()
],
"set_elements": None,
"state": "open",
"corpus_id": str(self.corpus.id),
......@@ -1942,7 +1811,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
"created": self.dataset.created.isoformat().replace("+00:00", "Z"),
"updated": self.dataset.updated.isoformat().replace("+00:00", "Z"),
},
"set": "train",
"set": "training",
"previous": None,
"next": None
}, {
......@@ -1950,7 +1819,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(self.dataset.id),
"name": "First Dataset",
"description": "dataset number one",
"sets": ["training", "test", "validation"],
"sets": [
{
"id": str(ds.id),
"name": ds.name
}
for ds in self.dataset.sets.all()
],
"set_elements": None,
"state": "open",
"corpus_id": str(self.corpus.id),
......@@ -1967,7 +1842,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(self.dataset2.id),
"name": "Second Dataset",
"description": "dataset number two",
"sets": ["training", "test", "validation"],
"sets": [
{
"id": str(ds.id),
"name": ds.name
}
for ds in self.dataset2.sets.all()
],
"set_elements": None,
"state": "open",
"corpus_id": str(self.corpus.id),
......@@ -1976,7 +1857,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
"created": self.dataset2.created.isoformat().replace("+00:00", "Z"),
"updated": self.dataset2.updated.isoformat().replace("+00:00", "Z"),
},
"set": "train",
"set": "training",
"previous": None,
"next": None
}]
......@@ -1984,12 +1865,14 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_element_datasets_with_neighbors(self):
self.client.force_login(self.user)
self.dataset.dataset_elements.create(element=self.page1, set="train")
self.dataset.dataset_elements.create(element=self.page2, set="train")
self.dataset.dataset_elements.create(element=self.page3, set="train")
self.dataset.dataset_elements.create(element=self.page1, set="validation")
self.dataset2.dataset_elements.create(element=self.page1, set="train")
self.dataset2.dataset_elements.create(element=self.page3, set="train")
_, train_set, validation_set = self.dataset.sets.all().order_by("name")
train_set_2 = self.dataset2.sets.get(name="training")
train_set.set_elements.create(element=self.page1)
train_set.set_elements.create(element=self.page2)
train_set.set_elements.create(element=self.page3)
validation_set.set_elements.create(element=self.page1)
train_set_2.set_elements.create(element=self.page1)
train_set_2.set_elements.create(element=self.page3)
# Results are alphabetically ordered and must not depend on the random page UUIDs
sorted_dataset_elements = sorted([str(self.page1.id), str(self.page2.id), str(self.page3.id)])
......@@ -1997,9 +1880,10 @@ class TestDatasetsAPI(FixtureAPITestCase):
sorted_dataset2_elements = sorted([str(self.page1.id), str(self.page3.id)])
page1_index_2 = sorted_dataset2_elements.index(str(self.page1.id))
with self.assertNumQueries(7):
with self.assertNumQueries(8):
response = self.client.get(reverse("api:element-datasets", kwargs={"pk": str(self.page1.id)}), {"with_neighbors": True})
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.maxDiff = None
self.assertDictEqual(response.json(), {
"count": 3,
"next": None,
......@@ -2010,7 +1894,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(self.dataset.id),
"name": "First Dataset",
"description": "dataset number one",
"sets": ["training", "test", "validation"],
"sets": [
{
"id": str(ds.id),
"name": ds.name
}
for ds in self.dataset.sets.all()
],
"set_elements": None,
"state": "open",
"corpus_id": str(self.corpus.id),
......@@ -2019,7 +1909,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
"created": self.dataset.created.isoformat().replace("+00:00", "Z"),
"updated": self.dataset.updated.isoformat().replace("+00:00", "Z"),
},
"set": "train",
"set": "training",
"previous": (
sorted_dataset_elements[page1_index_1 - 1]
if page1_index_1 - 1 >= 0
......@@ -2035,7 +1925,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(self.dataset.id),
"name": "First Dataset",
"description": "dataset number one",
"sets": ["training", "test", "validation"],
"sets": [
{
"id": str(ds.id),
"name": ds.name
}
for ds in self.dataset.sets.all()
],
"set_elements": None,
"state": "open",
"corpus_id": str(self.corpus.id),
......@@ -2052,7 +1948,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(self.dataset2.id),
"name": "Second Dataset",
"description": "dataset number two",
"sets": ["training", "test", "validation"],
"sets": [
{
"id": str(ds.id),
"name": ds.name
}
for ds in self.dataset2.sets.all()
],
"set_elements": None,
"state": "open",
"corpus_id": str(self.corpus.id),
......@@ -2061,7 +1963,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
"created": self.dataset2.created.isoformat().replace("+00:00", "Z"),
"updated": self.dataset2.updated.isoformat().replace("+00:00", "Z"),
},
"set": "train",
"set": "training",
"previous": (
sorted_dataset2_elements[page1_index_2 - 1]
if page1_index_2 == 1
......@@ -2136,13 +2038,14 @@ class TestDatasetsAPI(FixtureAPITestCase):
self.dataset.state = DatasetState.Error
self.dataset.task = self.task
self.dataset.save()
self.dataset.dataset_elements.create(element=self.page1, set="test")
self.dataset.dataset_elements.create(element=self.page1, set="validation")
self.dataset.dataset_elements.create(element=self.vol, set="validation")
test_set, _, validation_set = self.dataset.sets.all().order_by("name")
test_set.set_elements.create(element=self.page1)
validation_set.set_elements.create(element=self.page1)
validation_set.set_elements.create(element=self.vol)
self.assertCountEqual(self.corpus.datasets.values_list("name", flat=True), ["First Dataset", "Second Dataset"])
self.client.force_login(self.user)
with self.assertNumQueries(12):
with self.assertNumQueries(16):
response = self.client.post(
reverse("api:dataset-clone", kwargs={"pk": self.dataset.id}),
format="json",
......@@ -2155,9 +2058,11 @@ class TestDatasetsAPI(FixtureAPITestCase):
])
data = response.json()
clone = self.corpus.datasets.get(id=data["id"])
test_clone, train_clone, val_clone = clone.sets.all().order_by("name")
self.assertEqual(clone.creator, self.user)
data.pop("created")
data.pop("updated")
cloned_sets = data.pop("sets")
self.assertDictEqual(
response.json(),
{
......@@ -2166,14 +2071,27 @@ class TestDatasetsAPI(FixtureAPITestCase):
"description": self.dataset.description,
"creator": self.user.display_name,
"corpus_id": str(self.corpus.id),
"sets": ["training", "test", "validation"],
"set_elements": {"test": 1, "training": 0, "validation": 2},
"state": DatasetState.Open.value,
"task_id": str(self.task.id),
},
)
self.assertCountEqual(cloned_sets, [
{
"name": "training",
"id": str(train_clone.id)
},
{
"name": "test",
"id": str(test_clone.id)
},
{
"name": "validation",
"id": str(val_clone.id)
}
])
self.assertQuerysetEqual(
clone.dataset_elements.values_list("set", "element__name").order_by("element__name", "set"),
DatasetElement.objects.filter(set__dataset_id=clone.id).values_list("set__name", "element__name").order_by("element__name", "set__name"),
[
("validation", "Volume 1"),
("test", "Volume 1, page 1r"),
......@@ -2184,7 +2102,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_clone_existing_name(self):
self.corpus.datasets.create(name="Clone of First Dataset", creator=self.user)
self.client.force_login(self.user)
with self.assertNumQueries(11):
with self.assertNumQueries(15):
response = self.client.post(
reverse("api:dataset-clone", kwargs={"pk": self.dataset.id}),
format="json",
......@@ -2198,18 +2116,26 @@ class TestDatasetsAPI(FixtureAPITestCase):
])
data = response.json()
data.pop("id")
data.pop("created")
data.pop("updated")
cloned_dataset = Dataset.objects.get(id=data["id"])
self.maxDiff = None
self.assertDictEqual(
response.json(),
{
"id": str(cloned_dataset.id),
"name": "Clone of First Dataset 1",
"description": self.dataset.description,
"creator": self.user.display_name,
"corpus_id": str(self.corpus.id),
"sets": self.dataset.sets,
"set_elements": {k: 0 for k in self.dataset.sets},
"sets": [
{
"id": str(ds.id),
"name": ds.name
}
for ds in cloned_dataset.sets.all()
],
"set_elements": {str(k.name): 0 for k in self.dataset.sets.all()},
"state": DatasetState.Open.value,
"task_id": None,
},
......@@ -2218,7 +2144,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_clone_name_too_long(self):
dataset = self.corpus.datasets.create(name="A" * 99, creator=self.user)
self.client.force_login(self.user)
with self.assertNumQueries(11):
with self.assertNumQueries(14):
response = self.client.post(
reverse("api:dataset-clone", kwargs={"pk": dataset.id}),
format="json",
......@@ -2236,7 +2162,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
response = self.client.delete(reverse(
"api:dataset-element",
kwargs={"dataset": str(self.dataset.id), "element": str(self.page1.id)})
+ "?set=train"
+ "?set=training"
)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
......@@ -2247,28 +2173,29 @@ class TestDatasetsAPI(FixtureAPITestCase):
response = self.client.delete(reverse(
"api:dataset-element",
kwargs={"dataset": str(self.dataset.id), "element": str(self.page1.id)})
+ "?set=train"
+ "?set=training"
)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
@patch("arkindex.project.mixins.has_access", return_value=False)
def test_destroy_dataset_element_requires_contributor(self, has_access_mock):
self.client.force_login(self.read_user)
self.dataset.dataset_elements.create(element=self.page1, set="train")
self.dataset.dataset_elements.create(element=self.page1, set="validation")
self.assertEqual(self.dataset.dataset_elements.filter(set="train").count(), 1)
self.assertEqual(self.dataset.dataset_elements.filter(set="validation").count(), 1)
_, train_set, validation_set = self.dataset.sets.all().order_by("name")
train_set.set_elements.create(element=self.page1)
validation_set.set_elements.create(element=self.page1)
self.assertEqual(train_set.set_elements.count(), 1)
self.assertEqual(validation_set.set_elements.count(), 1)
with self.assertNumQueries(3):
response = self.client.delete(reverse(
"api:dataset-element",
kwargs={"dataset": str(self.dataset.id), "element": str(self.page1.id)})
+ "?set=train"
+ "?set=training"
)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertDictEqual(response.json(), {"detail": "You need a Contributor access to the dataset to perform this action."})
self.dataset.refresh_from_db()
self.assertEqual(self.dataset.dataset_elements.filter(set="train").count(), 1)
self.assertEqual(self.dataset.dataset_elements.filter(set="validation").count(), 1)
self.assertEqual(train_set.set_elements.count(), 1)
self.assertEqual(validation_set.set_elements.count(), 1)
self.assertEqual(has_access_mock.call_count, 1)
self.assertEqual(has_access_mock.call_args, call(self.read_user, self.corpus, Role.Contributor.value, skip_public=False))
......@@ -2285,23 +2212,24 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_destroy_dataset_element_requires_open_dataset(self):
self.client.force_login(self.user)
self.dataset.dataset_elements.create(element=self.page1, set="train")
self.dataset.dataset_elements.create(element=self.page1, set="validation")
_, train_set, validation_set = self.dataset.sets.all().order_by("name")
train_set.set_elements.create(element=self.page1)
validation_set.set_elements.create(element=self.page1)
self.dataset.state = DatasetState.Error
self.dataset.save()
self.assertEqual(self.dataset.dataset_elements.filter(set="train").count(), 1)
self.assertEqual(self.dataset.dataset_elements.filter(set="validation").count(), 1)
self.assertEqual(train_set.set_elements.count(), 1)
self.assertEqual(validation_set.set_elements.count(), 1)
with self.assertNumQueries(3):
response = self.client.delete(reverse(
"api:dataset-element",
kwargs={"dataset": str(self.dataset.id), "element": str(self.page1.id)})
+ "?set=train"
+ "?set=training"
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), {"dataset": ["Elements can only be removed from open Datasets."]})
self.dataset.refresh_from_db()
self.assertEqual(self.dataset.dataset_elements.filter(set="train").count(), 1)
self.assertEqual(self.dataset.dataset_elements.filter(set="validation").count(), 1)
self.assertEqual(train_set.set_elements.count(), 1)
self.assertEqual(validation_set.set_elements.count(), 1)
def test_destroy_dataset_element_dataset_doesnt_exist(self):
self.client.force_login(self.user)
......@@ -2309,7 +2237,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
response = self.client.delete(reverse(
"api:dataset-element",
kwargs={"dataset": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "element": str(self.page1.id)})
+ "?set=train"
+ "?set=training"
)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertDictEqual(response.json(), {"detail": "Not found."})
......@@ -2331,49 +2259,52 @@ class TestDatasetsAPI(FixtureAPITestCase):
response = self.client.delete(reverse(
"api:dataset-element",
kwargs={"dataset": str(self.dataset.id), "element": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"})
+ "?set=train"
+ "?set=training"
)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertDictEqual(response.json(), {"detail": "Not found."})
def test_destroy_dataset_element_element_not_in_dataset(self):
self.dataset.dataset_elements.create(element=self.page1, set="train")
train_set = self.dataset.sets.get(name="training")
train_set.set_elements.create(element=self.page1, set="train")
self.client.force_login(self.user)
with self.assertNumQueries(3):
response = self.client.delete(reverse(
"api:dataset-element",
kwargs={"dataset": str(self.dataset.id), "element": str(self.page2.id)})
+ "?set=train"
+ "?set=training"
)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertDictEqual(response.json(), {"detail": "Not found."})
def test_destroy_dataset_element_wrong_set(self):
self.dataset.dataset_elements.create(element=self.page1, set="train")
self.dataset.dataset_elements.create(element=self.page2, set="validation")
_, train_set, validation_set = self.dataset.sets.all().order_by("name")
train_set.set_elements.create(element=self.page1)
validation_set.set_elements.create(element=self.page1)
self.client.force_login(self.user)
with self.assertNumQueries(3):
response = self.client.delete(reverse(
"api:dataset-element",
kwargs={"dataset": str(self.dataset.id), "element": str(self.page2.id)})
+ "?set=train"
+ "?set=training"
)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertDictEqual(response.json(), {"detail": "Not found."})
def test_destroy_dataset_element(self):
self.client.force_login(self.user)
self.dataset.dataset_elements.create(element=self.page1, set="train")
self.dataset.dataset_elements.create(element=self.page1, set="validation")
self.assertEqual(self.dataset.dataset_elements.filter(set="train").count(), 1)
self.assertEqual(self.dataset.dataset_elements.filter(set="validation").count(), 1)
_, train_set, validation_set = self.dataset.sets.all().order_by("name")
train_set.set_elements.create(element=self.page1)
validation_set.set_elements.create(element=self.page1)
self.assertEqual(train_set.set_elements.count(), 1)
self.assertEqual(validation_set.set_elements.count(), 1)
with self.assertNumQueries(4):
response = self.client.delete(reverse(
"api:dataset-element",
kwargs={"dataset": str(self.dataset.id), "element": str(self.page1.id)})
+ "?set=train"
+ "?set=training"
)
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
self.dataset.refresh_from_db()
self.assertEqual(self.dataset.dataset_elements.filter(set="train").count(), 0)
self.assertEqual(self.dataset.dataset_elements.filter(set="validation").count(), 1)
self.assertEqual(train_set.set_elements.count(), 0)
self.assertEqual(validation_set.set_elements.count(), 1)