Simplified options

This commit is contained in:
Syrus Akbary 2016-06-10 22:33:48 -07:00
parent 397df4ea1a
commit c0460060a0
2 changed files with 30 additions and 66 deletions

View File

@ -1,43 +1,29 @@
from ..utils.props import props
class Options(object): class Options(object):
'''
This is the class wrapper around Meta.
It helps to validate and cointain the attributes inside
'''
def __init__(self, meta=None, **defaults): def __init__(self, meta=None, **defaults):
self.meta = meta self.add_attrs_from_meta(meta, defaults)
self.abstract = False
self.parent = None
for name, value in defaults.items():
setattr(self, name, value)
self.valid_attrs = defaults.keys()
def validate_attrs(self): def add_attrs_from_meta(self, meta, defaults):
# Store the original user-defined values for each option, meta_attrs = props(meta) if meta else {}
# for use when serializing the model definition for attr_name, value in defaults.items():
self.original_attrs = {}
# Next, apply any overridden values from 'class Meta'.
if self.meta:
meta_attrs = self.meta.__dict__.copy()
for name in self.meta.__dict__:
# Ignore any private attributes that Django doesn't care about.
# NOTE: We can't modify a dictionary's contents while looping
# over it, so we loop over the *original* dictionary instead.
if name.startswith('_'):
del meta_attrs[name]
for attr_name in self.valid_attrs:
if attr_name in meta_attrs: if attr_name in meta_attrs:
setattr(self, attr_name, meta_attrs.pop(attr_name)) value = meta_attrs.pop(attr_name)
self.original_attrs[attr_name] = getattr(self, attr_name) elif hasattr(meta, attr_name):
elif hasattr(self.meta, attr_name): value = getattr(meta, attr_name)
setattr(self, attr_name, getattr(self.meta, attr_name)) setattr(self, attr_name, value)
self.original_attrs[attr_name] = getattr(self, attr_name)
del self.valid_attrs # If meta_attrs is not empty, it implicit means
# it received invalid attributes
# Any leftover attributes must be invalid. if meta_attrs:
if meta_attrs != {}:
raise TypeError( raise TypeError(
"{}.Meta got invalid attributes: {}".format( "Invalid attributes: {}".format(
self.parent.__name__, ','.join(meta_attrs.keys())
','.join(meta_attrs.keys())) )
) )
del self.meta

View File

@ -5,41 +5,19 @@ from ..options import Options
def test_options_defaults(): def test_options_defaults():
class Meta: class Meta:
overwritten = True valid_second = True
accepted = True
options = Options(Meta, attr=True, overwritten=False) options = Options(Meta, valid_second=False, valid_first=False)
options.valid_attrs = ['accepted', 'overwritten']
options.validate_attrs()
assert options.attr assert not options.valid_first
assert options.overwritten assert options.valid_second
def test_options_contribute_to_class():
class Meta:
overwritten = True
accepted = True
options = Options(Meta, attr=True, overwritten=False)
options.valid_attrs = ['accepted', 'overwritten']
assert options.attr
assert not options.overwritten
def test_options_invalid_attrs(): def test_options_invalid_attrs():
class Meta: class Meta:
invalid = True invalid = True
class MyObject(object):
pass
options = Options(Meta, valid=True)
options.parent = MyObject
options.valid_attrs = ['valid']
assert options.valid
with pytest.raises(TypeError) as excinfo: with pytest.raises(TypeError) as excinfo:
options.validate_attrs() Options(Meta, valid=True)
assert "MyObject.Meta got invalid attributes: invalid" == str(excinfo.value) assert "Invalid attributes: invalid" == str(excinfo.value)