linkml 1.9.3rc1__py3-none-any.whl → 1.9.3rc2__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.
Files changed (60) hide show
  1. linkml/generators/PythonGenNotes.md +49 -49
  2. linkml/generators/README.md +2 -2
  3. linkml/generators/dbmlgen.py +0 -1
  4. linkml/generators/docgen/class.md.jinja2 +35 -11
  5. linkml/generators/docgen/class_diagram.md.jinja2 +15 -15
  6. linkml/generators/docgen/common_metadata.md.jinja2 +3 -5
  7. linkml/generators/docgen/enum.md.jinja2 +4 -5
  8. linkml/generators/docgen/index.md.jinja2 +5 -5
  9. linkml/generators/docgen/index.tex.jinja2 +1 -1
  10. linkml/generators/docgen/schema.md.jinja2 +1 -3
  11. linkml/generators/docgen/slot.md.jinja2 +6 -8
  12. linkml/generators/docgen/subset.md.jinja2 +4 -7
  13. linkml/generators/docgen/type.md.jinja2 +2 -3
  14. linkml/generators/docgen.py +92 -4
  15. linkml/generators/erdiagramgen.py +1 -1
  16. linkml/generators/graphqlgen.py +1 -1
  17. linkml/generators/javagen/example_template.java.jinja2 +0 -1
  18. linkml/generators/jsonldcontextgen.py +0 -1
  19. linkml/generators/jsonldgen.py +3 -1
  20. linkml/generators/jsonschemagen.py +2 -2
  21. linkml/generators/linkmlgen.py +1 -1
  22. linkml/generators/markdowngen.py +20 -9
  23. linkml/generators/mermaidclassdiagramgen.py +4 -0
  24. linkml/generators/projectgen.py +17 -20
  25. linkml/generators/pydanticgen/includes.py +5 -5
  26. linkml/generators/pydanticgen/pydanticgen.py +1 -2
  27. linkml/generators/pydanticgen/template.py +1 -1
  28. linkml/generators/pydanticgen/templates/base_model.py.jinja +1 -1
  29. linkml/generators/pydanticgen/templates/class.py.jinja +1 -1
  30. linkml/generators/pydanticgen/templates/conditional_import.py.jinja +1 -1
  31. linkml/generators/pydanticgen/templates/footer.py.jinja +1 -1
  32. linkml/generators/pydanticgen/templates/imports.py.jinja +1 -1
  33. linkml/generators/python/python_ifabsent_processor.py +1 -1
  34. linkml/generators/pythongen.py +9 -8
  35. linkml/generators/shacl/shacl_ifabsent_processor.py +0 -1
  36. linkml/generators/shaclgen.py +1 -1
  37. linkml/generators/sparqlgen.py +1 -1
  38. linkml/generators/sqlalchemy/__init__.py +0 -4
  39. linkml/generators/sqlalchemygen.py +9 -15
  40. linkml/generators/sqltablegen.py +70 -4
  41. linkml/generators/string_template.md +3 -4
  42. linkml/generators/terminusdbgen.py +1 -2
  43. linkml/linter/cli.py +3 -4
  44. linkml/linter/config/datamodel/config.py +286 -135
  45. linkml/linter/config/datamodel/config.yaml +26 -11
  46. linkml/linter/config/default.yaml +6 -0
  47. linkml/linter/config/recommended.yaml +6 -0
  48. linkml/linter/linter.py +10 -6
  49. linkml/linter/rules.py +144 -46
  50. linkml/transformers/relmodel_transformer.py +2 -1
  51. linkml/utils/generator.py +3 -0
  52. linkml/utils/logictools.py +5 -5
  53. linkml/utils/schemaloader.py +4 -4
  54. linkml/utils/schemasynopsis.py +11 -7
  55. linkml/workspaces/datamodel/workspaces.yaml +0 -5
  56. {linkml-1.9.3rc1.dist-info → linkml-1.9.3rc2.dist-info}/LICENSE +1 -1
  57. {linkml-1.9.3rc1.dist-info → linkml-1.9.3rc2.dist-info}/METADATA +1 -1
  58. {linkml-1.9.3rc1.dist-info → linkml-1.9.3rc2.dist-info}/RECORD +60 -60
  59. {linkml-1.9.3rc1.dist-info → linkml-1.9.3rc2.dist-info}/WHEEL +0 -0
  60. {linkml-1.9.3rc1.dist-info → linkml-1.9.3rc2.dist-info}/entry_points.txt +0 -0
@@ -8,7 +8,7 @@ The elements that control the python for slot generation include
8
8
  * Whether `range` references an instance of a LinkML `type` or a LinkML `class`
9
9
  * If the slot range is a `class`:
10
10
  * Whether the class has a key (`key: <type>`), an identifier (`identifier: <type>`), or neither
11
- * _If_ the class has a `key` or `identifier`, whether the instances are inlined as a dictionary (`inlined: true`),
11
+ * _If_ the class has a `key` or `identifier`, whether the instances are inlined as a dictionary (`inlined: true`),
12
12
  inlined as a list (`inlined_as_list: true`) or are referenced elsewhere in the model (Default).
