linkml 1.8.1__tar.gz → 1.8.3__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 (166) hide show
  1. {linkml-1.8.1 → linkml-1.8.3}/PKG-INFO +2 -2
  2. linkml-1.8.3/linkml/cli/__main__.py +4 -0
  3. linkml-1.8.3/linkml/cli/main.py +130 -0
  4. linkml-1.8.3/linkml/generators/common/build.py +105 -0
  5. linkml-1.8.3/linkml/generators/common/ifabsent_processor.py +286 -0
  6. linkml-1.8.3/linkml/generators/common/lifecycle.py +124 -0
  7. linkml-1.8.3/linkml/generators/common/template.py +89 -0
  8. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/csvgen.py +1 -1
  9. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/docgen/slot.md.jinja2 +4 -0
  10. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/docgen.py +1 -1
  11. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/dotgen.py +1 -1
  12. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/erdiagramgen.py +1 -1
  13. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/excelgen.py +1 -1
  14. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/golanggen.py +1 -1
  15. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/golrgen.py +1 -1
  16. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/graphqlgen.py +1 -1
  17. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/javagen.py +1 -1
  18. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/jsonldcontextgen.py +4 -5
  19. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/jsonldgen.py +1 -1
  20. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/jsonschemagen.py +69 -22
  21. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/linkmlgen.py +1 -1
  22. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/markdowngen.py +1 -1
  23. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/namespacegen.py +1 -1
  24. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/oocodegen.py +2 -1
  25. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/owlgen.py +1 -1
  26. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/plantumlgen.py +1 -1
  27. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/prefixmapgen.py +1 -1
  28. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/projectgen.py +1 -1
  29. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/protogen.py +1 -1
  30. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/pydanticgen/__init__.py +8 -3
  31. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/pydanticgen/array.py +114 -194
  32. linkml-1.8.3/linkml/generators/pydanticgen/build.py +118 -0
  33. linkml-1.8.3/linkml/generators/pydanticgen/includes.py +22 -0
  34. linkml-1.8.3/linkml/generators/pydanticgen/pydanticgen.py +1234 -0
  35. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/pydanticgen/template.py +152 -184
  36. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/pydanticgen/templates/attribute.py.jinja +9 -7
  37. linkml-1.8.3/linkml/generators/pydanticgen/templates/base_model.py.jinja +16 -0
  38. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/pydanticgen/templates/class.py.jinja +2 -2
  39. linkml-1.8.3/linkml/generators/pydanticgen/templates/footer.py.jinja +5 -0
  40. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/pydanticgen/templates/module.py.jinja +2 -2
  41. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/pydanticgen/templates/validator.py.jinja +0 -4
  42. linkml-1.8.3/linkml/generators/python/__init__.py +1 -0
  43. linkml-1.8.3/linkml/generators/python/python_ifabsent_processor.py +92 -0
  44. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/pythongen.py +19 -23
  45. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/rdfgen.py +1 -1
  46. linkml-1.8.3/linkml/generators/shacl/__init__.py +1 -0
  47. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/shacl/shacl_data_type.py +1 -1
  48. linkml-1.8.3/linkml/generators/shacl/shacl_ifabsent_processor.py +89 -0
  49. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/shaclgen.py +11 -5
  50. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/shexgen.py +1 -1
  51. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/sparqlgen.py +1 -1
  52. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/sqlalchemygen.py +1 -1
  53. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/sqltablegen.py +1 -1
  54. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/sssomgen.py +1 -1
  55. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/summarygen.py +1 -1
  56. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/terminusdbgen.py +7 -4
  57. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/typescriptgen.py +1 -1
  58. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/yamlgen.py +1 -1
  59. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/yumlgen.py +1 -1
  60. {linkml-1.8.1 → linkml-1.8.3}/linkml/linter/cli.py +1 -1
  61. {linkml-1.8.1 → linkml-1.8.3}/linkml/transformers/logical_model_transformer.py +117 -18
  62. {linkml-1.8.1 → linkml-1.8.3}/linkml/utils/converter.py +1 -1
  63. {linkml-1.8.1 → linkml-1.8.3}/linkml/utils/execute_tutorial.py +2 -0
  64. {linkml-1.8.1 → linkml-1.8.3}/linkml/utils/logictools.py +142 -29
  65. {linkml-1.8.1 → linkml-1.8.3}/linkml/utils/schema_builder.py +7 -6
  66. {linkml-1.8.1 → linkml-1.8.3}/linkml/utils/schema_fixer.py +1 -1
  67. {linkml-1.8.1 → linkml-1.8.3}/linkml/utils/sqlutils.py +1 -1
  68. {linkml-1.8.1 → linkml-1.8.3}/linkml/validator/cli.py +4 -1
  69. {linkml-1.8.1 → linkml-1.8.3}/linkml/validators/jsonschemavalidator.py +1 -1
  70. {linkml-1.8.1 → linkml-1.8.3}/linkml/validators/sparqlvalidator.py +1 -1
  71. linkml-1.8.3/linkml/workspaces/datamodel/__init__.py +0 -0
  72. {linkml-1.8.1 → linkml-1.8.3}/linkml/workspaces/example_runner.py +1 -1
  73. {linkml-1.8.1 → linkml-1.8.3}/pyproject.toml +18 -4
  74. {linkml-1.8.1 → linkml-1.8.3}/setup.py +5 -3
  75. linkml-1.8.1/linkml/generators/pydanticgen/build.py +0 -79
  76. linkml-1.8.1/linkml/generators/pydanticgen/includes.py +0 -52
  77. linkml-1.8.1/linkml/generators/pydanticgen/pydanticgen.py +0 -889
  78. linkml-1.8.1/linkml/generators/pydanticgen/templates/base_model.py.jinja +0 -29
  79. linkml-1.8.1/linkml/generators/pydanticgen/templates/footer.py.jinja +0 -13
  80. linkml-1.8.1/linkml/generators/shacl/__init__.py +0 -3
  81. linkml-1.8.1/linkml/generators/shacl/ifabsent_processor.py +0 -59
  82. linkml-1.8.1/linkml/utils/ifabsent_functions.py +0 -138
  83. {linkml-1.8.1 → linkml-1.8.3}/LICENSE +0 -0
  84. {linkml-1.8.1 → linkml-1.8.3}/README.md +0 -0
  85. {linkml-1.8.1 → linkml-1.8.3}/linkml/__init__.py +0 -0
  86. {linkml-1.8.1 → linkml-1.8.3}/linkml/_version.py +0 -0
  87. {linkml-1.8.1/linkml/generators/common → linkml-1.8.3/linkml/cli}/__init__.py +0 -0
  88. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/PythonGenNotes.md +0 -0
  89. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/README.md +0 -0
  90. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/__init__.py +0 -0
  91. {linkml-1.8.1/linkml/generators/legacy → linkml-1.8.3/linkml/generators/common}/__init__.py +0 -0
  92. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/common/type_designators.py +0 -0
  93. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/docgen/class.md.jinja2 +0 -0
  94. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/docgen/class_diagram.md.jinja2 +0 -0
  95. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/docgen/common_metadata.md.jinja2 +0 -0
  96. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/docgen/enum.md.jinja2 +0 -0
  97. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/docgen/index.md.jinja2 +0 -0
  98. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/docgen/index.tex.jinja2 +0 -0
  99. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/docgen/schema.md.jinja2 +0 -0
  100. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/docgen/subset.md.jinja2 +0 -0
  101. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/docgen/type.md.jinja2 +0 -0
  102. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/javagen/example_template.java.jinja2 +0 -0
  103. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/javagen/java_record_template.jinja2 +0 -0
  104. {linkml-1.8.1/linkml/linter → linkml-1.8.3/linkml/generators/legacy}/__init__.py +0 -0
  105. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/pydanticgen/black.py +0 -0
  106. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/pydanticgen/templates/conditional_import.py.jinja +0 -0
  107. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/pydanticgen/templates/enum.py.jinja +0 -0
  108. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/pydanticgen/templates/imports.py.jinja +0 -0
  109. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/sqlalchemy/__init__.py +0 -0
  110. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/sqlalchemy/sqlalchemy_declarative_template.py +0 -0
  111. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/sqlalchemy/sqlalchemy_imperative_template.py +0 -0
  112. {linkml-1.8.1 → linkml-1.8.3}/linkml/generators/string_template.md +0 -0
  113. {linkml-1.8.1/linkml/linter/config/datamodel → linkml-1.8.3/linkml/linter}/__init__.py +0 -0
  114. {linkml-1.8.1 → linkml-1.8.3}/linkml/linter/config/datamodel/.linkmllint.yaml +0 -0
  115. {linkml-1.8.1/linkml/transformers → linkml-1.8.3/linkml/linter/config/datamodel}/__init__.py +0 -0
  116. {linkml-1.8.1 → linkml-1.8.3}/linkml/linter/config/datamodel/config.py +0 -0
  117. {linkml-1.8.1 → linkml-1.8.3}/linkml/linter/config/datamodel/config.yaml +0 -0
  118. {linkml-1.8.1 → linkml-1.8.3}/linkml/linter/config/default.yaml +0 -0
  119. {linkml-1.8.1 → linkml-1.8.3}/linkml/linter/config/recommended.yaml +0 -0
  120. {linkml-1.8.1 → linkml-1.8.3}/linkml/linter/formatters/__init__.py +0 -0
  121. {linkml-1.8.1 → linkml-1.8.3}/linkml/linter/formatters/formatter.py +0 -0
  122. {linkml-1.8.1 → linkml-1.8.3}/linkml/linter/formatters/json_formatter.py +0 -0
  123. {linkml-1.8.1 → linkml-1.8.3}/linkml/linter/formatters/markdown_formatter.py +0 -0
  124. {linkml-1.8.1 → linkml-1.8.3}/linkml/linter/formatters/terminal_formatter.py +0 -0
  125. {linkml-1.8.1 → linkml-1.8.3}/linkml/linter/formatters/tsv_formatter.py +0 -0
  126. {linkml-1.8.1 → linkml-1.8.3}/linkml/linter/linter.py +0 -0
  127. {linkml-1.8.1 → linkml-1.8.3}/linkml/linter/rules.py +0 -0
  128. {linkml-1.8.1 → linkml-1.8.3}/linkml/reporting/__init__.py +0 -0
  129. {linkml-1.8.1 → linkml-1.8.3}/linkml/reporting/model.py +0 -0
  130. {linkml-1.8.1/linkml/workspaces → linkml-1.8.3/linkml/transformers}/__init__.py +0 -0
  131. {linkml-1.8.1 → linkml-1.8.3}/linkml/transformers/model_transformer.py +0 -0
  132. {linkml-1.8.1 → linkml-1.8.3}/linkml/transformers/relmodel_transformer.py +0 -0
  133. {linkml-1.8.1 → linkml-1.8.3}/linkml/transformers/schema_renamer.py +0 -0
  134. {linkml-1.8.1 → linkml-1.8.3}/linkml/utils/__init__.py +0 -0
  135. {linkml-1.8.1 → linkml-1.8.3}/linkml/utils/cli_utils.py +0 -0
  136. {linkml-1.8.1 → linkml-1.8.3}/linkml/utils/datautils.py +0 -0
  137. {linkml-1.8.1 → linkml-1.8.3}/linkml/utils/datavalidator.py +0 -0
  138. {linkml-1.8.1 → linkml-1.8.3}/linkml/utils/deprecation.py +0 -0
  139. {linkml-1.8.1 → linkml-1.8.3}/linkml/utils/generator.py +0 -0
  140. {linkml-1.8.1 → linkml-1.8.3}/linkml/utils/helpers.py +0 -0
  141. {linkml-1.8.1 → linkml-1.8.3}/linkml/utils/mergeutils.py +0 -0
  142. {linkml-1.8.1 → linkml-1.8.3}/linkml/utils/rawloader.py +0 -0
  143. {linkml-1.8.1 → linkml-1.8.3}/linkml/utils/schemaloader.py +0 -0
  144. {linkml-1.8.1 → linkml-1.8.3}/linkml/utils/schemasynopsis.py +0 -0
  145. {linkml-1.8.1 → linkml-1.8.3}/linkml/utils/typereferences.py +0 -0
  146. {linkml-1.8.1 → linkml-1.8.3}/linkml/utils/validation.py +0 -0
  147. {linkml-1.8.1 → linkml-1.8.3}/linkml/validator/__init__.py +0 -0
  148. {linkml-1.8.1 → linkml-1.8.3}/linkml/validator/loaders/__init__.py +0 -0
  149. {linkml-1.8.1 → linkml-1.8.3}/linkml/validator/loaders/delimited_file_loader.py +0 -0
  150. {linkml-1.8.1 → linkml-1.8.3}/linkml/validator/loaders/json_loader.py +0 -0
  151. {linkml-1.8.1 → linkml-1.8.3}/linkml/validator/loaders/loader.py +0 -0
  152. {linkml-1.8.1 → linkml-1.8.3}/linkml/validator/loaders/passthrough_loader.py +0 -0
  153. {linkml-1.8.1 → linkml-1.8.3}/linkml/validator/loaders/yaml_loader.py +0 -0
  154. {linkml-1.8.1 → linkml-1.8.3}/linkml/validator/plugins/__init__.py +0 -0
  155. {linkml-1.8.1 → linkml-1.8.3}/linkml/validator/plugins/jsonschema_validation_plugin.py +0 -0
  156. {linkml-1.8.1 → linkml-1.8.3}/linkml/validator/plugins/pydantic_validation_plugin.py +0 -0
  157. {linkml-1.8.1 → linkml-1.8.3}/linkml/validator/plugins/recommended_slots_plugin.py +0 -0
  158. {linkml-1.8.1 → linkml-1.8.3}/linkml/validator/plugins/shacl_validation_plugin.py +0 -0
  159. {linkml-1.8.1 → linkml-1.8.3}/linkml/validator/plugins/validation_plugin.py +0 -0
  160. {linkml-1.8.1 → linkml-1.8.3}/linkml/validator/report.py +0 -0
  161. {linkml-1.8.1 → linkml-1.8.3}/linkml/validator/validation_context.py +0 -0
  162. {linkml-1.8.1 → linkml-1.8.3}/linkml/validator/validator.py +0 -0
  163. {linkml-1.8.1 → linkml-1.8.3}/linkml/validators/__init__.py +0 -0
  164. {linkml-1.8.1/linkml/workspaces/datamodel → linkml-1.8.3/linkml/workspaces}/__init__.py +0 -0
  165. {linkml-1.8.1 → linkml-1.8.3}/linkml/workspaces/datamodel/workspaces.py +0 -0
  166. {linkml-1.8.1 → linkml-1.8.3}/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.1
