[docs]classMultiDictProxy(Mapping):""" A proxy object which wraps multidict types along with a matching schema Whenever a value is looked up, it is checked against the schema to see if there is a matching field where `is_multiple` is True. If there is, then the data should be loaded as a list or tuple. In all other cases, __getitem__ proxies directly to the input multidict. """def__init__(self,multidict,schema:ma.Schema,known_multi_fields:typing.Tuple[typing.Type,...]=(ma.fields.List,ma.fields.Tuple,),):self.data=multidictself.known_multi_fields=known_multi_fieldsself.multiple_keys=self._collect_multiple_keys(schema)def_is_multiple(self,field:ma.fields.Field)->bool:"""Return whether or not `field` handles repeated/multi-value arguments."""# fields which set `is_multiple = True/False` will have the value selected,# otherwise, we check for explicit criteriais_multiple_attr=getattr(field,"is_multiple",None)ifis_multiple_attrisnotNone:returnis_multiple_attrreturnisinstance(field,self.known_multi_fields)def_collect_multiple_keys(self,schema:ma.Schema):result=set()forname,fieldinschema.fields.items():ifnotself._is_multiple(field):continueresult.add(field.data_keyiffield.data_keyisnotNoneelsename)returnresultdef__getitem__(self,key):val=self.data.get(key,ma.missing)ifvalisma.missingorkeynotinself.multiple_keys:returnvalifhasattr(self.data,"getlist"):returnself.data.getlist(key)ifhasattr(self.data,"getall"):returnself.data.getall(key)ifisinstance(val,(list,tuple)):returnvalifvalisNone:returnNonereturn[val]def__str__(self):# str(proxy) proxies to str(proxy.data)returnstr(self.data)def__repr__(self):return(f"MultiDictProxy(data={self.data!r}, multiple_keys={self.multiple_keys!r})")def__delitem__(self,key):delself.data[key]def__setitem__(self,key,value):self.data[key]=valuedef__getattr__(self,name):returngetattr(self.data,name)def__iter__(self):forxiniter(self.data):# special case for header dicts which produce an iterator of tuples# instead of an iterator of stringsifisinstance(x,tuple):yieldx[0]else:yieldxdef__contains__(self,x):returnxinself.datadef__len__(self):returnlen(self.data)def__eq__(self,other):returnself.data==otherdef__ne__(self,other):returnself.data!=other