diff options
author | Andy McCurdy <andy@andymccurdy.com> | 2011-06-01 01:08:10 -0700 |
---|---|---|
committer | Andy McCurdy <andy@andymccurdy.com> | 2011-06-01 01:08:10 -0700 |
commit | 2c4b66d40d34f71742e9a0bf5c4721eee66fc6a1 (patch) | |
tree | 2a0b27dc0fe740d2c19d17af36008d4538498fbd | |
parent | 47a4a7e339ea9c4243ea14303d7234f0de13f959 (diff) | |
download | redis-py-2c4b66d40d34f71742e9a0bf5c4721eee66fc6a1.tar.gz |
pipelines need the response_callback love, too. grammar fixes in docs
-rw-r--r-- | README.md | 47 | ||||
-rw-r--r-- | redis/client.py | 10 | ||||
-rw-r--r-- | tests/server_commands.py | 15 |
3 files changed, 46 insertions, 26 deletions
@@ -43,8 +43,8 @@ are managed. ConnectionPools manage a set of Connection instances. redis-py ships with two types of Connections. The default, Connection, is a normal TCP socket based -connection. UnixDomainSocketConnection allows for clients running on the same -device to connect via a unix domain socket. To use a +connection. The UnixDomainSocketConnection allows for clients running on the +same device as the server to connect via a unix domain socket. To use a UnixDomainSocketConnection connection, simply pass the class to the connection_class argument of either the Redis or ConnectionPool class. You must also specify the path argument, which is a string to the unix domain socket @@ -60,15 +60,16 @@ useful if you want to control the socket behavior within an async framework. ### Parsers Parser classes provide a way to control how responses from the Redis server -are parsed. redis-py ships with two parse classes, the PythonParse and the +are parsed. redis-py ships with two parser classes, the PythonParser and the HiredisParser. By default, redis-py will attempt to use the HiredisParser if you have the hiredis module installed and will fallback to the PythonParser otherwise. Hiredis is a C library maintained by the core Redis team. Pieter Noordhuis was kind enough to create Python bindings. Using Hiredis can provide up to a -10x speed improvement. The performance increase is most noticeable when -retrieving many pieces of data, such as from a ZRANGE or HGETALL operation. +10x speed improvement in parsing responses from the Redis server. The +performance increase is most noticeable when retrieving many pieces of data, +such as from LRANGE or SMEMBERS operations. Hiredis is available on Pypi, and can be installed via pip or easy_install just like redis-py. @@ -89,14 +90,14 @@ Custom callbacks can be added on a per-instance basis using the set_response_callback method. This method accepts two arguments: a command name and the callback. Callbacks added in this manner are only valid on the instance the callback is added to. If you want to define or override a callback -globally, then you should look into making a subclass and added your callback -to the REDIS_CALLBACKS class dictionary. +globally, you should make a subclass of the Redis client and add your callback +to its REDIS_CALLBACKS class dictionary. Response callbacks take at least one parameter: the response from the Redis server. Keyword arguments may also be accepted in order to further control -how to interpret the response. The keyword arguments are specified during the +how to interpret the response. These keyword arguments are specified during the command's call to execute_command. The ZRANGE implementation demonstrates the -use of response callback keyword arguments using the "withscores" argument. +use of response callback keyword arguments with its "withscores" argument. ## Thread Safety @@ -106,19 +107,15 @@ command execution, and returned to the pool directly after. Command execution never modifies state on the client instance. However, there is one caveat: the Redis SELECT command. The SELECT command -allows you to switch to a separate database on the same Redis server. That -database remains selected until another is selected. This creates a proble in -that connections could be returned to the pool that are now set to a different -database. +allows you to switch the database currently in use by the connection. That +database remains selected until another is selected or until the connection is +closed. This creates an issue in that connections could be returned to the pool +that are connected to a different database. As a result, redis-py does not implement the SELECT command on client instances. -If you use multiple Redis databases, you should create a separate client -instance (and possible a separate connection pool) to each database. - -## Versioning scheme - -redis-py is versioned after Redis. So, for example, redis-py 2.0.0 should -support all the commands available in Redis 2.0.0. +If you use multiple Redis databases within the same application, you should +create a separate client instance (and possibly a separate connection pool) for +each database. ## API Reference @@ -131,20 +128,24 @@ arguments as the official spec. There are a few exceptions noted here: * ZADD: Redis specifies the 'score' argument before 'value'. These were swapped accidentally when being implemented and not discovered until after people were already using it. As of Redis 2.4, ZADD will start supporting variable - arguments. redis-py implements these as python keyword arguments, where the + arguments. redis-py implements these as python keyword arguments where the name is the 'value' and the value is the 'score'. * DEL: 'del' is a reserved keyword in the Python syntax. Therefore redis-py uses 'delete' instead. -* CONFIG GET|SET: These are implemented separately config_get or config_set. +* CONFIG GET|SET: These are implemented separately as config_get or config_set. * MULTI/EXEC: These are implemented as part of the Pipeline class. Calling the pipeline method and specifying use_transaction=True will cause the - pipline to be wrapped with the MULTI and EXEC statements when it is executed. + pipeline to be wrapped with the MULTI and EXEC statements when it is executed. * SUBSCRIBE/LISTEN: Similar to pipelines, PubSub is implemented as a separate class as it places the underlying connection in a state where it can't execute non-pubsub commands. Calling the pubsub method from the Redis client will return a PubSub instance where you can subscribe to channels and listen for messages. You can call PUBLISH from both classes. +## Versioning scheme + +redis-py is versioned after Redis. For example, redis-py 2.0.0 should +support all the commands available in Redis 2.0.0. Author ------ diff --git a/redis/client.py b/redis/client.py index c14499c..14dde9e 100644 --- a/redis/client.py +++ b/redis/client.py @@ -196,7 +196,11 @@ class Redis(object): atomic, pipelines are useful for reducing the back-and-forth overhead between the client and server. """ - return Pipeline(self.connection_pool, transaction, shard_hint) + return Pipeline( + self.connection_pool, + self.response_callbacks, + transaction, + shard_hint) def lock(self, name, timeout=None, sleep=0.1): """ @@ -1170,8 +1174,10 @@ class Pipeline(Redis): ResponseError exceptions, such as those raised when issuing a command on a key of a different datatype. """ - def __init__(self, connection_pool, transaction, shard_hint): + def __init__(self, connection_pool, response_callbacks, transaction, + shard_hint): self.connection_pool = connection_pool + self.response_callbacks = response_callbacks self.transaction = transaction self.shard_hint = shard_hint self.reset() diff --git a/tests/server_commands.py b/tests/server_commands.py index babb98e..9d82eac 100644 --- a/tests/server_commands.py +++ b/tests/server_commands.py @@ -18,6 +18,17 @@ class ServerCommandsTestCase(unittest.TestCase): self.client.flushdb() self.client.connection_pool.disconnect() + def test_response_callbacks(self): + self.assertEquals( + self.client.response_callbacks, + redis.Redis.RESPONSE_CALLBACKS) + self.assertNotEquals( + id(self.client.response_callbacks), + id(redis.Redis.RESPONSE_CALLBACKS)) + self.client.set_response_callback('GET', lambda x: 'static') + self.client.set('a', 'foo') + self.assertEquals(self.client.get('a'), 'static') + # GENERAL SERVER COMMANDS def test_dbsize(self): self.client['a'] = 'foo' @@ -35,7 +46,9 @@ class ServerCommandsTestCase(unittest.TestCase): self.assert_(self.client.set('unicode_string', unicode_string)) self.assertEquals(self.client.get('byte_string'), byte_string) self.assertEquals(self.client.get('integer'), str(integer)) - self.assertEquals(self.client.get('unicode_string').decode('utf-8'), unicode_string) + self.assertEquals( + self.client.get('unicode_string').decode('utf-8'), + unicode_string) def test_getitem_and_setitem(self): self.client['a'] = 'bar' |