linkml 1.6.9__tar.gz → 1.7.0rc2__tar.gz
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-1.6.9 → linkml-1.7.0rc2}/PKG-INFO +2 -2
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/__init__.py +2 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/csvgen.py +1 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/dotgen.py +1 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/golrgen.py +1 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/javagen.py +1 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/jsonldcontextgen.py +2 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/jsonldgen.py +10 -7
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/jsonschemagen.py +19 -1
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/markdowngen.py +5 -5
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/owlgen.py +9 -1
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/plantumlgen.py +1 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/prefixmapgen.py +1 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/rdfgen.py +1 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/shaclgen.py +1 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/shexgen.py +1 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/sqlddlgen.py +1 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/summarygen.py +1 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/yamlgen.py +1 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/yumlgen.py +1 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/transformers/logical_model_transformer.py +1 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/generator.py +7 -4
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/ifabsent_functions.py +7 -1
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/schemasynopsis.py +5 -7
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/__init__.py +1 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/loaders/__init__.py +1 -0
- linkml-1.7.0rc2/linkml/validator/plugins/shacl_validation_plugin.py +93 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/validator.py +1 -1
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/workspaces/example_runner.py +1 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/pyproject.toml +8 -4
- {linkml-1.6.9 → linkml-1.7.0rc2}/setup.py +2 -2
- {linkml-1.6.9 → linkml-1.7.0rc2}/LICENSE +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/README.md +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/__init__.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/_version.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/PythonGenNotes.md +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/README.md +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/common/__init__.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/common/type_designators.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/docgen/class.md.jinja2 +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/docgen/class_diagram.md.jinja2 +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/docgen/common_metadata.md.jinja2 +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/docgen/enum.md.jinja2 +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/docgen/index.md.jinja2 +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/docgen/index.tex.jinja2 +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/docgen/schema.md.jinja2 +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/docgen/slot.md.jinja2 +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/docgen/subset.md.jinja2 +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/docgen/type.md.jinja2 +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/docgen.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/erdiagramgen.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/excelgen.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/golanggen.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/graphqlgen.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/javagen/example_template.java.jinja2 +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/javagen/java_record_template.jinja2 +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/legacy/__init__.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/linkmlgen.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/namespacegen.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/oocodegen.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/projectgen.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/protogen.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/pydanticgen.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/pythongen.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/sparqlgen.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/sqlalchemy/__init__.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/sqlalchemy/sqlalchemy_declarative_template.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/sqlalchemy/sqlalchemy_imperative_template.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/sqlalchemygen.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/sqltablegen.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/sssomgen.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/string_template.md +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/terminusdbgen.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/typescriptgen.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/__init__.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/cli.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/config/datamodel/.linkmllint.yaml +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/config/datamodel/__init__.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/config/datamodel/config.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/config/datamodel/config.yaml +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/config/default.yaml +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/config/recommended.yaml +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/formatters/__init__.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/formatters/formatter.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/formatters/json_formatter.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/formatters/markdown_formatter.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/formatters/terminal_formatter.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/formatters/tsv_formatter.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/linter.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/rules.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/reporting/__init__.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/reporting/model.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/transformers/__init__.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/transformers/model_transformer.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/transformers/relmodel_transformer.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/transformers/schema_renamer.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/__init__.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/cli_utils.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/converter.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/datautils.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/datavalidator.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/execute_tutorial.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/helpers.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/logictools.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/mergeutils.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/rawloader.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/schema_builder.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/schema_fixer.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/schemaloader.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/sqlutils.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/typereferences.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/validation.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/cli.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/loaders/delimited_file_loader.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/loaders/json_loader.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/loaders/loader.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/loaders/passthrough_loader.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/loaders/yaml_loader.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/plugins/__init__.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/plugins/jsonschema_validation_plugin.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/plugins/pydantic_validation_plugin.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/plugins/recommended_slots_plugin.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/plugins/validation_plugin.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/report.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/validation_context.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validators/__init__.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validators/jsonschemavalidator.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validators/sparqlvalidator.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/workspaces/__init__.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/workspaces/datamodel/__init__.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/workspaces/datamodel/workspaces.py +0 -0
- {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/workspaces/datamodel/workspaces.yaml +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: linkml
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.7.0rc2
|
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
|
@@ -31,7 +31,7 @@ Requires-Dist: jinja2 (>=3.1.0)
|
|
31
31
|
Requires-Dist: jsonasobj2 (>=1.0.3,<2.0.0)
|
32
32
|
Requires-Dist: jsonschema[format] (>=4.0.0)
|
33
33
|
Requires-Dist: linkml-dataops
|
34
|
-
Requires-Dist: linkml-runtime (>=1.
|
34
|
+
Requires-Dist: linkml-runtime (>=1.7.0rc1)
|
35
35
|
Requires-Dist: openpyxl
|
36
36
|
Requires-Dist: parse
|
37
37
|
Requires-Dist: prefixcommons (>=0.1.7)
|
@@ -4,6 +4,7 @@ representation such as JsonSchema
|
|
4
4
|
"""
|
5
5
|
|
6
6
|
from linkml.generators.javagen import JavaGenerator
|
7
|
+
from linkml.generators.jsonldcontextgen import ContextGenerator
|
7
8
|
from linkml.generators.jsonschemagen import JsonSchemaGenerator
|
8
9
|
from linkml.generators.owlgen import OwlSchemaGenerator
|
9
10
|
from linkml.generators.pydanticgen import PydanticGenerator
|
@@ -41,6 +42,7 @@ __all__ = [
|
|
41
42
|
"PydanticGenerator",
|
42
43
|
"PythonGenerator",
|
43
44
|
"JavaGenerator",
|
45
|
+
"ContextGenerator",
|
44
46
|
"JsonSchemaGenerator",
|
45
47
|
"ShaclGenerator",
|
46
48
|
"ShExGenerator",
|
@@ -2,6 +2,7 @@
|
|
2
2
|
Generate JSON-LD contexts
|
3
3
|
|
4
4
|
"""
|
5
|
+
|
5
6
|
import os
|
6
7
|
import re
|
7
8
|
from dataclasses import dataclass, field
|
@@ -37,6 +38,7 @@ class ContextGenerator(Generator):
|
|
37
38
|
visit_all_class_slots = False
|
38
39
|
uses_schemaloader = True
|
39
40
|
requires_metamodel = True
|
41
|
+
file_extension = "context.jsonld"
|
40
42
|
|
41
43
|
# ObjectVars
|
42
44
|
emit_prefixes: Set[str] = field(default_factory=lambda: set())
|
@@ -1,6 +1,7 @@
|
|
1
1
|
""" Generate JSONld
|
2
2
|
|
3
3
|
"""
|
4
|
+
|
4
5
|
import os
|
5
6
|
from copy import deepcopy
|
6
7
|
from dataclasses import dataclass
|
@@ -99,13 +100,15 @@ class JSONLDGenerator(Generator):
|
|
99
100
|
return (
|
100
101
|
ClassDefinitionName(camelcase(node))
|
101
102
|
if node in self.schema.classes
|
102
|
-
else
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
103
|
+
else (
|
104
|
+
SlotDefinitionName(underscore(node))
|
105
|
+
if node in self.schema.slots
|
106
|
+
else (
|
107
|
+
SubsetDefinitionName(camelcase(node))
|
108
|
+
if node in self.schema.subsets
|
109
|
+
else TypeDefinitionName(underscore(node)) if node in self.schema.types else None
|
110
|
+
)
|
111
|
+
)
|
109
112
|
)
|
110
113
|
return None
|
111
114
|
|
@@ -193,6 +193,9 @@ class JsonSchemaGenerator(Generator):
|
|
193
193
|
Note that if the range of a slot has a type designator, descendants will always be included.
|
194
194
|
"""
|
195
195
|
|
196
|
+
title_from: str = "name"
|
197
|
+
"""The slot from which to populate JSONSchema title annotation."""
|
198
|
+
|
196
199
|
top_level_schema: JsonSchema = None
|
197
200
|
|
198
201
|
def __post_init__(self):
|
@@ -215,7 +218,7 @@ class JsonSchemaGenerator(Generator):
|
|
215
218
|
"$id": self.schema.id,
|
216
219
|
"metamodel_version": metamodel_version,
|
217
220
|
"version": self.schema.version if self.schema.version else None,
|
218
|
-
"title": self.schema.name,
|
221
|
+
"title": self.schema.title if self.title_from == "title" and self.schema.title else self.schema.name,
|
219
222
|
"type": "object",
|
220
223
|
"additionalProperties": self.not_closed,
|
221
224
|
}
|
@@ -238,6 +241,8 @@ class JsonSchemaGenerator(Generator):
|
|
238
241
|
"description": be(cls.description),
|
239
242
|
}
|
240
243
|
)
|
244
|
+
if self.title_from == "title" and cls.title:
|
245
|
+
class_subschema["title"] = cls.title
|
241
246
|
|
242
247
|
for slot_definition in self.schemaview.class_induced_slots(cls.name):
|
243
248
|
self.handle_class_slot(subschema=class_subschema, cls=cls, slot=slot_definition)
|
@@ -364,6 +369,9 @@ class JsonSchemaGenerator(Generator):
|
|
364
369
|
"description": be(enum.description),
|
365
370
|
}
|
366
371
|
)
|
372
|
+
if self.title_from == "title" and enum.title:
|
373
|
+
enum_schema["title"] = enum.title
|
374
|
+
|
367
375
|
if permissible_values_texts:
|
368
376
|
enum_schema["enum"] = permissible_values_texts
|
369
377
|
self.top_level_schema.add_def(enum.name, enum_schema)
|
@@ -480,6 +488,8 @@ class JsonSchemaGenerator(Generator):
|
|
480
488
|
prop = JsonSchema.array_of(prop)
|
481
489
|
|
482
490
|
prop.add_keyword("description", slot.description)
|
491
|
+
if self.title_from == "title" and slot.title:
|
492
|
+
prop.add_keyword("title", slot.title)
|
483
493
|
|
484
494
|
own_constraints = self.get_value_constraints_for_slot(slot)
|
485
495
|
|
@@ -619,6 +629,14 @@ If this is a positive number the resulting JSON will be pretty-printed with that
|
|
619
629
|
disable pretty-printing and return the most compact JSON representation
|
620
630
|
""",
|
621
631
|
)
|
632
|
+
@click.option(
|
633
|
+
"--title-from",
|
634
|
+
type=click.Choice(["name", "title"], case_sensitive=False),
|
635
|
+
default="name",
|
636
|
+
help="""
|
637
|
+
Specify from which slot are JSON Schema 'title' annotations generated.
|
638
|
+
""",
|
639
|
+
)
|
622
640
|
@click.version_option(__version__, "-V", "--version")
|
623
641
|
def cli(yamlfile, **kwargs):
|
624
642
|
"""Generate JSON Schema representation of a LinkML model"""
|
@@ -456,11 +456,11 @@ class MarkdownGenerator(Generator):
|
|
456
456
|
filename = (
|
457
457
|
self.formatted_element_name(obj)
|
458
458
|
if isinstance(obj, ClassDefinition)
|
459
|
-
else
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
459
|
+
else (
|
460
|
+
underscore(obj.name)
|
461
|
+
if isinstance(obj, SlotDefinition)
|
462
|
+
else underscore(obj.name) if isinstance(obj, EnumDefinition) else camelcase(obj.name)
|
463
|
+
)
|
464
464
|
)
|
465
465
|
subdir = "/types" if isinstance(obj, TypeDefinition) and not self.no_types_dir else ""
|
466
466
|
return f"{self.directory}{subdir}/{filename}.md"
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""Generate OWL ontology representation of a LinkML schema."""
|
2
|
+
|
2
3
|
import logging
|
3
4
|
import os
|
4
5
|
from collections import defaultdict
|
@@ -1219,6 +1220,12 @@ class OwlSchemaGenerator(Generator):
|
|
1219
1220
|
show_default=True,
|
1220
1221
|
help="If true, then mixins are represented as existential expressions",
|
1221
1222
|
)
|
1223
|
+
@click.option(
|
1224
|
+
"--use-native-uris/--no-use-native-uris",
|
1225
|
+
default=True,
|
1226
|
+
show_default=True,
|
1227
|
+
help="Use model URIs rather than class/slot URIs",
|
1228
|
+
)
|
1222
1229
|
@click.version_option(__version__, "-V", "--version")
|
1223
1230
|
def cli(yamlfile, metadata_profile: str, **kwargs):
|
1224
1231
|
"""Generate an OWL representation of a LinkML model
|
@@ -1238,7 +1245,8 @@ def cli(yamlfile, metadata_profile: str, **kwargs):
|
|
1238
1245
|
metadata_profiles = [MetadataProfile(metadata_profile)]
|
1239
1246
|
else:
|
1240
1247
|
metadata_profiles = [MetadataProfile.linkml]
|
1241
|
-
|
1248
|
+
gen = OwlSchemaGenerator(yamlfile, metadata_profiles=metadata_profiles, **kwargs)
|
1249
|
+
print(gen.serialize(**kwargs))
|
1242
1250
|
|
1243
1251
|
|
1244
1252
|
if __name__ == "__main__":
|
@@ -116,6 +116,7 @@ class ShaclGenerator(Generator):
|
|
116
116
|
prop_pv_literal(SH.minCount, 1)
|
117
117
|
prop_pv_literal(SH.minInclusive, s.minimum_value)
|
118
118
|
prop_pv_literal(SH.maxInclusive, s.maximum_value)
|
119
|
+
prop_pv_literal(SH.hasValue, s.equals_number)
|
119
120
|
r = s.range
|
120
121
|
if r in sv.all_classes():
|
121
122
|
range_ref = sv.get_uri(r, expand=True)
|
@@ -14,6 +14,7 @@ New generators should always using the latter approach
|
|
14
14
|
See: https://github.com/linkml/linkml/issues/923
|
15
15
|
|
16
16
|
"""
|
17
|
+
|
17
18
|
import abc
|
18
19
|
import logging
|
19
20
|
import os
|
@@ -453,9 +454,11 @@ class Generator(metaclass=abc.ABCMeta):
|
|
453
454
|
return (
|
454
455
|
None
|
455
456
|
if element.is_a is None
|
456
|
-
else
|
457
|
-
|
458
|
-
|
457
|
+
else (
|
458
|
+
self.schema.classes[element.is_a]
|
459
|
+
if isinstance(element, ClassDefinition)
|
460
|
+
else self.schema.slots[element.is_a]
|
461
|
+
)
|
459
462
|
)
|
460
463
|
|
461
464
|
def ancestors(self, element: Union[ClassDefinition, SlotDefinition]) -> List[ElementName]:
|
@@ -904,7 +907,7 @@ def shared_arguments(g: Type[Generator]) -> Callable[[Command], Command]:
|
|
904
907
|
("--useuris/--metauris",),
|
905
908
|
default=True,
|
906
909
|
show_default=True,
|
907
|
-
help="
|
910
|
+
help="Use class and slot URIs over model uris",
|
908
911
|
)
|
909
912
|
)
|
910
913
|
f.params.append(Option(("--importmap", "-im"), type=click.File(), help="Import mapping file"))
|
@@ -113,7 +113,13 @@ default_library: List[
|
|
113
113
|
|
114
114
|
def isabsent_match(
|
115
115
|
txt: Text,
|
116
|
-
) -> Optional[
|
116
|
+
) -> Optional[
|
117
|
+
Tuple[
|
118
|
+
Match[str],
|
119
|
+
bool,
|
120
|
+
Callable[[Match[str], SchemaLoader, ClassDefinition, SlotDefinition], str],
|
121
|
+
]
|
122
|
+
]:
|
117
123
|
txt = str(txt)
|
118
124
|
for pattern, postinit, f in default_library:
|
119
125
|
m = re.match(pattern + "$", txt)
|
@@ -120,13 +120,11 @@ class SchemaSynopsis:
|
|
120
120
|
self.add_ref(
|
121
121
|
SlotType,
|
122
122
|
k,
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
if v.range in self.schema.types
|
129
|
-
else None,
|
123
|
+
(
|
124
|
+
ClassType
|
125
|
+
if v.range in self.schema.classes
|
126
|
+
else EnumType if v.range in self.schema.enums else TypeType if v.range in self.schema.types else None
|
127
|
+
),
|
130
128
|
v.range,
|
131
129
|
)
|
132
130
|
|
@@ -3,6 +3,7 @@ The ``linkml.validator`` package contains a new LinkML validation framework that
|
|
3
3
|
than the ``linkml.validators`` package. While that package still exists, it may become deprecated
|
4
4
|
in the future.
|
5
5
|
"""
|
6
|
+
|
6
7
|
import os
|
7
8
|
from pathlib import Path
|
8
9
|
from typing import Any, Optional, Union
|
@@ -0,0 +1,93 @@
|
|
1
|
+
import os
|
2
|
+
from typing import Any, Iterator, Optional
|
3
|
+
|
4
|
+
import rdflib
|
5
|
+
from linkml_runtime.dumpers import rdflib_dumper
|
6
|
+
|
7
|
+
from linkml.generators import PythonGenerator, ShaclGenerator
|
8
|
+
from linkml.validator.plugins.validation_plugin import ValidationPlugin
|
9
|
+
from linkml.validator.report import Severity, ValidationResult
|
10
|
+
from linkml.validator.validation_context import ValidationContext
|
11
|
+
|
12
|
+
SH = rdflib.Namespace("http://www.w3.org/ns/shacl#")
|
13
|
+
|
14
|
+
|
15
|
+
class ShaclValidationPlugin(ValidationPlugin):
|
16
|
+
"""A validation plugin which validates instances using SHACL.
|
17
|
+
|
18
|
+
:param shacl_path: If provided, SHACL will not be generated from the schema,
|
19
|
+
instead it will be read from this path.
|
20
|
+
:param closed: If ``True``, additional properties are not allowed on instances.
|
21
|
+
Defaults to ``False``.
|
22
|
+
:param raise_on_conversion_error: If ``True``, raise an exception if the instance
|
23
|
+
cannot be converted to a Python class. Otherwise, treat as a ValidationError.
|
24
|
+
Defaults to ``False``.
|
25
|
+
"""
|
26
|
+
|
27
|
+
def __init__(
|
28
|
+
self,
|
29
|
+
*,
|
30
|
+
closed: bool = False,
|
31
|
+
shacl_path: Optional[os.PathLike] = None,
|
32
|
+
raise_on_conversion_error: bool = False,
|
33
|
+
) -> None:
|
34
|
+
self.closed = closed
|
35
|
+
self.shacl_path = shacl_path
|
36
|
+
self.raise_on_conversion_error = raise_on_conversion_error
|
37
|
+
|
38
|
+
def _shacl_graph(self, context: ValidationContext) -> Optional[rdflib.Graph]:
|
39
|
+
g = rdflib.Graph()
|
40
|
+
if self.shacl_path:
|
41
|
+
g.parse(str(self.shacl_path))
|
42
|
+
else:
|
43
|
+
gen = ShaclGenerator(context._schema)
|
44
|
+
g = gen.as_graph()
|
45
|
+
return g
|
46
|
+
|
47
|
+
def process(self, instance: Any, context: ValidationContext) -> Iterator[ValidationResult]:
|
48
|
+
"""Perform JSON Schema validation on the provided instance
|
49
|
+
|
50
|
+
:param instance: The instance to validate
|
51
|
+
:param context: The validation context which provides a JSON Schema artifact
|
52
|
+
:return: Iterator over validation results
|
53
|
+
:rtype: Iterator[ValidationResult]
|
54
|
+
"""
|
55
|
+
import pyshacl
|
56
|
+
|
57
|
+
shacl_graph = self._shacl_graph(context)
|
58
|
+
if isinstance(instance, dict):
|
59
|
+
pygen = PythonGenerator(context._schema)
|
60
|
+
mod = pygen.compile_module()
|
61
|
+
py_cls = getattr(mod, context._target_class)
|
62
|
+
if self.raise_on_conversion_error:
|
63
|
+
instance = py_cls(**instance)
|
64
|
+
else:
|
65
|
+
try:
|
66
|
+
instance = py_cls(**instance)
|
67
|
+
except (ValueError, TypeError):
|
68
|
+
yield ValidationResult(
|
69
|
+
type="shacl validation",
|
70
|
+
severity=Severity.ERROR,
|
71
|
+
instance=instance,
|
72
|
+
instantiates=context.target_class,
|
73
|
+
message="failed at class instantiation stage",
|
74
|
+
)
|
75
|
+
return
|
76
|
+
data_graph = rdflib_dumper.as_rdf_graph(instance, schemaview=context.schema_view)
|
77
|
+
validator = pyshacl.Validator(
|
78
|
+
shacl_graph=shacl_graph,
|
79
|
+
data_graph=data_graph,
|
80
|
+
inference="rdfs",
|
81
|
+
)
|
82
|
+
conforms, report_graph, report_text = validator.run()
|
83
|
+
for s, _, o in report_graph.triples((None, SH.result, None)):
|
84
|
+
msg = ""
|
85
|
+
for p, o2 in report_graph.predicate_objects(o):
|
86
|
+
msg += f"{p} {o2}\n"
|
87
|
+
yield ValidationResult(
|
88
|
+
type="shacl validation",
|
89
|
+
severity=Severity.ERROR,
|
90
|
+
instance=instance,
|
91
|
+
instantiates=context.target_class,
|
92
|
+
message=f"{msg}",
|
93
|
+
)
|
@@ -29,7 +29,7 @@ class Validator:
|
|
29
29
|
schema: Union[str, dict, TextIO, Path, SchemaDefinition],
|
30
30
|
validation_plugins: Optional[List[ValidationPlugin]] = None,
|
31
31
|
*,
|
32
|
-
strict: bool = False
|
32
|
+
strict: bool = False,
|
33
33
|
) -> None:
|
34
34
|
if isinstance(schema, Path):
|
35
35
|
schema = str(schema)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "linkml"
|
3
|
-
version = "1.
|
3
|
+
version = "1.7.0rc2"
|
4
4
|
description = "Linked Open Data Modeling Language"
|
5
5
|
authors = [
|
6
6
|
"Chris Mungall <cjmungall@lbl.gov>",
|
@@ -106,7 +106,7 @@ jinja2 = ">= 3.1.0"
|
|
106
106
|
jsonasobj2 = "==1.*,>=1.0.0,>=1.0.3"
|
107
107
|
jsonschema = {extras = ["format"], version = ">=4.0.0"}
|
108
108
|
linkml-dataops = "*"
|
109
|
-
linkml-runtime = ">=1.
|
109
|
+
linkml-runtime = ">=1.7.0rc1"
|
110
110
|
openpyxl = "*"
|
111
111
|
parse = "*"
|
112
112
|
prefixcommons = ">=0.1.7"
|
@@ -143,6 +143,10 @@ pytest = "^7.4.0"
|
|
143
143
|
pytest-subtests = "^0.11.0"
|
144
144
|
numpy = ">=1.24.3"
|
145
145
|
|
146
|
+
|
147
|
+
[tool.poetry.group.shacl.dependencies]
|
148
|
+
pyshacl = "^0.25.0"
|
149
|
+
|
146
150
|
[tool.poetry.extras]
|
147
151
|
docs = ["Sphinx", "sphinxcontrib-mermaid", "furo"]
|
148
152
|
|
@@ -152,7 +156,7 @@ build-backend = "poetry_dynamic_versioning.backend"
|
|
152
156
|
|
153
157
|
[tool.codespell]
|
154
158
|
# TODO: bring in tests in too
|
155
|
-
skip = '.git,*.pdf,*.svg,./tests,pyproject.toml,*.dill'
|
159
|
+
skip = '.git,*.pdf,*.svg,./tests,pyproject.toml,*.dill,poetry.lock'
|
156
160
|
# Ignore table where words could be split across rows
|
157
161
|
# Ignore shortcut specifications like [Ff]alse
|
158
162
|
ignore-regex = '(\|.*\|.*\|.*\||\[[A-Z][a-z]\][a-z][a-z])'
|
@@ -161,7 +165,7 @@ quiet-level = 3
|
|
161
165
|
|
162
166
|
[tool.black]
|
163
167
|
line-length = 120
|
164
|
-
target-
|
168
|
+
target-version = ["py38", "py39", "py310", "py311"]
|
165
169
|
force-exclude = '''
|
166
170
|
/(
|
167
171
|
# default exclude
|
@@ -35,7 +35,7 @@ install_requires = \
|
|
35
35
|
'jsonasobj2>=1.0.3,<2.0.0',
|
36
36
|
'jsonschema[format]>=4.0.0',
|
37
37
|
'linkml-dataops',
|
38
|
-
'linkml-runtime>=1.
|
38
|
+
'linkml-runtime>=1.7.0rc1',
|
39
39
|
'openpyxl',
|
40
40
|
'parse',
|
41
41
|
'prefixcommons>=0.1.7',
|
@@ -109,7 +109,7 @@ entry_points = \
|
|
109
109
|
|
110
110
|
setup_kwargs = {
|
111
111
|
'name': 'linkml',
|
112
|
-
'version': '1.
|
112
|
+
'version': '1.7.0rc2',
|
113
113
|
'description': 'Linked Open Data Modeling Language',
|
114
114
|
'long_description': '[](https://pypi.python.org/pypi/linkml)\n\n[](https://pypi.python.org/pypi/linkml)\n[](https://mybinder.org/v2/gh/linkml/linkml/main?filepath=notebooks)\n[](https://zenodo.org/badge/latestdoi/13996/linkml/linkml)\n[](https://pepy.tech/project/linkml)\n[](https://pypi.org/project/linkml)\n[](https://codecov.io/gh/linkml/linkml)\n\n\n# LinkML - Linked Data Modeling Language\n\nLinkML is a linked data modeling language following object-oriented and ontological principles. LinkML models are typically authored in YAML, and can be converted to other schema representation formats such as JSON or RDF.\n\nThis repo holds the tools for generating and working with LinkML. For the LinkML schema (metamodel), please see https://github.com/linkml/linkml-model\n\nThe complete documentation for LinkML can be found here:\n\n - [linkml.io/linkml](https://linkml.io/linkml)\n',
|
115
115
|
'author': 'Chris Mungall',
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/sqlalchemy/sqlalchemy_declarative_template.py
RENAMED
File without changes
|
{linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/sqlalchemy/sqlalchemy_imperative_template.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|