linkml 1.5.5__py3-none-any.whl → 1.5.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- linkml/__init__.py +2 -6
- linkml/_version.py +1 -1
- linkml/generators/PythonGenNotes.md +4 -4
- linkml/generators/__init__.py +26 -5
- linkml/generators/common/type_designators.py +27 -22
- linkml/generators/csvgen.py +4 -10
- linkml/generators/docgen/class.md.jinja2 +7 -0
- linkml/generators/docgen/class_diagram.md.jinja2 +0 -6
- linkml/generators/docgen/subset.md.jinja2 +54 -13
- linkml/generators/docgen.py +94 -92
- linkml/generators/dotgen.py +5 -9
- linkml/generators/erdiagramgen.py +58 -53
- linkml/generators/excelgen.py +10 -16
- linkml/generators/golanggen.py +11 -21
- linkml/generators/golrgen.py +4 -13
- linkml/generators/graphqlgen.py +3 -11
- linkml/generators/javagen.py +8 -15
- linkml/generators/jsonldcontextgen.py +7 -36
- linkml/generators/jsonldgen.py +14 -12
- linkml/generators/jsonschemagen.py +183 -136
- linkml/generators/linkmlgen.py +1 -1
- linkml/generators/markdowngen.py +40 -89
- linkml/generators/namespacegen.py +1 -2
- linkml/generators/oocodegen.py +22 -25
- linkml/generators/owlgen.py +48 -49
- linkml/generators/prefixmapgen.py +6 -14
- linkml/generators/projectgen.py +7 -14
- linkml/generators/protogen.py +3 -5
- linkml/generators/pydanticgen.py +85 -73
- linkml/generators/pythongen.py +89 -157
- linkml/generators/rdfgen.py +5 -11
- linkml/generators/shaclgen.py +32 -18
- linkml/generators/shexgen.py +19 -24
- linkml/generators/sparqlgen.py +5 -13
- linkml/generators/sqlalchemy/__init__.py +3 -2
- linkml/generators/sqlalchemy/sqlalchemy_declarative_template.py +7 -7
- linkml/generators/sqlalchemy/sqlalchemy_imperative_template.py +3 -3
- linkml/generators/sqlalchemygen.py +29 -27
- linkml/generators/sqlddlgen.py +34 -26
- linkml/generators/sqltablegen.py +21 -21
- linkml/generators/sssomgen.py +11 -13
- linkml/generators/summarygen.py +2 -4
- linkml/generators/terminusdbgen.py +7 -19
- linkml/generators/typescriptgen.py +10 -18
- linkml/generators/yamlgen.py +0 -2
- linkml/generators/yumlgen.py +23 -71
- linkml/linter/cli.py +4 -11
- linkml/linter/config/datamodel/config.py +17 -47
- linkml/linter/linter.py +2 -4
- linkml/linter/rules.py +34 -48
- linkml/reporting/__init__.py +2 -0
- linkml/reporting/model.py +9 -24
- linkml/transformers/relmodel_transformer.py +20 -33
- linkml/transformers/schema_renamer.py +14 -10
- linkml/utils/converter.py +15 -15
- linkml/utils/datautils.py +9 -24
- linkml/utils/datavalidator.py +2 -2
- linkml/utils/execute_tutorial.py +10 -12
- linkml/utils/generator.py +74 -92
- linkml/utils/helpers.py +4 -2
- linkml/utils/ifabsent_functions.py +23 -15
- linkml/utils/mergeutils.py +19 -35
- linkml/utils/rawloader.py +2 -6
- linkml/utils/schema_builder.py +31 -19
- linkml/utils/schema_fixer.py +28 -18
- linkml/utils/schemaloader.py +44 -89
- linkml/utils/schemasynopsis.py +50 -73
- linkml/utils/sqlutils.py +40 -30
- linkml/utils/typereferences.py +9 -6
- linkml/utils/validation.py +4 -5
- linkml/validators/__init__.py +2 -0
- linkml/validators/jsonschemavalidator.py +104 -53
- linkml/validators/sparqlvalidator.py +5 -15
- linkml/workspaces/datamodel/workspaces.py +13 -30
- linkml/workspaces/example_runner.py +75 -68
- {linkml-1.5.5.dist-info → linkml-1.5.7.dist-info}/METADATA +2 -2
- linkml-1.5.7.dist-info/RECORD +109 -0
- linkml-1.5.5.dist-info/RECORD +0 -109
- {linkml-1.5.5.dist-info → linkml-1.5.7.dist-info}/LICENSE +0 -0
- {linkml-1.5.5.dist-info → linkml-1.5.7.dist-info}/WHEEL +0 -0
- {linkml-1.5.5.dist-info → linkml-1.5.7.dist-info}/entry_points.txt +0 -0
linkml/generators/docgen.py
CHANGED
@@ -1,23 +1,28 @@
|
|
1
|
+
import importlib.util
|
1
2
|
import logging
|
2
3
|
import os
|
3
4
|
from copy import deepcopy
|
4
5
|
from dataclasses import dataclass, field
|
5
6
|
from enum import Enum
|
6
7
|
from pathlib import Path
|
7
|
-
from typing import
|
8
|
-
TextIO, Tuple, TypeVar, Union)
|
8
|
+
from typing import Dict, Iterable, Iterator, List, Optional, Tuple, Union
|
9
9
|
|
10
10
|
import click
|
11
|
-
import importlib.util
|
12
11
|
from jinja2 import Environment, FileSystemLoader, Template
|
13
12
|
from linkml_runtime.dumpers import yaml_dumper
|
14
|
-
from linkml_runtime.linkml_model.meta import (
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
13
|
+
from linkml_runtime.linkml_model.meta import (
|
14
|
+
ClassDefinition,
|
15
|
+
ClassDefinitionName,
|
16
|
+
Definition,
|
17
|
+
DefinitionName,
|
18
|
+
Element,
|
19
|
+
EnumDefinition,
|
20
|
+
SlotDefinition,
|
21
|
+
SlotDefinitionName,
|
22
|
+
SubsetDefinition,
|
23
|
+
TypeDefinition,
|
24
|
+
TypeDefinitionName,
|
25
|
+
)
|
21
26
|
from linkml_runtime.utils.formatutils import camelcase, underscore
|
22
27
|
from linkml_runtime.utils.schemaview import SchemaView
|
23
28
|
|
@@ -28,14 +33,15 @@ from linkml.workspaces.example_runner import ExampleRunner
|
|
28
33
|
|
29
34
|
|
30
35
|
class MarkdownDialect(Enum):
|
31
|
-
python = "python"
|
32
|
-
myst = "myst"
|
36
|
+
python = "python" # https://python-markdown.github.io/ -- used by mkdocs
|
37
|
+
myst = "myst" # https://myst-parser.readthedocs.io/en/latest/ -- used by sphinx
|
33
38
|
|
34
39
|
|
35
40
|
class DiagramType(Enum):
|
36
41
|
uml_class_diagram = "uml_class_diagram"
|
37
42
|
er_diagram = "er_diagram"
|
38
43
|
|
44
|
+
|
39
45
|
# In future this may become a Union statement, but for now we only have dialects for markdown
|
40
46
|
DIALECT = MarkdownDialect
|
41
47
|
|
@@ -77,14 +83,15 @@ class DocGenerator(Generator):
|
|
77
83
|
|
78
84
|
Note: this is a replacement for MarkdownGenerator
|
79
85
|
|
80
|
-
Documents can be generated using either provided Jinja2 templates, or by
|
86
|
+
Documents can be generated using either provided Jinja2 templates, or by
|
87
|
+
providing your own
|
81
88
|
|
82
|
-
Currently the provided templates are for markdown but this framework allows
|
83
|
-
to rst, html, etc
|
89
|
+
Currently the provided templates are for markdown but this framework allows
|
90
|
+
direct generation to rst, html, etc
|
84
91
|
|
85
|
-
This works via jinja2 templates (found in docgen/ folder). By default, only
|
86
|
-
are provided. You can either override these, or you can
|
87
|
-
e.g. for html, latex, etc
|
92
|
+
This works via jinja2 templates (found in docgen/ folder). By default, only
|
93
|
+
markdown templates are provided. You can either override these, or you can
|
94
|
+
create entirely different templates e.g. for html, latex, etc
|
88
95
|
|
89
96
|
The template folder is expected to have files:
|
90
97
|
|
@@ -96,8 +103,9 @@ class DocGenerator(Generator):
|
|
96
103
|
- subset.FMT.jinja2
|
97
104
|
- index.FMT.jinja2
|
98
105
|
|
99
|
-
Most of these accept a jinja2 variable `element`, except index, schema,
|
100
|
-
This will generate a single
|
106
|
+
Most of these accept a jinja2 variable `element`, except index, schema,
|
107
|
+
which accept `schema`. See docgen for examples This will generate a single
|
108
|
+
document for every
|
101
109
|
|
102
110
|
- class, enum, type, slot
|
103
111
|
- subset
|
@@ -141,7 +149,6 @@ class DocGenerator(Generator):
|
|
141
149
|
use_slot_uris: bool = field(default_factory=lambda: False)
|
142
150
|
hierarchical_class_view: bool = field(default_factory=lambda: False)
|
143
151
|
|
144
|
-
|
145
152
|
def __post_init__(self):
|
146
153
|
dialect = self.dialect
|
147
154
|
if dialect is not None:
|
@@ -152,13 +159,14 @@ class DocGenerator(Generator):
|
|
152
159
|
elif dialect == MarkdownDialect.python.value:
|
153
160
|
dialect = MarkdownDialect.python
|
154
161
|
else:
|
155
|
-
raise
|
162
|
+
raise NotImplementedError(f"{dialect} not supported")
|
156
163
|
self.dialect = dialect
|
157
164
|
if isinstance(self.diagram_type, str):
|
158
165
|
self.diagram_type = DiagramType[self.diagram_type]
|
159
166
|
if self.example_directory:
|
160
167
|
self.example_runner = ExampleRunner(input_directory=Path(self.example_directory))
|
161
168
|
super().__post_init__()
|
169
|
+
self.logger = logging.getLogger(__name__)
|
162
170
|
self.schemaview = SchemaView(self.schema, merge_imports=self.mergeimports)
|
163
171
|
|
164
172
|
def serialize(self, directory: str = None) -> None:
|
@@ -172,19 +180,17 @@ class DocGenerator(Generator):
|
|
172
180
|
if directory is None:
|
173
181
|
directory = self.directory
|
174
182
|
if directory is None:
|
175
|
-
raise ValueError(
|
176
|
-
template_vars = {
|
177
|
-
|
178
|
-
|
183
|
+
raise ValueError("Directory must be provided")
|
184
|
+
template_vars = {
|
185
|
+
"sort_by": self.sort_by,
|
186
|
+
"diagram_type": self.diagram_type.value if self.diagram_type else None,
|
187
|
+
"include_top_level_diagram": self.include_top_level_diagram,
|
188
|
+
}
|
179
189
|
template = self._get_template("index")
|
180
|
-
out_str = template.render(
|
181
|
-
|
182
|
-
)
|
183
|
-
self._write(out_str, directory, "index") ## TODO: make configurable
|
190
|
+
out_str = template.render(gen=self, schema=sv.schema, schemaview=sv, **template_vars)
|
191
|
+
self._write(out_str, directory, "index") # TODO: make configurable
|
184
192
|
if self._is_single_file_format(self.format):
|
185
|
-
logging.info(
|
186
|
-
f"{self.format} is a single-page format, skipping non-index elements"
|
187
|
-
)
|
193
|
+
logging.info(f"{self.format} is a single-page format, skipping non-index elements")
|
188
194
|
return
|
189
195
|
template = self._get_template("schema")
|
190
196
|
for schema_name in sv.imports_closure():
|
@@ -198,9 +204,7 @@ class DocGenerator(Generator):
|
|
198
204
|
if self._is_external(c):
|
199
205
|
continue
|
200
206
|
n = self.name(c)
|
201
|
-
out_str = template.render(
|
202
|
-
gen=self, element=c, schemaview=sv, **template_vars
|
203
|
-
)
|
207
|
+
out_str = template.render(gen=self, element=c, schemaview=sv, **template_vars)
|
204
208
|
self._write(out_str, directory, n)
|
205
209
|
template = self._get_template("slot")
|
206
210
|
for sn, s in sv.all_slots().items():
|
@@ -208,18 +212,14 @@ class DocGenerator(Generator):
|
|
208
212
|
continue
|
209
213
|
n = self.name(s)
|
210
214
|
s = sv.induced_slot(sn)
|
211
|
-
out_str = template.render(
|
212
|
-
gen=self, element=s, schemaview=sv, **template_vars
|
213
|
-
)
|
215
|
+
out_str = template.render(gen=self, element=s, schemaview=sv, **template_vars)
|
214
216
|
self._write(out_str, directory, n)
|
215
217
|
template = self._get_template("enum")
|
216
218
|
for en, e in sv.all_enums().items():
|
217
219
|
if self._is_external(e):
|
218
220
|
continue
|
219
221
|
n = self.name(e)
|
220
|
-
out_str = template.render(
|
221
|
-
gen=self, element=e, schemaview=sv, **template_vars
|
222
|
-
)
|
222
|
+
out_str = template.render(gen=self, element=e, schemaview=sv, **template_vars)
|
223
223
|
self._write(out_str, directory, n)
|
224
224
|
template = self._get_template("type")
|
225
225
|
for tn, t in sv.all_types().items():
|
@@ -227,18 +227,14 @@ class DocGenerator(Generator):
|
|
227
227
|
continue
|
228
228
|
n = self.name(t)
|
229
229
|
t = sv.induced_type(tn)
|
230
|
-
out_str = template.render(
|
231
|
-
gen=self, element=t, schemaview=sv, **template_vars
|
232
|
-
)
|
230
|
+
out_str = template.render(gen=self, element=t, schemaview=sv, **template_vars)
|
233
231
|
self._write(out_str, directory, n)
|
234
232
|
template = self._get_template("subset")
|
235
233
|
for _, s in sv.all_subsets().items():
|
236
234
|
if self._is_external(c):
|
237
235
|
continue
|
238
236
|
n = self.name(s)
|
239
|
-
out_str = template.render(
|
240
|
-
gen=self, element=s, schemaview=sv, **template_vars
|
241
|
-
)
|
237
|
+
out_str = template.render(gen=self, element=s, schemaview=sv, **template_vars)
|
242
238
|
self._write(out_str, directory, n)
|
243
239
|
|
244
240
|
def _write(self, out_str: str, directory: str, name: str) -> None:
|
@@ -275,7 +271,7 @@ class DocGenerator(Generator):
|
|
275
271
|
Create a jinja2 template object for a given schema element type
|
276
272
|
|
277
273
|
The default location for templates is in the linkml/docgen folder,
|
278
|
-
but this can be
|
274
|
+
but this can be overridden
|
279
275
|
:param element_type: e.g. class, enum, index, subset, ...
|
280
276
|
:return:
|
281
277
|
"""
|
@@ -328,13 +324,10 @@ class DocGenerator(Generator):
|
|
328
324
|
slot_uri
|
329
325
|
"""
|
330
326
|
if type(element).class_name == "slot_definition":
|
331
|
-
|
332
327
|
if self.use_slot_uris:
|
333
328
|
curie = self.schemaview.get_uri(element)
|
334
|
-
if curie
|
329
|
+
if curie:
|
335
330
|
return curie.split(":")[1]
|
336
|
-
else:
|
337
|
-
return underscore(element.name)
|
338
331
|
|
339
332
|
return underscore(element.name)
|
340
333
|
else:
|
@@ -364,7 +357,6 @@ class DocGenerator(Generator):
|
|
364
357
|
|
365
358
|
uri = self.uri(element)
|
366
359
|
curie = self.uri(element, expand=False)
|
367
|
-
sc = element.from_schema
|
368
360
|
return f"[{curie}]({uri})"
|
369
361
|
|
370
362
|
def link(self, e: Union[Definition, DefinitionName]) -> str:
|
@@ -396,7 +388,7 @@ class DocGenerator(Generator):
|
|
396
388
|
return self._markdown_link(camelcase(e.name))
|
397
389
|
else:
|
398
390
|
return e.name
|
399
|
-
|
391
|
+
|
400
392
|
def links(self, e_list: List[DefinitionName]) -> List[str]:
|
401
393
|
"""Render list of element documentation pages as hyperlinks.
|
402
394
|
|
@@ -429,11 +421,9 @@ class DocGenerator(Generator):
|
|
429
421
|
|
430
422
|
return f"[{n}]({rel_path}.md)"
|
431
423
|
|
432
|
-
def inheritance_tree(
|
433
|
-
self, element: Definition, children: bool = True, **kwargs
|
434
|
-
) -> str:
|
424
|
+
def inheritance_tree(self, element: Definition, children: bool = True, **kwargs) -> str:
|
435
425
|
"""
|
436
|
-
Show an element in the context of its is-a
|
426
|
+
Show an element in the context of its is-a hierarchy
|
437
427
|
|
438
428
|
Limitations: currently only implemented for markdown (uses nested bullets)
|
439
429
|
|
@@ -472,9 +462,7 @@ class DocGenerator(Generator):
|
|
472
462
|
else:
|
473
463
|
pre, depth = "", 0
|
474
464
|
s = pre
|
475
|
-
s += self._tree_info(
|
476
|
-
element, depth, mixins=mixins, descriptions=descriptions, focus=focus
|
477
|
-
)
|
465
|
+
s += self._tree_info(element, depth, mixins=mixins, descriptions=descriptions, focus=focus)
|
478
466
|
return s, depth
|
479
467
|
|
480
468
|
def _tree_info(
|
@@ -486,7 +474,7 @@ class DocGenerator(Generator):
|
|
486
474
|
focus: DefinitionName = None,
|
487
475
|
) -> str:
|
488
476
|
indent = " " * depth * 4
|
489
|
-
|
477
|
+
|
490
478
|
if self.use_slot_uris:
|
491
479
|
name = self.schemaview.get_element(element).name
|
492
480
|
else:
|
@@ -594,8 +582,8 @@ class DocGenerator(Generator):
|
|
594
582
|
return erdgen.serialize_classes(class_names, follow_references=True, max_hops=2)
|
595
583
|
else:
|
596
584
|
return erdgen.serialize()
|
597
|
-
elif self.diagram_type == DiagramType.uml_class_diagram:
|
598
|
-
|
585
|
+
elif self.diagram_type.value == DiagramType.uml_class_diagram.value:
|
586
|
+
self.logger.info("This is currently handled in the jinja templates")
|
599
587
|
else:
|
600
588
|
raise NotImplementedError(f"Diagram type {self.diagram_type} not implemented")
|
601
589
|
|
@@ -635,9 +623,7 @@ class DocGenerator(Generator):
|
|
635
623
|
c.slots = []
|
636
624
|
return yaml_dumper.dumps(c)
|
637
625
|
|
638
|
-
def class_induced_slots(
|
639
|
-
self, class_name: ClassDefinitionName
|
640
|
-
) -> Iterator[SlotDefinition]:
|
626
|
+
def class_induced_slots(self, class_name: ClassDefinitionName) -> Iterator[SlotDefinition]:
|
641
627
|
"""
|
642
628
|
Yields all induced slots for a class
|
643
629
|
|
@@ -786,16 +772,19 @@ class DocGenerator(Generator):
|
|
786
772
|
return cls.slots + list(cls.attributes.keys())
|
787
773
|
|
788
774
|
def get_direct_slots(self, cls: ClassDefinition) -> List[SlotDefinition]:
|
789
|
-
"""Fetch list of all own attributes of a class, i.e.,
|
775
|
+
"""Fetch list of all own attributes of a class, i.e.,
|
790
776
|
all slots that belong to the domain of a class.
|
791
777
|
|
792
778
|
:param cls: class for which we want to determine the attributes
|
793
779
|
:return: list of all own attributes of a class
|
794
780
|
"""
|
795
|
-
return [
|
781
|
+
return [
|
782
|
+
self.inject_slot_info(self.schemaview.induced_slot(sn, cls.name))
|
783
|
+
for sn in self.get_direct_slot_names(cls)
|
784
|
+
]
|
796
785
|
|
797
786
|
def get_indirect_slots(self, cls: ClassDefinition) -> List[SlotDefinition]:
|
798
|
-
"""Fetch list of all inherited attributes of a class, i.e.,
|
787
|
+
"""Fetch list of all inherited attributes of a class, i.e.,
|
799
788
|
all slots that belong to the domain of a class.
|
800
789
|
|
801
790
|
:param cls: class for which we want to determine the attributes
|
@@ -803,9 +792,15 @@ class DocGenerator(Generator):
|
|
803
792
|
"""
|
804
793
|
sv = self.schemaview
|
805
794
|
direct_slot_names = self.get_direct_slot_names(cls)
|
806
|
-
return [
|
807
|
-
|
808
|
-
|
795
|
+
return [
|
796
|
+
self.inject_slot_info(slot)
|
797
|
+
for slot in sv.class_induced_slots(cls.name)
|
798
|
+
if slot.name not in direct_slot_names
|
799
|
+
]
|
800
|
+
|
801
|
+
def get_slot_inherited_from(
|
802
|
+
self, class_name: ClassDefinitionName, slot_name: SlotDefinitionName
|
803
|
+
) -> List[ClassDefinitionName]:
|
809
804
|
"""Get the name of the class that a given slot is inherited from.
|
810
805
|
|
811
806
|
:param class_name: name of the class whose slot we are checking
|
@@ -816,7 +811,7 @@ class DocGenerator(Generator):
|
|
816
811
|
induced_slot = sv.induced_slot(slot_name, class_name)
|
817
812
|
ancestors = sv.class_ancestors(class_name)
|
818
813
|
return list(set(induced_slot.domain_of).intersection(ancestors))
|
819
|
-
|
814
|
+
|
820
815
|
def get_mixin_inherited_slots(self, cls: ClassDefinition) -> Dict[str, List[str]]:
|
821
816
|
"""Fetch list of all slots acquired through mixing.
|
822
817
|
|
@@ -829,7 +824,7 @@ class DocGenerator(Generator):
|
|
829
824
|
mixins = sv.class_parents(class_name=cls.name, mixins=True, is_a=False)
|
830
825
|
for c in mixins:
|
831
826
|
mixed_in_slots[c] = sv.class_slots(c)
|
832
|
-
|
827
|
+
|
833
828
|
return mixed_in_slots
|
834
829
|
|
835
830
|
def example_object_blobs(self, class_name: str) -> List[Tuple[str, str]]:
|
@@ -849,7 +844,6 @@ class DocGenerator(Generator):
|
|
849
844
|
return objs
|
850
845
|
|
851
846
|
|
852
|
-
|
853
847
|
@shared_arguments(DocGenerator)
|
854
848
|
@click.option(
|
855
849
|
"--directory",
|
@@ -858,13 +852,17 @@ class DocGenerator(Generator):
|
|
858
852
|
help="Folder to which document files are written",
|
859
853
|
)
|
860
854
|
@click.option("--dialect", help="Dialect or 'flavor' of Markdown used.")
|
861
|
-
@click.option(
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
855
|
+
@click.option(
|
856
|
+
"--diagram-type",
|
857
|
+
type=click.Choice([e.value for e in DiagramType]),
|
858
|
+
help="Type of UML diagram to be rendered on class documentation pages.",
|
859
|
+
)
|
860
|
+
@click.option(
|
861
|
+
"--include-top-level-diagram/--no-include-top-level-diagram",
|
862
|
+
default=False,
|
863
|
+
show_default=True,
|
864
|
+
help="Include ER diagram of the entire schema on index page.",
|
865
|
+
)
|
868
866
|
@click.option(
|
869
867
|
"--sort-by",
|
870
868
|
default="name",
|
@@ -890,21 +888,25 @@ class DocGenerator(Generator):
|
|
890
888
|
)
|
891
889
|
@click.option(
|
892
890
|
"--example-directory",
|
893
|
-
help="Folder in which example files are found. These are used to make inline examples"
|
891
|
+
help="Folder in which example files are found. These are used to make inline examples",
|
894
892
|
)
|
895
893
|
@click.version_option(__version__, "-V", "--version")
|
896
894
|
@click.command()
|
897
|
-
def cli(
|
895
|
+
def cli(
|
896
|
+
yamlfile, directory, dialect, template_directory, use_slot_uris, hierarchical_class_view, **args
|
897
|
+
):
|
898
898
|
"""Generate documentation folder from a LinkML YAML schema
|
899
899
|
|
900
|
-
Currently a default set of templates for markdown is provided (see the
|
900
|
+
Currently a default set of templates for markdown is provided (see the
|
901
|
+
folder linkml/generators/docgen/)
|
901
902
|
|
902
|
-
If you specify another format (e.g. html) then you need to provide a
|
903
|
-
each type of entity inside.
|
903
|
+
If you specify another format (e.g. html) then you need to provide a
|
904
|
+
template_directory argument, with a template for each type of entity inside.
|
904
905
|
|
905
|
-
Examples can optionally be integrated into the documentation; to enable
|
906
|
-
--example-directory argument. The example directory
|
907
|
-
following the naming convention
|
906
|
+
Examples can optionally be integrated into the documentation; to enable
|
907
|
+
this, pass in the --example-directory argument. The example directory
|
908
|
+
should contain one file per example, following the naming convention
|
909
|
+
<ClassName>-<ExampleName>.<extension>.
|
908
910
|
|
909
911
|
For example, to include examples on the page for Person, include examples
|
910
912
|
|
linkml/generators/dotgen.py
CHANGED
@@ -3,13 +3,12 @@ Generate dotfiles
|
|
3
3
|
"""
|
4
4
|
import os
|
5
5
|
from dataclasses import dataclass
|
6
|
-
from typing import List, Optional
|
6
|
+
from typing import List, Optional
|
7
7
|
|
8
8
|
import click
|
9
9
|
from deprecated.classic import deprecated
|
10
10
|
from graphviz import FORMATS, Digraph
|
11
|
-
from linkml_runtime.linkml_model.meta import
|
12
|
-
SchemaDefinition, SlotDefinition)
|
11
|
+
from linkml_runtime.linkml_model.meta import ClassDefinition, SlotDefinition
|
13
12
|
from linkml_runtime.utils.formatutils import underscore
|
14
13
|
|
15
14
|
from linkml._version import __version__
|
@@ -26,6 +25,7 @@ class DotGenerator(Generator):
|
|
26
25
|
|
27
26
|
No longer in use: use mermaid generator instead
|
28
27
|
"""
|
28
|
+
|
29
29
|
generatorname = os.path.basename(__file__)
|
30
30
|
generatorversion = "0.1.1"
|
31
31
|
directory_output = True
|
@@ -104,9 +104,7 @@ class DotGenerator(Generator):
|
|
104
104
|
format=self.format,
|
105
105
|
)
|
106
106
|
|
107
|
-
def visit_class_slot(
|
108
|
-
self, cls: ClassDefinition, aliased_slot_name: str, slot: SlotDefinition
|
109
|
-
):
|
107
|
+
def visit_class_slot(self, cls: ClassDefinition, aliased_slot_name: str, slot: SlotDefinition):
|
110
108
|
if aliased_slot_name == "subject":
|
111
109
|
self.cls_subj = slot
|
112
110
|
elif aliased_slot_name == "object":
|
@@ -143,9 +141,7 @@ class DotGenerator(Generator):
|
|
143
141
|
"-d",
|
144
142
|
help="Output directory - if supplied, a graph per class will be generated",
|
145
143
|
)
|
146
|
-
@click.option(
|
147
|
-
"--out", "-o", help="Target file -- if supplied, one large graph will be generated"
|
148
|
-
)
|
144
|
+
@click.option("--out", "-o", help="Target file -- if supplied, one large graph will be generated")
|
149
145
|
@click.option("--classname", "-c", multiple=True, help="Class(es) to transform")
|
150
146
|
@click.version_option(__version__, "-V", "--version")
|
151
147
|
def cli(yamlfile, out, **args):
|