@@ -445,11 +445,11 @@ def _identity(self, key: str) -> str:
445445 if isinstance (key , istr ):
446446 ret = key .__istr_identity__
447447 if ret is None :
448- ret = key .title ()
448+ ret = key .lower ()
449449 key .__istr_identity__ = ret
450450 return ret
451451 if isinstance (key , str ):
452- return key .title ()
452+ return key .lower ()
453453 else :
454454 raise TypeError ("MultiDict keys should be either str or subclasses of str" )
455455
@@ -632,13 +632,13 @@ def __init__(self, arg: MDArg[_V] = None, /, **kwargs: _V):
632632 self ._from_md (md )
633633 return
634634
635- items = self ._parse_args (arg , kwargs )
636- log2_size = estimate_log2_keysize (len ( items ))
635+ it = self ._parse_args (arg , kwargs )
636+ log2_size = estimate_log2_keysize (cast ( int , next ( it ) ))
637637 if log2_size > 17 : # pragma: no cover
638638 # Don't overallocate really huge keys space in init
639639 log2_size = 17
640640 self ._keys : _HtKeys [_V ] = _HtKeys .new (log2_size , [])
641- self ._extend_items (items )
641+ self ._extend_items (cast ( Iterator [ _Entry [ _V ]], it ) )
642642
643643 def _from_md (self , md : "MultiDict[_V]" ) -> None :
644644 # Copy everything as-is without compacting the new multidict,
@@ -790,58 +790,57 @@ def extend(self, arg: MDArg[_V] = None, /, **kwargs: _V) -> None:
790790
791791 This method must be used instead of update.
792792 """
793- items = self ._parse_args (arg , kwargs )
794- newsize = self ._used + len ( items )
793+ it = self ._parse_args (arg , kwargs )
794+ newsize = self ._used + cast ( int , next ( it ) )
795795 self ._resize (estimate_log2_keysize (newsize ), False )
796- self ._extend_items (items )
796+ self ._extend_items (cast ( Iterator [ _Entry [ _V ]], it ) )
797797
798798 def _parse_args (
799799 self ,
800800 arg : MDArg [_V ],
801801 kwargs : Mapping [str , _V ],
802- ) -> list [ _Entry [_V ]]:
802+ ) -> Iterator [ Union [ int , _Entry [_V ] ]]:
803803 identity_func = self ._identity
804804 if arg :
805805 if isinstance (arg , MultiDictProxy ):
806806 arg = arg ._md
807807 if isinstance (arg , MultiDict ):
808+ yield len (arg ) + len (kwargs )
808809 if self ._ci is not arg ._ci :
809- items = []
810810 for e in arg ._keys .iter_entries ():
811811 identity = identity_func (e .key )
812- items . append ( _Entry (hash (identity ), identity , e .key , e .value ) )
812+ yield _Entry (hash (identity ), identity , e .key , e .value )
813813 else :
814- items = [
815- _Entry (e .hash , e .identity , e .key , e .value )
816- for e in arg ._keys .iter_entries ()
817- ]
814+ for e in arg ._keys .iter_entries ():
815+ yield _Entry (e .hash , e .identity , e .key , e .value )
818816 if kwargs :
819817 for key , value in kwargs .items ():
820818 identity = identity_func (key )
821- items . append ( _Entry (hash (identity ), identity , key , value ) )
819+ yield _Entry (hash (identity ), identity , key , value )
822820 else :
823821 if hasattr (arg , "keys" ):
824822 arg = cast (SupportsKeys [_V ], arg )
825823 arg = [(k , arg [k ]) for k in arg .keys ()]
826824 if kwargs :
827825 arg = list (arg )
828826 arg .extend (list (kwargs .items ()))
829- items = []
827+ try :
828+ yield len (arg ) + len (kwargs ) # type: ignore[arg-type]
829+ except TypeError :
830+ yield 0
830831 for pos , item in enumerate (arg ):
831832 if not len (item ) == 2 :
832833 raise ValueError (
833834 f"multidict update sequence element #{ pos } "
834835 f"has length { len (item )} ; 2 is required"
835836 )
836837 identity = identity_func (item [0 ])
837- items . append ( _Entry (hash (identity ), identity , item [0 ], item [1 ]) )
838+ yield _Entry (hash (identity ), identity , item [0 ], item [1 ])
838839 else :
839- items = []
840+ yield len ( kwargs )
840841 for key , value in kwargs .items ():
841842 identity = identity_func (key )
842- items .append (_Entry (hash (identity ), identity , key , value ))
843-
844- return items
843+ yield _Entry (hash (identity ), identity , key , value )
845844
846845 def _extend_items (self , items : Iterable [_Entry [_V ]]) -> None :
847846 for e in items :
@@ -989,19 +988,21 @@ def popitem(self) -> tuple[str, _V]:
989988
990989 def update (self , arg : MDArg [_V ] = None , / , ** kwargs : _V ) -> None :
991990 """Update the dictionary, overwriting existing keys."""
992- items = self ._parse_args (arg , kwargs )
993- newsize = self ._used + len ( items )
991+ it = self ._parse_args (arg , kwargs )
992+ newsize = self ._used + cast ( int , next ( it ) )
994993 log2_size = estimate_log2_keysize (newsize )
995994 if log2_size > 17 : # pragma: no cover
996995 # Don't overallocate really huge keys space in update,
997996 # duplicate keys could reduce the resulting anount of entries
998997 log2_size = 17
999998 if log2_size > self ._keys .log2_size :
1000999 self ._resize (log2_size , False )
1001- self ._update_items (items )
1002- self ._post_update ()
1000+ try :
1001+ self ._update_items (cast (Iterator [_Entry [_V ]], it ))
1002+ finally :
1003+ self ._post_update ()
10031004
1004- def _update_items (self , items : list [_Entry [_V ]]) -> None :
1005+ def _update_items (self , items : Iterator [_Entry [_V ]]) -> None :
10051006 for entry in items :
10061007 found = False
10071008 hash_ = entry .hash
@@ -1038,19 +1039,21 @@ def _post_update(self) -> None:
10381039
10391040 def merge (self , arg : MDArg [_V ] = None , / , ** kwargs : _V ) -> None :
10401041 """Merge into the dictionary, adding non-existing keys."""
1041- items = self ._parse_args (arg , kwargs )
1042- newsize = self ._used + len ( items )
1042+ it = self ._parse_args (arg , kwargs )
1043+ newsize = self ._used + cast ( int , next ( it ) )
10431044 log2_size = estimate_log2_keysize (newsize )
10441045 if log2_size > 17 : # pragma: no cover
10451046 # Don't overallocate really huge keys space in update,
10461047 # duplicate keys could reduce the resulting anount of entries
10471048 log2_size = 17
10481049 if log2_size > self ._keys .log2_size :
10491050 self ._resize (log2_size , False )
1050- self ._merge_items (items )
1051- self ._post_update ()
1051+ try :
1052+ self ._merge_items (cast (Iterator [_Entry [_V ]], it ))
1053+ finally :
1054+ self ._post_update ()
10521055
1053- def _merge_items (self , items : list [_Entry [_V ]]) -> None :
1056+ def _merge_items (self , items : Iterator [_Entry [_V ]]) -> None :
10541057 for entry in items :
10551058 hash_ = entry .hash
10561059 identity = entry .identity
0 commit comments