diff options
author | Andy McCurdy <andy@andymccurdy.com> | 2014-04-21 00:29:56 -0700 |
---|---|---|
committer | Andy McCurdy <andy@andymccurdy.com> | 2014-04-21 00:29:56 -0700 |
commit | ca9f228da156df41d8c833a01da8551848629ee4 (patch) | |
tree | 1e0a776657ccb8ff254e84ee9db448cc15f5650f /redis/connection.py | |
parent | f96e46b971a5bb66ab5f94ba87ab3e092e5f01ac (diff) | |
download | redis-py-ca9f228da156df41d8c833a01da8551848629ee4.tar.gz |
better error handling with hiredis. fully fixes #456
Diffstat (limited to 'redis/connection.py')
-rw-r--r-- | redis/connection.py | 37 |
1 files changed, 29 insertions, 8 deletions
diff --git a/redis/connection.py b/redis/connection.py index eae8619..92a5c16 100644 --- a/redis/connection.py +++ b/redis/connection.py @@ -1,10 +1,12 @@ from __future__ import with_statement +from distutils.version import StrictVersion from itertools import chain from select import select import os import socket import sys import threading +import warnings from redis._compat import (b, xrange, imap, byte_to_chr, unicode, bytes, long, BytesIO, nativestr, basestring, @@ -23,6 +25,14 @@ from redis.utils import HIREDIS_AVAILABLE if HIREDIS_AVAILABLE: import hiredis + hiredis_version = StrictVersion(hiredis.__version__) + HIREDIS_SUPPORTS_CALLABLE_ERRORS = \ + hiredis_version >= StrictVersion('0.1.3') + + if not HIREDIS_SUPPORTS_CALLABLE_ERRORS: + msg = ('redis-py works best with hiredis >= 0.1.3. Your hiredis ' + 'is %s. Please consider upgrading.' % hiredis.__version__) + warnings.warn(msg) SYM_STAR = b('*') SYM_DOLLAR = b('$') @@ -48,8 +58,6 @@ class BaseParser(object): class SocketBuffer(object): - MAX_READ_LENGTH = 1000000 - def __init__(self, socket): self._sock = socket self._buffer = BytesIO() @@ -222,8 +230,12 @@ class HiredisParser(BaseParser): self._sock = connection._sock kwargs = { 'protocolError': InvalidResponse, - 'replyError': ResponseError, + 'replyError': self.parse_error, } + + if not HIREDIS_SUPPORTS_CALLABLE_ERRORS: + kwargs['replyError'] = ResponseError + if connection.decode_responses: kwargs['encoding'] = connection.encoding self._reader = hiredis.Reader(**kwargs) @@ -268,13 +280,22 @@ class HiredisParser(BaseParser): if not buffer.endswith(SYM_CRLF): continue response = self._reader.gets() - if isinstance(response, ResponseError): - response = self.parse_error(response.args[0]) - # hiredis only knows about ResponseErrors. - # self.parse_error() might turn the exception into a ConnectionError - # which needs raising. + # if an older version of hiredis is installed, we need to attempt + # to convert ResponseErrors to their appropriate types. + if not HIREDIS_SUPPORTS_CALLABLE_ERRORS: + if isinstance(response, ResponseError): + response = self.parse_error(response.args[0]) + elif isinstance(response, list) and response and \ + isinstance(response[0], ResponseError): + response[0] = self.parse_error(response[0].args[0]) + # if the response is a ConnectionError or the response is a list and + # the first item is a ConnectionError, raise it as something bad + # happened if isinstance(response, ConnectionError): raise response + elif isinstance(response, list) and response and \ + isinstance(response[0], ConnectionError): + raise response[0] return response if HIREDIS_AVAILABLE: |