redis.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. import random
  2. from collections import defaultdict
  3. from mockredis.lock import MockRedisLock
  4. class MockRedis(object):
  5. """Imitate a Redis object so unit tests can run on our Hudson CI server
  6. without needing a real Redis server."""
  7. # The 'Redis' store
  8. redis = defaultdict(dict)
  9. # The pipeline
  10. pipe = None
  11. def __init__(self):
  12. """Initialize the object."""
  13. pass
  14. def type(self, key):
  15. _type = type(self.redis[key])
  16. if _type == dict:
  17. return 'hash'
  18. elif _type == str:
  19. return 'string'
  20. elif _type == set:
  21. return 'set'
  22. elif _type == list:
  23. return 'list'
  24. return None
  25. def get(self, key): # pylint: disable=R0201
  26. """Emulate get."""
  27. # Override the default dict
  28. result = '' if key not in self.redis else self.redis[key]
  29. return result
  30. def keys(self, pattern): # pylint: disable=R0201
  31. """Emulate keys."""
  32. import re
  33. # Make a regex out of pattern. The only special matching character we look for is '*'
  34. regex = '^' + pattern.replace('*', '.*') + '$'
  35. # Find every key that matches the pattern
  36. result = [key for key in self.redis.keys() if re.match(regex, key)]
  37. return result
  38. def lock(self, key, timeout=0, sleep=0): # pylint: disable=W0613
  39. """Emulate lock."""
  40. return MockRedisLock(self, key)
  41. def pipeline(self):
  42. """Emulate a redis-python pipeline."""
  43. # Prevent a circular import
  44. from mockredis.pipeline import MockRedisPipeline
  45. if self.pipe == None:
  46. self.pipe = MockRedisPipeline(self.redis)
  47. return self.pipe
  48. def delete(self, key): # pylint: disable=R0201
  49. """Emulate delete."""
  50. if key in self.redis:
  51. del self.redis[key]
  52. def exists(self, key): # pylint: disable=R0201
  53. """Emulate get."""
  54. return key in self.redis
  55. def execute(self):
  56. """Emulate the execute method. All piped commands are executed immediately
  57. in this mock, so this is a no-op."""
  58. pass
  59. def hget(self, hashkey, attribute): # pylint: disable=R0201
  60. """Emulate hget."""
  61. # Return '' if the attribute does not exist
  62. result = self.redis[hashkey][attribute] if attribute in self.redis[hashkey] \
  63. else ''
  64. return result
  65. def hgetall(self, hashkey): # pylint: disable=R0201
  66. """Emulate hgetall."""
  67. return self.redis[hashkey]
  68. def hlen(self, hashkey): # pylint: disable=R0201
  69. """Emulate hlen."""
  70. return len(self.redis[hashkey])
  71. def hmset(self, hashkey, value): # pylint: disable=R0201
  72. """Emulate hmset."""
  73. # Iterate over every key:value in the value argument.
  74. for attributekey, attributevalue in value.items():
  75. self.redis[hashkey][attributekey] = attributevalue
  76. def hset(self, hashkey, attribute, value): # pylint: disable=R0201
  77. """Emulate hset."""
  78. self.redis[hashkey][attribute] = value
  79. def lrange(self, key, start, stop):
  80. """Emulate lrange."""
  81. # Does the set at this key already exist?
  82. if key in self.redis:
  83. # Yes, add this to the list
  84. return self.redis[key][start:stop + 1]
  85. else:
  86. # No, override the defaultdict's default and create the list
  87. self.redis[key] = list([])
  88. def rpush(self, key, *args):
  89. """Emulate rpush."""
  90. # Does the set at this key already exist?
  91. if not key in self.redis:
  92. self.redis[key] = list([])
  93. for arg in args:
  94. self.redis[key].append(arg)
  95. def sadd(self, key, value): # pylint: disable=R0201
  96. """Emulate sadd."""
  97. # Does the set at this key already exist?
  98. if key in self.redis:
  99. # Yes, add this to the set
  100. self.redis[key].add(value)
  101. else:
  102. # No, override the defaultdict's default and create the set
  103. self.redis[key] = set([value])
  104. def srem(self, key, member):
  105. """Emulate a srem."""
  106. self.redis[key].discard(member)
  107. return self
  108. def srandmember(self, key):
  109. """Emulate a srandmember."""
  110. length = len(self.redis[key])
  111. rand_index = random.randint(0, length - 1)
  112. i = 0
  113. for set_item in self.redis[key]:
  114. if i == rand_index:
  115. return set_item
  116. def smembers(self, key): # pylint: disable=R0201
  117. """Emulate smembers."""
  118. return self.redis[key]
  119. def flushdb(self):
  120. self.redis.clear()
  121. def mock_redis_client():
  122. """Mock common.util.redis_client so we can return a MockRedis object
  123. instead of a Redis object."""
  124. return MockRedis()