Commits

Hynek Cernoch committed 191a6d8 Draft Merge

Merged a Big refactoring CraigDS/django-livesettings. Implemented issue #24.

code https://github.com/craigds/django-livesettings
- Removed dependency on keyedcache
- Changed ConfigurationSettings from singleton to module level instance
- Replaced catchall except blocks by explicit exceptions
- Removed table livesettings_longsetting by SOUTH

  • Participants
  • Parent commits 41daf73, 3681e76

Comments (0)

Files changed (26)

File docs/usage.rst

File contents unchanged.

File livesettings/__init__.py

 
 """
 
-from functions import *
-from models import *
-from values import *
+from livesettings.exceptions import *
+from livesettings.functions import *
+from livesettings.models import *
+from livesettings.values import *

File livesettings/caching.py

+from django.conf import settings
+from django.core.cache import cache
+from django.core.exceptions import ImproperlyConfigured
+
+__all__ = ('USE_KEYEDCACHE', 'cache_key', 'cache_get', 'cache_set', 'NotCachedError', 'CachedObjectMixin')
+
+USE_KEYEDCACHE = getattr(settings, 'LIVESETTINGS_USE_KEYEDCACHE', True)
+if USE_KEYEDCACHE:
+    try:
+        import keyedcache
+    except ImportError, e:
+        raise ImproperlyConfigured("LIVESETTINGS_USE_KEYEDCACHE is %r but couldn't import keyedcache: %r" % (
+            USE_KEYEDCACHE, e
+        ))
+    
+    from keyedcache import cache_key, cache_get, cache_set, NotCachedError
+    from keyedcache.models import CachedObjectMixin
+else:
+    # provide the same API as keyedcache but skip the middleman and just
+    # defer directly to the django cache backend.
+    
+    class NotCachedError(Exception):
+        pass
+    
+    def cache_key(*args):
+        return ':'.join([unicode(val) for val in args])
+    
+    def cache_get(key):
+        val = cache.get(key)
+        if val is None:
+            raise NotCachedError(key)
+        return val
+    
+    def cache_set(key, value):
+        cache.set(key, value, getattr(settings, 'CACHE_TIMEOUT', 300))
+    
+    def cache_delete(key):
+        cache.delete(key)
+    
+    class CachedObjectMixin(object):
+        def cache_delete(self, *args, **kwargs):
+            key = self.cache_key(*args, **kwargs)
+            cache_delete(key)
+    
+        def cache_get(self, *args, **kwargs):
+            key = self.cache_key(*args, **kwargs)
+            return cache.get(key)
+    
+        def cache_key(self, *args, **kwargs):
+            keys = [self.__class__.__name__, self]
+            keys.extend(args)
+            return cache_key(*keys)
+        
+        def cache_reset(self):
+            self.cache_delete()
+            self.cache_set()
+        
+        def cache_set(self, *args, **kwargs):
+            val = kwargs.pop('value', self)
+            key = self.cache_key(*args, **kwargs)
+            cache_set(key, value=val)
+        
+        def is_cached(self, *args, **kwargs):
+            return self.cache_get(*args, **kwargs) is not None

File livesettings/exceptions.py

+
+class SettingNotSet(Exception):
+    def __init__(self, k, cachekey=None):
+        self.key = k
+        self.cachekey = cachekey
+        self.args = [self.key, self.cachekey]

File livesettings/functions.py

 from django.utils.translation import ugettext
 from livesettings import values
-from livesettings.models import SettingNotSet
+from livesettings.exceptions import SettingNotSet
 from livesettings.utils import is_string_like
 
 import logging
+import warnings
 
 log = logging.getLogger('configuration')
 
 _NOTSET = object()
 
 class ConfigurationSettings(object):
-    """A singleton manager for ConfigurationSettings"""
+    _instance = None
+    
+    def __new__(cls, *args, **kwargs):
+        # for backwards compatibility, make this a singleton.
+        if ConfigurationSettings._instance is None:
+            instance = ConfigurationSettings._instance = super(ConfigurationSettings, cls).__new__(cls, *args, **kwargs)
+            instance.settings = values.SortedDotDict()
+            instance.prereg = {}
+        else:
+            warnings.warn("The ConfigurationSettings singleton is deprecated. Use livesettings.configuration_settings instead", DeprecationWarning)
+        return ConfigurationSettings._instance
+    
+    def __getitem__(self, key):
+        """Get an element either by ConfigurationGroup object or by its key"""
+        key = self._resolve_key(key)
+        return self.settings.get(key)
 
-    class __impl(object):
-        def __init__(self):
-            self.settings = values.SortedDotDict()
-            self.prereg = {}
+    def __getattr__(self, key):
+        """Get an element either by ConfigurationGroup object or by its key"""
+        try:
+            return self[key]
+        except KeyError:
+            raise AttributeError, key
 
-        def __getitem__(self, key):
-            """Get an element either by ConfigurationGroup object or by its key"""
-            key = self._resolve_key(key)
-            return self.settings.get(key)
+    def __iter__(self):
+        for v in self.groups():
+            yield v
 
-        def __getattr__(self, key):
-            """Get an element either by ConfigurationGroup object or by its key"""
-            try:
-                return self[key]
-            except:
-                raise AttributeError, key
+    def __len__(self):
+        return len(self.settings)
 
-        def __iter__(self):
-            for v in self.groups():
-                yield v
+    def __contains__(self, key):
+        key = self._resolve_key(key)
+        return key in self.settings
 
-        def __len__(self):
-            return len(self.settings)
+    def _resolve_key(self, raw):
+        if is_string_like(raw):
+            key = raw
 
-        def __contains__(self, key):
-            try:
-                key = self._resolve_key(key)
-                return self.settings.has_key(key)
-            except:
-                return False
+        elif isinstance(raw, values.ConfigurationGroup):
+            key = raw.key
 
-        def _resolve_key(self, raw):
-            if is_string_like(raw):
-                key = raw
+        else:
+            group = self.groups()[raw]
+            key = group.key
 
-            elif isinstance(raw, values.ConfigurationGroup):
-                key = raw.key
+        return key
 
-            else:
-                group = self.groups()[raw]
-                key = group.key
-
-            return key
-
-        def get_config(self, group, key):
-            try:
-                if isinstance(group, values.ConfigurationGroup):
-                    group = group.key
-
-                cg = self.settings.get(group, None)
-                if not cg:
-                    raise SettingNotSet('%s config group does not exist' % group)
-
-                else:
-                    return cg[key]
-            except KeyError:
-                raise SettingNotSet('%s.%s' % (group, key))
-
-        def groups(self):
-            """Return ordered list"""
-            return self.settings.values()
-
-        def has_config(self, group, key):
+    def get_config(self, group, key):
+        try:
             if isinstance(group, values.ConfigurationGroup):
                 group = group.key
 
-            cfg = self.settings.get(group, None)
-            if cfg and key in cfg:
-                return True
+            cg = self.settings.get(group, None)
+            if not cg:
+                raise SettingNotSet('%s config group does not exist' % group)
+
             else:
-                return False
+                return cg[key]
+        except KeyError:
+            raise SettingNotSet('%s.%s' % (group, key))
+    
+    def groups(self):
+        """Return ordered list"""
+        values = self.settings.values()
+        values.sort()
+        return values
 
-        def preregister_choice(self, group, key, choice):
-            """Setup a choice for a group/key which hasn't been instantiated yet."""
-            k = (group, key)
-            if self.prereg.has_key(k):
-                self.prereg[k].append(choice)
-            else:
-                self.prereg[k] = [choice]
+    def has_config(self, group, key):
+        if isinstance(group, values.ConfigurationGroup):
+            group = group.key
 
