Skip to content

Commit

Permalink
Merge pull request #52 from TheJacksonLaboratory/G3-230-geneset-gene-…
Browse files Browse the repository at this point in the history
…values-endpoint

G3-230 geneset gene values endpoint
  • Loading branch information
francastell authored Apr 22, 2024
2 parents 59c4ece + fc2e668 commit 027801a
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 7 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "geneweaver-api"
version = "0.4.0a13"
version = "0.4.0a14"
description = "The Geneweaver API"
authors = [
"Alexander Berger <alexander.berger@jax.org>",
Expand Down
24 changes: 24 additions & 0 deletions src/geneweaver/api/controller/genesets.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from fastapi import APIRouter, Depends, HTTPException, Path, Query, Security
from fastapi.responses import FileResponse
from geneweaver.api import dependencies as deps
from geneweaver.api.schemas.apimodels import GeneValueReturn
from geneweaver.api.schemas.auth import UserInternal
from geneweaver.api.services import geneset as genset_service
from geneweaver.api.services import publications as publication_service
Expand Down Expand Up @@ -140,6 +141,29 @@ def get_geneset(
return response


@router.get("/{geneset_id}/values")
def get_geneset_values(
geneset_id: Annotated[
int, Path(format="int64", minimum=0, maxiumum=9223372036854775807)
],
user: UserInternal = Security(deps.full_user),
cursor: Optional[deps.Cursor] = Depends(deps.cursor),
) -> GeneValueReturn:
"""Get geneset gene values by geneset ID."""
response = genset_service.get_geneset_gene_values(cursor, geneset_id, user)

if "error" in response:
if response.get("message") == api_message.ACCESS_FORBIDDEN:
raise HTTPException(status_code=403, detail=api_message.ACCESS_FORBIDDEN)
else:
raise HTTPException(status_code=500, detail=api_message.UNEXPECTED_ERROR)

if response.get("data") is None:
raise HTTPException(status_code=404, detail=api_message.RECORD_NOT_FOUND_ERROR)

return response


@router.get("/{geneset_id}/file", response_class=FileResponse)
def get_export_geneset_by_id_type(
geneset_id: Annotated[
Expand Down
7 changes: 7 additions & 0 deletions src/geneweaver/api/schemas/apimodels.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from geneweaver.core.enum import GeneIdentifier, Species
from geneweaver.core.schema.gene import Gene as GeneSchema
from geneweaver.core.schema.geneset import GeneValue as GeneValueSchema
from geneweaver.core.schema.species import Species as SpeciesSchema
from pydantic import AnyUrl, BaseModel

Expand Down Expand Up @@ -75,3 +76,9 @@ class SpeciesReturn(CollectionResponse):
"""Model for Species endpoint return."""

data: List[SpeciesSchema]


class GeneValueReturn(BaseModel):
"""Model for geneset values endpoint return."""

data: List[GeneValueSchema]
29 changes: 29 additions & 0 deletions src/geneweaver/api/services/geneset.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,42 @@ def get_geneset(cursor: Cursor, geneset_id: int, user: User) -> dict:
)
geneset = results[0]
geneset_values = db_geneset_value.by_geneset_id(cursor, geneset_id)

return {"geneset": geneset, "geneset_values": geneset_values}

except Exception as err:
logger.error(err)
raise err


def get_geneset_gene_values(cursor: Cursor, geneset_id: int, user: User) -> dict:
"""Get a gene values for a given geneset ID.
@param cursor: DB cursor
@param geneset_id: geneset identifier
@param user: GW user
@return: dictionary response (geneset and genset values).
"""
try:
if user is None or user.id is None:
return {"error": True, "message": message.ACCESS_FORBIDDEN}

geneset_values = db_geneset_value.by_geneset_id(cursor, geneset_id)
if geneset_values is None or len(geneset_values) <= 0:
return {"data": None}

genes_data = []
for gsv in geneset_values:
gene_value = {"symbol": gsv["ode_ref_id"], "value": float(gsv["gsv_value"])}
genes_data.append(gene_value)

return {"data": genes_data}

except Exception as err:
logger.error(err)
raise err


def get_geneset_w_gene_id_type(
cursor: Cursor, geneset_id: int, user: User, gene_id_type: GeneIdentifier
) -> dict:
Expand Down
30 changes: 30 additions & 0 deletions tests/controllers/test_genesets.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
geneset_w_gene_id_type_resp = test_geneset_data.get("geneset_w_gene_id_type_resp")
geneset_metadata_w_pub_info = test_geneset_data.get("geneset_metadata_w_pub_info")
publication_by_id_resp = test_publication_data.get("publication_by_id")
geneset_genes_values_resp = test_geneset_data.get("geneset_genes_values_resp_1")


@patch("geneweaver.api.services.geneset.get_geneset")
Expand Down Expand Up @@ -198,3 +199,32 @@ def test_get_visible_geneset_errors(mock_get_visible_genesets, client):

response = client.get("/api/genesets?gs_id=1234")
assert response.status_code == 500


@patch("geneweaver.api.services.geneset.get_geneset_gene_values")
def test_get_geneset_gene_values_url_response(mock_get_geneset_gene_values, client):
"""Test get geneset gene values data response."""
mock_get_geneset_gene_values.return_value = geneset_genes_values_resp

response = client.get("/api/genesets/1234/values")
assert response.status_code == 200
assert response.json() == geneset_genes_values_resp


@patch("geneweaver.api.services.geneset.get_geneset_gene_values")
def test_get_geneset_gene_values_errors(mock_get_geneset_gene_values, client):
"""Test get geneset gene values error responses."""
mock_get_geneset_gene_values.return_value = {
"error": True,
"message": message.ACCESS_FORBIDDEN,
}
response = client.get("/api/genesets/1234/values")
assert response.status_code == 403

mock_get_geneset_gene_values.return_value = {"error": True, "message": "other"}
response = client.get("/api/genesets/1234/values")
assert response.status_code == 500

mock_get_geneset_gene_values.return_value = {"data": None}
response = client.get("/api/genesets/1234/values")
assert response.status_code == 404
7 changes: 6 additions & 1 deletion tests/data/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,12 @@
"geneset_metadata_w_pub_info": json.loads(geneset_response_json).get(
"geneset_with_publication_info"
),
"geneset_list_resp": json.loads(geneset_list_response_json),
"geneset_list_resp": json.loads(geneset_list_response_json).get(
"geneset_resp_1_list_10"
),
"geneset_genes_values_resp_1": json.loads(geneset_list_response_json).get(
"geneset_genes_values_resp_1"
),
}

# Gene homolog ids test data
Expand Down
18 changes: 17 additions & 1 deletion tests/data/geneset.json
Original file line number Diff line number Diff line change
Expand Up @@ -280,5 +280,21 @@
"publication_year": null,
"publication_pubmed_id": null
}
]
],
"geneset_genes_values_resp_1": {
"data": [
{
"symbol": "Hs.629744",
"value": 1.0
},
{
"symbol": "Hs.517155",
"value": 1.0
},
{
"symbol": "Hs.356063",
"value": 1.0
}
]
}
}
37 changes: 33 additions & 4 deletions tests/services/test_genset.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
geneset_list_resp = test_geneset_data.get("geneset_list_resp")
geneset_w_gene_id_type_resp = test_geneset_data.get("geneset_w_gene_id_type_resp")
geneset_metadata_w_pub_info = test_geneset_data.get("geneset_metadata_w_pub_info")
geneset_genes_values_resp = test_geneset_data.get("geneset_genes_values_resp_1")
mock_user = User()
mock_user.id = 1

