@@ -2,7 +2,8 @@ use super::{PyStrRef, PyType, PyTypeRef, PyWeak};
22use crate :: {
33 class:: PyClassImpl ,
44 function:: OptionalArg ,
5- types:: { Constructor , GetAttr , SetAttr } ,
5+ protocol:: { PyMappingMethods , PySequence , PySequenceMethods } ,
6+ types:: { AsMapping , AsSequence , Constructor , GetAttr , SetAttr } ,
67 Context , Py , PyObjectRef , PyPayload , PyRef , PyResult , VirtualMachine ,
78} ;
89
@@ -57,14 +58,44 @@ crate::common::static_cell! {
5758 static WEAK_SUBCLASS : PyTypeRef ;
5859}
5960
60- #[ pyimpl( with( GetAttr , SetAttr , Constructor ) ) ]
61+ #[ pyimpl( with( GetAttr , SetAttr , Constructor , AsSequence , AsMapping ) ) ]
6162impl PyWeakProxy {
63+ fn try_upgrade ( & self , vm : & VirtualMachine ) -> PyResult {
64+ self . weak . upgrade ( ) . ok_or_else ( || new_reference_error ( vm) )
65+ }
66+
6267 #[ pymethod( magic) ]
6368 fn str ( & self , vm : & VirtualMachine ) -> PyResult < PyStrRef > {
64- match self . weak . upgrade ( ) {
65- Some ( obj) => obj. str ( vm) ,
66- None => Err ( new_reference_error ( vm) ) ,
67- }
69+ self . try_upgrade ( vm) ?. str ( vm)
70+ }
71+
72+ fn len ( & self , vm : & VirtualMachine ) -> PyResult < usize > {
73+ self . try_upgrade ( vm) ?. length ( vm)
74+ }
75+
76+ fn contains ( & self , needle : PyObjectRef , vm : & VirtualMachine ) -> PyResult < bool > {
77+ let obj = self . try_upgrade ( vm) ?;
78+ PySequence :: contains ( & obj, & needle, vm)
79+ }
80+
81+ fn getitem ( & self , needle : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
82+ let obj = self . try_upgrade ( vm) ?;
83+ obj. get_item ( & * needle, vm)
84+ }
85+
86+ fn setitem (
87+ & self ,
88+ needle : PyObjectRef ,
89+ value : PyObjectRef ,
90+ vm : & VirtualMachine ,
91+ ) -> PyResult < ( ) > {
92+ let obj = self . try_upgrade ( vm) ?;
93+ obj. set_item ( & * needle, value, vm)
94+ }
95+
96+ fn delitem ( & self , needle : PyObjectRef , vm : & VirtualMachine ) -> PyResult < ( ) > {
97+ let obj = self . try_upgrade ( vm) ?;
98+ obj. del_item ( & * needle, vm)
6899 }
69100}
70101
@@ -78,7 +109,7 @@ fn new_reference_error(vm: &VirtualMachine) -> PyRef<super::PyBaseException> {
78109impl GetAttr for PyWeakProxy {
79110 // TODO: callbacks
80111 fn getattro ( zelf : & Py < Self > , name : PyStrRef , vm : & VirtualMachine ) -> PyResult {
81- let obj = zelf. weak . upgrade ( ) . ok_or_else ( || new_reference_error ( vm ) ) ?;
112+ let obj = zelf. try_upgrade ( vm ) ?;
82113 obj. get_attr ( name, vm)
83114 }
84115}
@@ -90,16 +121,38 @@ impl SetAttr for PyWeakProxy {
90121 value : Option < PyObjectRef > ,
91122 vm : & VirtualMachine ,
92123 ) -> PyResult < ( ) > {
93- match zelf. weak . upgrade ( ) {
94- Some ( obj) => obj. call_set_attr ( vm, attr_name, value) ,
95- None => Err ( vm. new_exception_msg (
96- vm. ctx . exceptions . reference_error . to_owned ( ) ,
97- "weakly-referenced object no longer exists" . to_owned ( ) ,
98- ) ) ,
99- }
124+ let obj = zelf. try_upgrade ( vm) ?;
125+ obj. call_set_attr ( vm, attr_name, value)
100126 }
101127}
102128
129+ impl AsSequence for PyWeakProxy {
130+ const AS_SEQUENCE : PySequenceMethods = PySequenceMethods {
131+ length : Some ( |seq, vm| Self :: sequence_downcast ( seq) . len ( vm) ) ,
132+ contains : Some ( |seq, needle, vm| {
133+ Self :: sequence_downcast ( seq) . contains ( needle. to_owned ( ) , vm)
134+ } ) ,
135+ ..PySequenceMethods :: NOT_IMPLEMENTED
136+ } ;
137+ }
138+
139+ impl AsMapping for PyWeakProxy {
140+ const AS_MAPPING : PyMappingMethods = PyMappingMethods {
141+ length : Some ( |mapping, vm| Self :: mapping_downcast ( mapping) . len ( vm) ) ,
142+ subscript : Some ( |mapping, needle, vm| {
143+ Self :: mapping_downcast ( mapping) . getitem ( needle. to_owned ( ) , vm)
144+ } ) ,
145+ ass_subscript : Some ( |mapping, needle, value, vm| {
146+ let zelf = Self :: mapping_downcast ( mapping) ;
147+ if let Some ( value) = value {
148+ zelf. setitem ( needle. to_owned ( ) , value, vm)
149+ } else {
150+ zelf. delitem ( needle. to_owned ( ) , vm)
151+ }
152+ } ) ,
153+ } ;
154+ }
155+
103156pub fn init ( context : & Context ) {
104157 PyWeakProxy :: extend_class ( context, context. types . weakproxy_type ) ;
105158}
0 commit comments