11import asyncio
22import json
33import logging
4- from typing import List , Union
54import os
65import bmt
76from biothings .utils import serializer
2625
2726logger = logging .getLogger ("smartAPI" )
2827
29- from tornado .web import RequestHandler
30-
3128def 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