<commit_before>============
Simple Model
============

.. image:: https://travis-ci.org/lamenezes/simple-model.svg?branch=master
    :target: https://travis-ci.org/lamenezes/simple-model

.. image:: https://coveralls.io/repos/github/lamenezes/simple-model/badge.svg?branch=master
    :target: https://coveralls.io/github/lamenezes/simple-model?branch=master


*SimpleModel* offers a simple way to handle data using classes instead of a
plenty of lists and dicts.

It has simple objectives:

- Define your fields easily (just a tuple, not dicts or instances from type classes whatever)
- Support for field validation
- Serialize to dict

That's it. If you want something more complex there are plenty of libraries and frameworks that does a lot of cool stuff.


How to install
--------------
.. code:: shell

    pip install pysimplemodel


How to use
----------
.. code:: python

    from simple_model import Model
    from simple_model.exceptions import ValidationError


    class Person(Model):
        fields = ('name', 'age', 'gender', 'height', 'weight')
        allow_empty = ('height', 'weight')

        def validate_age(self, value):
            if 0 > value > 150:
                raise ValidationError

        def validate_gender(self, value):
            if value not in ('M', 'F'):
                raise ValidationError

.. code:: python

    >> person = Person(name='<NAME>', age=18, gender='M')
    >> person.name
    '<NAME>'
    >> person.validate()
    >> person.serialize()
    {'name': '<NAME>', 'age': 18, 'gender': 'M', 'height': '', 'weight': ''}
<commit_msg>Add docs about validation and serialization on readme<commit_after>============
Simple Model
============

.. image:: https://travis-ci.org/lamenezes/simple-model.svg?branch=master
    :target: https://travis-ci.org/lamenezes/simple-model

.. image:: https://coveralls.io/repos/github/lamenezes/simple-model/badge.svg?branch=master
    :target: https://coveralls.io/github/lamenezes/simple-model?branch=master


*SimpleModel* offers a simple way to handle data using classes instead of a
plenty of lists and dicts.

It has simple objectives:

- Define your fields easily (just a tuple, not dicts or instances from type classes whatever)
- Support for field validation
- Serialize to dict

That's it. If you want something more complex there are plenty of libraries and frameworks that does a lot of cool stuff.

--------------
How to install
--------------

.. code:: shell

    pip install pysimplemodel

----------
How to use
----------

.. code:: python

    from simple_model import Model
    from simple_model.exceptions import ValidationError


    class Person(Model):
        fields = ('name', 'age', 'gender', 'height', 'weight')
        allow_empty = ('height', 'weight')

        def validate_age(self, value):
            if 0 > value > 150:
                raise ValidationError

        def validate_gender(self, value):
            if value not in ('M', 'F'):
                raise ValidationError

.. code:: python

    >> person = Person(name='<NAME>', age=18, gender='M')
    >> person.name
    '<NAME>'
    >> person.validate()
    >> person.serialize()
    {'name': '<NAME>', 'age': 18, 'gender': 'M', 'height': '', 'weight': ''}


Validation
----------

Model values aren't validated until the `validated` method is called:

.. code:: python
    
    >> person = Person()  # no exception
    >> person.validate()
    ...
    EmptyField: name field cannot be empty
    >> person = Person(name='<NAME>', age=60, gender='F')
    >> person.validate()  # now it's ok!
    

You may change the validate method to return a boolean instead of raising an exception:

.. code:: python

    >> person = Person()
    >> person.validate(raise_exception=False)
    False
    >>> person = Person(name='<NAME>', age=60, gender='F')
    >>> person.validate(raise_exception=False)
    True
   
Custom validation can make your simple models awesome:  

.. code:: python


Serialization
-------------

Simple serialization is pretty straight-forward:

.. code:: python
    >> person = Person(name='<NAME>', age=60, gender='F')
    >> person.serialize()
    {'age': 60, 'gender': 'F', 'height': None, 'name': '<NAME>', 'weight': None}
    
You may also hide some fields from serialization by passing a list to the `serialize` method:

.. code:: python
    >> person.serialize(exclude_fields=('gender', 'weight'))
    {'age': 60, 'height': None, 'name': '<NAME>'}
    
Simple model also supports nested models:

.. code:: python

    class SocialPerson(Model):
        fields = ('name', 'friend')
        
    >> person = Person(name='<NAME>', age=60, gender='F')
    >> other_person = SocialPerson(name='<NAME>', friend=person)
    >> other_person.serialize()
    {'friend': {'age': 60, 'gender': 'F', 'height': None, 'name': '<NAME>', 'weight': None}, 'name': '<NAME>'}
    
    
It also supports nested models as lists:

.. code:: python

    class MoreSocialPerson(Model):
        fields = ('name', 'friends')
        
    >> person = Person(name='<NAME>', age=60, gender='F')
    >> other_person = Person(name='<NAME>', age=15, gender='M')
    >> social_person = MoreSocialPerson(name='<NAME>', friends=[person, other_person])
    {
        'name': '<NAME>',
        'friends': [
            {
                'age': 60,
                'gender': 'F',
                'height': None,
                'name': '<NAME>',
                'weight': None
            },
            {
                'age': 15,
                'gender': 'M',
                'height': None,
                'name': '<NAME>',
                'weight': None
            }
        ]
    }

{'fraction_non_alphanumeric': 0.16563440099097504, 'fraction_numerical': 0.006724473544505397, 'mean_word_length': 2.6115015974440894, 'pattern_counts': {'":': 0, '<': 24, '<?xml version=': 0, '>': 80, 'https://': 8, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1482349', 'n_tokens_mistral': 1659, 'n_tokens_neox': 1591, 'n_words': 503}