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.
Files changed (132) hide show
  1. {linkml-1.6.9 → linkml-1.7.0rc2}/PKG-INFO +2 -2
  2. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/__init__.py +2 -0
  3. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/csvgen.py +1 -0
  4. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/dotgen.py +1 -0
  5. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/golrgen.py +1 -0
  6. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/javagen.py +1 -0
  7. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/jsonldcontextgen.py +2 -0
  8. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/jsonldgen.py +10 -7
  9. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/jsonschemagen.py +19 -1
  10. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/markdowngen.py +5 -5
  11. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/owlgen.py +9 -1
  12. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/plantumlgen.py +1 -0
  13. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/prefixmapgen.py +1 -0
  14. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/rdfgen.py +1 -0
  15. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/shaclgen.py +1 -0
  16. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/shexgen.py +1 -0
  17. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/sqlddlgen.py +1 -0
  18. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/summarygen.py +1 -0
  19. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/yamlgen.py +1 -0
  20. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/yumlgen.py +1 -0
  21. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/transformers/logical_model_transformer.py +1 -0
  22. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/generator.py +7 -4
  23. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/ifabsent_functions.py +7 -1
  24. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/schemasynopsis.py +5 -7
  25. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/__init__.py +1 -0
  26. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/loaders/__init__.py +1 -0
  27. linkml-1.7.0rc2/linkml/validator/plugins/shacl_validation_plugin.py +93 -0
  28. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/validator.py +1 -1
  29. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/workspaces/example_runner.py +1 -0
  30. {linkml-1.6.9 → linkml-1.7.0rc2}/pyproject.toml +8 -4
  31. {linkml-1.6.9 → linkml-1.7.0rc2}/setup.py +2 -2
  32. {linkml-1.6.9 → linkml-1.7.0rc2}/LICENSE +0 -0
  33. {linkml-1.6.9 → linkml-1.7.0rc2}/README.md +0 -0
  34. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/__init__.py +0 -0
  35. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/_version.py +0 -0
  36. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/PythonGenNotes.md +0 -0
  37. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/README.md +0 -0
  38. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/common/__init__.py +0 -0
  39. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/common/type_designators.py +0 -0
  40. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/docgen/class.md.jinja2 +0 -0
  41. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/docgen/class_diagram.md.jinja2 +0 -0
  42. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/docgen/common_metadata.md.jinja2 +0 -0
  43. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/docgen/enum.md.jinja2 +0 -0
  44. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/docgen/index.md.jinja2 +0 -0
  45. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/docgen/index.tex.jinja2 +0 -0
  46. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/docgen/schema.md.jinja2 +0 -0
  47. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/docgen/slot.md.jinja2 +0 -0
  48. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/docgen/subset.md.jinja2 +0 -0
  49. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/docgen/type.md.jinja2 +0 -0
  50. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/docgen.py +0 -0
  51. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/erdiagramgen.py +0 -0
  52. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/excelgen.py +0 -0
  53. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/golanggen.py +0 -0
  54. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/graphqlgen.py +0 -0
  55. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/javagen/example_template.java.jinja2 +0 -0
  56. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/javagen/java_record_template.jinja2 +0 -0
  57. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/legacy/__init__.py +0 -0
  58. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/linkmlgen.py +0 -0
  59. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/namespacegen.py +0 -0
  60. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/oocodegen.py +0 -0
  61. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/projectgen.py +0 -0
  62. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/protogen.py +0 -0
  63. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/pydanticgen.py +0 -0
  64. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/pythongen.py +0 -0
  65. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/sparqlgen.py +0 -0
  66. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/sqlalchemy/__init__.py +0 -0
  67. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/sqlalchemy/sqlalchemy_declarative_template.py +0 -0
  68. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/sqlalchemy/sqlalchemy_imperative_template.py +0 -0
  69. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/sqlalchemygen.py +0 -0
  70. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/sqltablegen.py +0 -0
  71. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/sssomgen.py +0 -0
  72. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/string_template.md +0 -0
  73. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/terminusdbgen.py +0 -0
  74. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/generators/typescriptgen.py +0 -0
  75. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/__init__.py +0 -0
  76. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/cli.py +0 -0
  77. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/config/datamodel/.linkmllint.yaml +0 -0
  78. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/config/datamodel/__init__.py +0 -0
  79. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/config/datamodel/config.py +0 -0
  80. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/config/datamodel/config.yaml +0 -0
  81. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/config/default.yaml +0 -0
  82. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/config/recommended.yaml +0 -0
  83. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/formatters/__init__.py +0 -0
  84. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/formatters/formatter.py +0 -0
  85. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/formatters/json_formatter.py +0 -0
  86. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/formatters/markdown_formatter.py +0 -0
  87. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/formatters/terminal_formatter.py +0 -0
  88. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/formatters/tsv_formatter.py +0 -0
  89. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/linter.py +0 -0
  90. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/linter/rules.py +0 -0
  91. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/reporting/__init__.py +0 -0
  92. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/reporting/model.py +0 -0
  93. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/transformers/__init__.py +0 -0
  94. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/transformers/model_transformer.py +0 -0
  95. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/transformers/relmodel_transformer.py +0 -0
  96. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/transformers/schema_renamer.py +0 -0
  97. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/__init__.py +0 -0
  98. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/cli_utils.py +0 -0
  99. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/converter.py +0 -0
  100. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/datautils.py +0 -0
  101. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/datavalidator.py +0 -0
  102. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/execute_tutorial.py +0 -0
  103. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/helpers.py +0 -0
  104. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/logictools.py +0 -0
  105. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/mergeutils.py +0 -0
  106. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/rawloader.py +0 -0
  107. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/schema_builder.py +0 -0
  108. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/schema_fixer.py +0 -0
  109. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/schemaloader.py +0 -0
  110. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/sqlutils.py +0 -0
  111. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/typereferences.py +0 -0
  112. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/utils/validation.py +0 -0
  113. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/cli.py +0 -0
  114. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/loaders/delimited_file_loader.py +0 -0
  115. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/loaders/json_loader.py +0 -0
  116. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/loaders/loader.py +0 -0
  117. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/loaders/passthrough_loader.py +0 -0
  118. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/loaders/yaml_loader.py +0 -0
  119. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/plugins/__init__.py +0 -0
  120. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/plugins/jsonschema_validation_plugin.py +0 -0
  121. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/plugins/pydantic_validation_plugin.py +0 -0
  122. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/plugins/recommended_slots_plugin.py +0 -0
  123. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/plugins/validation_plugin.py +0 -0
  124. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/report.py +0 -0
  125. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validator/validation_context.py +0 -0
  126. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validators/__init__.py +0 -0
  127. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validators/jsonschemavalidator.py +0 -0
  128. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/validators/sparqlvalidator.py +0 -0
  129. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/workspaces/__init__.py +0 -0
  130. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/workspaces/datamodel/__init__.py +0 -0
  131. {linkml-1.6.9 → linkml-1.7.0rc2}/linkml/workspaces/datamodel/workspaces.py +0 -0
  132. {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.6.9
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.6.0)
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",
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Generate CSVs
3
3
  """
4
+
4
5
  import os
5
6
  import sys
6
7
  from csv import DictWriter
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Generate dotfiles
3
3
  """
