Source code for frame_cli.metadata
"""Module for manipulating FRAME metadata files."""
import os
from git import Repo, InvalidGitRepositoryError
import requests
from typing import TYPE_CHECKING
import yaml
from .config import FRAME_METADATA_FILE_NAME, FRAME_METADATA_TEMPLATE_URL
from .logging import logger
from .update import install_api_package, CannotInstallFRAMEAPIError
if TYPE_CHECKING:
from api.models.metadata_file import MetadataFromFile
[docs]
class NotInsideGitRepositoryError(Exception):
"""Not inside a Git repository."""
[docs]
def get_model_name() -> str:
"""Return the model name (unique id) from the metadata file.
Raises:
NotInsideGitRepositoryError: If the current directory is not a Git repository.
YAMLError: If the metadata file is not a valid YAML file.
"""
metadata = get_metadata()
return metadata["hybrid_model"]["id"]
[docs]
def get_model_url() -> str | None:
"""Return the model URL from the metadata file.
Raises:
NotInsideGitRepositoryError: If the current directory is not a Git repository.
YAMLError: If the metadata file is not a valid YAML file.
"""
metadata = get_metadata()
return metadata["hybrid_model"].get("url", None)
[docs]
def show_fair_level(metadata: "MetadataFromFile") -> None:
from operator import attrgetter
from api.models.hybrid_model import HybridModel
from api.services.metadata import compute_fair_level, FAIR_LEVEL_PROPERTIES
model = HybridModel(
**metadata.hybrid_model.model_dump(),
compatible_physics_based_component_ids=[],
compatible_machine_learning_component_ids=[],
data=metadata.data,
)
fair_level = compute_fair_level(model)
max_fair_level = len(FAIR_LEVEL_PROPERTIES)
logger.info(f"FAIR level of the hybrid model: {fair_level}/{max_fair_level}")
if fair_level < max_fair_level:
logger.info(
f"To get to a FAIR level of {fair_level + 1}/{max_fair_level},"
" make sure to fill in all the following properties: "
)
for prop in FAIR_LEVEL_PROPERTIES[fair_level]:
filled = True
try:
value = attrgetter(prop)(model)
if value is None:
filled = False
if isinstance(value, list) and len(value) == 0:
filled = False
except AttributeError:
filled = False
logger.info(f"- {prop} ({'OK' if filled else 'MISSING'})")
else:
logger.info("Well done!")
[docs]
def validate() -> bool:
from pydantic import ValidationError
try:
metadata = get_metadata()
except MetadataFileNotFoundError:
logger.info("Metadata file not found. Please run `frame init` to create one.")
return False
except InvalidMetadataFileError:
logger.info("Invalid yaml file.")
return False
try:
from api.models.metadata_file import MetadataFromFile
except ImportError:
try:
install_api_package()
except CannotInstallFRAMEAPIError:
logger.info("Error installing FRAME API package. Please check your internet connection.")
return False
from api.models.metadata_file import MetadataFromFile
try:
metadata = MetadataFromFile(**metadata)
except ValidationError as e:
logger.info("Validation error in metadata file:")
for error in e.errors():
logger.info(f"- {error['loc']}: {error['msg']}")
return False
except Exception as e:
logger.info(f"Unexpected error during validation: {e}")
return False
try:
show_fair_level(metadata)
except ImportError:
logger.info("Could not compute the FAIR level of the hybrid model. Please update FRAME CLI.")
return True