@@ -0,0 +1,2703 @@
+import time%0A%0Afrom collections import deque%0Afrom pybloom import ScalableBloomFilter%0A%0A%0Aclass DecayScalableBloomFilter(ScalableBloomFilter):%0A    '''%0A    Stepwise decaying Bloom Filter%0A    '''%0A    def __init__(self, initial_capacity=1000, error_rate=0.01, window_period = 60):%0A        super(DecayScalableBloomFilter, self).__init__(initial_capacity, error_rate)%0A        self.window_period = 60%0A        self.timestamp = time.time()%0A        self._expired = False%0A%0A    @property%0A    def expired(self):%0A        if time.time() - self.timestamp %3E self.window_period:%0A            self._expired = True%0A        return self._expired%0A%0A%0Aclass SlidingWindowScalableBloomFilter(object):%0A    '''%0A    Sliding Window Bloom Filter using a coarse expiration%0A    '''%0A%0A    VALID_RES = %7B'Min': 60,%0A                 'Hour': 3600,%0A                 'Day': 86400%7D%0A%0A    def __init__(self, initial_capacity=1000, window_period = %2210_Min%22):%0A        self.initial_capacity = initial_capacity%0A        self.error_rate = 0.01%0A        self._setup_window_period(window_period)%0A%0A    def _setup_window_period(self, window_period):%0A        try:%0A            self.amount, self.res = window_period.split('_')%0A            self.amount = int(self.amount)%0A        except ValueError:%0A            raise Exception('Invalid window period')%0A        self.window_period = SlidingWindowScalableBloomFilter.VALID_RES%5Bself.res%5D%0A        self.filters = deque(maxlen = self.amount)%0A%0A    def total_error(self):%0A        '''%0A        Return the total error: temporal error + native bf error%0A        '''%0A        temporal_error = float(1.0 / self.amount)%0A        total_error = self.error_rate + temporal_error%0A        return total_error%0A%0A    def __contains__(self, key):%0A        for f in reversed(self.filters):%0A            if key in f:%0A                return True%0A        return False%0A%0A    def check_expiration(self):%0A        filter = self.filters%5B0%5D%0A        if filter.expired:%0A            filter = DecayScalableBloomFilter(initial_capacity=self.initial_capacity,%0A                                              error_rate=self.error_rate,%0A                                              window_period=self.window_period)%0A            self.filters.append(filter)%0A%0A%0A    def add(self, key):%0A        self.check_expiration()%0A        if key in self:%0A            return True%0A        if not self.filters:%0A            filter = DecayScalableBloomFilter(initial_capacity=self.initial_capacity,%0A                                              error_rate=self.error_rate,%0A                                              window_period=self.window_period)%0A            self.filters.append(filter)%0A        else:%0A            filter = self.filters%5B-1%5D%0A        filter.add(key)%0A        return False%0A%0A

Add simple SlidingWindowScalableBloomFilter for combating overengineer habit