Skip to content

Commit baca2db

Browse files
committed
Issue #22: Use converter instead of strict mode.
1 parent a9ea607 commit baca2db

File tree

3 files changed

+171
-50
lines changed

3 files changed

+171
-50
lines changed

domain_models/fields.py

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ def bind_model_cls(self, model_cls):
4141

4242
def init_model(self, model, value):
4343
"""Init model with field."""
44-
if value is None:
44+
if value is None and self.default is not None:
4545
value = self.default() if callable(self.default) else self.default
46+
value = self.converter(value)
4647

4748
if value is None and self.required:
4849
raise AttributeError("This field is required.")
@@ -59,65 +60,59 @@ def set_value(self, model, value):
5960
raise AttributeError("This field is required.")
6061

6162
if value is not None:
62-
value = self._converter(value)
63-
setattr(model, self.storage_name, value)
64-
65-
def is_valid_type(self, value):
66-
"""Check whether the value is valid type.
63+
value = self.converter(value)
6764

68-
:param value:
69-
"""
70-
return self._converter(value) == value
65+
setattr(model, self.storage_name, value)
7166

72-
def _converter(self, value):
67+
def converter(self, value):
7368
"""Convert raw input value of the field."""
7469
return value
7570

7671

7772
class Bool(Field):
7873
"""Bool field."""
7974

80-
def _converter(self, value):
75+
def converter(self, value):
8176
"""Convert raw input value of the field."""
8277
return bool(value)
8378

8479

8580
class Int(Field):
8681
"""Int field."""
8782

88-
def _converter(self, value):
83+
def converter(self, value):
8984
"""Convert raw input value of the field."""
9085
return int(value)
9186

9287

9388
class Float(Field):
9489
"""Float field."""
9590

96-
def _converter(self, value):
91+
def converter(self, value):
9792
"""Convert raw input value of the field."""
9893
return float(value)
9994

10095

10196
class String(Field):
10297
"""String field."""
10398

104-
def _converter(self, value):
99+
def converter(self, value):
105100
"""Convert raw input value of the field."""
106101
return str(value)
107102

108103

109104
class Binary(Field):
110105
"""Binary field."""
111106

112-
def _converter(self, value):
107+
def converter(self, value):
113108
"""Convert raw input value of the field."""
114109
return six.binary_type(value)
115110

116111

117112
class Date(Field):
118113
"""Date field."""
119114

120-
def _converter(self, value):
115+
def converter(self, value):
121116
"""Convert raw input value of the field."""
122117
if not isinstance(value, datetime.date):
123118
raise TypeError('{0} is not valid date'.format(value))
@@ -127,7 +122,7 @@ def _converter(self, value):
127122
class DateTime(Field):
128123
"""Date and time field."""
129124

130-
def _converter(self, value):
125+
def converter(self, value):
131126
"""Convert raw input value of the field."""
132127
if not isinstance(value, datetime.datetime):
133128
raise TypeError('{0} is not valid date and time')
@@ -143,7 +138,7 @@ def __init__(self, related_model_cls, default=None, required=False):
143138

144139
self.related_model_cls = related_model_cls
145140

