Skip to content
This repository has been archived by the owner on Jan 1, 2020. It is now read-only.

Commit

Permalink
Added Config inheritance workaround
Browse files Browse the repository at this point in the history
  • Loading branch information
dferens committed Mar 8, 2014
1 parent 2b6f003 commit 34806a0
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 13 deletions.
43 changes: 39 additions & 4 deletions classsettings/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,45 @@ def __init__(cls, name, bases, attrs):

class ConfigMeta(type):

def __init__(cls, name, bases, attrs):
public_members, module = inspect_class(cls)
result = dict((name, value()) for (name, value) in public_members)
def __new__(cls, name, bases, attrs):
Class = super(ConfigMeta, cls).__new__(cls, name, bases, attrs)

if name == 'NewBase':
return Class

public_members, module = inspect_class(Class)
variables = ((k, val()) for (k, val) in public_members)
result = ConfigResult(variables, Class)
setattr(module, name, result)
return result


class ConfigResult(dict):
"""
Dict-like object which adds inheritance support.
"""
def __new__(cls, *args, **kwargs):
if len(args) == 2:
# Used to create dict object
return super(ConfigResult, cls).__new__(cls, *args, **kwargs)
else:
# Used as superclass
name, bases, attrs = args
bases = tuple(b.ConfigClass for b in bases if isinstance(b, ConfigResult))
return ConfigMeta(name, bases, attrs)

def __init__(self, *args, **kwargs):
if len(args) == 2:
# Is used as dict instance
dict_arg, self._ConfigClass = args
super(ConfigResult, self).__init__(dict_arg, **kwargs)
else:
# Is used as class
pass

@property
def ConfigClass(self):
return self._ConfigClass


class Settings(six.with_metaclass(SettingsMeta)):
Expand All @@ -40,5 +75,5 @@ class Settings(six.with_metaclass(SettingsMeta)):
class Config(six.with_metaclass(ConfigMeta)):
"""
Calls each public method of class, constructs dictionary with `name-result`
pairs and injects it into module scope.
pairs and replaces class with it.
"""
20 changes: 11 additions & 9 deletions tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class MyConfig(Config): pass
new_module_vars = set(globals())
self.assertEqual(new_module_vars - old_module_vars,
set(('MyConfig',)))
self.assertEqual(globals()['MyConfig'], dict())
self.assertTrue(globals()['MyConfig'] == MyConfig == dict())

def test_fields(self):
class MyConfig(Config):
Expand All @@ -89,20 +89,22 @@ def _private_setting(self): return 1
def test_inheritance(self):
old_module_vars = set(globals())
self.assertFalse('SuperConfig' in old_module_vars or
'SubConfig' in old_module_vars)
'Sub1Config' in old_module_vars)

class SuperConfig(Config):
def public_super(self): return 1

class SubConfig(SuperConfig):
def public_sub(self): return 2
class Sub1Config(SuperConfig):
def public_sub(self): return 2 * self.public_super()

class Sub2Config(Sub1Config):
def public_sub2(self): return 2 * self.public_sub()

self.assertEqual(set(globals()) - old_module_vars,
set(('SuperConfig', 'SubConfig')))
self.assertEqual(globals()['SuperConfig'],
{'public_super': 1})
self.assertEqual(globals()['SubConfig'],
{'public_super': 1, 'public_sub': 2})
set(('SuperConfig', 'Sub1Config', 'Sub2Config')))
self.assertEqual(SuperConfig, dict(public_super=1))
self.assertEqual(Sub1Config, dict(public_super=1, public_sub=2))
self.assertEqual(Sub2Config, dict(public_super=1, public_sub=2, public_sub2=4))


class FromEnvTestCase(unittest.TestCase):
Expand Down

0 comments on commit 34806a0

Please sign in to comment.