13
13
  * Whether the slot is or concrete (`abstract: false`) or abstract (`abstract: true` or `mixin: true`) (Default: `false`)
14
14
  * Whether a slot is required (`required: true`) or optional (`required: false`) (Default: `false`)
@@ -128,11 +128,11 @@ The python then emits a class definition for the `Integers` class, where we have
128
128
 
129
129
  * The type, `int`, is from the `base` attribute. The python generator does make use of strictly positional parameters,
130
130
  so all type declarations will have an appropriate default, which is `None` in this case:
131
-
131
+
132
132
  `mand_integer: int = None`
133
-
133
+
134
134
  * Check for the presence of the value itself:
135
- ```
135
+ ```
136
136
  if self.mand_integer is None:
137
137
  raise ValueError("mand_integer must be supplied")
138
138
  ```
@@ -145,68 +145,68 @@ The python then emits a class definition for the `Integers` class, where we have
145
145
  2) `mand_multi_integer` - a mandatory list of integers
146
146
 
147
147
  * Accept _either_ a list of integers or a single integer, which will be converted to a list:
148
-
149
- `mand_multi_integer: Union[int, List[int]] = None`
150
-
148
+
149
+ `mand_multi_integer: Union[int, List[int]] = None`
150
+
151
151
  * Check that the value is present. _Note:_ LinkML treats an empty list as the same as an absent value.
152
-
152
+
153
153
  ```
154
154
  if self.mand_multi_integer is None:
155
155
  raise ValueError("mand_multi_integer must be supplied")
156
156
  ```
157
157
  * Convert a non-list value into a list. This allows constructors to be lazy when it comes to single valued entries.
158
- Note, however, that this _does_ require that list-of-list constructs to be explicitly declared because, while the
158
+ Note, however, that this _does_ require that list-of-list constructs to be explicitly declared because, while the
159
159
  code treats `x = C(1)` as the same as `x = C([1])` in the multivalued case, it does _not_ attempt to differentiate
160
160
  `x = C([1])` and `x = C([[1]])`. This could be done if there is a compelling reason to, however:
161
-
162
- ```
161
+
162
+ ```
163
163
  elif not isinstance(self.mand_multi_integer, list):
164
164
  self.mand_multi_integer = [self.mand_multi_integer]
165
165
  ```
166
166
  * Check that the mandatory list has at least one element (our definition of `mandatory list`:
167
- ```
167
+ ```
168
168
  elif len(self.mand_multi_integer) == 0:
169
169
  raise ValueError(f"mand_multi_integer must be a non-empty list")
170
170
  ```
171
171
  * Coerce all of the member of the list into the target type (`int`):
172
-
172
+
173
173
  `self.mand_multi_integer = [v if isinstance(v, int) else int(v) for v in self.mand_multi_integer]`
174
-
174
+
175
175
  3) `opt_integer` - Optional non-list.
176
176
  * Accept either an `int` or `None`, the latter being entailed in the `Optional` type:
177
177
  `opt_integer: Optional[int] = None`
178
-
178
+
179
179
  * Coerce to an integer if the value is present, otherwise let it be:
180
- ```
180
+ ```
181
181
  if self.opt_integer is not None and not isinstance(self.opt_integer, int):
182
182
  self.opt_integer = int(self.opt_integer)
183
183
  ```
184
184
  * Type is `Optional[<type>]`
185
185
  * `__post_init__` adds type coercion if necessary
186
-
186
+
187
187
  4) `opt_multi_integer`: list:
188
188
  * Accept one of `None`, `int`, list of `int`, or anything that can be coerced into `List[int]`:
189
-
189
+
190
190
  `opt_multi_integer: Optional[Union[int, List[int]]] = empty_list()`
191
-
191
+
192
192
  * The absence of a list property is always represented as an empty list:
193
- ```
193
+ ```
194
194
  if self.opt_multi_integer is None:
195
195
  self.opt_multi_integer = []
196
196
  ```
197
-
197
+
198
198
  * Coerce any other non-list into a list:
199
- ```
199
+ ```
200
200
  if not isinstance(self.opt_multi_integer, list):
201
201
  self.opt_multi_integer = [self.opt_multi_integer]
202
202
  ```
203
-
203
+
204
204
  * Coerce all the members of the list into the range type
205
- ```
205
+ ```
206
206
  self.opt_multi_integer = [v if isinstance(v, int) else int(v) for v in self.opt_multi_integer]
207
207
  ```
208
208
 
209
-
209
+
210
210
  ### 2) Python generation for a Type defined in `metamodelcore.py` -- `XSDDate` in this example
211
211
  YAML:
212
212
  ```yaml
