[Python-modules-commits] [python-fakeredis] 01/08: Import python-fakeredis_0.9.0.orig.tar.gz
Ondrej Koblizek
kobla-guest at moszumanska.debian.org
Thu Nov 9 13:18:45 UTC 2017
This is an automated email from the git hooks/post-receive script.
kobla-guest pushed a commit to branch master
in repository python-fakeredis.
commit 31702cafebadba6d0555cc661de92497f7dd06ce
Author: Ondřej Kobližek <ondrej.koblizek at firma.seznam.cz>
Date: Thu Nov 9 11:48:20 2017 +0100
Import python-fakeredis_0.9.0.orig.tar.gz
---
.travis.yml | 12 +++++---
README.rst | 4 +--
fakeredis.py | 91 +++++++++++++++++++++++++++++++++++++++++++------------
setup.py | 9 ++++--
test_fakeredis.py | 81 +++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 167 insertions(+), 30 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 4e6cd9d..769d5ff 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,10 +1,12 @@
language: python
python:
- - "2.6"
- - "2.7"
- - "3.3"
- - "3.4"
- - "3.5"
+ - 2.6
+ - 2.7
+ - 3.3
+ - 3.4
+ - 3.5
+ - 3.6
+ - nightly
sudo: false
cache:
- pip
diff --git a/README.rst b/README.rst
index b57ca6a..3adb65c 100644
--- a/README.rst
+++ b/README.rst
@@ -1,11 +1,11 @@
fakeredis: A fake version of a redis-py
=======================================
-.. image:: https://secure.travis-ci.org/jamesls/fakeredis.png?branch=master
+.. image:: https://secure.travis-ci.org/jamesls/fakeredis.svg?branch=master
:target: http://travis-ci.org/jamesls/fakeredis
-.. image:: https://coveralls.io/repos/jamesls/fakeredis/badge.png?branch=master
+.. image:: https://coveralls.io/repos/jamesls/fakeredis/badge.svg?branch=master
:target: https://coveralls.io/r/jamesls/fakeredis
diff --git a/fakeredis.py b/fakeredis.py
index ee83fe2..29e7196 100644
--- a/fakeredis.py
+++ b/fakeredis.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
import random
import warnings
import copy
@@ -25,25 +26,23 @@ except:
PY2 = sys.version_info[0] == 2
-if not PY2:
- long = int
-
-__version__ = '0.8.2'
+__version__ = '0.9.0'
-if sys.version_info[0] == 2:
+if PY2:
+ DEFAULT_ENCODING = 'utf-8'
text_type = unicode
string_types = (str, unicode)
redis_string_types = (str, unicode, bytes)
byte_to_int = ord
int_to_byte = chr
- def to_bytes(x, charset=sys.getdefaultencoding(), errors='strict'):
- if isinstance(x, (bytes, bytearray, buffer)) or hasattr(x, '__str__'):
- return bytes(x)
+ def to_bytes(x, charset=DEFAULT_ENCODING, errors='strict'):
if isinstance(x, unicode):
return x.encode(charset, errors)
+ if isinstance(x, (bytes, bytearray, buffer)) or hasattr(x, '__str__'):
+ return bytes(x)
if hasattr(x, '__unicode__'):
return unicode(x).encode(charset, errors)
raise TypeError('expected bytes or unicode, not ' + type(x).__name__)
@@ -58,6 +57,9 @@ if sys.version_info[0] == 2:
iteritems = lambda d: d.iteritems()
from urlparse import urlparse
else:
+ DEFAULT_ENCODING = sys.getdefaultencoding()
+ long = int
+ basestring = str
text_type = str
string_types = (str,)
redis_string_types = (bytes, str)
@@ -130,6 +132,12 @@ class _StrKeyDict(MutableMapping):
def expire(self, key, timestamp):
self._ex_keys[key] = timestamp
+ def persist(self, key):
+ try:
+ del self._ex_keys[key]
+ except KeyError:
+ pass
+
def expiring(self, key):
if key not in self._ex_keys:
return None
@@ -174,8 +182,10 @@ def DecodeGenerator(gen):
def _decode(value):
- if isinstance(value, bytes):
- value = value.decode()
+ if isinstance(value, text_type):
+ return value
+ elif isinstance(value, bytes):
+ value = value.decode(DEFAULT_ENCODING)
elif isinstance(value, dict):
value = dict((_decode(k), _decode(v)) for k, v in value.items())
elif isinstance(value, (list, set, tuple)):
@@ -403,7 +413,7 @@ class FakeStrictRedis(object):
pass
def persist(self, name):
- pass
+ self._db.persist(name)
def ping(self):
return True
@@ -446,6 +456,8 @@ class FakeStrictRedis(object):
if px > 0:
self._db.expire(name, datetime.now() +
timedelta(milliseconds=px))
+ else:
+ self._db.persist(name)
self._db[name] = to_bytes(value)
return True
else:
@@ -474,6 +486,9 @@ class FakeStrictRedis(object):
def setex(self, name, time, value):
if isinstance(time, timedelta):
time = int(timedelta_total_seconds(time))
+ if not isinstance(time, int):
+ raise ResponseError(
+ 'value is not an integer or out of range')
return self.set(name, value, ex=time)
def psetex(self, name, time_ms, value):
@@ -491,7 +506,12 @@ class FakeStrictRedis(object):
return result
def setrange(self, name, offset, value):
- pass
+ val = self._db.get(name, b"")
+ if len(val) < offset:
+ val += b'\x00' * (offset - len(val))
+ val = val[0:offset] + to_bytes(value) + val[offset+len(value):]
+ self.set(name, val)
+ return len(val)
def strlen(self, name):
try:
@@ -544,6 +564,9 @@ class FakeStrictRedis(object):
return b'list'
elif isinstance(key, set):
return b'set'
+ else:
+ assert key is None
+ return b'none'
def watch(self, *names):
pass
@@ -963,12 +986,34 @@ class FakeStrictRedis(object):
except KeyError:
return None
- def srandmember(self, name):
- "Return a random member of set ``name``"
+ def srandmember(self, name, number=None):
+ """
+ If ``number`` is None, returns a random member of set ``name``.
+
+ If ``number`` is supplied, returns a list of ``number`` random
+ memebers of set ``name``.
+ """
members = self._db.get(name, set())
- if members:
+ if not members:
+ if number is not None:
+ return []
+ else:
+ return None
+
+ if number is None:
index = random.randint(0, len(members) - 1)
return list(members)[index]
+ elif len(members) <= number:
+ # We return them all, shuffled.
+ res = list(members)
+ random.shuffle(res)
+ return res
+ else:
+ member_list = list(members)
+ return [
+ member_list[i] for i
+ in sorted(random.sample(range(len(members)), number))
+ ]
def srem(self, name, *values):
"Remove ``value`` from set ``name``"
@@ -1450,11 +1495,15 @@ class FakeStrictRedis(object):
self._db[dest] = new_zset
def _list_or_args(self, keys, args):
- # Based off of list_or_args from redis-py.
# Returns a single list combining keys and args.
- # A string can be iterated, but indicates
- # keys wasn't passed as a list.
- if isinstance(keys, string_types):
+ # Copy of list_or_args from redis-py.
+ try:
+ iter(keys)
+ # a string or bytes instance can be iterated, but indicates
+ # keys wasn't passed as a list
+ if isinstance(keys, (basestring, bytes)):
+ keys = [keys]
+ except TypeError:
keys = [keys]
if args:
keys.extend(args)
@@ -1727,6 +1776,7 @@ class FakePubSub(object):
SUBSCRIBE_MESSAGE_TYPES = ['subscribe', 'psubscribe']
UNSUBSCRIBE_MESSAGE_TYPES = ['unsubscribe', 'punsubscribe']
PATTERN_MESSAGE_TYPES = ['psubscribe', 'punsubscribe']
+ LISTEN_DELAY = 0.1 # delay between listen loops (seconds)
def __init__(self, decode_responses=False, *args, **kwargs):
self.channels = {}
@@ -1877,8 +1927,9 @@ class FakePubSub(object):
message = self.get_message()
if message:
yield message
+ continue
- time.sleep(1)
+ time.sleep(self.LISTEN_DELAY)
def close(self):
"""
diff --git a/setup.py b/setup.py
index c4c1b13..35e0656 100644
--- a/setup.py
+++ b/setup.py
@@ -5,7 +5,7 @@ from setuptools import setup, find_packages
setup(
name='fakeredis',
- version='0.8.2',
+ version='0.9.0',
description="Fake implementation of redis API for testing purposes.",
long_description=open(os.path.join(os.path.dirname(__file__),
'README.rst')).read(),
@@ -16,14 +16,17 @@ setup(
py_modules=['fakeredis'],
classifiers=[
'Development Status :: 5 - Production/Stable',
+ 'License :: OSI Approved :: BSD License',
+ 'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
- 'License :: OSI Approved :: BSD License',
+ 'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6',
],
install_requires=[
'redis',
]
)
-
diff --git a/test_fakeredis.py b/test_fakeredis.py
index 0fc76c3..c98a34b 100644
--- a/test_fakeredis.py
+++ b/test_fakeredis.py
@@ -1,8 +1,10 @@
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
from time import sleep, time
from redis.exceptions import ResponseError
import inspect
from functools import wraps
+import os
import sys
import threading
@@ -41,6 +43,9 @@ except:
pass
+DEFAULT_ENCODING = fakeredis.DEFAULT_ENCODING
+
+
def redis_must_be_running(cls):
# This can probably be improved. This will determines
# at import time if the tests should be run, but we probably
@@ -99,6 +104,24 @@ class TestFakeStrictRedis(unittest.TestCase):
self.assertEqual(self.redis.set('foo', None), True)
self.assertEqual(self.redis.get('foo'), b'None')
+ def test_saving_non_ascii_chars_as_value(self):
+ self.assertEqual(self.redis.set('foo', 'Ñandu'), True)
+ self.assertEqual(self.redis.get('foo'),
+ u'Ñandu'.encode(DEFAULT_ENCODING))
+
+ def test_saving_unicode_type_as_value(self):
+ self.assertEqual(self.redis.set('foo', u'Ñandu'), True)
+ self.assertEqual(self.redis.get('foo'),
+ u'Ñandu'.encode(DEFAULT_ENCODING))
+
+ def test_saving_non_ascii_chars_as_key(self):
+ self.assertEqual(self.redis.set('Ñandu', 'foo'), True)
+ self.assertEqual(self.redis.get('Ñandu'), b'foo')
+
+ def test_saving_unicode_type_as_key(self):
+ self.assertEqual(self.redis.set(u'Ñandu', 'foo'), True)
+ self.assertEqual(self.redis.get(u'Ñandu'), b'foo')
+
def test_get_does_not_exist(self):
self.assertEqual(self.redis.get('foo'), None)
@@ -361,6 +384,11 @@ class TestFakeStrictRedis(unittest.TestCase):
self.redis.setex('foo', timedelta(seconds=100), 'bar'), True)
self.assertEqual(self.redis.get('foo'), b'bar')
+ def test_setex_using_float(self):
+ self.assertRaisesRegexp(
+ redis.ResponseError, 'integer', self.redis.setex, 'foo', 1.2,
+ 'bar')
+
def test_set_ex(self):
self.assertEqual(self.redis.set('foo', 'bar', ex=100), True)
self.assertEqual(self.redis.get('foo'), b'bar')
@@ -979,6 +1007,18 @@ class TestFakeStrictRedis(unittest.TestCase):
self.redis.sadd('baz', 'member1')
self.assertEqual(self.redis.scard('baz'), 1)
+ def test_setrange(self):
+ self.redis.set('foo', 'test')
+ self.assertEqual(self.redis.setrange('foo', 1, 'aste'), 5)
+ self.assertEqual(self.redis.get('foo'), b'taste')
+
+ self.redis.set('foo', 'test')
+ self.assertEqual(self.redis.setrange('foo', 1, 'a'), 4)
+ self.assertEqual(self.redis.get('foo'), b'tast')
+
+ self.assertEqual(self.redis.setrange('bar', 2, 'test'), 6)
+ self.assertEqual(self.redis.get('bar'), b'\x00\x00test')
+
def test_sinter(self):
self.redis.sadd('foo', 'member1')
self.redis.sadd('foo', 'member2')
@@ -988,6 +1028,16 @@ class TestFakeStrictRedis(unittest.TestCase):
self.assertEqual(self.redis.sinter('foo'),
set([b'member1', b'member2']))
+ def test_sinter_bytes_keys(self):
+ foo = os.urandom(10)
+ bar = os.urandom(10)
+ self.redis.sadd(foo, 'member1')
+ self.redis.sadd(foo, 'member2')
+ self.redis.sadd(bar, 'member2')
+ self.redis.sadd(bar, 'member3')
+ self.assertEqual(self.redis.sinter(foo, bar), set([b'member2']))
+ self.assertEqual(self.redis.sinter(foo), set([b'member1', b'member2']))
+
def test_sinterstore(self):
self.redis.sadd('foo', 'member1')
self.redis.sadd('foo', 'member2')
@@ -1029,6 +1079,26 @@ class TestFakeStrictRedis(unittest.TestCase):
# Shouldn't be removed from the set.
self.assertEqual(self.redis.srandmember('foo'), b'member1')
+ def test_srandmember_number(self):
+ """srandmember works with the number argument."""
+ self.assertEqual(self.redis.srandmember('foo', 2), [])
+ self.redis.sadd('foo', b'member1')
+ self.assertEqual(self.redis.srandmember('foo', 2), [b'member1'])
+ self.redis.sadd('foo', b'member2')
+ self.assertEqual(set(self.redis.srandmember('foo', 2)),
+ set([b'member1', b'member2']))
+ self.redis.sadd('foo', b'member3')
+ res = self.redis.srandmember('foo', 2)
+ self.assertEqual(len(res), 2)
+
+ if self.decode_responses:
+ superset = set(['member1', 'member2', 'member3'])
+ else:
+ superset = set([b'member1', b'member2', b'member3'])
+
+ for e in res:
+ self.assertIn(e, superset)
+
def test_srem(self):
self.redis.sadd('foo', 'member1', 'member2', 'member3', 'member4')
self.assertEqual(self.redis.smembers('foo'),
@@ -2085,6 +2155,7 @@ class TestFakeStrictRedis(unittest.TestCase):
self.assertEqual(self.redis.type('set_key'), b'set')
self.assertEqual(self.redis.type('zset_key'), b'zset')
self.assertEqual(self.redis.type('hset_key'), b'hash')
+ self.assertEqual(self.redis.type('none_key'), b'none')
@attr('slow')
def test_pubsub_subscribe(self):
@@ -2430,6 +2501,16 @@ class TestFakeStrictRedis(unittest.TestCase):
self.assertEqual(self.redis.get('foo'), None)
self.assertEqual(self.redis.pttl('foo'), -2)
+ def test_persist(self):
+ self.redis.set('foo', 'bar', ex=20)
+ self.redis.persist('foo')
+ self.assertEqual(self.redis.ttl('foo'), -1)
+
+ def test_set_existing_key_persists(self):
+ self.redis.set('foo', 'bar', ex=20)
+ self.redis.set('foo', 'foo')
+ self.assertEqual(self.redis.ttl('foo'), -1)
+
class TestFakeRedis(unittest.TestCase):
decode_responses = False
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-fakeredis.git
More information about the Python-modules-commits
mailing list