use crate::err::PyResult;
use crate::ffi_ptr_ext::FfiPtrExt;
use crate::py_result_ext::PyResultExt;
use crate::{ffi, Bound, PyAny, Python};
#[cfg(RustPython)]
use crate::{
sync::PyOnceLock,
types::{PyType, PyTypeMethods},
Py,
};
#[repr(transparent)]
pub struct PyGenericAlias(PyAny);
#[cfg(not(RustPython))]
pyobject_native_type!(
PyGenericAlias,
ffi::PyDictObject,
pyobject_native_static_type_object!(ffi::Py_GenericAliasType),
"builtins",
"GenericAlias"
);
#[cfg(RustPython)]
pyobject_native_type!(
PyGenericAlias,
ffi::PyDictObject,
|py| {
static TYPE: PyOnceLock<Py<PyType>> = PyOnceLock::new();
TYPE.import(py, "types", "GenericAlias")
.unwrap()
.as_type_ptr()
},
"builtins",
"GenericAlias"
);
impl PyGenericAlias {
pub fn new<'py>(
py: Python<'py>,
origin: &Bound<'py, PyAny>,
args: &Bound<'py, PyAny>,
) -> PyResult<Bound<'py, PyGenericAlias>> {
unsafe {
ffi::Py_GenericAlias(origin.as_ptr(), args.as_ptr())
.assume_owned_or_err(py)
.cast_into_unchecked()
}
}
}
#[cfg(test)]
mod tests {
use crate::instance::BoundObject;
use crate::types::any::PyAnyMethods;
use crate::Python;
use super::PyGenericAlias;
#[test]
fn equivalency_test() {
Python::attach(|py| {
let list_int = py.eval(c"list[int]", None, None).unwrap().into_bound();
let cls = py.eval(c"list", None, None).unwrap().into_bound();
let key = py.eval(c"(int,)", None, None).unwrap().into_bound();
let generic_alias = PyGenericAlias::new(py, &cls, &key).unwrap();
assert!(generic_alias.eq(list_int).unwrap());
})
}
}