linkml 1.7.4__tar.gz → 1.7.6__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 (147) hide show
  1. {linkml-1.7.4 → linkml-1.7.6}/PKG-INFO +4 -1
  2. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/__init__.py +2 -0
  3. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/docgen/class.md.jinja2 +15 -2
  4. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/docgen/slot.md.jinja2 +14 -1
  5. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/docgen.py +32 -11
  6. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/excelgen.py +5 -3
  7. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/golanggen.py +6 -3
  8. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/jsonldcontextgen.py +9 -6
  9. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/jsonldgen.py +3 -1
  10. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/oocodegen.py +6 -3
  11. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/owlgen.py +30 -3
  12. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/prefixmapgen.py +5 -4
  13. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/projectgen.py +18 -5
  14. linkml-1.7.6/linkml/generators/pydanticgen/__init__.py +29 -0
  15. {linkml-1.7.4/linkml/generators → linkml-1.7.6/linkml/generators/pydanticgen}/pydanticgen.py +196 -301
  16. linkml-1.7.6/linkml/generators/pydanticgen/template.py +504 -0
  17. linkml-1.7.6/linkml/generators/pydanticgen/templates/attribute.py.jinja +10 -0
  18. linkml-1.7.6/linkml/generators/pydanticgen/templates/base_model.py.jinja +27 -0
  19. linkml-1.7.6/linkml/generators/pydanticgen/templates/class.py.jinja +21 -0
  20. linkml-1.7.6/linkml/generators/pydanticgen/templates/conditional_import.py.jinja +9 -0
  21. linkml-1.7.6/linkml/generators/pydanticgen/templates/enum.py.jinja +16 -0
  22. linkml-1.7.6/linkml/generators/pydanticgen/templates/footer.py.jinja +13 -0
  23. linkml-1.7.6/linkml/generators/pydanticgen/templates/imports.py.jinja +31 -0
  24. linkml-1.7.6/linkml/generators/pydanticgen/templates/module.py.jinja +27 -0
  25. linkml-1.7.6/linkml/generators/pydanticgen/templates/validator.py.jinja +15 -0
  26. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/pythongen.py +19 -10
  27. linkml-1.7.6/linkml/generators/shacl/__init__.py +3 -0
  28. linkml-1.7.6/linkml/generators/shacl/ifabsent_processor.py +41 -0
  29. linkml-1.7.6/linkml/generators/shacl/shacl_data_type.py +40 -0
  30. linkml-1.7.6/linkml/generators/shaclgen.py +229 -0
  31. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/shexgen.py +1 -1
  32. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/sparqlgen.py +5 -4
  33. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/sqlalchemygen.py +15 -14
  34. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/sqltablegen.py +37 -25
  35. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/terminusdbgen.py +7 -1
  36. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/typescriptgen.py +2 -1
  37. {linkml-1.7.4 → linkml-1.7.6}/linkml/linter/config/datamodel/config.py +8 -0
  38. {linkml-1.7.4 → linkml-1.7.6}/linkml/linter/linter.py +2 -1
  39. {linkml-1.7.4 → linkml-1.7.6}/linkml/linter/rules.py +11 -2
  40. {linkml-1.7.4 → linkml-1.7.6}/linkml/transformers/logical_model_transformer.py +2 -1
  41. {linkml-1.7.4 → linkml-1.7.6}/linkml/transformers/relmodel_transformer.py +4 -2
  42. {linkml-1.7.4 → linkml-1.7.6}/linkml/transformers/schema_renamer.py +1 -1
  43. {linkml-1.7.4 → linkml-1.7.6}/linkml/utils/generator.py +11 -8
  44. {linkml-1.7.4 → linkml-1.7.6}/linkml/utils/ifabsent_functions.py +7 -9
  45. {linkml-1.7.4 → linkml-1.7.6}/linkml/utils/schema_builder.py +1 -0
  46. {linkml-1.7.4 → linkml-1.7.6}/linkml/utils/schema_fixer.py +3 -2
  47. {linkml-1.7.4 → linkml-1.7.6}/linkml/utils/schemaloader.py +1 -9
  48. {linkml-1.7.4 → linkml-1.7.6}/linkml/utils/sqlutils.py +39 -25
  49. {linkml-1.7.4 → linkml-1.7.6}/linkml/validator/validation_context.py +2 -1
  50. {linkml-1.7.4 → linkml-1.7.6}/pyproject.toml +8 -5
  51. {linkml-1.7.4 → linkml-1.7.6}/setup.py +7 -3
  52. linkml-1.7.4/linkml/generators/shaclgen.py +0 -206
  53. linkml-1.7.4/linkml/generators/sqlddlgen.py +0 -559
  54. {linkml-1.7.4 → linkml-1.7.6}/LICENSE +0 -0
  55. {linkml-1.7.4 → linkml-1.7.6}/README.md +0 -0
  56. {linkml-1.7.4 → linkml-1.7.6}/linkml/__init__.py +0 -0
  57. {linkml-1.7.4 → linkml-1.7.6}/linkml/_version.py +0 -0
  58. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/PythonGenNotes.md +0 -0
  59. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/README.md +0 -0
  60. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/common/__init__.py +0 -0
  61. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/common/type_designators.py +0 -0
  62. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/csvgen.py +0 -0
  63. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/docgen/class_diagram.md.jinja2 +0 -0
  64. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/docgen/common_metadata.md.jinja2 +0 -0
  65. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/docgen/enum.md.jinja2 +0 -0
  66. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/docgen/index.md.jinja2 +0 -0
  67. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/docgen/index.tex.jinja2 +0 -0
  68. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/docgen/schema.md.jinja2 +0 -0
  69. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/docgen/subset.md.jinja2 +0 -0
  70. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/docgen/type.md.jinja2 +0 -0
  71. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/dotgen.py +0 -0
  72. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/erdiagramgen.py +0 -0
  73. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/golrgen.py +0 -0
  74. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/graphqlgen.py +0 -0
  75. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/javagen/example_template.java.jinja2 +0 -0
  76. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/javagen/java_record_template.jinja2 +0 -0
  77. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/javagen.py +0 -0
  78. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/jsonschemagen.py +0 -0
  79. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/legacy/__init__.py +0 -0
  80. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/linkmlgen.py +0 -0
  81. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/markdowngen.py +0 -0
  82. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/namespacegen.py +0 -0
  83. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/plantumlgen.py +0 -0
  84. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/protogen.py +0 -0
  85. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/rdfgen.py +0 -0
  86. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/sqlalchemy/__init__.py +0 -0
  87. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/sqlalchemy/sqlalchemy_declarative_template.py +0 -0
  88. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/sqlalchemy/sqlalchemy_imperative_template.py +0 -0
  89. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/sssomgen.py +0 -0
  90. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/string_template.md +0 -0
  91. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/summarygen.py +0 -0
  92. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/yamlgen.py +0 -0
  93. {linkml-1.7.4 → linkml-1.7.6}/linkml/generators/yumlgen.py +0 -0
  94. {linkml-1.7.4 → linkml-1.7.6}/linkml/linter/__init__.py +0 -0
  95. {linkml-1.7.4 → linkml-1.7.6}/linkml/linter/cli.py +0 -0
  96. {linkml-1.7.4 → linkml-1.7.6}/linkml/linter/config/datamodel/.linkmllint.yaml +0 -0
  97. {linkml-1.7.4 → linkml-1.7.6}/linkml/linter/config/datamodel/__init__.py +0 -0
  98. {linkml-1.7.4 → linkml-1.7.6}/linkml/linter/config/datamodel/config.yaml +0 -0
  99. {linkml-1.7.4 → linkml-1.7.6}/linkml/linter/config/default.yaml +0 -0
  100. {linkml-1.7.4 → linkml-1.7.6}/linkml/linter/config/recommended.yaml +0 -0
  101. {linkml-1.7.4 → linkml-1.7.6}/linkml/linter/formatters/__init__.py +0 -0
  102. {linkml-1.7.4 → linkml-1.7.6}/linkml/linter/formatters/formatter.py +0 -0
  103. {linkml-1.7.4 → linkml-1.7.6}/linkml/linter/formatters/json_formatter.py +0 -0
  104. {linkml-1.7.4 → linkml-1.7.6}/linkml/linter/formatters/markdown_formatter.py +0 -0
  105. {linkml-1.7.4 → linkml-1.7.6}/linkml/linter/formatters/terminal_formatter.py +0 -0
  106. {linkml-1.7.4 → linkml-1.7.6}/linkml/linter/formatters/tsv_formatter.py +0 -0
  107. {linkml-1.7.4 → linkml-1.7.6}/linkml/reporting/__init__.py +0 -0
  108. {linkml-1.7.4 → linkml-1.7.6}/linkml/reporting/model.py +0 -0
  109. {linkml-1.7.4 → linkml-1.7.6}/linkml/transformers/__init__.py +0 -0
  110. {linkml-1.7.4 → linkml-1.7.6}/linkml/transformers/model_transformer.py +0 -0
  111. {linkml-1.7.4 → linkml-1.7.6}/linkml/utils/__init__.py +0 -0
  112. {linkml-1.7.4 → linkml-1.7.6}/linkml/utils/cli_utils.py +0 -0
  113. {linkml-1.7.4 → linkml-1.7.6}/linkml/utils/converter.py +0 -0
  114. {linkml-1.7.4 → linkml-1.7.6}/linkml/utils/datautils.py +0 -0
  115. {linkml-1.7.4 → linkml-1.7.6}/linkml/utils/datavalidator.py +0 -0
  116. {linkml-1.7.4 → linkml-1.7.6}/linkml/utils/execute_tutorial.py +0 -0
  117. {linkml-1.7.4 → linkml-1.7.6}/linkml/utils/helpers.py +0 -0
  118. {linkml-1.7.4 → linkml-1.7.6}/linkml/utils/logictools.py +0 -0
  119. {linkml-1.7.4 → linkml-1.7.6}/linkml/utils/mergeutils.py +0 -0
  120. {linkml-1.7.4 → linkml-1.7.6}/linkml/utils/rawloader.py +0 -0
  121. {linkml-1.7.4 → linkml-1.7.6}/linkml/utils/schemasynopsis.py +0 -0
  122. {linkml-1.7.4 → linkml-1.7.6}/linkml/utils/typereferences.py +0 -0
  123. {linkml-1.7.4 → linkml-1.7.6}/linkml/utils/validation.py +0 -0
  124. {linkml-1.7.4 → linkml-1.7.6}/linkml/validator/__init__.py +0 -0
  125. {linkml-1.7.4 → linkml-1.7.6}/linkml/validator/cli.py +0 -0
  126. {linkml-1.7.4 → linkml-1.7.6}/linkml/validator/loaders/__init__.py +0 -0
  127. {linkml-1.7.4 → linkml-1.7.6}/linkml/validator/loaders/delimited_file_loader.py +0 -0
  128. {linkml-1.7.4 → linkml-1.7.6}/linkml/validator/loaders/json_loader.py +0 -0
  129. {linkml-1.7.4 → linkml-1.7.6}/linkml/validator/loaders/loader.py +0 -0
  130. {linkml-1.7.4 → linkml-1.7.6}/linkml/validator/loaders/passthrough_loader.py +0 -0
  131. {linkml-1.7.4 → linkml-1.7.6}/linkml/validator/loaders/yaml_loader.py +0 -0
  132. {linkml-1.7.4 → linkml-1.7.6}/linkml/validator/plugins/__init__.py +0 -0
  133. {linkml-1.7.4 → linkml-1.7.6}/linkml/validator/plugins/jsonschema_validation_plugin.py +0 -0
  134. {linkml-1.7.4 → linkml-1.7.6}/linkml/validator/plugins/pydantic_validation_plugin.py +0 -0
  135. {linkml-1.7.4 → linkml-1.7.6}/linkml/validator/plugins/recommended_slots_plugin.py +0 -0
  136. {linkml-1.7.4 → linkml-1.7.6}/linkml/validator/plugins/shacl_validation_plugin.py +0 -0
  137. {linkml-1.7.4 → linkml-1.7.6}/linkml/validator/plugins/validation_plugin.py +0 -0
  138. {linkml-1.7.4 → linkml-1.7.6}/linkml/validator/report.py +0 -0
  139. {linkml-1.7.4 → linkml-1.7.6}/linkml/validator/validator.py +0 -0
  140. {linkml-1.7.4 → linkml-1.7.6}/linkml/validators/__init__.py +0 -0
  141. {linkml-1.7.4 → linkml-1.7.6}/linkml/validators/jsonschemavalidator.py +0 -0
  142. {linkml-1.7.4 → linkml-1.7.6}/linkml/validators/sparqlvalidator.py +0 -0
  143. {linkml-1.7.4 → linkml-1.7.6}/linkml/workspaces/__init__.py +0 -0
  144. {linkml-1.7.4 → linkml-1.7.6}/linkml/workspaces/datamodel/__init__.py +0 -0
  145. {linkml-1.7.4 → linkml-1.7.6}/linkml/workspaces/datamodel/workspaces.py +0 -0
  146. {linkml-1.7.4 → linkml-1.7.6}/linkml/workspaces/datamodel/workspaces.yaml +0 -0
  147. {linkml-1.7.4 → linkml-1.7.6}/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.4
