From ce5e1a919597aa8e4720a1ac61eeced0c0fc3405 Mon Sep 17 00:00:00 2001 From: alfred82santa Date: Wed, 11 May 2016 18:49:36 +0200 Subject: [PATCH] Fix model autoreference --- Makefile | 6 ++--- README.rst | 40 +++++++++++++++++++----------- dirty_models/fields.py | 4 +++ dirty_models/models.py | 24 +++++++++++++----- setup.py | 2 +- tests/dirty_models/tests_fields.py | 20 +++++++++++++++ tox.ini | 3 +++ 7 files changed, 75 insertions(+), 24 deletions(-) diff --git a/Makefile b/Makefile index 21fbb4f..1f3997b 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ help: @echo "Options" @echo "---------------------------------------------------------------" @echo "help: This help" - @echo "requirements: Download requeroments" + @echo "requirements: Download requirements" @echo "requirements-test: Download requirements for tests" @echo "requirements-docs: Download requirements for docs" @echo "run-tests: Run tests with coverage" @@ -31,12 +31,12 @@ requirements-docs: run-tests: @echo "Running tests..." - nosetests --with-coverage -d --cover-package=dirty_models + nosetests --with-coverage -d --cover-package=dirty_models --cover-erase publish: @echo "Publishing new version on Pypi..." python setup.py sdist upload - + clean: @echo "Cleaning compiled files..." find . | grep -E "(__pycache__|\.pyc|\.pyo)$ " | xargs rm -rf diff --git a/README.rst b/README.rst index e57b099..ac8f101 100644 --- a/README.rst +++ b/README.rst @@ -1,28 +1,28 @@ |travis-master| |coverall-master| |doc-master| |pypi-downloads| |pypi-lastrelease| |python-versions| |project-status| |project-license| |project-format| |project-implementation| -.. |travis-master| image:: https://travis-ci.org/alfred82santa/dirty-models.svg?branch=master +.. |travis-master| image:: https://travis-ci.org/alfred82santa/dirty-models.svg?branch=master :target: https://travis-ci.org/alfred82santa/dirty-models - + .. |coverall-master| image:: https://coveralls.io/repos/alfred82santa/dirty-models/badge.svg?branch=master&service=github :target: https://coveralls.io/r/alfred82santa/dirty-models?branch=master - + .. |doc-master| image:: https://readthedocs.org/projects/dirty-models/badge/?version=latest :target: https://readthedocs.org/projects/dirty-models/?badge=latest :alt: Documentation Status - + .. |pypi-downloads| image:: https://img.shields.io/pypi/dm/dirty-models.svg :target: https://pypi.python.org/pypi/dirty-models/ :alt: Downloads - + .. |pypi-lastrelease| image:: https://img.shields.io/pypi/v/dirty-models.svg :target: https://pypi.python.org/pypi/dirty-models/ :alt: Latest Version - + .. |python-versions| image:: https://img.shields.io/pypi/pyversions/dirty-models.svg :target: https://pypi.python.org/pypi/dirty-models/ :alt: Supported Python versions - + .. |project-status| image:: https://img.shields.io/pypi/status/dirty-models.svg :target: https://pypi.python.org/pypi/dirty-models/ :alt: Development Status @@ -82,6 +82,18 @@ Features Changelog ********* +Version 0.6.1 +------------- + +- Improved model field autoreference. + +.. code-block:: python + + class ExampleModel(BaseModel): + model_field = ModelField() # Field with a ExampleModel + array_of_model = ArrayField(field_type=ModelField()) # Array of ExampleModels + + Version 0.6.0 ------------- @@ -169,23 +181,23 @@ Basic usage from dirty_models.models import BaseModel from dirty_models.fields import StringField, IntegerField - + class FooBarModel(BaseModel): foo = IntegerField() bar = StringField(name="real_bar") alias_field = IntegerField(alias=['alias1', 'alias2']) - - - + + + fb = FooBarModel() - + fb.foo = 2 assert fb.foo is 2 - + fb.bar = 'wow' assert fb.bar is 'wow' assert fb.real_bar is 'wow' - + fb.alias_field = 3 assert fb.alias_field is 3 assert fb.alias1 is fb.alias_field diff --git a/dirty_models/fields.py b/dirty_models/fields.py index 07cc4cb..73320d2 100644 --- a/dirty_models/fields.py +++ b/dirty_models/fields.py @@ -525,3 +525,7 @@ def can_use_value(self, value): if ft.can_use_value(value): return True return False + + @property + def field_types(self): + return self._field_types.copy() diff --git a/dirty_models/models.py b/dirty_models/models.py index 73131e7..c57f97d 100644 --- a/dirty_models/models.py +++ b/dirty_models/models.py @@ -58,17 +58,29 @@ def process_base_field(cls, field, key): field.name = key elif key != field.name: setattr(cls, field.name, field) + + cls.prepare_field(field) + + if field.alias: + for alias_name in field.alias: + setattr(cls, alias_name, field) + + def prepare_field(cls, field): if isinstance(field, ModelField) and not field.model_class: field.model_class = cls field.__doc__ = field.get_field_docstring() - if isinstance(field, ArrayField) and isinstance(field.field_type, ModelField) \ - and not field.field_type.model_class: - field.field_type.model_class = cls + + try: + cls.prepare_field(field.field_type) field.field_type.__doc__ = field.field_type.get_field_docstring() + except AttributeError: + pass - if field.alias: - for alias_name in field.alias: - setattr(cls, alias_name, field) + try: + for inner_field in field.field_types: + cls.prepare_field(inner_field) + except AttributeError: + pass def recover_model_from_data(model_class, original_data, modified_data, deleted_data): diff --git a/setup.py b/setup.py index 1451d07..c7021ba 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ name='dirty-models', url='https://github.com/alfred82santa/dirty-models', author='alfred82santa', - version='0.6.0', + version='0.6.1', author_email='alfred82santa@gmail.com', classifiers=[ 'Intended Audience :: Developers', diff --git a/tests/dirty_models/tests_fields.py b/tests/dirty_models/tests_fields.py index 39d7397..88c1985 100644 --- a/tests/dirty_models/tests_fields.py +++ b/tests/dirty_models/tests_fields.py @@ -1404,3 +1404,23 @@ def test_update_integer_field(self): self.model.flat_data() self.model.multi_field = 3 self.assertEqual(self.model.multi_field, 3) + + +class TestAutoreferenceModel(TestCase): + + def setUp(self): + super(TestAutoreferenceModel, self).setUp() + + class AutoreferenceModel(BaseModel): + multi_field = MultiTypeField(field_types=[IntegerField(), (ArrayField, {"field_type": ModelField()})]) + array_of_array = ArrayField(field_type=ArrayField(field_type=ModelField())) + test_field = IntegerField() + + self.model = AutoreferenceModel() + + def test_model_reference(self): + self.model.import_data({'multi_field': [{'test_field': 1}, {'test_field': 2}], + 'array_of_array': [[{'test_field': 3}]]}) + self.assertIsInstance(self.model.multi_field[0], self.model.__class__) + self.assertIsInstance(self.model.multi_field[1], self.model.__class__) + self.assertIsInstance(self.model.array_of_array[0][0], self.model.__class__) diff --git a/tox.ini b/tox.ini index 6deafc2..433157f 100644 --- a/tox.ini +++ b/tox.ini @@ -1,2 +1,5 @@ +[tox] +envlist = py33,py34,py35 + [flake8] max-line-length = 120