Newer
Older

Lluis Gifre Renom
committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import copy
from redis.client import Redis
class EntityAttributes:
def __init__(self, parent, entity_key_attributes, validators, transcoders={}):
self.__parent = parent
self.__redis_client : Redis = self.__parent.get_context().get_redis_client()
self.__entity_key_attributes = entity_key_attributes.format(**self.__parent.__dict__)
self.__validators = validators
self.__transcoders = transcoders
def validate(self, update_attributes, remove_attributes, attribute_name):
remove_attributes.discard(attribute_name)
value = update_attributes.pop(attribute_name, None)
validator = self.__validators.get(attribute_name)
if not validator(value): raise AttributeError('{} is invalid'.format(attribute_name))
def transcode(self, attribute_name, attribute_value):
transcoder_set = self.__transcoders.get(attribute_name, {})
transcoder = transcoder_set.get(type(attribute_value))
return attribute_value if transcoder is None else transcoder(attribute_value)
def get(self, attributes=[]):
if len(attributes) == 0: # retrieve all
keys_values = self.__redis_client.hgetall(self.__entity_key_attributes).items()
else: # retrieve selected
names = list(attributes)
keys_values = zip(names, self.__redis_client.hmget(self.__entity_key_attributes, attributes))
attributes = {}
for key,value in keys_values:
str_key = key.decode('UTF-8') if isinstance(key, bytes) else key
str_value = value.decode('UTF-8') if isinstance(value, bytes) else value
attributes[str_key] = self.transcode(str_key, str_value)
return attributes
def update(self, update_attributes={}, remove_attributes=[]):
remove_attributes = set(remove_attributes)
copy_update_attributes = copy.deepcopy(update_attributes)
copy_remove_attributes = copy.deepcopy(remove_attributes)
for attribute_name in self.__validators.keys():
self.validate(copy_update_attributes, copy_remove_attributes, attribute_name)
attribute_value = update_attributes.get(attribute_name)
if attribute_value is None: continue
update_attributes[attribute_name] = self.transcode(attribute_name, attribute_value)
if len(copy_update_attributes) > 0:
raise AttributeError('Unexpected update_attributes: {}'.format(str(copy_update_attributes)))
if len(copy_remove_attributes) > 0:
raise AttributeError('Unexpected remove_attributes: {}'.format(str(copy_remove_attributes)))
if len(remove_attributes) > 0:
self.__redis_client.hdel(self.__entity_key_attributes, remove_attributes)
if len(update_attributes) > 0:
self.__redis_client.hmset(self.__entity_key_attributes, update_attributes)
return self
def delete(self, attributes=[]):
if len(attributes) == 0: # delete all
self.__redis_client.delete(self.__entity_key_attributes)
else: # delete selected
self.__redis_client.hdel(self.__entity_key_attributes, attributes)