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", "model": "process.process",
<<<<<<< HEAD
"pk": "76506eee-43ab-4caa-966c-9e8e5d10ef93", "pk": "76506eee-43ab-4caa-966c-9e8e5d10ef93",
=======
"pk": "432278f2-a60e-4865-b474-de83833d0497",
"fields": { "fields": {
"created": "2020-02-02T01:23:45.678Z", "created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z",
"name": null, "name": null,
"creator": 1, "creator": 1,
"corpus": null, "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", "mode": "local",
"activity_state": "disabled", "activity_state": "disabled",
"started": null, "started": null,
...@@ -73,6 +171,14 @@ ...@@ -73,6 +171,14 @@
"started": null, "started": null,
"finished": null, "finished": null,
"farm": 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, "element": null,
"folder_type": null, "folder_type": null,
"element_type": null, "element_type": null,
...@@ -91,6 +197,7 @@ ...@@ -91,6 +197,7 @@
}, },
{ {
"model": "process.repository", "model": "process.repository",
<<<<<<< HEAD
"pk": "bcfed350-d5be-4f27-b66a-042be3e6ee64", "pk": "bcfed350-d5be-4f27-b66a-042be3e6ee64",
"fields": { "fields": {
"url": "http://gitlab/repo" "url": "http://gitlab/repo"
...@@ -99,17 +206,35 @@ ...@@ -99,17 +206,35 @@
{ {
"model": "process.repository", "model": "process.repository",
"pk": "e3f470b1-fc46-4bc1-8117-30e1c62962b7", "pk": "e3f470b1-fc46-4bc1-8117-30e1c62962b7",
=======
"pk": "565a09bb-0f64-49b5-acbf-8e5fde104cbb",
>>>>>>> 7912af40 (wip API endpoints)
"fields": { "fields": {
"url": "http://my_repo.fake/workers/worker" "url": "http://my_repo.fake/workers/worker"
} }
}, },
{
"model": "process.repository",
"pk": "deea5468-0e94-4215-bef3-efb8d18f0065",
"fields": {
"url": "http://gitlab/repo"
}
},
{ {
"model": "process.revision", "model": "process.revision",
<<<<<<< HEAD
"pk": "2d087aa1-82ba-4ec5-af14-c19e4213f913", "pk": "2d087aa1-82ba-4ec5-af14-c19e4213f913",
"fields": { "fields": {
"created": "2020-02-02T01:23:45.678Z", "created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z",
"repo": "e3f470b1-fc46-4bc1-8117-30e1c62962b7", "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", "hash": "1337",
"message": "My w0rk3r", "message": "My w0rk3r",
"author": "Test user" "author": "Test user"
...@@ -117,11 +242,19 @@ ...@@ -117,11 +242,19 @@
}, },
{ {
"model": "process.revision", "model": "process.revision",
<<<<<<< HEAD
"pk": "7876a435-f3a5-40f8-b30b-f388f22019bf", "pk": "7876a435-f3a5-40f8-b30b-f388f22019bf",
"fields": { "fields": {
"created": "2020-02-02T01:23:45.678Z", "created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z",
"repo": "bcfed350-d5be-4f27-b66a-042be3e6ee64", "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", "hash": "42",
"message": "Salve", "message": "Salve",
"author": "Some user" "author": "Some user"
...@@ -129,6 +262,7 @@ ...@@ -129,6 +262,7 @@
}, },
{ {
"model": "process.worker", "model": "process.worker",
<<<<<<< HEAD
"pk": "12b2344f-4871-40ad-aa1b-efaa70b5823f", "pk": "12b2344f-4871-40ad-aa1b-efaa70b5823f",
"fields": { "fields": {
"name": "Document layout analyser", "name": "Document layout analyser",
...@@ -136,12 +270,22 @@ ...@@ -136,12 +270,22 @@
"type": "e84d4893-ae73-4162-acb6-13d606587644", "type": "e84d4893-ae73-4162-acb6-13d606587644",
"description": "", "description": "",
"repository": "e3f470b1-fc46-4bc1-8117-30e1c62962b7", "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, "public": false,
"archived": null "archived": null
} }
}, },
{ {
"model": "process.worker", "model": "process.worker",
<<<<<<< HEAD
"pk": "1a18dc1d-49e3-4724-b1e3-cbc8da483610", "pk": "1a18dc1d-49e3-4724-b1e3-cbc8da483610",
"fields": { "fields": {
"name": "Worker requiring a GPU", "name": "Worker requiring a GPU",
...@@ -149,12 +293,48 @@ ...@@ -149,12 +293,48 @@
"type": "20d3065e-0ef7-428b-888f-177f59e6ddd0", "type": "20d3065e-0ef7-428b-888f-177f59e6ddd0",
"description": "", "description": "",
"repository": "e3f470b1-fc46-4bc1-8117-30e1c62962b7", "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, "public": false,
"archived": null "archived": null
} }
}, },
{ {
"model": "process.worker", "model": "process.worker",
<<<<<<< HEAD
"pk": "219444d1-2a84-49f4-94d6-d5c21e36fcb9", "pk": "219444d1-2a84-49f4-94d6-d5c21e36fcb9",
"fields": { "fields": {
"name": "Generic worker with a Model", "name": "Generic worker with a Model",
...@@ -173,6 +353,13 @@ ...@@ -173,6 +353,13 @@
"name": "Custom worker", "name": "Custom worker",
"slug": "custom", "slug": "custom",
"type": "64a618df-09d0-47eb-b999-02ceb0a114a4", "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": "", "description": "",
"repository": null, "repository": null,
"public": false, "public": false,
...@@ -181,6 +368,7 @@ ...@@ -181,6 +368,7 @@
}, },
{ {
"model": "process.worker", "model": "process.worker",
<<<<<<< HEAD
"pk": "9775f6a1-6238-4943-b245-b69bde621912", "pk": "9775f6a1-6238-4943-b245-b69bde621912",
"fields": { "fields": {
"name": "Recognizer", "name": "Recognizer",
...@@ -201,12 +389,22 @@ ...@@ -201,12 +389,22 @@
"type": "3a0b2c85-f53f-4ce7-942d-37c08f356880", "type": "3a0b2c85-f53f-4ce7-942d-37c08f356880",
"description": "", "description": "",
"repository": "e3f470b1-fc46-4bc1-8117-30e1c62962b7", "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, "public": false,
"archived": null "archived": null
} }
}, },
{ {
"model": "process.workertype", "model": "process.workertype",
<<<<<<< HEAD
"pk": "20d3065e-0ef7-428b-888f-177f59e6ddd0", "pk": "20d3065e-0ef7-428b-888f-177f59e6ddd0",
"fields": { "fields": {
"created": "2020-02-02T01:23:45.678Z", "created": "2020-02-02T01:23:45.678Z",
...@@ -218,6 +416,9 @@ ...@@ -218,6 +416,9 @@
{ {
"model": "process.workertype", "model": "process.workertype",
"pk": "3a0b2c85-f53f-4ce7-942d-37c08f356880", "pk": "3a0b2c85-f53f-4ce7-942d-37c08f356880",
=======
"pk": "1adb460c-149c-4b77-9d56-9a306ab49993",
>>>>>>> 7912af40 (wip API endpoints)
"fields": { "fields": {
"created": "2020-02-02T01:23:45.678Z", "created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z",
...@@ -227,7 +428,11 @@ ...@@ -227,7 +428,11 @@
}, },
{ {
"model": "process.workertype", "model": "process.workertype",
<<<<<<< HEAD
"pk": "50729501-d9c4-473d-803f-a7cf25f0f9bd", "pk": "50729501-d9c4-473d-803f-a7cf25f0f9bd",
=======
"pk": "3c93cbb2-97a1-4b0c-8ddf-98ee99760805",
>>>>>>> 7912af40 (wip API endpoints)
"fields": { "fields": {
"created": "2020-02-02T01:23:45.678Z", "created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z",
...@@ -237,7 +442,11 @@ ...@@ -237,7 +442,11 @@
}, },
{ {
"model": "process.workertype", "model": "process.workertype",
<<<<<<< HEAD
"pk": "64a618df-09d0-47eb-b999-02ceb0a114a4", "pk": "64a618df-09d0-47eb-b999-02ceb0a114a4",
=======
"pk": "8f8a02cd-e97f-479c-96d1-8d019f31e25b",
>>>>>>> 7912af40 (wip API endpoints)
"fields": { "fields": {
"created": "2020-02-02T01:23:45.678Z", "created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z",
...@@ -247,19 +456,118 @@ ...@@ -247,19 +456,118 @@
}, },
{ {
"model": "process.workertype", "model": "process.workertype",
<<<<<<< HEAD
"pk": "e84d4893-ae73-4162-acb6-13d606587644", "pk": "e84d4893-ae73-4162-acb6-13d606587644",
=======
"pk": "c2db222a-f974-4c20-979e-9e95e1a80ee7",
>>>>>>> 7912af40 (wip API endpoints)
"fields": { "fields": {
"created": "2020-02-02T01:23:45.678Z", "created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z",
"slug": "dla", "slug": "dla",
"display_name": "Document Layout Analysis" "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", "model": "process.workerversion",
<<<<<<< HEAD
"pk": "229fc630-728b-421b-a2de-9618bd8e401f", "pk": "229fc630-728b-421b-a2de-9618bd8e401f",
"fields": { "fields": {
"worker": "667a82ac-a19a-4e97-9239-35a3026246cb", "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, "revision": null,
"version": 1, "version": 1,
"configuration": { "configuration": {
...@@ -276,6 +584,7 @@ ...@@ -276,6 +584,7 @@
}, },
{ {
"model": "process.workerversion", "model": "process.workerversion",
<<<<<<< HEAD
"pk": "57cd018c-43e2-491e-9684-3b939df52921", "pk": "57cd018c-43e2-491e-9684-3b939df52921",
"fields": { "fields": {
"worker": "df6dbbb2-0526-46f9-8da2-5ada8f93826a", "worker": "df6dbbb2-0526-46f9-8da2-5ada8f93826a",
...@@ -354,6 +663,12 @@ ...@@ -354,6 +663,12 @@
"fields": { "fields": {
"worker": "9775f6a1-6238-4943-b245-b69bde621912", "worker": "9775f6a1-6238-4943-b245-b69bde621912",
"revision": "2d087aa1-82ba-4ec5-af14-c19e4213f913", "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, "version": null,
"configuration": { "configuration": {
"test": 42 "test": 42
...@@ -361,18 +676,60 @@ ...@@ -361,18 +676,60 @@
"state": "available", "state": "available",
"gpu_usage": "disabled", "gpu_usage": "disabled",
"model_usage": "disabled", "model_usage": "disabled",
<<<<<<< HEAD
"docker_image": null, "docker_image": null,
"docker_image_iid": "registry.somewhere.com/something:latest", "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", "created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z" "updated": "2020-02-02T01:23:45.678Z"
} }
}, },
{ {
"model": "process.workerrun", "model": "process.workerrun",
<<<<<<< HEAD
"pk": "14356945-e3a4-4d8b-b9b2-b4bc5e9287cc", "pk": "14356945-e3a4-4d8b-b9b2-b4bc5e9287cc",
"fields": { "fields": {
"process": "76506eee-43ab-4caa-966c-9e8e5d10ef93", "process": "76506eee-43ab-4caa-966c-9e8e5d10ef93",
"version": "229fc630-728b-421b-a2de-9618bd8e401f", "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, "model_version": null,
"parents": "[]", "parents": "[]",
"configuration": null, "configuration": null,
...@@ -384,6 +741,7 @@ ...@@ -384,6 +741,7 @@
}, },
{ {
"model": "process.workerrun", "model": "process.workerrun",
<<<<<<< HEAD
"pk": "2f828b7f-c169-4a8e-9555-0b4060e05641", "pk": "2f828b7f-c169-4a8e-9555-0b4060e05641",
"fields": { "fields": {
"process": "7a6fed8c-ed9c-4714-8036-7048462ce0f2", "process": "7a6fed8c-ed9c-4714-8036-7048462ce0f2",
...@@ -418,6 +776,12 @@ ...@@ -418,6 +776,12 @@
"fields": { "fields": {
"process": "b6b7dbcb-e134-4274-93fd-9d6d06818c6f", "process": "b6b7dbcb-e134-4274-93fd-9d6d06818c6f",
"version": "229fc630-728b-421b-a2de-9618bd8e401f", "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, "model_version": null,
"parents": "[]", "parents": "[]",
"configuration": null, "configuration": null,
...@@ -429,7 +793,11 @@ ...@@ -429,7 +793,11 @@
}, },
{ {
"model": "documents.corpus", "model": "documents.corpus",
<<<<<<< HEAD
"pk": "f34313ec-45ec-4ac4-92e5-43d7eb045c12", "pk": "f34313ec-45ec-4ac4-92e5-43d7eb045c12",
=======
"pk": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
>>>>>>> 7912af40 (wip API endpoints)
"fields": { "fields": {
"created": "2020-02-02T01:23:45.678Z", "created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z",
...@@ -442,11 +810,16 @@ ...@@ -442,11 +810,16 @@
}, },
{ {
"model": "documents.elementtype", "model": "documents.elementtype",
<<<<<<< HEAD
"pk": "329625fb-1514-492a-9567-e231f7646648", "pk": "329625fb-1514-492a-9567-e231f7646648",
"fields": { "fields": {
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12", "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, "folder": false,
"indexable": false, "indexable": false,
"color": "28b62c" "color": "28b62c"
...@@ -454,23 +827,23 @@ ...@@ -454,23 +827,23 @@
}, },
{ {
"model": "documents.elementtype", "model": "documents.elementtype",
"pk": "ab1c133b-71d0-4928-b388-7c12345a8416", "pk": "18027add-0729-400d-a225-60927f1dd2d9",
"fields": { "fields": {
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12", "corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"slug": "text_line", "slug": "volume",
"display_name": "Line", "display_name": "Volume",
"folder": false, "folder": true,
"indexable": false, "indexable": false,
"color": "28b62c" "color": "28b62c"
} }
}, },
{ {
"model": "documents.elementtype", "model": "documents.elementtype",
"pk": "c196f23a-6843-48e1-a885-c7cda27e64ca", "pk": "1ca6552d-f876-4d2a-a167-38736ebed338",
"fields": { "fields": {
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12", "corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"slug": "act", "slug": "text_line",
"display_name": "Act", "display_name": "Line",
"folder": false, "folder": false,
"indexable": false, "indexable": false,
"color": "28b62c" "color": "28b62c"
...@@ -478,10 +851,72 @@ ...@@ -478,10 +851,72 @@
}, },
{ {
"model": "documents.elementtype", "model": "documents.elementtype",
"pk": "d15930a5-ebb8-40aa-968d-8bd2cf504230", "pk": "2bee95f7-e16e-41ae-a61d-51b9a22c3fa0",
"fields": { "fields": {
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12", "corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
"slug": "word", "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", "display_name": "Word",
"folder": false, "folder": false,
"indexable": false, "indexable": false,
...@@ -518,65 +953,217 @@ ...@@ -518,65 +953,217 @@
"fields": { "fields": {
"element": "9fc5e0a3-9afb-493e-bf0f-fc2998ba4ba4", "element": "9fc5e0a3-9afb-493e-bf0f-fc2998ba4ba4",
"path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\"]", "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 "ordering": 0
} }
}, },
{ {
"model": "documents.elementpath", "model": "documents.elementpath",
<<<<<<< HEAD
"pk": "156e125d-4550-4a72-a124-3b5e7fe25e77", "pk": "156e125d-4550-4a72-a124-3b5e7fe25e77",
"fields": { "fields": {
"element": "c8e488da-28d8-467e-a651-7d6f2ad6600d", "element": "c8e488da-28d8-467e-a651-7d6f2ad6600d",
"path": "[\"2cd80ca1-7d55-4750-8c90-2b693e14a058\"]", "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 "ordering": 2
} }
}, },
{ {
"model": "documents.elementpath", "model": "documents.elementpath",
<<<<<<< HEAD
"pk": "17526830-1f55-41e1-82c5-6faf34831a0d", "pk": "17526830-1f55-41e1-82c5-6faf34831a0d",
"fields": { "fields": {
"element": "7ea6161f-62f5-4bdf-9412-bbc4d13b3e6f", "element": "7ea6161f-62f5-4bdf-9412-bbc4d13b3e6f",
"path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\", \"d9744e02-66ef-424e-a71c-88b94b209688\"]", "path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\", \"d9744e02-66ef-424e-a71c-88b94b209688\"]",
"ordering": 0 "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", "model": "documents.elementpath",
<<<<<<< HEAD
"pk": "210c3ff2-1aac-4b1d-bcff-67a76b2bc4f9", "pk": "210c3ff2-1aac-4b1d-bcff-67a76b2bc4f9",
"fields": { "fields": {
"element": "e7027313-7910-44b4-bdff-28e8d187c0b4", "element": "e7027313-7910-44b4-bdff-28e8d187c0b4",
"path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\"]", "path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\"]",
"ordering": 5 "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", "model": "documents.elementpath",
<<<<<<< HEAD
"pk": "21af7d64-10db-43f4-a0dd-386be73314cd", "pk": "21af7d64-10db-43f4-a0dd-386be73314cd",
"fields": { "fields": {
"element": "2df1881f-d666-43c9-8af7-507b277c4e23", "element": "2df1881f-d666-43c9-8af7-507b277c4e23",
"path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\", \"02a6f67e-c7d4-4dec-b3a0-9f9ab3f2ee99\"]", "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 "ordering": 1
} }
}, },
{ {
"model": "documents.elementpath", "model": "documents.elementpath",
<<<<<<< HEAD
"pk": "262709fc-3d1f-46e2-8ba5-5c63b8d2b96f", "pk": "262709fc-3d1f-46e2-8ba5-5c63b8d2b96f",
"fields": { "fields": {
"element": "d9744e02-66ef-424e-a71c-88b94b209688", "element": "d9744e02-66ef-424e-a71c-88b94b209688",
"path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\"]", "path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\"]",
"ordering": 7 "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", "model": "documents.elementpath",
<<<<<<< HEAD
"pk": "32644adb-c33b-47bd-befe-f5d2142d60ee", "pk": "32644adb-c33b-47bd-befe-f5d2142d60ee",
"fields": { "fields": {
"element": "ec742315-a1e6-4cf2-96c0-abe2b0e0e3fc", "element": "ec742315-a1e6-4cf2-96c0-abe2b0e0e3fc",
"path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\", \"9fc5e0a3-9afb-493e-bf0f-fc2998ba4ba4\"]", "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 "ordering": 2
} }
}, },
{ {
"model": "documents.elementpath", "model": "documents.elementpath",
<<<<<<< HEAD
"pk": "3a86e5d2-3c7c-474f-82b1-60dae09a82b4", "pk": "3a86e5d2-3c7c-474f-82b1-60dae09a82b4",
"fields": { "fields": {
"element": "dc66eac3-a4e9-4c55-a4a8-d239bd79f3f6", "element": "dc66eac3-a4e9-4c55-a4a8-d239bd79f3f6",
...@@ -590,29 +1177,60 @@ ...@@ -590,29 +1177,60 @@
"fields": { "fields": {
"element": "b8d9cf10-dc77-4a41-90f8-badf9718ebb9", "element": "b8d9cf10-dc77-4a41-90f8-badf9718ebb9",
"path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\", \"f530bd2f-d0ab-4f14-9d98-087486c4b1ab\"]", "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 "ordering": 0
} }
}, },
{ {
"model": "documents.elementpath", "model": "documents.elementpath",
<<<<<<< HEAD
"pk": "650ef880-9d63-4164-8d50-b7dff16ca738", "pk": "650ef880-9d63-4164-8d50-b7dff16ca738",
"fields": { "fields": {
"element": "aec1257f-bcbe-41d5-8983-966da539e912", "element": "aec1257f-bcbe-41d5-8983-966da539e912",
"path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\", \"e7027313-7910-44b4-bdff-28e8d187c0b4\"]", "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 "ordering": 0
} }
}, },
{ {
"model": "documents.elementpath", "model": "documents.elementpath",
<<<<<<< HEAD
"pk": "666416c1-5aa0-4f57-a21f-b7585b10efd2", "pk": "666416c1-5aa0-4f57-a21f-b7585b10efd2",
"fields": { "fields": {
"element": "f75ca797-0067-4711-b899-6ed39b0a6f1a", "element": "f75ca797-0067-4711-b899-6ed39b0a6f1a",
"path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\"]", "path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\"]",
"ordering": 4 "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", "model": "documents.elementpath",
<<<<<<< HEAD
"pk": "6f42e63d-d4ba-495b-8e22-e059577c669f", "pk": "6f42e63d-d4ba-495b-8e22-e059577c669f",
"fields": { "fields": {
"element": "f530bd2f-d0ab-4f14-9d98-087486c4b1ab", "element": "f530bd2f-d0ab-4f14-9d98-087486c4b1ab",
...@@ -626,19 +1244,78 @@ ...@@ -626,19 +1244,78 @@
"fields": { "fields": {
"element": "39210eb6-70a9-4660-8a45-5c6957508936", "element": "39210eb6-70a9-4660-8a45-5c6957508936",
"path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\"]", "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 "ordering": 3
} }
}, },
{ {
"model": "documents.elementpath", "model": "documents.elementpath",
<<<<<<< HEAD
"pk": "733ddae3-62e2-433a-b322-41bb6502ac93", "pk": "733ddae3-62e2-433a-b322-41bb6502ac93",
"fields": { "fields": {
"element": "34cd2540-0a05-4812-add5-f24c08d46f73", "element": "34cd2540-0a05-4812-add5-f24c08d46f73",
"path": "[\"1d4b82fe-f9c5-4012-a9ae-c2ff83c9cc02\", \"1d0f7ea6-6455-4a8d-ade2-a853f8ab7e08\"]", "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 "ordering": 0
} }
}, },
{ {
<<<<<<< HEAD
"model": "documents.elementpath", "model": "documents.elementpath",
"pk": "79ecb1ed-8036-4e88-a659-605fb3b5c8aa", "pk": "79ecb1ed-8036-4e88-a659-605fb3b5c8aa",
"fields": { "fields": {
...@@ -844,6 +1521,21 @@ ...@@ -844,6 +1521,21 @@
"worker_run": null, "worker_run": null,
"image": "f5ddf7e0-3dd3-4f4f-ada6-f42de7be869d", "image": "f5ddf7e0-3dd3-4f4f-ada6-f42de7be869d",
"polygon": "LINEARRING (700 700, 700 800, 800 800, 800 700, 700 700)", "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, "rotation_angle": 0,
"mirrored": false, "mirrored": false,
"confidence": null "confidence": null
...@@ -851,6 +1543,7 @@ ...@@ -851,6 +1543,7 @@
}, },
{ {
"model": "documents.element", "model": "documents.element",
<<<<<<< HEAD
"pk": "2cd80ca1-7d55-4750-8c90-2b693e14a058", "pk": "2cd80ca1-7d55-4750-8c90-2b693e14a058",
"fields": { "fields": {
"created": "2020-02-02T01:23:45.678Z", "created": "2020-02-02T01:23:45.678Z",
...@@ -858,6 +1551,53 @@ ...@@ -858,6 +1551,53 @@
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12", "corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12",
"type": "e28100cb-49a4-4837-a9ae-81a519ebb43f", "type": "e28100cb-49a4-4837-a9ae-81a519ebb43f",
"name": "Volume 2", "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, "creator": null,
"worker_version": null, "worker_version": null,
"worker_run": null, "worker_run": null,
...@@ -870,6 +1610,7 @@ ...@@ -870,6 +1610,7 @@
}, },
{ {
"model": "documents.element", "model": "documents.element",
<<<<<<< HEAD
"pk": "2df1881f-d666-43c9-8af7-507b277c4e23", "pk": "2df1881f-d666-43c9-8af7-507b277c4e23",
"fields": { "fields": {
"created": "2020-02-02T01:23:45.678Z", "created": "2020-02-02T01:23:45.678Z",
...@@ -882,6 +1623,20 @@ ...@@ -882,6 +1623,20 @@
"worker_run": null, "worker_run": null,
"image": "a38b69a3-a4f8-4dfc-a6b9-38ea2e52c713", "image": "a38b69a3-a4f8-4dfc-a6b9-38ea2e52c713",
"polygon": "LINEARRING (400 400, 400 500, 500 500, 500 400, 400 400)", "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, "rotation_angle": 0,
"mirrored": false, "mirrored": false,
"confidence": null "confidence": null
...@@ -889,17 +1644,30 @@ ...@@ -889,17 +1644,30 @@
}, },
{ {
"model": "documents.element", "model": "documents.element",
<<<<<<< HEAD
"pk": "2e8101c4-6fca-49b6-9b7b-41554facfa01", "pk": "2e8101c4-6fca-49b6-9b7b-41554facfa01",
"fields": { "fields": {
"created": "2020-02-02T01:23:45.678Z", "created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z",
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12", "corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12",
"type": "d15930a5-ebb8-40aa-968d-8bd2cf504230", "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", "name": "DATUM",
"creator": null, "creator": null,
"worker_version": null, "worker_version": null,
"worker_run": null, "worker_run": null,
<<<<<<< HEAD
"image": "a38b69a3-a4f8-4dfc-a6b9-38ea2e52c713", "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)", "polygon": "LINEARRING (700 700, 700 800, 800 800, 800 700, 700 700)",
"rotation_angle": 0, "rotation_angle": 0,
"mirrored": false, "mirrored": false,
...@@ -908,6 +1676,7 @@ ...@@ -908,6 +1676,7 @@
}, },
{ {
"model": "documents.element", "model": "documents.element",
<<<<<<< HEAD
"pk": "344f6b5b-b001-4084-950c-1925fdd2eef4", "pk": "344f6b5b-b001-4084-950c-1925fdd2eef4",
"fields": { "fields": {
"created": "2020-02-02T01:23:45.678Z", "created": "2020-02-02T01:23:45.678Z",
...@@ -920,6 +1689,20 @@ ...@@ -920,6 +1689,20 @@
"worker_run": null, "worker_run": null,
"image": "f250d3f3-bd56-4a2f-bffc-fc3a33cd1902", "image": "f250d3f3-bd56-4a2f-bffc-fc3a33cd1902",
"polygon": "LINEARRING (100 100, 100 200, 200 200, 200 100, 100 100)", "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, "rotation_angle": 0,
"mirrored": false, "mirrored": false,
"confidence": null "confidence": null
...@@ -927,6 +1710,7 @@ ...@@ -927,6 +1710,7 @@
}, },
{ {
"model": "documents.element", "model": "documents.element",
<<<<<<< HEAD
"pk": "34cd2540-0a05-4812-add5-f24c08d46f73", "pk": "34cd2540-0a05-4812-add5-f24c08d46f73",
"fields": { "fields": {
"created": "2020-02-02T01:23:45.678Z", "created": "2020-02-02T01:23:45.678Z",
...@@ -939,6 +1723,20 @@ ...@@ -939,6 +1723,20 @@
"worker_run": null, "worker_run": null,
"image": "a38b69a3-a4f8-4dfc-a6b9-38ea2e52c713", "image": "a38b69a3-a4f8-4dfc-a6b9-38ea2e52c713",
"polygon": "LINEARRING (300 300, 300 600, 600 600, 600 300, 300 300)", "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, "rotation_angle": 0,
"mirrored": false, "mirrored": false,
"confidence": null "confidence": null
...@@ -946,6 +1744,7 @@ ...@@ -946,6 +1744,7 @@
}, },
{ {
"model": "documents.element", "model": "documents.element",
<<<<<<< HEAD
"pk": "39210eb6-70a9-4660-8a45-5c6957508936", "pk": "39210eb6-70a9-4660-8a45-5c6957508936",
"fields": { "fields": {
"created": "2020-02-02T01:23:45.678Z", "created": "2020-02-02T01:23:45.678Z",
...@@ -953,11 +1752,19 @@ ...@@ -953,11 +1752,19 @@
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12", "corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12",
"type": "c196f23a-6843-48e1-a885-c7cda27e64ca", "type": "c196f23a-6843-48e1-a885-c7cda27e64ca",
"name": "Act 1", "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, "creator": null,
"worker_version": null, "worker_version": null,
"worker_run": null, "worker_run": null,
"image": null, "image": "bd7d9ffd-013c-4970-9df8-1d18bbe88bd5",
"polygon": null, "polygon": "LINEARRING (0 0, 0 1000, 1000 1000, 1000 0, 0 0)",
"rotation_angle": 0, "rotation_angle": 0,
"mirrored": false, "mirrored": false,
"confidence": null "confidence": null
...@@ -965,7 +1772,47 @@ ...@@ -965,7 +1772,47 @@
}, },
{ {
"model": "documents.element", "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": { "fields": {
"created": "2020-02-02T01:23:45.678Z", "created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z",
...@@ -996,6 +1843,20 @@ ...@@ -996,6 +1843,20 @@
"worker_run": null, "worker_run": null,
"image": "a38b69a3-a4f8-4dfc-a6b9-38ea2e52c713", "image": "a38b69a3-a4f8-4dfc-a6b9-38ea2e52c713",
"polygon": "LINEARRING (600 600, 600 1000, 1000 1000, 1000 600, 600 600)", "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, "rotation_angle": 0,
"mirrored": false, "mirrored": false,
"confidence": null "confidence": null
...@@ -1003,6 +1864,7 @@ ...@@ -1003,6 +1864,7 @@
}, },
{ {
"model": "documents.element", "model": "documents.element",
<<<<<<< HEAD
"pk": "86304b47-3d6a-48dd-a903-d0e09cde91ba", "pk": "86304b47-3d6a-48dd-a903-d0e09cde91ba",
"fields": { "fields": {
"created": "2020-02-02T01:23:45.678Z", "created": "2020-02-02T01:23:45.678Z",
...@@ -1200,6 +2062,15 @@ ...@@ -1200,6 +2062,15 @@
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12", "corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12",
"type": "c196f23a-6843-48e1-a885-c7cda27e64ca", "type": "c196f23a-6843-48e1-a885-c7cda27e64ca",
"name": "Act 5", "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, "creator": null,
"worker_version": null, "worker_version": null,
"worker_run": null, "worker_run": null,
...@@ -1212,6 +2083,7 @@ ...@@ -1212,6 +2083,7 @@
}, },
{ {
"model": "documents.element", "model": "documents.element",
<<<<<<< HEAD
"pk": "dc66eac3-a4e9-4c55-a4a8-d239bd79f3f6", "pk": "dc66eac3-a4e9-4c55-a4a8-d239bd79f3f6",
"fields": { "fields": {
"created": "2020-02-02T01:23:45.678Z", "created": "2020-02-02T01:23:45.678Z",
...@@ -1322,10 +2194,322 @@ ...@@ -1322,10 +2194,322 @@
"rotation_angle": 0, "rotation_angle": 0,
"mirrored": false, "mirrored": false,
"confidence": null "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", "model": "documents.entitytype",
<<<<<<< HEAD
"pk": "0199d0f3-a2e6-4422-9202-2be9fe6d9dff", "pk": "0199d0f3-a2e6-4422-9202-2be9fe6d9dff",
"fields": { "fields": {
"name": "number", "name": "number",
...@@ -1349,44 +2533,174 @@ ...@@ -1349,44 +2533,174 @@
"name": "organization", "name": "organization",
"color": "ff0000", "color": "ff0000",
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12" "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", "model": "documents.entitytype",
<<<<<<< HEAD
"pk": "7051555a-449f-4ebb-a519-f5b65517a520", "pk": "7051555a-449f-4ebb-a519-f5b65517a520",
"fields": { "fields": {
"name": "person", "name": "person",
"color": "ff0000", "color": "ff0000",
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12" "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", "model": "documents.entitytype",
<<<<<<< HEAD
"pk": "c6cb242c-688d-484f-87d1-42cabd41f67f", "pk": "c6cb242c-688d-484f-87d1-42cabd41f67f",
"fields": { "fields": {
"name": "date", "name": "date",
"color": "ff0000", "color": "ff0000",
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12" "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", "model": "documents.transcription",
"pk": "05882194-0210-441a-a167-f0b58cca0d2e", "pk": "bf9dddc1-c158-487c-99b4-37e0f7f44759",
"fields": { "fields": {
"element": "2df1881f-d666-43c9-8af7-507b277c4e23", "element": "4fed0e6a-9e3f-4e59-9c70-c5e74cc6d73c",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60", "worker_version": "f62b2301-0447-4848-9848-a731ad801d60",
"worker_run": null, "worker_run": null,
"text": "ROY", "text": "PARIS",
"orientation": "horizontal-lr", "orientation": "horizontal-lr",
"confidence": 1.0 "confidence": 1.0
} }
}, },
{ {
"model": "documents.transcription", "model": "documents.transcription",
"pk": "29dca1b6-8661-4bb5-933f-0b05ac7c30bb", "pk": "e1978d01-9182-4a42-a76f-7ae776aaaf55",
"fields": { "fields": {
"element": "86304b47-3d6a-48dd-a903-d0e09cde91ba", "element": "e9aa6eb2-eb0b-4503-9bbf-c3d27b9cce5f",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60", "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, "worker_run": null,
"text": "ROY", "text": "ROY",
"orientation": "horizontal-lr", "orientation": "horizontal-lr",
...@@ -1395,10 +2709,16 @@ ...@@ -1395,10 +2709,16 @@
}, },
{ {
"model": "documents.transcription", "model": "documents.transcription",
"pk": "413a4b08-c496-4925-a440-e9edad4a9dc1", <<<<<<< HEAD
"pk": "f5b81d19-ebb7-412d-9deb-455d72aaf829",
"fields": { "fields": {
"element": "b8d9cf10-dc77-4a41-90f8-badf9718ebb9", "element": "2e8101c4-6fca-49b6-9b7b-41554facfa01",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60", "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, "worker_run": null,
"text": "PARIS", "text": "PARIS",
"orientation": "horizontal-lr", "orientation": "horizontal-lr",
...@@ -1407,46 +2727,55 @@ ...@@ -1407,46 +2727,55 @@
}, },
{ {
"model": "documents.transcription", "model": "documents.transcription",
"pk": "5107512b-9bda-4f59-98e0-a0ff40c76d11", "pk": "6fb2d310-d2ce-4de8-89fc-2af120735fc1",
"fields": { "fields": {
"element": "ec742315-a1e6-4cf2-96c0-abe2b0e0e3fc", "element": "2ef2d52a-0316-4eb6-a3f4-a48c4e25ce7c",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60", "worker_version": "110fd472-59f4-43fa-a954-0a8dd776c86d",
"worker_run": null, "worker_run": null,
"text": "DATUM", "text": "PARIS",
"orientation": "horizontal-lr", "orientation": "horizontal-lr",
"confidence": 1.0 "confidence": 1.0
} }
}, },
{ {
"model": "documents.transcription", "model": "documents.transcription",
"pk": "5b4bd0f0-63fa-43d1-970f-a79c44784392", "pk": "9fd17563-7f50-4073-b286-42ddf7e47fcc",
"fields": { "fields": {
"element": "344f6b5b-b001-4084-950c-1925fdd2eef4", "element": "39d46933-549e-40cc-93e4-3535db7ad8a0",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60", "worker_version": "110fd472-59f4-43fa-a954-0a8dd776c86d",
>>>>>>> 7912af40 (wip API endpoints)
"worker_run": null, "worker_run": null,
"text": "PARIS", "text": "DATUM",
"orientation": "horizontal-lr", "orientation": "horizontal-lr",
"confidence": 1.0 "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", "model": "documents.transcription",
"pk": "7e865edb-f16e-4406-a497-682e5a946593", "pk": "b1260aaa-bcba-43ed-bab9-27a6effa99e0",
"fields": { "fields": {
"element": "9fc5e0a3-9afb-493e-bf0f-fc2998ba4ba4", "element": "1f8e08ad-ee8e-4924-a0b3-740722dfae47",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60", "worker_version": "110fd472-59f4-43fa-a954-0a8dd776c86d",
"worker_run": null, "worker_run": null,
"text": "Lorem ipsum dolor sit amet", "text": "PARIS",
"orientation": "horizontal-lr", "orientation": "horizontal-lr",
"confidence": 1.0 "confidence": 1.0
} }
}, },
{ {
"model": "documents.transcription", "model": "documents.transcription",
"pk": "b3ec03c1-fa36-4347-b3ad-64abf63ce10c", "pk": "b58a6fca-0ef0-4a9a-b020-cfc5d2bf0c38",
"fields": { "fields": {
"element": "2039b7b8-15cb-4b1f-a9e6-c681aa20e13a", "element": "2f7f15c7-c39b-4164-aea0-050c2a0e9d34",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60", "worker_version": "110fd472-59f4-43fa-a954-0a8dd776c86d",
"worker_run": null, "worker_run": null,
"text": "DATUM", "text": "DATUM",
"orientation": "horizontal-lr", "orientation": "horizontal-lr",
...@@ -1455,22 +2784,22 @@ ...@@ -1455,22 +2784,22 @@
}, },
{ {
"model": "documents.transcription", "model": "documents.transcription",
"pk": "bf9dddc1-c158-487c-99b4-37e0f7f44759", "pk": "bfa7949c-ad04-4c20-a92f-2e67006c4b5e",
"fields": { "fields": {
"element": "4fed0e6a-9e3f-4e59-9c70-c5e74cc6d73c", "element": "81938246-57ff-49ad-bc79-d07de4275096",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60", "worker_version": "110fd472-59f4-43fa-a954-0a8dd776c86d",
"worker_run": null, "worker_run": null,
"text": "PARIS", "text": "ROY",
"orientation": "horizontal-lr", "orientation": "horizontal-lr",
"confidence": 1.0 "confidence": 1.0
} }
}, },
{ {
"model": "documents.transcription", "model": "documents.transcription",
"pk": "e1978d01-9182-4a42-a76f-7ae776aaaf55", "pk": "e66cc126-2d3c-4419-bd18-c4f8f0cb4bbb",
"fields": { "fields": {
"element": "e9aa6eb2-eb0b-4503-9bbf-c3d27b9cce5f", "element": "fa35b384-692f-4b42-91ba-60d384ef251f",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60", "worker_version": "110fd472-59f4-43fa-a954-0a8dd776c86d",
"worker_run": null, "worker_run": null,
"text": "ROY", "text": "ROY",
"orientation": "horizontal-lr", "orientation": "horizontal-lr",
...@@ -1479,35 +2808,52 @@ ...@@ -1479,35 +2808,52 @@
}, },
{ {
"model": "documents.transcription", "model": "documents.transcription",
"pk": "f5b81d19-ebb7-412d-9deb-455d72aaf829", "pk": "ebce2b3b-c593-4a72-bf99-ffd16d552aa0",
"fields": { "fields": {
"element": "2e8101c4-6fca-49b6-9b7b-41554facfa01", "element": "6953caa3-b8bb-46a8-a222-1f386ff539f5",
"worker_version": "f62b2301-0447-4848-9848-a731ad801d60", "worker_version": "110fd472-59f4-43fa-a954-0a8dd776c86d",
"worker_run": null, "worker_run": null,
"text": "DATUM", "text": "DATUM",
"orientation": "horizontal-lr", "orientation": "horizontal-lr",
"confidence": 1.0 "confidence": 1.0
>>>>>>> 7912af40 (wip API endpoints)
} }
}, },
{ {
"model": "documents.allowedmetadata", "model": "documents.allowedmetadata",
"pk": "6437fdd1-97c0-4fff-a325-039d0379bdbe", <<<<<<< HEAD
"pk": "89efa0fd-a187-4177-8de5-f3477dde921f",
"fields": { "fields": {
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12", "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", "type": "text",
"name": "folio" "name": "folio"
} }
}, },
{ {
"model": "documents.allowedmetadata", "model": "documents.allowedmetadata",
"pk": "89efa0fd-a187-4177-8de5-f3477dde921f", "pk": "e44b9326-0e8c-4e0f-a735-3d701bda3852",
"fields": { "fields": {
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12", "corpus": "3a30b730-9c9e-4b5a-828e-abc4365ea1b9",
>>>>>>> 7912af40 (wip API endpoints)
"type": "location", "type": "location",
"name": "location" "name": "location"
} }
}, },
{ {
<<<<<<< HEAD
"model": "documents.allowedmetadata", "model": "documents.allowedmetadata",
"pk": "ab34cc71-a15a-40d9-8cc5-f680adca898b", "pk": "ab34cc71-a15a-40d9-8cc5-f680adca898b",
"fields": { "fields": {
...@@ -1547,6 +2893,12 @@ ...@@ -1547,6 +2893,12 @@
"pk": "52139b43-747a-4ffe-9f5c-cd43e0ad2b39", "pk": "52139b43-747a-4ffe-9f5c-cd43e0ad2b39",
"fields": { "fields": {
"element": "e7027313-7910-44b4-bdff-28e8d187c0b4", "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", "name": "number",
"type": "text", "type": "text",
"value": "3", "value": "3",
...@@ -1557,9 +2909,54 @@ ...@@ -1557,9 +2909,54 @@
}, },
{ {
"model": "documents.metadata", "model": "documents.metadata",
<<<<<<< HEAD
"pk": "62347283-e04f-4401-a8a9-ff402766ac2d", "pk": "62347283-e04f-4401-a8a9-ff402766ac2d",
"fields": { "fields": {
"element": "c8e488da-28d8-467e-a651-7d6f2ad6600d", "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", "name": "folio",
"type": "text", "type": "text",
"value": "2r", "value": "2r",
...@@ -1570,9 +2967,15 @@ ...@@ -1570,9 +2967,15 @@
}, },
{ {
"model": "documents.metadata", "model": "documents.metadata",
<<<<<<< HEAD
"pk": "660e0182-f139-4a4b-b65e-b60b3051ef4c", "pk": "660e0182-f139-4a4b-b65e-b60b3051ef4c",
"fields": { "fields": {
"element": "9c42123c-b940-4695-b083-5b19392f68a6", "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", "name": "folio",
"type": "text", "type": "text",
"value": "1r", "value": "1r",
...@@ -1583,6 +2986,7 @@ ...@@ -1583,6 +2986,7 @@
}, },
{ {
"model": "documents.metadata", "model": "documents.metadata",
<<<<<<< HEAD
"pk": "af1f94f7-b9a8-4963-9e21-d4a8c34b2627", "pk": "af1f94f7-b9a8-4963-9e21-d4a8c34b2627",
"fields": { "fields": {
"element": "39210eb6-70a9-4660-8a45-5c6957508936", "element": "39210eb6-70a9-4660-8a45-5c6957508936",
...@@ -1612,6 +3016,11 @@ ...@@ -1612,6 +3016,11 @@
"pk": "da44df4c-a8ac-4bdc-a10b-ab6939ac76cd", "pk": "da44df4c-a8ac-4bdc-a10b-ab6939ac76cd",
"fields": { "fields": {
"element": "dc66eac3-a4e9-4c55-a4a8-d239bd79f3f6", "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", "name": "folio",
"type": "text", "type": "text",
"value": "1v", "value": "1v",
...@@ -1622,12 +3031,21 @@ ...@@ -1622,12 +3031,21 @@
}, },
{ {
"model": "documents.metadata", "model": "documents.metadata",
<<<<<<< HEAD
"pk": "f55c81b9-bc87-4086-8cb1-b3a0eea6d491", "pk": "f55c81b9-bc87-4086-8cb1-b3a0eea6d491",
"fields": { "fields": {
"element": "f530bd2f-d0ab-4f14-9d98-087486c4b1ab", "element": "f530bd2f-d0ab-4f14-9d98-087486c4b1ab",
"name": "folio", "name": "folio",
"type": "text", "type": "text",
"value": "1v", "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, "entity": null,
"worker_version": null, "worker_version": null,
"worker_run": null "worker_run": null
...@@ -1635,9 +3053,28 @@ ...@@ -1635,9 +3053,28 @@
}, },
{ {
"model": "documents.metadata", "model": "documents.metadata",
<<<<<<< HEAD
"pk": "fb0bedec-cc2d-424e-86bf-05239865e3fd", "pk": "fb0bedec-cc2d-424e-86bf-05239865e3fd",
"fields": { "fields": {
"element": "02a6f67e-c7d4-4dec-b3a0-9f9ab3f2ee99", "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", "name": "folio",
"type": "text", "type": "text",
"value": "2r", "value": "2r",
...@@ -1648,9 +3085,15 @@ ...@@ -1648,9 +3085,15 @@
}, },
{ {
"model": "documents.metadata", "model": "documents.metadata",
<<<<<<< HEAD
"pk": "fe60529e-30d4-4824-bb87-3534a652da81", "pk": "fe60529e-30d4-4824-bb87-3534a652da81",
"fields": { "fields": {
"element": "9fc5e0a3-9afb-493e-bf0f-fc2998ba4ba4", "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", "name": "folio",
"type": "text", "type": "text",
"value": "1r", "value": "1r",
...@@ -1676,6 +3119,7 @@ ...@@ -1676,6 +3119,7 @@
}, },
{ {
"model": "images.image", "model": "images.image",
<<<<<<< HEAD
"pk": "27c0757d-4d15-4f0e-bfc1-ec63bfada9e7", "pk": "27c0757d-4d15-4f0e-bfc1-ec63bfada9e7",
"fields": { "fields": {
"created": "2020-02-02T01:23:45.678Z", "created": "2020-02-02T01:23:45.678Z",
...@@ -1691,6 +3135,9 @@ ...@@ -1691,6 +3135,9 @@
{ {
"model": "images.image", "model": "images.image",
"pk": "468df2f7-e22a-4dba-96d2-9c464ba6c2b0", "pk": "468df2f7-e22a-4dba-96d2-9c464ba6c2b0",
=======
"pk": "0e219e81-b8ab-484b-a8f2-cb848a9c8b45",
>>>>>>> 7912af40 (wip API endpoints)
"fields": { "fields": {
"created": "2020-02-02T01:23:45.678Z", "created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z",
...@@ -1704,7 +3151,39 @@ ...@@ -1704,7 +3151,39 @@
}, },
{ {
"model": "images.image", "model": "images.image",
<<<<<<< HEAD
"pk": "53421855-db25-4abd-aba4-d86710a76d5d", "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": { "fields": {
"created": "2020-02-02T01:23:45.678Z", "created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z",
...@@ -1718,6 +3197,7 @@ ...@@ -1718,6 +3197,7 @@
}, },
{ {
"model": "images.image", "model": "images.image",
<<<<<<< HEAD
"pk": "a38b69a3-a4f8-4dfc-a6b9-38ea2e52c713", "pk": "a38b69a3-a4f8-4dfc-a6b9-38ea2e52c713",
"fields": { "fields": {
"created": "2020-02-02T01:23:45.678Z", "created": "2020-02-02T01:23:45.678Z",
...@@ -1767,10 +3247,37 @@ ...@@ -1767,10 +3247,37 @@
"content_type": 19, "content_type": 19,
"content_id": "f34313ec-45ec-4ac4-92e5-43d7eb045c12", "content_id": "f34313ec-45ec-4ac4-92e5-43d7eb045c12",
"level": 100 "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", "model": "users.right",
<<<<<<< HEAD
"pk": "2a7d975d-4f18-41f4-964f-817aeae09582", "pk": "2a7d975d-4f18-41f4-964f-817aeae09582",
"fields": { "fields": {
"user": 2, "user": 2,
...@@ -1783,22 +3290,71 @@ ...@@ -1783,22 +3290,71 @@
{ {
"model": "users.right", "model": "users.right",
"pk": "7e2ea5d2-2408-49b4-b1b4-2ea0e12da7e4", "pk": "7e2ea5d2-2408-49b4-b1b4-2ea0e12da7e4",
=======
"pk": "053ed1e1-850b-4554-b0d0-d05576b71696",
>>>>>>> 7912af40 (wip API endpoints)
"fields": { "fields": {
"user": 2, "user": 2,
"group": null, "group": null,
"content_type": 34, "content_type": 34,
<<<<<<< HEAD
"content_id": "8f459bd8-0440-444e-940b-3c14b10bdb0d", "content_id": "8f459bd8-0440-444e-940b-3c14b10bdb0d",
"level": 100 "level": 100
=======
"content_id": "18eabf1f-18b6-43d9-b104-7abfcb5b9baa",
"level": 50
>>>>>>> 7912af40 (wip API endpoints)
} }
}, },
{ {
"model": "users.right", "model": "users.right",
<<<<<<< HEAD
"pk": "db08fb62-277f-475c-ae92-cfb4a515b146", "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": { "fields": {
"user": 4, "user": 4,
"group": null, "group": null,
"content_type": 34, "content_type": 34,
<<<<<<< HEAD
"content_id": "8f459bd8-0440-444e-940b-3c14b10bdb0d", "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 "level": 10
} }
}, },
...@@ -1817,7 +3373,11 @@ ...@@ -1817,7 +3373,11 @@
"model": "users.user", "model": "users.user",
"pk": 1, "pk": 1,
"fields": { "fields": {
<<<<<<< HEAD
"password": "pbkdf2_sha256$390000$n41pgYuMjEMc9yABOJDuv7$szqrPzEEMyrNyvxRF5ekrtgzLra4rnw09jkS/Rlb65M=", "password": "pbkdf2_sha256$390000$n41pgYuMjEMc9yABOJDuv7$szqrPzEEMyrNyvxRF5ekrtgzLra4rnw09jkS/Rlb65M=",
=======
"password": "pbkdf2_sha256$390000$K7ghXs3mkOALU9T2ri8k6D$Hw9rIqH0Mdlvd2vaMSsj7lH3TLerOKfpkHUVk4ZfZPM=",
>>>>>>> 7912af40 (wip API endpoints)
"last_login": null, "last_login": null,
"email": "root@root.fr", "email": "root@root.fr",
"display_name": "Admin", "display_name": "Admin",
...@@ -1832,7 +3392,11 @@ ...@@ -1832,7 +3392,11 @@
"model": "users.user", "model": "users.user",
"pk": 2, "pk": 2,
"fields": { "fields": {
<<<<<<< HEAD
"password": "pbkdf2_sha256$390000$82MV7wfiM1CYxnR3JI9dRw$vavB8EAQRE2Z0REJhhWU7bRyrQqZF5wazXjl1rOrvTY=", "password": "pbkdf2_sha256$390000$82MV7wfiM1CYxnR3JI9dRw$vavB8EAQRE2Z0REJhhWU7bRyrQqZF5wazXjl1rOrvTY=",
=======
"password": "pbkdf2_sha256$390000$4SWGc0rfBPkIHNBjmvIVhM$F81VX9tQd5l9iKOdb970liPhie/hbyyHNsYO7O7fOKE=",
>>>>>>> 7912af40 (wip API endpoints)
"last_login": null, "last_login": null,
"email": "user@user.fr", "email": "user@user.fr",
"display_name": "Test user", "display_name": "Test user",
...@@ -1875,7 +3439,11 @@ ...@@ -1875,7 +3439,11 @@
}, },
{ {
"model": "users.group", "model": "users.group",
<<<<<<< HEAD
"pk": "8f459bd8-0440-444e-940b-3c14b10bdb0d", "pk": "8f459bd8-0440-444e-940b-3c14b10bdb0d",
=======
"pk": "18eabf1f-18b6-43d9-b104-7abfcb5b9baa",
>>>>>>> 7912af40 (wip API endpoints)
"fields": { "fields": {
"name": "User group", "name": "User group",
"public": false, "public": false,
...@@ -3871,42 +5439,188 @@ ...@@ -3871,42 +5439,188 @@
"codename": "view_datasetelement" "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", "model": "ponos.farm",
<<<<<<< HEAD
"pk": "395522d1-94a0-407a-b5cb-347fa68ec2c4", "pk": "395522d1-94a0-407a-b5cb-347fa68ec2c4",
"fields": { "fields": {
"name": "Wheat farm", "name": "Wheat farm",
"seed": "444809637bf8b3088a181de520a02151a99477edd051710e90a2d1fcdf860dbb" "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", "model": "training.dataset",
<<<<<<< HEAD
"pk": "4a844b36-08bd-4284-918e-5e03d543df13", "pk": "4a844b36-08bd-4284-918e-5e03d543df13",
"fields": { "fields": {
"created": "2020-02-02T01:23:45.678Z", "created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z",
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12", "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, "creator": 2,
"task": null, "task": null,
"name": "Second Dataset", "name": "Second Dataset",
"description": "dataset number two", "description": "dataset number two",
"state": "open", "state": "open"
"sets": "[\"training\", \"test\", \"validation\"]"
} }
}, },
{ {
"model": "training.dataset", "model": "training.dataset",
<<<<<<< HEAD
"pk": "630d1cf5-3ba8-4335-b0be-d1be4cb18782", "pk": "630d1cf5-3ba8-4335-b0be-d1be4cb18782",
"fields": { "fields": {
"created": "2020-02-02T01:23:45.678Z", "created": "2020-02-02T01:23:45.678Z",
"updated": "2020-02-02T01:23:45.678Z", "updated": "2020-02-02T01:23:45.678Z",
"corpus": "f34313ec-45ec-4ac4-92e5-43d7eb045c12", "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, "creator": 2,
"task": null, "task": null,
"name": "First Dataset", "name": "First Dataset",
"description": "dataset number one", "description": "dataset number one",
"state": "open", "state": "open"
"sets": "[\"training\", \"test\", \"validation\"]" }
},
{
"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 ( ...@@ -20,6 +20,7 @@ from arkindex.process.models import (
WorkerVersionState, WorkerVersionState,
) )
from arkindex.project.tools import fake_now from arkindex.project.tools import fake_now
from arkindex.training.models import DatasetSet
from arkindex.users.models import Group, Right, Role, User from arkindex.users.models import Group, Right, Role, User
...@@ -271,8 +272,15 @@ class Command(BaseCommand): ...@@ -271,8 +272,15 @@ class Command(BaseCommand):
) )
# Create 2 datasets # Create 2 datasets
corpus.datasets.create(name="First Dataset", description="dataset number one", creator=user) dataset_1 = 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_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 # Create 2 volumes
vol1 = Element.objects.create( vol1 = Element.objects.create(
......
import django.core.validators import django.core.validators
from django.db import migrations, models from django.db import migrations, models
import arkindex.process.models
import arkindex.project.fields import arkindex.project.fields
import arkindex.training.models
class Migration(migrations.Migration): class Migration(migrations.Migration):
...@@ -37,7 +37,7 @@ class Migration(migrations.Migration): ...@@ -37,7 +37,7 @@ class Migration(migrations.Migration):
validators=[django.core.validators.MinLengthValidator(1)] validators=[django.core.validators.MinLengthValidator(1)]
), ),
size=None, 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 ...@@ -5,6 +5,7 @@ from typing import Optional
from django.conf import settings from django.conf import settings
from django.contrib.contenttypes.fields import GenericRelation from django.contrib.contenttypes.fields import GenericRelation
from django.core.exceptions import ValidationError
from django.core.validators import MinLengthValidator, MinValueValidator from django.core.validators import MinLengthValidator, MinValueValidator
from django.db import models, transaction from django.db import models, transaction
from django.db.models import F, Q from django.db.models import F, Q
...@@ -28,7 +29,7 @@ from arkindex.project.aws import S3FileMixin, S3FileStatus ...@@ -28,7 +29,7 @@ from arkindex.project.aws import S3FileMixin, S3FileStatus
from arkindex.project.fields import ArrayField, MD5HashField from arkindex.project.fields import ArrayField, MD5HashField
from arkindex.project.models import IndexableModel from arkindex.project.models import IndexableModel
from arkindex.project.validators import MaxValueValidator 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 from arkindex.users.models import Role
...@@ -40,6 +41,11 @@ def process_max_chunks(): ...@@ -40,6 +41,11 @@ def process_max_chunks():
return settings.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): class ActivityState(Enum):
""" """
Store the state of the workers activity tracking for a process. Store the state of the workers activity tracking for a process.
......
...@@ -109,7 +109,7 @@ from arkindex.training.api import ( ...@@ -109,7 +109,7 @@ from arkindex.training.api import (
DatasetElementDestroy, DatasetElementDestroy,
DatasetElements, DatasetElements,
DatasetUpdate, DatasetUpdate,
ElementDatasets, ElementDatasetSets,
MetricValueBulkCreate, MetricValueBulkCreate,
MetricValueCreate, MetricValueCreate,
ModelCompatibleWorkerManage, ModelCompatibleWorkerManage,
...@@ -184,7 +184,7 @@ api = [ ...@@ -184,7 +184,7 @@ api = [
# Datasets # Datasets
path("corpus/<uuid:pk>/datasets/", CorpusDataset.as_view(), name="corpus-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("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>/", DatasetUpdate.as_view(), name="dataset-update"),
path("datasets/<uuid:pk>/clone/", DatasetClone.as_view(), name="dataset-clone"), path("datasets/<uuid:pk>/clone/", DatasetClone.as_view(), name="dataset-clone"),
path("datasets/<uuid:pk>/elements/", DatasetElements.as_view(), name="dataset-elements"), path("datasets/<uuid:pk>/elements/", DatasetElements.as_view(), name="dataset-elements"),
......
...@@ -12,6 +12,7 @@ from arkindex.documents.models import MetaType ...@@ -12,6 +12,7 @@ from arkindex.documents.models import MetaType
from arkindex.ponos.utils import get_process_from_task_auth from arkindex.ponos.utils import get_process_from_task_auth
from arkindex.process.models import ProcessMode, WorkerRun from arkindex.process.models import ProcessMode, WorkerRun
from arkindex.project.gis import ensure_linear_ring from arkindex.project.gis import ensure_linear_ring
from arkindex.training.models import DatasetElement
class EnumField(serializers.ChoiceField): class EnumField(serializers.ChoiceField):
...@@ -283,12 +284,12 @@ class DatasetSetsCountField(serializers.DictField): ...@@ -283,12 +284,12 @@ class DatasetSetsCountField(serializers.DictField):
def get_attribute(self, instance): def get_attribute(self, instance):
if not self.context.get("sets_count", True): if not self.context.get("sets_count", True):
return None 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( elts_count.update(
instance.dataset_elements DatasetElement.objects.filter(set_id__in=instance.sets.values_list("id"))
.values("set") .values("set__name")
.annotate(count=Count("id")) .annotate(count=Count("id"))
.values_list("set", "count") .values_list("set__name", "count")
) )
return elts_count return elts_count
......
...@@ -2,7 +2,7 @@ from django.contrib import admin ...@@ -2,7 +2,7 @@ from django.contrib import admin
from enumfields.admin import EnumFieldListFilter from enumfields.admin import EnumFieldListFilter
from arkindex.project.admin import ArchivedListFilter 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): class ModelAdmin(admin.ModelAdmin):
...@@ -31,21 +31,17 @@ class MetricKeyAdmin(admin.ModelAdmin): ...@@ -31,21 +31,17 @@ class MetricKeyAdmin(admin.ModelAdmin):
inlines = [MetricValueInline, ] inlines = [MetricValueInline, ]
class DatasetSetInLine(admin.StackedInline):
model = DatasetSet
class DatasetAdmin(admin.ModelAdmin): class DatasetAdmin(admin.ModelAdmin):
list_display = ("name", "corpus", "state") list_display = ("name", "corpus", "state")
list_filter = (("state", EnumFieldListFilter), "corpus") list_filter = (("state", EnumFieldListFilter), "corpus")
search_fields = ("name", "description") 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") readonly_fields = ("id", "created", "updated", "task")
inlines = [DatasetSetInLine, ]
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
admin.site.register(Model, ModelAdmin) admin.site.register(Model, ModelAdmin)
......
...@@ -29,6 +29,7 @@ from arkindex.project.tools import BulkMap ...@@ -29,6 +29,7 @@ from arkindex.project.tools import BulkMap
from arkindex.training.models import ( from arkindex.training.models import (
Dataset, Dataset,
DatasetElement, DatasetElement,
DatasetSet,
DatasetState, DatasetState,
MetricValue, MetricValue,
Model, Model,
...@@ -40,7 +41,7 @@ from arkindex.training.serializers import ( ...@@ -40,7 +41,7 @@ from arkindex.training.serializers import (
DatasetElementInfoSerializer, DatasetElementInfoSerializer,
DatasetElementSerializer, DatasetElementSerializer,
DatasetSerializer, DatasetSerializer,
ElementDatasetSerializer, ElementDatasetSetSerializer,
MetricValueBulkSerializer, MetricValueBulkSerializer,
MetricValueCreateSerializer, MetricValueCreateSerializer,
ModelCompatibleWorkerSerializer, ModelCompatibleWorkerSerializer,
...@@ -58,7 +59,7 @@ def _fetch_datasetelement_neighbors(datasetelements): ...@@ -58,7 +59,7 @@ def _fetch_datasetelement_neighbors(datasetelements):
""" """
Retrieve the neighbors for a list of DatasetElements, and annotate these DatasetElements Retrieve the neighbors for a list of DatasetElements, and annotate these DatasetElements
with next and previous attributes. 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 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. post-processing after pagination in Django without having to use Django private methods.
""" """
...@@ -71,18 +72,18 @@ def _fetch_datasetelement_neighbors(datasetelements): ...@@ -71,18 +72,18 @@ def _fetch_datasetelement_neighbors(datasetelements):
SELECT SELECT
n.id, n.id,
lag(element_id) OVER ( lag(element_id) OVER (
partition BY (n.dataset_id, n.set) partition BY (n.set_id)
order by order by
n.element_id n.element_id
) as previous, ) as previous,
lead(element_id) OVER ( lead(element_id) OVER (
partition BY (n.dataset_id, n.set) partition BY (n.set_id)
order by order by
n.element_id n.element_id
) as next ) as next
FROM training_datasetelement as n FROM training_datasetelement as n
WHERE (dataset_id, set) IN ( WHERE set_id IN (
SELECT dataset_id, set SELECT set_id
FROM training_datasetelement FROM training_datasetelement
WHERE id IN %(ids)s WHERE id IN %(ids)s
) )
...@@ -609,6 +610,7 @@ class CorpusDataset(CorpusACLMixin, ListCreateAPIView): ...@@ -609,6 +610,7 @@ class CorpusDataset(CorpusACLMixin, ListCreateAPIView):
def get_queryset(self): def get_queryset(self):
return Dataset.objects \ return Dataset.objects \
.select_related("creator") \ .select_related("creator") \
.prefetch_related("sets") \
.filter(corpus=self.corpus) \ .filter(corpus=self.corpus) \
.order_by("name") .order_by("name")
...@@ -707,7 +709,8 @@ class DatasetUpdate(ACLMixin, RetrieveUpdateDestroyAPIView): ...@@ -707,7 +709,8 @@ class DatasetUpdate(ACLMixin, RetrieveUpdateDestroyAPIView):
raise ValidationError(detail="This dataset is in complete state and cannot be modified anymore.") raise ValidationError(detail="This dataset is in complete state and cannot be modified anymore.")
def perform_destroy(self, dataset): 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) super().perform_destroy(dataset)
...@@ -768,13 +771,13 @@ class DatasetElements(CorpusACLMixin, ListCreateAPIView): ...@@ -768,13 +771,13 @@ class DatasetElements(CorpusACLMixin, ListCreateAPIView):
def get_queryset(self): def get_queryset(self):
qs = ( qs = (
self.dataset.dataset_elements DatasetElement.objects.filter(set__dataset_id=self.dataset.id)
.prefetch_related("element") .prefetch_related("element", "set")
.select_related("element__type", "element__corpus", "element__image__server") .select_related("element__type", "element__corpus", "element__image__server")
.order_by("element_id", "id") .order_by("element_id", "id")
) )
if "set" in self.request.query_params: 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 return qs
def get_serializer_context(self): def get_serializer_context(self):
...@@ -787,20 +790,12 @@ class DatasetElements(CorpusACLMixin, ListCreateAPIView): ...@@ -787,20 +790,12 @@ class DatasetElements(CorpusACLMixin, ListCreateAPIView):
@extend_schema_view( @extend_schema_view(
delete=extend_schema( delete=extend_schema(
operation_id="DestroyDatasetElement", operation_id="DestroyDatasetElement",
parameters=[
OpenApiParameter(
"set",
type=str,
description="Name of the set from which to remove the element.",
required=True,
)
],
tags=["datasets"] tags=["datasets"]
) )
) )
class DatasetElementDestroy(CorpusACLMixin, DestroyAPIView): 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. Elements can only be removed from **open** datasets.
...@@ -811,17 +806,15 @@ class DatasetElementDestroy(CorpusACLMixin, DestroyAPIView): ...@@ -811,17 +806,15 @@ class DatasetElementDestroy(CorpusACLMixin, DestroyAPIView):
lookup_url_kwarg = "element" lookup_url_kwarg = "element"
def destroy(self, request, *args, **kwargs): 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."]}) raise ValidationError({"set": ["This field is required."]})
dataset_element = get_object_or_404( dataset_element = get_object_or_404(
DatasetElement.objects.select_related("dataset__corpus"), DatasetElement.objects.select_related("set__dataset__corpus").filter(set__dataset_id=self.kwargs["dataset"], set__name=set_name),
dataset_id=self.kwargs["dataset"], element_id=self.kwargs["element"]
element_id=self.kwargs["element"],
set=self.request.query_params.get("set")
) )
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."]}) 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.") raise PermissionDenied(detail="You need a Contributor access to the dataset to perform this action.")
dataset_element.delete() dataset_element.delete()
return Response(status=status.HTTP_204_NO_CONTENT) return Response(status=status.HTTP_204_NO_CONTENT)
...@@ -896,14 +889,14 @@ class CreateDatasetElementsSelection(CorpusACLMixin, CreateAPIView): ...@@ -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. Requires a **guest** access to the element's corpus.
""" """
permission_classes = (IsVerifiedOrReadOnly, ) permission_classes = (IsVerifiedOrReadOnly, )
serializer_class = ElementDatasetSerializer serializer_class = ElementDatasetSetSerializer
@cached_property @cached_property
def element(self): def element(self):
...@@ -915,9 +908,10 @@ class ElementDatasets(CorpusACLMixin, ListAPIView): ...@@ -915,9 +908,10 @@ class ElementDatasets(CorpusACLMixin, ListAPIView):
def get_queryset(self): def get_queryset(self):
qs = ( qs = (
self.element.dataset_elements.all() self.element.dataset_elements
.select_related("dataset__creator") .select_related("set__dataset__creator")
.order_by("dataset__name", "set", "dataset_id") .prefetch_related("set__dataset__sets")
.order_by("set__dataset__name", "set__name")
) )
with_neighbors = self.request.query_params.get("with_neighbors", "false") with_neighbors = self.request.query_params.get("with_neighbors", "false")
...@@ -960,7 +954,9 @@ class DatasetClone(CorpusACLMixin, CreateAPIView): ...@@ -960,7 +954,9 @@ class DatasetClone(CorpusACLMixin, CreateAPIView):
serializer_class = DatasetSerializer serializer_class = DatasetSerializer
def get_queryset(self): 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): def check_object_permissions(self, request, dataset):
if not self.has_write_access(dataset.corpus): if not self.has_write_access(dataset.corpus):
...@@ -995,11 +991,18 @@ class DatasetClone(CorpusACLMixin, CreateAPIView): ...@@ -995,11 +991,18 @@ class DatasetClone(CorpusACLMixin, CreateAPIView):
clone.creator = request.user clone.creator = request.user
clone.save() 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 # Associate all elements to the clone
DatasetElement.objects.bulk_create([ DatasetElement.objects.bulk_create([
DatasetElement(element_id=elt_id, dataset_id=clone.id, set=set_name) 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 dataset.dataset_elements.values_list("element_id", "set") for elt_id, set_name in DatasetElement.objects.filter(set__dataset_id=dataset.id)
.values_list("element_id", "set__name")
]) ])
return Response( return Response(
DatasetSerializer(clone).data, DatasetSerializer(clone).data,
status=status.HTTP_201_CREATED, status=status.HTTP_201_CREATED,
......
...@@ -8,9 +8,13 @@ import django.db.models.deletion ...@@ -8,9 +8,13 @@ import django.db.models.deletion
import enumfields.fields import enumfields.fields
from django.db import migrations, models from django.db import migrations, models
import arkindex.process.models
import arkindex.project.aws import arkindex.project.aws
import arkindex.project.fields import arkindex.project.fields
import arkindex.training.models
def default_sets():
return ["training", "test", "validation"]
class Migration(migrations.Migration): class Migration(migrations.Migration):
...@@ -32,7 +36,7 @@ class Migration(migrations.Migration): ...@@ -32,7 +36,7 @@ class Migration(migrations.Migration):
("name", models.CharField(max_length=100, validators=[django.core.validators.MinLengthValidator(1)])), ("name", models.CharField(max_length=100, validators=[django.core.validators.MinLengthValidator(1)])),
("description", models.TextField(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)), ("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")), ("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 ...@@ -4,8 +4,6 @@ from hashlib import sha256
from django.conf import settings from django.conf import settings
from django.contrib.contenttypes.fields import GenericRelation 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.core.validators import MinLengthValidator
from django.db import models from django.db import models
from django.db.models import Q from django.db.models import Q
...@@ -242,15 +240,6 @@ class DatasetState(Enum): ...@@ -242,15 +240,6 @@ class DatasetState(Enum):
Error = "error" 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): class Dataset(models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True, editable=False) id = models.UUIDField(default=uuid.uuid4, primary_key=True, editable=False)
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
...@@ -278,21 +267,6 @@ class Dataset(models.Model): ...@@ -278,21 +267,6 @@ class Dataset(models.Model):
description = models.TextField(validators=[MinLengthValidator(1)]) description = models.TextField(validators=[MinLengthValidator(1)])
state = EnumField(DatasetState, default=DatasetState.Open, max_length=50) 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: class Meta:
constraints = [ constraints = [
models.UniqueConstraint( models.UniqueConstraint(
...@@ -305,24 +279,41 @@ class Dataset(models.Model): ...@@ -305,24 +279,41 @@ class Dataset(models.Model):
return self.name return self.name
class DatasetElement(models.Model): class DatasetSet(models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True, editable=False) id = models.UUIDField(default=uuid.uuid4, primary_key=True, editable=False)
name = models.CharField(max_length=50, validators=[MinLengthValidator(1)])
dataset = models.ForeignKey( dataset = models.ForeignKey(
Dataset, Dataset,
related_name="dataset_elements", related_name="sets",
on_delete=models.DO_NOTHING, 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( element = models.ForeignKey(
"documents.Element", "documents.Element",
related_name="dataset_elements", related_name="dataset_elements",
on_delete=models.DO_NOTHING, 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: class Meta:
constraints = [ constraints = [
models.UniqueConstraint( models.UniqueConstraint(
fields=["dataset", "element", "set"], fields=["element_id", "set_id"],
name="unique_dataset_elements", name="unique_set_element",
), ),
] ]
...@@ -6,18 +6,19 @@ from textwrap import dedent ...@@ -6,18 +6,19 @@ from textwrap import dedent
from django.db import transaction from django.db import transaction
from django.db.models import Count, Q from django.db.models import Count, Q
from drf_spectacular.utils import extend_schema_field 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.exceptions import PermissionDenied, ValidationError
from rest_framework.validators import UniqueTogetherValidator 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.documents.serializers.elements import ElementListSerializer
from arkindex.ponos.models import Task 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.project.serializer_fields import ArchivedField, DatasetSetsCountField, EnumField
from arkindex.training.models import ( from arkindex.training.models import (
Dataset, Dataset,
DatasetElement, DatasetElement,
DatasetSet,
DatasetState, DatasetState,
MetricKey, MetricKey,
MetricMode, MetricMode,
...@@ -479,6 +480,12 @@ class MetricValueBulkSerializer(serializers.Serializer): ...@@ -479,6 +480,12 @@ class MetricValueBulkSerializer(serializers.Serializer):
return validated_data return validated_data
class DatasetSetSerializer(serializers.ModelSerializer):
class Meta:
model = DatasetSet
fields = ("id", "name",)
class DatasetSerializer(serializers.ModelSerializer): class DatasetSerializer(serializers.ModelSerializer):
state = EnumField( state = EnumField(
DatasetState, DatasetState,
...@@ -505,6 +512,13 @@ class DatasetSerializer(serializers.ModelSerializer): ...@@ -505,6 +512,13 @@ class DatasetSerializer(serializers.ModelSerializer):
help_text="Display name of the user who created the dataset.", 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 # 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) corpus = serializers.HiddenField(default=_corpus_from_context)
...@@ -517,16 +531,6 @@ class DatasetSerializer(serializers.ModelSerializer): ...@@ -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.", 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): def validate_state(self, state):
""" """
Dataset's state update is limited to these transitions: Dataset's state update is limited to these transitions:
...@@ -550,27 +554,14 @@ class DatasetSerializer(serializers.ModelSerializer): ...@@ -550,27 +554,14 @@ class DatasetSerializer(serializers.ModelSerializer):
raise ValidationError(f"Transition from {self.instance.state} to {state} is not allowed.") raise ValidationError(f"Transition from {self.instance.state} to {state} is not allowed.")
return state return state
def validate_sets(self, sets): def validate_set_names(self, set_names):
""" if self.context["request"].method not in permissions.SAFE_METHODS and self.context["request"].method != "POST":
Ensure sets are updated in a comprehensible way. raise ValidationError("This API endpoint does not allow updating a dataset's sets.")
It is either possible to add multiple sets, if set_names is not None and len(set(set_names)) != len(set_names):
remove multiple sets or update a single set.
"""
if sets is not None and len(set(sets)) != len(sets):
raise ValidationError("Set names must be unique.") raise ValidationError("Set names must be unique.")
if set_names is not None and len(set_names) == 0:
removed, added = self.sets_diff(sets) raise ValidationError("Either do not specify set names to use the default values, or specify a non-empty list of names.")
if removed and ProcessDataset.objects.filter(sets__overlap=removed, dataset_id=self.instance.id).exists(): return set_names
# 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.")
def validate(self, data): def validate(self, data):
data = super().validate(data) data = super().validate(data)
...@@ -598,13 +589,17 @@ class DatasetSerializer(serializers.ModelSerializer): ...@@ -598,13 +589,17 @@ class DatasetSerializer(serializers.ModelSerializer):
return data return data
@transaction.atomic() @transaction.atomic
def update(self, instance, validated_data): def create(self, validated_data):
removed, added = self.sets_diff(validated_data.get("sets", self.instance.sets)) sets = validated_data.pop("set_names")
if len(removed) == 1 and len(added) == 1: dataset = Dataset.objects.create(**validated_data)
set_from, set_to = *removed, *added DatasetSet.objects.bulk_create(
instance.dataset_elements.filter(set=set_from).update(set=set_to) DatasetSet(
return super().update(instance, validated_data) name=set_name,
dataset_id=dataset.id
) for set_name in sets
)
return dataset
class Meta: class Meta:
model = Dataset model = Dataset
...@@ -613,6 +608,7 @@ class DatasetSerializer(serializers.ModelSerializer): ...@@ -613,6 +608,7 @@ class DatasetSerializer(serializers.ModelSerializer):
"name", "name",
"description", "description",
"sets", "sets",
"set_names",
"set_elements", "set_elements",
"state", "state",
# Only the corpus ID is actually serialized # Only the corpus ID is actually serialized
...@@ -647,13 +643,7 @@ class DatasetSerializer(serializers.ModelSerializer): ...@@ -647,13 +643,7 @@ class DatasetSerializer(serializers.ModelSerializer):
"sets": { "sets": {
"error_messages": { "error_messages": {
"empty": "Either do not specify set names to use the default values, or specify a non-empty list of names." "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): ...@@ -673,6 +663,7 @@ class DatasetElementSerializer(serializers.ModelSerializer):
default=_dataset_from_context, default=_dataset_from_context,
write_only=True, write_only=True,
) )
set = serializers.SlugRelatedField(queryset=DatasetSet.objects.none(), slug_field="name")
class Meta: class Meta:
model = DatasetElement model = DatasetElement
...@@ -681,7 +672,7 @@ class DatasetElementSerializer(serializers.ModelSerializer): ...@@ -681,7 +672,7 @@ class DatasetElementSerializer(serializers.ModelSerializer):
validators = [ validators = [
UniqueTogetherValidator( UniqueTogetherValidator(
queryset=DatasetElement.objects.all(), queryset=DatasetElement.objects.all(),
fields=["dataset", "element_id", "set"], fields=["element_id", "set"],
message="This element is already part of this set.", message="This element is already part of this set.",
) )
] ]
...@@ -690,13 +681,12 @@ class DatasetElementSerializer(serializers.ModelSerializer): ...@@ -690,13 +681,12 @@ class DatasetElementSerializer(serializers.ModelSerializer):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
if dataset := self.context.get("dataset"): if dataset := self.context.get("dataset"):
self.fields["element_id"].queryset = Element.objects.filter(corpus=dataset.corpus) self.fields["element_id"].queryset = Element.objects.filter(corpus=dataset.corpus)
self.fields["set"].queryset = dataset.sets.all()
def validate_set(self, value): def validate(self, data):
# The set must match the `sets` array defined at the dataset level data = super().validate(data)
dataset = self.context["dataset"] data.pop("dataset")
if dataset and value not in dataset.sets: return data
raise ValidationError(f"This dataset has no set named {value}.")
return value
class DatasetElementInfoSerializer(DatasetElementSerializer): class DatasetElementInfoSerializer(DatasetElementSerializer):
...@@ -714,10 +704,11 @@ class DatasetElementInfoSerializer(DatasetElementSerializer): ...@@ -714,10 +704,11 @@ class DatasetElementInfoSerializer(DatasetElementSerializer):
fields = DatasetElementSerializer.Meta.fields + ("dataset",) fields = DatasetElementSerializer.Meta.fields + ("dataset",)
class ElementDatasetSerializer(serializers.ModelSerializer): class ElementDatasetSetSerializer(serializers.ModelSerializer):
dataset = DatasetSerializer() dataset = DatasetSerializer(source="set.dataset")
previous = serializers.UUIDField(allow_null=True, read_only=True) previous = serializers.UUIDField(allow_null=True, read_only=True)
next = 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: class Meta:
model = DatasetElement model = DatasetElement
...@@ -726,35 +717,29 @@ class ElementDatasetSerializer(serializers.ModelSerializer): ...@@ -726,35 +717,29 @@ class ElementDatasetSerializer(serializers.ModelSerializer):
class SelectionDatasetElementSerializer(serializers.Serializer): class SelectionDatasetElementSerializer(serializers.Serializer):
dataset_id = serializers.PrimaryKeyRelatedField( set_id = serializers.PrimaryKeyRelatedField(
queryset=Dataset.objects.all(), queryset=DatasetSet.objects.none(),
source="dataset", source="set",
write_only=True, 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"}, 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 ( if (
(corpus := self.context.get("corpus")) (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}.") raise ValidationError(f"Dataset {set.dataset.id} is not part of corpus {corpus.name}.")
if dataset.state == DatasetState.Complete: if set.dataset.state == DatasetState.Complete:
raise ValidationError(f"Dataset {dataset.id} is marked as completed.") raise ValidationError(f"Dataset {set.dataset.id} is marked as completed.")
return dataset return set
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
def create(self, validated_data): def create(self, validated_data):
user = self.context["request"].user user = self.context["request"].user
......
...@@ -9,7 +9,7 @@ from arkindex.documents.models import Corpus ...@@ -9,7 +9,7 @@ from arkindex.documents.models import Corpus
from arkindex.process.models import Process, ProcessDataset, ProcessMode from arkindex.process.models import Process, ProcessDataset, ProcessMode
from arkindex.project.tests import FixtureAPITestCase from arkindex.project.tests import FixtureAPITestCase
from arkindex.project.tools import fake_now 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 from arkindex.users.models import Role, User
# Using the fake DB fixtures creation date when needed # Using the fake DB fixtures creation date when needed
...@@ -33,6 +33,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -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.dataset, sets=["training", "test", "validation"])
ProcessDataset.objects.create(process=cls.process, dataset=cls.dataset2, sets=["test"]) 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 = 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.vol = cls.corpus.elements.get(name="Volume 1")
cls.page1 = cls.corpus.elements.get(name="Volume 1, page 1r") cls.page1 = cls.corpus.elements.get(name="Volume 1, page 1r")
cls.page2 = cls.corpus.elements.get(name="Volume 1, page 1v") cls.page2 = cls.corpus.elements.get(name="Volume 1, page 1v")
...@@ -75,7 +76,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -75,7 +76,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_list(self): def test_list(self):
self.client.force_login(self.user) 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})) 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.status_code, status.HTTP_200_OK)
self.assertEqual(response.json()["results"], [ self.assertEqual(response.json()["results"], [
...@@ -83,7 +84,13 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -83,7 +84,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"name": "First Dataset", "name": "First Dataset",
"description": "dataset number one", "description": "dataset number one",
"id": str(self.dataset.pk), "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, "set_elements": None,
"state": "open", "state": "open",
"creator": "Test user", "creator": "Test user",
...@@ -96,7 +103,13 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -96,7 +103,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"name": "Second Dataset", "name": "Second Dataset",
"description": "dataset number two", "description": "dataset number two",
"id": str(self.dataset2.pk), "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, "set_elements": None,
"state": "open", "state": "open",
"creator": "Test user", "creator": "Test user",
...@@ -254,7 +267,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -254,7 +267,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_create(self): def test_create(self):
self.client.force_login(self.user) self.client.force_login(self.user)
with self.assertNumQueries(6): with self.assertNumQueries(11):
response = self.client.post( response = self.client.post(
reverse("api:corpus-datasets", kwargs={"pk": self.corpus.pk}), reverse("api:corpus-datasets", kwargs={"pk": self.corpus.pk}),
data={"name": "My dataset", "description": "My dataset for my experiments."}, data={"name": "My dataset", "description": "My dataset for my experiments."},
...@@ -266,7 +279,13 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -266,7 +279,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(created_dataset.id), "id": str(created_dataset.id),
"name": "My dataset", "name": "My dataset",
"description": "My dataset for my experiments.", "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": { "set_elements": {
"training": 0, "training": 0,
"test": 0, "test": 0,
...@@ -282,7 +301,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -282,7 +301,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_create_state_ignored(self): def test_create_state_ignored(self):
self.client.force_login(self.user) self.client.force_login(self.user)
with self.assertNumQueries(6): with self.assertNumQueries(11):
response = self.client.post( response = self.client.post(
reverse("api:corpus-datasets", kwargs={"pk": self.corpus.pk}), reverse("api:corpus-datasets", kwargs={"pk": self.corpus.pk}),
data={"name": "My dataset", "description": "My dataset for my experiments.", "state": "complete"}, data={"name": "My dataset", "description": "My dataset for my experiments.", "state": "complete"},
...@@ -295,8 +314,18 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -295,8 +314,18 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(created_dataset.id), "id": str(created_dataset.id),
"name": "My dataset", "name": "My dataset",
"description": "My dataset for my experiments.", "description": "My dataset for my experiments.",
"sets": ["training", "test", "validation"], "sets": [
"set_elements": {"test": 0, "training": 0, "validation": 0}, {
"id": str(ds.id),
"name": ds.name
}
for ds in created_dataset.sets.all()
],
"set_elements": {
"training": 0,
"test": 0,
"validation": 0,
},
"state": "open", "state": "open",
"creator": "Test user", "creator": "Test user",
"task_id": None, "task_id": None,
...@@ -307,10 +336,10 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -307,10 +336,10 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_create_sets(self): def test_create_sets(self):
self.client.force_login(self.user) self.client.force_login(self.user)
with self.assertNumQueries(6): with self.assertNumQueries(11):
response = self.client.post( response = self.client.post(
reverse("api:corpus-datasets", kwargs={"pk": self.corpus.pk}), 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" format="json"
) )
self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertEqual(response.status_code, status.HTTP_201_CREATED)
...@@ -319,7 +348,13 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -319,7 +348,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(created_dataset.id), "id": str(created_dataset.id),
"name": "My dataset", "name": "My dataset",
"description": "My dataset for my experiments.", "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}, "set_elements": {"a": 0, "b": 0, "c": 0, "d": 0},
"state": "open", "state": "open",
"creator": "Test user", "creator": "Test user",
...@@ -329,39 +364,39 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -329,39 +364,39 @@ class TestDatasetsAPI(FixtureAPITestCase):
"updated": created_dataset.updated.isoformat().replace("+00:00", "Z"), "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) self.client.force_login(self.user)
with self.assertNumQueries(3): with self.assertNumQueries(3):
response = self.client.post( response = self.client.post(
reverse("api:corpus-datasets", kwargs={"pk": self.corpus.pk}), 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" format="json"
) )
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) 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): def test_create_sets_unique_names(self):
self.client.force_login(self.user) self.client.force_login(self.user)
with self.assertNumQueries(3): with self.assertNumQueries(3):
response = self.client.post( response = self.client.post(
reverse("api:corpus-datasets", kwargs={"pk": self.corpus.pk}), 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" format="json"
) )
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) 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): def test_create_sets_blank_names(self):
self.client.force_login(self.user) self.client.force_login(self.user)
with self.assertNumQueries(3): with self.assertNumQueries(3):
response = self.client.post( response = self.client.post(
reverse("api:corpus-datasets", kwargs={"pk": self.corpus.pk}), 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" format="json"
) )
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), { self.assertDictEqual(response.json(), {
"sets": "set_names":
{ {
"0": ["This field may not be blank."], "0": ["This field may not be blank."],
"1": ["This field may not be blank."] "1": ["This field may not be blank."]
...@@ -376,13 +411,13 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -376,13 +411,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
data={ data={
"name": "My Dataset", "name": "My Dataset",
"description": "My dataset for my experiments.", "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" format="json"
) )
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), { self.assertDictEqual(response.json(), {
"sets": { "set_names": {
"1": ["Ensure this field has no more than 50 characters."] "1": ["Ensure this field has no more than 50 characters."]
} }
}) })
...@@ -396,7 +431,6 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -396,7 +431,6 @@ class TestDatasetsAPI(FixtureAPITestCase):
data={ data={
"name": "Shin Seiki Evangelion", "name": "Shin Seiki Evangelion",
"description": "Omedeto!", "description": "Omedeto!",
"sets": ["unit-01", "unit-00", "unit-02"],
}, },
format="json" format="json"
) )
...@@ -412,7 +446,6 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -412,7 +446,6 @@ class TestDatasetsAPI(FixtureAPITestCase):
data={ data={
"name": "Shin Seiki Evangelion", "name": "Shin Seiki Evangelion",
"description": "Omedeto!", "description": "Omedeto!",
"sets": ["unit-01", "unit-00", "unit-02"],
}, },
format="json" format="json"
) )
...@@ -428,7 +461,6 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -428,7 +461,6 @@ class TestDatasetsAPI(FixtureAPITestCase):
data={ data={
"name": "Shin Seiki Evangelion", "name": "Shin Seiki Evangelion",
"description": "Omedeto!", "description": "Omedeto!",
"sets": ["unit-01", "unit-00", "unit-02"],
}, },
format="json" format="json"
) )
...@@ -446,7 +478,6 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -446,7 +478,6 @@ class TestDatasetsAPI(FixtureAPITestCase):
data={ data={
"name": "Shin Seiki Evangelion", "name": "Shin Seiki Evangelion",
"description": "Omedeto!", "description": "Omedeto!",
"sets": ["unit-01", "unit-00", "unit-02"],
}, },
format="json" format="json"
) )
...@@ -476,7 +507,6 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -476,7 +507,6 @@ class TestDatasetsAPI(FixtureAPITestCase):
data={ data={
"name": "Another Dataset", "name": "Another Dataset",
"description": "My dataset for my experiments.", "description": "My dataset for my experiments.",
"sets": self.dataset.sets,
}, },
format="json" format="json"
) )
...@@ -494,199 +524,21 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -494,199 +524,21 @@ class TestDatasetsAPI(FixtureAPITestCase):
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), {"description": ["This field is required."]}) 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.client.force_login(self.user)
self.assertIsNone(self.dataset.task_id) 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): with self.assertNumQueries(3):
response = self.client.put( response = self.client.put(
reverse("api:dataset-update", kwargs={"pk": self.dataset.pk}), reverse("api:dataset-update", kwargs={"pk": self.dataset.pk}),
data={ data={
"name": "Shin Seiki Evangelion", "name": "Shin Seiki Evangelion",
"description": "Omedeto!", "description": "Omedeto!",
"sets": [] "set_names": ["unit-01", "unit-02"],
}, },
format="json" format="json"
) )
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) 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": ["This API endpoint does not allow updating a dataset's sets."]})
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."]
}
})
def test_update_empty_or_blank_description_or_name(self): def test_update_empty_or_blank_description_or_name(self):
self.client.force_login(self.user) self.client.force_login(self.user)
...@@ -696,15 +548,13 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -696,15 +548,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
data={ data={
"name": "", "name": "",
"description": " ", "description": " ",
"sets": "",
}, },
format="json" format="json"
) )
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), { self.assertDictEqual(response.json(), {
"name": ["This field may not be blank."], "name": ["This field may not be blank."],
"description": ["This field may not be blank."], "description": ["This field may not be blank."]
"sets": ['Expected a list of items but got type "str".'],
}) })
def test_update_all_errors(self): def test_update_all_errors(self):
...@@ -715,7 +565,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -715,7 +565,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
data={ data={
"name": "", "name": "",
"description": " ", "description": " ",
"sets": ["unit-00", "unit-00", "unit-02"] "set_names": ["unit-00", "unit-00", "unit-02"]
}, },
format="json" format="json"
) )
...@@ -723,7 +573,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -723,7 +573,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
self.assertDictEqual(response.json(), { self.assertDictEqual(response.json(), {
"name": ["This field may not be blank."], "name": ["This field may not be blank."],
"description": ["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): def test_update_state_requires_ponos_auth(self):
...@@ -819,7 +669,6 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -819,7 +669,6 @@ class TestDatasetsAPI(FixtureAPITestCase):
data={ data={
"name": "AA", "name": "AA",
"description": "BB", "description": "BB",
"sets": self.dataset.sets + ["CC"],
"state": new_state.value, "state": new_state.value,
}, },
format="json" format="json"
...@@ -946,7 +795,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -946,7 +795,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
self.assertEqual(self.dataset.state, DatasetState.Open) self.assertEqual(self.dataset.state, DatasetState.Open)
self.assertEqual(self.dataset.name, "First Dataset") self.assertEqual(self.dataset.name, "First Dataset")
self.assertEqual(self.dataset.description, "Omedeto!") 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): def test_partial_update_empty_or_blank_description_or_name(self):
self.client.force_login(self.user) self.client.force_login(self.user)
...@@ -1022,23 +871,6 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1022,23 +871,6 @@ class TestDatasetsAPI(FixtureAPITestCase):
self.dataset.refresh_from_db() self.dataset.refresh_from_db()
self.assertEqual(self.dataset.state, DatasetState.Open) 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): def test_partial_update_ponos_task_state_forbidden(self):
"""Dataset's state update is limited to specific transitions""" """Dataset's state update is limited to specific transitions"""
op, build, complete, error = [DatasetState[state] for state in ("Open", "Building", "Complete", "Error")] op, build, complete, error = [DatasetState[state] for state in ("Open", "Building", "Complete", "Error")]
...@@ -1093,7 +925,6 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1093,7 +925,6 @@ class TestDatasetsAPI(FixtureAPITestCase):
data={ data={
"name": "AA", "name": "AA",
"description": "BB", "description": "BB",
"sets": self.dataset.sets + ["CC"],
"state": new_state.value, "state": new_state.value,
}, },
format="json" format="json"
...@@ -1150,7 +981,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1150,7 +981,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_retrieve(self): def test_retrieve(self):
self.client.force_login(self.user) self.client.force_login(self.user)
with self.assertNumQueries(4): with self.assertNumQueries(6):
response = self.client.get( response = self.client.get(
reverse("api:dataset-update", kwargs={"pk": self.dataset.pk}) reverse("api:dataset-update", kwargs={"pk": self.dataset.pk})
) )
...@@ -1160,7 +991,13 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1160,7 +991,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"name": "First Dataset", "name": "First Dataset",
"description": "dataset number one", "description": "dataset number one",
"state": "open", "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}, "set_elements": {"test": 0, "training": 0, "validation": 0},
"creator": "Test user", "creator": "Test user",
"task_id": None, "task_id": None,
...@@ -1173,7 +1010,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1173,7 +1010,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
self.client.force_login(self.user) self.client.force_login(self.user)
self.dataset.task = self.task self.dataset.task = self.task
self.dataset.save() self.dataset.save()
with self.assertNumQueries(4): with self.assertNumQueries(6):
response = self.client.get( response = self.client.get(
reverse("api:dataset-update", kwargs={"pk": self.dataset.pk}) reverse("api:dataset-update", kwargs={"pk": self.dataset.pk})
) )
...@@ -1224,7 +1061,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1224,7 +1061,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_delete(self): def test_delete(self):
self.client.force_login(self.user) self.client.force_login(self.user)
with self.assertNumQueries(6): with self.assertNumQueries(7):
response = self.client.delete( response = self.client.delete(
reverse("api:dataset-update", kwargs={"pk": self.dataset.pk}), reverse("api:dataset-update", kwargs={"pk": self.dataset.pk}),
) )
...@@ -1250,14 +1087,15 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1250,14 +1087,15 @@ class TestDatasetsAPI(FixtureAPITestCase):
""" """
DestroyDataset also deletes DatasetElements DestroyDataset also deletes DatasetElements
""" """
self.dataset.dataset_elements.create(element_id=self.vol.id, set="test") test_set, train_set, validation_set = self.dataset.sets.all().order_by("name")
self.dataset.dataset_elements.create(element_id=self.vol.id, set="training") test_set.set_elements.create(element_id=self.vol.id)
self.dataset.dataset_elements.create(element_id=self.page1.id, set="training") train_set.set_elements.create(element_id=self.vol.id, set="training")
self.dataset.dataset_elements.create(element_id=self.page2.id, set="validation") train_set.set_elements.create(element_id=self.page1.id, set="training")
self.dataset.dataset_elements.create(element_id=self.page3.id, set="validation") 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) self.client.force_login(self.user)
with self.assertNumQueries(6): with self.assertNumQueries(7):
response = self.client.delete( response = self.client.delete(
reverse("api:dataset-update", kwargs={"pk": self.dataset.pk}), reverse("api:dataset-update", kwargs={"pk": self.dataset.pk}),
) )
...@@ -1266,7 +1104,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1266,7 +1104,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
with self.assertRaises(Dataset.DoesNotExist): with self.assertRaises(Dataset.DoesNotExist):
self.dataset.refresh_from_db() 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 # No elements should have been deleted
self.vol.refresh_from_db() self.vol.refresh_from_db()
...@@ -1296,12 +1134,13 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1296,12 +1134,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
self.assertEqual(filter_rights_mock.call_args, call(self.user, Corpus, Role.Guest.value)) self.assertEqual(filter_rights_mock.call_args, call(self.user, Corpus, Role.Guest.value))
def test_list_elements_set_filter_wrong_set(self): 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) self.client.force_login(self.user)
with self.assertNumQueries(4): with self.assertNumQueries(4):
response = self.client.get( response = self.client.get(
reverse("api:dataset-elements", kwargs={"pk": str(self.dataset.id)}), 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.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertDictEqual(response.json(), { self.assertDictEqual(response.json(), {
...@@ -1312,10 +1151,11 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1312,10 +1151,11 @@ class TestDatasetsAPI(FixtureAPITestCase):
}) })
def test_list_elements_set_filter(self): def test_list_elements_set_filter(self):
self.dataset.dataset_elements.create(element_id=self.page1.id, set="test") test_set, train_set, _ = self.dataset.sets.all().order_by("name")
self.dataset.dataset_elements.create(element_id=self.page2.id, set="training") 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) self.client.force_login(self.user)
with self.assertNumQueries(5): with self.assertNumQueries(6):
response = self.client.get( response = self.client.get(
reverse("api:dataset-elements", kwargs={"pk": self.dataset.pk}), reverse("api:dataset-elements", kwargs={"pk": self.dataset.pk}),
data={"set": "training", "with_count": "true"}, data={"set": "training", "with_count": "true"},
...@@ -1326,15 +1166,17 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1326,15 +1166,17 @@ class TestDatasetsAPI(FixtureAPITestCase):
self.assertDictEqual(data, {"count": 1, "next": None, "previous": None}) self.assertDictEqual(data, {"count": 1, "next": None, "previous": None})
self.assertEqual(len(results), 1) self.assertEqual(len(results), 1)
dataset_element = results[0] dataset_element = results[0]
print(dataset_element)
self.assertEqual(dataset_element["element"]["id"], str(self.page2.id)) self.assertEqual(dataset_element["element"]["id"], str(self.page2.id))
self.assertEqual(dataset_element["set"], "training") self.assertEqual(dataset_element["set"], "training")
@patch("arkindex.documents.models.Element.thumbnail", MagicMock(s3_url="s3_url")) @patch("arkindex.documents.models.Element.thumbnail", MagicMock(s3_url="s3_url"))
def test_list_elements(self): def test_list_elements(self):
self.dataset.dataset_elements.create(element_id=self.vol.id, set="test") test_set, train_set, validation_set = self.dataset.sets.all().order_by("name")
self.dataset.dataset_elements.create(element_id=self.page1.id, set="training") test_set.set_elements.create(element_id=self.vol.id)
self.dataset.dataset_elements.create(element_id=self.page2.id, set="validation") train_set.set_elements.create(element_id=self.page1.id)
self.dataset.dataset_elements.create(element_id=self.page3.id, set="validation") 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.confidence = 0.42
self.page3.mirrored = True self.page3.mirrored = True
self.page3.rotation_angle = 42 self.page3.rotation_angle = 42
...@@ -1523,7 +1365,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1523,7 +1365,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
self.dataset.state = state self.dataset.state = state
self.dataset.save() self.dataset.save()
with self.subTest(state=state): with self.subTest(state=state):
with self.assertNumQueries(4): with self.assertNumQueries(5):
response = self.client.get( response = self.client.get(
reverse("api:dataset-elements", kwargs={"pk": self.dataset.pk}), reverse("api:dataset-elements", kwargs={"pk": self.dataset.pk}),
{"page_size": 3}, {"page_size": 3},
...@@ -1589,7 +1431,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1589,7 +1431,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_add_element_wrong_element(self): def test_add_element_wrong_element(self):
element = self.private_corpus.elements.create(type=self.private_corpus.types.create(slug="folder")) element = self.private_corpus.elements.create(type=self.private_corpus.types.create(slug="folder"))
self.client.force_login(self.user) self.client.force_login(self.user)
with self.assertNumQueries(4): with self.assertNumQueries(5):
response = self.client.post( response = self.client.post(
reverse("api:dataset-elements", kwargs={"pk": self.dataset.id}), reverse("api:dataset-elements", kwargs={"pk": self.dataset.id}),
data={"set": "test", "element_id": str(element.id)}, data={"set": "test", "element_id": str(element.id)},
...@@ -1602,7 +1444,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1602,7 +1444,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_add_element_wrong_set(self): def test_add_element_wrong_set(self):
self.client.force_login(self.user) self.client.force_login(self.user)
with self.assertNumQueries(4): with self.assertNumQueries(5):
response = self.client.post( response = self.client.post(
reverse("api:dataset-elements", kwargs={"pk": self.dataset.id}), reverse("api:dataset-elements", kwargs={"pk": self.dataset.id}),
data={"set": "aaaaaaaaaaa", "element_id": str(self.vol.id)}, data={"set": "aaaaaaaaaaa", "element_id": str(self.vol.id)},
...@@ -1610,7 +1452,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1610,7 +1452,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
) )
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), { 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): def test_add_element_dataset_requires_open(self):
...@@ -1627,9 +1469,10 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1627,9 +1469,10 @@ class TestDatasetsAPI(FixtureAPITestCase):
self.assertListEqual(response.json(), ["You can only add elements to a dataset in an open state."]) self.assertListEqual(response.json(), ["You can only add elements to a dataset in an open state."])
def test_add_element_already_exists(self): 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) self.client.force_login(self.user)
with self.assertNumQueries(5): with self.assertNumQueries(6):
response = self.client.post( response = self.client.post(
reverse("api:dataset-elements", kwargs={"pk": self.dataset.id}), reverse("api:dataset-elements", kwargs={"pk": self.dataset.id}),
data={"set": "test", "element_id": str(self.page1.id)}, data={"set": "test", "element_id": str(self.page1.id)},
...@@ -1639,8 +1482,9 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1639,8 +1482,9 @@ class TestDatasetsAPI(FixtureAPITestCase):
self.assertDictEqual(response.json(), {"non_field_errors": ["This element is already part of this set."]}) self.assertDictEqual(response.json(), {"non_field_errors": ["This element is already part of this set."]})
def test_add_element(self): def test_add_element(self):
train_set = self.dataset.sets.get(name="training")
self.client.force_login(self.user) self.client.force_login(self.user)
with self.assertNumQueries(10): with self.assertNumQueries(11):
response = self.client.post( response = self.client.post(
reverse("api:dataset-elements", kwargs={"pk": self.dataset.id}), reverse("api:dataset-elements", kwargs={"pk": self.dataset.id}),
data={"set": "training", "element_id": str(self.page1.id)}, data={"set": "training", "element_id": str(self.page1.id)},
...@@ -1648,10 +1492,12 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1648,10 +1492,12 @@ class TestDatasetsAPI(FixtureAPITestCase):
) )
self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertQuerysetEqual( 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")] [("training", "Volume 1, page 1r")]
) )
# CreateDatasetElementSelection
def test_add_from_selection_requires_login(self): def test_add_from_selection_requires_login(self):
with self.assertNumQueries(0): with self.assertNumQueries(0):
response = self.client.post(reverse("api:dataset-elements-selection", kwargs={"pk": self.corpus.id})) response = self.client.post(reverse("api:dataset-elements-selection", kwargs={"pk": self.corpus.id}))
...@@ -1710,8 +1556,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1710,8 +1556,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
response = self.client.post(reverse("api:dataset-elements-selection", kwargs={"pk": self.corpus.id})) 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.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), { self.assertDictEqual(response.json(), {
"dataset_id": ["This field is required."], "set_id": ["This field is required."],
"set": ["This field is required."],
}) })
def test_add_from_selection_wrong_values(self): def test_add_from_selection_wrong_values(self):
...@@ -1719,61 +1564,50 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1719,61 +1564,50 @@ class TestDatasetsAPI(FixtureAPITestCase):
with self.assertNumQueries(3): with self.assertNumQueries(3):
response = self.client.post( response = self.client.post(
reverse("api:dataset-elements-selection", kwargs={"pk": self.corpus.id}), reverse("api:dataset-elements-selection", kwargs={"pk": self.corpus.id}),
data={"set": {}, "dataset_id": "AAA"}, data={"set_id": "AAA"},
format="json", format="json",
) )
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), { self.assertDictEqual(response.json(), {
"dataset_id": ["“AAA” is not a valid UUID."], "set_id": ["“AAA” is not a valid UUID."],
"set": ["Not a valid string."],
}) })
def test_add_from_selection_wrong_dataset(self): 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) self.client.force_login(self.user)
with self.assertNumQueries(4): with self.assertNumQueries(4):
response = self.client.post( response = self.client.post(
reverse("api:dataset-elements-selection", kwargs={"pk": self.corpus.id}), 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", format="json",
) )
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), { 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): def test_add_from_selection_completed_dataset(self):
"""A dataset in the Complete state is immutable""" """A dataset in the Complete state is immutable"""
test_set = self.dataset.sets.first()
self.client.force_login(self.user) self.client.force_login(self.user)
self.dataset.state = DatasetState.Complete self.dataset.state = DatasetState.Complete
self.dataset.save() self.dataset.save()
with self.assertNumQueries(4): with self.assertNumQueries(4):
response = self.client.post( response = self.client.post(
reverse("api:dataset-elements-selection", kwargs={"pk": self.corpus.id}), 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(), {
"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},
format="json", format="json",
) )
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), { 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): 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.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")] [("training", "Volume 1, page 1r")]
) )
self.user.selected_elements.set([self.vol, self.page1, self.page2]) self.user.selected_elements.set([self.vol, self.page1, self.page2])
...@@ -1782,12 +1616,12 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1782,12 +1616,12 @@ class TestDatasetsAPI(FixtureAPITestCase):
with self.assertNumQueries(6): with self.assertNumQueries(6):
response = self.client.post( response = self.client.post(
reverse("api:dataset-elements-selection", kwargs={"pk": self.corpus.id}), 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", format="json",
) )
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
self.assertQuerysetEqual( 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"),
("training", "Volume 1, page 1r"), ("training", "Volume 1, page 1r"),
...@@ -1819,8 +1653,9 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1819,8 +1653,9 @@ class TestDatasetsAPI(FixtureAPITestCase):
""" """
A non authenticated user can list datasets of a public element A non authenticated user can list datasets of a public element
""" """
self.dataset.dataset_elements.create(element=self.vol, set="train") train_set = self.dataset.sets.get(name="training")
with self.assertNumQueries(3): 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)})) response = self.client.get(reverse("api:element-datasets", kwargs={"pk": str(self.vol.id)}))
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertDictEqual(response.json(), { self.assertDictEqual(response.json(), {
...@@ -1833,7 +1668,13 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1833,7 +1668,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(self.dataset.id), "id": str(self.dataset.id),
"name": "First Dataset", "name": "First Dataset",
"description": "dataset number one", "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, "set_elements": None,
"state": "open", "state": "open",
"corpus_id": str(self.corpus.id), "corpus_id": str(self.corpus.id),
...@@ -1842,7 +1683,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1842,7 +1683,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
"created": self.dataset.created.isoformat().replace("+00:00", "Z"), "created": self.dataset.created.isoformat().replace("+00:00", "Z"),
"updated": self.dataset.updated.isoformat().replace("+00:00", "Z"), "updated": self.dataset.updated.isoformat().replace("+00:00", "Z"),
}, },
"set": "train", "set": "training",
"previous": None, "previous": None,
"next": None "next": None
}] }]
...@@ -1850,10 +1691,12 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1850,10 +1691,12 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_element_datasets(self): def test_element_datasets(self):
self.client.force_login(self.user) self.client.force_login(self.user)
self.dataset.dataset_elements.create(element=self.page1, set="train") _, train_set, validation_set = self.dataset.sets.all().order_by("name")
self.dataset.dataset_elements.create(element=self.page1, set="validation") train_set.set_elements.create(element=self.page1, set="train")
self.dataset2.dataset_elements.create(element=self.page1, set="train") validation_set.set_elements.create(element=self.page1, set="validation")
with self.assertNumQueries(5): 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)})) response = self.client.get(reverse("api:element-datasets", kwargs={"pk": str(self.page1.id)}))
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertDictEqual(response.json(), { self.assertDictEqual(response.json(), {
...@@ -1866,7 +1709,13 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1866,7 +1709,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(self.dataset.id), "id": str(self.dataset.id),
"name": "First Dataset", "name": "First Dataset",
"description": "dataset number one", "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, "set_elements": None,
"state": "open", "state": "open",
"corpus_id": str(self.corpus.id), "corpus_id": str(self.corpus.id),
...@@ -1875,7 +1724,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1875,7 +1724,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
"created": self.dataset.created.isoformat().replace("+00:00", "Z"), "created": self.dataset.created.isoformat().replace("+00:00", "Z"),
"updated": self.dataset.updated.isoformat().replace("+00:00", "Z"), "updated": self.dataset.updated.isoformat().replace("+00:00", "Z"),
}, },
"set": "train", "set": "training",
"previous": None, "previous": None,
"next": None "next": None
}, { }, {
...@@ -1883,7 +1732,13 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1883,7 +1732,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(self.dataset.id), "id": str(self.dataset.id),
"name": "First Dataset", "name": "First Dataset",
"description": "dataset number one", "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, "set_elements": None,
"state": "open", "state": "open",
"corpus_id": str(self.corpus.id), "corpus_id": str(self.corpus.id),
...@@ -1900,7 +1755,13 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1900,7 +1755,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(self.dataset2.id), "id": str(self.dataset2.id),
"name": "Second Dataset", "name": "Second Dataset",
"description": "dataset number two", "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, "set_elements": None,
"state": "open", "state": "open",
"corpus_id": str(self.corpus.id), "corpus_id": str(self.corpus.id),
...@@ -1909,7 +1770,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1909,7 +1770,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
"created": self.dataset2.created.isoformat().replace("+00:00", "Z"), "created": self.dataset2.created.isoformat().replace("+00:00", "Z"),
"updated": self.dataset2.updated.isoformat().replace("+00:00", "Z"), "updated": self.dataset2.updated.isoformat().replace("+00:00", "Z"),
}, },
"set": "train", "set": "training",
"previous": None, "previous": None,
"next": None "next": None
}] }]
...@@ -1917,10 +1778,12 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1917,10 +1778,12 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_element_datasets_with_neighbors_false(self): def test_element_datasets_with_neighbors_false(self):
self.client.force_login(self.user) self.client.force_login(self.user)
self.dataset.dataset_elements.create(element=self.page1, set="train") _, train_set, validation_set = self.dataset.sets.all().order_by("name")
self.dataset.dataset_elements.create(element=self.page1, set="validation") train_set_2 = self.dataset2.sets.get(name="training")
self.dataset2.dataset_elements.create(element=self.page1, set="train") train_set.set_elements.create(element=self.page1)
with self.assertNumQueries(5): 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}) 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.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertDictEqual(response.json(), { self.assertDictEqual(response.json(), {
...@@ -1933,7 +1796,13 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1933,7 +1796,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(self.dataset.id), "id": str(self.dataset.id),
"name": "First Dataset", "name": "First Dataset",
"description": "dataset number one", "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, "set_elements": None,
"state": "open", "state": "open",
"corpus_id": str(self.corpus.id), "corpus_id": str(self.corpus.id),
...@@ -1942,7 +1811,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1942,7 +1811,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
"created": self.dataset.created.isoformat().replace("+00:00", "Z"), "created": self.dataset.created.isoformat().replace("+00:00", "Z"),
"updated": self.dataset.updated.isoformat().replace("+00:00", "Z"), "updated": self.dataset.updated.isoformat().replace("+00:00", "Z"),
}, },
"set": "train", "set": "training",
"previous": None, "previous": None,
"next": None "next": None
}, { }, {
...@@ -1950,7 +1819,13 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1950,7 +1819,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(self.dataset.id), "id": str(self.dataset.id),
"name": "First Dataset", "name": "First Dataset",
"description": "dataset number one", "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, "set_elements": None,
"state": "open", "state": "open",
"corpus_id": str(self.corpus.id), "corpus_id": str(self.corpus.id),
...@@ -1967,7 +1842,13 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1967,7 +1842,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(self.dataset2.id), "id": str(self.dataset2.id),
"name": "Second Dataset", "name": "Second Dataset",
"description": "dataset number two", "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, "set_elements": None,
"state": "open", "state": "open",
"corpus_id": str(self.corpus.id), "corpus_id": str(self.corpus.id),
...@@ -1976,7 +1857,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1976,7 +1857,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
"created": self.dataset2.created.isoformat().replace("+00:00", "Z"), "created": self.dataset2.created.isoformat().replace("+00:00", "Z"),
"updated": self.dataset2.updated.isoformat().replace("+00:00", "Z"), "updated": self.dataset2.updated.isoformat().replace("+00:00", "Z"),
}, },
"set": "train", "set": "training",
"previous": None, "previous": None,
"next": None "next": None
}] }]
...@@ -1984,12 +1865,14 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1984,12 +1865,14 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_element_datasets_with_neighbors(self): def test_element_datasets_with_neighbors(self):
self.client.force_login(self.user) self.client.force_login(self.user)
self.dataset.dataset_elements.create(element=self.page1, set="train") _, train_set, validation_set = self.dataset.sets.all().order_by("name")
self.dataset.dataset_elements.create(element=self.page2, set="train") train_set_2 = self.dataset2.sets.get(name="training")
self.dataset.dataset_elements.create(element=self.page3, set="train") train_set.set_elements.create(element=self.page1)
self.dataset.dataset_elements.create(element=self.page1, set="validation") train_set.set_elements.create(element=self.page2)
self.dataset2.dataset_elements.create(element=self.page1, set="train") train_set.set_elements.create(element=self.page3)
self.dataset2.dataset_elements.create(element=self.page3, set="train") 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 # 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)]) sorted_dataset_elements = sorted([str(self.page1.id), str(self.page2.id), str(self.page3.id)])
...@@ -1997,9 +1880,10 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -1997,9 +1880,10 @@ class TestDatasetsAPI(FixtureAPITestCase):
sorted_dataset2_elements = sorted([str(self.page1.id), str(self.page3.id)]) sorted_dataset2_elements = sorted([str(self.page1.id), str(self.page3.id)])
page1_index_2 = sorted_dataset2_elements.index(str(self.page1.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}) 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.assertEqual(response.status_code, status.HTTP_200_OK)
self.maxDiff = None
self.assertDictEqual(response.json(), { self.assertDictEqual(response.json(), {
"count": 3, "count": 3,
"next": None, "next": None,
...@@ -2010,7 +1894,13 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -2010,7 +1894,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(self.dataset.id), "id": str(self.dataset.id),
"name": "First Dataset", "name": "First Dataset",
"description": "dataset number one", "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, "set_elements": None,
"state": "open", "state": "open",
"corpus_id": str(self.corpus.id), "corpus_id": str(self.corpus.id),
...@@ -2019,7 +1909,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -2019,7 +1909,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
"created": self.dataset.created.isoformat().replace("+00:00", "Z"), "created": self.dataset.created.isoformat().replace("+00:00", "Z"),
"updated": self.dataset.updated.isoformat().replace("+00:00", "Z"), "updated": self.dataset.updated.isoformat().replace("+00:00", "Z"),
}, },
"set": "train", "set": "training",
"previous": ( "previous": (
sorted_dataset_elements[page1_index_1 - 1] sorted_dataset_elements[page1_index_1 - 1]
if page1_index_1 - 1 >= 0 if page1_index_1 - 1 >= 0
...@@ -2035,7 +1925,13 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -2035,7 +1925,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(self.dataset.id), "id": str(self.dataset.id),
"name": "First Dataset", "name": "First Dataset",
"description": "dataset number one", "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, "set_elements": None,
"state": "open", "state": "open",
"corpus_id": str(self.corpus.id), "corpus_id": str(self.corpus.id),
...@@ -2052,7 +1948,13 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -2052,7 +1948,13 @@ class TestDatasetsAPI(FixtureAPITestCase):
"id": str(self.dataset2.id), "id": str(self.dataset2.id),
"name": "Second Dataset", "name": "Second Dataset",
"description": "dataset number two", "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, "set_elements": None,
"state": "open", "state": "open",
"corpus_id": str(self.corpus.id), "corpus_id": str(self.corpus.id),
...@@ -2061,7 +1963,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -2061,7 +1963,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
"created": self.dataset2.created.isoformat().replace("+00:00", "Z"), "created": self.dataset2.created.isoformat().replace("+00:00", "Z"),
"updated": self.dataset2.updated.isoformat().replace("+00:00", "Z"), "updated": self.dataset2.updated.isoformat().replace("+00:00", "Z"),
}, },
"set": "train", "set": "training",
"previous": ( "previous": (
sorted_dataset2_elements[page1_index_2 - 1] sorted_dataset2_elements[page1_index_2 - 1]
if page1_index_2 == 1 if page1_index_2 == 1
...@@ -2136,13 +2038,14 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -2136,13 +2038,14 @@ class TestDatasetsAPI(FixtureAPITestCase):
self.dataset.state = DatasetState.Error self.dataset.state = DatasetState.Error
self.dataset.task = self.task self.dataset.task = self.task
self.dataset.save() self.dataset.save()
self.dataset.dataset_elements.create(element=self.page1, set="test") test_set, _, validation_set = self.dataset.sets.all().order_by("name")
self.dataset.dataset_elements.create(element=self.page1, set="validation") test_set.set_elements.create(element=self.page1)
self.dataset.dataset_elements.create(element=self.vol, set="validation") 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.assertCountEqual(self.corpus.datasets.values_list("name", flat=True), ["First Dataset", "Second Dataset"])
self.client.force_login(self.user) self.client.force_login(self.user)
with self.assertNumQueries(12): with self.assertNumQueries(16):
response = self.client.post( response = self.client.post(
reverse("api:dataset-clone", kwargs={"pk": self.dataset.id}), reverse("api:dataset-clone", kwargs={"pk": self.dataset.id}),
format="json", format="json",
...@@ -2155,9 +2058,11 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -2155,9 +2058,11 @@ class TestDatasetsAPI(FixtureAPITestCase):
]) ])
data = response.json() data = response.json()
clone = self.corpus.datasets.get(id=data["id"]) 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) self.assertEqual(clone.creator, self.user)
data.pop("created") data.pop("created")
data.pop("updated") data.pop("updated")
cloned_sets = data.pop("sets")
self.assertDictEqual( self.assertDictEqual(
response.json(), response.json(),
{ {
...@@ -2166,14 +2071,27 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -2166,14 +2071,27 @@ class TestDatasetsAPI(FixtureAPITestCase):
"description": self.dataset.description, "description": self.dataset.description,
"creator": self.user.display_name, "creator": self.user.display_name,
"corpus_id": str(self.corpus.id), "corpus_id": str(self.corpus.id),
"sets": ["training", "test", "validation"],
"set_elements": {"test": 1, "training": 0, "validation": 2}, "set_elements": {"test": 1, "training": 0, "validation": 2},
"state": DatasetState.Open.value, "state": DatasetState.Open.value,
"task_id": str(self.task.id), "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( 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"), ("validation", "Volume 1"),
("test", "Volume 1, page 1r"), ("test", "Volume 1, page 1r"),
...@@ -2184,7 +2102,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -2184,7 +2102,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_clone_existing_name(self): def test_clone_existing_name(self):
self.corpus.datasets.create(name="Clone of First Dataset", creator=self.user) self.corpus.datasets.create(name="Clone of First Dataset", creator=self.user)
self.client.force_login(self.user) self.client.force_login(self.user)
with self.assertNumQueries(11): with self.assertNumQueries(15):
response = self.client.post( response = self.client.post(
reverse("api:dataset-clone", kwargs={"pk": self.dataset.id}), reverse("api:dataset-clone", kwargs={"pk": self.dataset.id}),
format="json", format="json",
...@@ -2198,18 +2116,26 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -2198,18 +2116,26 @@ class TestDatasetsAPI(FixtureAPITestCase):
]) ])
data = response.json() data = response.json()
data.pop("id")
data.pop("created") data.pop("created")
data.pop("updated") data.pop("updated")
cloned_dataset = Dataset.objects.get(id=data["id"])
self.maxDiff = None
self.assertDictEqual( self.assertDictEqual(
response.json(), response.json(),
{ {
"id": str(cloned_dataset.id),
"name": "Clone of First Dataset 1", "name": "Clone of First Dataset 1",
"description": self.dataset.description, "description": self.dataset.description,
"creator": self.user.display_name, "creator": self.user.display_name,
"corpus_id": str(self.corpus.id), "corpus_id": str(self.corpus.id),
"sets": self.dataset.sets, "sets": [
"set_elements": {k: 0 for k in self.dataset.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, "state": DatasetState.Open.value,
"task_id": None, "task_id": None,
}, },
...@@ -2218,7 +2144,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -2218,7 +2144,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_clone_name_too_long(self): def test_clone_name_too_long(self):
dataset = self.corpus.datasets.create(name="A" * 99, creator=self.user) dataset = self.corpus.datasets.create(name="A" * 99, creator=self.user)
self.client.force_login(self.user) self.client.force_login(self.user)
with self.assertNumQueries(11): with self.assertNumQueries(14):
response = self.client.post( response = self.client.post(
reverse("api:dataset-clone", kwargs={"pk": dataset.id}), reverse("api:dataset-clone", kwargs={"pk": dataset.id}),
format="json", format="json",
...@@ -2236,7 +2162,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -2236,7 +2162,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
response = self.client.delete(reverse( response = self.client.delete(reverse(
"api:dataset-element", "api:dataset-element",
kwargs={"dataset": str(self.dataset.id), "element": str(self.page1.id)}) 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.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
...@@ -2247,28 +2173,29 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -2247,28 +2173,29 @@ class TestDatasetsAPI(FixtureAPITestCase):
response = self.client.delete(reverse( response = self.client.delete(reverse(
"api:dataset-element", "api:dataset-element",
kwargs={"dataset": str(self.dataset.id), "element": str(self.page1.id)}) 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.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
@patch("arkindex.project.mixins.has_access", return_value=False) @patch("arkindex.project.mixins.has_access", return_value=False)
def test_destroy_dataset_element_requires_contributor(self, has_access_mock): def test_destroy_dataset_element_requires_contributor(self, has_access_mock):
self.client.force_login(self.read_user) self.client.force_login(self.read_user)
self.dataset.dataset_elements.create(element=self.page1, set="train") _, train_set, validation_set = self.dataset.sets.all().order_by("name")
self.dataset.dataset_elements.create(element=self.page1, set="validation") train_set.set_elements.create(element=self.page1)
self.assertEqual(self.dataset.dataset_elements.filter(set="train").count(), 1) validation_set.set_elements.create(element=self.page1)
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): with self.assertNumQueries(3):
response = self.client.delete(reverse( response = self.client.delete(reverse(
"api:dataset-element", "api:dataset-element",
kwargs={"dataset": str(self.dataset.id), "element": str(self.page1.id)}) 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.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.assertDictEqual(response.json(), {"detail": "You need a Contributor access to the dataset to perform this action."})
self.dataset.refresh_from_db() self.dataset.refresh_from_db()
self.assertEqual(self.dataset.dataset_elements.filter(set="train").count(), 1) self.assertEqual(train_set.set_elements.count(), 1)
self.assertEqual(self.dataset.dataset_elements.filter(set="validation").count(), 1) self.assertEqual(validation_set.set_elements.count(), 1)
self.assertEqual(has_access_mock.call_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)) 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): ...@@ -2285,23 +2212,24 @@ class TestDatasetsAPI(FixtureAPITestCase):
def test_destroy_dataset_element_requires_open_dataset(self): def test_destroy_dataset_element_requires_open_dataset(self):
self.client.force_login(self.user) self.client.force_login(self.user)
self.dataset.dataset_elements.create(element=self.page1, set="train") _, train_set, validation_set = self.dataset.sets.all().order_by("name")
self.dataset.dataset_elements.create(element=self.page1, set="validation") train_set.set_elements.create(element=self.page1)
validation_set.set_elements.create(element=self.page1)
self.dataset.state = DatasetState.Error self.dataset.state = DatasetState.Error
self.dataset.save() self.dataset.save()
self.assertEqual(self.dataset.dataset_elements.filter(set="train").count(), 1) self.assertEqual(train_set.set_elements.count(), 1)
self.assertEqual(self.dataset.dataset_elements.filter(set="validation").count(), 1) self.assertEqual(validation_set.set_elements.count(), 1)
with self.assertNumQueries(3): with self.assertNumQueries(3):
response = self.client.delete(reverse( response = self.client.delete(reverse(
"api:dataset-element", "api:dataset-element",
kwargs={"dataset": str(self.dataset.id), "element": str(self.page1.id)}) 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.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(response.json(), {"dataset": ["Elements can only be removed from open Datasets."]}) self.assertDictEqual(response.json(), {"dataset": ["Elements can only be removed from open Datasets."]})
self.dataset.refresh_from_db() self.dataset.refresh_from_db()
self.assertEqual(self.dataset.dataset_elements.filter(set="train").count(), 1) self.assertEqual(train_set.set_elements.count(), 1)
self.assertEqual(self.dataset.dataset_elements.filter(set="validation").count(), 1) self.assertEqual(validation_set.set_elements.count(), 1)
def test_destroy_dataset_element_dataset_doesnt_exist(self): def test_destroy_dataset_element_dataset_doesnt_exist(self):
self.client.force_login(self.user) self.client.force_login(self.user)
...@@ -2309,7 +2237,7 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -2309,7 +2237,7 @@ class TestDatasetsAPI(FixtureAPITestCase):
response = self.client.delete(reverse( response = self.client.delete(reverse(
"api:dataset-element", "api:dataset-element",
kwargs={"dataset": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "element": str(self.page1.id)}) 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.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertDictEqual(response.json(), {"detail": "Not found."}) self.assertDictEqual(response.json(), {"detail": "Not found."})
...@@ -2331,49 +2259,52 @@ class TestDatasetsAPI(FixtureAPITestCase): ...@@ -2331,49 +2259,52 @@ class TestDatasetsAPI(FixtureAPITestCase):
response = self.client.delete(reverse( response = self.client.delete(reverse(
"api:dataset-element", "api:dataset-element",
kwargs={"dataset": str(self.dataset.id), "element": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"}) 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.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertDictEqual(response.json(), {"detail": "Not found."}) self.assertDictEqual(response.json(), {"detail": "Not found."})
def test_destroy_dataset_element_element_not_in_dataset(self): 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) self.client.force_login(self.user)
with self.assertNumQueries(3): with self.assertNumQueries(3):
response = self.client.delete(reverse( response = self.client.delete(reverse(
"api:dataset-element", "api:dataset-element",
kwargs={"dataset": str(self.dataset.id), "element": str(self.page2.id)}) 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.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertDictEqual(response.json(), {"detail": "Not found."}) self.assertDictEqual(response.json(), {"detail": "Not found."})
def test_destroy_dataset_element_wrong_set(self): def test_destroy_dataset_element_wrong_set(self):
self.dataset.dataset_elements.create(element=self.page1, set="train") _, train_set, validation_set = self.dataset.sets.all().order_by("name")
self.dataset.dataset_elements.create(element=self.page2, set="validation") train_set.set_elements.create(element=self.page1)
validation_set.set_elements.create(element=self.page1)
self.client.force_login(self.user) self.client.force_login(self.user)
with self.assertNumQueries(3): with self.assertNumQueries(3):
response = self.client.delete(reverse( response = self.client.delete(reverse(
"api:dataset-element", "api:dataset-element",
kwargs={"dataset": str(self.dataset.id), "element": str(self.page2.id)}) 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.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertDictEqual(response.json(), {"detail": "Not found."}) self.assertDictEqual(response.json(), {"detail": "Not found."})
def test_destroy_dataset_element(self): def test_destroy_dataset_element(self):
self.client.force_login(self.user) self.client.force_login(self.user)
self.dataset.dataset_elements.create(element=self.page1, set="train") _, train_set, validation_set = self.dataset.sets.all().order_by("name")
self.dataset.dataset_elements.create(element=self.page1, set="validation") train_set.set_elements.create(element=self.page1)
self.assertEqual(self.dataset.dataset_elements.filter(set="train").count(), 1) validation_set.set_elements.create(element=self.page1)
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(4): with self.assertNumQueries(4):
response = self.client.delete(reverse( response = self.client.delete(reverse(
"api:dataset-element", "api:dataset-element",
kwargs={"dataset": str(self.dataset.id), "element": str(self.page1.id)}) 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.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
self.dataset.refresh_from_db() self.dataset.refresh_from_db()
self.assertEqual(self.dataset.dataset_elements.filter(set="train").count(), 0) self.assertEqual(train_set.set_elements.count(), 0)
self.assertEqual(self.dataset.dataset_elements.filter(set="validation").count(), 1) self.assertEqual(validation_set.set_elements.count(), 1)