diff --git a/fakeredis.py b/fakeredis.py index a10d927..63e2ced 100644 --- a/fakeredis.py +++ b/fakeredis.py @@ -142,6 +142,11 @@ def copy(self): new_copy.update(self._dict) return new_copy + # Not strictly necessary, but MutableMapping implements it by popping one + # item at a time, which may have odd effects in _ExpiringDict. + def clear(self): + self._dict.clear() + class _ExpiringDict(_StrKeyDict): def __getitem__(self, key): @@ -183,6 +188,15 @@ def persist(self, key): def expiring(self, key): return self._dict[to_bytes(key)][1] + def __iter__(self): + def generator(): + for key, (value, expiration) in iteritems(self._dict): + if expiration is not None and datetime.now() > expiration: + continue + yield key + + return generator() + class _ZSet(_StrKeyDict): redis_type = b'zset' diff --git a/test_fakeredis.py b/test_fakeredis.py index e494be7..de6a5dc 100644 --- a/test_fakeredis.py +++ b/test_fakeredis.py @@ -1294,6 +1294,13 @@ def test_scan_all_in_single_call(self): self.assertEqual(set(actual[1]), set(all_keys)) self.assertEqual(actual[0], 0) + @attr('slow') + def test_scan_expired_key(self): + self.redis.set('expiringkey', 'value') + self.redis.pexpire('expiringkey', 1) + sleep(1) + self.assertEqual(self.redis.scan()[1], []) + def test_scard(self): self.redis.sadd('foo', 'member1') self.redis.sadd('foo', 'member2')