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):
'''
This is the class wrapper around Meta.
It helps to validate and cointain the attributes inside
'''
def __init__(self, meta=None, **defaults):
self.meta = meta
self.abstract = False
self.parent = None
for name, value in defaults.items():
setattr(self, name, value)
self.valid_attrs = defaults.keys()
self.add_attrs_from_meta(meta, defaults)
def validate_attrs(self):
# Store the original user-defined values for each option,
# for use when serializing the model definition
self.original_attrs = {}
def add_attrs_from_meta(self, meta, defaults):
meta_attrs = props(meta) if meta else {}
for attr_name, value in defaults.items():
if attr_name in meta_attrs:
value = meta_attrs.pop(attr_name)
elif hasattr(meta, attr_name):
value = getattr(meta, attr_name)
setattr(self, attr_name, value)
# 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:
setattr(self, attr_name, meta_attrs.pop(attr_name))
self.original_attrs[attr_name] = getattr(self, attr_name)
elif hasattr(self.meta, attr_name):
setattr(self, attr_name, getattr(self.meta, attr_name))
self.original_attrs[attr_name] = getattr(self, attr_name)
del self.valid_attrs
# Any leftover attributes must be invalid.
if meta_attrs != {}:
raise TypeError(
"{}.Meta got invalid attributes: {}".format(
self.parent.__name__,
','.join(meta_attrs.keys()))
)
del self.meta
# If meta_attrs is not empty, it implicit means
# it received invalid attributes
if meta_attrs:
raise TypeError(
"Invalid attributes: {}".format(
','.join(meta_attrs.keys())
)
)

View File

@ -5,41 +5,19 @@ from ..options import Options
def test_options_defaults():
class Meta:
overwritten = True
accepted = True
valid_second = True
options = Options(Meta, attr=True, overwritten=False)
options.valid_attrs = ['accepted', 'overwritten']
options.validate_attrs()
options = Options(Meta, valid_second=False, valid_first=False)
assert options.attr
assert options.overwritten
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
assert not options.valid_first
assert options.valid_second
def test_options_invalid_attrs():
class Meta:
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:
options.validate_attrs()
Options(Meta, valid=True)
assert "MyObject.Meta got invalid attributes: invalid" == str(excinfo.value)
assert "Invalid attributes: invalid" == str(excinfo.value)