Skip to main content

Yet another form parser.

Project description

https://travis-ci.org/bninja/pilo.png https://coveralls.io/repos/bninja/pilo/badge.png

Yet another form parser.

dev

$ git clone git@github.com:bninja/pilo.git
$ cd pilo
$ mkvirtualenv pilo
(pilo)$ pip install -e .[tests]
(pilo)$ py.test tests/ --cov=pilo --cov-report term-missing

release

All is well:

(pilo)$ py.test tests/ --cov=pilo --cov-report term-missing

so update __version__ in:

  • pilo/__init__.py

then commit and tag it (travis will publish it to pypi):

$ git commit -am "release v{version}"
$ git tag -a v{version} -m "release v{version}"
$ git push --tags

usage

Validation

Here we validate that a message has acceptable headers and body.

from pilo import Form
from pilo.fields import Dict, String


class Message(Form):
    headers = Dict(String(choices=['to', 'from', 'content-type']), String())
    body = String(max_length=20)


>>> print Message(headers={'to': 'William III'}, body='ha'*10)
{'body': 'hahahahahahahahahaha', 'headers': {'to': 'William III'}}

>>> print Message(headers={'send-to': 'William III'}, body='ha'*10)
Invalid: headers - "send-to" is not one of "to", "from", "content-type"

>>> print Message(headers={'to': 'William III'}, body='ha'*11)
Invalid: body - "hahahahahahahahahahaha" must have length <= 20

Hooks

Override-able mechanism allowing users to inject functions to customize these behaviors:

  • compute

  • resolve

  • parse

  • default

  • munge

  • filter

  • validate

e.g.:

import pilo


class ExtraCurricular(pilo.Form):

   category = pilo.fields.String(
       choices=['athletics', 'academics', 'social', 'service']
   )

   name = pilo.fields.String(max_length=40)

   description = pilo.fields.String(max_length=140)

   role = pilo.fields.String(choices=['member', 'leader'])


class CollegeApplication(pilo.Form):

    high_school_name = pilo.fields.String()

    sat_score = pilo.fields.Integer()

    gpa = pilo.fields.Float()

    extra_curriculars = pilo.fields.List(pilo.fields.SubForm(ExtraCurricular))

    score = pilo.fields.Float(default=pilo.NONE)

    accepted = pilo.fields.Bool(default=False)

    @score.compute
    def score(self):
        leadership_roles = [
            ec for ec in self.extra_curriculars if ec.role == 'leader'
        ]
        relevant_extra_curriculars =[
            ec for ec in self.extra_curriculars
            if ec.category in ['academics', 'service']
        ]
        score = (
            10 * (self.sat_score / 1600.0) +
            10 * (self.gpa / 4.0) +
             5 * len(leadership_roles) +
             5 * len(relevant_extra_curriculars)
        )
        return score

    @accepted.compute
    def accepted(self):
        if self.score > 30:
            return True
        return False

    @high_school_name.munge
    def high_school_name(self, value):
        return value.upper()


application = CollegeApplication(
    high_school_name='Bodega High',
    sat_score=1400,
    gpa=4.0,
    extra_curriculars=[
        dict(category='athletics', role='leader', name='hockey', description=''),
        dict(category='academics', role='member', name='chess club', description=''),
    ]
)


>>> print application.high_school_name
BODEGA HIGH

>>> print application.score
28.75

>>> print application.accepted
False

Form polymorphism and type downcasting

In the following example, a user has an address, but the address schema is polymorphic on the country abbreviation.

import pilo
import uuid


class Address(pilo.Form):

    guid = pilo.fields.UUID(default=uuid.uuid4)
    country = pilo.fields.Type.abstract()


class UnitedKingdomAddress(Address):

    country = pilo.fields.Type.constant('UK')
    name = pilo.fields.String()
    street = pilo.fields.String()
    locality = pilo.fields.String()
    post_town = pilo.fields.String()
    postcode = pilo.fields.String()


class UnitedStatesAddress(Address):

    country = pilo.fields.Type.constant('USA')
    name = pilo.fields.String()
    street = pilo.fields.String()
    unit = pilo.fields.String(default=None)
    city = pilo.fields.String()
    state = pilo.fields.String()
    zip = pilo.fields.String(length=5)


class User(pilo.Form):

     guid = pilo.fields.UUID(default=uuid.uuid4)
     name = pilo.fields.String()
     address = pilo.fields.PolymorphicSubForm(Address.country)


mikey_representation = dict(
    name='Michael Pikey',
    address=dict(
        country='UK',
        name='Mikey Pikey',
        street='351 Meagre Lane',
        locality='Hedge End',
        post_town='Southampton',
        postcode='SO31 4NG',
    )
)


bart_representation = dict(
    name='Bartholomew Simpson',
    address=dict(
        country='USA',
        name='Bite Me',
        street='742 Evergreen Terrace',
        city='Springfield',
        state='???',
        zip='12345',
    )
)


mikey = User(**mikey_representation)


bart = User(**bart_representation)


>>> print dict(mikey)
{
    'address': {
        'country': 'UK',
        'guid': UUID('8c73752c-69a2-4832-99f8-c5354cbeec59'),
        'locality': 'Hedge End',
        'name': 'Mikey Pikey',
        'post_town': 'Southampton',
        'postcode': 'SO31 4NG',
        'street': '351 Meagre Lane'
    },
    'guid': UUID('eee0953c-1b5a-4bd0-893d-f513b1cf24f4'),
    'name': 'Michael Pikey'
}

>>> print dict(bart)
{
    'address': {
        'city': 'Springfield',
        'country': 'USA',
        'guid': UUID('a321bedd-8b94-46b8-830e-ea137b08a608'),
        'name': 'Bite Me',
        'state': '???',
        'street': '742 Evergreen Terrace',
        'unit': None,
        'zip': '12345'
    },
    'guid': UUID('3155a3dd-4b5a-4990-aaea-439359bb36a9'),
    'name': 'Bartholomew Simpson'
}

>>> print mikey.address.postcode
SO31 4NG

>>> print bart.address.zip
12345

>>> print type(mikey.address).__name__
UnitedKingdomAddress

>>> print type(bart.address).__name__
UnitedStatesAddress

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pilo-0.6.2.tar.gz (22.5 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page