summaryrefslogtreecommitdiff
path: root/redis/client.py
diff options
context:
space:
mode:
authorPieter Noordhuis <pcnoordhuis@gmail.com>2011-01-30 15:22:46 +0100
committerPieter Noordhuis <pcnoordhuis@gmail.com>2011-01-30 15:22:46 +0100
commit7d96a315ef08381649903b51d75127338421f76f (patch)
tree41df5c3479622c6229705e817c3819868fc47e14 /redis/client.py
parent7112f5bc1115c099a4f7872b9088ce71b08f37ff (diff)
downloadredis-py-7d96a315ef08381649903b51d75127338421f76f.tar.gz
Move protocol parsing code to Connection class
Diffstat (limited to 'redis/client.py')
-rw-r--r--redis/client.py111
1 files changed, 55 insertions, 56 deletions
diff --git a/redis/client.py b/redis/client.py
index 9ba3547..6e33888 100644
--- a/redis/client.py
+++ b/redis/client.py
@@ -108,6 +108,60 @@ class Connection(object):
e.args[1])
return ''
+ def read_response(self, command_name, catch_errors):
+ response = self.read()[:-2] # strip last two characters (\r\n)
+ if not response:
+ self.disconnect()
+ raise ConnectionError("Socket closed on remote end")
+
+ # server returned a null value
+ if response in ('$-1', '*-1'):
+ return None
+ byte, response = response[0], response[1:]
+
+ # server returned an error
+ if byte == '-':
+ if response.startswith('ERR '):
+ response = response[4:]
+ raise ResponseError(response)
+ # single value
+ elif byte == '+':
+ return response
+ # int value
+ elif byte == ':':
+ return int(response)
+ # bulk response
+ elif byte == '$':
+ length = int(response)
+ if length == -1:
+ return None
+ response = length and self.read(length) or ''
+ self.read(2) # read the \r\n delimiter
+ return response
+ # multi-bulk response
+ elif byte == '*':
+ length = int(response)
+ if length == -1:
+ return None
+ if not catch_errors:
+ return [self.read_response(command_name, catch_errors)
+ for i in range(length)]
+ else:
+ # for pipelines, we need to read everything,
+ # including response errors. otherwise we'd
+ # completely mess up the receive buffer
+ data = []
+ for i in range(length):
+ try:
+ data.append(
+ self.read_response(command_name, catch_errors)
+ )
+ except Exception, e:
+ data.append(e)
+ return data
+
+ raise InvalidResponse("Unknown response type for: %s" % command_name)
+
def list_or_args(command, keys, args):
# returns a single list combining keys and args
# if keys is not a list or args has items, issue a
@@ -339,64 +393,9 @@ class Redis(threading.local):
**options
)
- def _parse_response(self, command_name, catch_errors):
- conn = self.connection
- response = conn.read()[:-2] # strip last two characters (\r\n)
- if not response:
- self.connection.disconnect()
- raise ConnectionError("Socket closed on remote end")
-
- # server returned a null value
- if response in ('$-1', '*-1'):
- return None
- byte, response = response[0], response[1:]
-
- # server returned an error
- if byte == '-':
- if response.startswith('ERR '):
- response = response[4:]
- raise ResponseError(response)
- # single value
- elif byte == '+':
- return response
- # int value
- elif byte == ':':
- return int(response)
- # bulk response
- elif byte == '$':
- length = int(response)
- if length == -1:
- return None
- response = length and conn.read(length) or ''
- conn.read(2) # read the \r\n delimiter
- return response
- # multi-bulk response
- elif byte == '*':
- length = int(response)
- if length == -1:
- return None
- if not catch_errors:
- return [self._parse_response(command_name, catch_errors)
- for i in range(length)]
- else:
- # for pipelines, we need to read everything,
- # including response errors. otherwise we'd
- # completely mess up the receive buffer
- data = []
- for i in range(length):
- try:
- data.append(
- self._parse_response(command_name, catch_errors)
- )
- except Exception, e:
- data.append(e)
- return data
-
- raise InvalidResponse("Unknown response type for: %s" % command_name)
-
def parse_response(self, command_name, catch_errors=False, **options):
"Parses a response from the Redis server"
- response = self._parse_response(command_name, catch_errors)
+ response = self.connection.read_response(command_name, catch_errors)
if command_name in self.RESPONSE_CALLBACKS:
return self.RESPONSE_CALLBACKS[command_name](response, **options)
return response