pyo3/types/
genericalias.rs1use crate::err::PyResult;
2use crate::ffi_ptr_ext::FfiPtrExt;
3use crate::py_result_ext::PyResultExt;
4use crate::{ffi, Bound, PyAny, Python};
5#[cfg(RustPython)]
6use crate::{
7 sync::PyOnceLock,
8 types::{PyType, PyTypeMethods},
9 Py,
10};
11
12#[repr(transparent)]
21pub struct PyGenericAlias(PyAny);
22
23#[cfg(not(RustPython))]
24pyobject_native_type!(
25 PyGenericAlias,
26 ffi::PyDictObject,
27 pyobject_native_static_type_object!(ffi::Py_GenericAliasType),
28 "builtins",
29 "GenericAlias"
30);
31
32#[cfg(RustPython)]
33pyobject_native_type!(
34 PyGenericAlias,
35 ffi::PyDictObject,
36 |py| {
37 static TYPE: PyOnceLock<Py<PyType>> = PyOnceLock::new();
38 TYPE.import(py, "types", "GenericAlias")
39 .unwrap()
40 .as_type_ptr()
41 },
42 "builtins",
43 "GenericAlias"
44);
45
46impl PyGenericAlias {
47 pub fn new<'py>(
52 py: Python<'py>,
53 origin: &Bound<'py, PyAny>,
54 args: &Bound<'py, PyAny>,
55 ) -> PyResult<Bound<'py, PyGenericAlias>> {
56 unsafe {
57 ffi::Py_GenericAlias(origin.as_ptr(), args.as_ptr())
58 .assume_owned_or_err(py)
59 .cast_into_unchecked()
60 }
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use crate::instance::BoundObject;
67 use crate::types::any::PyAnyMethods;
68 use crate::Python;
69
70 use super::PyGenericAlias;
71
72 #[test]
75 fn equivalency_test() {
76 Python::attach(|py| {
77 let list_int = py.eval(c"list[int]", None, None).unwrap().into_bound();
78
79 let cls = py.eval(c"list", None, None).unwrap().into_bound();
80 let key = py.eval(c"(int,)", None, None).unwrap().into_bound();
81 let generic_alias = PyGenericAlias::new(py, &cls, &key).unwrap();
82
83 assert!(generic_alias.eq(list_int).unwrap());
84 })
85 }
86}