3
+ Version: 1.7.6
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
@@ -22,6 +22,8 @@ Classifier: Programming Language :: Python :: 3.11
22
22
  Classifier: Programming Language :: Python :: 3.8
23
23
  Classifier: Programming Language :: Python :: 3.9
24
24
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
25
+ Provides-Extra: shacl
26
+ Provides-Extra: tests
25
27
  Requires-Dist: antlr4-python3-runtime (>=4.9.0,<4.10)
26
28
  Requires-Dist: click (>=7.0)
27
29
  Requires-Dist: graphviz (>=0.10.1)
@@ -38,6 +40,7 @@ Requires-Dist: prefixcommons (>=0.1.7)
38
40
  Requires-Dist: prefixmaps (>=0.1.3)
39
41
  Requires-Dist: pydantic (>=1.0.0,<3.0.0)
40
42
  Requires-Dist: pyjsg (>=0.11.6)
43
+ Requires-Dist: pyshacl (>=0.25.0,<0.26.0) ; extra == "shacl" or extra == "tests"
41
44
  Requires-Dist: pyshex (>=0.7.20)
42
45
  Requires-Dist: pyshexc (>=0.8.3)
43
46
  Requires-Dist: python-dateutil
@@ -5,6 +5,7 @@ representation such as JsonSchema
5
5
 
