Skip to content

Commit 51b02b5

Browse files
committed
filter for get and post output in parse
1 parent f52acb6 commit 51b02b5

File tree

1 file changed

+115
-65
lines changed

1 file changed

+115
-65
lines changed

src/handlers/api.py

Lines changed: 115 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import asyncio
22
import json
33
import logging
4-
from typing import List, Union
54
import os
65
import bmt
76
from biothings.utils import serializer
@@ -26,8 +25,6 @@
2625

2726
logger = logging.getLogger("smartAPI")
2827

29-
from tornado.web import RequestHandler
30-
3128
def github_authenticated(func):
3229
"""
3330
RegistryHandler Decorator
@@ -497,7 +494,7 @@ def process_apis(self, apis):
497494
api_dict = apis["api"]
498495
filtered_api= self.get_filtered_api(api_dict)
499496
apis["api"] = filtered_api
500-
497+
501498
def write(self, chunk):
502499
"""
503500
Overwrite the biothings query handler to ...
@@ -524,7 +521,7 @@ def write(self, chunk):
524521
self.set_header("Content-Disposition", 'attachment; filename="smartapi_metakg.graphml"')
525522

526523
return super(BaseAPIHandler, self).write(chunk)
527-
524+
528525
if self.format == "html":
529526
# setup template
530527
template_path = os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..', 'templates'))
@@ -682,75 +679,124 @@ async def get(self, *args, **kwargs):
682679
raw_query_output = self.setup_pathfinder_rawquery(expanded_fields)
683680
self.write(raw_query_output)
684681
return
685-
res = {
686-
"total": len(paths_with_edges),
682+
res = {
683+
"total": len(paths_with_edges),
687684
"paths": paths_with_edges,
688685
}
689686
await asyncio.sleep(0.01)
690687
self.finish(res)
691688

692-
class MetaKGParserHandler(BaseHandler): #RequestHandler/BaseAPIHandler
689+
class MetaKGParserHandler(BaseHandler):
693690
name="metakgparser"
694691
kwargs = {
695692
"GET": {
696693
"url": {
697694
"type": str,
698-
"required": True,
695+
"required": True,
699696
"max": 1000,
700697
"description": "URL of the SmartAPI metadata to parse"
701698
},
699+
"api_details": {"type": bool, "default": 0 },
700+
"bte": {"type": bool, "default": 0},
701+
},
702+
"POST": {
703+
"api_details": {"type": bool, "default": 0 },
704+
"bte": {"type": bool, "default": 0 },
702705
},
703-
"POST": { }
704706
}
705707

708+
def initialize(self, *args, **kwargs):
709+
super().initialize(*args, **kwargs)
710+
# change the default query pipeline from self.biothings.pipeline
711+
self.pipeline = MetaKGQueryPipeline(ns=self.biothings)
712+
713+
def get_filtered_api(self, api_dict):
714+
"""Extract and return filtered API information."""
715+
api_info = api_dict["api"]
716+
# Default structure to preserve top-level keys
717+
filtered_dict = {
718+
"subject": api_dict.get("subject"),
719+
"object": api_dict.get("object"),
720+
"predicate": api_dict.get("predicate"),
721+
"subject_prefix": api_dict.get("subject_prefix"),
722+
"object_prefix": api_dict.get("object_prefix"),
723+
}
724+
# case: bte=1, api_details=0
725+
if self.args.bte == "1" and self.args.api_details == "0":
726+
filtered_api = {
727+
**({"name": api_info["name"]} if "name" in api_info else {}),
728+
**(
729+
{"smartapi": {"id": api_info["smartapi"]["id"]}}
730+
if "smartapi" in api_info and "id" in api_info["smartapi"]
731+
else {}
732+
),
733+
"bte": api_info.get("bte", {}),
734+
}
735+
# case: bte=0, api_details=1
736+
elif self.args.bte == "0" and self.args.api_details == "1":
737+
api_info.pop("bte", None)
738+
filtered_api = api_info
739+
# case: api_details=1, bte=1
740+
elif self.args.bte == "1" and self.args.api_details == "1":
741+
filtered_api = api_info
742+
# case: bte=0, api_details=0
743+
else:
744+
filtered_api = {
745+
**({"name": api_info["name"]} if "name" in api_info else {}),
746+
**(
747+
{"smartapi": {"id": api_info["smartapi"]["id"]}}
748+
if "smartapi" in api_info and "id" in api_info["smartapi"]
749+
else {}
750+
),
751+
}
752+
# Add the filtered 'api' key to the preserved top-level structure
753+
filtered_dict["api"] = filtered_api
754+
755+
return filtered_dict
756+
757+
def process_apis(self, apis):
758+
"""Process each API dict based on provided args."""
759+
if isinstance(apis, list):
760+
for i, api_dict in enumerate(apis):
761+
filtered_api = self.get_filtered_api(api_dict)
762+
apis[i] = filtered_api
763+
elif isinstance(apis, dict):
764+
if "bte" in apis:
765+
# Update dict for new format
766+
apis["api"]["bte"] = apis.pop("bte")
767+
api_dict = apis["api"]
768+
filtered_api = self.get_filtered_api(api_dict)
769+
apis["api"] = filtered_api
770+
return apis
771+
706772
async def get(self, *args, **kwargs):
707-
if self.request.method == "GET":
708-
if not self.get_argument("url", None): # Check if the 'url' argument is present
709-
self.set_status(400)
710-
self.write({"error": "Missing 'url' argument"})
711-
return
712-
# smartapi = API(url=self.get_argument("url"))
713-
# metakg_doc = smartapi.get_metakg()
714-
# call parser // pass URL to parser
715-
parser = MetaKGParser()
716-
url = self.get_argument("url")
717-
718-
trapi_data = parser.get_TRAPI_metadatas(data=None, url=url)
719-
nontrapi_data = parser.get_non_TRAPI_metadatas(data=None, url=url)
720-
combined_data = trapi_data + nontrapi_data
773+
if not self.get_argument("url", None):
774+
self.set_status(400)
775+
self.write({"error": "Missing 'url' argument"})
776+
return
721777

722-
# Transform the combined data to include an 'api' key and organize it into 'hits'
723-
hits = []
724-
for edge in combined_data:
725-
print(f"\n{json.dumps(edge, indent=4)}\n")
726-
transformed_edge = {
727-
"_id": edge['api'].get("_id"), # Include an ID if available
728-
"_score": 1, # Placeholder for scoring logic
729-
"api": {
730-
"name": edge['api'].get("name"), # Replace with actual API name key
731-
"smartapi": {
732-
"id": edge['api']['smartapi'].get("id") # Replace with actual SmartAPI ID key
733-
}
734-
},
735-
"subject": edge.get("subject"),
736-
"subject_prefix": edge.get("subject_prefix"),
737-
"predicate": edge.get("predicate"),
738-
"object": edge.get("object"),
739-
"object_prefix": edge.get("object_prefix"),
740-
}
741-
hits.append(transformed_edge)
778+
parser = MetaKGParser()
779+
url = self.get_argument("url")
780+
self.args.api_details = self.get_argument("api_details", False)
781+
self.args.bte = self.get_argument("bte", False)
742782

743-
# Create final response format
744-
response = {
745-
"took": 1, # Placeholder for actual timing logic
746-
"total": len(hits),
747-
"max_score": 1, # Placeholder for scoring logic
748-
"hits": hits
749-
}
783+
trapi_data = parser.get_TRAPI_metadatas(data=None, url=url)
784+
nontrapi_data = parser.get_non_TRAPI_metadatas(data=None, url=url)
785+
combined_data = trapi_data + nontrapi_data
750786

751-
# Write response
752-
self.set_header("Content-Type", "application/json")
753-
self.write(json.dumps(response))
787+
for i, api_dict in enumerate(combined_data):
788+
filtered_api = self.get_filtered_api(api_dict)
789+
combined_data[i] = filtered_api
790+
791+
response = {
792+
"took": 1,
793+
"total": len(combined_data),
794+
"max_score": 1,
795+
"hits": combined_data,
796+
}
797+
798+
self.set_header("Content-Type", "application/json")
799+
self.write(json.dumps(response))
754800

755801
async def post(self, *args, **kwargs):
756802
try:
@@ -762,17 +808,21 @@ async def post(self, *args, **kwargs):
762808
trapi_data = parser.get_TRAPI_metadatas(data=data)
763809
nontrapi_data = parser.get_non_TRAPI_metadatas(data=data)
764810
combined_data = trapi_data + nontrapi_data
765-
# self.write(json.dumps(combined_data))
766-
# Clean up the metakg_doc to remove the 'api' key
767-
cleaned_metakg_doc = []
768-
for edge in combined_data:
769-
if 'api' in edge:
770-
edge.pop('api') # Remove the 'api' key
771-
cleaned_metakg_doc.append(edge)
772-
773-
# Return the cleaned metakg document
811+
812+
for i, api_dict in enumerate(combined_data):
813+
filtered_api = self.get_filtered_api(api_dict)
814+
combined_data[i] = filtered_api
815+
816+
response = {
817+
"took": 1,
818+
"total": len(combined_data),
819+
"max_score": 1,
820+
"hits": combined_data,
821+
}
822+
774823
self.set_header("Content-Type", "application/json")
775-
self.write(json.dumps(cleaned_metakg_doc)) # make dict
824+
self.write(json.dumps(response)
825+
776826
except json.JSONDecodeError:
777827
self.set_status(400)
778-
self.write({"error": "Invalid JSON format"})
828+
self.write({"error": "Invalid JSON format"})

0 commit comments

Comments
 (0)