from dotenv import load_dotenv, find_dotenv load_dotenv(find_dotenv()) import os import modules.logger_tool as logger log_name = 'api_modules_database_tools_neontology_tools' log_dir = os.getenv("LOG_PATH", "/logs") # Default path as fallback logging = logger.get_logger( name=log_name, log_level=os.getenv("LOG_LEVEL", "DEBUG"), log_path=log_dir, log_file=log_name, runtime=True, log_format='default' ) from modules.database.tools.neontology.graphconnection import init_neontology, close_neontology from modules.database.tools.neontology.basenode import BaseNode from modules.database.tools.neontology.baserelationship import BaseRelationship from pydantic import ValidationError import os import neo4j # Initialize Neontology with the Neo4j database details def init_neontology_connection(uri=None, user=None, password=None): uri = uri or os.getenv("APP_BOLT_URL") user = user or os.getenv("USER_NEO4J") # Add default value password = password or os.getenv("PASSWORD_NEO4J") if not all([uri, user, password]): raise ValueError("Missing required Neo4j connection parameters") try: logging.info(f"Initializing Neontology with URI: {uri}") init_neontology( neo4j_uri=uri, neo4j_username=user, neo4j_password=password ) logging.info(f"Neontology connection initialized with URI: {uri}, user: {user}") except Exception as e: raise ValueError(f"Failed to initialize Neontology connection: {str(e)}") def close_neontology_connection(): logging.debug(f"Attempting to terminate Neontology connection") close_neontology() logging.info(f"Neontology connection terminated") # Terminates the Neo4j connection def close_neo4j_connection(): logging.debug(f"Attempting to terminate Neo4j connection") neo4j.close() logging.info(f"Neo4j connection terminated") # Create a Neontology node in the Neo4j database def create_or_merge_neontology_node(node: BaseNode, database: str = 'neo4j', operation: str = "merge"): """ Create or merge a Neontology node in the Neo4j database. Args: node (BaseNode): A Neontology node object. operation (str): The operation to perform ('create' or 'merge'). Defaults to 'merge'. """ try: logging.debug(f"Creating/merging node: {node.__class__.__name__} with label '{node.__primarylabel__}' in database '{database}'") logging.debug(f"Node data: {node.to_dict()}") if operation == "create": result = node.create(database=database) logging.debug(f"Create result: {result}") elif operation == "merge": result = node.merge(database=database) logging.debug(f"Merge result: {result}") else: logging.error(f"Invalid operation: {operation}") except Exception as e: logging.error(f"Error in processing node: {e}") raise # Re-raise to see the actual error # Create or merge a Neontology node in the Neo4j database. If a ValidationError occurs # due to a NaN value, replace it with a default value and retry. def create_or_merge_neontology_node_with_default(driver, node: BaseNode, database: str = 'neo4j', operation: str = "merge", default_values: dict = {}): """ Create or merge a Neontology node in the Neo4j database. If a ValidationError occurs due to a NaN value, replace it with a default value and retry. Args: node (BaseNode): A Neontology node object. operation (str): The operation to perform ('create' or 'merge'). Defaults to 'merge'. default_values (dict): A dictionary of default values for fields that might contain NaN. """ try: # Attempt to create or merge the node if operation == "create": node.create(database=database) else: # "merge" by default node.merge(database=database) except ValidationError as e: # Handle ValidationError due to NaN value for field, error in e.errors(): if field in default_values and 'type' in error and error['type'] == 'value_error.nan': setattr(node, field, default_values[field]) logging.warning(f"Warning: Replacing NaN in {field} with default value '{default_values[field]}' and retrying.") create_or_merge_neontology_node_with_default(driver, node, database, operation, default_values) break else: # If the error is not due to a NaN value or field not in default_values, re-raise the error logging.error(f"Error in processing node: {e}") raise except Exception as e: logging.error(f"Error in processing node: {e}") def create_or_merge_neontology_relationship(relationship: BaseRelationship, database: str = 'neo4j', operation: str = "merge"): """ Create or merge a Neontology relationship in the Neo4j database. Args: relationship (BaseRelationship): A Neontology relationship object. operation (str): The operation to perform ('create' or 'merge'). Defaults to 'merge'. """ try: if operation == "create": relationship.create(database=database) elif operation == "merge": relationship.merge(database=database) else: logging.error(f"Invalid operation: {operation}") except Exception as e: logging.error(f"Error in processing relationship: {e}")