Skip to content

Commit

Permalink
Add custom template loader (#388)
Browse files Browse the repository at this point in the history
Template schemas may now be passed to the `--template` option; pass the
path to the YAML file. The schema may still include imports, like the
`ontogpt` `core` schema, as long as they are present in the `templates`
directory already (or are part of the standard `ontogpt` installation).
  • Loading branch information
caufieldjh committed May 29, 2024
2 parents 4b42a58 + 0da2de7 commit 8d189d1
Showing 1 changed file with 41 additions and 8 deletions.
49 changes: 41 additions & 8 deletions src/ontogpt/io/template_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import logging
from pathlib import Path

from linkml.generators.pydanticgen import PydanticGenerator
from linkml_runtime import SchemaView
from linkml_runtime.linkml_model import ClassDefinition

Expand All @@ -17,24 +18,56 @@ def get_template_details(template: TEMPLATE_NAME) -> ClassDefinition:
"""
Get the LinkML class, module, and schemaview for a template.
This may be a template already known to ontogpt or the path
to a custom template. It is assumed to be the latter if the
template input is a path to a YAML file.
:param template: template name of the form module.ClassName
:return: tuple of (LinkML class definition, module, specific
Python class, schemaview)
"""
logger.info(f"Loading schema for {template}")
if "." in template:
module_name, class_name = template.split(".", 1)
else:
module_name = template
# Check if template is a path to a YAML file
# If so, this is a custom schema and needs python classes
if template.endswith(".yaml"):
logger.info(f"Loading custom schema from {template}")
path_to_template = Path(template)

# Check if file exists first
if not path_to_template.exists():
raise FileNotFoundError(f"Template file not found at {template}")

# Copy the schema to the templates directory
# So it will have access to imports like the core schema
templates_path = this_path.parent / "templates"
new_path_to_template = templates_path / path_to_template.name
new_path_to_template.write_text(path_to_template.read_text())
module_name = new_path_to_template.stem
path_to_module = new_path_to_template.with_suffix(".py")

sv = SchemaView(new_path_to_template)

gen = PydanticGenerator(str(new_path_to_template), pydantic_version=2)
path_to_module.write_text(gen.serialize())

mod = importlib.import_module(f"ontogpt.templates.{module_name}")
class_name = None
path_to_template = get_template_path(module_name)
sv = SchemaView(path_to_template)

else:
logger.info(f"Loading schema for {template}")
if "." in template:
module_name, class_name = template.split(".", 1)
else:
module_name = template
class_name = None
path_to_template = get_template_path(module_name)
sv = SchemaView(path_to_template)
mod = importlib.import_module(f"ontogpt.templates.{module_name}")

if class_name is None:
roots = [c.name for c in sv.all_classes().values() if c.tree_root]
if len(roots) != 1:
raise ValueError(f"Template {template} does not have singular root: {roots}")
class_name = roots[0]
mod = importlib.import_module(f"ontogpt.templates.{module_name}")

pyclass = mod.__dict__[class_name]

logger.info(f"Getting class for template {template}")
Expand Down

0 comments on commit 8d189d1

Please sign in to comment.