linkml 1.7.11rc1__tar.gz → 1.8.0__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 (150) hide show
  1. {linkml-1.7.11rc1 → linkml-1.8.0}/PKG-INFO +2 -2
  2. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/docgen/class.md.jinja2 +0 -14
  3. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/docgen/common_metadata.md.jinja2 +14 -1
  4. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/erdiagramgen.py +37 -3
  5. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/golanggen.py +1 -6
  6. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/plantumlgen.py +1 -5
  7. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/pydanticgen/array.py +1 -12
  8. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/pydanticgen/pydanticgen.py +1 -4
  9. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/pythongen.py +1 -8
  10. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/shaclgen.py +95 -3
  11. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/sqlalchemygen.py +2 -10
  12. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/linter/rules.py +1 -6
  13. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/transformers/logical_model_transformer.py +6 -2
  14. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/utils/schemaloader.py +27 -0
  15. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/utils/schemasynopsis.py +1 -9
  16. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/validator/__init__.py +1 -3
  17. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/validator/plugins/__init__.py +1 -3
  18. {linkml-1.7.11rc1 → linkml-1.8.0}/pyproject.toml +2 -2
  19. {linkml-1.7.11rc1 → linkml-1.8.0}/setup.py +2 -2
  20. {linkml-1.7.11rc1 → linkml-1.8.0}/LICENSE +0 -0
  21. {linkml-1.7.11rc1 → linkml-1.8.0}/README.md +0 -0
  22. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/__init__.py +0 -0
  23. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/_version.py +0 -0
  24. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/PythonGenNotes.md +0 -0
  25. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/README.md +0 -0
  26. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/__init__.py +0 -0
  27. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/common/__init__.py +0 -0
  28. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/common/type_designators.py +0 -0
  29. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/csvgen.py +0 -0
  30. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/docgen/class_diagram.md.jinja2 +0 -0
  31. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/docgen/enum.md.jinja2 +0 -0
  32. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/docgen/index.md.jinja2 +0 -0
  33. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/docgen/index.tex.jinja2 +0 -0
  34. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/docgen/schema.md.jinja2 +0 -0
  35. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/docgen/slot.md.jinja2 +0 -0
  36. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/docgen/subset.md.jinja2 +0 -0
  37. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/docgen/type.md.jinja2 +0 -0
  38. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/docgen.py +0 -0
  39. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/dotgen.py +0 -0
  40. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/excelgen.py +0 -0
  41. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/golrgen.py +0 -0
  42. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/graphqlgen.py +0 -0
  43. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/javagen/example_template.java.jinja2 +0 -0
  44. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/javagen/java_record_template.jinja2 +0 -0
  45. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/javagen.py +0 -0
  46. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/jsonldcontextgen.py +0 -0
  47. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/jsonldgen.py +0 -0
  48. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/jsonschemagen.py +0 -0
  49. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/legacy/__init__.py +0 -0
  50. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/linkmlgen.py +0 -0
  51. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/markdowngen.py +0 -0
  52. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/namespacegen.py +0 -0
  53. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/oocodegen.py +0 -0
  54. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/owlgen.py +0 -0
  55. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/prefixmapgen.py +0 -0
  56. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/projectgen.py +0 -0
  57. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/protogen.py +0 -0
  58. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/pydanticgen/__init__.py +0 -0
  59. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/pydanticgen/black.py +0 -0
  60. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/pydanticgen/build.py +0 -0
  61. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/pydanticgen/includes.py +0 -0
  62. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/pydanticgen/template.py +0 -0
  63. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/pydanticgen/templates/attribute.py.jinja +0 -0
  64. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/pydanticgen/templates/base_model.py.jinja +0 -0
  65. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/pydanticgen/templates/class.py.jinja +0 -0
  66. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/pydanticgen/templates/conditional_import.py.jinja +0 -0
  67. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/pydanticgen/templates/enum.py.jinja +0 -0
  68. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/pydanticgen/templates/footer.py.jinja +0 -0
  69. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/pydanticgen/templates/imports.py.jinja +0 -0
  70. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/pydanticgen/templates/module.py.jinja +0 -0
  71. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/pydanticgen/templates/validator.py.jinja +0 -0
  72. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/rdfgen.py +0 -0
  73. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/shacl/__init__.py +0 -0
  74. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/shacl/ifabsent_processor.py +0 -0
  75. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/shacl/shacl_data_type.py +0 -0
  76. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/shexgen.py +0 -0
  77. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/sparqlgen.py +0 -0
  78. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/sqlalchemy/__init__.py +0 -0
  79. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/sqlalchemy/sqlalchemy_declarative_template.py +0 -0
  80. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/sqlalchemy/sqlalchemy_imperative_template.py +0 -0
  81. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/sqltablegen.py +0 -0
  82. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/sssomgen.py +0 -0
  83. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/string_template.md +0 -0
  84. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/summarygen.py +0 -0
  85. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/terminusdbgen.py +0 -0
  86. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/typescriptgen.py +0 -0
  87. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/yamlgen.py +0 -0
  88. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/generators/yumlgen.py +0 -0
  89. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/linter/__init__.py +0 -0
  90. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/linter/cli.py +0 -0
  91. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/linter/config/datamodel/.linkmllint.yaml +0 -0
  92. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/linter/config/datamodel/__init__.py +0 -0
  93. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/linter/config/datamodel/config.py +0 -0
  94. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/linter/config/datamodel/config.yaml +0 -0
  95. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/linter/config/default.yaml +0 -0
  96. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/linter/config/recommended.yaml +0 -0
  97. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/linter/formatters/__init__.py +0 -0
  98. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/linter/formatters/formatter.py +0 -0
  99. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/linter/formatters/json_formatter.py +0 -0
  100. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/linter/formatters/markdown_formatter.py +0 -0
  101. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/linter/formatters/terminal_formatter.py +0 -0
  102. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/linter/formatters/tsv_formatter.py +0 -0
  103. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/linter/linter.py +0 -0
  104. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/reporting/__init__.py +0 -0
  105. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/reporting/model.py +0 -0
  106. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/transformers/__init__.py +0 -0
  107. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/transformers/model_transformer.py +0 -0
  108. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/transformers/relmodel_transformer.py +0 -0
  109. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/transformers/schema_renamer.py +0 -0
  110. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/utils/__init__.py +0 -0
  111. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/utils/cli_utils.py +0 -0
  112. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/utils/converter.py +0 -0
  113. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/utils/datautils.py +0 -0
  114. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/utils/datavalidator.py +0 -0
  115. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/utils/deprecation.py +0 -0
  116. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/utils/execute_tutorial.py +0 -0
  117. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/utils/generator.py +0 -0
  118. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/utils/helpers.py +0 -0
  119. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/utils/ifabsent_functions.py +0 -0
  120. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/utils/logictools.py +0 -0
  121. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/utils/mergeutils.py +0 -0
  122. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/utils/rawloader.py +0 -0
  123. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/utils/schema_builder.py +0 -0
  124. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/utils/schema_fixer.py +0 -0
  125. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/utils/sqlutils.py +0 -0
  126. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/utils/typereferences.py +0 -0
  127. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/utils/validation.py +0 -0
  128. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/validator/cli.py +0 -0
  129. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/validator/loaders/__init__.py +0 -0
  130. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/validator/loaders/delimited_file_loader.py +0 -0
  131. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/validator/loaders/json_loader.py +0 -0
  132. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/validator/loaders/loader.py +0 -0
  133. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/validator/loaders/passthrough_loader.py +0 -0
  134. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/validator/loaders/yaml_loader.py +0 -0
  135. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/validator/plugins/jsonschema_validation_plugin.py +0 -0
  136. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/validator/plugins/pydantic_validation_plugin.py +0 -0
  137. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/validator/plugins/recommended_slots_plugin.py +0 -0
  138. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/validator/plugins/shacl_validation_plugin.py +0 -0
  139. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/validator/plugins/validation_plugin.py +0 -0
  140. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/validator/report.py +0 -0
  141. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/validator/validation_context.py +0 -0
  142. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/validator/validator.py +0 -0
  143. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/validators/__init__.py +0 -0
  144. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/validators/jsonschemavalidator.py +0 -0
  145. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/validators/sparqlvalidator.py +0 -0
  146. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/workspaces/__init__.py +0 -0
  147. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/workspaces/datamodel/__init__.py +0 -0
  148. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/workspaces/datamodel/workspaces.py +0 -0
  149. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/workspaces/datamodel/workspaces.yaml +0 -0
  150. {linkml-1.7.11rc1 → linkml-1.8.0}/linkml/workspaces/example_runner.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: linkml
