Skip to content

Commit f1f618a

Browse files
Merge pull request #76 from KeithKelleher/main
make endpoints consistent, and share endpoint generation code
2 parents 59c720e + b60c794 commit f1f618a

File tree

5 files changed

+107
-125
lines changed

5 files changed

+107
-125
lines changed

src/api_adapters/arango_api_adapter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ def resolve_id(self, data_model: str, id: str, sortby: dict = {}) -> ResolveResu
257257

258258
query = f"""
259259
FOR doc IN `{label}`
260-
FILTER '{id}' IN doc.xref
260+
FILTER '{id}' IN doc.xref OR doc.id == '{id}'
261261
{self._get_sortby_clause(sortby)}
262262
LIMIT 11
263263
RETURN {self._get_document_cleanup_clause()}

src/api_adapters/strawberry_models/pharos_query_models.py

Lines changed: 33 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
from typing import Optional, List, Literal
1+
from typing import Optional, List, Literal, Dict
22

33
import strawberry
44
from strawberry import Info
55

6-
from src.api_adapters.strawberry_models.class_generators import make_linked_list_result_type, make_resolve_result_type, \
7-
make_details_result_type, make_list_result_type
8-
from src.api_adapters.strawberry_models.input_types import FilterOption, ListFilterSettings, LinkedListFilterSettings, \
9-
ListQueryContext
10-
from src.api_adapters.strawberry_models.shared_query_models import Provenance
6+
from src.api_adapters.strawberry_models.class_generators import make_linked_list_result_type
7+
from src.api_adapters.strawberry_models.input_types import FilterOption, ListFilterSettings, LinkedListFilterSettings
8+
from src.api_adapters.strawberry_models.shared_query_models import Provenance, generate_resolvers
119
from src.interfaces.result_types import LinkedListQueryContext
1210
from src.interfaces.simple_enum import NodeLabel, RelationshipLabel
1311
from src.models.analyte import Synonym
@@ -297,20 +295,6 @@ def provenance(root) -> Provenance:
297295

298296
evidence: List[GoEvidence]
299297

300-
301-
ProteinListResult = make_list_result_type("ProteinListResult", Protein)
302-
GeneListResult = make_list_result_type("GeneListResult", Gene)
303-
TranscriptListResult = make_list_result_type("TranscriptListResult", Transcript)
304-
LigandListResult = make_list_result_type("LigandListResult", Ligand)
305-
GoTermListResult = make_list_result_type("GoTermListResult", GoTerm)
306-
307-
ResolveProteinResult = make_resolve_result_type("ResolveProteinResult", Protein)
308-
ResolveGeneResult = make_resolve_result_type("ResolveGeneResult", Gene)
309-
ResolveTranscriptResult = make_resolve_result_type("ResolveTranscriptResult", Transcript)
310-
ResolveLigandResult = make_resolve_result_type("ResolveLigandResult", Ligand)
311-
312-
GoTermResult = make_details_result_type("GoTermResult", GoTerm)
313-
314298
ProteinGeneQueryResult = make_linked_list_result_type("ProteinGeneQueryResult", "ProteinGeneDetails", GeneProteinRelationship, Gene)
315299
ProteinTranscriptQueryResult = make_linked_list_result_type("ProteinTranscriptQueryResult", "ProteinTranscriptDetails", TranscriptProteinRelationship, Transcript)
316300
ProteinGoTermQueryResult = make_linked_list_result_type("ProteinGoTermQueryResult", "ProteinGoTermDetails", ProteinGoTermRelationship, GoTerm)
@@ -328,86 +312,32 @@ def provenance(root) -> Provenance:
328312

329313
LigandProteinQueryResult = make_linked_list_result_type("LigandProteinQueryResult", "LigandProteinDetails", ProteinLigandRelationship, Protein)
330314

331-
332-
333-
@strawberry.type
334-
class Query:
335-
@strawberry.field()
336-
def proteins(self, info: Info, filter: Optional[ListFilterSettings] = None) -> ProteinListResult:
337-
api = info.context["api"]
338-
context = ListQueryContext(
339-
source_data_model="Protein",
340-
filter = filter
341-
)
342-
result = api.get_list_obj(context)
343-
return result
344-
345-
@strawberry.field()
346-
def genes(self, info: Info, filter: Optional[ListFilterSettings] = None) -> GeneListResult:
347-
api = info.context["api"]
348-
context = ListQueryContext(
349-
source_data_model="Gene",
350-
filter = filter
351-
)
352-
result = api.get_list_obj(context)
353-
return result
354-
355-
@strawberry.field()
356-
def transcripts(self, info: Info, filter: Optional[ListFilterSettings] = None) -> TranscriptListResult:
357-
api = info.context["api"]
358-
context = ListQueryContext(
359-
source_data_model="Transcript",
360-
filter = filter
361-
)
362-
result = api.get_list_obj(context)
363-
return result
364-
365-
@strawberry.field()
366-
def ligands(self, info: Info, filter: Optional[ListFilterSettings] = None) -> LigandListResult:
367-
api = info.context["api"]
368-
context = ListQueryContext(
369-
source_data_model="Ligand",
370-
filter = filter
371-
)
372-
result = api.get_list_obj(context)
373-
return result
374-
375-
@strawberry.field()
376-
def go_terms(self, info: Info, filter: Optional[ListFilterSettings] = None) -> GoTermListResult:
377-
api = info.context["api"]
378-
context = ListQueryContext(
379-
source_data_model="GoTerm",
380-
filter = filter
381-
)
382-
result = api.get_list_obj(context)
383-
return result
384-
385-
@strawberry.field()
386-
def resolve_protein(self, info: Info, id: str) -> ResolveProteinResult:
387-
api = info.context["api"]
388-
result = api.resolve_id("Protein", id=id, sortby={"uniprot_reviewed": "desc", "uniprot_canonical": "desc", "mapping_ratio": "desc"})
389-
return result
390-
391-
@strawberry.field()
392-
def resolve_gene(self, info: Info, id: str) -> ResolveGeneResult:
393-
api = info.context["api"]
394-
result = api.resolve_id("Gene", id=id, sortby={"mapping_ratio": "desc"})
395-
return result
396-
397-
@strawberry.field()
398-
def resolve_transcript(self, info: Info, id: str) -> ResolveTranscriptResult:
399-
api = info.context["api"]
400-
result = api.resolve_id("Transcript", id=id, sortby={"mapping_ratio": "desc"})
401-
return result
402-
403-
@strawberry.field()
404-
def resolve_ligand(self, info: Info, id: str) -> ResolveLigandResult:
405-
api = info.context["api"]
406-
result = api.resolve_id("Ligand", id=id)
407-
return result
408-
409-
@strawberry.field()
410-
def go_term(self, info: Info, id: str) -> GoTermResult:
411-
api = info.context["api"]
412-
result = api.get_details("GoTerm", id=id)
413-
return result
315+
ENDPOINTS: Dict[type, Dict[str, str]] = {
316+
Protein: {
317+
"list": "proteins",
318+
"details": "resolve_protein",
319+
"sortby": {"uniprot_reviewed": "desc", "uniprot_canonical": "desc", "mapping_ratio": "desc"}
320+
},
321+
Gene: {
322+
"list": "genes",
323+
"details": "resolve_gene",
324+
"sortby": {"mapping_ratio": "desc"}
325+
},
326+
Transcript: {
327+
"list": "transcripts",
328+
"details": "resolve_transcript",
329+
"sortby": {"mapping_ratio": "desc"}
330+
},
331+
Ligand: {
332+
"list": "ligands",
333+
"details": "resolve_ligand"
334+
},
335+
GoTerm: {
336+
"list": "go_terms",
337+
"details": "resolve_go_term"
338+
}
339+
}
340+
341+
resolvers = generate_resolvers(ENDPOINTS)
342+
343+
Query = strawberry.type(type("Query", (), resolvers))

src/api_adapters/strawberry_models/pounce_query_models.py

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
from typing import Optional, Union, List
1+
from typing import Optional, Union, List, Dict
22

33
import strawberry
44
from strawberry import Info
55

66
from src.api_adapters.arango_api_adapter import ArangoAPIAdapter
77
from src.api_adapters.strawberry_models.class_generators import make_linked_list_result_type
88
from src.api_adapters.strawberry_models.input_types import LinkedListFilterSettings
9-
from src.api_adapters.strawberry_models.shared_query_models import Provenance, generate_list_resolver
9+
from src.api_adapters.strawberry_models.shared_query_models import Provenance, generate_resolvers
1010
from src.interfaces.result_types import LinkedListQueryContext
1111
from src.models.node import EquivalentId
1212
from src.models.pounce.data import (Biospecimen as BiospecimenBase, Sample as SampleBase,
@@ -468,22 +468,45 @@ class GeneDataResults:
468468

469469
top_level_classes = [Biospecimen, Sample, Investigator, Protein, Project, ProjectType, Experiment, Gene, Metabolite]
470470

471-
472-
LIST_RESOLVERS = {
473-
"projects": Project,
474-
"experiments": Experiment,
475-
"investigators": Investigator,
476-
"biospecimens": Biospecimen,
477-
"samples": Sample,
478-
"proteins": Protein,
479-
"project_types": ProjectType,
480-
"metabolite": Metabolite,
481-
"genes": Gene
471+
ENDPOINTS: Dict[type, Dict[str, str]] = {
472+
Project: {
473+
"list": "projects",
474+
"details": "resolve_project"
475+
},
476+
Experiment: {
477+
"list": "experiments",
478+
"details": "resolve_experiment"
479+
},
480+
Investigator: {
481+
"list": "investigators",
482+
"details": "resolve_investigator"
483+
},
484+
Biospecimen: {
485+
"list": "biospecimens",
486+
"details": "resolve_biospecimen"
487+
},
488+
Sample: {
489+
"list": "samples",
490+
"details": "resolve_sample"
491+
},
492+
Protein: {
493+
"list": "proteins",
494+
"details": "resolve_protein"
495+
},
496+
ProjectType: {
497+
"list": "project_types",
498+
"details": "resolve_project_type"
499+
},
500+
Metabolite: {
501+
"list": "metabolites",
502+
"details": "resolve_metabolite"
503+
},
504+
Gene: {
505+
"list": "genes",
506+
"details": "resolve_gene"
507+
}
482508
}
483509

484-
query_fields = {
485-
name: generate_list_resolver(model_name)
486-
for name, model_name in LIST_RESOLVERS.items()
487-
}
510+
resolvers = generate_resolvers(ENDPOINTS)
488511

489-
Query = strawberry.type(type("Query", (), query_fields))
512+
Query = strawberry.type(type("Query", (), resolvers))

src/api_adapters/strawberry_models/shared_query_models.py

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
from datetime import date, datetime
2-
from typing import Optional, List, Type
2+
from typing import Optional, List, Type, Dict
33

44
import strawberry
55
from strawberry import Info
66

7-
from src.api_adapters.strawberry_models.class_generators import make_list_result_type
7+
from src.api_adapters.strawberry_models.class_generators import make_list_result_type, make_resolve_result_type
88
from src.api_adapters.strawberry_models.input_types import ListFilterSettings, ListQueryContext
99

1010
from src.shared.record_merger import FieldConflictBehavior
@@ -78,6 +78,16 @@ def parse_to_date(iso_format_str: str) -> Optional[date]:
7878
return date.fromisoformat(iso_format_str)
7979

8080

81+
def generate_details_resolver(source_data_model: Type, sortby = {}):
82+
class_name = source_data_model.__name__
83+
return_type = make_resolve_result_type(f"{class_name}ResolveResult", source_data_model)
84+
@strawberry.field()
85+
def resolver(self, info: Info, id: str) -> return_type:
86+
api = info.context["api"]
87+
return api.resolve_id(class_name, id=id, sortby=sortby)
88+
return resolver
89+
90+
8191
def generate_list_resolver(source_data_model: Type):
8292
class_name = source_data_model.__name__
8393
return_type = make_list_result_type(f"{class_name}ListResult", source_data_model)
@@ -87,3 +97,22 @@ def resolver(self, info: Info, filter: Optional[ListFilterSettings] = None) -> r
8797
context = ListQueryContext(source_data_model=class_name, filter=filter)
8898
return api.get_list_obj(context)
8999
return resolver
100+
101+
102+
def generate_resolvers(ENDPOINTS: Dict[type, Dict[str, str]]):
103+
global resolvers
104+
list_resolvers = {
105+
info["list"]: generate_list_resolver(model_cls)
106+
for model_cls, info in ENDPOINTS.items()
107+
if "list" in info
108+
}
109+
details_resolvers = {
110+
info["details"]: generate_details_resolver(model_cls)
111+
for model_cls, info in ENDPOINTS.items()
112+
if "details" in info
113+
}
114+
resolvers = {
115+
**list_resolvers,
116+
**details_resolvers
117+
}
118+
return resolvers

src/use_cases/api/host_graphql_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44

55
import strawberry
66
from fastapi import FastAPI, Request
7+
from fastapi.middleware.cors import CORSMiddleware
78
from strawberry.fastapi import GraphQLRouter
89

910
from src.api_adapters.strawberry_models.pharos_query_models import Query as pharosQuery
1011
from src.api_adapters.strawberry_models.pounce_query_models import Query as pounceQuery
11-
from fastapi.middleware.cors import CORSMiddleware
1212

1313
from src.use_cases.build_from_yaml import HostDashboardFromYaml
1414

0 commit comments

Comments
 (0)