Skip to content

Commit

Permalink
Fix model autoreference
Browse files Browse the repository at this point in the history
  • Loading branch information
alfred82santa committed May 11, 2016
1 parent 65bd96c commit ce5e1a9
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 24 deletions.
6 changes: 3 additions & 3 deletions Makefile
Expand Up @@ -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"
Expand All @@ -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
Expand Down
40 changes: 26 additions & 14 deletions 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
Expand Down Expand Up @@ -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
-------------

Expand Down Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions dirty_models/fields.py
Expand Up @@ -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()
24 changes: 18 additions & 6 deletions dirty_models/models.py
Expand Up @@ -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):
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Expand Up @@ -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',
Expand Down
20 changes: 20 additions & 0 deletions tests/dirty_models/tests_fields.py
Expand Up @@ -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__)
3 changes: 3 additions & 0 deletions tox.ini
@@ -1,2 +1,5 @@
[tox]
envlist = py33,py34,py35

[flake8]
max-line-length = 120

0 comments on commit ce5e1a9

Please sign in to comment.