def test_formats(self): self.assertEqual("ThisIsIt", camelcase("this is it")) self.assertEqual("ThisIsIT", camelcase(" this is iT ")) self.assertEqual("IBeY", camelcase("i be y ")) self.assertEqual("ThisIsIt", camelcase("This__is_it")) self.assertEqual("this_is_it", underscore(" this is it ")) self.assertEqual("this_is_it", underscore("this is it")) self.assertEqual("thisIsIt", lcamelcase(" this is\t it\n")) self.assertEqual('abc', be(' abc\n')) self.assertEqual('', be(None)) self.assertEqual('', be(' '))
def visit_class_slot(self, cls: ClassDefinition, aliased_slot_name: str, slot: SlotDefinition) -> None: with open(self.dir_path(slot), 'w') as slotfile: with redirect_stdout(slotfile): self.frontmatter(f"Slot: {aliased_slot_name}") self.para(be(slot.description)) slot_curi = self.namespaces.uri_or_curie_for(self.namespaces._base, underscore(slot.name)) slot_uri = self.namespaces.uri_for(slot_curi) print(f'URI: [{slot_curi}]({slot_uri})') self.mappings(slot) self.header(2, 'Domain and Range') print(f'{self.class_link(slot.domain)} ->{self.predicate_cardinality(slot)} ' f'{self.class_type_link(slot.range)}') self.header(2, 'Inheritance') if slot.is_a: self.bullet(f' is_a: {self.slot_link(slot.is_a)}') self.header(2, 'Children') if slot.name in sorted(self.synopsis.isarefs): for child in sorted(self.synopsis.isarefs[slot.name].slotrefs): self.bullet(f' {self.slot_link(child)}') self.header(2, 'Used by') if slot.name in sorted(self.synopsis.slotrefs): for rc in sorted(self.synopsis.slotrefs[slot.name].classrefs): self.bullet(f'{self.class_link(rc)}') if aliased_slot_name == 'relation': if slot.subproperty_of: self.bullet(f' reifies: {self.slot_link(slot.subproperty_of)}')
def element_header(self, obj: Element, name: str, curie: str, uri: str) -> None: self.frontmatter(f"Type: {obj.name}" + (f" _(deprecated)_" if obj.deprecated else "")) self.para(be(obj.description)) print(f'URI: [{curie}]({uri})') print()
def _link(self, obj: Optional[Element], *, after_link: str = None, use_desc: bool = False, add_subset: bool = True) -> str: """ Create a link to ref if appropriate. @param ref: the name or value of a class, slot, type or the name of a built in type. @param after_link: Text to put between link and description @param use_desc: True means append a description after the link if available @param add_subset: True means add any subset information that is available @return: """ nl = '\n' if obj is None or not self.is_secondary_ref(obj.name): return self.bbin(obj) if isinstance(obj, SlotDefinition): link_name = ((be(obj.domain) + '➞') if obj.alias else '') + self.aliased_slot_name(obj) link_ref = underscore(obj.name) elif isinstance(obj, TypeDefinition): link_name = camelcase(obj.name) link_ref = f"types/{link_name}" elif isinstance(obj, ClassDefinition): link_name = camelcase(obj.name) link_ref = camelcase(link_name) else: link_name = obj.name link_ref = link_name desc = self.desc_for(obj, use_desc) return f'[{link_name}]' \ f'({link_ref}.{self.format})' + \ (f' {after_link} ' if after_link else '') + (f' - {desc.split(nl)[0]}' if desc else '')
def visit_class(self, cls: ClassDefinition) -> bool: if cls.abstract: return False self.clsobj = JsonObj(title=camelcase(cls.name), type='object', properties=JsonObj(), description=be(cls.description)) return True
def gen_schema(self) -> str: split_descripton = '\n# '.join(split_line(be(self.schema.description), split_len=100)) head = f'''# Auto generated from {self.schema.source_file} by {self.generatorname} version: {self.generatorversion} # Generation date: {self.schema.generation_date} # Schema: {self.schema.name} #''' if self.schema.generation_date else '' return f'''{head}
def visit_class(self, cls: ClassDefinition) -> bool: # TODO: find out what to do with mappings if not self.closure or cls.name in self.closure: self.writer.writerow({'id': underscore(cls.name), # 'mappings': "|".join(cls.mappings), 'mappings': '', 'description': be(cls.description)}) return True return False
def visit_class(self, cls: ClassDefinition) -> bool: if self.gen_classes and cls.name not in self.gen_classes: return False with open(self.dir_path(cls), 'w') as clsfile: with redirect_stdout(clsfile): self.frontmatter(f"Class: {cls.name}") self.para(be(cls.description)) class_curi = self.namespaces.uri_or_curie_for(self.namespaces._base, camelcase(cls.name)) class_uri = self.namespaces.uri_for(class_curi) print(f'URI: [{class_curi}]({class_uri})') print() if self.image_directory: yg = YumlGenerator(self) yg.serialize(classes=[cls.name], directory=self.image_directory, load_image=not self.noimages) img_url = os.path.join('images', os.path.basename(yg.output_file_name)) else: yg = YumlGenerator(self) img_url = yg.serialize(classes=[cls.name])\ .replace('[', '\\[').replace('?', '%3F').replace(' ', '%20') print(f'![img]({img_url})') self.mappings(cls) self.header(2, 'Inheritance') if cls.is_a is not None: self.bullet(f' is_a: {self.class_link(cls.is_a, use_desc=True)}') for mixin in cls.mixins: self.bullet(f' mixin: {self.class_link(mixin, use_desc=True)}') self.header(2, 'Children') if cls.name in self.synopsis.isarefs: for child in sorted(self.synopsis.isarefs[cls.name].classrefs): self.bullet(f'{self.class_link(child, use_desc=True)}') if cls.name in self.synopsis.mixinrefs: for mixin in sorted(self.synopsis.mixinrefs[cls.name].classrefs): self.bullet(f'{self.class_link(mixin, use_desc=True, after_link="(mixin)")}') if cls.name in self.synopsis.classrefs: self.header(2, 'Used by') for sn in sorted(self.synopsis.classrefs[cls.name].slotrefs): slot = self.schema.slots[sn] if slot.range == cls.name: self.bullet(f' **{self.class_link(slot.domain)}** ' f'*{self.slot_link(slot, add_subset=False)}*{self.predicate_cardinality(slot)} ' f'**{self.class_type_link(slot.range)}**') self.header(2, 'Fields') for sn in sorted(cls.slots): self.slot_field(cls, self.schema.slots[sn]) for slot in sorted(self.all_slots(cls), key=lambda s: s.name): if slot.name not in cls.slots: self.slot_field(cls, slot) return True
def visit_schema(self, directory: str = None, classes: Set[ClassDefinitionName] = None, image_dir: bool = False, noimages: bool = False, **_) -> None: self.gen_classes = classes if classes else [] for cls in self.gen_classes: if cls not in self.schema.classes: raise ValueError("Unknown class name: {cls}") if self.gen_classes: self.gen_classes_neighborhood = self.neighborhood(list(self.gen_classes)) self.directory = directory if directory: os.makedirs(directory, exist_ok=True) elif image_dir: raise ValueError(f"Image directory can only be used with '-d' option") if image_dir: self.image_directory = os.path.join(directory, 'images') if not noimages: os.makedirs(self.image_directory, exist_ok=True) self.noimages = noimages self.types_directory = os.path.join(directory, 'types') os.makedirs(self.types_directory, exist_ok=True) with open(os.path.join(directory, 'index.md'), 'w') as ixfile: with redirect_stdout(ixfile): self.frontmatter(f"{self.schema.name.title()} schema") self.para(be(self.schema.description)) self.header(3, 'Classes') for cls in sorted(self.schema.classes.values(), key=lambda c: c.name): if not cls.is_a and not cls.mixin and self.is_secondary_ref(cls.name): self.class_hier(cls) self.header(3, 'Mixins') for cls in sorted(self.schema.classes.values(), key=lambda c: c.name): if cls.mixin and self.is_secondary_ref(cls.name): self.class_hier(cls) self.header(3, 'Slots') for slot in sorted(self.schema.slots.values(), key=lambda s: s.name): if not slot.is_a and self.is_secondary_ref(slot.name): self.pred_hier(slot) self.header(3, 'Types') self.header(4, 'Built in') for builtin_name in sorted(self.synopsis.typebases.keys()): self.bullet(f'**{builtin_name}**') self.header(4, 'Defined') for typ in sorted(self.schema.types.values(), key=lambda t: t.name): if self.is_secondary_ref(typ.name): if typ.typeof: typ_typ = self.type_link(typ.typeof) else: typ_typ = f'**{typ.base}**' self.bullet(self.type_link(typ, after_link=f' ({typ_typ})', use_desc=True))
def gen_schema(self) -> str: # The metamodel uses Enumerations to define itself, so don't import if we are generating the metamodel enumimports = '' if self.genmeta else \ 'from biolinkml.meta import EnumDefinition, PermissibleValue, PvFormulaOptions\n' handlerimport = 'from biolinkml.utils.enumerations import EnumDefinitionImpl' split_descripton = '\n# '.join(split_line(be(self.schema.description), split_len=100)) head = f'''# Auto generated from {self.schema.source_file} by {self.generatorname} version: {self.generatorversion} # Generation date: {self.schema.generation_date} # Schema: {self.schema.name} #''' if self.schema.generation_date else '' return f'''{head}
def element_header(self, obj: Element, name: str, curie: str, uri: str) -> None: if curie.startswith('http'): simple_name = curie else: simple_name = curie.split(':', 1)[1] self.header( 1, f"Type: {simple_name}" + (f" _(deprecated)_" if obj.deprecated else "")) self.para(be(obj.description)) print(f'URI: [{curie}]({uri})') print()
def gen_classdef(self, cls: ClassDefinition) -> str: """ Generate python definition for class cls """ parentref = f'({self.formatted_element_name(cls.is_a, True) if cls.is_a else "YAMLRoot"})' inheritedslots = self.gen_inherited_slots(cls) slotdefs = self.gen_class_variables(cls) postinits = self.gen_postinits(cls) if not slotdefs: slotdefs = 'pass' wrapped_description = f''' """ {wrapped_annotation(be(cls.description))} """''' if be(cls.description) else '' return f'''
def element_header(self, obj: Element, name: str, curie: str, uri: str) -> None: simple_name = curie.split(':', 1)[1] if isinstance(obj, TypeDefinition): obj_type = 'Type' elif isinstance(obj, ClassDefinition): obj_type = 'Class' elif isinstance(obj, SlotDefinition): obj_type = 'Slot' else: obj_type = 'Class' self.header(1, f"{obj_type}: {simple_name}" + (f" _(deprecated)_" if obj.deprecated else "")) self.para(be(obj.description)) print(f'URI: [{curie}]({uri})') print()
def visit_class_slot(self, cls: ClassDefinition, aliased_slot_name: str, slot: SlotDefinition) -> None: with open(self.dir_path(slot), 'w') as slotfile: with redirect_stdout(slotfile): slot_curie = self.namespaces.uri_or_curie_for( self.namespaces._base, underscore(slot.name)) slot_uri = self.namespaces.uri_for(slot_curie) self.frontmatter( **{ 'parent': 'Slots', 'title': slot_curie, 'grand_parent': self.doc_root_title, 'layout': 'default' }) simple_name = slot_curie.split(':', 1)[1] self.header( 1, f"Type: {simple_name}" + (f" _(deprecated)_" if slot.deprecated else "")) for s in slot.in_subset: self.badges(s, f'{s}-subset-label') self.para(be(slot.description)) print(f'URI: [{slot_curie}]({slot_uri})') self.header(2, 'Domain and Range') print( f'{self.class_link(slot.domain)} ->{self.predicate_cardinality(slot)} ' f'{self.class_type_link(slot.range)}') self.header(2, 'Parents') if slot.is_a: self.bullet(f' is_a: {self.slot_link(slot.is_a)}') self.header(2, 'Children') if slot.name in sorted(self.synopsis.isarefs): for child in sorted( self.synopsis.isarefs[slot.name].slotrefs): self.bullet(f' {self.slot_link(child)}') self.header(2, 'Used by') if slot.name in sorted(self.synopsis.slotrefs): for rc in sorted( self.synopsis.slotrefs[slot.name].classrefs): self.bullet(f'{self.class_link(rc)}') if aliased_slot_name == 'relation': if slot.subproperty_of: self.bullet( f' reifies: {self.slot_link(slot.subproperty_of)}') self.element_properties(slot)
def element_header(self, obj: Element, name: str, curie: str, uri: str) -> None: """ Write the header for an element. Parameters ---------- obj: biolinkml.meta.Element An element name: str The name of the element curie: str The CURIE of the element uri: str The URI of the element """ if curie.startswith('http'): if curie.startswith( 'https://w3id.org/biolink/vocab/biolinkml:types/'): simple_name = curie.split('/')[-1] uri = f"https://biolink.github.io/biolinkml/docs/types/{simple_name}" simple_name = f"metatype:{simple_name}" else: simple_name = curie else: simple_name = curie.split(':', 1)[1] if isinstance(obj, TypeDefinition): obj_type = 'Type' elif isinstance(obj, ClassDefinition): obj_type = 'Class' elif isinstance(obj, SlotDefinition): obj_type = 'Slot' else: obj_type = 'Class' self.header( 1, f"{obj_type}: {simple_name}" + (f" _(deprecated)_" if obj.deprecated else "")) self.para(be(obj.description)) print(f'URI: [{curie}]({uri})') print()
def visit_slot(self, aliased_slot_name: str, slot: SlotDefinition) -> None: """ Visit a given slot definition and write the following properties in Markdown, - Frontmatter - Mappings - Description - Domain and Range constraints - Parents - Children - Used by Parameters ---------- cls: biolinkml.meta.SlotDefinition A SlotDefinition """ if not slot.alias: with open(self.dir_path(slot), 'w') as slotfile: with redirect_stdout(slotfile): slot_curie = self.namespaces.uri_or_curie_for( self.namespaces._base, underscore(slot.name)) slot_uri = self.namespaces.uri_for(slot_curie) ancs = self.ancestors(slot) if 'related to' in ancs: if slot.mixin: parent = 'Slot Mixins' else: parent = 'Predicates' grand_parent = 'Slots' slot_type = 'Relation' elif 'node property' in ancs: if slot.mixin: parent = 'Slot Mixins' else: parent = 'Node Properties' grand_parent = 'Slots' slot_type = 'Slot' elif 'association slot' in ancs: if slot.mixin: parent = 'Slot Mixins' else: parent = 'Edge Properties' grand_parent = 'Slots' slot_type = 'Slot' else: if slot.mixin: parent = 'Slot Mixins' else: parent = 'Other Slots' grand_parent = 'Slots' slot_type = 'Slot' self.frontmatter( **{ 'parent': parent, 'title': slot_curie, 'grand_parent': grand_parent, 'layout': 'default' }) simple_name = slot_curie.split(':', 1)[1] self.header( 1, f"{slot_type}: {simple_name}" + (f" _(deprecated)_" if slot.deprecated else "")) for s in slot.in_subset: self.badges(s, f'{s}-subset-label') self.para(be(slot.description)) print(f'URI: [{slot_curie}]({slot_uri})') self.header(2, 'Domain and Range') print( f'{self.class_link(slot.domain)} ->{self.predicate_cardinality(slot)} ' f'{self.class_type_link(slot.range)}') self.header(2, 'Parents') if slot.is_a: self.bullet(f' is_a: {self.slot_link(slot.is_a)}') self.header(2, 'Children') if slot.name in sorted(self.synopsis.isarefs): for child in sorted( self.synopsis.isarefs[slot.name].slotrefs): child_slot = self.schema.slots[child] if not child_slot.alias: self.bullet(f' {self.slot_link(child)}') self.header(2, 'Used by') if slot.name in sorted(self.synopsis.slotrefs): for rc in sorted( self.synopsis.slotrefs[slot.name].classrefs): self.bullet(f'{self.class_link(rc)}') if aliased_slot_name == 'relation': if slot.subproperty_of: self.bullet( f' reifies: {self.slot_link(slot.subproperty_of) if slot.subproperty_of in self.schema.slots else slot.subproperty_of}' ) self.element_properties(slot)
def gen_enum_comment(self, enum: EnumDefinition) -> str: return f'"""\n\t{wrapped_annotation(be(enum.description))}\n\t"""' if be( enum.description) else ''
def visit_schema(self, directory: str = None, classes: Set[ClassDefinitionName] = None, image_dir: bool = False, noimages: bool = False, **_) -> None: self.gen_classes = classes if classes else [] for cls in self.gen_classes: if cls not in self.schema.classes: raise ValueError("Unknown class name: {cls}") if self.gen_classes: self.gen_classes_neighborhood = self.neighborhood( list(self.gen_classes)) self.directory = directory if directory: os.makedirs(directory, exist_ok=True) elif image_dir: raise ValueError( f"Image directory can only be used with '-d' option") if image_dir: self.image_directory = os.path.join(directory, 'images') if not noimages: os.makedirs(self.image_directory, exist_ok=True) self.noimages = noimages self.types_directory = os.path.join(directory, 'types') os.makedirs(self.types_directory, exist_ok=True) self.doc_root_title = f'Browse {self.schema.name.title().replace("-", " ")}' with open(os.path.join(directory, 'index.md'), 'w') as ixfile: with redirect_stdout(ixfile): self.frontmatter( **{ 'title': self.doc_root_title, 'has_children': 'true', 'nav_order': 2, 'layout': 'default' }) self.para(be(self.schema.description)) self.header(3, 'Classes') with open(os.path.join(directory, 'Classes.md'), 'w') as file: file.write( f'---\nparent: {self.doc_root_title}\ntitle: Classes\nhas_children: true\nnav_order: 1\nlayout: default\n---' ) self.header(3, 'Entities') with open(os.path.join(directory, 'Entities.md'), 'w') as file: file.write( f'---\nparent: Classes\ntitle: Entities\nhas_children: true\nnav_order: 1\nlayout: default\n---' ) for cls in sorted(self.schema.classes.values(), key=lambda c: c.name): ancs = self.ancestors(cls) if 'named thing' in ancs: if not cls.is_a and not cls.mixin and self.is_secondary_ref( cls.name): self.class_hier(cls) self.header(3, 'Associations') with open(os.path.join(directory, 'Associations.md'), 'w') as file: file.write( f'---\nparent: Classes\ntitle: Associations\nhas_children: true\nnav_order: 2\nlayout: default\n---' ) for cls in sorted(self.schema.classes.values(), key=lambda c: c.name): ancs = self.ancestors(cls) if 'association' in ancs: if not cls.is_a and not cls.mixin and self.is_secondary_ref( cls.name): self.class_hier(cls) self.header(3, 'Mixins') with open(os.path.join(directory, 'Mixins.md'), 'w') as file: file.write( f'---\nparent: {self.doc_root_title}\ntitle: Mixins\nhas_children: true\nnav_order: 2\nlayout: default\n---' ) for cls in sorted(self.schema.classes.values(), key=lambda c: c.name): if cls.mixin and self.is_secondary_ref(cls.name): self.class_hier(cls) self.header(3, 'Relations') with open(os.path.join(directory, 'Relations.md'), 'w') as file: file.write( f'---\nparent: {self.doc_root_title}\ntitle: Relations\nhas_children: true\nnav_order: 3\nlayout: default\n---' ) for slot in sorted(self.schema.slots.values(), key=lambda c: c.name): if 'related to' in self.ancestors(slot): self.pred_hier(slot) self.header(3, 'Slots') with open(os.path.join(directory, 'Slots.md'), 'w') as file: file.write( f'---\nparent: {self.doc_root_title}\ntitle: Slots\nhas_children: true\nnav_order: 4\nlayout: default\n---' ) self.header(4, 'Node Properties') with open(os.path.join(directory, 'NodeProperties.md'), 'w') as file: file.write( f'---\nparent: Slots\ntitle: Node Properties\nhas_children: true\nnav_order: 1\nlayout: default\n---' ) for slot in sorted(self.schema.slots.values(), key=lambda s: s.name): ancs = self.ancestors(slot) if 'related to' not in ancs: if 'node property' in ancs: self.pred_hier(slot) self.header(4, 'Edge Properties') with open(os.path.join(directory, 'EdgeProperties.md'), 'w') as file: file.write( f'---\nparent: Slots\ntitle: Edge Properties\nhas_children: true\nnav_order: 2\nlayout: default\n---' ) for slot in sorted(self.schema.slots.values(), key=lambda s: s.name): ancs = self.ancestors(slot) if 'related to' not in ancs: if 'association slot' in ancs: self.pred_hier(slot) self.header(3, 'Types') with open(os.path.join(directory, 'Types.md'), 'w') as file: file.write( f'---\nparent: {self.doc_root_title}\ntitle: Types\nhas_children: true\nnav_order: 7\nlayout: default\n---' ) self.header(4, 'Built in') for builtin_name in sorted(self.synopsis.typebases.keys()): self.bullet(f'**{builtin_name}**') self.header(4, 'Defined') for typ in sorted(self.schema.types.values(), key=lambda t: t.name): if self.is_secondary_ref(typ.name): if typ.typeof: typ_typ = self.type_link(typ.typeof) else: typ_typ = f'**{typ.base}**' self.bullet( self.type_link(typ, after_link=f' ({typ_typ})', use_desc=True))
def visit_schema(self, directory: str = None, classes: Set[ClassDefinitionName] = None, image_dir: bool = False, noimages: bool = False, **_) -> None: """ Visit the schema and generate Markdown for each ClassDefinition, SlotDefinition, and TypeDefinition. Parameters ---------- directory: str The directory to write to classes: Set[ClassDefinitionName] A set of classes to subset image_dir: str The directory to write static images noimages: bool Whether or not to generate static images """ self.gen_classes = classes if classes else [] for cls in self.gen_classes: if cls not in self.schema.classes: raise ValueError("Unknown class name: {cls}") if self.gen_classes: self.gen_classes_neighborhood = self.neighborhood( list(self.gen_classes)) self.directory = directory if directory: os.makedirs(directory, exist_ok=True) elif image_dir: raise ValueError( f"Image directory can only be used with '-d' option") if image_dir: self.image_directory = os.path.join(directory, 'images') if not noimages: os.makedirs(self.image_directory, exist_ok=True) self.noimages = noimages self.types_directory = os.path.join(directory, 'types') os.makedirs(self.types_directory, exist_ok=True) self.doc_root_title = f'Browse {self.schema.name.title().replace("-", " ")}' self.seen_elements = set() with open(os.path.join(directory, 'index.md'), 'w') as ixfile: # Create the data model index with redirect_stdout(ixfile): self.frontmatter( **{ 'title': self.doc_root_title, 'has_children': 'true', 'nav_order': 2, 'layout': 'default', 'has_toc': 'false' }) self.para(be(self.schema.description)) self.header(2, 'Classes') self.header(3, 'Entities') for cls in sorted(self.schema.classes.values(), key=lambda c: c.name): ancs = self.ancestors(cls) if 'named thing' in ancs: if not cls.is_a and not cls.mixin and self.is_secondary_ref( cls.name): self.seen_elements.add(cls.name) self.class_hier(cls) self.header(3, 'Associations') for cls in sorted(self.schema.classes.values(), key=lambda c: c.name): ancs = self.ancestors(cls) if 'association' in ancs: if not cls.is_a and not cls.mixin and self.is_secondary_ref( cls.name): self.seen_elements.add(cls.name) self.class_hier(cls) self.header(3, 'Class Mixins') for cls in sorted(self.schema.classes.values(), key=lambda c: c.name): if cls.mixin and self.is_secondary_ref(cls.name): if cls.name not in self.seen_elements: self.seen_elements.add(cls.name) self.class_hier(cls) self.header(3, 'Other Classes') for cls in sorted(self.schema.classes.values(), key=lambda c: c.name): if cls.name not in self.seen_elements: self.seen_elements.add(cls.name) self.class_hier(cls) self.header(2, 'Slots') self.header(3, 'Predicates') for slot in sorted(self.schema.slots.values(), key=lambda c: c.name): if not slot.alias: if 'related to' in self.ancestors( slot) and not slot.mixin: self.seen_elements.add(slot.name) self.pred_hier(slot) self.header(3, 'Node Properties') for slot in sorted(self.schema.slots.values(), key=lambda s: s.name): ancs = self.ancestors(slot) if not slot.alias: if 'node property' in ancs and not slot.mixin: self.seen_elements.add(slot.name) self.pred_hier(slot) self.header(3, 'Edge Properties') for slot in sorted(self.schema.slots.values(), key=lambda s: s.name): ancs = self.ancestors(slot) if not slot.alias: if 'association slot' in ancs and not slot.mixin: self.seen_elements.add(slot.name) self.pred_hier(slot) self.header(3, 'Slot Mixins') for slot in sorted(self.schema.slots.values(), key=lambda s: s.name): if not slot.alias: if slot.mixin: self.seen_elements.add(slot.name) self.pred_hier(slot) self.header(3, 'Other Slots') for slot in sorted(self.schema.slots.values(), key=lambda s: s.name): if not slot.alias: if slot.name not in self.seen_elements: self.seen_elements.add(slot.name) self.pred_hier(slot) self.header(2, 'Types') self.header(3, 'Built in') for builtin_name in sorted(self.synopsis.typebases.keys()): self.bullet(f'**{builtin_name}**') self.header(3, 'Defined') for typ in sorted(self.schema.types.values(), key=lambda t: t.name): if self.is_secondary_ref(typ.name): if typ.typeof: typ_typ = self.type_link(typ.typeof) else: typ_typ = f'**{typ.base}**' self.bullet( self.type_link(typ, after_link=f' ({typ_typ})', use_desc=True)) # create parent for organizing markdown based on Class types with open(os.path.join(directory, 'classes.md'), 'w') as file: file.write( f'---\nparent: {self.doc_root_title}\ntitle: Classes\nhas_children: true\nnav_order: 1\nlayout: default\n---' ) with open(os.path.join(directory, 'entities.md'), 'w') as file: file.write( f'---\nparent: Classes\ngrand_parent: {self.doc_root_title}\ntitle: Entities\nhas_children: true\nnav_order: 1\nlayout: default\n---' ) with open(os.path.join(directory, 'associations.md'), 'w') as file: file.write( f'---\nparent: Classes\ngrand_parent: {self.doc_root_title}\ntitle: Associations\nhas_children: true\nnav_order: 2\nlayout: default\n---' ) with open(os.path.join(directory, 'class_mixins.md'), 'w') as file: file.write( f'---\nparent: Classes\ngrand_parent: {self.doc_root_title}\ntitle: Class Mixins\nhas_children: true\nnav_order: 3\nlayout: default\n---' ) with open(os.path.join(directory, 'other_classes.md'), 'w') as file: file.write( f'---\nparent: Classes\ngrand_parent: {self.doc_root_title}\ntitle: Other Classes\nhas_children: true\nnav_order: 4\nlayout: default\n---' ) # create parent for organizing markdown based on Slot types with open(os.path.join(directory, 'slots.md'), 'w') as file: file.write( f'---\nparent: {self.doc_root_title}\ntitle: Slots\nhas_children: true\nnav_order: 2\nlayout: default\n---' ) with open(os.path.join(directory, 'predicates.md'), 'w') as file: file.write( f'---\nparent: Slots\n\ngrand_parent: {self.doc_root_title}\ntitle: Predicates\nhas_children: true\nnav_order: 1\nlayout: default\n---' ) with open(os.path.join(directory, 'node_properties.md'), 'w') as file: file.write( f'---\nparent: Slots\ngrand_parent: {self.doc_root_title}\ntitle: Node Properties\nhas_children: true\nnav_order: 2\nlayout: default\n---' ) with open(os.path.join(directory, 'edge_properties.md'), 'w') as file: file.write( f'---\nparent: Slots\ngrand_parent: {self.doc_root_title}\ntitle: Edge Properties\nhas_children: true\nnav_order: 3\nlayout: default\n---' ) with open(os.path.join(directory, 'slot_mixins.md'), 'w') as file: file.write( f'---\nparent: Slots\ngrand_parent: {self.doc_root_title}\ntitle: Slot Mixins\nhas_children: true\nnav_order: 4\nlayout: default\n---' ) with open(os.path.join(directory, 'other_slots.md'), 'w') as file: file.write( f'---\nparent: Slots\ngrand_parent: {self.doc_root_title}\ntitle: Other Slots\nhas_children: true\nnav_order: 5\nlayout: default\n---' ) # create parent for organizing markdown based on Type types os.makedirs(os.path.join(directory, 'types'), exist_ok=True) with open(os.path.join(directory, 'types', 'index.md'), 'w') as file: file.write( f'---\nparent: {self.doc_root_title}\ntitle: Types\nhas_children: true\nnav_order: 3\nlayout: default\n---' ) with open(os.path.join(directory, 'types', 'built_in_types.md'), 'w') as file: file.write( f'---\nparent: Types\ngrand_parent: {self.doc_root_title}\ntitle: Built-in Types\nhas_children: true\nnav_order: 1\nlayout: default\n---' ) with open(os.path.join(directory, 'types', 'defined_types.md'), 'w') as file: file.write( f'---\nparent: Types\ngrand_parent: {self.doc_root_title}\ntitle: Defined Types\nhas_children: true\nnav_order: 2\nlayout: default\n---' )
def gen_classdef(self, cls: ClassDefinition) -> str: """ Generate python definition for class cls """ parentref = f'({self.formatted_element_name(cls.is_a, True) if cls.is_a else "YAMLRoot"})' slotdefs = self.gen_class_variables(cls) postinits = self.gen_postinits(cls) templatemethods = self.gen_parsers( cls) if cls.string_template else None wrapped_description = f'\n\t"""\n\t{wrapped_annotation(be(cls.description))}\n\t"""' if be( cls.description) else '' return ('\n@dataclass' if slotdefs else '') + \ f'\nclass {self.class_or_type_name(cls.name)}{parentref}:{wrapped_description}' + \ f'\n\t{self.gen_inherited_slots(cls)}\n' + \ f'\n\t{self.gen_class_meta(cls)}\n' + \ (f'\n\t{slotdefs}' if slotdefs else '') + \ (f'\n{postinits}' if postinits else '') + \ (f'\n{templatemethods}' if templatemethods else '')