[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