]> git.openstreetmap.org Git - osqa.git/blob - forum/settings/base.py
Merge branch 'threadsafe_requestholder' into update_django
[osqa.git] / forum / settings / base.py
1 import django.dispatch
2 from django.utils.encoding import force_unicode, smart_unicode
3 from datetime import datetime, timedelta
4 import logging
5
6 TMP_MINICACHE_SECONDS = 5
7
8 class SettingSet(list):
9     def __init__(self, name, title, description, weight=1000, markdown=False, can_preview=False):
10         self.name = name
11         self.title = title
12         self.description = description
13         self.weight = weight
14         self.markdown = markdown
15         self.can_preview = can_preview
16
17
18 class BaseSetting(object):
19     @classmethod
20     def add_to_class(cls, name):
21         def wrapper(self, *args, **kwargs):
22             return self.value.__getattribute__(name)(*args, **kwargs)
23
24         setattr(cls, name, wrapper)
25
26     def __init__(self, name, default, set=None, field_context=None):
27         self.name = name
28         self.default = default
29         self.field_context = field_context or {}
30
31         self._temp = None
32
33         if set is not None:
34             self.set = set
35             
36             if not set.name in Setting.sets:
37                 Setting.sets[set.name] = set
38
39             Setting.sets[set.name].append(self)
40
41     def __str__(self):
42         return str(self.value)
43
44     def __unicode__(self):
45         return smart_unicode(self.value)
46
47     @property
48     def value(self):
49         if self._temp:
50             v, exp = self._temp
51             if exp + timedelta(seconds=TMP_MINICACHE_SECONDS) > datetime.now():
52                 return v
53
54         from forum.models import KeyValue
55
56         try:
57             kv = KeyValue.objects.get(key=self.name)
58             v = kv.value
59             self._temp = (v, datetime.now() + timedelta(seconds=TMP_MINICACHE_SECONDS))
60             return v
61         except KeyValue.DoesNotExist:
62             self._temp = (self.default, datetime.now() + timedelta(seconds=TMP_MINICACHE_SECONDS))
63             self.save(self.default)
64         except Exception, e:
65             logging.error("Error retrieving setting from database (%s): %s" % (self.name, str(e)))
66             
67         return self.default
68
69     def set_value(self, new_value):
70         new_value = self._parse(new_value)
71         self._temp = None
72         self.save(new_value)
73
74     def save(self, value):
75         from forum.models import KeyValue
76
77         try:
78             kv = KeyValue.objects.get(key=self.name)
79         except KeyValue.DoesNotExist:
80             kv = KeyValue(key=self.name)
81         except Exception, e:
82             logging.error("Error saving setting to database (%s): %s" % (self.name, str(e)))
83             return
84
85         kv.value = value
86         kv.save()
87
88     def to_default(self):
89         self.set_value(self.default)
90
91     def _parse(self, value):
92         if not isinstance(value, self.base_type):
93             try:
94                 return self.base_type(value)
95             except:
96                 pass
97         return value
98
99 class AnyTypeSetting(BaseSetting):
100      def _parse(self, value):
101         return value
102
103
104 class Setting(object):
105     emulators = {}
106     sets = {}
107
108     def __new__(cls, name, default, set=None, field_context=None):
109         if default is None:
110             return AnyTypeSetting(name, default, set, field_context)
111             
112         deftype = type(default)
113
114         if deftype in Setting.emulators:
115             emul = Setting.emulators[deftype]
116         else:
117             emul = type(deftype.__name__ + cls.__name__, (BaseSetting,), {'base_type': deftype})
118
119             fns = [n for n, f in [(p, getattr(deftype, p)) for p in dir(deftype) if not p in dir(cls)] if callable(f)]
120
121             for n in fns:
122                emul.add_to_class(n)
123
124             Setting.emulators[deftype] = emul
125
126         return emul(name, default, set, field_context)