-        def register(self, value):
-            g = value.group
-            if not isinstance(g, values.ConfigurationGroup):
-                raise ValueError('value.group should be an instance of ConfigurationGroup')
+        cfg = self.settings.get(group, None)
+        if cfg and key in cfg:
+            return True
+        else:
+            return False
 
-            groupkey = g.key
-            valuekey = value.key
+    def preregister_choice(self, group, key, choice):
+        """Setup a choice for a group/key which hasn't been instantiated yet."""
+        k = (group, key)
+        if self.prereg.has_key(k):
+            self.prereg[k].append(choice)
+        else:
+            self.prereg[k] = [choice]
 
-            k = (groupkey, valuekey)
-            if self.prereg.has_key(k):
-                for choice in self.prereg[k]:
-                    value.add_choice(choice)
+    def register(self, value):
+        g = value.group
+        if not isinstance(g, values.ConfigurationGroup):
+            raise ValueError('value.group should be an instance of ConfigurationGroup')
 
-            if not groupkey in self.settings:
-                self.settings[groupkey] = g
+        groupkey = g.key
+        valuekey = value.key
 
-            self.settings[groupkey][valuekey] = value
+        k = (groupkey, valuekey)
+        if self.prereg.has_key(k):
+            for choice in self.prereg[k]:
+                value.add_choice(choice)
 
