Пример #1
0
    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('   '))
Пример #2
0
    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)}')
Пример #3
0
 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()
Пример #4
0
    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 '')
Пример #5
0
 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
Пример #6
0
    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}
Пример #7
0
 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
Пример #8
0
    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
Пример #9
0
    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))
Пример #10
0
    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}
Пример #11
0
 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()
Пример #12
0
 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'''
Пример #13
0
 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()
Пример #14
0
    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)
Пример #17
0
 def gen_enum_comment(self, enum: EnumDefinition) -> str:
     return f'"""\n\t{wrapped_annotation(be(enum.description))}\n\t"""' if be(
         enum.description) else ''
Пример #18
0
    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---'
            )
Пример #20
0
    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 '')