6
6
  from linkml.generators.javagen import JavaGenerator
7
7
  from linkml.generators.jsonldcontextgen import ContextGenerator
8
+ from linkml.generators.jsonldgen import JSONLDGenerator
8
9
  from linkml.generators.jsonschemagen import JsonSchemaGenerator
9
10
  from linkml.generators.owlgen import OwlSchemaGenerator
10
11
  from linkml.generators.pydanticgen import PydanticGenerator
@@ -43,6 +44,7 @@ __all__ = [
43
44
  "PythonGenerator",
44
45
  "JavaGenerator",
45
46
  "ContextGenerator",
47
+ "JSONLDGenerator",
46
48
  "JsonSchemaGenerator",
47
49
  "ShaclGenerator",
48
50
  "ShExGenerator",
@@ -8,6 +8,19 @@
8
8
  {%- endif -%}
9
9
  {%- endif -%}
10
10
 
11
+ {% macro compute_range(slot) -%}
12
+ {%- if slot.any_of or slot.exactly_one_of -%}
13
+ {%- for subslot_range in schemaview.slot_range_as_union(slot) -%}
14
+ {{ gen.link(subslot_range) }}
15
+ {%- if not loop.last -%}
16
+ &nbsp;or&nbsp;<br />
17
+ {%- endif -%}
18
+ {%- endfor -%}
19
+ {%- else -%}
20
+ {{ gen.link(slot.range) }}
21
+ {%- endif -%}
22
+ {% endmacro %}
23
+
11
24
  # Class: {{ title }}
12
25
 
13
26
  {%- if header -%}
@@ -55,12 +68,12 @@ URI: {{ gen.uri_link(element) }}
55
68
  | --- | --- | --- | --- |
56
69
  {% if gen.get_direct_slots(element)|length > 0 %}
57
70
  {%- for slot in gen.get_direct_slots(element) -%}
58
- | {{ gen.link(slot) }} | {{ gen.cardinality(slot) }} <br/> {{ gen.link(slot.range) }} | {{ slot.description|enshorten }} | direct |
71
+ | {{ gen.link(slot) }} | {{ gen.cardinality(slot) }} <br/> {{ compute_range(slot) }} | {{ slot.description|enshorten }} | direct |
59
72
  {% endfor -%}
60
73
  {% endif -%}
61
74
  {% if gen.get_indirect_slots(element)|length > 0 %}
62
75
  {%- for slot in gen.get_indirect_slots(element) -%}
63
- | {{ gen.link(slot) }} | {{ gen.cardinality(slot) }} <br/> {{ gen.link(slot.range) }} | {{ slot.description|enshorten }} | {{ gen.links(gen.get_slot_inherited_from(element.name, slot.name))|join(', ') }} |
76
+ | {{ gen.link(slot) }} | {{ gen.cardinality(slot) }} <br/> {{ compute_range(slot) }} | {{ slot.description|enshorten }} | {{ gen.links(gen.get_slot_inherited_from(element.name, slot.name))|join(', ') }} |
64
77
  {% endfor -%}
65
78
  {% endif %}
66
79
 
@@ -8,6 +8,19 @@
8
8
  {%- endif -%}
9
9
  {%- endif -%}
10
10
 
11
+ {% macro compute_range(slot) -%}
12
+ {%- if slot.any_of or slot.exactly_one_of -%}
13
+ {%- for subslot_range in schemaview.slot_range_as_union(slot) -%}
14
+ {{ gen.link(subslot_range) }}
15
+ {%- if not loop.last -%}
16
+ &nbsp;or&nbsp;<br />
17
+ {%- endif -%}
18
+ {%- endfor -%}
19
+ {%- else -%}
20
+ {{ gen.link(slot.range) }}
21
+ {%- endif -%}
22
+ {% endmacro %}
23
+
11
24
  # Slot: {{ title }}
12
25
 
13
26
  {%- if header -%}
@@ -58,7 +71,7 @@ URI: {{ gen.uri_link(element) }}
58
71
 
59
72
  ## Properties
60
73
 
61
- * Range: {{gen.link(element.range)}}
74
+ * Range: {{ compute_range(element) }}
62
75
  {% if element.multivalued %}
63
76
  * Multivalued: {{ element.multivalued }}
64
77
  {% endif -%}
@@ -192,52 +192,65 @@ class DocGenerator(Generator):
192
192
  "diagram_type": self.diagram_type.value if self.diagram_type else None,
193
193
  "include_top_level_diagram": self.include_top_level_diagram,
194
194
  }
