linkml 1.5.5__py3-none-any.whl → 1.5.7__py3-none-any.whl

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 (81) hide show
  1. linkml/__init__.py +2 -6
  2. linkml/_version.py +1 -1
  3. linkml/generators/PythonGenNotes.md +4 -4
  4. linkml/generators/__init__.py +26 -5
  5. linkml/generators/common/type_designators.py +27 -22
  6. linkml/generators/csvgen.py +4 -10
  7. linkml/generators/docgen/class.md.jinja2 +7 -0
  8. linkml/generators/docgen/class_diagram.md.jinja2 +0 -6
  9. linkml/generators/docgen/subset.md.jinja2 +54 -13
  10. linkml/generators/docgen.py +94 -92
  11. linkml/generators/dotgen.py +5 -9
  12. linkml/generators/erdiagramgen.py +58 -53
  13. linkml/generators/excelgen.py +10 -16
  14. linkml/generators/golanggen.py +11 -21
  15. linkml/generators/golrgen.py +4 -13
  16. linkml/generators/graphqlgen.py +3 -11
  17. linkml/generators/javagen.py +8 -15
  18. linkml/generators/jsonldcontextgen.py +7 -36
  19. linkml/generators/jsonldgen.py +14 -12
  20. linkml/generators/jsonschemagen.py +183 -136
  21. linkml/generators/linkmlgen.py +1 -1
  22. linkml/generators/markdowngen.py +40 -89
  23. linkml/generators/namespacegen.py +1 -2
  24. linkml/generators/oocodegen.py +22 -25
  25. linkml/generators/owlgen.py +48 -49
  26. linkml/generators/prefixmapgen.py +6 -14
  27. linkml/generators/projectgen.py +7 -14
  28. linkml/generators/protogen.py +3 -5
  29. linkml/generators/pydanticgen.py +85 -73
  30. linkml/generators/pythongen.py +89 -157
  31. linkml/generators/rdfgen.py +5 -11
  32. linkml/generators/shaclgen.py +32 -18
  33. linkml/generators/shexgen.py +19 -24
  34. linkml/generators/sparqlgen.py +5 -13
  35. linkml/generators/sqlalchemy/__init__.py +3 -2
  36. linkml/generators/sqlalchemy/sqlalchemy_declarative_template.py +7 -7
  37. linkml/generators/sqlalchemy/sqlalchemy_imperative_template.py +3 -3
  38. linkml/generators/sqlalchemygen.py +29 -27
  39. linkml/generators/sqlddlgen.py +34 -26
  40. linkml/generators/sqltablegen.py +21 -21
  41. linkml/generators/sssomgen.py +11 -13
  42. linkml/generators/summarygen.py +2 -4
  43. linkml/generators/terminusdbgen.py +7 -19
  44. linkml/generators/typescriptgen.py +10 -18
  45. linkml/generators/yamlgen.py +0 -2
  46. linkml/generators/yumlgen.py +23 -71
  47. linkml/linter/cli.py +4 -11
  48. linkml/linter/config/datamodel/config.py +17 -47
  49. linkml/linter/linter.py +2 -4
  50. linkml/linter/rules.py +34 -48
  51. linkml/reporting/__init__.py +2 -0
  52. linkml/reporting/model.py +9 -24
  53. linkml/transformers/relmodel_transformer.py +20 -33
  54. linkml/transformers/schema_renamer.py +14 -10
  55. linkml/utils/converter.py +15 -15
  56. linkml/utils/datautils.py +9 -24
  57. linkml/utils/datavalidator.py +2 -2
  58. linkml/utils/execute_tutorial.py +10 -12
  59. linkml/utils/generator.py +74 -92
  60. linkml/utils/helpers.py +4 -2
  61. linkml/utils/ifabsent_functions.py +23 -15
  62. linkml/utils/mergeutils.py +19 -35
  63. linkml/utils/rawloader.py +2 -6
  64. linkml/utils/schema_builder.py +31 -19
  65. linkml/utils/schema_fixer.py +28 -18
  66. linkml/utils/schemaloader.py +44 -89
  67. linkml/utils/schemasynopsis.py +50 -73
  68. linkml/utils/sqlutils.py +40 -30
  69. linkml/utils/typereferences.py +9 -6
  70. linkml/utils/validation.py +4 -5
  71. linkml/validators/__init__.py +2 -0
  72. linkml/validators/jsonschemavalidator.py +104 -53
  73. linkml/validators/sparqlvalidator.py +5 -15
  74. linkml/workspaces/datamodel/workspaces.py +13 -30
  75. linkml/workspaces/example_runner.py +75 -68
  76. {linkml-1.5.5.dist-info → linkml-1.5.7.dist-info}/METADATA +2 -2
  77. linkml-1.5.7.dist-info/RECORD +109 -0
  78. linkml-1.5.5.dist-info/RECORD +0 -109
  79. {linkml-1.5.5.dist-info → linkml-1.5.7.dist-info}/LICENSE +0 -0
  80. {linkml-1.5.5.dist-info → linkml-1.5.7.dist-info}/WHEEL +0 -0
  81. {linkml-1.5.5.dist-info → linkml-1.5.7.dist-info}/entry_points.txt +0 -0
