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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import django.dispatch
from django.utils.encoding import force_unicode, smart_unicode
from datetime import datetime, timedelta
import logging
TMP_MINICACHE_SECONDS = 5
class SettingSet(list):
def __init__(self, name, title, description, weight=1000, markdown=False, can_preview=False):
self.name = name
self.title = title
self.description = description
self.weight = weight
self.markdown = markdown
self.can_preview = can_preview
class BaseSetting(object):
@classmethod
def add_to_class(cls, name):
def wrapper(self, *args, **kwargs):
return self.value.__getattribute__(name)(*args, **kwargs)
setattr(cls, name, wrapper)
def __init__(self, name, default, set=None, field_context=None):
self.name = name
self.default = default
self.field_context = field_context or {}
self._temp = None
if set is not None:
self.set = set
if not set.name in Setting.sets:
Setting.sets[set.name] = set
Setting.sets[set.name].append(self)
def __str__(self):
return str(self.value)
def __unicode__(self):
return smart_unicode(self.value)
@property
def value(self):
if self._temp:
v, exp = self._temp
if exp + timedelta(seconds=TMP_MINICACHE_SECONDS) > datetime.now():
return v
from forum.models import KeyValue
try:
kv = KeyValue.objects.get(key=self.name)
v = kv.value
self._temp = (v, datetime.now() + timedelta(seconds=TMP_MINICACHE_SECONDS))
return v
except KeyValue.DoesNotExist:
self._temp = (self.default, datetime.now() + timedelta(seconds=TMP_MINICACHE_SECONDS))
self.save(self.default)
except Exception, e:
logging.error("Error retrieving setting from database (%s): %s" % (self.name, str(e)))
return self.default
def set_value(self, new_value):
new_value = self._parse(new_value)
self._temp = None
self.save(new_value)
def save(self, value):
from forum.models import KeyValue
try:
kv = KeyValue.objects.get(key=self.name)
except KeyValue.DoesNotExist:
kv = KeyValue(key=self.name)
except Exception, e:
logging.error("Error saving setting to database (%s): %s" % (self.name, str(e)))
return
kv.value = value
kv.save()
def to_default(self):
self.set_value(self.default)
def _parse(self, value):
if not isinstance(value, self.base_type):
try:
return self.base_type(value)
except:
pass
return value
class AnyTypeSetting(BaseSetting):
def _parse(self, value):
return value
class Setting(object):
emulators = {}
sets = {}
def __new__(cls, name, default, set=None, field_context=None):
if default is None:
return AnyTypeSetting(name, default, set, field_context)
deftype = type(default)
if deftype in Setting.emulators:
emul = Setting.emulators[deftype]
else:
emul = type(deftype.__name__ + cls.__name__, (BaseSetting,), {'base_type': deftype})
fns = [n for n, f in [(p, getattr(deftype, p)) for p in dir(deftype) if not p in dir(cls)] if callable(f)]
for n in fns:
emul.add_to_class(n)
Setting.emulators[deftype] = emul
return emul(name, default, set, field_context)