diff --git a/src/mavedb/lib/validation/constants/general.py b/src/mavedb/lib/validation/constants/general.py index 92b4fd5bb..d994dfcc0 100644 --- a/src/mavedb/lib/validation/constants/general.py +++ b/src/mavedb/lib/validation/constants/general.py @@ -44,6 +44,7 @@ variant_count_data = "count_data" required_score_column = "score" +multi_value_keys = ["molecular mechanism assessed"] valid_dataset_columns = [score_columns, count_columns] valid_variant_columns = [variant_score_data, variant_count_data] diff --git a/src/mavedb/lib/validation/keywords.py b/src/mavedb/lib/validation/keywords.py index 305a7c5aa..7d90ac047 100644 --- a/src/mavedb/lib/validation/keywords.py +++ b/src/mavedb/lib/validation/keywords.py @@ -1,5 +1,6 @@ from typing import Optional +from mavedb.lib.validation.constants.general import multi_value_keys from mavedb.lib.validation.exceptions import ValidationError from mavedb.lib.validation.utilities import is_null @@ -7,7 +8,7 @@ def validate_code(key: str, label: str, code: Optional[str]): # TODO(#511) Re-enable the Gene Ontology code requirement. pass - # if key.lower() == "phenotypic assay mechanism" and label.lower() != "other": + # if key.lower() == "molecular mechanism assessed" and label.lower() != "other": # # The Gene Ontology accession is a unique seven digit identifier prefixed by GO:. # # e.g. GO:0005739, GO:1904659, or GO:0016597. # if code is None or not re.match(r"^GO:\d{7}$", code): @@ -26,9 +27,12 @@ def validate_duplicates(keywords: list): keys = [] labels = [] for k in keywords: - keys.append(k.keyword.key.lower()) # k: ExperimentControlledKeywordCreate object - if k.keyword.label.lower() != "other": - labels.append(k.keyword.label.lower()) + key = k.keyword.key.lower() + label = k.keyword.label.lower() + if key not in multi_value_keys: + keys.append(key) + if label != "other": + labels.append(label) keys_set = set(keys) labels_set = set(labels) diff --git a/tests/helpers/constants.py b/tests/helpers/constants.py index 481b5703f..02a013e82 100644 --- a/tests/helpers/constants.py +++ b/tests/helpers/constants.py @@ -429,19 +429,26 @@ }, {"key": "Delivery Method", "label": "Other", "special": False, "description": "Description"}, { - "key": "Phenotypic Assay Mechanism", + "key": "Molecular Mechanism Assessed", "label": "Other", "code": None, "special": False, "description": "Description", }, { - "key": "Phenotypic Assay Mechanism", - "label": "Label", + "key": "Molecular Mechanism Assessed", + "label": "Sodium channel activity", "code": "GO:1234567", "special": False, "description": "Description", }, + { + "key": "Molecular Mechanism Assessed", + "label": "Calcium-mediated signaling", + "code": "GO:1134567", + "special": False, + "description": "Description", + }, { "key": "Phenotypic Assay Profiling Strategy", "label": "Shotgun sequencing", diff --git a/tests/routers/test_experiments.py b/tests/routers/test_experiments.py index 1a04ed6a2..d2bddc586 100644 --- a/tests/routers/test_experiments.py +++ b/tests/routers/test_experiments.py @@ -528,8 +528,8 @@ def test_create_experiment_that_keyword_gene_ontology_has_valid_code(client, set "keywords": [ { "keyword": { - "key": "Phenotypic Assay Mechanism", - "label": "Label", + "key": "Molecular Mechanism Assessed", + "label": "Sodium channel activity", "code": "GO:1234567", "special": False, "description": "Description", @@ -541,8 +541,8 @@ def test_create_experiment_that_keyword_gene_ontology_has_valid_code(client, set response = client.post("/api/v1/experiments/", json=experiment) assert response.status_code == 200 response_data = response.json() - assert response_data["keywords"][0]["keyword"]["key"] == "Phenotypic Assay Mechanism" - assert response_data["keywords"][0]["keyword"]["label"] == "Label" + assert response_data["keywords"][0]["keyword"]["key"] == "Molecular Mechanism Assessed" + assert response_data["keywords"][0]["keyword"]["label"] == "Sodium channel activity" assert response_data["keywords"][0]["keyword"]["code"] == "GO:1234567" @@ -551,7 +551,7 @@ def test_create_experiment_that_keyword_gene_ontology_is_other_without_code(clie "keywords": [ { "keyword": { - "key": "Phenotypic Assay Mechanism", + "key": "Molecular Mechanism Assessed", "label": "Other", "code": None, "description": "Description", @@ -564,17 +564,60 @@ def test_create_experiment_that_keyword_gene_ontology_is_other_without_code(clie response = client.post("/api/v1/experiments/", json=experiment) assert response.status_code == 200 response_data = response.json() - assert response_data["keywords"][0]["keyword"]["key"] == "Phenotypic Assay Mechanism" + assert response_data["keywords"][0]["keyword"]["key"] == "Molecular Mechanism Assessed" assert response_data["keywords"][0]["keyword"]["label"] == "Other" +def test_create_experiment_that_keywords_has_multiple_molecular_mechanism_assessed_labels(client, setup_router_db): + valid_keywords = { + "keywords": [ + { + "keyword": { + "key": "Molecular Mechanism Assessed", + "label": "Sodium channel activity", + "code": "GO:1234567", + "special": False, + "description": "Description", + }, + }, + { + "keyword": { + "key": "Molecular Mechanism Assessed", + "label": "Calcium-mediated signaling", + "code": "GO:1134567", + "special": False, + "description": "Description", + }, + } + ], + } + experiment = {**TEST_MINIMAL_EXPERIMENT, **valid_keywords} + response = client.post("/api/v1/experiments/", json=experiment) + assert response.status_code == 200 + response_data = response.json() + assert len(response_data["keywords"]) == 2 + labels = {kw["keyword"]["label"] for kw in response_data["keywords"]} + codes = {kw["keyword"]["code"] for kw in response_data["keywords"]} + keys = {kw["keyword"]["key"] for kw in response_data["keywords"]} + + assert keys == {"Molecular Mechanism Assessed"} + assert labels == { + "Sodium channel activity", + "Calcium-mediated signaling", + } + assert codes == { + "GO:1234567", + "GO:1134567", + } + + # TODO(#511) Re-enable the Gene Ontology code requirement. # def test_cannot_create_experiment_that_keyword_has_an_invalid_code(client, setup_router_db): # invalid_keyword = { # "keywords": [ # { # "keyword": { -# "key": "Phenotypic Assay Mechanism", +# "key": "Molecular Mechanism Assessed", # "label": "Label", # "code": "invalid", # "description": "Description",