linkml/__init__.py CHANGED
@@ -20,9 +20,7 @@ MODULE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
20
20
  LOCAL_METAMODEL_YAML_FILE = linkml_files.LOCAL_PATH_FOR(Source.META, Format.YAML)
21
21
  LOCAL_TYPES_YAML_FILE = linkml_files.LOCAL_PATH_FOR(Source.TYPES, Format.YAML)
22
22
  LOCAL_MAPPINGS_YAML_FILE = linkml_files.LOCAL_PATH_FOR(Source.MAPPINGS, Format.YAML)
23
- LOCAL_ANNOTATIONS_YAML_FILE = linkml_files.LOCAL_PATH_FOR(
24
- Source.ANNOTATIONS, Format.YAML
25
- )
23
+ LOCAL_ANNOTATIONS_YAML_FILE = linkml_files.LOCAL_PATH_FOR(Source.ANNOTATIONS, Format.YAML)
26
24
  LOCAL_EXTENSIONS_YAML_FILE = linkml_files.LOCAL_PATH_FOR(Source.EXTENSIONS, Format.YAML)
27
25
 
28
26
  # Local location of jsonld and context.jsonld files
@@ -30,9 +28,7 @@ LOCAL_METAMODEL_LDCONTEXT_FILE = linkml_files.LOCAL_PATH_FOR(Source.META, Format
30
28
  LOCAL_METAMODEL_JSONLD_FILE = linkml_files.LOCAL_PATH_FOR(Source.META, Format.JSON)
31
29
  LOCAL_TYPES_LDCONTEXT_FILE = linkml_files.LOCAL_PATH_FOR(Source.TYPES, Format.JSONLD)
32
30
  LOCAL_TYPES_JSONLD_FILE = linkml_files.LOCAL_PATH_FOR(Source.TYPES, Format.JSON)
33
- LOCAL_MAPPINGS_LDCONTEXT_FILE = linkml_files.LOCAL_PATH_FOR(
34
- Source.MAPPINGS, Format.JSONLD
35
- )
31
+ LOCAL_MAPPINGS_LDCONTEXT_FILE = linkml_files.LOCAL_PATH_FOR(Source.MAPPINGS, Format.JSONLD)
36
32
  LOCAL_MAPPINGS_JSONLD_FILE = linkml_files.LOCAL_PATH_FOR(Source.MAPPINGS, Format.JSON)
37
33
 
38
34
  # Local location of metamodel shex file
linkml/_version.py CHANGED
@@ -3,7 +3,7 @@ try:
3
3
  except ImportError:
4
4
  # Python < 3.8
5
5
  import importlib_metadata as metadata # pragma: no cover
6
-
6
+
7
7
  try:
8
8
  __version__ = metadata.version(__package__)
9
9
  except metadata.PackageNotFoundError:
@@ -122,7 +122,7 @@ the builtin type `int`. Four class variables are included in the generation:
122
122
  * `type_name` - the non-mangled name assigned to the type in the original definition
123
123
  * `type_model_uri` - the URIRef of the type definition in the default LinkML namespace
124
124
 
125
- The python then emits a class definition for the `Integers` classe, where we have defined four slot type permutations:
125
+ The python then emits a class definition for the `Integers` class, where we have defined four slot type permutations:
126
126
 
127
127
  1) `mand_integer` - a single valued required type:
128
128
 
@@ -189,7 +189,7 @@ The python then emits a class definition for the `Integers` classe, where we hav
189
189
 
190
190
  `opt_multi_integer: Optional[Union[int, List[int]]] = empty_list()`
191
191
 
192
- * The absence of a list property is always represented as an emtpy list:
192
+ * The absence of a list property is always represented as an empty list:
193
193
  ```
194
194
  if self.opt_multi_integer is None:
195
195
  self.opt_multi_integer = []
@@ -1232,7 +1232,7 @@ dictionary. You can construct a list of integers with a single value:
1232
1232
  ```python
1233
1233
  my_entries = ListOfIntegers(17)
1234
1234
  ```
1235
- Which would, if the class `ListOfIntegers`'s first variable was a multivalued slot with a range of intgers, result in
1235
+ Which would, if the class `ListOfIntegers`'s first variable was a multivalued slot with a range of integers, result in
1236
1236
  `my_entries.v == [17]`. When dealing with classes, however, the following:
1237
1237
  ```python
1238
1238
  my_entries = ListOfClasses(dict(name='element1', value=17))
@@ -1243,7 +1243,7 @@ The final line in the `__post_init__` section:
1243
1243
  ```python
1244
1244
  self._normalize_inlined_slot(slot_name="v1", slot_type=IdentifiedThreeElementClass, key_name="name", inlined_as_list=True, keyed=True)
1245
1245
  ```
1246
- passes the remainder of the post initilization normalization to a function defined in `YAMLRoot`.
1246
+ passes the remainder of the post initialization normalization to a function defined in `YAMLRoot`.
1247
1247
 
1248
1248
 
1249
1249
  The final case, Case 2.4 (Inlined as dictionary) is essentially the same, with the exception that the target type is
@@ -2,7 +2,17 @@
2
2
  Generators translate between a SchemaDefinition and an alternative
3
3
  representation such as JsonSchema
4
4
  """
5
- # Generator version numbers
5
+
6
+ from linkml.generators.javagen import JavaGenerator
7
+ from linkml.generators.jsonschemagen import JsonSchemaGenerator
8
+ from linkml.generators.owlgen import OwlSchemaGenerator
9
+ from linkml.generators.pydanticgen import PydanticGenerator
10
+ from linkml.generators.pythongen import PythonGenerator
11
+ from linkml.generators.shaclgen import ShaclGenerator
12
+ from linkml.generators.shexgen import ShExGenerator
13
+ from linkml.generators.sqlalchemygen import SQLAlchemyGenerator
14
+ from linkml.generators.sqltablegen import SQLTableGenerator
15
+
6
16
  __all__ = [
7
17
  "csvgen",
8
18
  "dotgen",
@@ -18,15 +28,26 @@ __all__ = [
18
28
  "owlgen",
19
29
  "protogen",
20
30
  "pythongen",
31
+ "pydanticgen",
21
32
  "rdfgen",
22
33
  "shexgen",
34
+ "shaclgen",
23
35
  "sssomgen",
24
36
  "summarygen",
25
37
  "yamlgen",
26
38
  "yumlgen",
27
- "PYTHON_GEN_VERSION",
39
+ "OwlSchemaGenerator",
40
+ "PydanticGenerator",
41
+ "PythonGenerator",
42
+ "JavaGenerator",
43
+ "JsonSchemaGenerator",
44
+ "ShaclGenerator",
45
+ "ShExGenerator",
46
+ "SQLAlchemyGenerator",
47
+ "SQLTableGenerator",
28
48
  ]
29
- GENERATOR_BASE = "0.9"
30
49
 
31
- PYTHON_GEN_VERSION = GENERATOR_BASE + ".0"
32
- JAVA_GEN_VERSION = GENERATOR_BASE + ".0"
50
+ # TODO: deprecate usage of these
51
+ # GENERATOR_BASE = "0.9"
52
+
53
+ # PYTHON_GEN_VERSION = GENERATOR_BASE + ".0"
@@ -1,44 +1,49 @@
1
- from linkml_runtime.linkml_model.meta import SlotDefinition, ClassDefinition
1
+ from typing import List
2
+
3
+ from linkml_runtime.linkml_model.meta import ClassDefinition, SlotDefinition
2
4
  from linkml_runtime.utils.schemaview import SchemaView
3
- from linkml_runtime.utils.formatutils import camelcase
4
- from typing import List, Tuple
5
5
 
6
- def get_type_designator_value(sv: SchemaView, type_designator_slot: SlotDefinition, class_def: ClassDefinition) -> str:
6
+
7
+ def get_type_designator_value(
8
+ sv: SchemaView, type_designator_slot: SlotDefinition, class_def: ClassDefinition
9
+ ) -> str:
7
10
  """