@@ -287,7 +287,7 @@ are the `Union` of the class representing the element and the `repr` element (e.
287
287
  `int` type:
288
288
 
289
289
  mand_multi_integer: Union[int, List[int]] = None
290
-
290
+
291
291
  `XSDDate` type:
292
292
 
293
293
  mand_multi_date: Union[Union[str, XSDDate], List[Union[str, XSDDate]]] = None
@@ -375,15 +375,15 @@ The Python patterns for each of the inherited types (Inherited from basic (e.g.
375
375
  ### 2) Slot range is a LinkML `class` definition
376
376
  The previous section described the Python that was generated for slot ranges that reference LinkML **Type** definitions.
377
377
  This section addresses the second use case, where the slot range references another LinkML **Class**. Classes are
378
- a more complex example, because, as opposed to types, classes can either be represented by _value_ or, if they have been
378
+ a more complex example, because, as opposed to types, classes can either be represented by _value_ or, if they have been
379
379
  declared to have unique identifiers, by _reference_. In addition, classes that are represented by value can either be
380
- represented as lists of values or dictionaries.
380
+ represented as lists of values or dictionaries.
381
381
 
382
382
  The following attributes control how the python is generated for a LinkML `class` definition:
383
383
  * The slot `abstract` setting
384
384
  * The slot `required` setting
385
385
  * The slot `multivalued` setting
386
- * Whether a class includes a slot identified as a "key" (`"key": true`), an "identifier" (`"identifier": true`) or
386
+ * Whether a class includes a slot identified as a "key" (`"key": true`), an "identifier" (`"identifier": true`) or
387
387
  neither. Note that at the moment, a class may have at most one key or identifier slot. Two keys, two identifiers or
388
388
  a key and an identifier are all considered errors. It is anticipated that a future version of LinkML will allow
389
389
  multiple key slots, directly implementing the notion of a "compound key".
@@ -438,16 +438,16 @@ An optional, single element class generates the following code:
438
438
  Range is a optional class that contains one non-key/non-identifier element
439
439
  """
440
440
  ...
441
-
441
+
442
442
  v1: Optional[Union[dict, OneElementClass]] = None
443
-
443
+
444
444
  def __post_init__(self, **kwargs: Dict[str, Any]):
445
445
  if self.v1 is not None and not isinstance(self.v1, OneElementClass):
446
446
  self.v1 = OneElementClass(**self.v1)
447
-
447
+
448
448
  super().__post_init__(**kwargs)
449
449
  ```
450
- `v1` can be one of:
450
+ `v1` can be one of:
451
451
  * `None` - as in indicated by the `Optional` type
452
452
  * any python `dict`, which is the type that underlies all class representations
453
453
  * an instance of `OneElementClass`
@@ -512,7 +512,7 @@ The code:
512
512
 
513
513
  In the final case, we've attempted to show both a) what a required inline list looks like and b) show that the target
514
514
  type is irrelevant as long as it is a LinkML `Class` and has no `key` or `identifier` slots
515
-
515
+
516
516
 
517
517
  ```python
518
518
  @dataclass
@@ -542,7 +542,7 @@ The structural differences between the above class and its predecessor are:
542
542
 
543
543
 
544
544
  ### Keyed or Identified Classes
545
- When the range of a slot is a LinkML class that has a `key` or an `identifier`, additional options
545
+ When the range of a slot is a LinkML class that has a `key` or an `identifier`, additional options
546
546
  present themselves:
547
547
  1) Should elements be represented inline or as references?
548
548
  2) If inline, should the elements be represented as lists or as dictionaries, whose key is the `key` or `identifier`
@@ -776,7 +776,7 @@ The table below describes the various python generation options for single-value
776
776
  | 1.4 | false | - | Y | Y | slot value in of containing class (i.e. inline) |
777
777
 
778
778
  The YAML examples below the above options for both optional and required slots.
779
-
779
+
780
780
  ```yaml
781
781
  OptionalThreeElementRange:
782
782
  description: Case 1.1(o) -- single values optional slot - range has no keys or identifiers
@@ -1135,7 +1135,7 @@ Starting with the signature:
1135
1135
  `v1: Optional[Union[Dict[Union[str, IdentifiedThreeElementClassName], Union[dict, IdentifiedThreeElementClass]], List[Union[dict, IdentifiedThreeElementClass]]]] = empty_list()`
1136
1136
 
1137
1137
  The outermost declaration: `Optional[...] = empty_list()` reflects:
1138
- 1) `v1` is not required: `None` is a valid value
1138
+ 1) `v1` is not required: `None` is a valid value
1139
1139
  2) the internal storage structure is going to be a list. Note that None, [] and {} (Missing scalar, empty list and empty dictionary all indicate absence of a value)
1140
1140
 
1141
1141
  Moving inwards, `Union[Dict[...], List[...]]` means that the inputs can either be in the form of a dictionary or a list.
@@ -1172,12 +1172,12 @@ One can represent instances of `OptionalMultivaluedInlinedListIdentifiedThreeEle
1172
1172
  or in python as:
1173
1173
  ```python
1174
1174
  ktec_examples = OptionalMultivaluedInlinedListIdentifiedThreeElementRange(
1175
- {
1175
+ {
1176
1176
  element1: {value: 17, modifier: "2012-03-11"},
1177
1177
  KeyedThreeElementClassKey('element2'): {},
1178
1178
  element3: {name: 'element3', value: 42}
1179
- }
1180
- )
1179
+ }
1180
+ )
1181
1181
  ```
1182
1182
  Note that the following is not valid because, while the `name` attribute (the key) is not required, as it has already
1183
1183
  been established by the key, if present it _must_ match the key itself
@@ -1197,9 +1197,9 @@ ktec_examples: OptionalMultivaluedInlinedListIdentifiedThreeElementRange = {
1197
1197
  Would result in an error, as `itc.name` is an instance of `IdentifiedThreeElementClassKey` while `KeyedThreeElementClass` expects a `KeyedThreeElementClassKey`
1198
1198
 
1199
1199
  #### Input in the form of a list
1200
- Starting with the skeleton we visited earlier, Moving inwards, `Union[Dict[...], List[...]]` the second option,
1200
+ Starting with the skeleton we visited earlier, Moving inwards, `Union[Dict[...], List[...]]` the second option,
1201
1201
  `List[Union[dict, IdentifiedThreeElementClass]]` indicates that the input to the constructor can also be a _list_ of
1202
- dictionaries that conform to the `IdentifiedThreeElementClass` model. Referencing the examples that we used above,
1202
+ dictionaries that conform to the `IdentifiedThreeElementClass` model. Referencing the examples that we used above,
1203
1203
  we could also use:
1204
1204
  ```yaml
1205
1205
  - name: element1
@@ -1215,8 +1215,8 @@ ktec_examples = OptionalMultivaluedInlinedListIdentifiedThreeElementRange(
1215
1215
  [ {name: 'element1', value: 17, modifier: "2012-03-11"},
1216
1216
  {name: KeyedThreeElementClassKey('element2')},
1217
1217
  {name: 'element3', value: 42}
1218
- ]
1219
- )
1218
+ ]
1219
+ )
1220
1220
  ```
1221
1221
  We then move on to the generated code:
1222
1222
  ```python
@@ -1243,12 +1243,12 @@ The final line in the `__post_init__` section:
1243
1243
  ```python
1244
1244
  self._normalize_inlined_slot(slot_name="v1", slot_type=IdentifiedThreeElementClass, key_name="name", inlined_as_list=True, keyed=True)
1245
1245
  ```
1246
- passes the remainder of the post initialization normalization to a function defined in `YAMLRoot`.
1246
+ passes the remainder of the post initialization normalization to a function defined in `YAMLRoot`.
1247
1247
 
1248
1248
 
1249
1249
  The final case, Case 2.4 (Inlined as dictionary) is essentially the same, with the exception that the target type is
1250
- a dictionary rather than a list.
1251
-
1250
+ a dictionary rather than a list.
1251
+
1252
1252
  ```yaml
1253
1253
  OptionalMultivaluedInlinedIdentifiedThreeElementRangeList:
1254
1254
  description: 2.4(o) Range is an optional identified three element class that is represented as an inlined dictionary
@@ -1321,7 +1321,7 @@ At the moment, the following code is emitted:
1321
1321
  # Slots
1322
1322
  class slots:
1323
1323
  pass
1324
-
1324
+
1325
1325
  ...
1326
1326
 
1327
1327
  slots.RequiredInlinedKeyedTwoElementRange_v1 = Slot(uri=LISTS_AND_KEYS.v1, name="RequiredInlinedKeyedTwoElementRange_v1", curie=LISTS_AND_KEYS.curie('v1'),
@@ -1343,7 +1343,7 @@ a slot, you use `slots.RequiredInlinedTwoElementRange_v1` (which is the mangling
1343
1343
  At the _moment_, you have the following elements:
1344
1344
 
1345
1345
  * uri - the SLOT URI
1346
- * name - the mangled name
1346
+ * name - the mangled name
1347
1347
  * curie - the SLOT CURIE
1348
1348
  * model_uri - the slot URI where the base is the Model URI vs. one assigned via `slot_uri`
1349
1349
  * domain - the slot domain
@@ -15,8 +15,8 @@
15
15
  | gen-markdown | [markdowngen.py](https://github.com/linkml/linkml/blob/main/linkml/generators/markdowngen.py) | MarkdownGenerator | generate markdown documentation of the model | [markdowngen help](../../tests/test_scripts/output/genmarkdown/help) |
16
16
  | gen-namespaces | [namespacegen.py](https://github.com/linkml/linkml/blob/main/linkml/generators/namespacegen.py) | NamespaceGenerator | generate namespace manager for URI's in model | [namespacegen help](../../tests/test_scripts/output/gennamespace/help) |
17
17
  | gen-owl | [owlgen.py](https://github.com/linkml/linkml/blob/main/linkml/generators/owlgen.py) | OwlSchemaGenerator | generate an OWL representation | [owlgen help](../../tests/test_scripts/output/genowl/help) |
18
- | gen-plantuml | [plantumlgen.py](https://github.com/linkml/linkml/blob/main/linkml/generators/plantumlgen.py) | PlantumlGenerator | generate PlantUML representation via [PlantUML](https://plantuml.com/) | [plantumlgen help](../../tests/test_scripts/output/genuml/help) |
18
+ | gen-plantuml | [plantumlgen.py](https://github.com/linkml/linkml/blob/main/linkml/generators/plantumlgen.py) | PlantumlGenerator | generate PlantUML representation via [PlantUML](https://plantuml.com/) | [plantumlgen help](../../tests/test_scripts/output/genuml/help) |
19
19
  | gen-python | [pythongen.py](https://github.com/linkml/linkml/blob/main/linkml/generators/pythongen.py) | PythonGenerator | generate python classes for a model | [pythongen help](../../tests/test_scripts/output/genpython/help) |
20
20
  | gen-rdf | [rdfgen.py](https://github.com/linkml/linkml/blob/main/linkml/generators/rdfgen.py) | RDFGenerator | generate RDF representation of model | [rdfgen help](../../tests/test_scripts/output/genrdf/help) |
21
21
  | gen-shex | [shexgen.py](https://github.com/linkml/linkml/blob/main/linkml/generators/shexgen.py) | ShExGenerator | generate a ShEx model representation | [shexgen help](../../tests/test_scripts/output/genshex/help) |
22
- | gen-yuml | [yumlgen.py](https://github.com/linkml/linkml/blob/main/linkml/generators/yumlgen.py) | YumlGenerator | generate YUML representation via [YUML](https://yuml.me/) | [yumlgen help](../../tests/test_scripts/output/genuml/help) |
22
+ | gen-yuml | [yumlgen.py](https://github.com/linkml/linkml/blob/main/linkml/generators/yumlgen.py) | YumlGenerator | generate YUML representation via [YUML](https://yuml.me/) | [yumlgen help](../../tests/test_scripts/output/genuml/help) |
@@ -113,7 +113,6 @@ class DBMLGenerator(Generator):
113
113
 
114
114
  # Check if the slot references another class
115
115
  if slot.range in self.schemaview.all_classes():
116
-
117
116
  # Find the identifier slot of the referenced class
118
117
  identifier_slot_name = next(
119
118
  (
@@ -21,13 +21,12 @@
21
21
  {%- endif -%}
22
22
  {% endmacro %}
23
23
 
24
- # Class: {{ title }} {% if element.deprecated %} <span style="color: red;"><strong> (DEPRECATED) </strong> {% endif %}
24
+ # Class: {{ title }} {% if element.deprecated %} <span style="color: red;"><strong> (DEPRECATED) </strong></span> {% endif %}
25
25
 
26
26
  {%- if header -%}
27
- {{header}}
27
+ {{ header }}
28
28
  {%- endif -%}
29
29
 
30
-
31
30
  {% if element.description %}
32
31
  {% set element_description_lines = element.description.split('\n') %}
33
32
  {% for element_description_line in element_description_lines %}
@@ -41,7 +40,6 @@ _{{ element_description_line }}_
41
40
 
42
41
  URI: {{ gen.uri_link(element) }}
43
42
 
44
-
45
43
  {% if diagram_type == "er_diagram" %}
46
44
  ```{{ gen.mermaid_directive() }}
47
45
  {{ gen.mermaid_diagram([element.name]) }}
@@ -93,7 +91,34 @@ URI: {{ gen.uri_link(element) }}
93
91
  | used by | used in | type | used |
94
92
  | --- | --- | --- | --- |
95
93
  {% for usage in schemaview.usage_index().get(element.name) -%}
96
- | {{gen.link(usage.used_by)}} | {{gen.link(usage.slot)}} | {{usage.metaslot}} | {{ gen.link(usage.used) }} |
94
+ | {{ gen.link(usage.used_by) }} | {{ gen.link(usage.slot) }} | {{ usage.metaslot }} | {{ gen.link(usage.used) }} |
95
+ {% endfor %}
96
+ {% endif %}
97
+
98
+ {% if element.rules %}
99
+ ## Rules
100
+
101
+ {% for rule in gen.classrule_to_dict_view(element) %}
102
+ ### {{ rule.title }}
103
+
104
+ | Rule Applied | Preconditions | Postconditions | Elseconditions |
105
+ |--------------|---------------|----------------|----------------|
106
+ {% for key in rule.preconditions -%}
107
+ | {{ key }} |
108
+ {%- if rule.preconditions[key] is defined -%}
109
+ ```{{ rule.preconditions[key] }}```
110
+ {%- else -%}
111
+ {% endif %} |
112
+ {%- if rule.postconditions and rule.postconditions[key] is defined -%}
113
+ ```{{ rule.postconditions[key] }}```
114
+ {%- else -%}
115
+ {% endif %} |
116
+ {%- if rule.elseconditions and rule.elseconditions[key] is defined -%}
117
+ ```{{ rule.elseconditions[key] }}```
118
+ {%- else -%}
119
+ {% endif %} |
120
+ {% endfor %}
121
+
97
122
  {% endfor %}
98
123
  {% endif %}
99
124
 
@@ -102,7 +127,7 @@ URI: {{ gen.uri_link(element) }}
102
127
  {% if gen.example_object_blobs(element.name) -%}
103
128
  ## Examples
104
129
  {% for name, blob in gen.example_object_blobs(element.name) -%}
105
- ### Example: {{name}}
130
+ ### Example: {{ name }}
106
131
 
107
132
  ```yaml
108
133
  {{ blob }}
@@ -110,7 +135,6 @@ URI: {{ gen.uri_link(element) }}
110
135
  {% endfor %}
111
136
  {% endif %}
112
137
 
113
-
114
138
  ## LinkML Source
115
139
 
116
140
  <!-- TODO: investigate https://stackoverflow.com/questions/37606292/how-to-create-tabbed-code-blocks-in-mkdocs-or-sphinx -->
@@ -119,7 +143,7 @@ URI: {{ gen.uri_link(element) }}
119
143
 
120
144
  <details>
121
145
  ```yaml
122
- {{gen.yaml(element)}}
146
+ {{ gen.yaml(element) }}
123
147
  ```
124
148
  </details>
125
149
 
@@ -127,10 +151,10 @@ URI: {{ gen.uri_link(element) }}
127
151
 
128
152
  <details>
129
153
  ```yaml
130
- {{gen.yaml(element, inferred=True)}}
154
+ {{ gen.yaml(element, inferred=True) }}
131
155
  ```
132
156
  </details>
133
157
 
134
158
  {%- if footer -%}
135
- {{footer}}
136
- {%- endif -%}
159
+ {{ footer }}
160
+ {%- endif -%}
@@ -3,7 +3,7 @@
3
3
  {% set range_element = gen.name(schemaview.get_element(slot.range)) %}
4
4
  {% set relation_label = gen.name(slot) %}
5
5
  {{ gen.name(element) }} --> "{{ gen.cardinality(slot) }}" {{ range_element }} : {{ relation_label }}
6
- click {{ range_element }} href "../{{ range_element }}"
6
+ click {{ range_element }} href "{{ gen.link_mermaid(schemaview.get_element(slot.range)) }}"
7
7
  {% endif %}
8
8
  {% endmacro %}
9
9
 
@@ -11,19 +11,19 @@
11
11
  ```{{ gen.mermaid_directive() }}
12
12
  classDiagram
13
13
  class {{ gen.name(element) }}
14
- click {{ gen.name(element) }} href "../{{gen.name(element)}}"
14
+ click {{ gen.name(element) }} href "{{ gen.link_mermaid(element) }}"
15
15
  {% for s in schemaview.class_parents(element.name)|sort(attribute='name') -%}
16
16
  {{ gen.name(schemaview.get_element(s)) }} <|-- {{ gen.name(element) }}
17
- click {{ gen.name(schemaview.get_element(s)) }} href "../{{gen.name(schemaview.get_element(s))}}"
17
+ click {{ gen.name(schemaview.get_element(s)) }} href "{{ gen.link_mermaid(schemaview.get_element(s)) }}"
18
18
  {% endfor %}
19
19
 
20
20
  {% for s in schemaview.class_children(element.name)|sort(attribute='name') -%}
21
21
  {{ gen.name(element) }} <|-- {{ gen.name(schemaview.get_element(s)) }}
22
- click {{ gen.name(schemaview.get_element(s)) }} href "../{{gen.name(schemaview.get_element(s))}}"
22
+ click {{ gen.name(schemaview.get_element(s)) }} href "{{ gen.link_mermaid(schemaview.get_element(s)) }}"
23
23
  {% endfor %}
24
-
24
+
25
25
  {% for s in schemaview.class_induced_slots(element.name)|sort(attribute='name') -%}
26
- {{ gen.name(element) }} : {{gen.name(s)}}
26
+ {{ gen.name(element) }} : {{ gen.name(s) }}
27
27
  {% if s.range is not none and s.range not in gen.all_type_object_names() %}
28
28
  {{ slot_relationship(element, s) }}
29
29
  {% endif %}
@@ -33,13 +33,13 @@
33
33
  ```{{ gen.mermaid_directive() }}
34
34
  classDiagram
35
35
  class {{ gen.name(element) }}
36
- click {{ gen.name(element) }} href "../{{gen.name(element)}}"
36
+ click {{ gen.name(element) }} href "{{ gen.link_mermaid(element) }}"
37
37
  {% for s in schemaview.class_parents(element.name)|sort(attribute='name') -%}
38
38
  {{ gen.name(schemaview.get_element(s)) }} <|-- {{ gen.name(element) }}
39
- click {{ gen.name(schemaview.get_element(s)) }} href "../{{gen.name(schemaview.get_element(s))}}"
39
+ click {{ gen.name(schemaview.get_element(s)) }} href "{{ gen.link_mermaid(schemaview.get_element(s)) }}"
40
40
  {% endfor %}
41
41
  {% for s in schemaview.class_induced_slots(element.name)|sort(attribute='name') -%}
42
- {{ gen.name(element) }} : {{gen.name(s)}}
42
+ {{ gen.name(element) }} : {{ gen.name(s) }}
43
43
  {% if s.range is not none and s.range not in gen.all_type_object_names() %}
44
44
  {{ slot_relationship(element, s) }}
45
45
  {% endif %}
@@ -49,13 +49,13 @@
49
49
  ```{{ gen.mermaid_directive() }}
50
50
  classDiagram
51
51
  class {{ gen.name(element) }}
52
- click {{ gen.name(element) }} href "../{{gen.name(element)}}"
52
+ click {{ gen.name(element) }} href "{{ gen.link_mermaid(element) }}"
53
53
  {% for s in schemaview.class_children(element.name)|sort(attribute='name') -%}
54
54
  {{ gen.name(element) }} <|-- {{ gen.name(schemaview.get_element(s)) }}
55
- click {{ gen.name(schemaview.get_element(s)) }} href "../{{gen.name(schemaview.get_element(s))}}"
55
+ click {{ gen.name(schemaview.get_element(s)) }} href "{{ gen.link_mermaid(schemaview.get_element(s)) }}"
56
56
  {% endfor %}
57
57
  {% for s in schemaview.class_induced_slots(element.name)|sort(attribute='name') -%}
58
- {{ gen.name(element) }} : {{gen.name(s)}}
58
+ {{ gen.name(element) }} : {{ gen.name(s) }}
59
59
  {% if s.range is not none and s.range not in gen.all_type_object_names() %}
60
60
  {{ slot_relationship(element, s) }}
61
61
  {% endif %}
@@ -65,12 +65,12 @@
65
65
  ```{{ gen.mermaid_directive() }}
66
66
  classDiagram
67
67
  class {{ gen.name(element) }}
68
- click {{ gen.name(element) }} href "../{{gen.name(element)}}"
68
+ click {{ gen.name(element) }} href "{{ gen.link_mermaid(element) }}"
69
69
  {% for s in schemaview.class_induced_slots(element.name)|sort(attribute='name') -%}
70
- {{ gen.name(element) }} : {{gen.name(s)}}
70
+ {{ gen.name(element) }} : {{ gen.name(s) }}
71
71
  {% if s.range is not none and s.range not in gen.all_type_object_names() %}
72
72
  {{ slot_relationship(element, s) }}
73
73
  {% endif %}
74
74
  {% endfor %}
75
75
  ```
76
- {% endif %}
76
+ {% endif %}
@@ -6,7 +6,6 @@
6
6
  {%- endfor %}
7
7
  {% endif %}
8
8
 
9
-
10
9
  {% if element.examples %}
11
10
  ## Examples
12
11
 
@@ -21,7 +20,7 @@
21
20
  ## Comments
22
21
 
23
22
  {% for x in element.comments -%}
24
- * {{x}}
23
+ * {{ x }}
25
24
  {% endfor %}
26
25
  {% endif -%}
27
26
 
@@ -29,7 +28,7 @@
29
28
  ## TODOs
30
29
 
31
30
  {% for x in element.todos -%}
32
- * {{x}}
31
+ * {{ x }}
33
32
  {% endfor %}
34
33
  {% endif -%}
35
34
 
@@ -48,12 +47,11 @@
48
47
 
49
48
  Instances of this class *should* have identifiers with one of the following prefixes:
50
49
  {% for p in element.id_prefixes %}
51
- * {{p}}
50
+ * {{ p }}
52
51
  {% endfor %}
53
52
 
54
53
  {% endif %}
55
54
 
56
-
57
55
  {% if element.annotations %}
58
56
  ### Annotations
59
57
 
@@ -1,4 +1,4 @@
1
- # Enum: {{ gen.name(element) }} {% if element.deprecated %} <span style="color: red;"><strong> (DEPRECATED) </strong> {% endif %}
1
+ # Enum: {{ gen.name(element) }} {% if element.deprecated %} <span style="color: red;"><strong> (DEPRECATED) </strong></span> {% endif %}
2
2
 
3
3
  {% if element.description %}
4
4
  {% set element_description_lines = element.description.split('\n') %}
@@ -15,7 +15,7 @@ URI: {{ gen.link(element) }}
15
15
  | Value | Meaning | Description |
16
16
  | --- | --- | --- |
17
17
  {% for pv in element.permissible_values.values() -%}
18
- | {{pv.text}} | {{pv.meaning}} | {{pv.description|enshorten}} |
18
+ | {{ pv.text }} | {{ pv.meaning }} | {{ pv.description|enshorten }} |
19
19
  {% endfor %}
20
20
  {% else %}
21
21
  _This is a dynamic enum_
@@ -28,7 +28,7 @@ _This is a dynamic enum_
28
28
  | Name | Description |
29
29
  | --- | --- |
30
30
  {% for s in schemaview.get_slots_by_enum(element.name) -%}
31
- | {{gen.link(s)}} | {{s.description|enshorten}} |
31
+ | {{ gen.link(s) }} | {{ s.description|enshorten }} |
32
32
  {% endfor %}
33
33
  {% endif %}
34
34
 
@@ -38,7 +38,6 @@ _This is a dynamic enum_
38
38
 
39
39
  <details>
40
40
  ```yaml
41
- {{gen.yaml(element)}}
41
+ {{ gen.yaml(element) }}
42
42
  ```
43
43
  </details>
44
-
@@ -25,7 +25,7 @@ Name: {{ schema.name }}
25
25
  {% endfor %}
26
26
  {% else -%}
27
27
  {% for c in gen.all_class_objects()|sort(attribute=sort_by) -%}
28
- | {{gen.link(c, True)}} | {{c.description|enshorten}} |
28
+ | {{ gen.link(c, True) }} | {{ c.description|enshorten }} |
29
29
  {% endfor %}
30
30
  {% endif %}
31
31
 
@@ -34,7 +34,7 @@ Name: {{ schema.name }}
34
34
  | Slot | Description |
35
35
  | --- | --- |
36
36
  {% for s in gen.all_slot_objects()|sort(attribute=sort_by) -%}
37
- | {{gen.link(s, True)}} | {{s.description|enshorten}} |
37
+ | {{ gen.link(s, True) }} | {{ s.description|enshorten }} |
38
38
  {% endfor %}
39
39
 
40
40
  ## Enumerations
@@ -42,7 +42,7 @@ Name: {{ schema.name }}
42
42
  | Enumeration | Description |
43
43
  | --- | --- |
44
44
  {% for e in gen.all_enum_objects()|sort(attribute=sort_by) -%}
45
- | {{gen.link(e, True)}} | {{e.description|enshorten}} |
45
+ | {{ gen.link(e, True) }} | {{ e.description|enshorten }} |
46
46
  {% endfor %}
47
47
 
48
48
  ## Types
@@ -50,7 +50,7 @@ Name: {{ schema.name }}
50
50
  | Type | Description |
51
51
  | --- | --- |
52
52
  {% for t in gen.all_type_objects()|sort(attribute=sort_by) -%}
53
- | {{gen.link(t, True)}} | {{t.description|enshorten}} |
53
+ | {{ gen.link(t, True) }} | {{ t.description|enshorten }} |
54
54
  {% endfor %}
55
55
 
56
56
  ## Subsets
@@ -58,5 +58,5 @@ Name: {{ schema.name }}
58
58
  | Subset | Description |
59
59
  | --- | --- |
60
60
  {% for ss in schemaview.all_subsets().values()|sort(attribute='name') -%}
61
- | {{gen.link(ss, True)}} | {{ss.description|enshorten}} |
61
+ | {{ gen.link(ss, True) }} | {{ ss.description|enshorten }} |
62
62
  {% endfor %}
@@ -1,7 +1,7 @@
1
1
  \documentclass{article}
2
2
  \usepackage[utf8]{inputenc}
3
3
 
4
- \title{ {{gen.latex(gen.schema_title())}} }
4
+ \title{ {{ gen.latex(gen.schema_title()) }} }
5
5
 
6
6
  \begin{document}
7
7
 
@@ -1,7 +1,5 @@
1
- # {{ schema.name }} {% if schema.deprecated %} <span style="color: red;"><strong> (DEPRECATED) </strong> {% endif %}
1
+ # {{ schema.name }} {% if schema.deprecated %} <span style="color: red;"><strong> (DEPRECATED) </strong></span> {% endif %}
2
2
 
3
3
  {{ schema.description }}
4
4
 
5
5
  URI: {{ schema.id }}
6
-
7
-
@@ -21,10 +21,10 @@
21
21
  {%- endif -%}
22
22
  {% endmacro %}
23
23
 
24
- # Slot: {{ title }} {% if element.deprecated %} <span style="color: red;"><strong> (DEPRECATED) </strong> {% endif %}
24
+ # Slot: {{ title }} {% if element.deprecated %} <span style="color: red;"><strong> (DEPRECATED) </strong></span> {% endif %}
25
25
 
26
26
  {%- if header -%}
27
- {{header}}
27
+ {{ header }}
28
28
  {%- endif -%}
29
29
 
30
30
  {% if element.description %}
@@ -66,7 +66,6 @@ Alias: {{ element.alias }}
66
66
 
67
67
  {% endif %}
68
68
 
69
-
70
69
  {% if schemaview.is_mixin(element.name) %}
71
70
  ## Mixin Usage
72
71
 
@@ -95,20 +94,19 @@ Alias: {{ element.alias }}
95
94
  * Maximum Value: {{ element.maximum_value|int }}
96
95
  {% endif -%}
97
96
  {% if element.pattern %}
98
- * Regex pattern: {{ '`' }}{{ element.pattern }}{{ '`' }}
97
+ * Regex pattern: {{ '`' }}{{ element.pattern }}{{ '`' }}
99
98
  {% endif -%}
100
99
  {% if schemaview.is_mixin(element.name) %}
101
100
  * Mixin: {{ element.mixin }}
102
101
  {% endif -%}
103
102
 
104
-
105
103
  {% if schemaview.usage_index().get(element.name) %}
106
104
  ## Usages
107
105
 
108
106
  | used by | used in | type | used |
109
107
  | --- | --- | --- | --- |
110
108
  {% for usage in schemaview.usage_index().get(element.name) -%}
111
- | {{gen.link(usage.used_by)}} | {{gen.link(usage.slot)}} | {{usage.metaslot}} | {{ gen.link(usage.used) }} |
109
+ | {{ gen.link(usage.used_by) }} | {{ gen.link(usage.slot) }} | {{ usage.metaslot }} | {{ gen.link(usage.used) }} |
112
110
  {% endfor %}
113
111
  {% endif %}
114
112
 
@@ -123,5 +121,5 @@ Alias: {{ element.alias }}
123
121
  </details>
124
122
 
125
123
  {%- if footer -%}
126
- {{footer}}
127
- {%- endif -%}
124
+ {{ footer }}
125
+ {%- endif -%}