redis/hiredis-py — pull request #21 by andymccurdy (2014-04-15 09:18:34+00:00)
Title: Allow replyError and protocolError to be any type of callable

Currently in `_Reader_set_exception` (https://github.com/redis/hiredis-py/blob/master/src/reader.c#L155), `replyError` and `protocolError` must be subclasses of Exception. I'd like to propose that any callable (class, function, etc.) could be passed to these attributes.

In redis-py, I have custom exception classes for certain errors (https://github.com/andymccurdy/redis-py/blob/master/redis/connection.py#L41). These are used to handle specific error conditions within redis-py. For instance, redis-py's Script object specifically looks for `NoScriptError`s when calling `EVALSHA` against a script that's not already loaded on the Redis server.

In the plain `PythonParser`, I use the `parse_error` function from the URL above to parse the error string and create the appropriate exception instance. For the `HiredisParser`, I'm currently checking the type of the response, and if it's a `ResponseError` (what all hiredis errors are currently), then I replace the response with the result of running `parse_error` instead. While this code works for single item responses, it doesn't work when the response is a list of responses from a Pipeline. I could detect if the response is a list, and then iterate over each item in the list, testing for an Exception subclass and calling parse_error, but I fear that would significantly impact performance.

What I'd like to be able to do is just pass my `parse_error` function as the `replyError` kwarg to the hiredis Reader init. This would ensure that I always get the correct types of exceptions.

I believe the only change required to support this is to change `_Reader_set_exception` to use the `PyCallable_Check` function to verify that the value is a callable rather than a subclass. Existing classes should pass the `PyCallable_Check`, so there shouldn't be any backwards incompatibility issues.