linkml 1.8.6__tar.gz → 1.9.0rc1__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 (163) hide show
  1. {linkml-1.8.6 → linkml-1.9.0rc1}/PKG-INFO +1 -1
  2. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/docgen/class.md.jinja2 +1 -1
  3. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/docgen/enum.md.jinja2 +1 -1
  4. linkml-1.9.0rc1/linkml/generators/docgen/schema.md.jinja2 +7 -0
  5. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/docgen/slot.md.jinja2 +4 -1
  6. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/docgen/subset.md.jinja2 +1 -1
  7. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/docgen/type.md.jinja2 +1 -1
  8. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/jsonldgen.py +1 -3
  9. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/jsonschemagen.py +11 -0
  10. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/linkmlgen.py +10 -2
  11. linkml-1.9.0rc1/linkml/generators/mermaidclassdiagramgen.py +133 -0
  12. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/owlgen.py +5 -13
  13. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/shacl/shacl_ifabsent_processor.py +2 -1
  14. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/shaclgen.py +10 -1
  15. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/shexgen.py +1 -3
  16. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/summarygen.py +1 -3
  17. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/yamlgen.py +1 -3
  18. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/transformers/logical_model_transformer.py +7 -5
  19. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/utils/generator.py +11 -2
  20. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/workspaces/example_runner.py +1 -3
  21. {linkml-1.8.6 → linkml-1.9.0rc1}/pyproject.toml +5 -3
  22. {linkml-1.8.6 → linkml-1.9.0rc1}/setup.py +3 -1
  23. linkml-1.8.6/linkml/generators/docgen/schema.md.jinja2 +0 -7
  24. {linkml-1.8.6 → linkml-1.9.0rc1}/LICENSE +0 -0
  25. {linkml-1.8.6 → linkml-1.9.0rc1}/README.md +0 -0
  26. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/__init__.py +0 -0
  27. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/_version.py +0 -0
  28. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/cli/__init__.py +0 -0
  29. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/cli/__main__.py +0 -0
  30. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/cli/main.py +0 -0
  31. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/PythonGenNotes.md +0 -0
  32. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/README.md +0 -0
  33. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/__init__.py +0 -0
  34. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/common/__init__.py +0 -0
  35. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/common/build.py +0 -0
  36. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/common/ifabsent_processor.py +0 -0
  37. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/common/lifecycle.py +0 -0
  38. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/common/naming.py +0 -0
  39. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/common/template.py +0 -0
  40. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/common/type_designators.py +0 -0
  41. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/csvgen.py +0 -0
  42. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/dbmlgen.py +0 -0
  43. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/docgen/class_diagram.md.jinja2 +0 -0
  44. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/docgen/common_metadata.md.jinja2 +0 -0
  45. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/docgen/index.md.jinja2 +0 -0
  46. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/docgen/index.tex.jinja2 +0 -0
  47. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/docgen.py +0 -0
  48. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/dotgen.py +0 -0
  49. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/erdiagramgen.py +0 -0
  50. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/excelgen.py +0 -0
  51. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/golanggen.py +0 -0
  52. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/golrgen.py +0 -0
  53. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/graphqlgen.py +0 -0
  54. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/javagen/example_template.java.jinja2 +0 -0
  55. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/javagen/java_record_template.jinja2 +0 -0
  56. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/javagen.py +0 -0
  57. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/jsonldcontextgen.py +0 -0
  58. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/legacy/__init__.py +0 -0
  59. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/markdowngen.py +0 -0
  60. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/namespacegen.py +0 -0
  61. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/oocodegen.py +0 -0
  62. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/plantumlgen.py +0 -0
  63. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/prefixmapgen.py +0 -0
  64. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/projectgen.py +0 -0
  65. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/protogen.py +0 -0
  66. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/pydanticgen/__init__.py +0 -0
  67. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/pydanticgen/array.py +0 -0
  68. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/pydanticgen/black.py +0 -0
  69. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/pydanticgen/build.py +0 -0
  70. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/pydanticgen/includes.py +0 -0
  71. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/pydanticgen/pydanticgen.py +0 -0
  72. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/pydanticgen/template.py +0 -0
  73. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/pydanticgen/templates/attribute.py.jinja +0 -0
  74. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/pydanticgen/templates/base_model.py.jinja +0 -0
  75. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/pydanticgen/templates/class.py.jinja +0 -0
  76. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/pydanticgen/templates/conditional_import.py.jinja +0 -0
  77. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/pydanticgen/templates/enum.py.jinja +0 -0
  78. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/pydanticgen/templates/footer.py.jinja +0 -0
  79. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/pydanticgen/templates/imports.py.jinja +0 -0
  80. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/pydanticgen/templates/module.py.jinja +0 -0
  81. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/pydanticgen/templates/validator.py.jinja +0 -0
  82. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/python/__init__.py +0 -0
  83. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/python/python_ifabsent_processor.py +0 -0
  84. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/pythongen.py +0 -0
  85. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/rdfgen.py +0 -0
  86. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/shacl/__init__.py +0 -0
  87. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/shacl/shacl_data_type.py +0 -0
  88. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/sparqlgen.py +0 -0
  89. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/sqlalchemy/__init__.py +0 -0
  90. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/sqlalchemy/sqlalchemy_declarative_template.py +0 -0
  91. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/sqlalchemy/sqlalchemy_imperative_template.py +0 -0
  92. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/sqlalchemygen.py +0 -0
  93. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/sqltablegen.py +0 -0
  94. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/sssomgen.py +0 -0
  95. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/string_template.md +0 -0
  96. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/terminusdbgen.py +0 -0
  97. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/typescriptgen.py +0 -0
  98. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/generators/yumlgen.py +0 -0
  99. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/linter/__init__.py +0 -0
  100. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/linter/cli.py +0 -0
  101. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/linter/config/datamodel/.linkmllint.yaml +0 -0
  102. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/linter/config/datamodel/__init__.py +0 -0
  103. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/linter/config/datamodel/config.py +0 -0
  104. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/linter/config/datamodel/config.yaml +0 -0
  105. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/linter/config/default.yaml +0 -0
  106. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/linter/config/recommended.yaml +0 -0
  107. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/linter/formatters/__init__.py +0 -0
  108. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/linter/formatters/formatter.py +0 -0
  109. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/linter/formatters/json_formatter.py +0 -0
  110. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/linter/formatters/markdown_formatter.py +0 -0
  111. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/linter/formatters/terminal_formatter.py +0 -0
  112. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/linter/formatters/tsv_formatter.py +0 -0
  113. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/linter/linter.py +0 -0
  114. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/linter/rules.py +0 -0
  115. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/reporting/__init__.py +0 -0
  116. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/reporting/model.py +0 -0
  117. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/transformers/__init__.py +0 -0
  118. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/transformers/model_transformer.py +0 -0
  119. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/transformers/relmodel_transformer.py +0 -0
  120. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/transformers/schema_renamer.py +0 -0
  121. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/utils/__init__.py +0 -0
  122. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/utils/cli_utils.py +0 -0
  123. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/utils/converter.py +0 -0
  124. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/utils/datautils.py +0 -0
  125. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/utils/datavalidator.py +0 -0
  126. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/utils/deprecation.py +0 -0
  127. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/utils/exceptions.py +0 -0
  128. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/utils/execute_tutorial.py +0 -0
  129. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/utils/helpers.py +0 -0
  130. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/utils/logictools.py +0 -0
  131. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/utils/mergeutils.py +0 -0
  132. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/utils/rawloader.py +0 -0
  133. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/utils/schema_builder.py +0 -0
  134. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/utils/schema_fixer.py +0 -0
  135. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/utils/schemaloader.py +0 -0
  136. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/utils/schemasynopsis.py +0 -0
  137. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/utils/sqlutils.py +0 -0
  138. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/utils/typereferences.py +0 -0
  139. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/utils/validation.py +0 -0
  140. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/validator/__init__.py +0 -0
  141. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/validator/cli.py +0 -0
  142. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/validator/loaders/__init__.py +0 -0
  143. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/validator/loaders/delimited_file_loader.py +0 -0
  144. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/validator/loaders/json_loader.py +0 -0
  145. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/validator/loaders/loader.py +0 -0
  146. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/validator/loaders/passthrough_loader.py +0 -0
  147. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/validator/loaders/yaml_loader.py +0 -0
  148. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/validator/plugins/__init__.py +0 -0
  149. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/validator/plugins/jsonschema_validation_plugin.py +0 -0
  150. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/validator/plugins/pydantic_validation_plugin.py +0 -0
  151. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/validator/plugins/recommended_slots_plugin.py +0 -0
  152. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/validator/plugins/shacl_validation_plugin.py +0 -0
  153. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/validator/plugins/validation_plugin.py +0 -0
  154. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/validator/report.py +0 -0
  155. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/validator/validation_context.py +0 -0
  156. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/validator/validator.py +0 -0
  157. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/validators/__init__.py +0 -0
  158. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/validators/jsonschemavalidator.py +0 -0
  159. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/validators/sparqlvalidator.py +0 -0
  160. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/workspaces/__init__.py +0 -0
  161. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/workspaces/datamodel/__init__.py +0 -0
  162. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/workspaces/datamodel/workspaces.py +0 -0
  163. {linkml-1.8.6 → linkml-1.9.0rc1}/linkml/workspaces/datamodel/workspaces.yaml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: linkml
