[docs]classMultiChainMap(ChainMap):""" Implements the logic of chainmap, but for multidicts. It also allows to unset values on some key, this will be used for headers, cookies, query string ... to allow the user to rewrite requests/responses in a memory efficient way. The current implementation is neither complete, nor optimized. TODO: find a better way for __iter__ """def__getitem__(self,key):x=super().__getitem__(key)ifxisNotSet:returnself.__missing__(key)returnxdef__delitem__(self,key):ifkeynotinself:returnsuper().__delitem__(key)self.maps[0][key]=NotSetdef__contains__(self,key):ifkeyinself.maps[0]andself.maps[0][key]isNotSet:returnFalsereturnsuper().__contains__(key)def__len__(self):returnlen(list(self.__iter__()))
[docs]defitems(self):# TODO this needs a better algorithm (that does not involve creating a lot of multidicts)d=CIMultiDict()formappinginreversed(self.maps):d.update(CIMultiDict(((k,v)fork,vinmapping.items())))return[(k,v)fork,vind.items()ifvisnotNotSet]
def__iter__(self):# TODO this needs a better algorithm (that does not involve creating a lot of multidicts)d=CIMultiDict()formappinginreversed(self.maps):d.update(CIMultiDict(((k,v)fork,vinmapping.items())))returniter(CIMultiDict(((k,v)fork,vind.items()ifvisnotNotSet)))
[docs]defpop(self,key):# it has already been unset, or is not thereifnotself.__contains__(key):raiseKeyError(f"Key not found in the first mapping: {key!r}")# otherwise, it's simpler to just set it as not setvalue=self[key]self[key]=NotSetreturnvalue