0
# Compatibility and Patching
1
2
Monkey-patch functionality to replace redis-py classes with redislite classes, enabling existing code to use embedded Redis servers without modification.
3
4
## Capabilities
5
6
### Complete Redis Patching
7
8
Patch all Redis classes provided by redislite to enable seamless replacement of redis-py.
9
10
```python { .api }
11
def patch_redis(dbfile=None):
12
"""
13
Patch all the redis classes provided by redislite that have been patched.
14
15
Parameters:
16
dbfile (str, optional): The name of the Redis db file to be used. If
17
provided, all instances of redis.Redis() will share
18
a single instance of the embedded redis server.
19
20
Returns:
21
None
22
"""
23
24
def unpatch_redis():
25
"""
26
Unpatch all the redis classes provided by redislite that have been patched.
27
28
Returns:
29
None
30
"""
31
```
32
33
**Usage Examples:**
34
35
```python
36
import redislite.patch
37
38
# Patch all Redis classes to use redislite
39
redislite.patch.patch_redis('/tmp/shared.db')
40
41
# Now regular redis imports use redislite
42
import redis
43
r = redis.Redis() # Actually creates redislite.Redis instance
44
r.set('key', 'value')
45
46
# Restore original redis classes
47
redislite.patch.unpatch_redis()
48
```
49
50
### Redis Class Patching
51
52
Patch the redis.Redis class specifically with redislite functionality.
53
54
```python { .api }
55
def patch_redis_Redis(dbfile=None):
56
"""
57
Patch the redis module to replace the redis.Redis() class with the
58
redislite enhanced redislite.Redis() class that uses the embedded redis server.
59
60
Parameters:
61
dbfile (str, optional): The name of the Redis db file to be used. If this
62
argument is passed all instances of the redis.Redis
63
class will share a single embedded redis server.
64
65
Returns:
66
None
67
"""
68
69
def unpatch_redis_Redis():
70
"""
71
Unpatch the redis.Redis() class of the redis module and restore the
72
original redis.Redis() class.
73
74
Returns:
75
None
76
"""
77
```
78
79
**Usage Examples:**
80
81
```python
82
import redislite.patch
83
84
# Patch only Redis class
85
redislite.patch.patch_redis_Redis('/tmp/redis.db')
86
87
import redis
88
r = redis.Redis() # Uses redislite.Redis with embedded server
89
r.set('patched', 'true')
90
91
# Check if patching is active
92
from redislite.patch import Redis_Patched
93
print(f"Redis patched: {Redis_Patched}") # True
94
95
# Restore original Redis class
96
redislite.patch.unpatch_redis_Redis()
97
print(f"Redis patched: {Redis_Patched}") # False
98
```
99
100
### StrictRedis Class Patching
101
102
Patch the redis.StrictRedis class specifically with redislite functionality.
103
104
```python { .api }
105
def patch_redis_StrictRedis(dbfile=None):
106
"""
107
Patch the redis module to replace the redis.StrictRedis() class with the
108
redislite enhanced redislite.StrictRedis() class that uses the embedded redis server.
109
110
Parameters:
111
dbfile (str, optional): The name of the Redis db file to be used. If this
112
argument is passed all instances of the redis.Redis
113
class will share a single instance of the embedded
114
redis server.
115
116
Returns:
117
None
118
"""
119
120
def unpatch_redis_StrictRedis():
121
"""
122
Unpatch the redis.StrictRedis() class of the redis module and restore the
123
original redis.StrictRedis() class.
124
125
Returns:
126
None
127
"""
128
```
129
130
**Usage Examples:**
131
132
```python
133
import redislite.patch
134
135
# Patch only StrictRedis class
136
redislite.patch.patch_redis_StrictRedis('/tmp/strict.db')
137
138
import redis
139
r = redis.StrictRedis() # Uses redislite.StrictRedis with embedded server
140
r.set('strict_key', 'strict_value')
141
142
# Check if patching is active
143
from redislite.patch import StrictRedis_Patched
144
print(f"StrictRedis patched: {StrictRedis_Patched}") # True
145
146
# Restore original StrictRedis class
147
redislite.patch.unpatch_redis_StrictRedis()
148
```
149
150
### Compatibility with Third-Party Libraries
151
152
Use redislite with existing libraries that depend on redis-py without code changes.
153
154
**Usage Examples:**
155
156
```python
157
import redislite.patch
158
159
# Patch Redis before importing third-party libraries
160
redislite.patch.patch_redis('/tmp/app_cache.db')
161
162
# Now third-party libraries use embedded Redis
163
import redis_collections
164
import rq
165
from flask_caching import Cache
166
167
# redis_collections will use embedded Redis
168
cache_dict = redis_collections.Dict()
169
cache_dict['app_data'] = {'version': '1.0', 'users': 1000}
170
171
# RQ (Redis Queue) will use embedded Redis
172
from rq import Queue
173
q = Queue() # Uses embedded Redis server
174
175
# Flask-Caching will use embedded Redis
176
from flask import Flask
177
app = Flask(__name__)
178
cache = Cache(app, config={'CACHE_TYPE': 'redis'})
179
180
# All of these use the same embedded Redis instance at /tmp/app_cache.db
181
```
182
183
### Selective Patching
184
185
Apply patches selectively based on application needs.
186
187
**Usage Examples:**
188
189
```python
190
import redislite.patch
191
192
# Patch for testing only
193
def setup_test_environment():
194
redislite.patch.patch_redis() # No dbfile = separate instances
195
196
def teardown_test_environment():
197
redislite.patch.unpatch_redis()
198
199
# Patch for development with shared database
200
def setup_dev_environment():
201
redislite.patch.patch_redis('/tmp/dev_redis.db')
202
203
# Patch specific classes for gradual migration
204
def gradual_migration():
205
# Start with Redis only
206
redislite.patch.patch_redis_Redis('/tmp/migration.db')
207
208
# Later add StrictRedis
209
redislite.patch.patch_redis_StrictRedis('/tmp/migration.db')
210
211
# Conditional patching based on environment
212
import os
213
214
if os.getenv('USE_EMBEDDED_REDIS', 'false').lower() == 'true':
215
redislite.patch.patch_redis(os.getenv('REDIS_DB_FILE', '/tmp/app.db'))
216
```
217
218
### Error Handling and State Management
219
220
Handle patching states and errors gracefully.
221
222
**Usage Examples:**
223
224
```python
225
import redislite.patch
226
227
# Check current patch status
228
def check_patch_status():
229
print(f"Redis patched: {redislite.patch.Redis_Patched}")
230
print(f"StrictRedis patched: {redislite.patch.StrictRedis_Patched}")
231
232
# Safe patching with error handling
233
def safe_patch(dbfile=None):
234
try:
235
if not redislite.patch.Redis_Patched:
236
redislite.patch.patch_redis_Redis(dbfile)
237
print("Redis successfully patched")
238
else:
239
print("Redis already patched")
240
241
if not redislite.patch.StrictRedis_Patched:
242
redislite.patch.patch_redis_StrictRedis(dbfile)
243
print("StrictRedis successfully patched")
244
else:
245
print("StrictRedis already patched")
246
247
except Exception as e:
248
print(f"Patching failed: {e}")
249
250
# Context manager for temporary patching
251
class TemporaryPatch:
252
def __init__(self, dbfile=None):
253
self.dbfile = dbfile
254
self.was_redis_patched = False
255
self.was_strictredis_patched = False
256
257
def __enter__(self):
258
self.was_redis_patched = redislite.patch.Redis_Patched
259
self.was_strictredis_patched = redislite.patch.StrictRedis_Patched
260
261
if not self.was_redis_patched:
262
redislite.patch.patch_redis_Redis(self.dbfile)
263
if not self.was_strictredis_patched:
264
redislite.patch.patch_redis_StrictRedis(self.dbfile)
265
266
return self
267
268
def __exit__(self, exc_type, exc_val, exc_tb):
269
if not self.was_redis_patched:
270
redislite.patch.unpatch_redis_Redis()
271
if not self.was_strictredis_patched:
272
redislite.patch.unpatch_redis_StrictRedis()
273
274
# Usage
275
with TemporaryPatch('/tmp/temp.db'):
276
import redis
277
r = redis.Redis() # Uses embedded server
278
r.set('temp', 'data')
279
# Patches are automatically removed here
280
```
281
282
## Global State Variables
283
284
```python { .api }
285
original_classes: defaultdict # Storage for original Redis classes
286
Redis_Patched: bool # Whether redis.Redis class has been patched
287
StrictRedis_Patched: bool # Whether redis.StrictRedis class has been patched
288
```
289
290
These variables track the current patching state and can be used to check whether classes have been patched before applying or removing patches.