@@ -0,0 +1,1667 @@
+#!/usr/bin/env python%0A# -*- coding: utf-8 -*-%0A#%0A# Copyright (c) 2017~2999 - cologler %3Cskyoflw@gmail.com%3E%0A# ----------%0A#%0A# ----------%0A%0Afrom collections import KeysView, ValuesView, ItemsView, MutableMapping%0A%0A_NO_VALUE = object()%0A%0Aclass ContextDict(MutableMapping):%0A    '''context dict can override base_dict.'''%0A%0A    def __init__(self, base_dict: dict, *args, **kwargs):%0A        if base_dict is None:%0A            raise ValueError('base_dict cannot be None')%0A%0A        self._base_dict = base_dict%0A        self._data = dict(*args, **kwargs) # data maybe not empty.%0A%0A    def __setitem__(self, key, value):%0A        self._data%5Bkey%5D = value%0A%0A    def __delitem__(self, key):%0A        del self._data%5Bkey%5D%0A%0A    def __getitem__(self, key):%0A        value = self._data.get(key, _NO_VALUE)%0A        if value is _NO_VALUE:%0A            value = self._base_dict%5Bkey%5D%0A        return value%0A%0A    def __iter__(self):%0A        for k in self._data:%0A            yield k%0A        for k in self._base_dict:%0A            if k not in self._data:%0A                yield k%0A%0A    def __len__(self):%0A        # base dict may change, so we cannot cache the size.%0A        d1 = self._data%0A        d2 = self._base_dict%0A        d1_len = len(d1)%0A        d2_len = len(d2)%0A        if d1_len %3E d2_len: # ensure d1 %3C d2%0A            d1, d2 = d2, d1%0A        total_size = d1_len + d2_len%0A        for k in d1:%0A            if k in d2:%0A                total_size -= 1%0A        return total_size%0A%0A    def scope(self):%0A        '''create a scoped dict.'''%0A        return ContextDict(self)%0A%0A    def __enter__(self):%0A        '''return a new context dict.'''%0A        return self.scope()%0A%0A    def __exit__(self, *args):%0A        pass%0A

add ContextDict