8
- retuns the correct value for a type designator field for a given class, depending on its range
9
- this implements the logic described in https://github.com/linkml/linkml/issues/945:
11
+ returns the correct value for a type designator field for a given class, depending on its range
12
+ this implements the logic described in https://github.com/linkml/linkml/issues/945:
10
13
  """
11
14
  slot_types = set(sv.type_ancestors(type_designator_slot.range))
12
- if 'uri' in slot_types:
13
- return sv.get_uri(class_def,expand=True,native=False)
14
- elif 'uriorcurie' in slot_types:
15
- return sv.get_uri(class_def,expand=False, native=False)
16
- elif 'string' in slot_types:
15
+ if "uri" in slot_types:
16
+ return sv.get_uri(class_def, expand=True, native=False)
17
+ elif "uriorcurie" in slot_types:
18
+ return sv.get_uri(class_def, expand=False, native=False)
19
+ elif "string" in slot_types:
17
20
  return class_def.name
18
21
  else:
19
- return sv.get_uri(class_def,expand=False, native=False)
22
+ return sv.get_uri(class_def, expand=False, native=False)
20
23
 
21
24
 
22
- def get_accepted_type_designator_values(sv: SchemaView, type_designator_slot: SlotDefinition, class_def: ClassDefinition) -> List[str]:
25
+ def get_accepted_type_designator_values(
26
+ sv: SchemaView, type_designator_slot: SlotDefinition, class_def: ClassDefinition
27
+ ) -> List[str]:
23
28
  """