-            return value
+        if not groupkey in self.settings:
+            self.settings[groupkey] = g
 
-    __instance = None
+        self.settings[groupkey][valuekey] = value
 
-    def __init__(self):
-        if ConfigurationSettings.__instance is None:
-            ConfigurationSettings.__instance = ConfigurationSettings.__impl()
-            #ConfigurationSettings.__instance.load_app_configurations()
-
-        self.__dict__['_ConfigurationSettings__instance'] = ConfigurationSettings.__instance
-
-    def __getattr__(self, attr):
-            """ Delegate access to implementation """
-            return getattr(self.__instance, attr)
-
-    def __getitem__(self, key):
-        return self.__instance[key]
-
-    def __len__(self):
-        return len(self.__instance)
-
-    def __setattr__(self, attr, value):
-        """ Delegate access to implementation """
-        return setattr(self.__instance, attr, value)
-
+        return value
+    
     def __unicode__(self):
         return u"ConfigurationSettings: " + unicode(self.groups())
 
+configuration_settings = ConfigurationSettings()
+
+
 def config_exists(group, key):
     """Test to see if a setting has been registered"""
 
-    return ConfigurationSettings().has_config(group, key)
+    return configuration_settings.has_config(group, key)
 
 def config_get(group, key):
     """Get a configuration setting"""
     try:
-        return ConfigurationSettings().get_config(group, key)
+        return configuration_settings.get_config(group, key)
     except SettingNotSet:
         log.debug('SettingNotSet: %s.%s', group, key)
         raise
 
 def config_get_group(group):
-    return ConfigurationSettings()[group]
+    return configuration_settings[group]
 
 def config_collect_values(group, groupkey, key, unique=True, skip_missing=True):
     """Look up (group, groupkey) from config, then take the values returned and
     for g in groups:
         try:
             ret.append(config_value(g, key))
-        except KeyError, ke:
+        except KeyError:
             if not skip_missing:
                 raise SettingNotSet('No config %s.%s' % (g, key))
 
     Parameters:
         -A Value
     """
-    return ConfigurationSettings().register(value)
+    return configuration_settings.register(value)
 
 def config_register_list(*args):
     for value in args:
         raw = config_value(group, key)
     except SettingNotSet:
         pass
-    except ImportError, e:
+    except ImportError:
         log.warn("Error getting %s.%s, OK if you are in SyncDB.", group, key)
 
     return raw
         cfg = config_get(group, key)
         cfg.add_choice(choice)
     else:
-        ConfigurationSettings().preregister_choice(group, key, choice)
+        configuration_settings.preregister_choice(group, key, choice)

File livesettings/migrations/0001_initial.py

+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        
+        # Adding model 'Setting'
+        db.create_table('livesettings_setting', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('site', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['sites.Site'])),
+            ('group', self.gf('django.db.models.fields.CharField')(max_length=100)),
+            ('key', self.gf('django.db.models.fields.CharField')(max_length=100)),
+            ('value', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True)),
+        ))
+        db.send_create_signal('livesettings', ['Setting'])
+
+        # Adding unique constraint on 'Setting', fields ['site', 'group', 'key']
+        db.create_unique('livesettings_setting', ['site_id', 'group', 'key'])
+
+        # Adding model 'LongSetting'
+        db.create_table('livesettings_longsetting', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('site', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['sites.Site'])),
+            ('group', self.gf('django.db.models.fields.CharField')(max_length=100)),
+            ('key', self.gf('django.db.models.fields.CharField')(max_length=100)),
+            ('value', self.gf('django.db.models.fields.TextField')(blank=True)),
+        ))
+        db.send_create_signal('livesettings', ['LongSetting'])
+
+        # Adding unique constraint on 'LongSetting', fields ['site', 'group', 'key']
+        db.create_unique('livesettings_longsetting', ['site_id', 'group', 'key'])
+
+
+    def backwards(self, orm):
+        
+        # Removing unique constraint on 'LongSetting', fields ['site', 'group', 'key']
+        db.delete_unique('livesettings_longsetting', ['site_id', 'group', 'key'])
+
+        # Removing unique constraint on 'Setting', fields ['site', 'group', 'key']
+        db.delete_unique('livesettings_setting', ['site_id', 'group', 'key'])
+
+        # Deleting model 'Setting'
+        db.delete_table('livesettings_setting')
+
+        # Deleting model 'LongSetting'
+        db.delete_table('livesettings_longsetting')
+
+
+    models = {
+        'livesettings.longsetting': {
+            'Meta': {'unique_together': "(('site', 'group', 'key'),)", 'object_name': 'LongSetting'},
+            'group': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}),
+            'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
+        },
+        'livesettings.setting': {
+            'Meta': {'unique_together': "(('site', 'group', 'key'),)", 'object_name': 'Setting'},
+            'group': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}),
+            'value': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'})
+        },
+        'sites.site': {
+            'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"},
+            'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        }
+    }
+
+    complete_apps = ['livesettings']

