linkml 1.7.11rc1__py3-none-any.whl → 1.8.0__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/generators/docgen/class.md.jinja2 +0 -14
- linkml/generators/docgen/common_metadata.md.jinja2 +14 -1
- linkml/generators/erdiagramgen.py +37 -3
- linkml/generators/golanggen.py +1 -6
- linkml/generators/plantumlgen.py +1 -5
- linkml/generators/pydanticgen/array.py +1 -12
- linkml/generators/pydanticgen/pydanticgen.py +1 -4
- linkml/generators/pythongen.py +1 -8
- linkml/generators/shaclgen.py +95 -3
- linkml/generators/sqlalchemygen.py +2 -10
- linkml/linter/rules.py +1 -6
- linkml/transformers/logical_model_transformer.py +6 -2
- linkml/utils/schemaloader.py +27 -0
- linkml/utils/schemasynopsis.py +1 -9
- linkml/validator/__init__.py +1 -3
- linkml/validator/plugins/__init__.py +1 -3
- {linkml-1.7.11rc1.dist-info → linkml-1.8.0.dist-info}/METADATA +2 -2
- {linkml-1.7.11rc1.dist-info → linkml-1.8.0.dist-info}/RECORD +21 -21
- {linkml-1.7.11rc1.dist-info → linkml-1.8.0.dist-info}/LICENSE +0 -0
- {linkml-1.7.11rc1.dist-info → linkml-1.8.0.dist-info}/WHEEL +0 -0
- {linkml-1.7.11rc1.dist-info → linkml-1.8.0.dist-info}/entry_points.txt +0 -0
@@ -99,20 +99,6 @@ URI: {{ gen.uri_link(element) }}
|
|
99
99
|
|
100
100
|
{% include "common_metadata.md.jinja2" %}
|
101
101
|
|
102
|
-
|
103
|
-
{% if schemaview.get_mappings(element.name).items() -%}
|
104
|
-
## Mappings
|
105
|
-
|
106
|
-
| Mapping Type | Mapped Value |
|
107
|
-
| --- | --- |
|
108
|
-
{% for m, mt in schemaview.get_mappings(element.name).items() -%}
|
109
|
-
{% if mt|length > 0 -%}
|
110
|
-
| {{ m }} | {{ mt|join(', ') }} |
|
111
|
-
{% endif -%}
|
112
|
-
{% endfor %}
|
113
|
-
|
114
|
-
{% endif -%}
|
115
|
-
|
116
102
|
{% if gen.example_object_blobs(element.name) -%}
|
117
103
|
## Examples
|
118
104
|
{% for name, blob in gen.example_object_blobs(element.name) -%}
|
@@ -75,4 +75,17 @@ Instances of this class *should* have identifiers with one of the following pref
|
|
75
75
|
{% if element.imported_from %}
|
76
76
|
* imported from: {{ element.imported_from }}
|
77
77
|
{% endif %}
|
78
|
-
{% endif %}
|
78
|
+
{% endif %}
|
79
|
+
|
80
|
+
{% if schemaview.get_mappings(element.name).items() -%}
|
81
|
+
## Mappings
|
82
|
+
|
83
|
+
| Mapping Type | Mapped Value |
|
84
|
+
| --- | --- |
|
85
|
+
{% for m, mt in schemaview.get_mappings(element.name).items() -%}
|
86
|
+
{% if mt|length > 0 -%}
|
87
|
+
| {{ m }} | {{ mt|join(', ') }} |
|
88
|
+
{% endif -%}
|
89
|
+
{% endfor %}
|
90
|
+
|
91
|
+
{% endif -%}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import os
|
2
2
|
from dataclasses import dataclass
|
3
3
|
from enum import Enum
|
4
|
-
from typing import List, Optional, Union
|
4
|
+
from typing import List, Optional, Set, Union
|
5
5
|
|
6
6
|
import click
|
7
7
|
import pydantic
|
@@ -163,6 +163,7 @@ class ERDiagramGenerator(Generator):
|
|
163
163
|
class_names: List[Union[str, ClassDefinitionName]],
|
164
164
|
follow_references=False,
|
165
165
|
max_hops: int = None,
|
166
|
+
include_upstream: bool = False,
|
166
167
|
) -> MERMAID_SERIALIZATION:
|
167
168
|
"""
|
168
169
|
Serialize a list of classes as an ER Diagram.
|
@@ -195,6 +196,15 @@ class ERDiagramGenerator(Generator):
|
|
195
196
|
if follow_references or sv.is_inlined(slot):
|
196
197
|
if rng not in visited:
|
197
198
|
stack.append((rng, depth + 1))
|
199
|
+
|
200
|
+
# Now Add upstream classes if needed
|
201
|
+
if include_upstream:
|
202
|
+
for sn in sv.all_slots():
|
203
|
+
slot = sv.schema.slots.get(sn)
|
204
|
+
if slot and slot.range in set(class_names):
|
205
|
+
for cl in sv.all_classes():
|
206
|
+
if slot.name in sv.get_class(cl).slots and cl not in visited:
|
207
|
+
self.add_upstream_class(cl, set(class_names), diagram)
|
198
208
|
return self.serialize_diagram(diagram)
|
199
209
|
|
200
210
|
def serialize_diagram(self, diagram: ERDiagram) -> str:
|
@@ -210,6 +220,15 @@ class ERDiagramGenerator(Generator):
|
|
210
220
|
else:
|
211
221
|
return er
|
212
222
|
|
223
|
+
def add_upstream_class(self, class_name: ClassDefinitionName, targets: Set[str], diagram: ERDiagram) -> None:
|
224
|
+
sv = self.schemaview
|
225
|
+
cls = sv.get_class(class_name)
|
226
|
+
entity = Entity(name=camelcase(cls.name))
|
227
|
+
diagram.entities.append(entity)
|
228
|
+
for slot in sv.class_induced_slots(class_name):
|
229
|
+
if slot.range in targets:
|
230
|
+
self.add_relationship(entity, slot, diagram)
|
231
|
+
|
213
232
|
def add_class(self, class_name: ClassDefinitionName, diagram: ERDiagram) -> None:
|
214
233
|
"""
|
215
234
|
Add a class to the ER Diagram.
|
@@ -291,9 +310,17 @@ class ERDiagramGenerator(Generator):
|
|
291
310
|
)
|
292
311
|
@click.option("--max-hops", default=None, type=click.INT, help="Maximum number of hops")
|
293
312
|
@click.option("--classes", "-c", multiple=True, help="List of classes to serialize")
|
313
|
+
@click.option("--include-upstream", is_flag=True, help="Include upstream classes")
|
294
314
|
@click.version_option(__version__, "-V", "--version")
|
295
315
|
@click.command()
|
296
|
-
def cli(
|
316
|
+
def cli(
|
317
|
+
yamlfile,
|
318
|
+
classes: List[str],
|
319
|
+
max_hops: Optional[int],
|
320
|
+
follow_references: bool,
|
321
|
+
include_upstream: bool = False,
|
322
|
+
**args,
|
323
|
+
):
|
297
324
|
"""Generate a mermaid ER diagram from a schema.
|
298
325
|
|
299
326
|
By default, all entities traversable from the tree_root are included. If no tree_root is
|
@@ -306,7 +333,14 @@ def cli(yamlfile, classes: List[str], max_hops: Optional[int], follow_references
|
|
306
333
|
**args,
|
307
334
|
)
|
308
335
|
if classes:
|
309
|
-
print(
|
336
|
+
print(
|
337
|
+
gen.serialize_classes(
|
338
|
+
classes,
|
339
|
+
follow_references=follow_references,
|
340
|
+
max_hops=max_hops,
|
341
|
+
include_upstream=include_upstream,
|
342
|
+
)
|
343
|
+
)
|
310
344
|
else:
|
311
345
|
print(gen.serialize())
|
312
346
|
|
linkml/generators/golanggen.py
CHANGED
@@ -5,12 +5,7 @@ from typing import List, Optional
|
|
5
5
|
|
6
6
|
import click
|
7
7
|
from jinja2 import Template
|
8
|
-
from linkml_runtime.linkml_model.meta import
|
9
|
-
ClassDefinition,
|
10
|
-
ClassDefinitionName,
|
11
|
-
Element,
|
12
|
-
SlotDefinition,
|
13
|
-
)
|
8
|
+
from linkml_runtime.linkml_model.meta import ClassDefinition, ClassDefinitionName, Element, SlotDefinition
|
14
9
|
from linkml_runtime.utils.formatutils import camelcase, underscore
|
15
10
|
|
16
11
|
from linkml._version import __version__
|
linkml/generators/plantumlgen.py
CHANGED
@@ -12,11 +12,7 @@ from typing import Callable, List, Optional, Set, cast
|
|
12
12
|
|
13
13
|
import click
|
14
14
|
import requests
|
15
|
-
from linkml_runtime.linkml_model.meta import
|
16
|
-
ClassDefinition,
|
17
|
-
ClassDefinitionName,
|
18
|
-
SlotDefinition,
|
19
|
-
)
|
15
|
+
from linkml_runtime.linkml_model.meta import ClassDefinition, ClassDefinitionName, SlotDefinition
|
20
16
|
from linkml_runtime.utils.formatutils import camelcase, underscore
|
21
17
|
|
22
18
|
from linkml import REQUESTS_TIMEOUT
|
@@ -1,18 +1,7 @@
|
|
1
1
|
import sys
|
2
2
|
from abc import ABC, abstractmethod
|
3
3
|
from enum import Enum
|
4
|
-
from typing import
|
5
|
-
Any,
|
6
|
-
ClassVar,
|
7
|
-
Generic,
|
8
|
-
Iterable,
|
9
|
-
List,
|
10
|
-
Optional,
|
11
|
-
Type,
|
12
|
-
TypeVar,
|
13
|
-
Union,
|
14
|
-
get_args,
|
15
|
-
)
|
4
|
+
from typing import Any, ClassVar, Generic, Iterable, List, Optional, Type, TypeVar, Union, get_args
|
16
5
|
|
17
6
|
from linkml_runtime.linkml_model import Element
|
18
7
|
from linkml_runtime.linkml_model.meta import ArrayExpression, DimensionExpression
|
@@ -25,10 +25,7 @@ from linkml_runtime.utils.schemaview import SchemaView
|
|
25
25
|
from pydantic.version import VERSION as PYDANTIC_VERSION
|
26
26
|
|
27
27
|
from linkml._version import __version__
|
28
|
-
from linkml.generators.common.type_designators import
|
29
|
-
get_accepted_type_designator_values,
|
30
|
-
get_type_designator_value,
|
31
|
-
)
|
28
|
+
from linkml.generators.common.type_designators import get_accepted_type_designator_values, get_type_designator_value
|
32
29
|
from linkml.generators.oocodegen import OOCodeGenerator
|
33
30
|
from linkml.generators.pydanticgen import includes
|
34
31
|
from linkml.generators.pydanticgen.array import ArrayRangeGenerator, ArrayRepresentation
|
linkml/generators/pythongen.py
CHANGED
@@ -23,14 +23,7 @@ from linkml_runtime.linkml_model.meta import (
|
|
23
23
|
TypeDefinition,
|
24
24
|
)
|
25
25
|
from linkml_runtime.utils.compile_python import compile_python
|
26
|
-
from linkml_runtime.utils.formatutils import
|
27
|
-
be,
|
28
|
-
camelcase,
|
29
|
-
sfx,
|
30
|
-
split_col,
|
31
|
-
underscore,
|
32
|
-
wrapped_annotation,
|
33
|
-
)
|
26
|
+
from linkml_runtime.utils.formatutils import be, camelcase, sfx, split_col, underscore, wrapped_annotation
|
34
27
|
from linkml_runtime.utils.metamodelcore import builtinnames
|
35
28
|
from rdflib import URIRef
|
36
29
|
|
linkml/generators/shaclgen.py
CHANGED
@@ -1,15 +1,17 @@
|
|
1
1
|
import logging
|
2
2
|
import os
|
3
3
|
from dataclasses import dataclass
|
4
|
-
from typing import Callable
|
4
|
+
from typing import Callable, List
|
5
5
|
|
6
6
|
import click
|
7
|
+
from jsonasobj2 import JsonObj, as_dict
|
7
8
|
from linkml_runtime.linkml_model.meta import ElementName
|
8
9
|
from linkml_runtime.utils.formatutils import underscore
|
9
10
|
from linkml_runtime.utils.schemaview import SchemaView
|
11
|
+
from linkml_runtime.utils.yamlutils import TypedNode, extended_float, extended_int, extended_str
|
10
12
|
from rdflib import BNode, Graph, Literal, URIRef
|
11
13
|
from rdflib.collection import Collection
|
12
|
-
from rdflib.namespace import RDF, SH
|
14
|
+
from rdflib.namespace import RDF, SH, XSD
|
13
15
|
|
14
16
|
from linkml._version import __version__
|
15
17
|
from linkml.generators.shacl.ifabsent_processor import IfAbsentProcessor
|
@@ -24,6 +26,8 @@ class ShaclGenerator(Generator):
|
|
24
26
|
"""True means add 'sh:closed=true' to all shapes, except of mixin shapes and shapes, that have parents"""
|
25
27
|
suffix: str = None
|
26
28
|
"""parameterized suffix to be appended. No suffix per default."""
|
29
|
+
include_annotations: bool = False
|
30
|
+
"""True means include all class / slot / type annotations in generated Node or Property shapes"""
|
27
31
|
generatorname = os.path.basename(__file__)
|
28
32
|
generatorversion = "0.0.1"
|
29
33
|
valid_formats = ["ttl"]
|
@@ -83,6 +87,8 @@ class ShaclGenerator(Generator):
|
|
83
87
|
list_node = BNode()
|
84
88
|
Collection(g, list_node, [RDF.type])
|
85
89
|
shape_pv(SH.ignoredProperties, list_node)
|
90
|
+
if c.annotations and self.include_annotations:
|
91
|
+
self._add_annotations(shape_pv, c)
|
86
92
|
order = 0
|
87
93
|
for s in sv.class_induced_slots(c.name):
|
88
94
|
# fixed in linkml-runtime 1.1.3
|
@@ -116,6 +122,12 @@ class ShaclGenerator(Generator):
|
|
116
122
|
|
117
123
|
all_classes = sv.all_classes()
|
118
124
|
if s.any_of:
|
125
|
+
# It is not allowed to use any of and equals_string or equals_string_in in one
|
126
|
+
# slot definition, as both are mapped to sh:in in SHACL
|
127
|
+
if s.equals_string or s.equals_string_in:
|
128
|
+
error = "'equals_string'/'equals_string_in' and 'any_of' are mutually exclusive"
|
129
|
+
raise ValueError(f'{TypedNode.yaml_loc(s, suffix="")} {error}')
|
130
|
+
|
119
131
|
or_node = BNode()
|
120
132
|
prop_pv(SH["or"], or_node)
|
121
133
|
range_list = []
|
@@ -158,10 +170,17 @@ class ShaclGenerator(Generator):
|
|
158
170
|
add_simple_data_type(st_node_pv, r)
|
159
171
|
range_list.append(st_node)
|
160
172
|
Collection(g, or_node, range_list)
|
161
|
-
|
162
173
|
else:
|
163
174
|
prop_pv_literal(SH.hasValue, s.equals_number)
|
164
175
|
r = s.range
|
176
|
+
if s.equals_string or s.equals_string_in:
|
177
|
+
# Check if range is "string" as this is mandatory for "equals_string" and "equals_string_in"
|
178
|
+
if r != "string":
|
179
|
+
raise ValueError(
|
180
|
+
f"slot: \"{slot_uri}\" - 'equals_string' and 'equals_string_in'"
|
181
|
+
f" require range 'string' and not '{r}'"
|
182
|
+
)
|
183
|
+
|
165
184
|
if r in all_classes:
|
166
185
|
self._add_class(prop_pv, r)
|
167
186
|
if sv.get_identifier_slot(r) is not None:
|
@@ -176,6 +195,14 @@ class ShaclGenerator(Generator):
|
|
176
195
|
add_simple_data_type(prop_pv, r)
|
177
196
|
if s.pattern:
|
178
197
|
prop_pv(SH.pattern, Literal(s.pattern))
|
198
|
+
if s.annotations and self.include_annotations:
|
199
|
+
self._add_annotations(prop_pv, s)
|
200
|
+
if s.equals_string:
|
201
|
+
# Map equal_string and equal_string_in to sh:in
|
202
|
+
self._and_equals_string(g, prop_pv, [s.equals_string])
|
203
|
+
if s.equals_string_in:
|
204
|
+
# Map equal_string and equal_string_in to sh:in
|
205
|
+
self._and_equals_string(g, prop_pv, s.equals_string_in)
|
179
206
|
|
180
207
|
ifabsent_processor.process_slot(prop_pv, s, class_uri)
|
181
208
|
|
@@ -206,9 +233,68 @@ class ShaclGenerator(Generator):
|
|
206
233
|
rt = sv.get_type(r)
|
207
234
|
if rt.uri:
|
208
235
|
func(SH.datatype, URIRef(sv.get_uri(rt, expand=True)))
|
236
|
+
if rt.pattern:
|
237
|
+
func(SH.pattern, Literal(rt.pattern))
|
238
|
+
if rt.annotations and self.include_annotations:
|
239
|
+
self._add_annotations(func, rt)
|
209
240
|
else:
|
210
241
|
logging.error(f"No URI for type {rt.name}")
|
211
242
|
|
243
|
+
def _and_equals_string(self, g: Graph, func: Callable, values: List) -> None:
|
244
|
+
pv_node = BNode()
|
245
|
+
Collection(
|
246
|
+
g,
|
247
|
+
pv_node,
|
248
|
+
[Literal(v) for v in values],
|
249
|
+
)
|
250
|
+
func(SH["in"], pv_node)
|
251
|
+
|
252
|
+
def _add_annotations(self, func: Callable, item) -> None:
|
253
|
+
# TODO: migrate some of this logic to SchemaView
|
254
|
+
sv = self.schemaview
|
255
|
+
annotations = item.annotations
|
256
|
+
# item could be a class, slot or type
|
257
|
+
# annotation type could be dict (on types) or JsonObj (on slots)
|
258
|
+
if type(annotations) == JsonObj:
|
259
|
+
annotations = as_dict(annotations)
|
260
|
+
for a in annotations.values():
|
261
|
+
# If ':' is in the tag, treat it as a CURIE, otherwise string Literal
|
262
|
+
if ":" in a["tag"]:
|
263
|
+
N_predicate = URIRef(sv.expand_curie(a["tag"]))
|
264
|
+
else:
|
265
|
+
N_predicate = Literal(a["tag"], datatype=XSD.string)
|
266
|
+
# If the value is a string and ':' is in the value, treat it as a CURIE,
|
267
|
+
# otherwise treat as Literal with derived XSD datatype
|
268
|
+
if type(a["value"]) == extended_str and ":" in a["value"]:
|
269
|
+
N_object = URIRef(sv.expand_curie(a["value"]))
|
270
|
+
else:
|
271
|
+
N_object = Literal(a["value"], datatype=self._getXSDtype(a["value"]))
|
272
|
+
|
273
|
+
func(N_predicate, N_object)
|
274
|
+
|
275
|
+
def _getXSDtype(self, value):
|
276
|
+
value_type = type(value)
|
277
|
+
if value_type == bool:
|
278
|
+
return XSD.boolean
|
279
|
+
elif value_type == extended_str:
|
280
|
+
return XSD.string
|
281
|
+
elif value_type == extended_int:
|
282
|
+
return XSD.integer
|
283
|
+
elif value_type == extended_float:
|
284
|
+
# TODO: distinguish between xsd:decimal and xsd:double?
|
285
|
+
return XSD.decimal
|
286
|
+
else:
|
287
|
+
return None
|
288
|
+
|
289
|
+
def _and_equals_string(self, g: Graph, func: Callable, values: List) -> None:
|
290
|
+
pv_node = BNode()
|
291
|
+
Collection(
|
292
|
+
g,
|
293
|
+
pv_node,
|
294
|
+
[Literal(v) for v in values],
|
295
|
+
)
|
296
|
+
func(SH["in"], pv_node)
|
297
|
+
|
212
298
|
|
213
299
|
def add_simple_data_type(func: Callable, r: ElementName) -> None:
|
214
300
|
for datatype in list(ShaclDataType):
|
@@ -231,6 +317,12 @@ def add_simple_data_type(func: Callable, r: ElementName) -> None:
|
|
231
317
|
show_default=True,
|
232
318
|
help="Use --suffix to append given string to SHACL class name (e. g. --suffix Shape: Person becomes PersonShape).",
|
233
319
|
)
|
320
|
+
@click.option(
|
321
|
+
"--include-annotations/--exclude-annotations",
|
322
|
+
default=False,
|
323
|
+
show_default=True,
|
324
|
+
help="Use --include-annotations to include annotations of slots, types, and classes in the generated SHACL shapes.",
|
325
|
+
)
|
234
326
|
@click.version_option(__version__, "-V", "--version")
|
235
327
|
def cli(yamlfile, **args):
|
236
328
|
"""Generate SHACL turtle from a LinkML model"""
|
@@ -7,12 +7,7 @@ from typing import List, Optional, Union
|
|
7
7
|
|
8
8
|
import click
|
9
9
|
from jinja2 import Template
|
10
|
-
from linkml_runtime.linkml_model import
|
11
|
-
Annotation,
|
12
|
-
ClassDefinition,
|
13
|
-
ClassDefinitionName,
|
14
|
-
SchemaDefinition,
|
15
|
-
)
|
10
|
+
from linkml_runtime.linkml_model import Annotation, ClassDefinition, ClassDefinitionName, SchemaDefinition
|
16
11
|
from linkml_runtime.utils.compile_python import compile_python
|
17
12
|
from linkml_runtime.utils.formatutils import camelcase, underscore
|
18
13
|
from linkml_runtime.utils.schemaview import SchemaView
|
@@ -21,10 +16,7 @@ from sqlalchemy import Enum
|
|
21
16
|
from linkml._version import __version__
|
22
17
|
from linkml.generators.pydanticgen import PydanticGenerator
|
23
18
|
from linkml.generators.pythongen import PythonGenerator
|
24
|
-
from linkml.generators.sqlalchemy import
|
25
|
-
sqlalchemy_declarative_template_str,
|
26
|
-
sqlalchemy_imperative_template_str,
|
27
|
-
)
|
19
|
+
from linkml.generators.sqlalchemy import sqlalchemy_declarative_template_str, sqlalchemy_imperative_template_str
|
28
20
|
from linkml.generators.sqltablegen import SQLTableGenerator
|
29
21
|
from linkml.transformers.relmodel_transformer import ForeignKeyPolicy, RelationalModelTransformer
|
30
22
|
from linkml.utils.generator import Generator, shared_arguments
|
linkml/linter/rules.py
CHANGED
@@ -3,12 +3,7 @@ from abc import ABC, abstractmethod
|
|
3
3
|
from functools import lru_cache
|
4
4
|
from typing import Callable, Iterable, List
|
5
5
|
|
6
|
-
from linkml_runtime.linkml_model import
|
7
|
-
ClassDefinition,
|
8
|
-
ClassDefinitionName,
|
9
|
-
Element,
|
10
|
-
SlotDefinition,
|
11
|
-
)
|
6
|
+
from linkml_runtime.linkml_model import ClassDefinition, ClassDefinitionName, Element, SlotDefinition
|
12
7
|
from linkml_runtime.utils.schemaview import SchemaView
|
13
8
|
from prefixmaps.io.parser import load_multi_context
|
14
9
|
|
@@ -32,6 +32,7 @@ from linkml.transformers.model_transformer import ModelTransformer
|
|
32
32
|
from linkml.utils import logictools
|
33
33
|
|
34
34
|
HERITABLE_METASLOT = [
|
35
|
+
# "multivalued",
|
35
36
|
"range",
|
36
37
|
"range_expression",
|
37
38
|
"minimum_value",
|
@@ -102,7 +103,7 @@ class LogicalModelTransformer(ModelTransformer):
|
|
102
103
|
>>> _ = sb.add_class("Person", slots={"age": {"range": "integer"}}, is_a="Thing")
|
103
104
|
>>> _ = sb.add_class("Organization", slots={"category": {"range": "OrganizationType"}}, is_a="Thing")
|
104
105
|
>>> _ = sb.add_enum("OrganizationType", ["commercial", "non-profit"])
|
105
|
-
>>> from linkml.transformers import LogicalModelTransformer
|
106
|
+
>>> from linkml.transformers.logical_model_transformer import LogicalModelTransformer
|
106
107
|
>>> tr = LogicalModelTransformer()
|
107
108
|
>>> tr.set_schema(sb.schema)
|
108
109
|
>>> flat_schema = tr.transform()
|
@@ -153,8 +154,8 @@ class LogicalModelTransformer(ModelTransformer):
|
|
153
154
|
attributes:
|
154
155
|
entities:
|
155
156
|
name: entities
|
156
|
-
multivalued: true
|
157
157
|
range: Thing
|
158
|
+
multivalued: true
|
158
159
|
|
159
160
|
...
|
160
161
|
|
@@ -443,6 +444,9 @@ class LogicalModelTransformer(ModelTransformer):
|
|
443
444
|
logger.debug(f"Simplified member of: {x}")
|
444
445
|
simplified_att = self._from_logical_expression(x)
|
445
446
|
for k, v in simplified_att.__dict__.items():
|
447
|
+
if v is None or v is False:
|
448
|
+
if k in ["multivalued"]:
|
449
|
+
continue
|
446
450
|
setattr(att, k, v)
|
447
451
|
|
448
452
|
def _simplify_member_ofs(self, expr: logictools.Expression):
|
linkml/utils/schemaloader.py
CHANGED
@@ -235,6 +235,9 @@ class SchemaLoader:
|
|
235
235
|
):
|
236
236
|
self.raise_value_error(f"slot: {slot.name} - unrecognized range ({slot.range})", slot.range)
|
237
237
|
|
238
|
+
# check constraints for usage of equals_string and equals_string_in
|
239
|
+
self._check_equals_string(slot)
|
240
|
+
|
238
241
|
# apply to --> mixins
|
239
242
|
for cls in self.schema.classes.values():
|
240
243
|
for apply_to_cls in cls.apply_to:
|
@@ -372,6 +375,9 @@ class SchemaLoader:
|
|
372
375
|
):
|
373
376
|
self.raise_value_error(f"slot: {slot.name} - unrecognized range ({slot.range})", slot.range)
|
374
377
|
|
378
|
+
# check constraints for usage of equals_string and equals_string_in
|
379
|
+
self._check_equals_string(slot)
|
380
|
+
|
375
381
|
# Massage classes, propagating class slots entries domain back to the target slots
|
376
382
|
for cls in self.schema.classes.values():
|
377
383
|
if not isinstance(cls, ClassDefinition):
|
@@ -964,3 +970,24 @@ class SchemaLoader:
|
|
964
970
|
return rval
|
965
971
|
else:
|
966
972
|
return None
|
973
|
+
|
974
|
+
def _check_equals_string(self, slot: SlotDefinition):
|
975
|
+
if slot.equals_string or slot.equals_string_in:
|
976
|
+
# Range "string" mandatory for "equals_string" and "equals_string_in"
|
977
|
+
range = slot.range
|
978
|
+
if not range:
|
979
|
+
# range is not defined --> check default range
|
980
|
+
range = self.schema.default_range
|
981
|
+
if range != "string":
|
982
|
+
self.raise_value_error(
|
983
|
+
f"slot: {slot.name} - 'equals_string' and 'equals_string_in' requires range "
|
984
|
+
f"'string' and not range '{range}'",
|
985
|
+
slot.range,
|
986
|
+
)
|
987
|
+
if slot.any_of:
|
988
|
+
# It is not allowed to use any of and equals_string or equals_string_in in one slot definition,
|
989
|
+
# as both are mapped to sh:in in SHACL
|
990
|
+
self.raise_value_error(
|
991
|
+
f"slot: {slot.name} - 'equals_string'/'equals_string_in' and 'any_of' are mutually exclusive",
|
992
|
+
slot.name,
|
993
|
+
)
|
linkml/utils/schemasynopsis.py
CHANGED
@@ -21,15 +21,7 @@ from linkml_runtime.utils.metamodelcore import empty_dict
|
|
21
21
|
from linkml_runtime.utils.yamlutils import TypedNode
|
22
22
|
from rdflib import URIRef
|
23
23
|
|
24
|
-
from linkml.utils.typereferences import
|
25
|
-
ClassType,
|
26
|
-
EnumType,
|
27
|
-
References,
|
28
|
-
RefType,
|
29
|
-
SlotType,
|
30
|
-
SubsetType,
|
31
|
-
TypeType,
|
32
|
-
)
|
24
|
+
from linkml.utils.typereferences import ClassType, EnumType, References, RefType, SlotType, SubsetType, TypeType
|
33
25
|
|
34
26
|
|
35
27
|
def empty_references() -> field:
|
linkml/validator/__init__.py
CHANGED
@@ -11,9 +11,7 @@ from typing import Any, Optional, Union
|
|
11
11
|
from linkml_runtime.linkml_model import SchemaDefinition
|
12
12
|
from linkml_runtime.loaders import yaml_loader
|
13
13
|
|
14
|
-
from linkml.validator.loaders import
|
15
|
-
default_loader_for_file,
|
16
|
-
)
|
14
|
+
from linkml.validator.loaders import default_loader_for_file
|
17
15
|
from linkml.validator.plugins import JsonschemaValidationPlugin
|
18
16
|
from linkml.validator.report import ValidationReport
|
19
17
|
from linkml.validator.validator import Validator
|
@@ -4,9 +4,7 @@ on data instances. Instances of these classes should be provided when constructi
|
|
4
4
|
:class:`linkml.validator.Validator` instance.
|
5
5
|
"""
|
6
6
|
|
7
|
-
from linkml.validator.plugins.jsonschema_validation_plugin import
|
8
|
-
JsonschemaValidationPlugin,
|
9
|
-
)
|
7
|
+
from linkml.validator.plugins.jsonschema_validation_plugin import JsonschemaValidationPlugin
|
10
8
|
from linkml.validator.plugins.pydantic_validation_plugin import PydanticValidationPlugin
|
11
9
|
from linkml.validator.plugins.recommended_slots_plugin import RecommendedSlotsPlugin
|
12
10
|
from linkml.validator.plugins.validation_plugin import ValidationPlugin
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: linkml
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.8.0
|
4
4
|
Summary: Linked Open Data Modeling Language
|
5
5
|
Home-page: https://linkml.io/linkml/
|
6
6
|
Keywords: schema,linked data,data modeling,rdf,owl,biolink
|
@@ -36,7 +36,7 @@ Requires-Dist: jinja2 (>=3.1.0)
|
|
36
36
|
Requires-Dist: jsonasobj2 (>=1.0.3,<2.0.0)
|
37
37
|
Requires-Dist: jsonschema[format] (>=4.0.0)
|
38
38
|
Requires-Dist: linkml-dataops
|
39
|
-
Requires-Dist: linkml-runtime (
|
39
|
+
Requires-Dist: linkml-runtime (==1.8.0)
|
40
40
|
Requires-Dist: openpyxl
|
41
41
|
Requires-Dist: parse
|
42
42
|
Requires-Dist: prefixcommons (>=0.1.7)
|
@@ -6,9 +6,9 @@ linkml/generators/__init__.py,sha256=dQ2EUKy_MctEVEzbC3XzEJL5YmYwjYfsa44mG2zKn7g
|
|
6
6
|
linkml/generators/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
7
|
linkml/generators/common/type_designators.py,sha256=lgVcIRJJ-yCvVGeP9U_gQZpm77UmJBQo9Bh3lGJITno,1956
|
8
8
|
linkml/generators/csvgen.py,sha256=R8VQdWXj43LNf5isJElo3MStsiNBSSF4ywIRS1c3_v0,3243
|
9
|
-
linkml/generators/docgen/class.md.jinja2,sha256
|
9
|
+
linkml/generators/docgen/class.md.jinja2,sha256=-JmjYHgYOaaBYd5r-Tr5dkk0CLM_lX0kHdocPQtRsjU,3504
|
10
10
|
linkml/generators/docgen/class_diagram.md.jinja2,sha256=gzskx4hOpU_s6BqOXdYZ9DwKxuClnsEgDzPurm30PeY,3469
|
11
|
-
linkml/generators/docgen/common_metadata.md.jinja2,sha256=
|
11
|
+
linkml/generators/docgen/common_metadata.md.jinja2,sha256=gy9J8rghBfKDKimwtHj_XuHY4PJRRYHLXVlBHqWrUzU,1604
|
12
12
|
linkml/generators/docgen/enum.md.jinja2,sha256=mXnUrRkleY2bOTEyAZ5c4pcUnqhs6BNa8a-4LVve-eo,1014
|
13
13
|
linkml/generators/docgen/index.md.jinja2,sha256=wXUYTmayPLFltC0vbGE_Mf6m3GkkWav7FOEjCvEpHp4,1466
|
14
14
|
linkml/generators/docgen/index.tex.jinja2,sha256=Go_EA-_N4JUpbOYbk3OY11mz5yV70VF2l2sMtgIPWw4,501
|
@@ -18,9 +18,9 @@ linkml/generators/docgen/subset.md.jinja2,sha256=EPln_fjlhlkmwEGEp2iPX-9Xm2vVodP
|
|
18
18
|
linkml/generators/docgen/type.md.jinja2,sha256=QmCMJZrFwP33eHkggBVtypbyrxTb-XZn9vHOYojVaYk,635
|
19
19
|
linkml/generators/docgen.py,sha256=QECBmOAiVr-DsUYOLmqapESSB_CiNoiHt_3vjiZCrUs,36396
|
20
20
|
linkml/generators/dotgen.py,sha256=kzp1EYtF8bBqOuycJokDmsvHVDVkkW-J-6-MiUhwJH0,5013
|
21
|
-
linkml/generators/erdiagramgen.py,sha256=
|
21
|
+
linkml/generators/erdiagramgen.py,sha256=7W010ngoHrk-BjhCEmpHyySPImLXIOTEBGO70hOUOH8,11341
|
22
22
|
linkml/generators/excelgen.py,sha256=3ILAeIHeYngNpPf3Ad7CXoHOLQ9KSiYcX5HdwHhQeQE,7696
|
23
|
-
linkml/generators/golanggen.py,sha256=
|
23
|
+
linkml/generators/golanggen.py,sha256=rDiDFyZBZ6_JygCEdpbKrohQCScvBlWi17AcoR6Qi3g,5790
|
24
24
|
linkml/generators/golrgen.py,sha256=OUBYRWicP7G7lrPu1VrxumbVpx3CBJal-o2imyeP05M,3437
|
25
25
|
linkml/generators/graphqlgen.py,sha256=ClJdD6fVjBI8rsIJ3DIuwdQScAJG0gYYKwS8SrFqVZk,2149
|
26
26
|
linkml/generators/javagen/example_template.java.jinja2,sha256=ec4CVTv_0zS7V5Y-1E6H4lRraya10gfX7BEMBlu38X4,444
|
@@ -35,16 +35,16 @@ linkml/generators/markdowngen.py,sha256=mwydWkrF-WzsTiKwJqqe9NUya5VaTj7ywKqodP85
|
|
35
35
|
linkml/generators/namespacegen.py,sha256=vVcIyM0zlKd7XRvtdzwTwHjG4Pg49801gy4FUmjJlqQ,6450
|
36
36
|
linkml/generators/oocodegen.py,sha256=r73QI08ajbTZTobc9OIG6BMWZft3zdu76vKVR33pyYg,7774
|
37
37
|
linkml/generators/owlgen.py,sha256=NHIcL1d79WoeqfiZRj6kRk5aTXcQ6JDNXV_VAtH6Vt0,57554
|
38
|
-
linkml/generators/plantumlgen.py,sha256=
|
38
|
+
linkml/generators/plantumlgen.py,sha256=2e4ejw0B72Sl_-mipgpKz743LVMs0kRZc8E0MK7gxFY,14919
|
39
39
|
linkml/generators/prefixmapgen.py,sha256=w8gMCFOI0DmZsNvo9IkbhOqVWqqWYEN6SXnAP3BgFSk,4240
|
40
40
|
linkml/generators/projectgen.py,sha256=OuT_AneoZFNMCn50GllfZafadUHt50u61JcftM2eed4,9750
|
41
41
|
linkml/generators/protogen.py,sha256=i4sEhNdAiFFP12fwfRdype1MX8yU-E5fF7XzkcpBCd0,2512
|
42
42
|
linkml/generators/pydanticgen/__init__.py,sha256=uKGaaQSaeKqinHImXGFE448i-t8Oi0No8suIO76sep8,629
|
43
|
-
linkml/generators/pydanticgen/array.py,sha256=
|
43
|
+
linkml/generators/pydanticgen/array.py,sha256=EYqAkT2_wE82kZ-niUWAC5U3V8EvjjyfSH7tz5GYKWo,19461
|
44
44
|
linkml/generators/pydanticgen/black.py,sha256=BaJ7b-kMUbIN_cKRT3yCaMEbFwxzj1_U7w4fKQnkL44,723
|
45
45
|
linkml/generators/pydanticgen/build.py,sha256=Ia8qy4C16b-KqO_fw4tGQW_Eo4grCVyX7RsuJ3uRTtk,2681
|
46
46
|
linkml/generators/pydanticgen/includes.py,sha256=PIVbACrtqQS6LFrXqQsJC6dQUcGBM3uY4E4qLQWJrnk,998
|
47
|
-
linkml/generators/pydanticgen/pydanticgen.py,sha256=
|
47
|
+
linkml/generators/pydanticgen/pydanticgen.py,sha256=WZxFfLvXhHXVtDQpLjMf63eoBMUxcW0oEMS14jbDOWo,34458
|
48
48
|
linkml/generators/pydanticgen/template.py,sha256=HESLY1Rd7N_e92dqrh_fif_yp3oDl0n1UAghklMyphA,20982
|
49
49
|
linkml/generators/pydanticgen/templates/attribute.py.jinja,sha256=S_T-M7n_eeM3LW5gQUuTPH1-Oc1CEtL7Bve7qAFouYQ,688
|
50
50
|
linkml/generators/pydanticgen/templates/base_model.py.jinja,sha256=48y64MnC9rjNSV-nKLMeDuHN4gm15UsInhnKxh65zoM,834
|
@@ -55,18 +55,18 @@ linkml/generators/pydanticgen/templates/footer.py.jinja,sha256=WuWGJjkWDQcEPL2bG
|
|
55
55
|
linkml/generators/pydanticgen/templates/imports.py.jinja,sha256=d1XFna2eOpkH8cgJML3vXwqGcocczvOcrbg6jjd4kP0,945
|
56
56
|
linkml/generators/pydanticgen/templates/module.py.jinja,sha256=nymjtSX4jqV9deSsXrsh1HWR90ygECHE4CV9MCyNrTY,615
|
57
57
|
linkml/generators/pydanticgen/templates/validator.py.jinja,sha256=Yo4dubQal-HwEoJKztQkLYM5qCz1I8na2oaDlXuEpwU,532
|
58
|
-
linkml/generators/pythongen.py,sha256=
|
58
|
+
linkml/generators/pythongen.py,sha256=CiLmc964siGeJWZC_bOffsqrSnJ5qzn7Eu961C47xgo,52850
|
59
59
|
linkml/generators/rdfgen.py,sha256=eQi3XXjWk6xliTLncQ4G0VYzGCJwCU_FFG-O7tA8DSA,2959
|
60
60
|
linkml/generators/shacl/__init__.py,sha256=O-M-wndKw8rMW-U8X3QCNHal-ErXP6uXZqxiQSa77l4,108
|
61
61
|
linkml/generators/shacl/ifabsent_processor.py,sha256=kV9BGA2ZPXLRfaFuW0o4jpkATvGggvrqpAo9c1UqWNE,2193
|
62
62
|
linkml/generators/shacl/shacl_data_type.py,sha256=BT3C9tdFyBQnuucPN7YQiFAKEa9yuzy-Q26X6dmOXgo,1827
|
63
|
-
linkml/generators/shaclgen.py,sha256=
|
63
|
+
linkml/generators/shaclgen.py,sha256=kgJ3VaVM0_7XBr5cvqgob6wjEarNINZzpC4FK61sC9M,13157
|
64
64
|
linkml/generators/shexgen.py,sha256=MhB1HidCREMCJcDGBqutFQ0gWKKz7aSVw-0s-IHUMm4,9930
|
65
65
|
linkml/generators/sparqlgen.py,sha256=c7x8GFChKWprBx4rToSnu9qN8OleWTCenVUdZ8XSTWM,6138
|
66
66
|
linkml/generators/sqlalchemy/__init__.py,sha256=mb9AC1rIFkSiNZhhG0TAk45ol9PjS1XvsrvCjgfVUpQ,249
|
67
67
|
linkml/generators/sqlalchemy/sqlalchemy_declarative_template.py,sha256=X_Ws1NUBikMI5HuNgEhl_PIeWM-B-c2B0W9KUBH4QTg,2542
|
68
68
|
linkml/generators/sqlalchemy/sqlalchemy_imperative_template.py,sha256=u4ZpponG1h6XROrOHGOf_0H2e6xL1_s8twAOA-gx94A,1622
|
69
|
-
linkml/generators/sqlalchemygen.py,sha256=
|
69
|
+
linkml/generators/sqlalchemygen.py,sha256=boXn_tlkbZ_a5TJYoXvdlKzABNwD-Jn5ld9IAbtzWm4,9286
|
70
70
|
linkml/generators/sqltablegen.py,sha256=87057FJi9EUVPXOjRfHuSqY0lKmepXRNQsose2fGts4,12343
|
71
71
|
linkml/generators/sssomgen.py,sha256=yur3q7so9uwIELWZaZRzkJwNbz_ppBL7IQki9XLIM3k,6879
|
72
72
|
linkml/generators/string_template.md,sha256=kRcfic6entgIaJdpSg6GF3jcjC9wbKsCVM6wVT2qipc,1788
|
@@ -90,11 +90,11 @@ linkml/linter/formatters/markdown_formatter.py,sha256=sumF2MNJYL5oipLwCftCr3AiaC
|
|
90
90
|
linkml/linter/formatters/terminal_formatter.py,sha256=xmNwlRieVCssRt3fpnNP5WWw_YXGmaBsbxFoMWufy5M,2085
|
91
91
|
linkml/linter/formatters/tsv_formatter.py,sha256=1VW-1Tv16mwhIDpHdExYpJJR3z42K5_XK2C-4mmYYdE,871
|
92
92
|
linkml/linter/linter.py,sha256=qfVV-vFT7bUJ2BmmDQteD7Jz8HZ-CNDSvnkyhJ-54H0,5113
|
93
|
-
linkml/linter/rules.py,sha256=
|
93
|
+
linkml/linter/rules.py,sha256=Eg_-lIX1KPsCp3PHdPcBiHmSS5qAVZkHbw5LURfkfXk,11481
|
94
94
|
linkml/reporting/__init__.py,sha256=Jo0V_nyEcnWhMukMW-bqW9dlbgCfaRlWm3CO-XzgU84,92
|
95
95
|
linkml/reporting/model.py,sha256=-10yNfk8wuRC48ZI-akrWvtlJ9a6RYWET2TzlZV3XXo,8622
|
96
96
|
linkml/transformers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
97
|
-
linkml/transformers/logical_model_transformer.py,sha256=
|
97
|
+
linkml/transformers/logical_model_transformer.py,sha256=z-1nyD0d8LYJeAPWRn29p-S4Hgmvjocfcj0VrHTAs2c,26703
|
98
98
|
linkml/transformers/model_transformer.py,sha256=tK_MpRDI-q2qfe8KHT6qJHP8ZruKjYx1FcM-Fnjse-E,678
|
99
99
|
linkml/transformers/relmodel_transformer.py,sha256=aiSI2xaqRz4f0Z_0WFaBP5bknzX0pTnvxsR5mESFysg,18857
|
100
100
|
linkml/transformers/schema_renamer.py,sha256=DYRbgL9j41M9FdbHYLY3u4YIdDM98laD3cv_lHcgWHQ,5275
|
@@ -113,12 +113,12 @@ linkml/utils/mergeutils.py,sha256=QVm2iQB4v_L2rSvPBsPe9C865R03BgV3TzlPoTTTwWQ,90
|
|
113
113
|
linkml/utils/rawloader.py,sha256=nUB8Gfn8yEVwyo6bx0TtB2mBGkilC-fybi0xvQ73Gks,4417
|
114
114
|
linkml/utils/schema_builder.py,sha256=4qhrur8O0xRZnPm7H1h2BZmTkut5R4q-IE_1KKiHy_c,9937
|
115
115
|
linkml/utils/schema_fixer.py,sha256=Uz8M3AOQ_BputJr1f6lbfk1iyvmANUNG80-0B3BQKJ8,16761
|
116
|
-
linkml/utils/schemaloader.py,sha256=
|
117
|
-
linkml/utils/schemasynopsis.py,sha256=
|
116
|
+
linkml/utils/schemaloader.py,sha256=dWZO044p_UcUWnrd8HZ-NsbLXQ9cA6c8HKfNI9-qH2A,47388
|
117
|
+
linkml/utils/schemasynopsis.py,sha256=j7sNt6j-E3rmf-1qEo351Kth2kltt6crQV-dxJAGCUE,18414
|
118
118
|
linkml/utils/sqlutils.py,sha256=Cwoaz44MLcvAGUEBshT4jtn0Z3w7jVOp85zGkd6FTHY,17071
|
119
119
|
linkml/utils/typereferences.py,sha256=8Yfuz9-HAwOPoJLbIcO_sY9zf32hvPRzGeSOzECfMWA,2232
|
120
120
|
linkml/utils/validation.py,sha256=eLw1-d8x3N1V14bSc6H_mJJXo59ryKvvUIBcOJ1dVMw,1438
|
121
|
-
linkml/validator/__init__.py,sha256=
|
121
|
+
linkml/validator/__init__.py,sha256=u0CeorIw50Qqwa60-lIFsJXg-sOdfo90hqvLpyvvwo4,4993
|
122
122
|
linkml/validator/cli.py,sha256=uVe_tbBzsK-4BNboE5zRyohS_dEs5Nl1gbhklrzOEpw,7605
|
123
123
|
linkml/validator/loaders/__init__.py,sha256=FjUqEfBHeT5PEMBEZ9XwpclyQOysr4OCI1M0w_MYPVc,1165
|
124
124
|
linkml/validator/loaders/delimited_file_loader.py,sha256=fdh61ZMPTfH29_DM93f5dY0jLP7KQPNh_QAHZppsdNw,2616
|
@@ -126,7 +126,7 @@ linkml/validator/loaders/json_loader.py,sha256=Qy42naS2clb0fNXbUushckRu5AIX32b3U
|
|
126
126
|
linkml/validator/loaders/loader.py,sha256=YKQXmSZhCymvvb2Dbr4lVCKVDt-lOIayzRD7CWrdsJI,559
|
127
127
|
linkml/validator/loaders/passthrough_loader.py,sha256=fQvBZqzGnpdwpZio4Mbehmsb6ePpzcacHPuR1QWuhFM,525
|
128
128
|
linkml/validator/loaders/yaml_loader.py,sha256=ZsMz-oGDkX9oPEOVcKnFRGhU9q0fKoHcL6BLOkCeB4c,914
|
129
|
-
linkml/validator/plugins/__init__.py,sha256=
|
129
|
+
linkml/validator/plugins/__init__.py,sha256=0ifiDqpcXVy4X7OJFm7FMYi1-6E06avNIIk9R0c6nD8,693
|
130
130
|
linkml/validator/plugins/jsonschema_validation_plugin.py,sha256=c3OjvLR5m83vppsDfkrS9nMXma_ogUxXpZuM_JIUVM4,2634
|
131
131
|
linkml/validator/plugins/pydantic_validation_plugin.py,sha256=C-Vp74bz5oqp5V-iuhXW8p0PPDoFY8NCU5x36Ur5Og4,1985
|
132
132
|
linkml/validator/plugins/recommended_slots_plugin.py,sha256=kOdoYQyye47nLA7BjorVmydS84nGpiVy3MoCbPq1Ymo,2308
|
@@ -143,8 +143,8 @@ linkml/workspaces/datamodel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMp
|
|
143
143
|
linkml/workspaces/datamodel/workspaces.py,sha256=4HdkqweGNfMPqnB1_Onc9DcTfkhoagTRcqruh08nRoI,14905
|
144
144
|
linkml/workspaces/datamodel/workspaces.yaml,sha256=EjVrwPpeRZqJRjuGyyDRxxFzuv55SiLIXPBRUG6HStU,4233
|
145
145
|
linkml/workspaces/example_runner.py,sha256=hDk2RGxRE5-WYNriWknugtbm3Mhn8bFcAcXGMlkYxVk,11705
|
146
|
-
linkml-1.
|
147
|
-
linkml-1.
|
148
|
-
linkml-1.
|
149
|
-
linkml-1.
|
150
|
-
linkml-1.
|
146
|
+
linkml-1.8.0.dist-info/entry_points.txt,sha256=7haDkIbyC7ZLhm5z-e3BhrLJpY2xoW1yuD8Y7QPNtVg,2093
|
147
|
+
linkml-1.8.0.dist-info/LICENSE,sha256=kORMoywK6j9_iy0UvLR-a80P1Rvc9AOM4gsKlUNZABg,535
|
148
|
+
linkml-1.8.0.dist-info/WHEEL,sha256=vVCvjcmxuUltf8cYhJ0sJMRDLr1XsPuxEId8YDzbyCY,88
|
149
|
+
linkml-1.8.0.dist-info/METADATA,sha256=ImZiqQezJfM8leU0WgCimYjcJXydh1XO8T22tlC9zpw,3724
|
150
|
+
linkml-1.8.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|