1
1
use crate :: err:: { self , PyResult } ;
2
- use crate :: { ffi, PyAny , PyTypeInfo , Python } ;
2
+ use crate :: ffi_ptr_ext:: FfiPtrExt ;
3
+ use crate :: instance:: Borrowed ;
4
+ use crate :: types:: any:: PyAnyMethods ;
5
+ use crate :: { ffi, Bound , PyAny , PyNativeType , PyTypeInfo , Python } ;
3
6
use std:: borrow:: Cow ;
4
7
#[ cfg( not( any( Py_LIMITED_API , PyPy ) ) ) ]
5
8
use std:: ffi:: CStr ;
@@ -20,7 +23,7 @@ impl PyType {
20
23
/// Retrieves the underlying FFI pointer associated with this Python object.
21
24
#[ inline]
22
25
pub fn as_type_ptr ( & self ) -> * mut ffi:: PyTypeObject {
23
- self . as_ptr ( ) as * mut ffi :: PyTypeObject
26
+ self . as_borrowed ( ) . as_type_ptr ( )
24
27
}
25
28
26
29
/// Retrieves the `PyType` instance for the given FFI pointer.
@@ -35,14 +38,81 @@ impl PyType {
35
38
36
39
/// Gets the [qualified name](https://docs.python.org/3/glossary.html#term-qualified-name) of the `PyType`.
37
40
pub fn qualname ( & self ) -> PyResult < String > {
41
+ self . as_borrowed ( ) . qualname ( )
42
+ }
43
+
44
+ /// Gets the full name, which includes the module, of the `PyType`.
45
+ pub fn name ( & self ) -> PyResult < Cow < ' _ , str > > {
46
+ self . as_borrowed ( ) . name ( )
47
+ }
48
+
49
+ /// Checks whether `self` is a subclass of `other`.
50
+ ///
51
+ /// Equivalent to the Python expression `issubclass(self, other)`.
52
+ pub fn is_subclass ( & self , other : & PyAny ) -> PyResult < bool > {
53
+ self . as_borrowed ( ) . is_subclass ( & other. as_borrowed ( ) )
54
+ }
55
+
56
+ /// Checks whether `self` is a subclass of type `T`.
57
+ ///
58
+ /// Equivalent to the Python expression `issubclass(self, T)`, if the type
59
+ /// `T` is known at compile time.
60
+ pub fn is_subclass_of < T > ( & self ) -> PyResult < bool >
61
+ where
62
+ T : PyTypeInfo ,
63
+ {
64
+ self . as_borrowed ( ) . is_subclass_of :: < T > ( )
65
+ }
66
+ }
67
+
68
+ /// Implementation of functionality for [`PyType`].
69
+ ///
70
+ /// These methods are defined for the `Bound<'py, PyType>` smart pointer, so to use method call
71
+ /// syntax these methods are separated into a trait, because stable Rust does not yet support
72
+ /// `arbitrary_self_types`.
73
+ #[ doc( alias = "PyType" ) ]
74
+ pub trait PyTypeMethods < ' py > {
75
+ /// Retrieves the underlying FFI pointer associated with this Python object.
76
+ fn as_type_ptr ( & self ) -> * mut ffi:: PyTypeObject ;
77
+
78
+ /// Gets the full name, which includes the module, of the `PyType`.
79
+ fn name ( & self ) -> PyResult < Cow < ' _ , str > > ;
80
+
81
+ /// Gets the [qualified name](https://docs.python.org/3/glossary.html#term-qualified-name) of the `PyType`.
82
+ fn qualname ( & self ) -> PyResult < String > ;
83
+
84
+ /// Checks whether `self` is a subclass of `other`.
85
+ ///
86
+ /// Equivalent to the Python expression `issubclass(self, other)`.
87
+ fn is_subclass ( & self , other : & Bound < ' _ , PyAny > ) -> PyResult < bool > ;
88
+
89
+ /// Checks whether `self` is a subclass of type `T`.
90
+ ///
91
+ /// Equivalent to the Python expression `issubclass(self, T)`, if the type
92
+ /// `T` is known at compile time.
93
+ fn is_subclass_of < T > ( & self ) -> PyResult < bool >
94
+ where
95
+ T : PyTypeInfo ;
96
+ }
97
+
98
+ impl < ' py > PyTypeMethods < ' py > for Bound < ' py , PyType > {
99
+ /// Retrieves the underlying FFI pointer associated with this Python object.
100
+ #[ inline]
101
+ fn as_type_ptr ( & self ) -> * mut ffi:: PyTypeObject {
102
+ self . as_ptr ( ) as * mut ffi:: PyTypeObject
103
+ }
104
+
105
+ /// Gets the name of the `PyType`.
106
+ fn name ( & self ) -> PyResult < Cow < ' _ , str > > {
107
+ Borrowed :: from ( self ) . name ( )
108
+ }
109
+
110
+ fn qualname ( & self ) -> PyResult < String > {
38
111
#[ cfg( any( Py_LIMITED_API , PyPy , not( Py_3_11 ) ) ) ]
39
112
let name = self . getattr ( intern ! ( self . py( ) , "__qualname__" ) ) ?. extract ( ) ;
40
113
41
114
#[ cfg( not( any( Py_LIMITED_API , PyPy , not( Py_3_11 ) ) ) ) ]
42
115
let name = {
43
- use crate :: ffi_ptr_ext:: FfiPtrExt ;
44
- use crate :: types:: any:: PyAnyMethods ;
45
-
46
116
let obj = unsafe {
47
117
ffi:: PyType_GetQualName ( self . as_type_ptr ( ) ) . assume_owned_or_err ( self . py ( ) ) ?
48
118
} ;
@@ -53,8 +123,29 @@ impl PyType {
53
123
name
54
124
}
55
125
56
- /// Gets the full name, which includes the module, of the `PyType`.
57
- pub fn name ( & self ) -> PyResult < Cow < ' _ , str > > {
126
+ /// Checks whether `self` is a subclass of `other`.
127
+ ///
128
+ /// Equivalent to the Python expression `issubclass(self, other)`.
129
+ fn is_subclass ( & self , other : & Bound < ' _ , PyAny > ) -> PyResult < bool > {
130
+ let result = unsafe { ffi:: PyObject_IsSubclass ( self . as_ptr ( ) , other. as_ptr ( ) ) } ;
131
+ err:: error_on_minusone ( self . py ( ) , result) ?;
132
+ Ok ( result == 1 )
133
+ }
134
+
135
+ /// Checks whether `self` is a subclass of type `T`.
136
+ ///
137
+ /// Equivalent to the Python expression `issubclass(self, T)`, if the type
138
+ /// `T` is known at compile time.
139
+ fn is_subclass_of < T > ( & self ) -> PyResult < bool >
140
+ where
141
+ T : PyTypeInfo ,
142
+ {
143
+ self . is_subclass ( & T :: type_object ( self . py ( ) ) . as_borrowed ( ) )
144
+ }
145
+ }
146
+
147
+ impl < ' a > Borrowed < ' a , ' _ , PyType > {
148
+ fn name ( self ) -> PyResult < Cow < ' a , str > > {
58
149
#[ cfg( not( any( Py_LIMITED_API , PyPy ) ) ) ]
59
150
{
60
151
let ptr = self . as_type_ptr ( ) ;
@@ -78,34 +169,12 @@ impl PyType {
78
169
79
170
#[ cfg( Py_3_11 ) ]
80
171
let name = {
81
- use crate :: ffi_ptr_ext:: FfiPtrExt ;
82
-
83
172
unsafe { ffi:: PyType_GetName ( self . as_type_ptr ( ) ) . assume_owned_or_err ( self . py ( ) ) ? }
84
173
} ;
85
174
86
175
Ok ( Cow :: Owned ( format ! ( "{}.{}" , module, name) ) )
87
176
}
88
177
}
89
-
90
- /// Checks whether `self` is a subclass of `other`.
91
- ///
92
- /// Equivalent to the Python expression `issubclass(self, other)`.
93
- pub fn is_subclass ( & self , other : & PyAny ) -> PyResult < bool > {
94
- let result = unsafe { ffi:: PyObject_IsSubclass ( self . as_ptr ( ) , other. as_ptr ( ) ) } ;
95
- err:: error_on_minusone ( self . py ( ) , result) ?;
96
- Ok ( result == 1 )
97
- }
98
-
99
- /// Checks whether `self` is a subclass of type `T`.
100
- ///
101
- /// Equivalent to the Python expression `issubclass(self, T)`, if the type
102
- /// `T` is known at compile time.
103
- pub fn is_subclass_of < T > ( & self ) -> PyResult < bool >
104
- where
105
- T : PyTypeInfo ,
106
- {
107
- self . is_subclass ( T :: type_object ( self . py ( ) ) )
108
- }
109
178
}
110
179
111
180
#[ cfg( test) ]
0 commit comments