File livesettings/migrations/0002_migrate_longsettings.py

+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Changing field 'Setting.value'
+        db.alter_column('livesettings_setting', 'value', self.gf('django.db.models.fields.TextField')())
+        
+        # turn longsettings into settings
+        for s in orm['livesettings.longsetting'].objects.all():
+            orm['livesettings.setting'].objects.filter(site__id=s.site_id, group=s.group, key=s.key).delete()
+            orm['livesettings.setting'].objects.create(
+                site_id=s.site_id,
+                group=s.group,
+                key=s.key,
+                value=s.value
+            )
+
+    def backwards(self, orm):
+        for s in orm['livesettings.setting'].objects.all():
+            if len(s.value) > 255:
+                s.delete()
+        
+        # Changing field 'Setting.value'
+        db.alter_column('livesettings_setting', 'value', self.gf('django.db.models.fields.CharField')(max_length=255))
+
+
+    models = {
+        'livesettings.longsetting': {
+            'Meta': {'unique_together': "(('site', 'group', 'key'),)", 'object_name': 'LongSetting'},
+            'group': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}),
+            'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
+        },
+        'livesettings.setting': {
+            'Meta': {'unique_together': "(('site', 'group', 'key'),)", 'object_name': 'Setting'},
+            'group': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}),
+            'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
+        },
+        'sites.site': {
+            'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"},
+            'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        }
+    }
+
+    complete_apps = ['livesettings']

File livesettings/migrations/0003_drop_longsettings.py

+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        
+        # Removing unique constraint on 'LongSetting', fields ['site', 'group', 'key']
+        db.delete_unique('livesettings_longsetting', ['site_id', 'group', 'key'])
+
+        # Deleting model 'LongSetting'
+        db.delete_table('livesettings_longsetting')
+
+
+    def backwards(self, orm):
+        
+        # Adding model 'LongSetting'
+        db.create_table('livesettings_longsetting', (
+            ('group', self.gf('django.db.models.fields.CharField')(max_length=100)),
+            ('site', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['sites.Site'])),
+            ('value', self.gf('django.db.models.fields.TextField')(blank=True)),
+            ('key', self.gf('django.db.models.fields.CharField')(max_length=100)),
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+        ))
+        db.send_create_signal('livesettings', ['LongSetting'])
+
+        # Adding unique constraint on 'LongSetting', fields ['site', 'group', 'key']
+        db.create_unique('livesettings_longsetting', ['site_id', 'group', 'key'])
+
+
+    models = {
+        'livesettings.setting': {
+            'Meta': {'unique_together': "(('site', 'group', 'key'),)", 'object_name': 'Setting'},
+            'group': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}),
+            'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
+        },
+        'sites.site': {
+            'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"},
+            'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        }
+    }
+
+    complete_apps = ['livesettings']

File livesettings/migrations/__init__.py

Empty file added.

File livesettings/models.py

 from django.db import models, connection, DatabaseError
 from django.db.models import loading
 from django.utils.translation import ugettext_lazy as _
-from keyedcache import cache_key, cache_get, cache_set, NotCachedError
-from keyedcache.models import CachedObjectMixin
+from livesettings.caching import cache_key, cache_get, cache_set, NotCachedError, CachedObjectMixin
+from livesettings.exceptions import SettingNotSet
 from livesettings.overrides import get_overrides
 import logging
 
 log = logging.getLogger('configuration.models')
 
-__all__ = ['SettingNotSet', 'Setting', 'LongSetting', 'find_setting']
+__all__ = ['SettingNotSet', 'Setting', 'find_setting']
 
 try:
     is_site_initializing
-except:
+except NameError:
     is_site_initializing = True  # until the first success find "django_site" table, by any thread
     is_first_warn = True
 
     return siteid
 
 def find_setting(group, key, site=None):
