Skip to content

Commit e2ebebd

Browse files
committed
port Python::get_type to Bound API
1 parent f04ad56 commit e2ebebd

33 files changed

+175
-156
lines changed

guide/src/class.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ impl SubSubClass {
401401
# pyo3::py_run!(py, subsub, "assert subsub.method3() == 3000");
402402
# let subsub = SubSubClass::factory_method(py, 2).unwrap();
403403
# let subsubsub = SubSubClass::factory_method(py, 3).unwrap();
404-
# let cls = py.get_type::<SubSubClass>();
404+
# let cls = py.get_type_bound::<SubSubClass>();
405405
# pyo3::py_run!(py, subsub cls, "assert not isinstance(subsub, cls)");
406406
# pyo3::py_run!(py, subsubsub cls, "assert isinstance(subsubsub, cls)");
407407
# });
@@ -497,7 +497,7 @@ impl MyDict {
497497
// some custom methods that use `private` here...
498498
}
499499
# Python::with_gil(|py| {
500-
# let cls = py.get_type::<MyDict>();
500+
# let cls = py.get_type_bound::<MyDict>();
501501
# pyo3::py_run!(py, cls, "cls(a=1, b=2)")
502502
# });
503503
# }
@@ -767,7 +767,7 @@ impl MyClass {
767767
}
768768

769769
Python::with_gil(|py| {
770-
let my_class = py.get_type::<MyClass>();
770+
let my_class = py.get_type_bound::<MyClass>();
771771
pyo3::py_run!(py, my_class, "assert my_class.my_attribute == 'hello'")
772772
});
773773
```
@@ -1026,7 +1026,7 @@ enum MyEnum {
10261026
Python::with_gil(|py| {
10271027
let x = Py::new(py, MyEnum::Variant).unwrap();
10281028
let y = Py::new(py, MyEnum::OtherVariant).unwrap();
1029-
let cls = py.get_type::<MyEnum>();
1029+
let cls = py.get_type_bound::<MyEnum>();
10301030
pyo3::py_run!(py, x y cls, r#"
10311031
assert x == cls.Variant
10321032
assert y == cls.OtherVariant
@@ -1046,7 +1046,7 @@ enum MyEnum {
10461046
}
10471047

10481048
Python::with_gil(|py| {
1049-
let cls = py.get_type::<MyEnum>();
1049+
let cls = py.get_type_bound::<MyEnum>();
10501050
let x = MyEnum::Variant as i32; // The exact value is assigned by the compiler.
10511051
pyo3::py_run!(py, cls x, r#"
10521052
assert int(cls.Variant) == x
@@ -1068,7 +1068,7 @@ enum MyEnum{
10681068
}
10691069

10701070
Python::with_gil(|py| {
1071-
let cls = py.get_type::<MyEnum>();
1071+
let cls = py.get_type_bound::<MyEnum>();
10721072
let x = Py::new(py, MyEnum::Variant).unwrap();
10731073
pyo3::py_run!(py, cls x, r#"
10741074
assert repr(x) == 'MyEnum.Variant'
@@ -1094,7 +1094,7 @@ impl MyEnum {
10941094
}
10951095

10961096
Python::with_gil(|py| {
1097-
let cls = py.get_type::<MyEnum>();
1097+
let cls = py.get_type_bound::<MyEnum>();
10981098
pyo3::py_run!(py, cls, "assert repr(cls.Answer) == '42'")
10991099
})
11001100
```
@@ -1111,7 +1111,7 @@ enum MyEnum {
11111111

11121112
Python::with_gil(|py| {
11131113
let x = Py::new(py, MyEnum::Variant).unwrap();
1114-
let cls = py.get_type::<MyEnum>();
1114+
let cls = py.get_type_bound::<MyEnum>();
11151115
pyo3::py_run!(py, x cls, r#"
11161116
assert repr(x) == 'RenamedEnum.UPPERCASE'
11171117
assert x == cls.UPPERCASE
@@ -1165,7 +1165,7 @@ enum Shape {
11651165
Python::with_gil(|py| {
11661166
let circle = Shape::Circle { radius: 10.0 }.into_py(py);
11671167
let square = Shape::RegularPolygon { side_count: 4, radius: 10.0 }.into_py(py);
1168-
let cls = py.get_type::<Shape>();
1168+
let cls = py.get_type_bound::<Shape>();
11691169
pyo3::py_run!(py, circle square cls, r#"
11701170
assert isinstance(circle, cls)
11711171
assert isinstance(circle, cls.Circle)
@@ -1204,7 +1204,7 @@ enum MyEnum {
12041204

12051205
Python::with_gil(|py| {
12061206
let x = Py::new(py, MyEnum::Variant { i: 42 }).unwrap();
1207-
let cls = py.get_type::<MyEnum>();
1207+
let cls = py.get_type_bound::<MyEnum>();
12081208
pyo3::py_run!(py, x cls, r#"
12091209
assert isinstance(x, cls)
12101210
assert not isinstance(x, cls.Variant)
@@ -1308,7 +1308,7 @@ impl pyo3::impl_::pyclass::PyClassImpl for MyClass {
13081308
}
13091309

13101310
# Python::with_gil(|py| {
1311-
# let cls = py.get_type::<MyClass>();
1311+
# let cls = py.get_type_bound::<MyClass>();
13121312
# pyo3::py_run!(py, cls, "assert cls.__name__ == 'MyClass'")
13131313
# });
13141314
# }

guide/src/exception.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use pyo3::exceptions::PyException;
2424
create_exception!(mymodule, CustomError, PyException);
2525

2626
Python::with_gil(|py| {
27-
let ctx = [("CustomError", py.get_type::<CustomError>())].into_py_dict_bound(py);
27+
let ctx = [("CustomError", py.get_type_bound::<CustomError>())].into_py_dict_bound(py);
2828
pyo3::py_run!(
2929
py,
3030
*ctx,
@@ -46,7 +46,7 @@ pyo3::create_exception!(mymodule, CustomError, PyException);
4646
#[pymodule]
4747
fn mymodule(py: Python<'_>, m: &PyModule) -> PyResult<()> {
4848
// ... other elements added to module ...
49-
m.add("CustomError", py.get_type::<CustomError>())?;
49+
m.add("CustomError", py.get_type_bound::<CustomError>())?;
5050

5151
Ok(())
5252
}

pyo3-macros-backend/src/pyclass.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1086,7 +1086,7 @@ pub fn gen_complex_enum_variant_attr(
10861086
let associated_method = quote! {
10871087
fn #wrapper_ident(py: _pyo3::Python<'_>) -> _pyo3::PyResult<_pyo3::PyObject> {
10881088
#deprecations
1089-
::std::result::Result::Ok(py.get_type::<#variant_cls>().into())
1089+
::std::result::Result::Ok(py.get_type_bound::<#variant_cls>().into_any().unbind())
10901090
}
10911091
};
10921092

src/conversions/chrono.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,7 @@ use crate::types::{
5252
};
5353
#[cfg(Py_LIMITED_API)]
5454
use crate::{intern, DowncastError};
55-
use crate::{
56-
Bound, FromPyObject, IntoPy, PyAny, PyErr, PyNativeType, PyObject, PyResult, Python, ToPyObject,
57-
};
55+
use crate::{Bound, FromPyObject, IntoPy, PyAny, PyErr, PyObject, PyResult, Python, ToPyObject};
5856
use chrono::offset::{FixedOffset, Utc};
5957
use chrono::{
6058
DateTime, Datelike, Duration, NaiveDate, NaiveDateTime, NaiveTime, Offset, TimeZone, Timelike,
@@ -461,7 +459,7 @@ fn warn_truncated_leap_second(obj: &Bound<'_, PyAny>) {
461459
let py = obj.py();
462460
if let Err(e) = PyErr::warn_bound(
463461
py,
464-
&py.get_type::<PyUserWarning>().as_borrowed(),
462+
&py.get_type_bound::<PyUserWarning>(),
465463
"ignored leap-second, `datetime` does not support leap-seconds",
466464
0,
467465
) {

src/conversions/num_bigint.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,8 @@ macro_rules! bigint_conversion {
9191
} else {
9292
None
9393
};
94-
py.get_type::<PyLong>()
95-
.call_method(
96-
"from_bytes",
97-
(bytes_obj, "little"),
98-
kwargs.as_ref().map(crate::Bound::as_gil_ref),
99-
)
94+
py.get_type_bound::<PyLong>()
95+
.call_method("from_bytes", (bytes_obj, "little"), kwargs.as_ref())
10096
.expect("int.from_bytes() failed during to_object()") // FIXME: #1813 or similar
10197
.into()
10298
}

src/err/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,7 @@ impl PyErr {
724724
/// # use pyo3::prelude::*;
725725
/// # fn main() -> PyResult<()> {
726726
/// Python::with_gil(|py| {
727-
/// let user_warning = py.get_type::<pyo3::exceptions::PyUserWarning>().as_borrowed();
727+
/// let user_warning = py.get_type_bound::<pyo3::exceptions::PyUserWarning>();
728728
/// PyErr::warn_bound(py, &user_warning, "I am warning you", 0)?;
729729
/// Ok(())
730730
/// })
@@ -1080,7 +1080,7 @@ impl_signed_integer!(isize);
10801080
mod tests {
10811081
use super::PyErrState;
10821082
use crate::exceptions::{self, PyTypeError, PyValueError};
1083-
use crate::{PyErr, PyNativeType, PyTypeInfo, Python};
1083+
use crate::{PyErr, PyTypeInfo, Python};
10841084

10851085
#[test]
10861086
fn no_error() {
@@ -1278,7 +1278,7 @@ mod tests {
12781278
// GIL locked should prevent effects to be visible to other testing
12791279
// threads.
12801280
Python::with_gil(|py| {
1281-
let cls = py.get_type::<exceptions::PyUserWarning>().as_borrowed();
1281+
let cls = py.get_type_bound::<exceptions::PyUserWarning>();
12821282

12831283
// Reset warning filter to default state
12841284
let warnings = py.import_bound("warnings").unwrap();
@@ -1293,14 +1293,14 @@ mod tests {
12931293

12941294
// Test with raising
12951295
warnings
1296-
.call_method1("simplefilter", ("error", cls))
1296+
.call_method1("simplefilter", ("error", &cls))
12971297
.unwrap();
12981298
PyErr::warn_bound(py, &cls, "I am warning you", 0).unwrap_err();
12991299

13001300
// Test with error for an explicit module
13011301
warnings.call_method0("resetwarnings").unwrap();
13021302
warnings
1303-
.call_method1("filterwarnings", ("error", "", cls, "pyo3test"))
1303+
.call_method1("filterwarnings", ("error", "", &cls, "pyo3test"))
13041304
.unwrap();
13051305

13061306
// This has the wrong module and will not raise, just be emitted

src/exceptions.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ macro_rules! impl_exception_boilerplate {
7272
/// import_exception!(socket, gaierror);
7373
///
7474
/// Python::with_gil(|py| {
75-
/// let ctx = [("gaierror", py.get_type::<gaierror>())].into_py_dict_bound(py);
75+
/// let ctx = [("gaierror", py.get_type_bound::<gaierror>())].into_py_dict_bound(py);
7676
/// pyo3::py_run!(py, *ctx, "import socket; assert gaierror is socket.gaierror");
7777
/// });
7878
///
@@ -160,15 +160,15 @@ macro_rules! import_exception {
160160
///
161161
/// #[pymodule]
162162
/// fn my_module(py: Python<'_>, m: &PyModule) -> PyResult<()> {
163-
/// m.add("MyError", py.get_type::<MyError>())?;
163+
/// m.add("MyError", py.get_type_bound::<MyError>())?;
164164
/// m.add_function(wrap_pyfunction!(raise_myerror, py)?)?;
165165
/// Ok(())
166166
/// }
167167
/// # fn main() -> PyResult<()> {
168168
/// # Python::with_gil(|py| -> PyResult<()> {
169169
/// # let fun = wrap_pyfunction!(raise_myerror, py)?;
170170
/// # let locals = pyo3::types::PyDict::new_bound(py);
171-
/// # locals.set_item("MyError", py.get_type::<MyError>())?;
171+
/// # locals.set_item("MyError", py.get_type_bound::<MyError>())?;
172172
/// # locals.set_item("raise_myerror", fun)?;
173173
/// #
174174
/// # py.run_bound(
@@ -241,7 +241,6 @@ macro_rules! create_exception_type_object {
241241
impl $name {
242242
fn type_object_raw(py: $crate::Python<'_>) -> *mut $crate::ffi::PyTypeObject {
243243
use $crate::sync::GILOnceCell;
244-
use $crate::PyNativeType;
245244
static TYPE_OBJECT: GILOnceCell<$crate::Py<$crate::types::PyType>> =
246245
GILOnceCell::new();
247246

@@ -251,7 +250,7 @@ macro_rules! create_exception_type_object {
251250
py,
252251
concat!(stringify!($module), ".", stringify!($name)),
253252
$doc,
254-
::std::option::Option::Some(&py.get_type::<$base>().as_borrowed()),
253+
::std::option::Option::Some(&py.get_type_bound::<$base>()),
255254
::std::option::Option::None,
256255
).expect("Failed to initialize new exception type.")
257256
).as_ptr() as *mut $crate::ffi::PyTypeObject
@@ -904,7 +903,7 @@ mod tests {
904903
create_exception!(mymodule, CustomError, PyException);
905904

906905
Python::with_gil(|py| {
907-
let error_type = py.get_type::<CustomError>();
906+
let error_type = py.get_type_bound::<CustomError>();
908907
let ctx = [("CustomError", error_type)].into_py_dict_bound(py);
909908
let type_description: String = py
910909
.eval_bound("str(CustomError)", None, Some(&ctx))
@@ -927,7 +926,7 @@ mod tests {
927926
fn custom_exception_dotted_module() {
928927
create_exception!(mymodule.exceptions, CustomError, PyException);
929928
Python::with_gil(|py| {
930-
let error_type = py.get_type::<CustomError>();
929+
let error_type = py.get_type_bound::<CustomError>();
931930
let ctx = [("CustomError", error_type)].into_py_dict_bound(py);
932931
let type_description: String = py
933932
.eval_bound("str(CustomError)", None, Some(&ctx))
@@ -946,7 +945,7 @@ mod tests {
946945
create_exception!(mymodule, CustomError, PyException, "Some docs");
947946

948947
Python::with_gil(|py| {
949-
let error_type = py.get_type::<CustomError>();
948+
let error_type = py.get_type_bound::<CustomError>();
950949
let ctx = [("CustomError", error_type)].into_py_dict_bound(py);
951950
let type_description: String = py
952951
.eval_bound("str(CustomError)", None, Some(&ctx))
@@ -979,7 +978,7 @@ mod tests {
979978
);
980979

981980
Python::with_gil(|py| {
982-
let error_type = py.get_type::<CustomError>();
981+
let error_type = py.get_type_bound::<CustomError>();
983982
let ctx = [("CustomError", error_type)].into_py_dict_bound(py);
984983
let type_description: String = py
985984
.eval_bound("str(CustomError)", None, Some(&ctx))

src/impl_/extract_argument.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,10 @@ pub fn from_py_with_with_default<'a, 'py, T>(
166166
#[cold]
167167
pub fn argument_extraction_error(py: Python<'_>, arg_name: &str, error: PyErr) -> PyErr {
168168
use crate::types::any::PyAnyMethods;
169-
if error.get_type_bound(py).is(py.get_type::<PyTypeError>()) {
169+
if error
170+
.get_type_bound(py)
171+
.is(&py.get_type_bound::<PyTypeError>())
172+
{
170173
let remapped_error = PyTypeError::new_err(format!(
171174
"argument '{}': {}",
172175
arg_name,

src/macros.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373
/// }
7474
///
7575
/// Python::with_gil(|py| {
76-
/// let locals = [("C", py.get_type::<MyClass>())].into_py_dict_bound(py);
76+
/// let locals = [("C", py.get_type_bound::<MyClass>())].into_py_dict_bound(py);
7777
/// pyo3::py_run!(py, *locals, "c = C()");
7878
/// });
7979
/// ```

src/marker.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -728,12 +728,28 @@ impl<'py> Python<'py> {
728728
}
729729

730730
/// Gets the Python type object for type `T`.
731+
#[cfg_attr(
732+
not(feature = "gil-refs"),
733+
deprecated(
734+
since = "0.21.0",
735+
note = "`Python::get_type` will be replaced by `Python::get_type_bound` in a future PyO3 version"
736+
)
737+
)]
731738
#[inline]
732739
pub fn get_type<T>(self) -> &'py PyType
733740
where
734741
T: PyTypeInfo,
735742
{
736-
T::type_object_bound(self).into_gil_ref()
743+
self.get_type_bound::<T>().into_gil_ref()
744+
}
745+
746+
/// Gets the Python type object for type `T`.
747+
#[inline]
748+
pub fn get_type_bound<T>(self) -> Bound<'py, PyType>
749+
where
750+
T: PyTypeInfo,
751+
{
752+
T::type_object_bound(self)
737753
}
738754

739755
/// Deprecated form of [`Python::import_bound`]

src/pyclass_init.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ impl<T: PyTypeInfo> PyObjectInit<T> for PyNativeTypeInitializer<T> {
122122
/// }
123123
/// }
124124
/// Python::with_gil(|py| {
125-
/// let typeobj = py.get_type::<SubSubClass>();
125+
/// let typeobj = py.get_type_bound::<SubSubClass>();
126126
/// let sub_sub_class = typeobj.call((), None).unwrap();
127127
/// py_run!(
128128
/// py,

src/tests/common.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ mod inner {
4242
($py:expr, *$dict:expr, $code:expr, $err:ident) => {{
4343
let res = $py.run_bound($code, None, Some(&$dict.as_borrowed()));
4444
let err = res.expect_err(&format!("Did not raise {}", stringify!($err)));
45-
if !err.matches($py, $py.get_type::<pyo3::exceptions::$err>()) {
45+
if !err.matches($py, $py.get_type_bound::<pyo3::exceptions::$err>()) {
4646
panic!("Expected {} but got {:?}", stringify!($err), err)
4747
}
4848
err

src/types/typeobject.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -217,22 +217,26 @@ impl<'a> Borrowed<'a, '_, PyType> {
217217

218218
#[cfg(test)]
219219
mod tests {
220+
use crate::types::typeobject::PyTypeMethods;
220221
use crate::types::{PyBool, PyLong};
221222
use crate::Python;
222223

223224
#[test]
224225
fn test_type_is_subclass() {
225226
Python::with_gil(|py| {
226-
let bool_type = py.get_type::<PyBool>();
227-
let long_type = py.get_type::<PyLong>();
228-
assert!(bool_type.is_subclass(long_type).unwrap());
227+
let bool_type = py.get_type_bound::<PyBool>();
228+
let long_type = py.get_type_bound::<PyLong>();
229+
assert!(bool_type.is_subclass(&long_type).unwrap());
229230
});
230231
}
231232

232233
#[test]
233234
fn test_type_is_subclass_of() {
234235
Python::with_gil(|py| {
235-
assert!(py.get_type::<PyBool>().is_subclass_of::<PyLong>().unwrap());
236+
assert!(py
237+
.get_type_bound::<PyBool>()
238+
.is_subclass_of::<PyLong>()
239+
.unwrap());
236240
});
237241
}
238242
}

0 commit comments

Comments
 (0)