#[derive(Clone)]
#[pyclass(frozen)]
pub struct {{ name }} {
pub(crate) inner: {{ core_path }},
}
#[pymethods]
impl {{ name }} {
{%- if has_sanitized %}
{{ string_methods_content }}
{{ variant_accessors_content }}
{{ serde_tag_content }}
{%- else %}
#[new]
#[pyo3(signature = (value=None, **kwargs))]
fn new(
py: Python<'_>,
value: Option<&Bound<'_, pyo3::types::PyAny>>,
kwargs: Option<&Bound<'_, pyo3::types::PyDict>>,
) -> PyResult<Self> {
// Accept three call shapes:
// {{ name }}("variant_name") -> unit variant
// {{ name }}({"type": "variant", ...}) -> dict positional
// {{ name }}(type="variant", field=...) -> kwargs (idiomatic)
// Kwargs are assembled into a Python dict and re-serialized via json so
// serde_json can deserialize into the tagged enum.
let json_str: String = if let Some(v) = value {
if let Ok(s) = v.extract::<String>() {
serde_json::to_string(&s).map_err(|e| pyo3::exceptions::PyValueError::new_err(format!("Invalid {{ name }}: {e}")))?
} else {
let json_mod = py.import("json")?;
json_mod.call_method1("dumps", (v,))?.extract()?
}
} else if let Some(kw) = kwargs {
let json_mod = py.import("json")?;
json_mod.call_method1("dumps", (kw,))?.extract()?
} else {
return Err(pyo3::exceptions::PyTypeError::new_err(
"{{ name }}() requires a positional value or keyword arguments".to_string(),
));
};
let inner: {{ core_path }} = serde_json::from_str(&json_str)
.map_err(|e| pyo3::exceptions::PyValueError::new_err(format!("Invalid {{ name }}: {e}")))?;
Ok(Self { inner })
}
{{ string_methods_content }}
{{ variant_accessors_content }}
{{ serde_tag_content }}
{%- endif %}
{%- if factory_methods_content %}
{{ factory_methods_content }}
{%- endif %}
}
impl From<{{ name }}> for {{ core_path }} {
fn from(val: {{ name }}) -> Self { val.inner }
}
impl From<{{ core_path }}> for {{ name }} {
fn from(val: {{ core_path }}) -> Self { Self { inner: val } }
}
impl serde::Serialize for {{ name }} {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.inner.serialize(serializer)
}
}
impl Default for {{ name }} {
fn default() -> Self { Self { inner: Default::default() } }
}
impl<'de> serde::Deserialize<'de> for {{ name }} {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let inner = {{ core_path }}::deserialize(deserializer)?;
Ok(Self { inner })
}
}