3
- Version: 1.8.6
3
+ Version: 1.9.0rc1
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
@@ -21,7 +21,7 @@
21
21
  {%- endif -%}
22
22
  {% endmacro %}
23
23
 
24
- # Class: {{ title }}
24
+ # Class: {{ title }} {% if element.deprecated %} <span style="color: red;"><strong> (DEPRECATED) </strong> {% endif %}
25
25
 
26
26
  {%- if header -%}
27
27
  {{header}}
@@ -1,4 +1,4 @@
1
- # Enum: {{ gen.name(element) }}
1
+ # Enum: {{ gen.name(element) }} {% if element.deprecated %} <span style="color: red;"><strong> (DEPRECATED) </strong> {% endif %}
2
2
 
3
3
  {% if element.description %}
4
4
  {% set element_description_lines = element.description.split('\n') %}
@@ -0,0 +1,7 @@
1
+ # {{ schema.name }} {% if schema.deprecated %} <span style="color: red;"><strong> (DEPRECATED) </strong> {% endif %}
2
+
3
+ {{ schema.description }}
4
+
5
+ URI: {{ schema.id }}
6
+
7
+
@@ -21,7 +21,7 @@
21
21
  {%- endif -%}
22
22
  {% endmacro %}
23
23
 
24
- # Slot: {{ title }}
24
+ # Slot: {{ title }} {% if element.deprecated %} <span style="color: red;"><strong> (DEPRECATED) </strong> {% endif %}
25
25
 
