1
1
use crate :: err:: PyResult ;
2
2
use crate :: ffi_ptr_ext:: FfiPtrExt ;
3
3
use crate :: py_result_ext:: PyResultExt ;
4
- use crate :: type_object :: PyTypeCheck ;
4
+ use crate :: sync :: PyOnceLock ;
5
5
use crate :: types:: any:: PyAny ;
6
- use crate :: { ffi , Borrowed , Bound , BoundObject , IntoPyObject , IntoPyObjectExt } ;
7
-
8
- use super :: PyWeakrefMethods ;
6
+ use crate :: types :: weakref :: PyWeakrefMethods ;
7
+ use crate :: types :: { PyAnyMethods , PyDict , PyType , PyTypeMethods } ;
8
+ use crate :: { ffi , Borrowed , Bound , BoundObject , IntoPyObject , IntoPyObjectExt , Py } ;
9
9
10
10
/// Represents any Python `weakref` Proxy type.
11
11
///
@@ -14,22 +14,31 @@ use super::PyWeakrefMethods;
14
14
#[ repr( transparent) ]
15
15
pub struct PyWeakrefProxy ( PyAny ) ;
16
16
17
- pyobject_native_type_named ! ( PyWeakrefProxy ) ;
17
+ pyobject_native_type_core ! (
18
+ PyWeakrefProxy ,
19
+ |py| {
20
+ static TYPE : PyOnceLock <Py <PyType >> = PyOnceLock :: new( ) ;
21
+ TYPE . get_or_try_init( py, || {
22
+ // Terrible way to generate a super class of both ProxyType and CallableProxyType
23
+ let globals = PyDict :: new( py) ;
24
+ globals. set_item( "abc" , py. import( "abc" ) ?) ?;
25
+ py. run( ffi:: c_str!( "class WeakrefProxy(abc.ABC):\n pass" ) , Some ( & globals) , None ) ?;
26
+ let cls = globals. get_item( "WeakrefProxy" ) ?. downcast_into:: <PyType >( ) ?;
27
+ let weakref = py. import( "weakref" ) ?;
28
+ for child_name in [ "ProxyType" , "CallableProxyType" ] {
29
+ cls. call_method1( "register" , ( weakref. getattr( child_name) ?, ) ) ?;
30
+ }
31
+ PyResult :: Ok ( cls. unbind( ) )
32
+ } ) . unwrap( ) . bind( py) . as_type_ptr( )
33
+ } ,
34
+ #module=Some ( "weakref" ) ,
35
+ #checkfunction=ffi:: PyWeakref_CheckProxy
36
+ ) ;
18
37
19
38
// TODO: We known the layout but this cannot be implemented, due to the lack of public typeobject pointers. And it is 2 distinct types
20
39
// #[cfg(not(Py_LIMITED_API))]
21
40
// pyobject_native_type_sized!(PyWeakrefProxy, ffi::PyWeakReference);
22
41
23
- impl PyTypeCheck for PyWeakrefProxy {
24
- const NAME : & ' static str = "weakref.ProxyTypes" ;
25
- #[ cfg( feature = "experimental-inspect" ) ]
26
- const PYTHON_TYPE : & ' static str = "weakref.ProxyType | weakref.CallableProxyType" ;
27
-
28
- fn type_check ( object : & Bound < ' _ , PyAny > ) -> bool {
29
- unsafe { ffi:: PyWeakref_CheckProxy ( object. as_ptr ( ) ) > 0 }
30
- }
31
- }
32
-
33
42
/// TODO: UPDATE DOCS
34
43
impl PyWeakrefProxy {
35
44
/// Constructs a new Weak Reference (`weakref.proxy`/`weakref.ProxyType`/`weakref.CallableProxyType`) for the given object.
@@ -183,7 +192,7 @@ mod tests {
183
192
use crate :: exceptions:: { PyAttributeError , PyReferenceError , PyTypeError } ;
184
193
use crate :: types:: any:: { PyAny , PyAnyMethods } ;
185
194
use crate :: types:: weakref:: { PyWeakrefMethods , PyWeakrefProxy } ;
186
- use crate :: { Bound , PyResult , Python } ;
195
+ use crate :: { Bound , PyResult , PyTypeInfo , Python } ;
187
196
188
197
#[ cfg( all( Py_3_13 , not( Py_LIMITED_API ) ) ) ]
189
198
const DEADREF_FIX : Option < & str > = None ;
@@ -412,6 +421,18 @@ mod tests {
412
421
Ok ( ( ) )
413
422
} )
414
423
}
424
+
425
+ #[ test]
426
+ fn test_type_object ( ) -> PyResult < ( ) > {
427
+ Python :: attach ( |py| {
428
+ let t = PyWeakrefProxy :: type_object ( py) ;
429
+ let class = get_type ( py) ?;
430
+ let object = class. call0 ( ) ?;
431
+ let reference = PyWeakrefProxy :: new ( & object) ?;
432
+ assert ! ( reference. is_instance( & t) ?) ;
433
+ Ok ( ( ) )
434
+ } )
435
+ }
415
436
}
416
437
417
438
// under 'abi3-py37' and 'abi3-py38' PyClass cannot be weakreferencable.
@@ -718,6 +739,17 @@ mod tests {
718
739
Ok ( ( ) )
719
740
} )
720
741
}
742
+
743
+ #[ test]
744
+ fn test_type_object ( ) -> PyResult < ( ) > {
745
+ Python :: attach ( |py| {
746
+ let class = get_type ( py) ?;
747
+ let object = class. call0 ( ) ?;
748
+ let reference = PyWeakrefProxy :: new ( & object) ?;
749
+ assert ! ( reference. is_instance( & PyWeakrefProxy :: type_object( py) ) ?) ;
750
+ Ok ( ( ) )
751
+ } )
752
+ }
721
753
}
722
754
723
755
// under 'abi3-py37' and 'abi3-py38' PyClass cannot be weakreferencable.
0 commit comments