-    """Get a setting or longsetting by group and key, cache and return it."""
+    """Get a setting by group and key, cache and return it."""
        
     siteid = _safe_get_siteid(site)
     setting = None
                     setting = Setting.objects.get(site__id__exact=siteid, key__exact=key, group__exact=group)
 
                 except Setting.DoesNotExist:
-                    # maybe it is a "long setting"
-                    try:
-                        setting = LongSetting.objects.get(site__id__exact=siteid, key__exact=key, group__exact=group)
-           
-                    except LongSetting.DoesNotExist:
-                        pass
-            
-                cache_set(ck, value=setting)
+                    pass
+                else:
+                    setting.cache_set()
 
     else:
         grp = overrides.get(group, None)
 
     return setting
 
-class SettingNotSet(Exception):    
-    def __init__(self, k, cachekey=None):
-        self.key = k
-        self.cachekey = cachekey
-        self.args = [self.key, self.cachekey]
-
 class SettingManager(models.Manager):
     def get_query_set(self):
         all = super(SettingManager, self).get_query_set()
         self.value = value
         
     def cache_key(self, *args, **kwargs):
-        return cache_key('OverrideSetting', self.site, self.group, self.key)
+        return cache_key('OverrideSetting', self.site_id, self.group, self.key)
         
     def delete(self):
         pass
     site = models.ForeignKey(Site, verbose_name=_('Site'))
     group = models.CharField(max_length=100, blank=False, null=False)
     key = models.CharField(max_length=100, blank=False, null=False)
-    value = models.CharField(max_length=255, blank=True)
+    value = models.TextField(blank=True)
 
     objects = SettingManager()
 
         return self.id is not None
 
     def cache_key(self, *args, **kwargs):
-        return cache_key('Setting', self.site, self.group, self.key)
+        return cache_key('Setting', self.site_id, self.group, self.key)
 
     def delete(self):
         self.cache_delete()
         
     class Meta:
         unique_together = ('site', 'group', 'key')
-
-
-class LongSettingManager(models.Manager):
-    def get_query_set(self):
-        all = super(LongSettingManager, self).get_query_set()
-        siteid = _safe_get_siteid(None)
-        return all.filter(site__id__exact=siteid)
-
-class LongSetting(models.Model, CachedObjectMixin):
-    """A Setting which can handle more than 255 characters"""
-    site = models.ForeignKey(Site, verbose_name=_('Site'))
-    group = models.CharField(max_length=100, blank=False, null=False)
-    key = models.CharField(max_length=100, blank=False, null=False)
-    value = models.TextField(blank=True)
-
-    objects = LongSettingManager()
-
-    def __nonzero__(self):
-        return self.id is not None
-
-    def cache_key(self, *args, **kwargs):
-        # note same cache pattern as Setting.  This is so we can look up in one check.
-        # they can't overlap anyway, so this is moderately safe.  At the worst, the 
-        # Setting will override a LongSetting.
-        return cache_key('Setting', self.site, self.group, self.key)
-
-    def delete(self):
-        self.cache_delete()
-        super(LongSetting, self).delete()
-
-    def save(self, force_insert=False, force_update=False):
-        try:
-            site = self.site
-        except Site.DoesNotExist:
-            self.site = Site.objects.get_current()
-        super(LongSetting, self).save(force_insert=force_insert, force_update=force_update)
-        self.cache_set()
-        
-    class Meta:
-        unique_together = ('site', 'group', 'key')
-    

File livesettings/overrides.py

 
 from django.conf import settings as djangosettings
 from django.contrib.sites.models import Site
-import logging
 
 __all__ = ['get_overrides']
 
         try:
             site = Site.objects.get_current()
             siteid = site.id
+        
+        # FIXME: why the catchall except? What could be thrown here?
         except:
             siteid = djangosettings.SITE_ID
     else:

File livesettings/templatetags/config_tags.py

 from django.core import urlresolvers
 from livesettings import config_value
 from livesettings.utils import url_join
+from livesettings.exceptions import SettingNotSet
 import logging
 
 log = logging.getLogger('configuration.config_tags')
     args = option.split('.')
     try:
         val = config_value(*args)
-    except:
+    except SettingNotSet:
         log.warn('config_boolean tag: Tried to look up config setting "%s", got SettingNotSet, returning False', option)
         val = False
     if val:

File livesettings/tests.py

 from django.conf import settings as djangosettings
 from django.core.urlresolvers import reverse
 from django.test import TestCase
-import keyedcache
 import livesettings
 from livesettings import *
 import logging
 class ConfigurationTestSettings(TestCase):
 
     def setUp(self):
