@@ -2,7 +2,7 @@ use super::{PyDict, PyGenericAlias, PyList, PyTuple, PyType, PyTypeRef};
22use crate :: {
33 class:: PyClassImpl ,
44 convert:: ToPyObject ,
5- function:: OptionalArg ,
5+ function:: { ArgMapping , OptionalArg } ,
66 protocol:: { PyMapping , PyMappingMethods , PySequence , PySequenceMethods } ,
77 types:: { AsMapping , AsSequence , Constructor , Iterable } ,
88 AsObject , Context , Py , PyObject , PyObjectRef , PyPayload , PyRef , PyResult , VirtualMachine ,
@@ -18,7 +18,7 @@ pub struct PyMappingProxy {
1818#[ derive( Debug ) ]
1919enum MappingProxyInner {
2020 Class ( PyTypeRef ) ,
21- Dict ( PyObjectRef ) ,
21+ Mapping ( ArgMapping ) ,
2222}
2323
2424impl PyPayload for PyMappingProxy {
@@ -39,21 +39,21 @@ impl Constructor for PyMappingProxy {
3939 type Args = PyObjectRef ;
4040
4141 fn py_new ( cls : PyTypeRef , mapping : Self :: Args , vm : & VirtualMachine ) -> PyResult {
42- if !PyMapping :: check ( mapping. as_ref ( ) , vm)
43- || mapping. payload_if_subclass :: < PyList > ( vm) . is_some ( )
44- || mapping. payload_if_subclass :: < PyTuple > ( vm) . is_some ( )
45- {
46- Err ( vm. new_type_error ( format ! (
47- "mappingproxy() argument must be a mapping, not {}" ,
48- mapping. class( )
49- ) ) )
50- } else {
51- Self {
52- mapping : MappingProxyInner :: Dict ( mapping) ,
42+ if let Some ( methods) = PyMapping :: find_methods ( & mapping, vm) {
43+ if mapping. payload_if_subclass :: < PyList > ( vm) . is_none ( )
44+ && mapping. payload_if_subclass :: < PyTuple > ( vm) . is_none ( )
45+ {
46+ return Self {
47+ mapping : MappingProxyInner :: Mapping ( ArgMapping :: with_methods ( mapping, methods) ) ,
48+ }
49+ . into_ref_with_type ( vm, cls)
50+ . map ( Into :: into) ;
5351 }
54- . into_ref_with_type ( vm, cls)
55- . map ( Into :: into)
5652 }
53+ Err ( vm. new_type_error ( format ! (
54+ "mappingproxy() argument must be a mapping, not {}" ,
55+ mapping. class( )
56+ ) ) )
5757 }
5858}
5959
@@ -64,7 +64,7 @@ impl PyMappingProxy {
6464 MappingProxyInner :: Class ( class) => key
6565 . as_interned_str ( vm)
6666 . and_then ( |key| class. attributes . read ( ) . get ( key) . cloned ( ) ) ,
67- MappingProxyInner :: Dict ( obj ) => obj . get_item ( & * key, vm) . ok ( ) ,
67+ MappingProxyInner :: Mapping ( mapping ) => mapping . mapping ( ) . subscript ( & * key, vm) . ok ( ) ,
6868 } ;
6969 Ok ( opt)
7070 }
@@ -92,7 +92,7 @@ impl PyMappingProxy {
9292 MappingProxyInner :: Class ( class) => Ok ( key
9393 . as_interned_str ( vm)
9494 . map_or ( false , |key| class. attributes . read ( ) . contains_key ( key) ) ) ,
95- MappingProxyInner :: Dict ( obj) => PySequence :: from ( obj. as_ref ( ) ) . contains ( key, vm) ,
95+ MappingProxyInner :: Mapping ( obj) => PySequence :: from ( obj. as_ref ( ) ) . contains ( key, vm) ,
9696 }
9797 }
9898
@@ -101,53 +101,42 @@ impl PyMappingProxy {
101101 self . _contains ( & key, vm)
102102 }
103103
104- #[ pymethod]
105- pub fn items ( & self , vm : & VirtualMachine ) -> PyResult {
106- let obj = match & self . mapping {
107- MappingProxyInner :: Dict ( d) => d. clone ( ) ,
104+ fn to_object ( & self , vm : & VirtualMachine ) -> PyResult {
105+ Ok ( match & self . mapping {
106+ MappingProxyInner :: Mapping ( d) => d. as_ref ( ) . to_owned ( ) ,
108107 MappingProxyInner :: Class ( c) => {
109108 PyDict :: from_attributes ( c. attributes . read ( ) . clone ( ) , vm) ?. to_pyobject ( vm)
110109 }
111- } ;
110+ } )
111+ }
112+
113+ #[ pymethod]
114+ pub fn items ( & self , vm : & VirtualMachine ) -> PyResult {
115+ let obj = self . to_object ( vm) ?;
112116 vm. call_method ( & obj, identifier ! ( vm, items) . as_str ( ) , ( ) )
113117 }
114118 #[ pymethod]
115119 pub fn keys ( & self , vm : & VirtualMachine ) -> PyResult {
116- let obj = match & self . mapping {
117- MappingProxyInner :: Dict ( d) => d. clone ( ) ,
118- MappingProxyInner :: Class ( c) => {
119- PyDict :: from_attributes ( c. attributes . read ( ) . clone ( ) , vm) ?. to_pyobject ( vm)
120- }
121- } ;
120+ let obj = self . to_object ( vm) ?;
122121 vm. call_method ( & obj, identifier ! ( vm, keys) . as_str ( ) , ( ) )
123122 }
124123 #[ pymethod]
125124 pub fn values ( & self , vm : & VirtualMachine ) -> PyResult {
126- let obj = match & self . mapping {
127- MappingProxyInner :: Dict ( d) => d. clone ( ) ,
128- MappingProxyInner :: Class ( c) => {
129- PyDict :: from_attributes ( c. attributes . read ( ) . clone ( ) , vm) ?. to_pyobject ( vm)
130- }
131- } ;
125+ let obj = self . to_object ( vm) ?;
132126 vm. call_method ( & obj, identifier ! ( vm, values) . as_str ( ) , ( ) )
133127 }
134128 #[ pymethod]
135129 pub fn copy ( & self , vm : & VirtualMachine ) -> PyResult {
136130 match & self . mapping {
137- MappingProxyInner :: Dict ( d) => vm. call_method ( d, identifier ! ( vm, copy) . as_str ( ) , ( ) ) ,
131+ MappingProxyInner :: Mapping ( d) => vm. call_method ( d, identifier ! ( vm, copy) . as_str ( ) , ( ) ) ,
138132 MappingProxyInner :: Class ( c) => {
139133 Ok ( PyDict :: from_attributes ( c. attributes . read ( ) . clone ( ) , vm) ?. to_pyobject ( vm) )
140134 }
141135 }
142136 }
143137 #[ pymethod( magic) ]
144138 fn repr ( & self , vm : & VirtualMachine ) -> PyResult < String > {
145- let obj = match & self . mapping {
146- MappingProxyInner :: Dict ( d) => d. clone ( ) ,
147- MappingProxyInner :: Class ( c) => {
148- PyDict :: from_attributes ( c. attributes . read ( ) . clone ( ) , vm) ?. to_pyobject ( vm)
149- }
150- } ;
139+ let obj = self . to_object ( vm) ?;
151140 Ok ( format ! ( "mappingproxy({})" , obj. repr( vm) ?) )
152141 }
153142
@@ -185,13 +174,7 @@ impl PyMappingProxy {
185174
186175impl Iterable for PyMappingProxy {
187176 fn iter ( zelf : PyRef < Self > , vm : & VirtualMachine ) -> PyResult {
188- let obj = match & zelf. mapping {
189- MappingProxyInner :: Dict ( d) => d. clone ( ) ,
190- MappingProxyInner :: Class ( c) => {
191- // TODO: something that's much more efficient than this
192- PyDict :: from_attributes ( c. attributes . read ( ) . clone ( ) , vm) ?. to_pyobject ( vm)
193- }
194- } ;
177+ let obj = zelf. to_object ( vm) ?;
195178 let iter = obj. get_iter ( vm) ?;
196179 Ok ( iter. into ( ) )
197180 }
0 commit comments