3
+ Version: 1.8.3
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.8.0)
39
+ Requires-Dist: linkml-runtime (>=1.8.1,<2.0.0)
40
40
  Requires-Dist: openpyxl
41
41
  Requires-Dist: parse
42
42
  Requires-Dist: prefixcommons (>=0.1.7)
@@ -0,0 +1,4 @@
1
+ from linkml.cli.main import linkml as cli
2
+
3
+ if __name__ == "__main__":
4
+ cli()
@@ -0,0 +1,130 @@
1
+ """
2
+ Main ``linkml`` entrypoint
3
+
4
+ Gathers all the other linkml click entrypoints and puts them under ``linkml`` :)
5
+ """
6
+
7
+ import click
8
+
9
+ from linkml._version import __version__
10
+ from linkml.generators.csvgen import cli as gen_csv
11
+ from linkml.generators.docgen import cli as gen_doc
12
+ from linkml.generators.dotgen import cli as gen_graphviz
13
+ from linkml.generators.erdiagramgen import cli as gen_erdiagram
14
+ from linkml.generators.excelgen import cli as gen_excel
15
+ from linkml.generators.golanggen import cli as gen_golang
16
+ from linkml.generators.golrgen import cli as gen_golr_views
17
+ from linkml.generators.graphqlgen import cli as gen_graphql
18
+ from linkml.generators.javagen import cli as gen_java
19
+ from linkml.generators.jsonldcontextgen import cli as gen_jsonld_context
20
+ from linkml.generators.jsonldgen import cli as gen_jsonld
21
+ from linkml.generators.jsonschemagen import cli as gen_json_schema
22
+ from linkml.generators.linkmlgen import cli as gen_linkml
23
+ from linkml.generators.markdowngen import cli as gen_markdown
24
+ from linkml.generators.namespacegen import cli as gen_namespaces
25
+ from linkml.generators.owlgen import cli as gen_owl
26
+ from linkml.generators.plantumlgen import cli as gen_plantuml
27
+ from linkml.generators.prefixmapgen import cli as gen_prefix_map
28
+ from linkml.generators.projectgen import cli as gen_project
29
+ from linkml.generators.protogen import cli as gen_proto
30
+ from linkml.generators.pydanticgen import cli as gen_pydantic
31
+ from linkml.generators.pythongen import cli as gen_python
32
+ from linkml.generators.rdfgen import cli as gen_rdf
33
+ from linkml.generators.shaclgen import cli as gen_shacl
34
+ from linkml.generators.shexgen import cli as gen_shex
35
+ from linkml.generators.sparqlgen import cli as gen_sparql
36
+ from linkml.generators.sqlalchemygen import cli as gen_sqla
37
+ from linkml.generators.sqltablegen import cli as gen_sqltables
38
+ from linkml.generators.sssomgen import cli as gen_sssom
39
+ from linkml.generators.summarygen import cli as gen_summary
40
+ from linkml.generators.terminusdbgen import cli as gen_terminusdb
41
+ from linkml.generators.typescriptgen import cli as gen_typescript
42
+ from linkml.generators.yamlgen import cli as gen_yaml
43
+ from linkml.generators.yumlgen import cli as gen_yuml
44
+ from linkml.linter.cli import main as linkml_lint
45
+ from linkml.utils.converter import cli as linkml_convert
46
+ from linkml.utils.execute_tutorial import cli as run_tutorial
47
+ from linkml.utils.schema_fixer import main as linkml_schema_fixer
48
+ from linkml.utils.sqlutils import main as linkml_sqldb
49
+ from linkml.validator.cli import cli as linkml_validate
50
+ from linkml.workspaces.example_runner import cli as linkml_run_examples
51
+
52
+ # --------------------------------------------------
53
+ # Command groups
54
+ # --------------------------------------------------
55
+
56
+
57
+ @click.group()
58
+ @click.version_option(__version__, "-V", "--version")
59
+ def linkml():
60
+ """
61
+ LinkML: A flexible linked data modeling language
62
+ """
63
+
64
+
65
+ @linkml.group()
66
+ @click.version_option(__version__, "-V", "--version")
67
+ def generate():
68
+ """
69
+ Generate formats from a LinkML schema
70
+ """
71
+
72
+
73
+ @linkml.group()
74
+ @click.version_option(__version__, "-V", "--version")
75
+ def dev():
76
+ """
77
+ Helper tools for linkml development
78
+ """
79
+
80
+
81
+ # --------------------------------------------------
82
+ # Add commands to groups
83
+ # --------------------------------------------------
84
+
85
+ # Top-level linkml commands
86
+ linkml.add_command(linkml_convert, name="convert")
87
+ linkml.add_command(linkml_lint, name="lint")
88
+ linkml.add_command(linkml_sqldb, name="sqldb")
89
+ linkml.add_command(linkml_schema_fixer, name="fix")
90
+ linkml.add_command(linkml_run_examples, name="examples")
91
+ linkml.add_command(linkml_validate, name="validate")
92
+
93
+ # Generators
94
+ generate.add_command(gen_jsonld_context, name="jsonld-context")
95
+ generate.add_command(gen_prefix_map, name="prefix-map")
96
+ generate.add_command(gen_csv, name="csv")
97
+ generate.add_command(gen_graphviz, name="graphviz")
98
+ generate.add_command(gen_golang, name="golang")
99
+ generate.add_command(gen_golr_views, name="golr-views")
100
+ generate.add_command(gen_graphql, name="graphql")
101
+ generate.add_command(gen_java, name="java")
102
+ generate.add_command(gen_jsonld, name="jsonld")
103
+ generate.add_command(gen_json_schema, name="json-schema")
104
+ generate.add_command(gen_markdown, name="markdown")
105
+ generate.add_command(gen_doc, name="doc")
106
+ generate.add_command(gen_namespaces, name="namespaces")
107
+ generate.add_command(gen_owl, name="owl")
108
+ generate.add_command(gen_plantuml, name="plantuml")
109
+ generate.add_command(gen_proto, name="proto")
110
+ generate.add_command(gen_python, name="python")
111
+ generate.add_command(gen_pydantic, name="pydantic")
112
+ generate.add_command(gen_rdf, name="rdf")
113
+ generate.add_command(gen_shex, name="shex")
114
+ generate.add_command(gen_shacl, name="shacl")
115
+ generate.add_command(gen_sparql, name="sparql")
116
+ generate.add_command(gen_typescript, name="typescript")
117
+ generate.add_command(gen_terminusdb, name="terminusdb")
118
+ generate.add_command(gen_yuml, name="yuml")
119
+ generate.add_command(gen_yaml, name="yaml")
120
+ generate.add_command(gen_erdiagram, name="erdiagram")
121
+ generate.add_command(gen_sqla, name="sqla")
122
+ generate.add_command(gen_sqltables, name="sqltables")
123
+ generate.add_command(gen_summary, name="summary")
124
+ generate.add_command(gen_project, name="project")
125
+ generate.add_command(gen_excel, name="excel")
126
+ generate.add_command(gen_sssom, name="sssom")
127
+ generate.add_command(gen_linkml, name="linkml")
128
+
129
+ # Dev helpers
130
+ dev.add_command(run_tutorial, name="tutorial")
@@ -0,0 +1,105 @@
1
+ """
2
+ Models for intermediate build results
3
+
4
+ (see PydanticGenerator for example implementation and use)
5
+ """
6
+
7
+ import dataclasses
8
+ from abc import abstractmethod
9
+ from typing import Any, TypeVar
10
+
11
+ try:
12
+ from typing import Annotated
13
+ except ImportError:
14
+ from typing_extensions import Annotated
15
+
16
+
17
+ from linkml_runtime.linkml_model import (
18
+ ClassDefinition,
19
+ EnumDefinition,
20
+ SchemaDefinition,
21
+ SlotDefinition,
22
+ TypeDefinition,
23
+ )
24
+ from pydantic import BaseModel, ConfigDict, GetCoreSchemaHandler
25
+ from pydantic_core import core_schema
26
+
27
+ T = TypeVar("T", bound="BuildResult", covariant=True)
28
+
29
+
30
+ @dataclasses.dataclass()
31
+ class SkipValidation:
32
+ """
33
+ A version of :class:`pydantic.SkipValidation` that actually skips generating the
34
+ schema for the field entirely - useful for including types that don't need to be validated
35
+ like the metamodel dataclasses
36
+ """
37
+
38
+ def __class_getitem__(cls, item: Any) -> Any:
39
+ return Annotated[item, SkipValidation()]
40
+
41
+ @classmethod
42
+ def __get_pydantic_core_schema__(cls, source: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:
43
+ return core_schema.any_schema()
44
+
45
+ __hash__ = object.__hash__
46
+
47
+
48
+ class BuildResult(BaseModel):
49
+ """
50
+ The result of any build phase for any linkML object
51
+
52
+ BuildResults are merged in the serialization process, and are used
53
+ to keep track of not only the particular representation
54
+ of the thing in question, but any "side effects" that need to happen
55
+ elsewhere in the generation process (like adding imports, injecting classes, etc.)
56
+ """
57
+
58
+ model_config = ConfigDict(arbitrary_types_allowed=True)
59
+
60
+ @abstractmethod
61
+ def merge(self, other: T) -> T:
62
+ """
63
+ Build results should have some means of merging results of a like kind
64
+ """
65
+
66
+
67
+ class SchemaResult(BuildResult):
68
+ """Abstract results container for built schemas"""
69
+
70
+ source: SkipValidation[SchemaDefinition]
71
+
72
+ def merge(self, other: T) -> T:
73
+ """
74
+ SchemaResults are special and don't need a merge method, since generating
75
+ multiple schemas at once is not common or expected behavior for a generator.
76
+ """
77
+ raise NotImplementedError("SchemaResult doesn't need a merge method, and none has been defined")
78
+
79
+
80
+ class ClassResult(BuildResult):
81
+ """Abstract results container for built classes"""
82
+
83
+ source: SkipValidation[ClassDefinition]
84
+
85
+
86
+ class SlotResult(BuildResult):
87
+ """Abstract results container for built slots"""
88
+
89
+ source: SkipValidation[SlotDefinition]
90
+
91
+
92
+ class TypeResult(BuildResult):
93
+ """Abstract results container for built types"""
94
+
95
+ source: SkipValidation[TypeDefinition]
96
+
97
+
98
+ class EnumResult(BuildResult):
99
+ """Abstract results container for built enums"""
100
+
101
+ source: SkipValidation[EnumDefinition]
102
+
103
+
104
+ class RangeResult(BuildResult):
105
+ """Abstract results container for just the range part of a slot"""
@@ -0,0 +1,286 @@
1
+ import abc
2
+ import re
3
+ from abc import ABC
4
+ from typing import Any, Optional
5
+
6
+ from linkml_runtime import SchemaView
7
+ from linkml_runtime.linkml_model import (
8
+ Boolean,
9
+ ClassDefinition,
10
+ Date,
11
+ Datetime,
12
+ Decimal,
13
+ Double,
14
+ EnumDefinitionName,
15
+ Float,
16
+ Integer,
17
+ SlotDefinition,
18
+ String,
19
+ Time,
20
+ Uri,
21
+ )
22
+ from linkml_runtime.linkml_model.types import (
23
+ Curie,
24
+ DateOrDatetime,
25
+ Jsonpath,
26
+ Jsonpointer,
27
+ Ncname,
28
+ Nodeidentifier,
29
+ Objectidentifier,
30
+ Sparqlpath,
31
+ Uriorcurie,
32
+ )
33
+
34
+
35
+ class IfAbsentProcessor(ABC):
36
+ """
37
+ Processes value of ifabsent slot.
38
+
39
+ See `<https://w3id.org/linkml/ifabsent>`_.
40
+ """
41
+
42
+ ifabsent_regex = re.compile("""(?:(?P<type>\w+)\()?[\"\']?(?P<default_value>[^\(\)\"\')]*)[\"\']?\)?""")
43
+
44
+ def __init__(self, schema_view: SchemaView):
45
+ self.schema_view = schema_view
46
+
47
+ def process_slot(self, slot: SlotDefinition, cls: ClassDefinition) -> Optional[str]:
48
+ if slot.ifabsent:
49
+ ifabsent_match = self.ifabsent_regex.search(slot.ifabsent)
50
+ ifabsent_default_value = ifabsent_match.group("default_value")
51
+
52
+ return self._map_to_default_value(slot, ifabsent_default_value, cls)
53
+
54
+ return None
55
+
56
+ def _map_to_default_value(
57
+ self, slot: SlotDefinition, ifabsent_default_value: Any, cls: ClassDefinition
58
+ ) -> Optional[str]:
59
+ # Used to manage specific cases that aren't generic
60
+ mapped, custom_default_value = self.map_custom_default_values(ifabsent_default_value, slot, cls)
61
+ if mapped:
62
+ return custom_default_value
63
+
64
+ if slot.range == String.type_name:
65
+ return self.map_string_default_value(ifabsent_default_value, slot, cls)
66
+
67
+ if slot.range == Boolean.type_name:
68
+ if re.match(r"^[Tt]rue$", ifabsent_default_value):
69
+ return self.map_boolean_true_default_value(slot, cls)
70
+ elif re.match(r"^[Ff]alse$", ifabsent_default_value):
71
+ return self.map_boolean_false_default_value(slot, cls)
72
+ else:
73
+ raise ValueError(
74
+ f"The ifabsent value `{slot.ifabsent}` of the `{slot.name}` slot does not match a valid boolean "
75
+ f"value"
76
+ )
77
+
78
+ if slot.range == Integer.type_name:
79
+ return self.map_integer_default_value(ifabsent_default_value, slot, cls)
80
+
81
+ if slot.range == Float.type_name:
82
+ return self.map_float_default_value(ifabsent_default_value, slot, cls)
83
+
84
+ if slot.range == Double.type_name:
85
+ return self.map_double_default_value(ifabsent_default_value, slot, cls)
86
+
87
+ if slot.range == Decimal.type_name:
88
+ return self.map_decimal_default_value(ifabsent_default_value, slot, cls)
89
+
90
+ if slot.range == Time.type_name:
91
+ match = re.match(r"^(\d{2}):(\d{2}):(\d{2}).*$", ifabsent_default_value)
92
+ if match:
93
+ return self.map_time_default_value(match[1], match[2], match[3], slot, cls)
94
+ else:
95
+ raise ValueError(
96
+ f"The ifabsent value `{slot.ifabsent}` of the `{slot.name}` slot does not match a valid time value"
97
+ )
98
+
99
+ # TODO manage timezones and offsets
100
+ if slot.range == Date.type_name:
101
+ match = re.match(r"^(\d{4})-(\d{2})-(\d{2})$", ifabsent_default_value)
102
+ if match:
103
+ return self.map_date_default_value(match[1], match[2], match[3], slot, cls)
104
+ else:
105
+ raise ValueError(
106
+ f"The ifabsent value `{slot.ifabsent}` of the `{slot.name}` slot does not match a valid date value"
107
+ )
108
+
109
+ # TODO manage timezones and offsets
110
+ if slot.range == Datetime.type_name:
111
+ match = re.match(r"^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}).*$", ifabsent_default_value)
112
+ if match:
113
+ return self.map_datetime_default_value(
114
+ match[1], match[2], match[3], match[4], match[5], match[6], slot, cls
115
+ )
116
+ else:
117
+ raise ValueError(
118
+ f"The ifabsent value `{slot.ifabsent}` of the `{slot.name}` slot does not match a valid datetime "
119
+ f"value"
120
+ )
121
+
122
+ # TODO manage timezones and offsets
123
+ if slot.range == DateOrDatetime.type_name:
124
+ match = re.match(r"^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}):(\d{2}):(\d{2}))?.*$", ifabsent_default_value)
125
+ if match and (match[4] is None or match[5] is None or match[6] is None):
126
+ return self.map_date_default_value(match[1], match[2], match[3], slot, cls)
127
+ elif match:
128
+ return self.map_datetime_default_value(
129
+ match[1], match[2], match[3], match[4], match[5], match[6], slot, cls
130
+ )
131
+ else:
132
+ raise ValueError(
133
+ f"The ifabsent value `{slot.ifabsent}` of the `{slot.name}` slot does not match a valid date or "
134
+ f"datetime value"
135
+ )
136
+
137
+ if slot.range == Uri.type_name:
138
+ return self.map_uri_default_value(ifabsent_default_value, slot, cls)
139
+
140
+ if slot.range == Curie.type_name:
141
+ return self.map_curie_default_value(ifabsent_default_value, slot, cls)
142
+
143
+ if slot.range == Uriorcurie.type_name:
144
+ return self.map_uri_or_curie_default_value(ifabsent_default_value, slot, cls)
145
+
146
+ if slot.range == Ncname.type_name:
147
+ return self.map_nc_name_default_value(ifabsent_default_value, slot, cls)
148
+
149
+ if slot.range == Objectidentifier.type_name:
150
+ return self.map_object_identifier_default_value(ifabsent_default_value, slot, cls)
151
+
152
+ if slot.range == Nodeidentifier.type_name:
153
+ return self.map_node_identifier_default_value(ifabsent_default_value, slot, cls)
154
+
155
+ if slot.range == Jsonpointer.type_name:
156
+ return self.map_json_pointer_default_value(ifabsent_default_value, slot, cls)
157
+
158
+ if slot.range == Jsonpath.type_name:
159
+ return self.map_json_path_default_value(ifabsent_default_value, slot, cls)
160
+
161
+ if slot.range == Sparqlpath.type_name:
162
+ return self.map_sparql_path_default_value(ifabsent_default_value, slot, cls)
163
+
164
+ # -----------------------
165
+ # Enum slot ranges
166
+ # -----------------------
167
+
168
+ for enum_name, enum in self.schema_view.all_enums().items():
169
+ if enum_name == slot.range:
170
+ for permissible_value_name, permissible_value in enum.permissible_values.items():
171
+ if permissible_value_name == ifabsent_default_value:
172
+ return self.map_enum_default_value(enum_name, permissible_value_name, slot, cls)
173
+
174
+ raise ValueError(f"The ifabsent value `{slot.ifabsent}` of the `{slot.name}` slot could not be processed")
175
+
176
+ @abc.abstractmethod
177
+ def map_custom_default_values(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition) -> (bool, str):
178
+ """
179
+ Maps custom default values that aren't generic behaviours.
180
+
181
+ @param default_value: the default value extracted from the ifabsent attribute
182
+ @param slot: the definition of the slot
183
+ @param cls: the definition of the class
184
+ @return: a boolean that indicates if the value has been mapped followed by the mapped value
185
+ """
186
+ return False, None
187
+
188
+ @abc.abstractmethod
189
+ def map_string_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
190
+ raise NotImplementedError()
191
+
192
+ @abc.abstractmethod
193
+ def map_integer_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
194
+ raise NotImplementedError()
195
+
196
+ @abc.abstractmethod
197
+ def map_boolean_true_default_value(self, slot: SlotDefinition, cls: ClassDefinition):
198
+ raise NotImplementedError()
199
+
200
+ @abc.abstractmethod
201
+ def map_boolean_false_default_value(self, slot: SlotDefinition, cls: ClassDefinition):
202
+ raise NotImplementedError()
203
+
204
+ @abc.abstractmethod
205
+ def map_float_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
206
+ raise NotImplementedError()
207
+
208
+ @abc.abstractmethod
209
+ def map_double_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
210
+ raise NotImplementedError()
211
+
212
+ @abc.abstractmethod
213
+ def map_decimal_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
214
+ raise NotImplementedError()
215
+
216
+ @abc.abstractmethod
217
+ def map_time_default_value(self, hour: str, minutes: str, seconds: str, slot: SlotDefinition, cls: ClassDefinition):
218
+ raise NotImplementedError()
219
+
220
+ @abc.abstractmethod
221
+ def map_date_default_value(self, year: str, month: str, day: str, slot: SlotDefinition, cls: ClassDefinition):
222
+ raise NotImplementedError()
223
+
224
+ @abc.abstractmethod
225
+ def map_datetime_default_value(
226
+ self,
227
+ year: str,
228
+ month: str,
229
+ day: str,
230
+ hour: str,
231
+ minutes: str,
232
+ seconds: str,
233
+ slot: SlotDefinition,
234
+ cls: ClassDefinition,
235
+ ):
236
+ raise NotImplementedError()
237
+
238
+ @abc.abstractmethod
239
+ def map_uri_or_curie_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
240
+ raise NotImplementedError()
241
+
242
+ @abc.abstractmethod
243
+ def map_curie_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
244
+ raise NotImplementedError()
245
+
246
+ @abc.abstractmethod
247
+ def map_uri_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
248
+ raise NotImplementedError()
249
+
250
+ @abc.abstractmethod
251
+ def map_nc_name_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
252
+ raise NotImplementedError()
253
+
254
+ @abc.abstractmethod
255
+ def map_object_identifier_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
256
+ raise NotImplementedError()
257
+
258
+ @abc.abstractmethod
259
+ def map_node_identifier_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
260
+ raise NotImplementedError()
261
+
262
+ @abc.abstractmethod
263
+ def map_json_pointer_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
264
+ raise NotImplementedError()
265
+
266
+ @abc.abstractmethod
267
+ def map_json_path_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
268
+ raise NotImplementedError()
269
+
270
+ @abc.abstractmethod
271
+ def map_sparql_path_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
272
+ raise NotImplementedError()
273
+
274
+ @abc.abstractmethod
275
+ def map_enum_default_value(
276
+ self, enum_name: EnumDefinitionName, permissible_value_name: str, slot: SlotDefinition, cls: ClassDefinition
277
+ ):
278
+ raise NotImplementedError()
279
+
280
+ def _uri_for(self, s: str) -> str:
281
+ uri = str(self.schema_view.namespaces().uri_for(s))
282
+ return self.schema_view.namespaces().curie_for(uri, True, True) or self._strval(uri)
283
+
284
+ def _strval(self, txt: str) -> str:
285
+ txt = str(txt).replace('"', '\\"')
286
+ return f'"{txt}"'
@@ -0,0 +1,124 @@
1
+ """
2
+ Lifestyle methods mixin
3
+ """
4
+
5
+ from typing import Iterable, TypeVar
6
+
7
+ from linkml_runtime import SchemaView
8
+ from linkml_runtime.linkml_model.meta import (
9
+ ClassDefinition,
10
+ EnumDefinition,
11
+ SchemaDefinition,
12
+ SlotDefinition,
13
+ TypeDefinition,
14
+ )
15
+
16
+ from linkml.generators.common.build import ClassResult, RangeResult, SchemaResult, SlotResult, TypeResult
17
+ from linkml.generators.common.template import TemplateModel
18
+
19
+ TSchema = TypeVar("TSchema", bound=SchemaResult)
20
+ TClass = TypeVar("TClass", bound=ClassResult)
21
+ TSlot = TypeVar("TSlot", bound=SlotResult)
22
+ TRange = TypeVar("TRange", bound=RangeResult)
23
+ TType = TypeVar("TType", bound=TypeResult)
24
+ TEnum = TypeVar("TEnum", bound=EnumDefinition)
25
+ TTemplate = TypeVar("TTemplate", bound=TemplateModel)
26
+
27
+
28
+ class LifecycleMixin:
29
+ """
30
+ Mixin class for implementing lifecycle methods to modify the generation process
31
+ without needing messy overrides and tiptoeing around parent generator classes.
32
+
33
+ Not all classes that inherit from the mixin will be able to implement all of the lifecycle methods.
34
+ The generator class should make it clear which methods are supported in its documentation -
35
+ no programmatic checking for lifecycle method support is available on first implementation.
36
+
37
+ Generators should **not** define any of the lifecycle methods themselves - the purpose is
38
+ to allow downstream modification of the generation process with clear entrypoints and without
39
+ needing to copy/paste code from the generator/call ``super()`` methods - if the Generator
40
+ is also using the lifecycle method, the point of the mixin is lost.
41
+
42
+ The order that these methods are called may vary in different generators, but in general, if
43
+ slots are generated hierarchically within classes as in the pydantic generator...
44
+
45
+ * :meth:`.before_generate_schema`
46
+ * :meth:`.before_generate_classes`
47
+ * :meth:`.before_generate_class`
48
+ * :meth:`.before_generate_slots`
49
+ * :meth:`.before_generate_slot`
50
+ * :meth:`.after_generate_slot`
51
+ * :meth:`.after_generate_slots`
52
+ * :meth:`.after_generate_class`
53
+ * :meth:`.after_generate_classes`
54
+ * :meth:`.after_generate_schema`
55
+ * :meth:`.before_render_template`
56
+ * :meth:`.after_render_template`
57
+
58
+ (Add other examples of ordering from other generators as implemented)
59
+
60
+ Each method should receive a :class:`.SchemaView` to get perspective on the current schema
61
+ being built. The ``before_`` methods should receive and return a single or list of ``Definitions``
62
+ and the ``after_`` methods should receive and return a single or list of the appropriate :class:`.BuildResult`
63
+ type.
64
+ """
65
+
66
+ def before_generate_schema(self, schema: SchemaDefinition, sv: SchemaView) -> SchemaDefinition:
67
+ return schema
68
+
69
+ def after_generate_schema(self, schema: TSchema, sv: SchemaView) -> TSchema:
70
+ return schema
71
+
72
+ def before_generate_class(self, cls: ClassDefinition, sv: SchemaView) -> ClassDefinition:
73
+ return cls
74
+
75
+ def after_generate_class(self, cls: TClass, sv: SchemaView) -> TClass:
76
+ return cls
77
+
78
+ def before_generate_classes(self, cls: Iterable[ClassDefinition], sv: SchemaView) -> Iterable[ClassDefinition]:
79
+ return cls
80
+
81
+ def after_generate_classes(self, cls: Iterable[TClass], sv: SchemaView) -> Iterable[TClass]:
82
+ return cls
83
+
84
+ def before_generate_slot(self, slot: SlotDefinition, sv: SchemaView) -> SlotDefinition:
85
+ return slot
86
+
87
+ def after_generate_slot(self, slot: TSlot, sv: SchemaView) -> TSlot:
88
+ return slot
89
+
90
+ def before_generate_slots(self, slot: Iterable[SlotDefinition], sv: SchemaView) -> Iterable[SlotDefinition]:
91
+ return slot
92
+
93
+ def after_generate_slots(self, slot: Iterable[TSlot], sv: SchemaView) -> Iterable[TSlot]:
94
+ return slot
95
+
96
+ def before_generate_type(self, typ: TypeDefinition, sv: SchemaView) -> TypeDefinition:
97
+ return typ
98
+
99
+ def after_generate_type(self, typ: TType, sv: SchemaView) -> TType:
100
+ return typ
101
+
102
+ def before_generate_types(self, typ: Iterable[TypeDefinition], sv: SchemaView) -> Iterable[TypeDefinition]:
103
+ return typ
104
+
105
+ def after_generate_types(self, typ: Iterable[TType], sv: SchemaView) -> Iterable[TType]:
106
+ return typ
107
+
108
+ def before_generate_enum(self, enum: EnumDefinition, sv: SchemaView) -> EnumDefinition:
109
+ return enum
110
+
111
+ def after_generate_enum(self, enum: TEnum, sv: SchemaView) -> TEnum:
112
+ return enum
113
+
114
+ def before_generate_enums(self, enum: Iterable[EnumDefinition], sv: SchemaView) -> Iterable[EnumDefinition]:
115
+ return enum
116
+
117
+ def after_generate_enums(self, enum: Iterable[TEnum], sv: SchemaView) -> Iterable[TEnum]:
118
+ return enum
119
+
120
+ def before_render_template(self, template: TTemplate, sv: SchemaView) -> TTemplate:
121
+ return template
122
+
123
+ def after_render_template(self, template: str, sv: SchemaView) -> str:
124
+ return template