Skip to content

Commit

Permalink
Added factory decorator in order to allow to set factories as default…
Browse files Browse the repository at this point in the history
… values
  • Loading branch information
alfred82santa committed Nov 2, 2017
1 parent 995104f commit f9f1f51
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 26 deletions.
3 changes: 2 additions & 1 deletion dirty_models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@

from .models import *
from .fields import *
from .utils import *

__version__ = '0.10.0'
__version__ = '0.10.1'
25 changes: 16 additions & 9 deletions dirty_models/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
Fields to be used with dirty models.
"""

from datetime import datetime, date, time, timedelta
from enum import Enum
from datetime import date, datetime, time, timedelta

from collections import Mapping
from dateutil.parser import parse as dateutil_parse
from enum import Enum
from functools import wraps

from .model_types import ListModel
Expand Down Expand Up @@ -103,10 +103,17 @@ def __set__(self, obj, value):
self._setter(self, obj, value)
return

if value is None:
self.delete_value(obj)
elif self.check_value(value) or self.can_use_value(value):
self.set_value(obj, self.use_value(value))
from dirty_models.utils import Factory

def set_value(v):
if value is None:
self.delete_value(obj)
elif self.check_value(v) or self.can_use_value(v):
self.set_value(obj, self.use_value(v))
elif isinstance(value, Factory):
set_value(v())

set_value(value)

def __delete__(self, obj):
self._check_name()
Expand Down Expand Up @@ -426,7 +433,7 @@ def convert_value(self, value):
return value.time()

return self.convert_value(self.get_parsed_value(value))
except:
except Exception:
return None
elif isinstance(value, datetime):
return value.timetz()
Expand Down Expand Up @@ -486,7 +493,7 @@ def convert_value(self, value):
return value.date()

return self.convert_value(self.get_parsed_value(value))
except:
except Exception:
return None
elif isinstance(value, datetime):
return value.date()
Expand Down Expand Up @@ -556,7 +563,7 @@ def convert_value(self, value):
return dateutil_parse(value)

return self.get_parsed_value(value)
except:
except Exception:
return None
elif isinstance(value, date):
return datetime(year=value.year, month=value.month,
Expand Down
2 changes: 1 addition & 1 deletion dirty_models/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ def is_modified_field(self, name):

try:
return self.get_field_value(name).is_modified()
except:
except Exception:
return False

def import_data(self, data):
Expand Down
22 changes: 21 additions & 1 deletion dirty_models/utils.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
from datetime import date, datetime, time, timedelta
from enum import Enum
from json.encoder import JSONEncoder as BaseJSONEncoder

import re
from enum import Enum

from .fields import MultiTypeField
from .model_types import ListModel
from .models import BaseModel


__all__ = ['factory', 'JSONEncoder']


def underscore_to_camel(string):
"""
Converts underscored string to camel case.
Expand Down Expand Up @@ -95,3 +98,20 @@ def default(self, obj):
return {k: v for k, v in obj}
elif isinstance(obj, ListFormatterIter):
return list(obj)


class Factory:
"""
Factory decorator could be used to define a default value as result of a function. It could
be useful to define a :class:`~dirty_models.field.DateTimeField` with :meth:`datetime.datetime.now`
in order to set the current datetime.
"""

def __init__(self, func):
self.func = func

def __call__(self):
return self.func()


factory = Factory
59 changes: 45 additions & 14 deletions tests/dirty_models/tests_models.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import pickle
from datetime import datetime, date, time, timedelta
from enum import Enum
from datetime import date, datetime, time, timedelta
from unittest import TestCase

from enum import Enum
from functools import partial

from dirty_models.base import Unlocker
from dirty_models.fields import (BaseField, IntegerField, FloatField,
StringField, DateTimeField, ModelField,
ArrayField, BooleanField, DateField, TimeField, HashMapField, TimedeltaField,
EnumField, MultiTypeField)
from dirty_models.models import BaseModel, DynamicModel, HashMapModel, FastDynamicModel, CamelCaseMeta
from dirty_models.fields import ArrayField, BaseField, BooleanField, DateField, DateTimeField, EnumField, FloatField, \
HashMapField, IntegerField, ModelField, MultiTypeField, StringField, TimeField, TimedeltaField
from dirty_models.models import BaseModel, CamelCaseMeta, DynamicModel, FastDynamicModel, HashMapModel
from dirty_models.utils import factory

INITIAL_DATA = {
'testField1': 'testValue1',
Expand Down Expand Up @@ -164,8 +163,7 @@ def test_export_data(self):
exported_data = self.model.export_data()
self.assertEqual(exported_data, {'testField1': 'Value1Modified',
'testField4':
{'testField2':
'Field Value2 Modified',
{'testField2': 'Field Value2 Modified',
'testField1': 'Field Value1'}})

def test_export_modified(self):
Expand Down Expand Up @@ -1634,13 +1632,13 @@ def test_wildcard_path_list_inner(self):
self.assertEqual(self.model.get_attrs_by_path('test_list.*.test_field_2'), ['string'])

def test_wildcard_path_all(self):
self.assertEqual(set(self.model.get_attrs_by_path('*')), set([1, self.model.test_list,
self.model.test_model,
self.model.test_list_int]))
self.assertEqual(set(self.model.get_attrs_by_path('*')), {1, self.model.test_list,
self.model.test_model,
self.model.test_list_int})

def test_wildcard_path_list(self):
self.assertEqual(set(self.model.get_attrs_by_path('test_list.*')), set([self.model.test_list[0],
self.model.test_list[1]]))
self.assertEqual(set(self.model.get_attrs_by_path('test_list.*')), {self.model.test_list[0],
self.model.test_list[1]})

def test_first_simple(self):
self.assertEqual(self.model.get_1st_attr_by_path('test_field_1'), 1)
Expand Down Expand Up @@ -1988,3 +1986,36 @@ def test_list_inner_list_model_append_item(self):
self.assertEqual(model.export_modifications(), {'test_array_array_model.0': [{'test_field_int': 3},
{'test_field_int': 4},
{'test_field_int': 6}]})


class IterFactory:

def __init__(self):
self.i = 0

def __call__(self):
self.i += 1
return self.i


class DefaultValueFactoryTests(TestCase):

class Model(BaseModel):
__default_data__ = {'test_field_float': factory(IterFactory())}

test_field_int = IntegerField(default=factory(IterFactory()))
test_field_string = StringField(default=factory(IterFactory()))
test_field_float = FloatField()

def test_default_value_factory(self):
model = self.Model()

self.assertEquals(model.test_field_int, 1)
self.assertEquals(model.test_field_string, '1')
self.assertEquals(model.test_field_float, 1.0)

model = self.Model()

self.assertEquals(model.test_field_int, 2)
self.assertEquals(model.test_field_string, '2')
self.assertEquals(model.test_field_float, 2.0)

0 comments on commit f9f1f51

Please sign in to comment.