@@ -445,11 +445,11 @@ def _identity(self, key: str) -> str:
445
445
if isinstance (key , istr ):
446
446
ret = key .__istr_identity__
447
447
if ret is None :
448
- ret = key .title ()
448
+ ret = key .lower ()
449
449
key .__istr_identity__ = ret
450
450
return ret
451
451
if isinstance (key , str ):
452
- return key .title ()
452
+ return key .lower ()
453
453
else :
454
454
raise TypeError ("MultiDict keys should be either str or subclasses of str" )
455
455
@@ -632,13 +632,13 @@ def __init__(self, arg: MDArg[_V] = None, /, **kwargs: _V):
632
632
self ._from_md (md )
633
633
return
634
634
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 ) ))
637
637
if log2_size > 17 : # pragma: no cover
638
638
# Don't overallocate really huge keys space in init
639
639
log2_size = 17
640
640
self ._keys : _HtKeys [_V ] = _HtKeys .new (log2_size , [])
641
- self ._extend_items (items )
641
+ self ._extend_items (cast ( Iterator [ _Entry [ _V ]], it ) )
642
642
643
643
def _from_md (self , md : "MultiDict[_V]" ) -> None :
644
644
# Copy everything as-is without compacting the new multidict,
@@ -790,58 +790,57 @@ def extend(self, arg: MDArg[_V] = None, /, **kwargs: _V) -> None:
790
790
791
791
This method must be used instead of update.
792
792
"""
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 ) )
795
795
self ._resize (estimate_log2_keysize (newsize ), False )
796
- self ._extend_items (items )
796
+ self ._extend_items (cast ( Iterator [ _Entry [ _V ]], it ) )
797
797
798
798
def _parse_args (
799
799
self ,
800
800
arg : MDArg [_V ],
801
801
kwargs : Mapping [str , _V ],
802
- ) -> list [ _Entry [_V ]]:
802
+ ) -> Iterator [ Union [ int , _Entry [_V ] ]]:
803
803
identity_func = self ._identity
804
804
if arg :
805
805
if isinstance (arg , MultiDictProxy ):
806
806
arg = arg ._md
807
807
if isinstance (arg , MultiDict ):
808
+ yield len (arg ) + len (kwargs )
808
809
if self ._ci is not arg ._ci :
809
- items = []
810
810
for e in arg ._keys .iter_entries ():
811
811
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 )
813
813
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 )
818
816
if kwargs :
819
817
for key , value in kwargs .items ():
820
818
identity = identity_func (key )
821
- items . append ( _Entry (hash (identity ), identity , key , value ) )
819
+ yield _Entry (hash (identity ), identity , key , value )
822
820
else :
823
821
if hasattr (arg , "keys" ):
824
822
arg = cast (SupportsKeys [_V ], arg )
825
823
arg = [(k , arg [k ]) for k in arg .keys ()]
826
824
if kwargs :
827
825
arg = list (arg )
828
826
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
830
831
for pos , item in enumerate (arg ):
831
832
if not len (item ) == 2 :
832
833
raise ValueError (
833
834
f"multidict update sequence element #{ pos } "
834
835
f"has length { len (item )} ; 2 is required"
835
836
)
836
837
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 ])
838
839
else :
839
- items = []
840
+ yield len ( kwargs )
840
841
for key , value in kwargs .items ():
841
842
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 )
845
844
846
845
def _extend_items (self , items : Iterable [_Entry [_V ]]) -> None :
847
846
for e in items :
@@ -989,19 +988,21 @@ def popitem(self) -> tuple[str, _V]:
989
988
990
989
def update (self , arg : MDArg [_V ] = None , / , ** kwargs : _V ) -> None :
991
990
"""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 ) )
994
993
log2_size = estimate_log2_keysize (newsize )
995
994
if log2_size > 17 : # pragma: no cover
996
995
# Don't overallocate really huge keys space in update,
997
996
# duplicate keys could reduce the resulting anount of entries
998
997
log2_size = 17
999
998
if log2_size > self ._keys .log2_size :
1000
999
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 ()
1003
1004
1004
- def _update_items (self , items : list [_Entry [_V ]]) -> None :
1005
+ def _update_items (self , items : Iterator [_Entry [_V ]]) -> None :
1005
1006
for entry in items :
1006
1007
found = False
1007
1008
hash_ = entry .hash
@@ -1038,19 +1039,21 @@ def _post_update(self) -> None:
1038
1039
1039
1040
def merge (self , arg : MDArg [_V ] = None , / , ** kwargs : _V ) -> None :
1040
1041
"""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 ) )
1043
1044
log2_size = estimate_log2_keysize (newsize )
1044
1045
if log2_size > 17 : # pragma: no cover
1045
1046
# Don't overallocate really huge keys space in update,
1046
1047
# duplicate keys could reduce the resulting anount of entries
1047
1048
log2_size = 17
1048
1049
if log2_size > self ._keys .log2_size :
1049
1050
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 ()
1052
1055
1053
- def _merge_items (self , items : list [_Entry [_V ]]) -> None :
1056
+ def _merge_items (self , items : Iterator [_Entry [_V ]]) -> None :
1054
1057
for entry in items :
1055
1058
hash_ = entry .hash
1056
1059
identity = entry .identity
0 commit comments