From 865f5d4bb8f8ebcca4f3141d64ef7118181f7f00 Mon Sep 17 00:00:00 2001 From: Bruce Merry Date: Fri, 10 Nov 2017 10:06:30 +0200 Subject: [PATCH] Use repr to encode floats in to_bytes This ensures that no precision is lost when encoding 64-bit floats. This matches the encoding logic in redis-py. Tests are added for `set`, `incrbyfloat` and `hincrbyfloat`. --- fakeredis.py | 4 ++++ test_fakeredis.py | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/fakeredis.py b/fakeredis.py index 29e7196..9575558 100644 --- a/fakeredis.py +++ b/fakeredis.py @@ -41,6 +41,8 @@ def to_bytes(x, charset=DEFAULT_ENCODING, errors='strict'): if isinstance(x, unicode): return x.encode(charset, errors) + if isinstance(x, float): + return repr(x) if isinstance(x, (bytes, bytearray, buffer)) or hasattr(x, '__str__'): return bytes(x) if hasattr(x, '__unicode__'): @@ -76,6 +78,8 @@ def to_bytes(x, charset=sys.getdefaultencoding(), errors='strict'): return bytes(x) if isinstance(x, str): return x.encode(charset, errors) + if isinstance(x, float): + return repr(x).encode(charset, errors) if hasattr(x, '__str__'): return str(x).encode(charset, errors) raise TypeError('expected bytes or str, not ' + type(x).__name__) diff --git a/test_fakeredis.py b/test_fakeredis.py index c98a34b..32bdf68 100644 --- a/test_fakeredis.py +++ b/test_fakeredis.py @@ -104,6 +104,11 @@ def test_set_None_value(self): self.assertEqual(self.redis.set('foo', None), True) self.assertEqual(self.redis.get('foo'), b'None') + def test_set_float_value(self): + x = 1.23456789123456789 + self.redis.set('foo', x) + self.assertEqual(float(self.redis.get('foo')), x) + def test_saving_non_ascii_chars_as_value(self): self.assertEqual(self.redis.set('foo', 'Ñandu'), True) self.assertEqual(self.redis.get('foo'), @@ -287,6 +292,11 @@ def test_incrbyfloat_bad_type(self): with self.assertRaisesRegexp(redis.ResponseError, 'not a valid float'): self.redis.incrbyfloat('foo', 1.0) + def test_incrbyfloat_precision(self): + x = 1.23456789123456789 + self.assertEqual(self.redis.incrbyfloat('foo', x), x) + self.assertEqual(float(self.redis.get('foo')), x) + def test_decr(self): self.redis.set('foo', 10) self.assertEqual(self.redis.decr('foo'), 9) @@ -884,6 +894,11 @@ def test_hincrbyfloat_with_non_float_amount_raises_error(self): with self.assertRaises(redis.ResponseError): self.redis.hincrbyfloat('foo', 'counter', 'cat') + def test_hincrbyfloat_precision(self): + x = 1.23456789123456789 + self.assertEqual(self.redis.hincrbyfloat('foo', 'bar', x), x) + self.assertEqual(float(self.redis.hget('foo', 'bar')), x) + def test_hsetnx(self): self.assertEqual(self.redis.hsetnx('foo', 'newkey', 'v1'), True) self.assertEqual(self.redis.hsetnx('foo', 'newkey', 'v1'), False)