@@ -1527,11 +1527,20 @@ impl ExecutingFrame<'_> {
15271527 let size = size as usize ;
15281528 let map_obj = vm. ctx . new_dict ( ) ;
15291529 for obj in self . pop_multiple ( size) {
1530- // Take all key-value pairs from the dict:
1531- let dict: PyDictRef = obj. downcast ( ) . map_err ( |obj| {
1532- vm. new_type_error ( format ! ( "'{}' object is not a mapping" , obj. class( ) . name( ) ) )
1533- } ) ?;
1534- for ( key, value) in dict {
1530+ // Use keys() method for all mapping objects to preserve order
1531+ let Some ( keys_method) = vm. get_method ( obj. clone ( ) , vm. ctx . intern_str ( "keys" ) ) else {
1532+ return Err (
1533+ vm. new_type_error ( format ! ( "'{}' object is not a mapping" , obj. class( ) . name( ) ) )
1534+ ) ;
1535+ } ;
1536+
1537+ let keys = keys_method?. call ( ( ) , vm) ?. get_iter ( vm) ?;
1538+ while let PyIterReturn :: Return ( key) = keys. next ( vm) ? {
1539+ // Check for keyword argument restrictions
1540+ if key. downcast_ref :: < PyStr > ( ) . is_none ( ) {
1541+ return Err ( vm. new_type_error ( "keywords must be strings" . to_owned ( ) ) ) ;
1542+ }
1543+
15351544 if map_obj. contains_key ( & * key, vm) {
15361545 let key_repr = & key. repr ( vm) ?;
15371546 let msg = format ! (
@@ -1540,6 +1549,8 @@ impl ExecutingFrame<'_> {
15401549 ) ;
15411550 return Err ( vm. new_type_error ( msg) ) ;
15421551 }
1552+
1553+ let value = obj. get_item ( & * key, vm) ?;
15431554 map_obj. set_item ( & * key, value, vm) ?;
15441555 }
15451556 }
@@ -1586,16 +1597,22 @@ impl ExecutingFrame<'_> {
15861597
15871598 fn collect_ex_args ( & mut self , vm : & VirtualMachine , has_kwargs : bool ) -> PyResult < FuncArgs > {
15881599 let kwargs = if has_kwargs {
1589- let kw_dict: PyDictRef = self . pop_value ( ) . downcast ( ) . map_err ( |_| {
1590- // TODO: check collections.abc.Mapping
1591- vm. new_type_error ( "Kwargs must be a dict." . to_owned ( ) )
1592- } ) ?;
1600+ let kw_obj = self . pop_value ( ) ;
15931601 let mut kwargs = IndexMap :: new ( ) ;
1594- for ( key, value) in kw_dict. into_iter ( ) {
1595- let key = key
1602+
1603+ // Use keys() method for all mapping objects to preserve order
1604+ let Some ( keys_method) = vm. get_method ( kw_obj. clone ( ) , vm. ctx . intern_str ( "keys" ) ) else {
1605+ return Err ( vm. new_type_error ( "argument after ** must be a mapping" . to_owned ( ) ) ) ;
1606+ } ;
1607+
1608+ // Handle custom mapping objects like OrderedDict using keys() method
1609+ let keys = keys_method?. call ( ( ) , vm) ?. get_iter ( vm) ?;
1610+ while let PyIterReturn :: Return ( key) = keys. next ( vm) ? {
1611+ let key_str = key
15961612 . payload_if_subclass :: < PyStr > ( vm)
15971613 . ok_or_else ( || vm. new_type_error ( "keywords must be strings" . to_owned ( ) ) ) ?;
1598- kwargs. insert ( key. as_str ( ) . to_owned ( ) , value) ;
1614+ let value = kw_obj. get_item ( & * key, vm) ?;
1615+ kwargs. insert ( key_str. as_str ( ) . to_owned ( ) , value) ;
15991616 }
16001617 kwargs
16011618 } else {
0 commit comments