3
- Version: 1.7.11rc1
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 (>=1.7.4)
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)
@@ -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(yamlfile, classes: List[str], max_hops: Optional[int], follow_references: bool, **args):
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(gen.serialize_classes(classes, follow_references=follow_references, max_hops=max_hops))
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
 
@@ -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__
@@ -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
@@ -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
 
@@ -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
@@ -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):
@@ -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
+ )
@@ -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:
@@ -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
  [tool.poetry]
2
2
  name = "linkml"
3
- version = "1.7.11rc1"
3
+ version = "1.8.0"
4
4
  description = "Linked Open Data Modeling Language"
5
5
  authors = [
6
6
  "Chris Mungall <cjmungall@lbl.gov>",
@@ -107,7 +107,7 @@ jinja2 = ">= 3.1.0"
107
107
  jsonasobj2 = "==1.*,>=1.0.0,>=1.0.3"
108
108
  jsonschema = {extras = ["format"], version = ">=4.0.0"}
109
109
  linkml-dataops = "*"
110
- linkml-runtime = ">=1.7.4"
110
+ linkml-runtime = "1.8.0"
111
111
  openpyxl = "*"
112
112
  parse = "*"
113
113
  prefixcommons = ">=0.1.7"
@@ -38,7 +38,7 @@ install_requires = \
38
38
  'jsonasobj2>=1.0.3,<2.0.0',
39
39
  'jsonschema[format]>=4.0.0',
40
40
  'linkml-dataops',
41
- 'linkml-runtime>=1.7.4',
41
+ 'linkml-runtime==1.8.0',
42
42
  'openpyxl',
43
43
  'parse',
44
44
  'prefixcommons>=0.1.7',
@@ -114,7 +114,7 @@ entry_points = \
114
114
 
115
115
  setup_kwargs = {
116
116
  'name': 'linkml',
117
- 'version': '1.7.11rc1',
117
+ 'version': '1.8.0',
118
118
  'description': 'Linked Open Data Modeling Language',
119
119
  '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',
120
120
  'author': 'Chris Mungall',
File without changes
File without changes
File without changes
File without changes
File without changes