diff --git a/PLATER/metadata/graph_metadata.json b/PLATER/metadata/graph_metadata.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/PLATER/metadata/graph_metadata.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/PLATER/metadata/schema.json b/PLATER/metadata/schema.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/PLATER/metadata/schema.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/PLATER/services/app_trapi.py b/PLATER/services/app_trapi.py index 2dc9071..6e7fffe 100644 --- a/PLATER/services/app_trapi.py +++ b/PLATER/services/app_trapi.py @@ -223,7 +223,33 @@ async def metadata(metadata_retriever: GraphMetadata = Depends(get_graph_metadat methods=["GET"], response_model=Any, summary="Metadata about the knowledge graph.", - description="Returns JSON with metadata about the data sources in this knowledge graph.", + description="Returns JSON with metadata about the knowledge graph.", +) + +async def graph_metadata(metadata_retriever: GraphMetadata = Depends(get_graph_metadata)) -> Any: + """Handle /metadata.""" + return metadata_retriever.get_graph_metadata() + +APP.add_api_route( + "/graph-metadata", + graph_metadata, + methods=["GET"], + response_model=Any, + summary="Metadata about the knowledge graph.", + description="Returns JSON with metadata about the knowledge graph.", +) + +async def schema(metadata_retriever: GraphMetadata = Depends(get_graph_metadata)) -> Any: + """Handle /metadata.""" + return metadata_retriever.get_schema() + +APP.add_api_route( + "/schema", + schema, + methods=["GET"], + response_model=Any, + summary="The schema of the contents of the knowledge graph.", + description="Returns a JSON schema for the knowledge graph.", ) @@ -321,7 +347,7 @@ async def one_hop_summary( ) APP.add_api_route( - "/edge_summary/{curie}", + "/edge-summary/{curie}", one_hop_summary, methods=["GET"], response_model=Dict, @@ -334,6 +360,16 @@ async def one_hop_summary( ), ) +# !!! NOTE - this is here to support backward compatibility for "/edge_summary/" +# it should be removed when all new platers are deployed and application usage switches to "/edge-summary/" +APP.add_api_route( + "/edge_summary/{curie}", + one_hop_summary, + methods=["GET"], + response_model=Dict, + include_in_schema=False, # this means it won't be shown in the openapi docs +) + async def simple_spec( source: str = None, diff --git a/PLATER/services/util/metadata.py b/PLATER/services/util/metadata.py index 3c89a86..15d9f81 100644 --- a/PLATER/services/util/metadata.py +++ b/PLATER/services/util/metadata.py @@ -22,9 +22,28 @@ class GraphMetadata: class _GraphMetadata: + METADATA_DIR = os.path.join(os.path.dirname(__file__), '..', '..', 'metadata') + + # Attempt to load a json file from the METADATA_DIR but return default as the content otherwise + @staticmethod + def _load_json(filename, default): + filepath = os.path.join(GraphMetadata._GraphMetadata.METADATA_DIR, filename) + try: + with open(filepath) as f: + data = json.load(f) + if data: + return data + except (FileNotFoundError, json.JSONDecodeError) as e: + logger.warning(f'Could not load {filename}: {e}, using default') + return default + def __init__(self): self.metadata = None self._retrieve_metadata() + self.graph_metadata = None + self._retrieve_graph_metadata() + self.schema = None + self._retrieve_schema() self.meta_kg = None self.meta_kg_response = None self.predicates_in_graph = set() @@ -39,12 +58,19 @@ def get_metadata(self): return self.metadata def _retrieve_metadata(self): - with open(os.path.join(os.path.dirname(__file__), '..', '..', 'metadata', 'metadata.json')) as f: - self.metadata = json.load(f) + self.metadata = self._load_json('metadata.json', {}) + + def get_graph_metadata(self): + return self.graph_metadata + + def _retrieve_graph_metadata(self): + self.graph_metadata = self._load_json('graph_metadata.json', {}) + + def get_schema(self): + return self.schema - if not self.metadata: - with open(os.path.join(os.path.dirname(__file__), '..', '..', 'metadata', 'about.json')) as f: - self.metadata = json.load(f) + def _retrieve_schema(self): + self.schema = self._load_json('schema.json', {}) def get_meta_kg(self): return self.meta_kg @@ -53,31 +79,33 @@ def get_meta_kg_response(self): return self.meta_kg_response def _retrieve_meta_kg(self): - with open(os.path.join(os.path.dirname(__file__), '..', '..', 'metadata', 'meta_knowledge_graph.json')) as f: - self.meta_kg = json.load(f) - try: - # validate the meta kg with the pydantic model - MetaKnowledgeGraph.parse_obj(self.meta_kg) - logger.info('Successfully validated meta kg') + self.meta_kg = self._load_json('meta_knowledge_graph.json', {"nodes": {}, "edges": []}) + try: + # validate the meta kg with the pydantic model + MetaKnowledgeGraph.parse_obj(self.meta_kg) + logger.info('Successfully validated meta kg') - self.node_categories_in_graph = set(self.meta_kg['nodes'].keys()) - logger.info(f'Used meta kg to determine node categories in graph: {self.node_categories_in_graph}') + self.node_categories_in_graph = set(self.meta_kg['nodes'].keys()) + logger.info(f'Used meta kg to determine node categories in graph: {self.node_categories_in_graph}') - for edge in self.meta_kg['edges']: - self.predicates_in_graph.add(edge['predicate']) - logger.info(f'Used meta kg to determine predicates in graph: {self.predicates_in_graph}') + for edge in self.meta_kg['edges']: + self.predicates_in_graph.add(edge['predicate']) + logger.info(f'Used meta kg to determine predicates in graph: {self.predicates_in_graph}') - # create an already-encoded object that is ready to be returned quickly - self.meta_kg_response = jsonable_encoder(self.meta_kg) - except ValidationError as e: - logger.error(f'Error validating meta kg: {e}') + # create an already-encoded object that is ready to be returned quickly + self.meta_kg_response = jsonable_encoder(self.meta_kg) + except ValidationError as e: + logger.error(f'Error validating meta kg: {e}') def get_sri_testing_data(self): return self.sri_testing_data def _retrieve_sri_test_data(self): - with open(os.path.join(os.path.dirname(__file__), '..', '..', 'metadata', 'sri_testing_data.json')) as f: - self.sri_testing_data = json.load(f) + self.sri_testing_data = self._load_json('sri_testing_data.json', { + "version": "", + "source_type": "primary", + "edges": [], + }) # version is technically not part of the spec anymore # but this ensures validation with the model until it's removed diff --git a/PLATER/setup.py b/PLATER/setup.py index 4ad501e..f0b515f 100644 --- a/PLATER/setup.py +++ b/PLATER/setup.py @@ -3,6 +3,6 @@ setup( name='PLATER', - version='v2.1.4', + version='v2.3.1', packages=find_packages(), )