linkml 1.9.4rc2__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.
- linkml/cli/main.py +5 -1
- linkml/converter/__init__.py +0 -0
- linkml/generators/__init__.py +2 -0
- linkml/generators/common/build.py +5 -20
- linkml/generators/common/template.py +289 -3
- linkml/generators/docgen.py +55 -10
- linkml/generators/erdiagramgen.py +9 -5
- linkml/generators/graphqlgen.py +32 -6
- linkml/generators/jsonldcontextgen.py +78 -12
- linkml/generators/jsonschemagen.py +29 -12
- linkml/generators/mermaidclassdiagramgen.py +21 -3
- linkml/generators/owlgen.py +13 -2
- linkml/generators/panderagen/dataframe_class.py +13 -0
- linkml/generators/panderagen/dataframe_field.py +50 -0
- linkml/generators/panderagen/linkml_pandera_validator.py +186 -0
- linkml/generators/panderagen/panderagen.py +22 -5
- linkml/generators/panderagen/panderagen_class_based/class.jinja2 +70 -13
- linkml/generators/panderagen/panderagen_class_based/custom_checks.jinja2 +27 -0
- linkml/generators/panderagen/panderagen_class_based/enums.jinja2 +3 -3
- linkml/generators/panderagen/panderagen_class_based/pandera.jinja2 +12 -2
- linkml/generators/panderagen/panderagen_class_based/slots.jinja2 +19 -17
- linkml/generators/panderagen/slot_generator_mixin.py +143 -16
- linkml/generators/panderagen/transforms/__init__.py +19 -0
- linkml/generators/panderagen/transforms/collection_dict_model_transform.py +62 -0
- linkml/generators/panderagen/transforms/list_dict_model_transform.py +66 -0
- linkml/generators/panderagen/transforms/model_transform.py +8 -0
- linkml/generators/panderagen/transforms/nested_struct_model_transform.py +27 -0
- linkml/generators/panderagen/transforms/simple_dict_model_transform.py +86 -0
- linkml/generators/plantumlgen.py +17 -11
- linkml/generators/pydanticgen/pydanticgen.py +53 -2
- linkml/generators/pydanticgen/template.py +45 -233
- linkml/generators/pydanticgen/templates/attribute.py.jinja +1 -0
- linkml/generators/pydanticgen/templates/base_model.py.jinja +16 -2
- linkml/generators/pydanticgen/templates/imports.py.jinja +1 -1
- linkml/generators/rdfgen.py +11 -2
- linkml/generators/rustgen/__init__.py +3 -0
- linkml/generators/rustgen/build.py +97 -0
- linkml/generators/rustgen/cli.py +83 -0
- linkml/generators/rustgen/rustgen.py +1186 -0
- linkml/generators/rustgen/template.py +910 -0
- linkml/generators/rustgen/templates/Cargo.toml.jinja +42 -0
- linkml/generators/rustgen/templates/anything.rs.jinja +149 -0
- linkml/generators/rustgen/templates/as_key_value.rs.jinja +86 -0
- linkml/generators/rustgen/templates/class_module.rs.jinja +8 -0
- linkml/generators/rustgen/templates/enum.rs.jinja +70 -0
- linkml/generators/rustgen/templates/file.rs.jinja +75 -0
- linkml/generators/rustgen/templates/import.rs.jinja +4 -0
- linkml/generators/rustgen/templates/imports.rs.jinja +8 -0
- linkml/generators/rustgen/templates/lib_shim.rs.jinja +52 -0
- linkml/generators/rustgen/templates/poly.rs.jinja +9 -0
- linkml/generators/rustgen/templates/poly_containers.rs.jinja +439 -0
- linkml/generators/rustgen/templates/poly_trait.rs.jinja +15 -0
- linkml/generators/rustgen/templates/poly_trait_impl.rs.jinja +5 -0
- linkml/generators/rustgen/templates/poly_trait_impl_orsubtype.rs.jinja +5 -0
- linkml/generators/rustgen/templates/poly_trait_property.rs.jinja +8 -0
- linkml/generators/rustgen/templates/poly_trait_property_impl.rs.jinja +134 -0
- linkml/generators/rustgen/templates/poly_trait_property_match.rs.jinja +10 -0
- linkml/generators/rustgen/templates/property.rs.jinja +28 -0
- linkml/generators/rustgen/templates/pyproject.toml.jinja +10 -0
- linkml/generators/rustgen/templates/serde_utils.rs.jinja +490 -0
- linkml/generators/rustgen/templates/slot_range_as_union.rs.jinja +64 -0
- linkml/generators/rustgen/templates/struct.rs.jinja +81 -0
- linkml/generators/rustgen/templates/struct_or_subtype_enum.rs.jinja +111 -0
- linkml/generators/rustgen/templates/stub_gen.rs.jinja +71 -0
- linkml/generators/rustgen/templates/stub_utils.rs.jinja +76 -0
- linkml/generators/rustgen/templates/typealias.rs.jinja +13 -0
- linkml/generators/sqltablegen.py +18 -16
- linkml/generators/yarrrmlgen.py +173 -0
- linkml/linter/config/datamodel/config.py +160 -293
- linkml/linter/config/datamodel/config.yaml +34 -26
- linkml/linter/config/default.yaml +4 -0
- linkml/linter/config/recommended.yaml +4 -0
- linkml/linter/linter.py +1 -2
- linkml/linter/rules.py +37 -0
- linkml/utils/schema_builder.py +2 -0
- linkml/utils/schemaloader.py +76 -3
- {linkml-1.9.4rc2.dist-info → linkml-1.9.5.dist-info}/METADATA +1 -1
- {linkml-1.9.4rc2.dist-info → linkml-1.9.5.dist-info}/RECORD +82 -40
- {linkml-1.9.4rc2.dist-info → linkml-1.9.5.dist-info}/entry_points.txt +2 -1
- linkml/generators/panderagen/panderagen_class_based/mixins.jinja2 +0 -26
- /linkml/{utils/converter.py → converter/cli.py} +0 -0
- {linkml-1.9.4rc2.dist-info → linkml-1.9.5.dist-info}/WHEEL +0 -0
- {linkml-1.9.4rc2.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,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,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 %}
|