diff --git a/.travis.yml b/.travis.yml index 7f48dd8..9d8e28d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,21 +1,34 @@ sudo: false -language: python -install: pip install tox -script: tox -python: - - 3.5 -env: - - TOXENV=coveralls - - TOXENV=pylint - - TOXENV=flake8 - - TOXENV=pydocstyle - - TOXENV=py26 - - TOXENV=py27 - - TOXENV=py33 - - TOXENV=py34 - - TOXENV=py35 - - TOXENV=pypy - - TOXENV=pypy3 +install: + - pip install tox +script: + - tox +language: + - python +matrix: + include: + - python: 2.7 + env: TOXENV=coveralls + - python: 2.7 + env: TOXENV=pylint + - python: 2.7 + env: TOXENV=flake8 + - python: 2.7 + env: TOXENV=pydocstyle + - python: 2.6 + env: TOXENV=py26 + - python: 2.7 + env: TOXENV=py27 + - python: 3.3 + env: TOXENV=py33 + - python: 3.4 + env: TOXENV=py34 + - python: 3.5 + env: TOXENV=py35 + - python: 3.6 + env: TOXENV=py36 + - python: pypy + env: TOXENV=pypy notifications: slack: secure: QHOypFu1TxCmkbCeNSqY39Bdj+hxOnA7H0zpTZrxDouLFdD+Ah5cKHFOFjFULruCdRo+JI8vPN0fmgRviUcyFVjKbs/3sEEUNU//JJpBPDQB9Epdc8jVp1w1GDF4fN/ujg3XW19U6N1dORRQBFi5EuJn/seYErogIs6F/4G8nEstyTLWqZ7DgnVBMM5aUVuwDae+iUNTutWTvVwJVqS84JC2rFzsRmXc9RJou6/PljBGogE5t+RYHWWAzSodwf3fMIdC7nKk+U6p5IwaDd021vgqk6Dduhu5qum89KsV80hP97qTIiJO/bz5gX6S/DG4cjjXFo2ELZARcRdQ2G7PJBooomiMPW3OTm4uTIbjxDKSIlZm/miHjUVv/+Am5TYgYPnOqU9RlYxAGFbKmkOXDwgJK3nyK8s4hK19cGss3hbRPC7VWRXAaGmO6Yk+UH7wUAbAPSzXvLT/GXc8VlY276KIFVoBX0dLlqSLt/jHrVvKZL1djXKIEa1cDUA9rDqybn+/Oue0QF9ask34lNM2Uu/5IdMAUz8V/U7UHtlfoYFMOJIbgzjUHRLAcIx9+k908rHAOzkMnPns9rDHkJFgJaj3n6Q5HJpQUMwq89Lhb1NHry0nNRE5awtXio6cRcri/ApVxFA+juuyRS64y1Adi8Su/ENAw4CkVeURJuMOqPk= diff --git a/domain_models/__init__.py b/domain_models/__init__.py index e1e9e56..b2f023c 100644 --- a/domain_models/__init__.py +++ b/domain_models/__init__.py @@ -1,3 +1,3 @@ """Domain models.""" -VERSION = '0.0.9' +VERSION = '0.0.10' diff --git a/domain_models/fields.py b/domain_models/fields.py index bede8ac..5e45471 100644 --- a/domain_models/fields.py +++ b/domain_models/fields.py @@ -16,6 +16,9 @@ def __init__(self, default=None, required=False): self.name = None self.storage_name = None + self.setter_fn = None + self.getter_fn = None + self.model_cls = None self.default = default @@ -60,7 +63,11 @@ def get_value(self, model, default=None): if default is not None: default = self._converter(default) - value = getattr(model, self.storage_name) + if callable(self.getter_fn): + value = self.getter_fn(model) + else: + value = getattr(model, self.storage_name) + return value if value is not None else default def set_value(self, model, value): @@ -75,7 +82,10 @@ def set_value(self, model, value): if value is not None: value = self._converter(value) - setattr(model, self.storage_name, value) + if callable(self.setter_fn) and value is not None: + self.setter_fn(model, value) + else: + setattr(model, self.storage_name, value) def get_builtin_type(self, model): """Return built-in type representation of Field. @@ -85,6 +95,14 @@ def get_builtin_type(self, model): """ return self.get_value(model) + def getter(self, fn): + """Set function for implementation custom getter feature.""" + self.getter_fn = fn + + def setter(self, fn): + """Set function for implementation custom setter feature.""" + self.setter_fn = fn + def _converter(self, value): """Convert raw input value of the field. diff --git a/setup.py b/setup.py index 04ec319..613ef8d 100644 --- a/setup.py +++ b/setup.py @@ -80,6 +80,7 @@ def run(self): 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', 'Topic :: Software Development', diff --git a/tests/test_fields.py b/tests/test_fields.py index 96f4868..e865007 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -44,6 +44,19 @@ class RequiredFieldModel(models.DomainModel): field_required = fields.Field(required=True) +class CustomGetterSetter(models.DomainModel): + open_id = fields.Int() + id = fields.Int() + + @open_id.getter + def _get_oid(self): + return self.id << 8 + + @open_id.setter + def _set_oid(self, value): + self.id = value >> 8 + + class FieldTest(unittest.TestCase): """Base field tests.""" @@ -454,3 +467,27 @@ def test_set_incorrect(self): with self.assertRaises(TypeError): model.collection_field = [some_object] + + +class CustomGetterSetterTest(unittest.TestCase): + """Test cases for custom getters and setters feature.""" + + def test_getter(self): + test_model = CustomGetterSetter() + test_model.id = 1 + self.assertEqual(test_model.id, 1) + self.assertEqual(test_model.open_id, 256) + + test_model = CustomGetterSetter(id=1) + self.assertEqual(test_model.id, 1) + self.assertEqual(test_model.open_id, 256) + + def test_setter(self): + test_model = CustomGetterSetter() + test_model.open_id = 256 + self.assertEqual(test_model.id, 1) + self.assertEqual(test_model.open_id, 256) + + test_model = CustomGetterSetter(open_id=256) + self.assertEqual(test_model.id, 1) + self.assertEqual(test_model.open_id, 256) diff --git a/tests/test_models.py b/tests/test_models.py index 78ef7c2..707916b 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -4,8 +4,6 @@ import unittest2 as unittest -import six - from domain_models import models from domain_models import fields from domain_models import collections diff --git a/tox.ini b/tox.ini index ff30cc6..f0755d6 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] envlist= - coveralls, pylint, flake8, pydocstyle, py26, py27, py33, py34, py35, pypy, pypy3 + coveralls, pylint, flake8, pydocstyle, py26, py27, py33, py34, py35, py36, pypy [testenv] whitelist_externals=