|
11 | 11 |
|
12 | 12 | from mockredis.clock import SystemClock
|
13 | 13 | from mockredis.lock import MockRedisLock
|
14 |
| -from mockredis.exceptions import RedisError, ResponseError |
| 14 | +from mockredis.exceptions import RedisError, ResponseError, WatchError |
15 | 15 | from mockredis.pipeline import MockRedisPipeline
|
16 | 16 | from mockredis.script import Script
|
17 | 17 | from mockredis.sortedset import SortedSet
|
@@ -75,6 +75,30 @@ def pipeline(self, transaction=True, shard_hint=None):
|
75 | 75 | """Emulate a redis-python pipeline."""
|
76 | 76 | return MockRedisPipeline(self, transaction, shard_hint)
|
77 | 77 |
|
| 78 | + def transaction(self, func, *watches, **kwargs): |
| 79 | + """ |
| 80 | + Convenience method for executing the callable `func` as a transaction |
| 81 | + while watching all keys specified in `watches`. The 'func' callable |
| 82 | + should expect a single argument which is a Pipeline object. |
| 83 | +
|
| 84 | + Copied directly from redis-py. |
| 85 | + """ |
| 86 | + shard_hint = kwargs.pop('shard_hint', None) |
| 87 | + value_from_callable = kwargs.pop('value_from_callable', False) |
| 88 | + watch_delay = kwargs.pop('watch_delay', None) |
| 89 | + with self.pipeline(True, shard_hint) as pipe: |
| 90 | + while 1: |
| 91 | + try: |
| 92 | + if watches: |
| 93 | + pipe.watch(*watches) |
| 94 | + func_value = func(pipe) |
| 95 | + exec_value = pipe.execute() |
| 96 | + return func_value if value_from_callable else exec_value |
| 97 | + except WatchError: |
| 98 | + if watch_delay is not None and watch_delay > 0: |
| 99 | + time.sleep(watch_delay) |
| 100 | + continue |
| 101 | + |
78 | 102 | def watch(self, *argv, **kwargs):
|
79 | 103 | """
|
80 | 104 | Mock does not support command buffering so watch
|
|
0 commit comments