4
+
4
5
  import os
5
6
  from dataclasses import dataclass
6
7
  from typing import List, Optional
@@ -6,6 +6,7 @@ These can be converted to solr schema-xml, and used in amigo-bbop tools
6
6
  See the golr-views directory in this repo for examples
7
7
 
8
8
  """
9
+
9
10
  import os
10
11
  from dataclasses import dataclass
11
12
  from typing import List, Optional
@@ -70,6 +70,7 @@ class JavaGenerator(OOCodeGenerator):
70
70
  generatorname = os.path.basename(__file__)
71
71
  generatorversion = "0.0.1"
72
72
  valid_formats = ["java"]
73
+ file_extension = "java"
73
74
 
74
75
  # ObjectVars
75
76
  generate_records: bool = False
@@ -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 SlotDefinitionName(underscore(node))
103
- if node in self.schema.slots
104
- else SubsetDefinitionName(camelcase(node))
105
- if node in self.schema.subsets
106
- else TypeDefinitionName(underscore(node))
107
- if node in self.schema.types
108
- else None
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 underscore(obj.name)
460
- if isinstance(obj, SlotDefinition)
461
- else underscore(obj.name)
462
- if isinstance(obj, EnumDefinition)
463
- else camelcase(obj.name)
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
- print(OwlSchemaGenerator(yamlfile, metadata_profiles=metadata_profiles, **kwargs).serialize(**kwargs))
1248
+ gen = OwlSchemaGenerator(yamlfile, metadata_profiles=metadata_profiles, **kwargs)
1249
+ print(gen.serialize(**kwargs))
1242
1250
 
1243
1251
 
1244
1252
  if __name__ == "__main__":
@@ -3,6 +3,7 @@
3
3
  https://plantuml.com/
4
4
 
5
5
  """