26
26
  {%- if header -%}
27
27
  {{header}}
@@ -40,6 +40,9 @@ _{{ element_description_line }}_
40
40
 
41
41
  URI: {{ gen.uri_link(element) }}
42
42
 
43
+ {%- if element.alias %}
44
+ Alias: {{ element.alias }}
45
+ {% endif -%}
43
46
 
44
47
  {% if schemaview.slot_parents(element.name) or schemaview.slot_children(element.name, mixins=False) %}
45
48
 
@@ -1,4 +1,4 @@
1
- # Subset: {{ gen.name(element) }}
1
+ # Subset: {{ gen.name(element) }} {% if element.deprecated %} <span style="color: red;"><strong> (DEPRECATED) </strong> {% endif %}
2
2
 
3
3
  {%- if header -%}
4
4
  {{ header }}
@@ -1,4 +1,4 @@
1
- # Type: {{ gen.name(element) }}
1
+ # Type: {{ gen.name(element) }} {% if element.deprecated %} <span style="color: red;"><strong> (DEPRECATED) </strong> {% endif %}
2
2
 
3
3
  {% if element.description %}
4
4
  {% set element_description_lines = element.description.split('\n') %}
@@ -1,6 +1,4 @@
1
- """ Generate JSONld
2
-
3
- """
1
+ """Generate JSONld from a LinkML schema."""
4
2
 