-        # clear out cache from previous runs
-        keyedcache.cache_delete()
         g = ConfigurationGroup('test2','test2')
         self.g = g
         config_register(StringValue(g, 's1'))
         self.assert_(c.update(20))
         self.assertEqual(c.value, 20)
         try:
-            s = c.setting
+            c.setting
         except SettingNotSet:
             self.fail("Should have a setting now")
 
         self.assertEqual(c.value, 10)
 
         try:
-            s = c.setting
+            c.setting
             self.fail('Should throw SettingNotSet')
         except SettingNotSet:
             pass
 
 class ConfigTestDotAccess(TestCase):
     def setUp(self):
-        # clear out cache from previous runs
-        keyedcache.cache_delete()
-
         g = ConfigurationGroup('test3','test3')
         self.g = g
-        c1 = config_register(BooleanValue(g, 's1', default=True))
+        config_register(BooleanValue(g, 's1', default=True))
         c2 = config_register(IntegerValue(g, 's2', default=10))
         c2.update(100)
 
     def testDotAccess(self):
-        self.assert_(ConfigurationSettings().test3.s1.value)
-        self.assertEqual(ConfigurationSettings().test3.s2.value, 100)
+        self.assert_(configuration_settings.test3.s1.value)
+        self.assertEqual(configuration_settings.test3.s2.value, 100)
 
     def testSettingProperty(self):
         c = config_get('test3','s2')
 
 class ConfigTestModuleValue(TestCase):
     def setUp(self):
-        # clear out cache from previous runs
-        keyedcache.cache_delete()
-
         g = ConfigurationGroup('modules','module test')
         self.g = g
         self.c = config_register(ModuleValue(g, 'test'))
 
 class ConfigTestSortOrder(TestCase):
     def setUp(self):
-        # clear out cache from previous runs
-        keyedcache.cache_delete()
-
         g1 = ConfigurationGroup('group1', 'Group 1', ordering=-1001)
         g2 = ConfigurationGroup('group2', 'Group 2', ordering=-1002)
         g3 = ConfigurationGroup('group3', 'Group 3', ordering=-1003)
         self.g3c3 = config_register(IntegerValue(g3, 'c3'))
 
     def testGroupOrdering(self):
-        mgr = ConfigurationSettings()
+        mgr = configuration_settings
         self.assertEqual(mgr[2].key, self.g1.key)
         self.assertEqual(mgr[1].key, self.g2.key)
         self.assertEqual(mgr[0].key, self.g3.key)
 class TestMultipleValues(TestCase):
 
     def setUp(self):
-        # clear out cache from previous runs
-        keyedcache.cache_delete()
-
         g1 = ConfigurationGroup('m1', 'Multiple Group 1', ordering=1000)
         self.g1 = g1
 
 class TestMultipleValuesWithDefault(TestCase):
 
     def setUp(self):
-        # clear out cache from previous runs
-        keyedcache.cache_delete()
-
         g1 = ConfigurationGroup('mv2', 'Multiple Group 2', ordering=1000)
         self.g1 = g1
 
 class ConfigTestRequires(TestCase):
 
     def setUp(self):
-        # clear out cache from previous runs
-        keyedcache.cache_delete()
-
         g1 = ConfigurationGroup('req1', 'Requirements 1', ordering=1000)
 
         self.g1 = g1
 class ConfigTestRequiresChoices(TestCase):
 
     def setUp(self):
-        # clear out cache from previous runs
-        keyedcache.cache_delete()
-
         g1 = ConfigurationGroup('req2', 'Requirements 2', ordering=1000)
 
         self.g1 = g1
 class ConfigTestRequiresValue(TestCase):
 
     def setUp(self):
-        # clear out cache from previous runs
-        keyedcache.cache_delete()
-
         g1 = ConfigurationGroup('reqval', 'Requirements 3', ordering=1000)
 
         self.g1 = g1
 
 class ConfigTestGroupRequires(TestCase):
     def setUp(self):
-        # clear out cache from previous runs
-        keyedcache.cache_delete()
-
         choices1 = config_register(MultipleStringValue(BASE_GROUP, 'groupchoice', ordering=1))
         choices2 = config_register(MultipleStringValue(BASE_GROUP, 'groupchoice2', ordering=1))
 
 
 class ConfigCollectGroup(TestCase):
     def setUp(self):
-        keyedcache.cache_delete()
         choices = config_register(MultipleStringValue(BASE_GROUP, 'collect', ordering=1))
         self.choices = choices
 
 
         self.assertEqual(v, ['set a', 'set d'])
 