195
+ self.logger.debug("Processing Index")
195
196
  template = self._get_template("index")
196
197
  out_str = template.render(gen=self, schema=sv.schema, schemaview=sv, **template_vars)
197
198
  self._write(out_str, directory, self.index_name)
198
199
  if self._is_single_file_format(self.format):
199
- logging.info(f"{self.format} is a single-page format, skipping non-index elements")
200
+ self.logger.info(f"{self.format} is a single-page format, skipping non-index elements")
200
201
  return
202
+ self.logger.debug("Processing Schemas...")
201
203
  template = self._get_template("schema")
202
204
  for schema_name in sv.imports_closure():
205
+ self.logger.debug(f" Generating doc for {schema_name}")
203
206
  imported_schema = sv.schema_map.get(schema_name)
204
207
  out_str = template.render(gen=self, schema=imported_schema, schemaview=sv, **template_vars)
205
208
  self._write(out_str, directory, imported_schema.name)
209
+ self.logger.debug("Processing Classes...")
206
210
  template = self._get_template("class")
207
211
  for cn, c in sv.all_classes().items():
208
212
  if self._is_external(c):
209
213
  continue
210
214
  n = self.name(c)
215
+ self.logger.debug(f" Generating doc for {n}")
211
216
  out_str = template.render(gen=self, element=c, schemaview=sv, **template_vars)
212
217
  self._write(out_str, directory, n)
218
+ self.logger.debug("Processing Slots...")
213
219
  template = self._get_template("slot")
214
220
  for sn, s in sv.all_slots().items():
215
221
  if self._is_external(s):
216
222
  continue
217
223
  n = self.name(s)
224
+ self.logger.debug(f" Generating doc for {n}")
218
225
  s = sv.induced_slot(sn)
219
226
  out_str = template.render(gen=self, element=s, schemaview=sv, **template_vars)
220
227
  self._write(out_str, directory, n)
228
+ self.logger.debug("Processing Enums...")
221
229
  template = self._get_template("enum")
222
230
  for en, e in sv.all_enums().items():
223
231
  if self._is_external(e):
224
232
  continue
225
233
  n = self.name(e)
234
+ self.logger.debug(f" Generating doc for {n}")
226
235
  out_str = template.render(gen=self, element=e, schemaview=sv, **template_vars)
227
236
  self._write(out_str, directory, n)
237
+ self.logger.debug("Processing Types...")
228
238
  template = self._get_template("type")
229
239
  for tn, t in sv.all_types().items():
230
240
  if self._exclude_type(t):
231
241
  continue
232
242
  n = self.name(t)
243
+ self.logger.debug(f" Generating doc for {n}")
233
244
  t = sv.induced_type(tn)
234
245
  out_str = template.render(gen=self, element=t, schemaview=sv, **template_vars)
235
246
  self._write(out_str, directory, n)
247
+ self.logger.debug("Processing Subsets...")
236
248
  template = self._get_template("subset")
237
249
  for _, s in sv.all_subsets().items():
238
250
  if self._is_external(c):
239
251
  continue
240
252
  n = self.name(s)
253
+ self.logger.debug(f" Generating doc for {n}")
241
254
  out_str = template.render(gen=self, element=s, schemaview=sv, **template_vars)
242
255
  self._write(out_str, directory, n)
243
256
 
@@ -253,6 +266,7 @@ class DocGenerator(Generator):
253
266
  path = Path(directory)
254
267
  path.mkdir(parents=True, exist_ok=True)
255
268
  file_name = f"{name}.{self._file_suffix()}"
269
+ self.logger.debug(f" Writing file: {file_name}")
256
270
  with open(path / file_name, "w", encoding="UTF-8") as stream:
257
271
  stream.write(out_str)
258
272
 
@@ -294,7 +308,7 @@ class DocGenerator(Generator):
294
308
  if p.is_file():
295
309
  folder = self.template_directory
296
310
  else:
