#[derive({{ derives }})]
{%- if serde_rename_all %}
#[serde(rename_all = "{{ serde_rename_all }}")]
{%- endif %}
{%- for attr in enum_attrs %}
#[{{ attr }}]
{%- endfor %}
pub enum {{ enum_name }} {
{%- for variant in variants %}
{%- if variant.has_pyo3_rename %}
#[pyo3(name = "{{ variant.pyo3_name }}")]
{%- endif %}
{%- if variant.is_default %}
#[default]
{%- endif %}
{%- if variant.serde_rename %}
#[serde(rename = "{{ variant.serde_rename }}")]
{%- endif %}
{{ variant.name }} = {{ variant.idx }},
{%- endfor %}
}
{%- if is_pyo3 %}
#[pymethods]
impl {{ enum_name }} {
#[new]
fn __new__(value: pyo3::Bound<'_, pyo3::PyAny>) -> pyo3::PyResult<Self> {
use pyo3::prelude::*;
// Try to extract as string first
if let Ok(s) = value.extract::<&str>() {
let s_lower = s.to_lowercase();
match s_lower.as_str() {
{%- for variant in variants %}
"{{ variant.name | lower }}" => return Ok(Self::{{ variant.name }}),
{%- if variant.serde_rename and (variant.serde_rename | lower) != (variant.name | lower) %}
"{{ variant.serde_rename | lower }}" => return Ok(Self::{{ variant.name }}),
{%- endif %}
{%- endfor %}
_ => {}
}
}
// Try to extract as integer (by discriminant value)
if let Ok(n) = value.extract::<i32>() {
match n {
{%- for variant in variants %}
{{ variant.idx }} => return Ok(Self::{{ variant.name }}),
{%- endfor %}
_ => {}
}
}
let type_name = stringify!({{ enum_name }});
Err(pyo3::exceptions::PyValueError::new_err(format!(
"invalid value for {}: {:#?}. Expected variant name (str) or discriminant (int)",
type_name, value
)))
}
{{ string_methods }}
}
{%- endif %}