5
3
  import os
6
4
  from copy import deepcopy
@@ -237,6 +237,7 @@ class JsonSchemaGenerator(Generator, LifecycleMixin):
237
237
  valid_formats = ["json"]
238
238
  uses_schemaloader = False
239
239
  file_extension = "schema.json"
240
+ materialize_patterns: bool = False
240
241
 
241
242
  # @deprecated("Use top_class")
242
243
  topClass: Optional[str] = None
@@ -690,6 +691,10 @@ class JsonSchemaGenerator(Generator, LifecycleMixin):
690
691
  return self.top_level_schema
691
692
 
692
693
  def serialize(self, **kwargs) -> str:
694
+ if self.materialize_patterns:
695
+ logger.info("Materializing patterns in the schema before serialization")
696
+ self.schemaview.materialize_patterns()
697
+
693
698
  return self.generate().to_json(sort_keys=True, indent=self.indent if self.indent > 0 else None)
694
699
 
695
700
 
@@ -752,6 +757,12 @@ Include LinkML Schema outside of imports mechanism. Helpful in including deprec
752
757
  YAML, and including it when necessary but not by default (e.g. in documentation or for backwards compatibility)
753
758
  """,
754
759
  )
760
+ @click.option(
761
+ "--materialize-patterns/--no-materialize-patterns",
762
+ default=True, # Default set to True
763
+ show_default=True,
764
+ help="If set, patterns will be materialized in the generated JSON Schema.",
765
+ )
755
766
  @click.version_option(__version__, "-V", "--version")
756
767
  def cli(yamlfile, **kwargs):
757
768
  """Generate JSON Schema representation of a LinkML model"""
@@ -114,8 +114,16 @@ def cli(
114
114
  ):
115
115
  # You can use the `--materialize` / `--no-materialize` for control
116
116
  # over both attribute and pattern materialization.
117
- materialize_attributes = bool(materialize)
118
- materialize_patterns = bool(materialize)
117
+
118
+ # If the user did not explicitly specify materialize_attributes,
119
+ # fall back to the umbrella materialize flag.
120
+ if materialize_attributes is None:
121
+ materialize_attributes = materialize
122
+
123
+ # If the user did not explicitly specify materialize_patterns,
124
+ # fall back to the umbrella materialize flag.
125
+ if materialize_patterns is None:
126
+ materialize_patterns = materialize
119
127
 
120
128
  gen = LinkmlGenerator(
121
129
  yamlfile,
@@ -0,0 +1,133 @@
1
+ import importlib
2
+ import logging
3
+ import os
4
+ from dataclasses import dataclass, field
5
+ from pathlib import Path
6
+ from typing import List, Optional
7
+
8
+ import click
9
+ from jinja2 import Environment, FileSystemLoader
10
+ from linkml_runtime.linkml_model.meta import Element, SlotDefinition
11
+ from linkml_runtime.utils.schemaview import SchemaView
12
+
13
+ from linkml.generators.docgen import DocGenerator, customize_environment
14
+ from linkml.utils.generator import Generator, shared_arguments
15
+
16
+
17
+ @dataclass
18
+ class MermaidClassDiagramGenerator(Generator):
19
+ """This generator creates Mermaid Class diagrams (https://mermaid.js.org/syntax/classDiagram.html)
20
+ for individual classes in a given LinkML schema and outputs them as Markdown files. It uses
21
+ a jinja template to render these class diagrams, which can be customized by the user and pointed
22
+ to using the `--template-file` option. If no template is provided, then the default template
23
+ file provided by LinkML and present at linkml/generators/docgen/class_diagram.md.jinja2 will be used.
24
+ The generator also has the option of specifying a certain set of classes for which you want the
25
+ class diagrams to be generated by using the `--classes` option.
26
+ """
27
+
28
+ generatorname = os.path.basename(__file__)
29
+ generatorversion = "0.0.1"
30
+ valid_formats = ["markdown"]
31
+ uses_schemaloader = False
32
+ requires_metamodel = False
33
+
34
+ directory: Optional[str] = None # output directory with generated markdown files
35
+ template_file: Optional[str] = None # custom/default jinja template for class diagrams
36
+ classes: List[str] = field(default_factory=list) # optional subset of classes
37
+
38
+ def __post_init__(self):
39
+ super().__post_init__()
40
+ self.logger = logging.getLogger(__name__)
41
+ self.schemaview = SchemaView(self.schema, merge_imports=self.mergeimports)
42
+
43
+ # set the output directory
44
+ self.output_directory = Path(self.directory)
45
+
46
+ # set the template file
47
+ if not self.template_file:
48
+ package_dir = os.path.dirname(importlib.util.find_spec("linkml").origin)
49
+ # Default location of the template file
50
+ self.template_file = os.path.join(package_dir, "generators", "docgen", "class_diagram.md.jinja2")
51
+
52
+ def generate_class_diagrams(self):
53
+ """Generate Mermaid class diagrams for the specified subset of classes
54
+ or all classes if none are specified.
55
+ """
56
+ self.output_directory.mkdir(parents=True, exist_ok=True)
57
+
58
+ template_folder = os.path.dirname(self.template_file)
59
+ template_name = os.path.basename(self.template_file)
60
+ loader = FileSystemLoader(template_folder)
61
+ env = Environment(loader=loader)
62
+ customize_environment(env)
63
+
64
+ template = env.get_template(template_name)
65
+
66
+ all_classes = self.schemaview.all_classes()
67
+
68
+ if self.classes:
69
+ class_items = [(cn, all_classes[cn]) for cn in self.classes if cn in all_classes]
70
+ else:
71
+ class_items = list(all_classes.items())
72
+
73
+ for cn, class_def in class_items:
74
+ self.logger.info(f"Generating Mermaid diagram for class: {cn}")
75
+ rendered = template.render(gen=self, element=class_def, schemaview=self.schemaview)
76
+ outfile = self.output_directory / f"{cn}.md"
77
+ with open(outfile, "w", encoding="utf-8") as f:
78
+ f.write(rendered)
79
+
80
+ def cardinality(self, slot: SlotDefinition) -> str:
81
+ """Reuses the cardinality logic from DocGenerator."""
82
+ return DocGenerator.cardinality(slot)
83
+
84
+ def mermaid_directive(self) -> str:
85
+ """Provides the code fence directive (e.g., `mermaid` or `{mermaid}`)."""
86
+ return "mermaid"
87
+
88
+ def name(self, element: Element) -> str:
89
+ """Returns the canonical name for an element."""
90
+ return element.name
91
+
92
+ def all_type_object_names(self):
93
+ return list(self.schemaview.all_types().keys())
94
+
95
+
96
+ @shared_arguments(MermaidClassDiagramGenerator)
97
+ @click.command()
98
+ @click.option(
99
+ "--template-file",
100
+ "-t",
101
+ type=click.Path(exists=True),
102
+ default=None,
103
+ help="Path to Jinja template for class diagrams.",
104
+ )
105
+ @click.option(
106
+ "--directory",
107
+ "-d",
108
+ type=click.Path(),
109
+ required=True,
110
+ help="Folder in which to write the Markdown files.",
111
+ )
112
+ @click.option(
113
+ "--classes",
114
+ "-c",
115
+ multiple=True,
116
+ help="One or more classes in the schema for which to generate diagrams. "
117
+ "If omitted, diagrams for all classes are generated.",
118
+ )
119
+ @click.version_option(click.__version__, "-V", "--version")
120
+ def cli(yamlfile, template_file, directory, classes, **args):
121
+ logging.basicConfig(level=logging.INFO)
122
+ gen = MermaidClassDiagramGenerator(
123
+ schema=yamlfile,
124
+ template_file=template_file,
125
+ directory=directory,
126
+ classes=list(classes), # convert tuple to a list
127
+ **args,
128
+ )
129
+ gen.generate_class_diagrams()
130
+
131
+
132
+ if __name__ == "__main__":
133
+ cli()
@@ -708,18 +708,10 @@ class OwlSchemaGenerator(Generator):
708
708
  owl_exprs.append(eq_uri)
709
709
  if element.equals_string_in:
710
710
  equals_string_in = element.equals_string_in
711
- if is_literal is None:
712
- logger.warning(f"ignoring equals_string={equals_string_in} as unable to tell if literal")
713
- elif is_literal:
714
- dt_exprs = [
715
- self._datatype_restriction(XSD.string, [self._facet(XSD.pattern, s)]) for s in equals_string_in
716
- ]
717
- union_expr = self._union_of(dt_exprs, owl_types={RDFS.Literal})
718
- owl_exprs.append(union_expr)
719
- owl_types.add(RDFS.Literal)
720
- else:
721
- eq_uris = [URIRef(self.schemaview.expand_curie(s)) for s in equals_string_in]
722
- owl_exprs.append(self._union_of(eq_uris))
711
+ literals = [Literal(s) for s in equals_string_in]
712
+ one_of_expr = self._boolean_expression(literals, OWL.oneOf, owl_types={RDFS.Literal})
713
+ owl_exprs.append(one_of_expr)
714
+ owl_types.add(RDFS.Literal)
723
715
  for constraint_prop, constraint_val in constraints.items():
724
716
  if is_literal is not None and not is_literal:
725
717
  # In LinkML, it is permissible to have a literal constraints on slots that refer to
@@ -1140,7 +1132,7 @@ class OwlSchemaGenerator(Generator):
1140
1132
 
1141
1133
  def _boolean_expression(
1142
1134
  self,
1143
- exprs: List[Union[BNode, URIRef]],
1135
+ exprs: List[Union[BNode, URIRef, Literal]],
1144
1136
  predicate: URIRef,
1145
1137
  node: Optional[URIRef] = None,
1146
1138
  owl_types: Set[OWL_TYPE] = None,
@@ -62,7 +62,8 @@ class ShaclIfAbsentProcessor(IfAbsentProcessor):
62
62
  return Literal(f"{year}-{month}-{day}T{hour}:{minutes}:{seconds}", datatype=ShaclDataType.DATETIME.uri_ref)
63
63
 
64
64
  def map_uri_or_curie_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
65
- raise NotImplementedError()
65
+ uri = URIRef(self.schema_view.expand_curie(default_value))
66
+ return Literal(uri, datatype=ShaclDataType.URI.uri_ref)
66
67
 
67
68
  def map_curie_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
68
69
  return Literal(default_value, datatype=ShaclDataType.CURIE.uri_ref)
@@ -30,6 +30,8 @@ class ShaclGenerator(Generator):
30
30
  """parameterized suffix to be appended. No suffix per default."""
31
31
  include_annotations: bool = False
32
32
  """True means include all class / slot / type annotations in generated Node or Property shapes"""
33
+ exclude_imports: bool = False
34
+ """If True, elements from imported ontologies won't be included in the generator's output"""
33
35
  generatorname = os.path.basename(__file__)
34
36
  generatorversion = "0.0.1"
35
37
  valid_formats = ["ttl"]
@@ -63,7 +65,7 @@ class ShaclGenerator(Generator):
63
65
  for pfx in self.schema.prefixes.values():
64
66
  g.bind(str(pfx.prefix_prefix), pfx.prefix_reference)
65
67
 
66
- for c in sv.all_classes().values():
68
+ for c in sv.all_classes(imports=not self.exclude_imports).values():
67
69
 
68
70
  def shape_pv(p, v):
69
71
  if v is not None:
@@ -364,6 +366,13 @@ def add_simple_data_type(func: Callable, r: ElementName) -> None:
364
366
  show_default=True,
365
367
  help="Use --include-annotations to include annotations of slots, types, and classes in the generated SHACL shapes.",
366
368
  )
369
+ @click.option(
370
+ "--exclude-imports/--include-imports",
371
+ default=False,
372
+ show_default=True,
373
+ help="Use --exclude-imports to exclude imported elements from the generated SHACL shapes. This is useful when "
374
+ "extending a substantial ontology to avoid large output files.",
375
+ )
367
376
  @click.version_option(__version__, "-V", "--version")
368
377
  def cli(yamlfile, **args):
369
378
  """Generate SHACL turtle from a LinkML model"""
@@ -1,6 +1,4 @@
1
- """Generate ShEx definition of a model
2
-
3
- """
1
+ """Generate ShEx definition of a model"""
4
2
 
5
3
  import os
6
4
  import urllib.parse as urlparse
@@ -1,6 +1,4 @@
1
- """Generate Summary Spreadsheets
2
-
3
- """
1
+ """Generate Summary Spreadsheets"""
4
2
 
5
3
  import os
6
4
  from csv import DictWriter
@@ -1,6 +1,4 @@
1
- """Validate linkml input and optionally emit completely resolved biolink yaml output
2
-
3
- """
1
+ """Validate linkml input and optionally emit completely resolved biolink yaml output"""
4
2
 
5
3
  import os
6
4
  from dataclasses import dataclass
@@ -409,11 +409,13 @@ class LogicalModelTransformer(ModelTransformer):
409
409
  target_class_name: ClassDefinitionName,
410
410
  ancestors: List[ClassDefinitionName],
411
411
  ):
412
- anc_classes = [self.schemaview.get_class(anc) for anc in ancestors]
412
+ anc_classes = [self.schemaview.get_class(ancestor) for ancestor in ancestors]
413
413
  attributes: Dict[SlotDefinitionName, SlotDefinition] = {}
414
- for anc in anc_classes:
415
- top_level_slots = [(s, target_schema.slots[s]) for s in anc.slots]
416
- for slot_name, slot_expr in list(anc.attributes.items()) + list(anc.slot_usage.items()) + top_level_slots:
414
+ for ancestor_class in anc_classes:
415
+ top_level_slots = [(s, target_schema.slots[s]) for s in ancestor_class.slots]
416
+ for slot_name, slot_expr in (
417
+ list(ancestor_class.attributes.items()) + list(ancestor_class.slot_usage.items()) + top_level_slots
418
+ ):
417
419
  if slot_name not in attributes:
418
420
  attributes[slot_name] = SlotDefinition(slot_name)
419
421
  sx = attributes[slot_name]
@@ -644,7 +646,7 @@ class LogicalModelTransformer(ModelTransformer):
644
646
  if slot_expression.all_of:
645
647
  exprs.append(logictools.And(*[self._as_logical_expression(subx) for subx in slot_expression.all_of]))
646
648
  if slot_expression.exactly_one_of:
647
- # TODO: disjointness
649
+ # TODO: disjointedness
648
650
  exprs.append(logictools.Or(*[self._as_logical_expression(subx) for subx in slot_expression.exactly_one_of]))
649
651
  if slot_expression.none_of:
650
652
  exprs.append(
@@ -27,6 +27,7 @@ from typing import Callable, ClassVar, Dict, List, Mapping, Optional, Set, TextI
27
27
 
28
28
  import click
29
29
  from click import Argument, Command, Option
30
+ from jsonasobj2 import JsonObj
30
31
  from linkml_runtime import SchemaView
31
32
  from linkml_runtime.linkml_model.meta import (
32
33
  ClassDefinition,
@@ -265,8 +266,16 @@ class Generator(metaclass=abc.ABCMeta):
265
266
  def _init_namespaces(self):
266
267
  if self.namespaces is None:
267
268
  self.namespaces = Namespaces()
268
- for prefix in self.schema.prefixes.values():
269
- self.namespaces[prefix.prefix_prefix] = prefix.prefix_reference
269
+ if isinstance(self.schema.prefixes, dict):
270
+ for key, value in self.schema.prefixes.items():
271
+ self.namespaces[key] = value
272
+ elif isinstance(self.schema.prefixes, JsonObj):
273
+ prefixes = vars(self.schema.prefixes)
274
+ for key, value in prefixes.items():
275
+ self.namespaces[key] = value
276
+ else:
277
+ for prefix in self.schema.prefixes.values():
278
+ self.namespaces[prefix.prefix_prefix] = prefix.prefix_reference
270
279
 
271
280
  def serialize(self, **kwargs) -> str:
272
281
  """
@@ -1,6 +1,4 @@
1
- """Iterate through all examples in a folder testing them for validity.
2
-
3
- """
1
+ """Iterate through all examples in a folder testing them for validity."""
4
2
 
5
3
  import glob
6
4
  import json
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "linkml"
3
- version = "1.8.6"
3
+ version = "1.9.0rc1"
4
4
  description = "Linked Open Data Modeling Language"
5
5
  authors = [
6
6
  "Chris Mungall <cjmungall@lbl.gov>",
@@ -93,6 +93,7 @@ linkml-run-examples = "linkml.workspaces.example_runner:cli"
93
93
  gen-excel = "linkml.generators.excelgen:cli"
94
94
  gen-sssom = "linkml.generators.sssomgen:cli"
95
95
  gen-linkml = "linkml.generators.linkmlgen:cli"
96
+ gen-mermaid-class-diagram = "linkml.generators.mermaidclassdiagramgen:cli"
96
97
  linkml-schema-fixer = "linkml.utils.schema_fixer:main"
97
98
 
98
99
  [tool.poetry.dependencies]
@@ -177,11 +178,11 @@ build-backend = "poetry_dynamic_versioning.backend"
177
178
 
178
179
  [tool.codespell]
179
180
  # TODO: bring in tests in too
180
- skip = '.git,*.pdf,*.svg,./tests,pyproject.toml,*.dill,poetry.lock'
181
+ skip = '.git,*.pdf,*.svg,./tests,pyproject.toml,*.dill,poetry.lock,./notebooks/DistributedModels.ipynb'
181
182
  # Ignore table where words could be split across rows
182
183
  # Ignore shortcut specifications like [Ff]alse
183
184
  ignore-regex = '(\|.*\|.*\|.*\||\[[A-Z][a-z]\][a-z][a-z])'
184
- ignore-words-list = 'mater,connexion,infarction,thirdparty,linke'
185
+ ignore-words-list = 'anc,mater,connexion,infarction,thirdparty,linke'
185
186
  quiet-level = 3
186
187
 
187
188
  [tool.black]
@@ -210,6 +211,7 @@ markers = [
210
211
  "slow: mark test as slow to run",
211
212
  "no_asserts: tests that don't have meaningful asserts, but are only snapshot comparisons, or historically had print statements, or other non-erroring behavior",
212
213
  "strcmp: tests that compare stringified values rather than the values themselves",
214
+ "biolink: tests that validate that the biolink model is unchanged",
213
215
  "docker: tests that require a running docker server",
214
216
  "plantumlgen: Tests for the plantuml generator",
215
217
  "pydanticgen_split: Split module generation in pydanticgen",
@@ -81,6 +81,8 @@ entry_points = \
81
81
  'linkml.generators.jsonldcontextgen:cli',
82
82
  'gen-linkml = linkml.generators.linkmlgen:cli',
83
83
  'gen-markdown = linkml.generators.markdowngen:cli',
84
+ 'gen-mermaid-class-diagram = '
85
+ 'linkml.generators.mermaidclassdiagramgen:cli',
84
86
  'gen-namespaces = linkml.generators.namespacegen:cli',
85
87
  'gen-owl = linkml.generators.owlgen:cli',
86
88
  'gen-plantuml = linkml.generators.plantumlgen:cli',
@@ -119,7 +121,7 @@ entry_points = \
119
121
 
120
122
  setup_kwargs = {
121
123
  'name': 'linkml',
122
- 'version': '1.8.6',
124
+ 'version': '1.9.0rc1',
123
125
  'description': 'Linked Open Data Modeling Language',
124
126
  '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',
125
127
  'author': 'Chris Mungall',
@@ -1,7 +0,0 @@
1
- # {{ schema.name }}
2
-
3
- {{ schema.description }}
4
-
5
- URI: {{ schema.id }}
6
-
7
-
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