-class LongSettingTest(TestCase):
-    def setUp(self):
-        keyedcache.cache_delete()
-        wide = config_register(LongStringValue(BASE_GROUP, 'LONG', ordering=1, default="woot"))
-        self.wide = wide
-        self.wide.update('*' * 1000)
-
-    def testLongStorage(self):
-        w = config_value('BASE', 'LONG')
-        self.assertEqual(len(w), 1000)
-        self.assertEqual(w, '*'*1000)
-
-    def testShortInLong(self):
-        self.wide.update("test")
-        w = config_value('BASE', 'LONG')
-        self.assertEqual(len(w), 4)
-        self.assertEqual(w, 'test')
-
-    def testDelete(self):
-        remember = self.wide.setting.id
-        self.wide.update('woot')
-
-        try:
-            q = LongSetting.objects.get(pk = remember)
             self.fail("Should be deleted")
-        except LongSetting.DoesNotExist:
-            pass
-
 class OverrideTest(TestCase):
     """Test settings overrides"""
     def setUp(self):
-        # clear out cache from previous runs
-        keyedcache.cache_delete()
-
         djangosettings.LIVESETTINGS_OPTIONS = {
             1 : {
                 'DB' : False,
         user3.is_superuser = True
         user3.save()
 
-        keyedcache.cache_delete()
         # Example config
         config_register(IntegerValue(BASE_GROUP, 'SingleItem', default=0))
 

File livesettings/utils.py

     """Test value to see if it is list like"""
     try:
         iter(maybe)
-    except:
-        return 0
-    else:
-        return 1
+    except TypeError:
+        return False
+    return True
 
 def is_list_or_tuple(maybe):
     return isinstance(maybe, (types.TupleType, types.ListType))
     try:
         maybe+""
     except TypeError:
-        return 0
-    else:
-        return 1
+        return False
+    return True
 
 
 def flatten_list(sequence, scalarp=is_scalar, result=None):

File livesettings/values.py

 
 http://code.google.com/p/django-values/
 """
-from decimal import Decimal
+from decimal import Decimal, InvalidOperation
 from django import forms
 from django.core.exceptions import ImproperlyConfigured
 from django.db import connection, DatabaseError
 from django.utils.encoding import smart_str
 from django.utils.safestring import mark_safe
 from django.utils.translation import gettext, ugettext_lazy as _
-from livesettings.models import find_setting, LongSetting, Setting, SettingNotSet
+from livesettings.models import find_setting, Setting, SettingNotSet
 from livesettings.overrides import get_overrides
 from livesettings.utils import load_module, is_string_like, is_list_or_tuple
 import datetime
 import logging
 import signals
+try:
+    from django.utils.simplejson import JSONDecodeError
+except ImportError:
+    JSONDecodeError = None
 
 __all__ = ['BASE_GROUP', 'ConfigurationGroup', 'Value', 'BooleanValue', 'DecimalValue', 'DurationValue',
       'FloatValue', 'IntegerValue', 'ModuleValue', 'PercentValue', 'PositiveIntegerValue', 'SortedDotDict',
 _WARN = {}
 try:
     is_setting_initializing
-except:
+except NameError:
     is_setting_initializing = True  # until the first success find "livesettings_setting" table, by any thread
 
 
 NOTSET = object()
 
 class SortedDotDict(SortedDict):
-
+    """
+    A dictionary that keeps its keys in the order in which they're inserted.
+    
+    Additionally, getattr just delegates to getitem, meaning you can do:
+    
+        sd = SortedDotDict(somedict)
+        sd.foo == sd['foo']
+    """
     def __getattr__(self, key):
         try:
             return self[key]
-        except:
+        except KeyError:
             raise AttributeError, key
 
     def __iter__(self):
-        vals = self.values()
-        for k in vals:
-            yield k
-
-    def values(self):
-        vals = super(SortedDotDict, self).values()
-        vals = [v for v in vals if isinstance(v, (ConfigurationGroup, Value))]
-        vals.sort()
-        return vals
+        # craigds - WTF? iter(mydict) usually iterates over keys, for some reason we're iterating over values??
+        return iter(self.values())
 
 class ConfigurationGroup(SortedDotDict):
     """A simple wrapper for a group of configuration values"""
             try:
                 val = self.setting.value
 
-            except SettingNotSet, sns:
+            except SettingNotSet:
                 is_setting_initializing = False
                 if self.use_default:
                     val = self.default
             if value == None:
                 return Decimal("0")
             return Decimal(value)
-
+     
     def to_python(self, value):
         if value == NOTSET:
             return Decimal("0")
             value = super(forms.DecimalField, self).clean(value)
             try:
                 value = Decimal(value)
-            except:
+            except (TypeError, InvalidOperation):
                 raise forms.ValidationError('This value must be a decimal number.')
             return unicode(Decimal(value)/100)
         
             def render(self, name, value, attrs=None):
                 # Place a percent sign after a smaller text field
                 try:
-                    value = unicode("%.2f" % (Decimal(value)*100))
-                except:
+                    value = Decimal(value)
+                except TypeError:
                     value = "N/A"
+                else:
+                    value = unicode("%.2f" % (value*100))
                 attrs['size'] = attrs['max_length'] = 6
                 return mark_safe(super(forms.TextInput, self).render(name, value, attrs) + '%')
 
                 return ''
         return new_value
 
-class LongStringValue(Value):
+class LongStringValue(StringValue):
 
     class field(forms.CharField):
         def __init__(self, *args, **kwargs):
             kwargs['widget'] = forms.Textarea()
             forms.CharField.__init__(self, *args, **kwargs)
 
-    def make_setting(self, db_value):
-        log.debug('new long setting %s.%s', self.group.key, self.key)
-        return LongSetting(group=self.group.key, key=self.key, value=db_value)
-
-    def to_python(self, value):
-        if value == NOTSET:
-            value = ""
-        return unicode(value)
-
-    to_editor = to_python
-
 class MultipleStringValue(Value):
 
     class field(forms.CharField):
         else:
             try:
                 return simplejson.loads(value)
-            except:
+            except (JSONDecodeError, ValueError, TypeError):
                 if is_string_like(value):
                     return [value]
                 else:
-                    log.warning('Could not decode returning empty list: %s', value)
-                    return []
+                    raise ValueError("Could not decode value: %r" % value)
 
 
     to_editor = to_python
 
 class LongMultipleStringValue(MultipleStringValue):
-    def make_setting(self, db_value):
-        log.debug('new long setting %s.%s', self.group.key, self.key)
-        return LongSetting(group=self.group.key, key=self.key, value=db_value)
+    """
+    Exists for backwards compatibility only
+    """
+    pass
 
 class ModuleValue(Value):
     """Handles setting modules, storing them as strings in the db."""
         return v
 
     def get_db_prep_save(self, value):
-        return getattr(value, '__name__', '')
+        return getattr(value, '__name__', '')  # TODO change to get
 
     def to_editor(self, value):
         if value == NOTSET:

File livesettings/views.py

 from django.template import RequestContext
 from django.views.decorators.csrf import csrf_protect
 from django.views.decorators.cache import never_cache
-from livesettings import ConfigurationSettings, forms
+from livesettings import configuration_settings, forms
 from livesettings.overrides import get_overrides
 import logging
 
 
     use_db, overrides = get_overrides();
 
-    mgr = ConfigurationSettings()
+    mgr = configuration_settings
     if group is None:
         settings = mgr
         title = 'Site settings'
 def export_as_python(request):
     """Export site settings as a dictionary of dictionaries"""
 
-    from livesettings.models import Setting, LongSetting
+    from livesettings.models import Setting
     import pprint
 
     work = {}
-    both = list(Setting.objects.all())
-    both.extend(list(LongSetting.objects.all()))
-
-    for s in both:
+    for s in Setting.objects.all():
         sitesettings = work.setdefault(s.site.id, {'DB': False, 'SETTINGS':{}})['SETTINGS']
         sitegroup = sitesettings.setdefault(s.group, {})
         sitegroup[s.key] = s.value
                    'Operating System :: OS Independent',
                    'Programming Language :: Python',
                    'Framework :: Django'],
-    packages = find_packages(),
-    setup_requires=["setuptools_hg"],
+    packages = ['livesettings', 'livesettings.templatetags', 'livesettings.migrations'],
     include_package_data = True,
 )

File test-project/localsite/__init__.py

File contents unchanged.

File test-project/localsite/config.py

File contents unchanged.

File test-project/localsite/models.py

File contents unchanged.

File test-project/localsite/templates/myapp/index.html

File contents unchanged.

File test-project/localsite/views.py

File contents unchanged.

File test-project/manage.py

File contents unchanged.

File test-project/test_project/__init__.py

File contents unchanged.

File test-project/test_project/settings.py

File contents unchanged.

File test-project/test_project/urls.py

File contents unchanged.