Source code for linkml.generators.lpgen

import os
from typing import Union, TextIO

import click
from prologterms import Term, TermGenerator, PrologRenderer, SExpressionRenderer

from linkml_runtime.linkml_model.meta import SchemaDefinition, ClassDefinition, SlotDefinition
from linkml_runtime.utils.formatutils import camelcase, underscore
from linkml.utils.generator import Generator, shared_arguments


[docs]class LogicProgramGenerator(Generator): generatorname = os.path.basename(__file__) generatorversion = "0.0.2" valid_formats = ['lp', 'sexpr'] visit_all_class_slots = True def __init__(self, schema: Union[str, TextIO, SchemaDefinition], **kwargs) -> None: super().__init__(schema, **kwargs) self.P = TermGenerator() self.R = PrologRenderer() if self.format == 'lp' else SExpressionRenderer()
[docs] def visit_class(self, cls: ClassDefinition) -> bool: cn = underscore(cls.name) self.emit('class', cn) for p in cls.mixins: self.emit('mixin', cn, underscore(p)) if cls.is_a: is_a = underscore(cls.is_a) self.emit('is_a', cn, is_a) if cls.defining_slots: self.emit('defining_slots', is_a, [underscore(s) for s in cls.defining_slots]) uri = f'http://w3id.org/biolink/vocab/{camelcase(cls.name)}' self.emit('has_uri', cn, uri) return True
[docs] def visit_slot(self, slot_name: str, slot: SlotDefinition) -> None: """ Add a slot definition per slot @param slot_name: @param slot: @return: """ sn = underscore(slot_name) self.emit('slot', sn) if slot.domain: self.emit('domain', sn, underscore(slot.domain)) if slot.range: self.emit('range', sn, underscore(slot.range)) for p in slot.mixins: self.emit('mixin', sn, underscore(p)) if slot.is_a: is_a = underscore(slot.is_a) #uri = self.owlgen._prop_uri(slot.name) uri = f'http://w3id.org/biolink/vocab/{sn}' self.emit('has_uri', sn, uri) if slot.multivalued: self.emit('multivalued', sn) if slot.required: self.emit('required', sn)
[docs] def visit_class_slot(self, cls: ClassDefinition, aliased_slot_name: str, slot: SlotDefinition) -> None: sn = underscore(aliased_slot_name) cn = underscore(cls.name) self.emit('class_slot', cn, sn) self.emit('required', sn) self.emit('slotrange', underscore(slot.range)) if slot.range in self.schema.classes or slot.range in self.schema.types or slot.range in self.schema.enums else "String" if slot.multivalued: self.emit('multivalued_in', sn, cn) if slot.required: self.emit('required_in', sn, cn) if slot.range: self.emit('range_in', sn, underscore(slot.range), cn)
[docs] def emit(self, p, *args): t = Term(p, *args) print(f'{self.R.render(t)}.')
@shared_arguments(LogicProgramGenerator) @click.command() def cli(yamlfile, **args): """ Generate logic program representation of a LinkML model """ print(LogicProgramGenerator(yamlfile, **args).serialize(**args)) if __name__ == "__main__": cli()