6
+
6
7
  import base64
7
8
  import os
8
9
  import zlib
@@ -2,6 +2,7 @@
2
2
  Generate JSON-LD contexts
3
3
 
4
4
  """
5
+
5
6
  import csv
6
7
  import os
7
8
  from dataclasses import dataclass, field
@@ -4,6 +4,7 @@ YAML Schema to RDF Generator
4
4
  Generate a JSON LD representation of the model
5
5
 
6
6
  """
7
+
7
8
  import os
8
9
  import urllib.parse as urlparse
9
10
  from dataclasses import dataclass, field
@@ -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)
@@ -1,6 +1,7 @@
1
1
  """Generate ShEx definition of a model
2
2
 
3
3
  """
4
+
4
5
  import os
5
6
  import urllib.parse as urlparse
6
7
  from dataclasses import dataclass, field
@@ -1,4 +1,5 @@
1
1
  """DEPRECATED: Use SQLTableGenerator instead"""
2
+
2
3
  import logging
3
4
  import os
4
5
  from contextlib import redirect_stdout
@@ -1,6 +1,7 @@
1
1
  """Generate Summary Spreadsheets
2
2
 
3
3
  """
4
+
4
5
  import os
5
6
  import sys
6
7
  from csv import DictWriter
@@ -1,6 +1,7 @@
1
1
  """Validate linkml input and optionally emit completely resolved biolink yaml output
2
2
 
3
3
  """
4
+
4
5
  import os
5
6
  from dataclasses import dataclass, field
6
7
 
@@ -3,6 +3,7 @@
3
3
  https://yuml.me/diagram/scruffy/class/samples
4
4
 
5
5
  """
6
+
6
7
  import os
7
8
  from dataclasses import dataclass, field
8
9
  from typing import Callable, List, Optional, Set, cast
@@ -12,6 +12,7 @@ of constraints in both classes hold.
12
12
  These logical constraints are then simplified by translating to disjunctive normal form,
13
13
  and applying simplification rules.
14
14
  """
15
+
15
16
  import logging
16
17
  from copy import deepcopy
17
18
  from dataclasses import dataclass
@@ -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 self.schema.classes[element.is_a]
457
- if isinstance(element, ClassDefinition)
458
- else self.schema.slots[element.is_a]
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="Include metadata in output",
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[Tuple[Match[str], bool, Callable[[Match[str], SchemaLoader, ClassDefinition, SlotDefinition], str],]]:
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
- ClassType
124
- if v.range in self.schema.classes
125
- else EnumType
126
- if v.range in self.schema.enums
127
- else TypeType
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
@@ -4,6 +4,7 @@ instance from a source. Instances of these classes are passed to
4
4
  :meth:`linkml.validator.Validator.validate_source` and
5
5
  :meth:`linkml.validator.Validator.iter_results_from_source`
6
6
  """
7
+
7
8
  import os
8
9
  from typing import Union
9
10
 
@@ -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,7 @@
1
1
  """Iterate through all examples in a folder testing them for validity.
2
2
 
3
3
  """
4
+
4
5
  import glob
5
6
  import json
6
7
  import logging
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "linkml"
3
- version = "1.6.9"
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.6.0"
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-versions = ["py38", "py39", "py310", "py311"]
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.6.0',
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.6.9',
112
+ 'version': '1.7.0rc2',
113
113
  'description': 'Linked Open Data Modeling Language',
114
114
  'long_description': '[![Pyversions](https://img.shields.io/pypi/pyversions/linkml.svg)](https://pypi.python.org/pypi/linkml)\n![](https://github.com/linkml/linkml/workflows/Build/badge.svg)\n[![PyPi](https://img.shields.io/pypi/v/linkml.svg)](https://pypi.python.org/pypi/linkml)\n[![badge](https://img.shields.io/badge/launch-binder-579ACA.svg)](https://mybinder.org/v2/gh/linkml/linkml/main?filepath=notebooks)\n[![DOI](https://zenodo.org/badge/13996/linkml/linkml.svg)](https://zenodo.org/badge/latestdoi/13996/linkml/linkml)\n[![PyPIDownloadsTotal](https://pepy.tech/badge/linkml)](https://pepy.tech/project/linkml)\n[![PyPIDownloadsMonth](https://img.shields.io/pypi/dm/linkml?logo=PyPI&color=blue)](https://pypi.org/project/linkml)\n[![codecov](https://codecov.io/gh/linkml/linkml/branch/main/graph/badge.svg?token=WNQNG986UN)](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