Expand Down Expand Up @@ -176,10 +177,10 @@ def test_geneset_metadata_db_call_error(mock_db_geneset):
@patch("geneweaver.api.services.geneset.db_geneset")
def test_visible_geneset_response(mock_db_geneset):
"""Test general get geneset data no parameters -- default limit."""
mock_db_geneset.get.return_value = geneset_list_resp.get("geneset_resp_1_list_10")
mock_db_geneset.get.return_value = geneset_list_resp

response = geneset.get_visible_genesets(None, mock_user)
assert response.get("data") == geneset_list_resp.get("geneset_resp_1_list_10")
assert response.get("data") == geneset_list_resp


def test_visible_geneset_no_user():
Expand All @@ -196,7 +197,7 @@ def test_visible_geneset_no_user():
@patch("geneweaver.api.services.geneset.db_geneset")
def test_visible_geneset_all_expected_parameters(mock_db_geneset):
"""Test general get geneset data no parameters -- default limit."""
mock_db_geneset.get.return_value = geneset_list_resp.get("geneset_resp_1_list_10")
mock_db_geneset.get.return_value = geneset_list_resp

response = geneset.get_visible_genesets(
cursor=None,
Expand All @@ -215,7 +216,7 @@ def test_visible_geneset_all_expected_parameters(mock_db_geneset):
with_publication_info=True,
)

assert response.get("data") == geneset_list_resp.get("geneset_resp_1_list_10")
assert response.get("data") == geneset_list_resp


@patch("geneweaver.api.services.geneset.db_geneset")
Expand Down Expand Up @@ -249,3 +250,31 @@ def test_map_geneset_homology_db_call_error(mock_db_gene):
geneset.map_geneset_homology(
None, geneset_by_id_resp["geneset_values"], GeneIdentifier(2)
)


@patch("geneweaver.api.services.geneset.db_geneset_value")
def test_geneset_gene_value_response(mock_db_geneset_value):
"""Test geneset gene value data response."""
mock_db_geneset_value.by_geneset_id.return_value = geneset_by_id_resp.get(
"geneset_values"
)

response = geneset.get_geneset_gene_values(None, user=mock_user, geneset_id=1234)
assert response == geneset_genes_values_resp


@patch("geneweaver.api.services.geneset.db_geneset_value")
def test_get_geneset_gene_values_db_errors(mock_db_geneset_value):
"""Test error in get DB call."""
mock_db_geneset_value.by_geneset_id.side_effect = Exception("ERROR")

with pytest.raises(expected_exception=Exception):
geneset.get_geneset_gene_values(None, user=mock_user, geneset_id=1234)


@patch("geneweaver.api.services.geneset.db_geneset_value")
def test_get_geneset_gene_values_invalid_user(mock_db_geneset_value):
"""Test invalid user."""
response = geneset.get_geneset_gene_values(None, user=None, geneset_id=1234)
assert response.get("error") is True
assert response.get("message") == message.ACCESS_FORBIDDEN

0 comments on commit 027801a

Please sign in to comment.