linkml 1.9.4rc1__py3-none-any.whl → 1.9.5__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 (83) hide show
  1. linkml/cli/main.py +5 -1
  2. linkml/converter/__init__.py +0 -0
  3. linkml/generators/__init__.py +2 -0
  4. linkml/generators/common/build.py +5 -20
  5. linkml/generators/common/template.py +289 -3
  6. linkml/generators/docgen.py +55 -10
  7. linkml/generators/erdiagramgen.py +9 -5
  8. linkml/generators/graphqlgen.py +32 -6
  9. linkml/generators/jsonldcontextgen.py +78 -12
  10. linkml/generators/jsonschemagen.py +29 -12
  11. linkml/generators/mermaidclassdiagramgen.py +21 -3
  12. linkml/generators/owlgen.py +13 -2
  13. linkml/generators/panderagen/dataframe_class.py +13 -0
  14. linkml/generators/panderagen/dataframe_field.py +50 -0
  15. linkml/generators/panderagen/linkml_pandera_validator.py +186 -0
  16. linkml/generators/panderagen/panderagen.py +22 -5
  17. linkml/generators/panderagen/panderagen_class_based/class.jinja2 +70 -13
  18. linkml/generators/panderagen/panderagen_class_based/custom_checks.jinja2 +27 -0
  19. linkml/generators/panderagen/panderagen_class_based/enums.jinja2 +3 -3
  20. linkml/generators/panderagen/panderagen_class_based/pandera.jinja2 +12 -2
  21. linkml/generators/panderagen/panderagen_class_based/slots.jinja2 +19 -17
  22. linkml/generators/panderagen/slot_generator_mixin.py +143 -16
  23. linkml/generators/panderagen/transforms/__init__.py +19 -0
  24. linkml/generators/panderagen/transforms/collection_dict_model_transform.py +62 -0
  25. linkml/generators/panderagen/transforms/list_dict_model_transform.py +66 -0
  26. linkml/generators/panderagen/transforms/model_transform.py +8 -0
  27. linkml/generators/panderagen/transforms/nested_struct_model_transform.py +27 -0
  28. linkml/generators/panderagen/transforms/simple_dict_model_transform.py +86 -0
  29. linkml/generators/plantumlgen.py +17 -11
  30. linkml/generators/pydanticgen/pydanticgen.py +53 -2
  31. linkml/generators/pydanticgen/template.py +45 -233
  32. linkml/generators/pydanticgen/templates/attribute.py.jinja +1 -0
  33. linkml/generators/pydanticgen/templates/base_model.py.jinja +16 -2
  34. linkml/generators/pydanticgen/templates/imports.py.jinja +1 -1
  35. linkml/generators/rdfgen.py +11 -2
  36. linkml/generators/rustgen/__init__.py +3 -0
  37. linkml/generators/rustgen/build.py +97 -0
  38. linkml/generators/rustgen/cli.py +83 -0
  39. linkml/generators/rustgen/rustgen.py +1186 -0
  40. linkml/generators/rustgen/template.py +910 -0
  41. linkml/generators/rustgen/templates/Cargo.toml.jinja +42 -0
  42. linkml/generators/rustgen/templates/anything.rs.jinja +149 -0
  43. linkml/generators/rustgen/templates/as_key_value.rs.jinja +86 -0
  44. linkml/generators/rustgen/templates/class_module.rs.jinja +8 -0
  45. linkml/generators/rustgen/templates/enum.rs.jinja +70 -0
  46. linkml/generators/rustgen/templates/file.rs.jinja +75 -0
  47. linkml/generators/rustgen/templates/import.rs.jinja +4 -0
  48. linkml/generators/rustgen/templates/imports.rs.jinja +8 -0
  49. linkml/generators/rustgen/templates/lib_shim.rs.jinja +52 -0
  50. linkml/generators/rustgen/templates/poly.rs.jinja +9 -0
  51. linkml/generators/rustgen/templates/poly_containers.rs.jinja +439 -0
  52. linkml/generators/rustgen/templates/poly_trait.rs.jinja +15 -0
  53. linkml/generators/rustgen/templates/poly_trait_impl.rs.jinja +5 -0
  54. linkml/generators/rustgen/templates/poly_trait_impl_orsubtype.rs.jinja +5 -0
  55. linkml/generators/rustgen/templates/poly_trait_property.rs.jinja +8 -0
  56. linkml/generators/rustgen/templates/poly_trait_property_impl.rs.jinja +134 -0
  57. linkml/generators/rustgen/templates/poly_trait_property_match.rs.jinja +10 -0
  58. linkml/generators/rustgen/templates/property.rs.jinja +28 -0
  59. linkml/generators/rustgen/templates/pyproject.toml.jinja +10 -0
  60. linkml/generators/rustgen/templates/serde_utils.rs.jinja +490 -0
  61. linkml/generators/rustgen/templates/slot_range_as_union.rs.jinja +64 -0
  62. linkml/generators/rustgen/templates/struct.rs.jinja +81 -0
  63. linkml/generators/rustgen/templates/struct_or_subtype_enum.rs.jinja +111 -0
  64. linkml/generators/rustgen/templates/stub_gen.rs.jinja +71 -0
  65. linkml/generators/rustgen/templates/stub_utils.rs.jinja +76 -0
  66. linkml/generators/rustgen/templates/typealias.rs.jinja +13 -0
  67. linkml/generators/sqltablegen.py +18 -16
  68. linkml/generators/yarrrmlgen.py +173 -0
  69. linkml/linter/config/datamodel/config.py +160 -293
  70. linkml/linter/config/datamodel/config.yaml +34 -26
  71. linkml/linter/config/default.yaml +4 -0
  72. linkml/linter/config/recommended.yaml +4 -0
  73. linkml/linter/linter.py +1 -2
  74. linkml/linter/rules.py +37 -0
  75. linkml/utils/schema_builder.py +2 -0
  76. linkml/utils/schemaloader.py +76 -3
  77. {linkml-1.9.4rc1.dist-info → linkml-1.9.5.dist-info}/METADATA +2 -2
  78. {linkml-1.9.4rc1.dist-info → linkml-1.9.5.dist-info}/RECORD +82 -40
  79. {linkml-1.9.4rc1.dist-info → linkml-1.9.5.dist-info}/entry_points.txt +2 -1
  80. linkml/generators/panderagen/panderagen_class_based/mixins.jinja2 +0 -26
  81. /linkml/{utils/converter.py → converter/cli.py} +0 -0
  82. {linkml-1.9.4rc1.dist-info → linkml-1.9.5.dist-info}/WHEEL +0 -0
  83. {linkml-1.9.4rc1.dist-info → linkml-1.9.5.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,42 @@
1
+ [package]
2
+ name = "{{ name }}"
3
+ version = "{{ version }}"
4
+ edition = "{{ edition }}"
5
+
6
+ [lib]
7
+ name = "{{ name }}"
8
+ {% if pyo3 %}
9
+ crate-type = ["cdylib", "rlib"]
10
+ {% else %}
11
+ crate-type = ["lib"]
12
+ {% endif %}
13
+
14
+ [dependencies]
15
+ {% for i in imports %}
16
+ {% if i.version %}
17
+ {% if i.features %}
18
+ {{ i.module }} = { version = "{{ i.version }}", features = [{% for feature in i.features %}"{{ feature }}"{% if not loop.last %},{% endif %}{% endfor %}] {% if i.feature_flag %} , optional = true {% endif %} }
19
+ {% else %}
20
+ {% if i.feature_flag %}
21
+ {{ i.module }} = { version = "{{ i.version }}", optional = true }
22
+ {% else %}
23
+ {{ i.module }} = "{{ i.version }}"
24
+ {% endif %}
25
+ {% endif %}
26
+ {% endif %}
27
+ {% endfor %}
28
+
29
+
30
+ [features]
31
+ {% if pyo3 and serde %}
32
+ default = ["pyo3", "serde"]
33
+ {% elif pyo3 %}
34
+ default = ["pyo3"]
35
+ {% elif serde %}
36
+ default = ["serde"]
37
+ {% else %}
38
+ default = []
39
+ {% endif %}
40
+ {% for k,v in cratefeatures.items() %}
41
+ {{ k }} = [{% for i in v %}"{{ i }}"{% if not loop.last %}, {% endif %}{% endfor %}]
42
+ {% endfor %}
@@ -0,0 +1,149 @@
1
+ #[derive(Clone, PartialEq)]
2
+ pub struct Anything(
3
+ #[cfg(feature = "serde")] pub serde_value::Value,
4
+ #[cfg(not(feature = "serde"))] pub (),
5
+ );
6
+
7
+
8
+ #[cfg(feature = "stubgen")]
9
+ impl ::pyo3_stub_gen::PyStubType for Anything {
10
+ fn type_output() -> ::pyo3_stub_gen::TypeInfo {
11
+ ::pyo3_stub_gen::TypeInfo::any()
12
+ }
13
+ }
14
+
15
+
16
+ #[cfg(feature = "serde")]
17
+ impl Serialize for Anything {
18
+ fn serialize<S>(&self, to_ser: S) -> Result<S::Ok, S::Error>
19
+ where S: serde::Serializer {
20
+ self.0.serialize(to_ser)
21
+ }
22
+ }
23
+
24
+ #[cfg(feature = "serde")]
25
+ impl<'de> Deserialize<'de> for Anything {
26
+ fn deserialize<D>(de: D) -> Result<Self, D::Error>
27
+ where D: serde::Deserializer<'de> {
28
+ <serde_value::Value as Deserialize>::deserialize(de).map(Anything)
29
+ }
30
+ }
31
+
32
+ #[cfg(all(feature = "pyo3", feature = "serde"))]
33
+ impl<'py> FromPyObject<'py> for Anything {
34
+ fn extract_bound(obj: &pyo3::Bound<'py, pyo3::types::PyAny>) -> pyo3::PyResult<Self> {
35
+ use pyo3::types::{PyAny, PyDict, PyList, PyTuple};
36
+ use serde_value::Value;
37
+
38
+ fn py_to_value<'py>(o: &pyo3::Bound<'py, PyAny>) -> pyo3::PyResult<Value> {
39
+ // None -> Unit
40
+ if o.is_none() {
41
+ return Ok(Value::Unit);
42
+ }
43
+
44
+ // Try simple primitives first
45
+ if let Ok(s) = o.extract::<&str>() {
46
+ return Ok(Value::String(s.to_string()));
47
+ }
48
+ if let Ok(b) = o.extract::<bool>() {
49
+ return Ok(Value::Bool(b));
50
+ }
51
+
52
+ // Sequences (list/tuple)
53
+ if let Ok(list) = o.downcast::<PyList>() {
54
+ let mut out = Vec::with_capacity(list.len());
55
+ for item in list.iter() {
56
+ out.push(py_to_value(&item)?);
57
+ }
58
+ return Ok(Value::Seq(out));
59
+ }
60
+ if let Ok(t) = o.downcast::<PyTuple>() {
61
+ let mut out = Vec::with_capacity(t.len());
62
+ for item in t.iter() {
63
+ out.push(py_to_value(&item)?);
64
+ }
65
+ return Ok(Value::Seq(out));
66
+ }
67
+
68
+ // Mappings (dict with string-like keys)
69
+ if let Ok(d) = o.downcast::<PyDict>() {
70
+ let mut map = std::collections::BTreeMap::<Value, Value>::new();
71
+ for (k, v) in d.iter() {
72
+ // Only accept string-like keys for deterministic ordering
73
+ if let Ok(ks) = k.extract::<&str>() {
74
+ map.insert(Value::String(ks.to_string()), py_to_value(&v)?);
75
+ } else {
76
+ return Err(pyo3::exceptions::PyTypeError::new_err(
77
+ "dict keys for Anything must be str",
78
+ ));
79
+ }
80
+ }
81
+ return Ok(Value::Map(map));
82
+ }
83
+
84
+ // Fallback: stringify unknown types
85
+ let s = format!("{}", o.str()?);
86
+ Ok(Value::String(s))
87
+ }
88
+
89
+ Ok(Anything(py_to_value(obj)?))
90
+ }
91
+ }
92
+
93
+ /* ---------- getter side ---------- */
94
+ #[cfg(all(feature = "pyo3", feature = "serde"))]
95
+ impl<'py> IntoPyObject<'py> for Anything {
96
+ type Target = PyAny;
97
+ type Output = Bound<'py, Self::Target>;
98
+ type Error = PyErr;
99
+
100
+ fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
101
+ use pyo3::types::{PyAny, PyDict, PyList, PyString};
102
+ use serde_value::Value;
103
+
104
+ fn value_to_py<'py>(py: Python<'py>, v: &Value) -> pyo3::PyResult<Bound<'py, PyAny>> {
105
+ match v {
106
+ Value::Unit => Ok(py.None().into_bound(py)),
107
+ Value::Bool(b) => Ok(pyo3::types::PyBool::new(py, *b).to_owned().into_any()),
108
+ Value::String(s) => Ok(PyString::new(py, s).into_any()),
109
+ Value::Seq(seq) => {
110
+ let list = PyList::empty(py);
111
+ for item in seq.iter() {
112
+ let ob = value_to_py(py, item)?;
113
+ list.append(ob)?;
114
+ }
115
+ Ok(list.into_any())
116
+ }
117
+ Value::Map(map) => {
118
+ let dict = PyDict::new(py);
119
+ for (k, v) in map.iter() {
120
+ let pk = value_to_py(py, k)?;
121
+ let pv = value_to_py(py, v)?;
122
+ dict.set_item(pk, pv)?;
123
+ }
124
+ Ok(dict.into_any())
125
+ }
126
+ // Best-effort for other serde_value variants
127
+ // (numbers, bytes, chars, etc.)
128
+ other => {
129
+ // Try common cases without bringing extra deps
130
+ // Numbers are converted via string if not covered above
131
+ let s = format!("{:?}", other);
132
+ Ok(PyString::new(py, &s).into_any())
133
+ }
134
+ }
135
+ }
136
+
137
+ value_to_py(py, &self.0)
138
+ }
139
+ }
140
+
141
+ impl std::fmt::Debug for Anything {
142
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
143
+ #[cfg(feature = "serde")]
144
+ return write!(f, "Anything({:?})", self.0);
145
+
146
+ #[cfg(not(feature = "serde"))]
147
+ return f.write_str("Anything(<opaque>)");
148
+ }
149
+ }
@@ -0,0 +1,86 @@
1
+ #[cfg(feature = "serde")]
2
+ impl serde_utils::InlinedPair for {{ name }} {
3
+ type Key = {{ key_property_type }};
4
+ {% if can_convert_from_primitive %}
5
+ type Value = {{ value_property_type }};
6
+ {% else %}
7
+ type Value = Value;
8
+ {% endif %}
9
+ type Error = String;
10
+
11
+ fn extract_key(&self) -> &Self::Key {
12
+ return &self.{{ key_property_name }};
13
+ }
14
+
15
+ fn from_pair_mapping(k: Self::Key, v: Value) -> Result<Self,Self::Error> {
16
+ let mut map = match v {
17
+ Value::Map(m) => m,
18
+ _ => return Err("ClassDefinition must be a mapping".into()),
19
+ };
20
+ let key_value = serde_value::to_value(k.clone())
21
+ .map_err(|e| format!("unable to serialize key: {}", e))?;
22
+ map.insert(Value::String("{{key_property_name}}".into()), key_value);
23
+ let de = Value::Map(map).into_deserializer();
24
+ match serde_path_to_error::deserialize(de) {
25
+ Ok(ok) => Ok(ok),
26
+ Err(e) => Err(format!("at `{}`: {}", e.path(), e.inner())),
27
+ }
28
+ }
29
+
30
+
31
+ {% if can_convert_from_primitive %}
32
+ fn from_pair_simple(k: Self::Key, v: Value) -> Result<Self,Self::Error> {
33
+ let mut map: BTreeMap<Value, Value> = BTreeMap::new();
34
+ let key_value = serde_value::to_value(k.clone())
35
+ .map_err(|e| format!("unable to serialize key: {}", e))?;
36
+ map.insert(Value::String("{{ key_property_name }}".into()), key_value);
37
+ map.insert(Value::String("{{ value_property_name }}".into()), v);
38
+ let de = Value::Map(map).into_deserializer();
39
+ match serde_path_to_error::deserialize(de) {
40
+ Ok(ok) => Ok(ok),
41
+ Err(e) => Err(format!("at `{}`: {}", e.path(), e.inner())),
42
+ }
43
+
44
+ {% elif can_convert_from_empty %}
45
+ fn from_pair_simple(k: Self::Key, _v: Value) -> Result<Self,Self::Error> {
46
+ let mut map: BTreeMap<Value, Value> = BTreeMap::new();
47
+ let key_value = serde_value::to_value(k.clone())
48
+ .map_err(|e| format!("unable to serialize key: {}", e))?;
49
+ map.insert(Value::String("{{ key_property_name }}".into()), key_value);
50
+ let de = Value::Map(map).into_deserializer();
51
+ match serde_path_to_error::deserialize(de) {
52
+ Ok(ok) => Ok(ok),
53
+ Err(e) => Err(format!("at `{}`: {}", e.path(), e.inner())),
54
+ }
55
+
56
+
57
+ {% else %}
58
+ fn from_pair_simple(_k: Self::Key, _v: Value) -> Result<Self,Self::Error> {
59
+ Err("Cannot create a {{name}} from a primitive value!".into())
60
+ {% endif %}
61
+ }
62
+
63
+ {% if can_convert_from_primitive %}
64
+ fn simple_value(&self) -> Option<&Self::Value> {
65
+ {% if value_property_optional %}
66
+ self.{{ value_property_name }}.as_ref()
67
+ {% else %}
68
+ Some(&self.{{ value_property_name }})
69
+ {% endif %}
70
+ }
71
+ {% endif %}
72
+
73
+ fn compact_value(&self) -> Option<Value> {
74
+ let value = match serde_value::to_value(self) {
75
+ Ok(v) => v,
76
+ Err(_) => return None,
77
+ };
78
+ match value {
79
+ Value::Map(mut map) => {
80
+ map.remove(&Value::String("{{ key_property_name }}".into()));
81
+ Some(Value::Map(map))
82
+ }
83
+ _ => None,
84
+ }
85
+ }
86
+ }
@@ -0,0 +1,8 @@
1
+ {% if slot_ranges | length > 0%}
2
+ pub mod {{ class_name_snakecase }}_utl {
3
+ use super::*;
4
+ {% for u in slot_ranges %}
5
+ {{ u}}
6
+ {% endfor %}
7
+ }
8
+ {% endif %}
@@ -0,0 +1,70 @@
1
+ #[derive(Debug, Clone, PartialEq)]
2
+ #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3
+ pub enum {{ name }} {
4
+ {% for item in items %}
5
+ {% if serde %}#[cfg_attr(feature = "serde", serde(rename = "{{ item.text_literal }}"))]
6
+ {% endif %}
7
+ {{ item.variant }},
8
+ {% endfor %}
9
+ }
10
+
11
+ impl core::fmt::Display for {{ name }} {
12
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
13
+ match self {
14
+ {% for item in items %}
15
+ {{ name }}::{{ item.variant }} => f.write_str("{{ item.text_literal }}"),
16
+ {% endfor %}
17
+ }
18
+ }
19
+ }
20
+
21
+ #[cfg(feature = "pyo3")]
22
+ impl<'py> IntoPyObject<'py> for {{ name }} {
23
+ type Target = PyAny;
24
+ type Output = Bound<'py, Self::Target>;
25
+ type Error = PyErr;
26
+ fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
27
+ let s: &str = match self {
28
+ {% for item in items %}
29
+ {{ name }}::{{ item.variant }} => "{{ item.text_literal }}",
30
+ {% endfor %}
31
+ };
32
+ Ok(pyo3::types::PyString::new(py, s).into_any())
33
+ }
34
+ }
35
+
36
+ #[cfg(feature = "pyo3")]
37
+ impl<'py> FromPyObject<'py> for {{ name }} {
38
+ fn extract_bound(ob: &pyo3::Bound<'py, pyo3::types::PyAny>) -> pyo3::PyResult<Self> {
39
+ if let Ok(s) = ob.extract::<&str>() {
40
+ match s {
41
+ {% for item in items %}
42
+ {{ item.python_match_pattern }} => Ok({{ name }}::{{ item.variant }}),
43
+ {% endfor %}
44
+ _ => Err(PyErr::new::<pyo3::exceptions::PyValueError, _>(
45
+ format!("invalid value for {{ name }}: {}", s),
46
+ )),
47
+ }
48
+ } else {
49
+ Err(PyErr::new::<pyo3::exceptions::PyTypeError, _>(
50
+ concat!("expected str for ", stringify!({{ name }})),
51
+ ))
52
+ }
53
+ }
54
+ }
55
+
56
+ #[cfg(feature = "stubgen")]
57
+ impl ::pyo3_stub_gen::PyStubType for {{ name }} {
58
+ fn type_output() -> ::pyo3_stub_gen::TypeInfo {
59
+ {% set literal_values = items | map(attribute='text_literal') | list %}
60
+ {% set escaped_values = literal_values | map('replace', "'", "\\'" ) | list %}
61
+ {% if escaped_values %}
62
+ ::pyo3_stub_gen::TypeInfo::with_module(
63
+ "typing.Literal['{{ escaped_values | join("', '") }}']",
64
+ "typing".into(),
65
+ )
66
+ {% else %}
67
+ ::pyo3_stub_gen::TypeInfo::ident("typing.Any")
68
+ {% endif %}
69
+ }
70
+ }
@@ -0,0 +1,75 @@
1
+ #![allow(non_camel_case_types)]
2
+
3
+ {% if inline_serde_utils %}
4
+ #[cfg(feature = "serde")]
5
+ mod serde_utils { {{ serde_utils }} }
6
+ {% else %}
7
+ #[cfg(feature = "serde")]
8
+ mod serde_utils;
9
+ {% endif %}
10
+ {% if emit_poly %}
11
+ pub mod poly;
12
+ pub mod poly_containers;
13
+ {% endif %}
14
+ {% if stubgen %}
15
+ #[cfg(feature = "stubgen")]
16
+ pub mod stub_utils;
17
+ {% endif %}
18
+
19
+ {{ imports }}
20
+
21
+ // Types
22
+
23
+ {% for type in types %}
24
+ {{ type }}
25
+ {% endfor %}
26
+
27
+ // Slots
28
+
29
+ {% for slot in slots %}
30
+ {{ slot }}
31
+ {% endfor %}
32
+
33
+ // Enums
34
+
35
+ {% for enum in enums %}
36
+ {{ enum }}
37
+ {% endfor %}
38
+
39
+ // Classes
40
+
41
+ {% for struct in structs %}
42
+ {{ struct }}
43
+ {% endfor %}
44
+
45
+
46
+ {% if needs_overwrite_except_none %}
47
+ /// Overwrite `left` with `right` unless `right` is `None`.
48
+ fn overwrite_except_none<T>(left: &mut Option<T>, right: Option<T>) {
49
+ if right.is_some() {
50
+ *left = right;
51
+ }
52
+ }
53
+ {% endif %}
54
+
55
+ {% if stubgen %}
56
+ #[cfg(feature = "stubgen")]
57
+ define_stub_info_gatherer!(stub_info);
58
+ {% endif %}
59
+
60
+
61
+ {% if pyo3 %}
62
+ #[cfg(feature = "pyo3")]
63
+ {% if handwritten_lib %}
64
+ pub fn register_pymodule(m: &Bound<'_, PyModule>) -> PyResult<()> {
65
+ {% else %}
66
+ #[pymodule]
67
+ #[pyo3(name="{{ name }}")]
68
+ fn {{ name }}(m: &Bound<'_, PyModule>) -> PyResult<()> {
69
+ {% endif %}
70
+ {% for s in pyclass_struct_names %}
71
+ m.add_class::<{{ s }}>()?;
72
+ {% endfor %}
73
+ Ok(())
74
+ }
75
+ {% endif %}
@@ -0,0 +1,4 @@
1
+ {% if feature_flag %}
2
+ #[cfg(feature = "{{ feature_flag }}")]
3
+ {% endif %}
4
+ use {{ module.replace('-','_') }}{% if objects %}::{{ "{" if objects|length > 1 else "" }}{% for obj in objects %}{{ obj.name }}{% if obj.alias %} as {{ obj.alias}}{% endif %}{% if not loop.last %},{% endif %}{% endfor %}{{ "}" if objects|length > 1 else "" }}{% else %}{% if alias %} as {{ alias }} {% endif %}{% endif %};
@@ -0,0 +1,8 @@
1
+ {% if imports is string %}
2
+ {{ imports }}
3
+ {% else %}
4
+ {% for import in imports %}
5
+ {{ import }}
6
+ {% endfor %}
7
+ {% endif %}
8
+ use std::collections::BTreeMap;
@@ -0,0 +1,52 @@
1
+ //! This file will only be autogenerated once, so it is safe to manually edit (unlike the other generated files)
2
+ //! If you want to re-generate it, just delete it and rerun rust generator.
3
+
4
+ pub mod generated;
5
+
6
+ pub use generated::*;
7
+ pub use chrono::NaiveDate;
8
+ pub use chrono::NaiveDateTime;
9
+
10
+ {% if root_struct_name %}
11
+ #[cfg(feature = "serde")]
12
+ /// Example helper that loads a YAML document into the root class. Edit or extend as needed.
13
+ pub fn load_yaml_{{ root_struct_fn_snake }}<P>(
14
+ path: P,
15
+ ) -> Result<generated::{{ root_struct_name }}, Box<dyn std::error::Error + Send + Sync>>
16
+ where
17
+ P: AsRef<std::path::Path>,
18
+ {
19
+ let file = std::fs::File::open(path)?;
20
+ let reader = std::io::BufReader::new(file);
21
+ let parsed = serde_yml::from_reader(reader)?;
22
+ Ok(parsed)
23
+ }
24
+
25
+ #[cfg(all(feature = "pyo3", feature = "serde"))]
26
+ #[pyfunction(name = "load_yaml_{{ root_struct_fn_snake }}")]
27
+ fn load_yaml_{{ root_struct_fn_snake }}_py(path: &str) -> PyResult<generated::{{ root_struct_name }}> {
28
+ load_yaml_{{ root_struct_fn_snake }}(path)
29
+ .map_err(|err| PyErr::new::<pyo3::exceptions::PyIOError, _>(err.to_string()))
30
+ }
31
+ {% endif %}
32
+
33
+ {% if pyo3 %}
34
+ #[cfg(feature = "pyo3")]
35
+ use pyo3::prelude::*;
36
+ #[cfg(all(feature = "pyo3", feature = "serde"))]
37
+ use pyo3::wrap_pyfunction;
38
+
39
+ #[cfg(feature = "pyo3")]
40
+ #[pymodule]
41
+ #[pyo3(name="{{ module_name }}")]
42
+ fn {{ module_name }}(m: &Bound<'_, PyModule>) -> PyResult<()> {
43
+ generated::register_pymodule(m)?;
44
+ {% if root_struct_name %}
45
+ #[cfg(all(feature = "serde", feature = "pyo3"))]
46
+ {
47
+ m.add_function(wrap_pyfunction!(load_yaml_{{ root_struct_fn_snake }}_py, m)?)?;
48
+ }
49
+ {% endif %}
50
+ Ok(())
51
+ }
52
+ {% endif %}
@@ -0,0 +1,9 @@
1
+ #![allow(non_camel_case_types)]
2
+
3
+ use crate::*;
4
+ use crate::poly_containers::*;
5
+
6
+
7
+ {% for t in traits %}
8
+ {{ t }}
9
+ {% endfor %}