linkml 1.9.4rc1__py3-none-any.whl → 1.9.5rc1__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 (77) hide show
  1. linkml/cli/main.py +4 -0
  2. linkml/generators/__init__.py +2 -0
  3. linkml/generators/common/build.py +5 -20
  4. linkml/generators/common/template.py +289 -3
  5. linkml/generators/docgen.py +55 -10
  6. linkml/generators/erdiagramgen.py +9 -5
  7. linkml/generators/graphqlgen.py +32 -6
  8. linkml/generators/jsonldcontextgen.py +78 -12
  9. linkml/generators/jsonschemagen.py +29 -12
  10. linkml/generators/mermaidclassdiagramgen.py +21 -3
  11. linkml/generators/owlgen.py +4 -1
  12. linkml/generators/panderagen/dataframe_class.py +13 -0
  13. linkml/generators/panderagen/dataframe_field.py +50 -0
  14. linkml/generators/panderagen/linkml_pandera_validator.py +186 -0
  15. linkml/generators/panderagen/panderagen.py +22 -5
  16. linkml/generators/panderagen/panderagen_class_based/class.jinja2 +70 -13
  17. linkml/generators/panderagen/panderagen_class_based/custom_checks.jinja2 +27 -0
  18. linkml/generators/panderagen/panderagen_class_based/enums.jinja2 +3 -3
  19. linkml/generators/panderagen/panderagen_class_based/pandera.jinja2 +12 -2
  20. linkml/generators/panderagen/panderagen_class_based/slots.jinja2 +19 -17
  21. linkml/generators/panderagen/slot_generator_mixin.py +143 -16
  22. linkml/generators/panderagen/transforms/__init__.py +19 -0
  23. linkml/generators/panderagen/transforms/collection_dict_model_transform.py +62 -0
  24. linkml/generators/panderagen/transforms/list_dict_model_transform.py +66 -0
  25. linkml/generators/panderagen/transforms/model_transform.py +8 -0
  26. linkml/generators/panderagen/transforms/nested_struct_model_transform.py +27 -0
  27. linkml/generators/panderagen/transforms/simple_dict_model_transform.py +86 -0
  28. linkml/generators/plantumlgen.py +17 -11
  29. linkml/generators/pydanticgen/pydanticgen.py +53 -2
  30. linkml/generators/pydanticgen/template.py +45 -233
  31. linkml/generators/pydanticgen/templates/attribute.py.jinja +1 -0
  32. linkml/generators/pydanticgen/templates/base_model.py.jinja +16 -2
  33. linkml/generators/pydanticgen/templates/imports.py.jinja +1 -1
  34. linkml/generators/rdfgen.py +11 -2
  35. linkml/generators/rustgen/__init__.py +3 -0
  36. linkml/generators/rustgen/build.py +94 -0
  37. linkml/generators/rustgen/cli.py +65 -0
  38. linkml/generators/rustgen/rustgen.py +1038 -0
  39. linkml/generators/rustgen/template.py +865 -0
  40. linkml/generators/rustgen/templates/Cargo.toml.jinja +42 -0
  41. linkml/generators/rustgen/templates/anything.rs.jinja +142 -0
  42. linkml/generators/rustgen/templates/as_key_value.rs.jinja +56 -0
  43. linkml/generators/rustgen/templates/class_module.rs.jinja +8 -0
  44. linkml/generators/rustgen/templates/enum.rs.jinja +54 -0
  45. linkml/generators/rustgen/templates/file.rs.jinja +62 -0
  46. linkml/generators/rustgen/templates/import.rs.jinja +4 -0
  47. linkml/generators/rustgen/templates/imports.rs.jinja +8 -0
  48. linkml/generators/rustgen/templates/poly.rs.jinja +9 -0
  49. linkml/generators/rustgen/templates/poly_containers.rs.jinja +439 -0
  50. linkml/generators/rustgen/templates/poly_trait.rs.jinja +15 -0
  51. linkml/generators/rustgen/templates/poly_trait_impl.rs.jinja +5 -0
  52. linkml/generators/rustgen/templates/poly_trait_impl_orsubtype.rs.jinja +5 -0
  53. linkml/generators/rustgen/templates/poly_trait_property.rs.jinja +8 -0
  54. linkml/generators/rustgen/templates/poly_trait_property_impl.rs.jinja +132 -0
  55. linkml/generators/rustgen/templates/poly_trait_property_match.rs.jinja +10 -0
  56. linkml/generators/rustgen/templates/property.rs.jinja +19 -0
  57. linkml/generators/rustgen/templates/pyproject.toml.jinja +10 -0
  58. linkml/generators/rustgen/templates/serde_utils.rs.jinja +310 -0
  59. linkml/generators/rustgen/templates/slot_range_as_union.rs.jinja +61 -0
  60. linkml/generators/rustgen/templates/struct.rs.jinja +75 -0
  61. linkml/generators/rustgen/templates/struct_or_subtype_enum.rs.jinja +108 -0
  62. linkml/generators/rustgen/templates/typealias.rs.jinja +13 -0
  63. linkml/generators/sqltablegen.py +18 -16
  64. linkml/generators/yarrrmlgen.py +157 -0
  65. linkml/linter/config/datamodel/config.py +160 -293
  66. linkml/linter/config/datamodel/config.yaml +34 -26
  67. linkml/linter/config/default.yaml +4 -0
  68. linkml/linter/config/recommended.yaml +4 -0
  69. linkml/linter/linter.py +1 -2
  70. linkml/linter/rules.py +37 -0
  71. linkml/utils/schemaloader.py +55 -3
  72. {linkml-1.9.4rc1.dist-info → linkml-1.9.5rc1.dist-info}/METADATA +2 -2
  73. {linkml-1.9.4rc1.dist-info → linkml-1.9.5rc1.dist-info}/RECORD +76 -38
  74. {linkml-1.9.4rc1.dist-info → linkml-1.9.5rc1.dist-info}/entry_points.txt +1 -0
  75. linkml/generators/panderagen/panderagen_class_based/mixins.jinja2 +0 -26
  76. {linkml-1.9.4rc1.dist-info → linkml-1.9.5rc1.dist-info}/WHEEL +0 -0
  77. {linkml-1.9.4rc1.dist-info → linkml-1.9.5rc1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,157 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ from typing import Any, TextIO
5
+
6
+ import click
7
+ import yaml
8
+ from linkml_runtime.linkml_model.meta import ClassDefinition, SchemaDefinition
9
+ from linkml_runtime.utils.schemaview import SchemaView
10
+
11
+ from linkml._version import __version__
12
+ from linkml.utils.generator import Generator, shared_arguments
13
+
14
+ # defaults
15
+ DEFAULT_SOURCE_JSON = "data.json~jsonpath"
16
+ DEFAULT_SOURCE_CSV = "data.csv~csv"
17
+ DEFAULT_ITERATOR = "$.items[*]" # generic top-level array
18
+
19
+
20
+ class _YamlDumper(yaml.Dumper):
21
+ # keep list indentation stable
22
+ def increase_indent(self, flow: bool = False, indentless: bool = False):
23
+ return super().increase_indent(flow, False)
24
+
25
+
26
+ class YarrrmlGenerator(Generator):
27
+ """LinkML -> YARRRML exporter."""
28
+
29
+ generatorname = os.path.basename(__file__)
30
+ generatorversion = "0.2.0"
31
+ valid_formats = ["yml", "yaml"]
32
+ visit_all_class_slots = False
33
+
34
+ def __init__(self, schema: str | TextIO | SchemaDefinition, format: str = "yml", **kwargs):
35
+ src = kwargs.pop("source", None)
36
+ it = kwargs.pop("iterator_template", None)
37
+
38
+ super().__init__(schema, **kwargs)
39
+
40
+ self.schemaview = SchemaView(schema)
41
+ self.schema: SchemaDefinition = self.schemaview.schema
42
+
43
+ self.format = format
44
+
45
+ self.source: str = src or DEFAULT_SOURCE_JSON
46
+ self.iterator_template: str = it or DEFAULT_ITERATOR
47
+
48
+ # public
49
+ def serialize(self, **args) -> str:
50
+ data = yaml.dump(
51
+ self.as_dict(),
52
+ Dumper=_YamlDumper,
53
+ sort_keys=False,
54
+ default_flow_style=False,
55
+ allow_unicode=True,
56
+ )
57
+ return data
58
+
59
+ def as_dict(self) -> dict[str, Any]:
60
+ sv = self.schemaview
61
+ mappings = {}
62
+ for cls in sv.all_classes().values():
63
+ if not (sv.get_identifier_slot(cls.name) or sv.get_key_slot(cls.name)):
64
+ continue
65
+
66
+ mapping = {
67
+ "s": self._subject_template_for_class(cls),
68
+ "po": self._po_list_for_class(cls),
69
+ }
70
+ if self._is_json_source():
71
+ mapping["sources"] = [[self.source, self._iterator_for_class(cls)]]
72
+ else:
73
+ mapping["sources"] = [self.source]
74
+
75
+ mappings[str(cls.name)] = mapping
76
+
77
+ return {"prefixes": self._prefixes(), "mappings": mappings}
78
+
79
+ # helpers
80
+ def _is_json_source(self) -> bool:
81
+ return "~jsonpath" in (self.source or "")
82
+
83
+ def _prefixes(self) -> dict[str, str]:
84
+ px: dict[str, str] = {}
85
+ if self.schema.prefixes:
86
+ for p in self.schema.prefixes.values():
87
+ if p.prefix_prefix and p.prefix_reference:
88
+ px[str(p.prefix_prefix)] = str(p.prefix_reference)
89
+ px.setdefault("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#")
90
+ return px
91
+
92
+ def _iterator_for_class(self, c: ClassDefinition) -> str:
93
+ # supports {Class}
94
+ return self.iterator_template.replace("{Class}", c.name)
95
+
96
+ def _subject_template_for_class(self, c: ClassDefinition) -> str:
97
+ sv = self.schemaview
98
+ default_prefix = sv.schema.default_prefix or "ex"
99
+ id_slot = sv.get_identifier_slot(c.name)
100
+ if id_slot:
101
+ return f"{default_prefix}:$({id_slot.name})"
102
+ key_slot = sv.get_key_slot(c.name)
103
+ if key_slot:
104
+ return f"{default_prefix}:$({key_slot.name})"
105
+ return f"{default_prefix}:{c.name}/$(subject_id)" # safe fallback
106
+
107
+ def _po_list_for_class(self, c: ClassDefinition) -> list[dict[str, Any]]:
108
+ sv = self.schemaview
109
+ po = []
110
+ class_curie = sv.get_uri(c, expand=False)
111
+ if class_curie:
112
+ po.append({"p": "rdf:type", "o": str(class_curie)})
113
+
114
+ default_prefix = sv.schema.default_prefix or "ex"
115
+
116
+ for s in sv.class_induced_slots(c.name):
117
+ pred = sv.get_uri(s, expand=False) or f"{default_prefix}:{s.name}"
118
+ decl = sv.get_slot(s.name)
119
+ alias = decl.alias if decl and decl.alias else s.alias
120
+ var = alias or s.name
121
+
122
+ is_obj = sv.get_class(s.range) is not None if s.range else False
123
+ if is_obj:
124
+ inlined = None
125
+ if decl and decl.inlined is not None:
126
+ inlined = decl.inlined
127
+ if inlined is False:
128
+ po.append({"p": pred, "o": {"value": f"$({var})", "type": "iri"}})
129
+ continue
130
+
131
+ po.append({"p": pred, "o": f"$({var})"})
132
+ return po
133
+
134
+
135
+ @shared_arguments(YarrrmlGenerator)
136
+ @click.command(name="yarrrml")
137
+ @click.option(
138
+ "--source",
139
+ help="YARRRML source shorthand, e.g., data.json~jsonpath or data.csv~csv",
140
+ )
141
+ @click.option(
142
+ "--iterator-template",
143
+ help='JSONPath iterator template; supports {Class}, default: "$.items[*]"',
144
+ )
145
+ @click.version_option(__version__, "-V", "--version")
146
+ def cli(yamlfile, source, iterator_template, **args):
147
+ """Generate YARRRML mappings from a LinkML schema."""
148
+ if source:
149
+ args["source"] = source
150
+ if iterator_template:
151
+ args["iterator_template"] = iterator_template
152
+ gen = YarrrmlGenerator(yamlfile, **args)
153
+ print(gen.serialize(**args))
154
+
155
+
156
+ if __name__ == "__main__":
157
+ cli()