24
- retuns the accepted values for a type designator field for a given class, depending on its range
25
- this implements the logic described in https://github.com/linkml/linkml/issues/945:
29
+ returns the accepted values for a type designator field for a given class, depending on its range
30
+ this implements the logic described in https://github.com/linkml/linkml/issues/945:
26
31
  """
27
32
  accepted_uri_values = [
28
- sv.get_uri(class_def, expand=True, native=True),
29
- sv.get_uri(class_def, expand=True, native=False),
30
- sv.get_uri(class_def, expand=False, native=True),
31
- sv.get_uri(class_def, expand=False, native=False),
32
- ]
33
+ sv.get_uri(class_def, expand=True, native=True),
34
+ sv.get_uri(class_def, expand=True, native=False),
35
+ sv.get_uri(class_def, expand=False, native=True),
36
+ sv.get_uri(class_def, expand=False, native=False),
37
+ ]
33
38
  # unique, but with order preserved (https://stackoverflow.com/a/17016257)
34
39
  accepted_uri_values = list(dict.fromkeys(accepted_uri_values))
35
40
 
36
41
  slot_types = set(sv.type_ancestors(type_designator_slot.range))
37
- uri_types = ['uri', 'uriorcurie']
42
+ uri_types = ["uri", "uriorcurie"]
38
43
 
39
44
  if slot_types.intersection(uri_types):
40
45
  return accepted_uri_values
41
- elif type_designator_slot.range == 'string':
46
+ elif type_designator_slot.range == "string":
42
47
  return [class_def.name]
43
48
  else:
44
49
  return accepted_uri_values
@@ -5,12 +5,10 @@ import os
5
5
  import sys
6
6
  from csv import DictWriter
7
7
  from dataclasses import dataclass
8
- from typing import List, Optional, Set, TextIO, Union
8
+ from typing import List, Optional, Set
9
9
 
10
10
  import click
11
- from linkml_runtime.linkml_model.meta import (ClassDefinition,
12
- ClassDefinitionName,
13
- SchemaDefinition)
11
+ from linkml_runtime.linkml_model.meta import ClassDefinition, ClassDefinitionName
14
12
  from linkml_runtime.utils.formatutils import be, underscore
15
13
 
16
14
  from linkml._version import __version__
@@ -37,9 +35,7 @@ class CsvGenerator(Generator):
37
35
  sep: Optional[str] = None
38
36
  """Separator for columns"""
39
37
 
40
- closure: Optional[
41
- Set[ClassDefinitionName]
42
- ] = None
38
+ closure: Optional[Set[ClassDefinitionName]] = None
43
39
  """List of classes to include in output"""
44
40
 
45
41
  writer: Optional[DictWriter] = None
@@ -69,9 +65,7 @@ class CsvGenerator(Generator):
69
65
  self.closure.update(self.ancestors(self.schema.classes[clsname]))
70
66
 
71
67
  dialect: str = "excel" if self.format == "csv" else "excel-tab"
72
- self.writer = DictWriter(
73
- sys.stdout, ["id", "mappings", "description"], dialect=dialect
74
- )
68
+ self.writer = DictWriter(sys.stdout, ["id", "mappings", "description"], dialect=dialect)
75
69
  self.writer.writeheader()
76
70
 
77
71
  def visit_class(self, cls: ClassDefinition) -> bool:
@@ -18,7 +18,14 @@ _{{ element_description_line }}_
18
18
 
19
19
  URI: {{ gen.uri_link(element) }}
20
20
 
21
+
22
+ {% if diagram_type == "er_diagram" %}
23
+ ```{{ gen.mermaid_directive() }}
24
+ {{ gen.mermaid_diagram([element.name]) }}
25
+ ```
26
+ {% else %}
21
27
  {% include "class_diagram.md.jinja2" %}
28
+ {% endif %}
22
29
 
23
30
  {% if schemaview.class_parents(element.name) or schemaview.class_children(element.name, mixins=False) %}
24
31
 
@@ -1,8 +1,3 @@
1
- {% if diagram_type == "er_diagram" %}
2
- ```{{ gen.mermaid_directive() }}
3
- {{ gen.mermaid_diagram([element.name]) }}
4
- ```
5
- {% else %}
6
1
  {% if schemaview.class_parents(element.name) and schemaview.class_children(element.name) %}
7
2
  ```{{ gen.mermaid_directive() }}
8
3
  classDiagram
@@ -61,5 +56,4 @@
61
56
  {% endif %}
62
57
  {% endfor %}
63
58
  ```
64
- {% endif %}
65
59
  {% endif %}
@@ -1,7 +1,7 @@
1
1
  # Subset: {{ gen.name(element) }}
2
2
 
3
3
  {%- if header -%}
4
- {{header}}
4
+ {{ header }}
5
5
  {%- endif -%}
6
6
 
7
7
  {% if element.description %}
@@ -13,9 +13,32 @@ _{{ element_description_line }}_
13
13
 
14
14
  URI: {{ gen.uri_link(element) }}
15
15
 
16
-
17
16
  {% include "common_metadata.md.jinja2" %}
18
17
 
18
+ {% set classes_in_subset = [] %}
19
+ {% set slots_in_subset = [] %}
20
+ {% set enums_in_subset = [] %}
21
+
22
+ {# Collect classes, slots, and enumerations in subset #}
23
+ {% for c in gen.all_class_objects()|sort(attribute=sort_by) %}
24
+ {%- if element.name in c.in_subset %}
25
+ {% set _ = classes_in_subset.append(c) %}
26
+ {%- endif %}
27
+ {% endfor %}
28
+
29
+ {% for s in gen.all_slot_objects()|sort(attribute=sort_by) %}
30
+ {%- if element.name in s.in_subset %}
31
+ {% set _ = slots_in_subset.append(s) %}
32
+ {%- endif %}
33
+ {% endfor %}
34
+
35
+ {% for e in schemaview.all_enums().values() %}
36
+ {%- if element.name in e.in_subset %}
37
+ {% set _ = enums_in_subset.append(e) %}
38
+ {%- endif %}
39
+ {% endfor %}
40
+
41
+ {% if classes_in_subset %}
19
42
  ## Classes in subset
20
43
 
21
44
  | Class | Description |
@@ -32,34 +55,52 @@ URI: {{ gen.uri_link(element) }}
32
55
 
33
56
  {{c.description}}
34
57
 
58
+ {%- set filtered_slots = [] -%}
59
+
60
+ {%- for s in induced_slots|sort(attribute=sort_by) -%}
61
+ {%- if element.name in s.in_subset or element.name in schemaview.get_slot(s.name).in_subset -%}
62
+ {% set _ = filtered_slots.append(s) %}
63
+ {%- endif -%}
64
+ {%- endfor %}
65
+
66
+ {%- if filtered_slots|length > 0 -%}
35
67
  | Name | Cardinality and Range | Description |
36
68
  | --- | --- | --- |
37
- {% for s in gen.class_induced_slots(c.name)|sort(attribute=sort_by) -%}
38
- {% if element.name in s.in_subset or element.name in schemaview.get_slot(s.name).in_subset -%}
69
+ {% for s in filtered_slots -%}
39
70
  | {{gen.link(s)}} | {{ gen.cardinality(s) }} <br/> {{gen.link(s.range)}} | {{s.description|enshorten}} {% if s.identifier %}**identifier**{% endif %} |
40
- {% endif -%}
41
71
  {% endfor %}
72
+ {%- endif %}
42
73
 
43
- {% endif -%}
74
+
75
+ {%- endif %}
44
76
  {% endfor %}
45
77
 
78
+ {%- endif %}
79
+
80
+
81
+ {% if slots_in_subset %}
46
82
  ## Slots in subset
47
83
 
48
84
  | Slot | Description |
49
85
  | --- | --- |
50
- {% for s in gen.all_slot_objects()|sort(attribute=sort_by) -%}
86
+ {% for s in slots_in_subset|sort(attribute=sort_by) -%}
51
87
  {%- if element.name in s.in_subset -%}
52
- | {{gen.link(s)}} | {{s.description|enshorten}} |
53
- {% endif -%}
88
+ | {{ gen.link(s) }} | {{ s.description|enshorten }} |
89
+ {%- endif %}
54
90
  {% endfor %}
55
91
 
92
+ {%- endif %}
93
+
94
+
95
+ {% if enums_in_subset %}
56
96
  ## Enumerations in subset
57
97
 
58
98
  | Enumeration | Description |
59
99
  | --- | --- |
60
- {% for e in schemaview.all_enums().values()|sort(attribute='name') -%}
61
- {%- if element.name in e.in_subset -%}
62
- | {{gen.link(e)}} | {{e.description|enshorten}} |
63
- {% endif -%}
100
+ {% for e in enums_in_subset|sort(attribute='name') -%}
101
+ {%- if element.name in e.in_subset %}
102
+ | {{ gen.link(e) }} | {{ e.description|enshorten }} |
103
+ {%- endif %}
64
104
  {% endfor %}
65
105
 
106
+ {%- endif %}