forked from PyO3/pyo3
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgenericalias.rs
71 lines (63 loc) · 2.27 KB
/
genericalias.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use crate::err::PyResult;
use crate::ffi_ptr_ext::FfiPtrExt;
use crate::{ffi, types::any::PyAnyMethods, Bound, PyAny, Python};
/// Represents a Python [`types.GenericAlias`](https://docs.python.org/3/library/types.html#types.GenericAlias) object.
///
/// Values of this type are accessed via PyO3's smart pointers, e.g. as
/// [`Py<PyGenericAlias>`][crate::Py] or [`Bound<'py, PyGenericAlias>`][Bound].
///
/// This type is particularly convenient for users implementing
/// [`__class_getitem__`](https://docs.python.org/3/reference/datamodel.html#object.__class_getitem__)
/// for PyO3 classes to allow runtime parameterization.
#[repr(transparent)]
pub struct PyGenericAlias(PyAny);
pyobject_native_type!(
PyGenericAlias,
ffi::PyDictObject,
pyobject_native_static_type_object!(ffi::Py_GenericAliasType)
);
impl PyGenericAlias {
/// Creates a new Python GenericAlias object.
///
/// origin should be a non-parameterized generic class.
/// args should be a tuple (possibly of length 1) of types which parameterize origin.
pub fn new<'py>(
py: Python<'py>,
origin: &Bound<'py, PyAny>,
args: &Bound<'py, PyAny>,
) -> PyResult<Bound<'py, PyGenericAlias>> {
unsafe {
Ok(ffi::Py_GenericAlias(origin.as_ptr(), args.as_ptr())
.assume_owned_or_err(py)?
.downcast_into_unchecked())
}
}
}
#[cfg(test)]
mod tests {
use crate::instance::BoundObject;
use crate::types::any::PyAnyMethods;
use crate::{ffi, Python};
use super::PyGenericAlias;
// Tests that PyGenericAlias::new is identical to types.GenericAlias
// created from Python.
#[test]
fn equivalency_test() {
Python::with_gil(|py| {
let list_int = py
.eval(ffi::c_str!("list[int]"), None, None)
.unwrap()
.into_bound();
let cls = py
.eval(ffi::c_str!("list"), None, None)
.unwrap()
.into_bound();
let key = py
.eval(ffi::c_str!("(int,)"), None, None)
.unwrap()
.into_bound();
let generic_alias = PyGenericAlias::new(py, &cls, &key).unwrap();
assert!(generic_alias.eq(list_int).unwrap());
})
}
}