From 7d2f3d9e0e094b46dec91d000a9c431bb86626c2 Mon Sep 17 00:00:00 2001 From: Sergii boonya Buinytskyi Date: Sat, 23 Jan 2016 03:14:45 +0200 Subject: [PATCH 1/3] Issue #16: Possibility to mark filed as required. --- domain_models/fields.py | 12 ++++++++++-- tests/test_fields.py | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/domain_models/fields.py b/domain_models/fields.py index 3e60f16..14e8813 100644 --- a/domain_models/fields.py +++ b/domain_models/fields.py @@ -10,7 +10,7 @@ class Field(property): """Base field.""" - def __init__(self, default=None): + def __init__(self, default=None, required=False): """Initializer.""" super(Field, self).__init__(self.get_value, self.set_value) self.name = None @@ -19,6 +19,7 @@ def __init__(self, default=None): self.model_cls = None self.default = default + self.required = required def bind_name(self, name): """Bind field to its name in model class.""" @@ -40,8 +41,12 @@ def bind_model_cls(self, model_cls): def init_model(self, model, value): """Init model with field.""" - if not value: + if value is None: value = self.default() if callable(self.default) else self.default + + if value is None and self.required: + raise AttributeError("This field is required.") + setattr(model, self.storage_name, value) def get_value(self, model): @@ -50,6 +55,9 @@ def get_value(self, model): def set_value(self, model, value): """Set field's value.""" + if value is None and self.required: + raise AttributeError("This field is required.") + if value is not None: value = self._converter(value) setattr(model, self.storage_name, value) diff --git a/tests/test_fields.py b/tests/test_fields.py index 8f1fc24..96f4868 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -22,6 +22,7 @@ class ExampleModel(models.DomainModel): field = fields.Field() field_default = fields.Field(default=123) field_default_callable = fields.Field(default=time.time) + field_required_default = fields.Field(default=123, required=True) bool_field = fields.Bool() @@ -38,6 +39,11 @@ class ExampleModel(models.DomainModel): collection_field = fields.Collection(RelatedModel) +class RequiredFieldModel(models.DomainModel): + """Example model for required fields.""" + field_required = fields.Field(required=True) + + class FieldTest(unittest.TestCase): """Base field tests.""" @@ -81,6 +87,37 @@ def test_field_default_callable(self): self.assertGreater(model2.field_default_callable, model1.field_default_callable) + def test_field_required(self): + """Test required field with default value.""" + model = ExampleModel() + self.assertEquals(model.field_required_default, 123) + + def test_field_required_set_valid(self): + """Test required field with valid value.""" + model = ExampleModel() + model.field_required_default = False + self.assertIs(model.field_required_default, False) + + def test_field_required_set_invalid(self): + """Test required field with invalid value.""" + model = ExampleModel() + with self.assertRaises(AttributeError): + model.field_required_default = None + + def test_field_required_init_valid_model(self): + """Test required field with valid value as model keyword.""" + model = RequiredFieldModel(field_required=False) + self.assertIs(model.field_required, False) + model.field_required = 123 + self.assertEqual(model.field_required, 123) + + def test_field_required_init_invalid_model(self): + """Test required field with invalid value as model keyword.""" + with self.assertRaises(AttributeError): + RequiredFieldModel() + with self.assertRaises(AttributeError): + RequiredFieldModel(field_required=None) + class BoolTest(unittest.TestCase): """Bool field tests.""" From a6626095e6c6a8ab6ba21c864aee4a3622d23148 Mon Sep 17 00:00:00 2001 From: Sergii boonya Buinytskyi Date: Sun, 24 Jan 2016 18:19:56 +0200 Subject: [PATCH 2/3] Issue #16: required keyword for `fields.Model` and `fields.Collection` initializers https://github.com/ets-labs/domain_models/pull/18#issuecomment-174224695 --- domain_models/fields.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/domain_models/fields.py b/domain_models/fields.py index 14e8813..4e6e20e 100644 --- a/domain_models/fields.py +++ b/domain_models/fields.py @@ -130,9 +130,9 @@ def _converter(self, value): class Model(Field): """Model relation field.""" - def __init__(self, related_model_cls, default=None): + def __init__(self, related_model_cls, default=None, required=False): """Initializer.""" - super(Model, self).__init__(default=default) + super(Model, self).__init__(default=default, required=required) self.related_model_cls = related_model_cls @@ -148,9 +148,9 @@ def _converter(self, value): class Collection(Field): """Models collection relation field.""" - def __init__(self, related_model_cls, default=None): + def __init__(self, related_model_cls, default=None, required=False): """Initializer.""" - super(Collection, self).__init__(default=default) + super(Collection, self).__init__(default=default, required=required) self.related_model_cls = related_model_cls def _converter(self, value): From 05d96b3c5b840ed73069cdfdf9a70fa08f4a3403 Mon Sep 17 00:00:00 2001 From: Sergii boonya Buinytskyi Date: Sun, 24 Jan 2016 18:22:38 +0200 Subject: [PATCH 3/3] Travis CI and Coveralls bages in README --- README.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.rst b/README.rst index a3c917b..a4ecb1f 100644 --- a/README.rst +++ b/README.rst @@ -3,6 +3,16 @@ Domain models Domain models framework for Python projects +============ + +.. image:: https://travis-ci.org/ets-labs/domain_models.svg?branch=master + :target: https://travis-ci.org/ets-labs/domain_models + :alt: Build Status + +.. image:: https://coveralls.io/repos/github/ets-labs/domain_models/badge.svg?branch=master + :target: https://coveralls.io/github/ets-labs/domain_models?branch=master + :alt: Coverage Status + Introduction ~~~~~~~~~~~~