297
- logging.info(
311
+ self.logger.info(
298
312
  f"Could not find {base_file_name} in {self.template_directory} - falling back to default"
299
313
  )
300
314
  if not folder:
@@ -325,7 +339,7 @@ class DocGenerator(Generator):
325
339
 
326
340
  :param element: SchemaView element definition
327
341
  :return: slot name or numeric portion of CURIE prefixed
328
- slot_uri
342
+ slot_uri
329
343
  """
330
344
  if type(element).class_name == "slot_definition":
331
345
  if self.use_slot_uris:
@@ -422,7 +436,8 @@ class DocGenerator(Generator):
422
436
  else:
423
437
  return False
424
438
 
425
- def _markdown_link(self, n: str, name: str = None, subfolder: str = None) -> str:
439
+ @staticmethod
440
+ def _markdown_link(n: str, name: str = None, subfolder: str = None) -> str:
426
441
  if subfolder:
427
442
  rel_path = f"{subfolder}/{n}"
428
443
  else:
@@ -507,7 +522,8 @@ class DocGenerator(Generator):
507
522
  s += "\n"
508
523
  return s
509
524
 
510
- def bullet(self, e: Element, meta_slot: SlotDefinitionName, backquote=False) -> str:
525
+ @staticmethod
526
+ def bullet(e: Element, meta_slot: SlotDefinitionName, backquote=False) -> str:
511
527
  """
512
528
  Render tag-value for an element as a bullet
513
529
 
@@ -526,7 +542,8 @@ class DocGenerator(Generator):
526
542
  else:
527
543
  return ""
528
544
 
529
- def number_value_range(self, e: Union[SlotDefinition, TypeDefinition]) -> str:
545
+ @staticmethod
546
+ def number_value_range(e: Union[SlotDefinition, TypeDefinition]) -> str:
530
547
  """
531
548
  Render the minimum and maximum values for a slot or type as a range, e.g 5-100
532
549
 
@@ -547,7 +564,8 @@ class DocGenerator(Generator):
547
564
  r = f"<= {e.maximum_value}"
548
565
  return r
549
566
 
550
- def cardinality(self, slot: SlotDefinition) -> str:
567
+ @staticmethod
568
+ def cardinality(slot: SlotDefinition) -> str:
551
569
  """
552
570
  Render combination of required, multivalued, and recommended as a range, e.g. 0..*
553
571
  :param slot:
@@ -605,7 +623,8 @@ class DocGenerator(Generator):
605
623
  else:
606
624
  raise NotImplementedError(f"Diagram type {self.diagram_type} not implemented")
607
625
 
608
- def latex(self, text: Optional[str]) -> str:
626
+ @staticmethod
627
+ def latex(text: Optional[str]) -> str:
609
628
  """
610
629
  Makes text safe for latex
611
630
 
@@ -757,7 +776,8 @@ class DocGenerator(Generator):
757
776
  # depth first - place at end of stack (to be processed next)
758
777
  stack.append((depth + 1, child))
759
778
 
760
- def _is_single_file_format(self, format: str):
779
+ @staticmethod
780
+ def _is_single_file_format(format: str):
761
781
  if format == "latex":
762
782
  return True
763
783
  else:
@@ -778,7 +798,8 @@ class DocGenerator(Generator):
778
798
  slot.range = "string"
779
799
  return slot
780
800
 
781
- def get_direct_slot_names(self, cls: ClassDefinition) -> List[SlotDefinitionName]:
801
+ @staticmethod
802
+ def get_direct_slot_names(cls: ClassDefinition) -> List[SlotDefinitionName]:
782
803
  """Fetch list of all own attributes of a class, i.e.,
783
804
  all slot names of slots that belong to the domain of a class.
784
805
 
@@ -845,7 +866,7 @@ class DocGenerator(Generator):
845
866
  def example_object_blobs(self, class_name: str) -> List[Tuple[str, str]]:
846
867
  """Fetch list of all examples of a class.
847
868
 
848
- :param cls: class for which we want to determine the examples
869
+ :param class_name: class for which we want to determine the examples
849
870
  :return: list of all examples of a class
850
871
  """
851
872
  if not self.example_runner:
@@ -30,7 +30,8 @@ class ExcelGenerator(Generator):
30
30
  self.logger = logging.getLogger(__name__)
31
31
  self.schemaview = SchemaView(self.schema)
32
32
 
33
- def create_workbook(self, workbook_path: Path) -> Workbook:
33
+ @staticmethod
34
+ def create_workbook(workbook_path: Path) -> Workbook:
34
35
  """
35
36
  Creates an Excel workbook using the openpyxl library and returns it.
36
37
 
@@ -87,7 +88,8 @@ class ExcelGenerator(Generator):
87
88
  if self.split_workbook_by_class:
88
89
  self.logger.info(f"The Excel workbooks have been written to {output_path}")
89
90
 
90
- def add_columns_to_worksheet(self, workbook: Workbook, worksheet_name: str, sheet_headings: List[str]) -> None:
91
+ @staticmethod
92
+ def add_columns_to_worksheet(workbook: Workbook, worksheet_name: str, sheet_headings: List[str]) -> None:
91
93
  """
92
94
  Get a worksheet by name and add a column to it in an existing workbook.
93
95
 
@@ -102,8 +104,8 @@ class ExcelGenerator(Generator):
102
104
  for i, heading in enumerate(sheet_headings):
103
105
  worksheet.cell(row=1, column=i + 1, value=heading)
104
106
 
107
+ @staticmethod
105
108
  def column_enum_validation(
106
- self,
107
109
  workbook: Workbook,
108
110
  worksheet_name: str,
109
111
  column_name: str,
@@ -100,7 +100,8 @@ class GolangGenerator(Generator):
100
100
  out_str = template_obj.render(gen=self, schema=self.schemaview.schema, view=self.schemaview)
101
101
  return out_str
102
102
 
103
- def name(self, element: Element) -> str:
103
+ @staticmethod
104
+ def name(element: Element) -> str:
104
105
  """
105
106
  Returns the name of the element in its canonical form
106
107
 
@@ -112,7 +113,8 @@ class GolangGenerator(Generator):
112
113
  alias = element.alias
113
114
  return camelcase(alias)
114
115
 
115
- def json_name(self, element: Element) -> str:
116
+ @staticmethod
117
+ def json_name(element: Element) -> str:
116
118
  """
117
119
  Returns the name of the element in its JSON (snake-case) form
118
120
 
@@ -181,7 +183,8 @@ class GolangGenerator(Generator):
181
183
  logging.warning(f"Unknown type.base: {t.name}")
182
184
  return "string"
183
185
 
184
- def parents(self, cls: ClassDefinition) -> List[ClassDefinitionName]:
186
+ @staticmethod
187
+ def parents(cls: ClassDefinition) -> List[ClassDefinitionName]:
185
188
  if cls.is_a:
186
189
  parents = [cls.is_a]
187
190
  else:
@@ -6,14 +6,14 @@ Generate JSON-LD contexts
6
6
  import os
7
7
  import re
8
8
  from dataclasses import dataclass, field
9
- from typing import Dict, Optional, Set
9
+ from typing import Dict, Optional, Set, Union
10
10
 
11
11
  import click
12
12
  from jsonasobj2 import JsonObj, as_json
13
13
  from linkml_runtime.linkml_model.meta import ClassDefinition, SlotDefinition
14
14
  from linkml_runtime.linkml_model.types import SHEX
15
15
  from linkml_runtime.utils.formatutils import camelcase, underscore
16
- from rdflib import SKOS, XSD
16
+ from rdflib import SKOS, XSD, Namespace
17
17
 
18
18
  from linkml._version import __version__
19
19
  from linkml.utils.generator import Generator, shared_arguments
@@ -47,7 +47,7 @@ class ContextGenerator(Generator):
47
47
  slot_class_maps: Dict = field(default_factory=lambda: dict())
48
48
  emit_metadata: bool = False
49
49
  model: Optional[bool] = True
50
- base: Optional[str] = None
50
+ base: Optional[Union[str, Namespace]] = None
51
51
  output: Optional[str] = None
52
52
  prefixes: Optional[bool] = True
53
53
  flatprefixes: Optional[bool] = False
@@ -57,7 +57,7 @@ class ContextGenerator(Generator):
57
57
  if self.namespaces is None:
58
58
  raise TypeError("Schema text must be supplied to context generator. Preparsed schema will not work")
59
59
 
60
- def visit_schema(self, base: Optional[str] = None, output: Optional[str] = None, **_):
60
+ def visit_schema(self, base: Optional[Union[str, Namespace]] = None, output: Optional[str] = None, **_):
61
61
  # Add any explicitly declared prefixes
62
62
  for prefix in self.schema.prefixes.values():
63
63
  self.emit_prefixes.add(prefix.prefix_prefix)
@@ -80,11 +80,10 @@ class ContextGenerator(Generator):
80
80
  self.namespaces[self.schema.name] = default_uri
81
81
  self.emit_prefixes.add(self.schema.name)
82
82
  self.context_body["@vocab"] = default_uri
83
- # self.context_body['@base'] = self.base_dir
84
83
 
85
84
  def end_schema(
86
85
  self,
87
- base: Optional[str] = None,
86
+ base: Optional[Union[str, Namespace]] = None,
88
87
  output: Optional[str] = None,
89
88
  prefixes: Optional[bool] = True,
90
89
  flatprefixes: Optional[bool] = False,
@@ -102,6 +101,7 @@ class ContextGenerator(Generator):
102
101
  context.comments = comments
103
102
  context_content = {}
104
103
  if base:
104
+ base = str(base)
105
105
  if "://" not in base:
106
106
  self.context_body["@base"] = os.path.relpath(base, os.path.dirname(self.schema.source_file))
107
107
  else:
@@ -178,6 +178,9 @@ class ContextGenerator(Generator):
178
178
  if slot_def:
179
179
  self.context_body[underscore(aliased_slot_name)] = slot_def
180
180
 
181
+ def serialize(self, base: Optional[Union[str, Namespace]] = None, **kwargs) -> str:
182
+ return super().serialize(base=base, **kwargs)
183
+
181
184
 
182
185
  @shared_arguments(ContextGenerator)
183
186
  @click.command()
@@ -37,7 +37,8 @@ class JSONLDGenerator(Generator):
37
37
 
38
38
  Status: incompletely implemented
39
39
 
40
- Note: this is distinct from :ref:`ContextGenerator`, which generates a JSON-LD context
40
+ Note: this is distinct from
41
+ :class:`~linkml.generators.jsonldcontextgen.ContextGenerator`, which generates a JSON-LD context
41
42
  """
42
43
 
43
44
  # ClassVars
@@ -49,6 +50,7 @@ class JSONLDGenerator(Generator):
49
50
  ] # jsonld includes @type and @context. json is pure JSON
50
51
  uses_schemaloader = True
51
52
  requires_metamodel = True
53
+ file_extension = "jsonld"
52
54
 
53
55
  # ObjectVars
54
56
  original_schema: SchemaDefinition = None
@@ -95,7 +95,8 @@ class OOCodeGenerator(Generator):
95
95
  def default_value_for_type(self, typ: str) -> str:
96
96
  raise NotImplementedError
97
97
 
98
- def get_class_name(self, cn):
98
+ @staticmethod
99
+ def get_class_name(cn):
99
100
  return camelcase(cn)
100
101
 
101
102
  def get_slot_name(self, sn):
@@ -108,10 +109,12 @@ class OOCodeGenerator(Generator):
108
109
  def map_type(self, t: TypeDefinition, required: bool = False) -> str:
109
110
  return t.base
110
111
 
111
- def make_multivalued(self, range: str) -> str:
112
+ @staticmethod
113
+ def make_multivalued(range: str) -> str:
112
114
  return f"List<{range}>"
113
115
 
114
- def replace_invalid_identifier_character(self, char: str) -> str:
116
+ @staticmethod
117
+ def replace_invalid_identifier_character(char: str) -> str:
115
118
  if char.isalpha() or char.isnumeric() or char == "_":
116
119
  return char
117
120
  else:
@@ -22,6 +22,7 @@ from linkml_runtime.linkml_model.meta import (
22
22
  EnumDefinition,
23
23
  EnumDefinitionName,
24
24
  PermissibleValue,
25
+ SchemaDefinitionName,
25
26
  SlotDefinition,
26
27
  SlotDefinitionName,
27
28
  TypeDefinition,
@@ -199,6 +200,12 @@ class OwlSchemaGenerator(Generator):
199
200
  for enm in sv.all_enums(imports=mergeimports).values():
200
201
  self.add_enum(enm)
201
202
 
203
+ if not mergeimports:
204
+ for imp in schema.imports:
205
+ if imp == "linkml:types":
206
+ continue
207
+ graph.add((base, OWL.imports, self._schema_uri(imp)))
208
+
202
209
  # Add metadata as annotation properties
203
210
  self.add_metadata(schema, base)
204
211
  return graph
@@ -459,6 +466,7 @@ class OwlSchemaGenerator(Generator):
459
466
  an anonymous expression)
460
467
 
461
468
  :param cls: LinkML class expression (anonymous if called recursively)
469
+ :param quantifier_predicate:
462
470
  :return: blank node representing the OWL expression
463
471
  """
464
472
  if cls is None:
@@ -569,6 +577,7 @@ class OwlSchemaGenerator(Generator):
569
577
  :param cls:
570
578
  :param slot:
571
579
  :param main_slot:
580
+ :param owl_types:
572
581
  :return:
573
582
  """
574
583
  sv = self.schemaview
@@ -687,6 +696,14 @@ class OwlSchemaGenerator(Generator):
687
696
  eq_uris = [URIRef(self.schemaview.expand_curie(s)) for s in equals_string_in]
688
697
  owl_exprs.append(self._union_of(eq_uris))
689
698
  for constraint_prop, constraint_val in constraints.items():
699
+ if is_literal is not None and not is_literal:
700
+ # In LinkML, it is permissible to have a literal constraints on slots that refer to
701
+ # other objects. E.g. a pattern on a in_organization slot which refers to an Organization
702
+ # will be applied to the id of that Organization.
703
+ # To support this in OWL we would need to change this to a complex expression - for
704
+ # now we will skip this.
705
+ # See: https://github.com/linkml/linkml/issues/1841
706
+ continue
690
707
  if constraint_val is not None:
691
708
  owl_types.add(RDFS.Literal)
692
709
  dr = BNode()
@@ -958,7 +975,8 @@ class OwlSchemaGenerator(Generator):
958
975
  self.graph.add((node, OWL.hasValue, filler))
959
976
  return node
960
977
 
961
- def _swrl_var(self, var: str) -> URIRef:
978
+ @staticmethod
979
+ def _swrl_var(var: str) -> URIRef:
962
980
  return URIRef(var)
963
981
 
964
982
  def _swrl_class_atom(self, cls_ref: Union[BNode, URIRef], var: str) -> BNode:
@@ -983,7 +1001,8 @@ class OwlSchemaGenerator(Generator):
983
1001
  self.graph.add((node, SWRL.head, head))
984
1002
  return node
985
1003
 
986
- def _metaslot_uri(self, name: str) -> URIRef:
1004
+ @staticmethod
1005
+ def _metaslot_uri(name: str) -> URIRef:
987
1006
  return URIRef("https://w3id.org/linkml/" + name)
988
1007
 
989
1008
  def _complement_of_union_of(
@@ -1086,7 +1105,8 @@ class OwlSchemaGenerator(Generator):
1086
1105
  else:
1087
1106
  return self._class_uri(ClassDefinitionName(slot.range))
1088
1107
 
1089
- def _mixin_grouping_class_uri(self):
1108
+ @staticmethod
1109
+ def _mixin_grouping_class_uri():
1090
1110
  return URIRef(ClassDefinition.class_class_uri + "#Mixin")
1091
1111
 
1092
1112
  def _class_uri(self, cn: Union[str, ClassDefinitionName]) -> URIRef:
@@ -1116,6 +1136,13 @@ class OwlSchemaGenerator(Generator):
1116
1136
  default_prefix = self.schemaview.schema.default_prefix or ""
1117
1137
  return URIRef(self.schemaview.expand_curie(f"{default_prefix}:{underscore(p.name)}"))
1118
1138
 
1139
+ def _schema_uri(self, scn: Union[str, SchemaDefinitionName]) -> URIRef:
1140
+ if ":" in scn:
1141
+ return URIRef(self.schemaview.expand_curie(scn))
1142
+ else:
1143
+ default_prefix = self.schemaview.schema.default_prefix or ""
1144
+ return URIRef(self.schemaview.expand_curie(f"{default_prefix}:{scn}"))
1145
+
1119
1146
  def _type_uri(self, tn: TypeDefinitionName, native: bool = None) -> URIRef:
1120
1147
  if native is None:
1121
1148
  # never use native unless type shadowing with objects is enabled
@@ -6,14 +6,14 @@ Generate JSON-LD contexts
6
6
  import csv
7
7
  import os
8
8
  from dataclasses import dataclass, field
9
- from typing import Dict, Optional, Set
9
+ from typing import Dict, Optional, Set, Union
10
10
 
11
11
  import click
12
12
  from jsonasobj2 import JsonObj, as_json
13
13
  from linkml_runtime.linkml_model.meta import ClassDefinition, SlotDefinition
14
14
  from linkml_runtime.linkml_model.types import SHEX
15
15
  from linkml_runtime.utils.formatutils import camelcase
16
- from rdflib import XSD
16
+ from rdflib import XSD, Namespace
17
17
 
18
18
  from linkml._version import __version__
19
19
  from linkml.utils.generator import Generator, shared_arguments
@@ -35,7 +35,7 @@ class PrefixGenerator(Generator):
35
35
  default_ns: str = None
36
36
  context_body: Dict = field(default_factory=lambda: dict())
37
37
  slot_class_maps: Dict = field(default_factory=lambda: dict())
38
- base: str = None
38
+ base: Optional[Union[str, Namespace]] = None
39
39
 
40
40
  def __post_init__(self):
41
41
  super().__post_init__()
@@ -59,9 +59,10 @@ class PrefixGenerator(Generator):
59
59
  if self.default_ns:
60
60
  self.emit_prefixes.add(self.default_ns)
61
61
 
62
- def end_schema(self, base: Optional[str] = None, output: Optional[str] = None, **_) -> None:
62
+ def end_schema(self, base: Optional[Union[str, Namespace]] = None, output: Optional[str] = None, **_) -> None:
63
63
  context = JsonObj()
64
64
  if base:
65
+ base = str(base)
65
66
  if "://" not in base:
66
67
  self.context_body["@base"] = os.path.relpath(base, os.path.dirname(self.schema.source_file))
67
68
  else:
@@ -22,7 +22,7 @@ from linkml.generators.protogen import ProtoGenerator
22
22
  from linkml.generators.pythongen import PythonGenerator
23
23
  from linkml.generators.shaclgen import ShaclGenerator
24
24
  from linkml.generators.shexgen import ShExGenerator
25
- from linkml.generators.sqlddlgen import SQLDDLGenerator
25
+ from linkml.generators.sqltablegen import SQLTableGenerator
26
26
  from linkml.utils.cli_utils import log_level_option
27
27
  from linkml.utils.generator import Generator
28
28
 
@@ -53,7 +53,7 @@ GEN_MAP = {
53
53
  # 'rdf': (RDFGenerator, 'rdf/{name}.ttl', {'context': '{parent}/../jsonld/{name}.context.jsonld'}),
54
54
  "shex": (ShExGenerator, "shex/{name}.shex", {}),
55
55
  "shacl": (ShaclGenerator, "shacl/{name}.shacl.ttl", {}),
56
- "sqlddl": (SQLDDLGenerator, "sqlschema/{name}.sql", {}),
56
+ "sqltable": (SQLTableGenerator, "sqlschema/{name}.sql", {}),
57
57
  # # linkml/generators/javagen.py uses different architecture from most of the other generators
58
58
  # # also linkml/generators/excelgen.py, which has a different mechanism for determining the output path
59
59
  # 'java': (JavaGenerator, 'java/{name}.java', {'directory': '{parent}'}),
@@ -96,7 +96,8 @@ class ProjectGenerator:
96
96
  Note this doesn't conform to overall generator framework, as it is a meta-generator
97
97
  """
98
98
 
99
- def generate(self, schema_path: str, config: ProjectConfiguration = ProjectConfiguration()):
99
+ @staticmethod
100
+ def generate(schema_path: str, config: ProjectConfiguration = ProjectConfiguration()):
100
101
  if config.directory is None:
101
102
  raise Exception("Must pass directory")
102
103
  Path(config.directory).mkdir(parents=True, exist_ok=True)
@@ -197,26 +198,38 @@ def cli(
197
198
 
198
199
  Generate all downstream artefacts using default configuration:
199
200
 
200
- gen-project -d . personinfo.yaml
201
+ .. code-block: bash
202
+
203
+ gen-project -d . personinfo.yaml
201
204
 
202
205
  Exclusion lists: all except ShEx:
203
206
 
204
- gen-project --exclude shex -d . personinfo.yaml
207
+ .. code-block: bash
208
+
209
+ gen-project --exclude shex -d . personinfo.yaml
205
210
 
206
211
  Inclusion lists: only jsonschema and python:
207
212
 
213
+ .. code-block: bash
214
+
208
215
  gen-project -I python -I jsonschema -d . personinfo.yaml
209
216
 
210
217
  Configuration, on command line:
211
218
 
219
+ .. code-block: bash
220
+
212
221
  gen-project -A 'jsonschema: {top_class: Container}' -d . personinfo.yaml
213
222
 
214
223
  Configuration, via yaml file:
215
224
 
225
+ .. code-block: bash
226
+
216
227
  gen-project --config config.yaml personinfo.yaml
217
228
 
218
229
  config.yaml:
219
230
 
231
+ .. code-block: yaml
232
+
220
233
  directory: .
221
234
  generator_args:
222
235
  json_schema:
@@ -0,0 +1,29 @@
1
+ from linkml.generators.pydanticgen.pydanticgen import DEFAULT_IMPORTS, PydanticGenerator, cli
2
+ from linkml.generators.pydanticgen.template import (
3
+ ConditionalImport,
4
+ Import,
5
+ Imports,
6
+ PydanticAttribute,
7
+ PydanticBaseModel,
8
+ PydanticClass,
9
+ PydanticEnum,
10
+ PydanticModule,
11
+ PydanticValidator,
12
+ TemplateModel,
13
+ )
14
+
15
+ __all__ = [
16
+ "cli",
17
+ "ConditionalImport",
18
+ "DEFAULT_IMPORTS",
19
+ "Import",
20
+ "Imports",
21
+ "PydanticAttribute",
22
+ "PydanticBaseModel",
23
+ "PydanticClass",
24
+ "PydanticEnum",
25
+ "PydanticGenerator",
26
+ "PydanticModule",
27
+ "PydanticValidator",
28
+ "TemplateModel",
29
+ ]