146-
def _converter(self, value):
141+
def converter(self, value):
147142
"""Convert raw input value of the field."""
148143
if not isinstance(value, self.related_model_cls):
149144
raise TypeError('{0} is not valid model instance, instance of '
@@ -160,7 +155,7 @@ def __init__(self, related_model_cls, default=None, required=False):
160155
super(Collection, self).__init__(default=default, required=required)
161156
self.related_model_cls = related_model_cls
162157

163-
def _converter(self, value):
158+
def converter(self, value):
164159
"""Convert raw input value of the field."""
165160
if type(value) is not self.related_model_cls.Collection:
166161
value = self.related_model_cls.Collection(value)

domain_models/models.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -192,20 +192,25 @@ def get(self, field_name, default=None):
192192
one of the existent fields, the result is the value of that field.
193193
For example, `model.get('foobar')` is equivalent to `model.foobar`.
194194
If the filed does not have a value, `default` is returned if provided.
195-
It will raise `AttributeError` if `default` is not the same type
196-
as field value.
195+
It will raise `AttributeError` if `default` can not be converted to
196+
right type value.
197197
If the field does not exist, `AttributeError` is raised as well.
198198
199199
:param string field_name:
200200
:param mixed default:
201201
"""
202-
value = getattr(self, field_name)
202+
if not hasattr(self, field_name):
203+
raise AttributeError(
204+
"Model doesn't have a field '{name}'".format(name=field_name))
203205

204-
if default is not None and value is None:
206+
if default is not None:
205207
field = dict((field.name, field) for field in
206208
self.__class__.__fields__).get(field_name)
207-
if not field.is_valid_type(default):
209+
try:
210+
default = field.converter(default)
211+
except (TypeError, ValueError):
208212
raise AttributeError(
209-
"default must be the same type as the field.")
213+
"default can not be converted to right type value")
210214

211-
return value if value else default
215+
value = getattr(self, field_name)
216+
return value if value is not None else default

tests/test_models.py

Lines changed: 145 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
"""Models tests."""
22

3+
import datetime
4+
35
import unittest2 as unittest
46

7+
import six
8+
59
from domain_models import models
610
from domain_models import fields
711
from domain_models import collections
@@ -164,38 +168,155 @@ class Model2(models.DomainModel):
164168

165169
field = Model1.field
166170

167-
def test_get_method(self):
168-
mock_id = 2
169-
mock_name = 'foobar'
171+
def test_get_method_on_undefined(self):
172+
"""Test method get of Model."""
170173

171-
class SomeModel(models.DomainModel):
172-
"""Test domain model."""
173-
id = fields.Int()
174-
name = fields.String()
175-
string = fields.String()
174+
class Model(models.DomainModel):
175+
"""Test model."""
176+
field = fields.Int()
177+
178+
model = Model()
176179

177-
model = SomeModel(id=mock_id, name=mock_name)
180+
with self.assertRaises(AttributeError):
181+
model.get('undefined')
182+
183+
def test_get_method_on_int(self):
184+
"""Test method get on Int of Model."""
185+
valid_defaults = [0, 3, 5.5, False, True]
178186

179-
self.assertEqual(model.get('id'), mock_id)
180-
self.assertEqual(model.get('id', 0), mock_id)
181-
self.assertEqual(model.get('id', 123), mock_id)
187+
class Model(models.DomainModel):
188+
"""Test model."""
189+
field = fields.Int()
182190

183-
self.assertEqual(model.get('name'), mock_name)
184-
self.assertEqual(model.get('name', ''), mock_name)
185-
self.assertEqual(model.get('name', 'another-name'), mock_name)
191+
model = Model(field=2)
192+
for value in valid_defaults:
193+
self.assertEqual(model.get('field', default=value), 2)
186194

187-
self.assertEqual(model.get('string'), None)
188-
self.assertEqual(model.get('string', ''), '')
189-
self.assertEqual(model.get('string', 'not-empty'), 'not-empty')
195+
model = Model()
196+
self.assertEqual(model.get('field'), None)
197+
for value in valid_defaults:
198+
self.assertEqual(model.get('field', default=value), int(value))
190199

191-
string = model.get('string', '')
192-
self.assertEqual(string, '')
200+
for value in ['', u'baz']:
201+
with self.assertRaises(AttributeError):
202+
model.get('field', value)
203+
self.fail("Failed with {value}".format(value=str(value)))
193204

194-
with self.assertRaises(AttributeError):
195-
model.get('unknown')
205+
def test_get_method_on_string(self):
206+
"""Test method get on String of Model."""
207+
valid_defaults = ['', 'baz', u'baz', False, True, 1, 2.3]
196208

197-
with self.assertRaises(AttributeError):
198-
model.get('string', 0)
209+
class Model(models.DomainModel):
210+
"""Test model."""
211+
field = fields.String()
212+
213+
model = Model(field='foobar')
214+
for value in valid_defaults:
215+
self.assertEqual(model.get('field', default=value), 'foobar')
216+
217+
model = Model()
218+
self.assertEqual(model.get('field'), None)
219+
for value in valid_defaults:
220+
self.assertEqual(model.get('field', default=value), str(value))
221+
222+
def test_get_method_on_bool(self):
223+
"""Test method get on Bool of Model."""
224+
225+
class Model(models.DomainModel):
226+
"""Test model."""
227+
field = fields.Bool()
228+
229+
model = Model(field=True)
230+
self.assertEqual(model.get('field'), True)
231+
self.assertEqual(model.get('field', default=False), True)
232+
233+
model = Model(field=False)
234+
self.assertEqual(model.get('field'), False)
235+
self.assertEqual(model.get('field', default=True), False)
236+
237+
model = Model()
238+
self.assertEqual(model.get('field'), None)
239+
self.assertEqual(model.get('field', default=False), False)
240+
self.assertEqual(model.get('field', default=True), True)
241+
242+
def test_get_method_on_float(self):
243+
"""Test method get on Float of Model."""
244+
valid_defaults = [7.5, 7, '7.5', '7', 0, '0.0', .9, '.9', False, True]
245+
246+
class Model(models.DomainModel):
247+
"""Test model."""
248+
field = fields.Float()
249+
250+
model = Model(field=5.5)
251+
self.assertEqual(model.get('field'), 5.5)
252+
for value in valid_defaults:
253+
self.assertEqual(model.get('field', default=value), 5.5)
254+
255+
model = Model()
256+
self.assertEqual(model.get('field'), None)
257+
for value in valid_defaults:
258+
self.assertEqual(model.get('field', default=value), float(value))
259+
260+
for value in ['', 'baz', u'baz', datetime]:
261+
with self.assertRaises(AttributeError):
262+
model.get('field', value)
263+
self.fail("Failed with {value}".format(value=str(value)))
264+
265+
def test_get_method_on_date(self):
266+
"""Test method get on Date of Model."""
267+
once = datetime.date(year=1986, month=4, day=26)
268+
today = datetime.date.today()
269+
270+
class Model(models.DomainModel):
271+
"""Test model."""
272+
field = fields.Date()
273+
274+
model = Model(field=today)
275+
self.assertEqual(model.get('field'), today)
276+
self.assertEqual(model.get('field', once), today)
277+
278+
model = Model()
279+
self.assertEqual(model.get('field'), None)
280+
self.assertEqual(model.get('field', once), once)
281+
282+
for value in ['', 'baz', u'baz', 0, 3, 0.7, '.5', False, True]:
283+
with self.assertRaises(AttributeError):
284+
model.get('field', value)
285+
self.fail("Failed with {value}".format(value=str(value)))
286+
287+
def test_get_method_on_datetime(self):
288+
"""Test method get on Date of Model."""
289+
once = datetime.datetime(year=1986, month=4, day=26)
290+
now = datetime.datetime.now()
291+
292+
class Model(models.DomainModel):
293+
"""Test model."""
294+
field = fields.DateTime()
295+
296+
model = Model(field=now)
297+
self.assertEqual(model.get('field'), now)
298+
self.assertEqual(model.get('field', once), now)
299+
300+
model = Model()
301+
self.assertEqual(model.get('field'), None)
302+
self.assertEqual(model.get('field', once), once)
303+
304+
for value in ['', 'baz', u'baz', 0, 3, 0.7, '.5', False, True]:
305+
with self.assertRaises(AttributeError):
306+
model.get('field', value)
307+
self.fail("Failed with {value}".format(value=str(value)))
308+
309+
def test_get_method_on_binary(self):
310+
"""Test method get on Binary of Model."""
311+
self.skipTest("Test is not implemented yet")
312+
313+
def test_get_method_on_model(self):
314+
"""Test method get on Model of Model."""
315+
self.skipTest("Test is not implemented yet")
316+
317+
def test_get_method_on_collection(self):
318+
"""Test method get on Collection of Model."""
319+
self.skipTest("Test is not implemented yet")
199320

200321

201322
class ModelReprTests(unittest.TestCase):

0 commit comments

Comments
 (0)