"Fossies" - the Fresh Open Source Software Archive 
Member "pyzor-1.0.0/pyzor/engines/redis_v0.py" (10 Dec 2014, 4666 Bytes) of package /linux/privat/pyzor-1.0.0.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style:
standard) with prefixed line numbers.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "redis_v0.py" see the
Fossies "Dox" file reference documentation.
1 """Redis database engine.
2
3 XXX Deprecated version.
4 """
5
6 import logging
7 import datetime
8 import functools
9
10 try:
11 import redis
12
13 _has_redis = True
14 except ImportError:
15 redis = None
16 _has_redis = False
17
18 from pyzor.engines.common import *
19
20 NAMESPACE = "pyzord.digest"
21
22 encode_date = lambda d: "" if d is None else d.strftime("%Y-%m-%d %H:%M:%S")
23 decode_date = lambda x: None if x == "" else datetime.datetime.strptime(
24 x, "%Y-%m-%d %H:%M:%S")
25
26
27 def safe_call(f):
28 """Decorator that wraps a method for handling database operations."""
29
30 def wrapped_f(self, *args, **kwargs):
31 # This only logs the error and raise the usual Error for consistency,
32 # the redis library takes care of reconnecting and everything else.
33 try:
34 return f(self, *args, **kwargs)
35 except redis.exceptions.RedisError as e:
36 self.log.error("Redis error while calling %s: %s",
37 f.__name__, e)
38 raise DatabaseError("Database temporarily unavailable.")
39
40 return wrapped_f
41
42
43 class RedisDBHandle(BaseEngine):
44 absolute_source = False
45 handles_one_step = False
46
47 log = logging.getLogger("pyzord")
48
49 def __init__(self, fn, mode, max_age=None):
50 self.max_age = max_age
51 # The 'fn' is host,port,password,db. We ignore mode.
52 # We store the authentication details so that we can reconnect if
53 # necessary.
54 fn = fn.split(",")
55 self.host = fn[0] or "localhost"
56 self.port = fn[1] or "6379"
57 self.passwd = fn[2] or None
58 self.db_name = fn[3] or "0"
59 self.db = self._get_new_connection()
60
61 @staticmethod
62 def _encode_record(r):
63 return ("%s,%s,%s,%s,%s,%s" %
64 (r.r_count,
65 encode_date(r.r_entered),
66 encode_date(r.r_updated),
67 r.wl_count,
68 encode_date(r.wl_entered),
69 encode_date(r.wl_updated))).encode()
70
71 @staticmethod
72 def _decode_record(r):
73 if r is None:
74 return Record()
75 fields = r.decode().split(",")
76 return Record(r_count=int(fields[0]),
77 r_entered=decode_date(fields[1]),
78 r_updated=decode_date(fields[2]),
79 wl_count=int(fields[3]),
80 wl_entered=decode_date(fields[4]),
81 wl_updated=decode_date(fields[5]))
82
83 def __iter__(self):
84 for key in self.db.keys(self._real_key("*")):
85 yield key.rsplit(".", 1)[-1]
86
87 def _iteritems(self):
88 for key in self:
89 try:
90 yield key, self[key]
91 except Exception as ex:
92 self.log.warning("Invalid record %s: %s", key, ex)
93
94 def iteritems(self):
95 return self._iteritems()
96
97 def items(self):
98 return list(self._iteritems())
99
100 @staticmethod
101 def _real_key(key):
102 return "%s.%s" % (NAMESPACE, key)
103
104 @safe_call
105 def _get_new_connection(self):
106 if "/" in self.host:
107 return redis.StrictRedis(unix_socket_path=self.host,
108 db=int(self.db_name), password=self.passwd)
109 return redis.StrictRedis(host=self.host, port=int(self.port),
110 db=int(self.db_name), password=self.passwd)
111
112 @safe_call
113 def __getitem__(self, key):
114 return self._decode_record(self.db.get(self._real_key(key)))
115
116 @safe_call
117 def __setitem__(self, key, value):
118 if self.max_age is None:
119 self.db.set(self._real_key(key), self._encode_record(value))
120 else:
121 self.db.setex(self._real_key(key), self.max_age,
122 self._encode_record(value))
123
124 @safe_call
125 def __delitem__(self, key):
126 self.db.delete(self._real_key(key))
127
128 @classmethod
129 def get_prefork_connections(cls, fn, mode, max_age=None):
130 """Yields a number of database connections suitable for a Pyzor
131 pre-fork server.
132 """
133 while True:
134 yield functools.partial(cls, fn, mode, max_age=max_age)
135
136
137 class ThreadedRedisDBHandle(RedisDBHandle):
138 def __init__(self, fn, mode, max_age=None, bound=None):
139 RedisDBHandle.__init__(self, fn, mode, max_age=max_age)
140
141
142 if not _has_redis:
143 handle = DBHandle(single_threaded=None,
144 multi_threaded=None,
145 multi_processing=None,
146 prefork=None)
147 else:
148 handle = DBHandle(single_threaded=RedisDBHandle,
149 multi_threaded=ThreadedRedisDBHandle,
150 multi_processing=None,
151 prefork=RedisDBHandle)